source: trunk/NewView/CmdLineParameterUnit.pas@ 78

Last change on this file since 78 was 78, checked in by RBRi, 19 years ago

method name refactoring

  • Property svn:eol-style set to native
File size: 16.3 KB
RevLine 
[23]1Unit CmdLineParameterUnit;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2006 Ronald Brill (rbri at rbri dot de)
[42]5// This software is released under the GNU Public License - see readme.txt
[23]6
7// Helper functions to address the command line parameters newview
8// is started with
9
10Interface
11
12uses
[32]13 Os2Def,
14 BseTib,
15 BseDos,
[23]16 SysUtils,
17 Classes,
18 PMWIN,
[42]19 StringUtilsUnit,
20 DebugUnit;
[23]21
[78]22CONST
23 ENV_DEBUG = 'NEWVIEW_DEBUG';
[23]24
[76]25
[42]26 TYPE EParsingFailed=CLASS(Exception);
27
[23]28 TYPE
29 TWindowPosition = record
30 left: longint;
31 bottom: longint;
32 width: longint;
33 height: longint;
34 end;
35 TYPE
36 TCmdLineParameters = class
37 private
[42]38 commandLine : String;
[23]39 showUsageFlag : boolean;
[42]40 searchFlag : boolean;
41 globalSearchFlag : boolean;
[23]42 language : string;
43 helpManagerFlag : boolean;
[69]44 helpManagerWindow : HWND;
[23]45 windowPositionFlag: boolean;
46 windowPosition: TWindowPosition;
47 ownerWindow : integer;
48 windowTitle : string;
[78]49 parsedFileNames : string;
50 parsedRawFileNames : string;
[25]51 fileNames : string;
[78]52 parsedSearchText : string;
[42]53 searchText : string;
[78]54 debugEnabled : boolean;
[23]55
[67]56 FUNCTION handleSwitchWithValue(const aSwitchString : String; const aSwitch : String; var aValue : String) : Boolean;
57 PROCEDURE parseSwitch(aSwitchString : String);
[78]58 PROPERTY getParsedFileNames : string read parsedFileNames;
59 PROPERTY getParsedSearchText : string read parsedSearchText;
[42]60
[23]61 public
[78]62 PROPERTY isDebugEnabled : boolean read debugEnabled;
[32]63 PROPERTY getShowUsageFlag : boolean read showUsageFlag;
[42]64 PROPERTY getSearchFlag : boolean read searchFlag;
65 PROPERTY getGlobalSearchFlag : boolean read globalSearchFlag;
[32]66 PROPERTY getLanguage : string read language;
67 PROPERTY getHelpManagerFlag : boolean read helpManagerFlag;
[25]68 FUNCTION setHelpManagerFlag(aNewValue : boolean) : boolean;
[69]69 PROPERTY getHelpManagerWindow : HWND read helpManagerWindow;
[32]70 PROPERTY getWindowPositionFlag : boolean read windowPositionFlag;
71 PROPERTY getWindowPosition : TWindowPosition read windowPosition;
72 PROPERTY getOwnerWindow : integer read ownerWindow;
73 PROPERTY getWindowTitle : string read windowTitle;
[78]74 PROPERTY getFileNames : string read fileNames;
75 PROPERTY getSearchText : string read searchText;
[42]76
[65]77 PROCEDURE writeDetailsTo(aStrings : TStrings);
[42]78 PROCEDURE parseCmdLine(aCmdLineString : String);
[23]79 end;
80
[54]81 FUNCTION getOwnHelpFileName: String;
82
[42]83 // returns a string containing the whole
84 // command line parametes
[54]85 FUNCTION nativeOS2GetCmdLineParameter : String;
[23]86
87
88Implementation
[54]89uses
[76]90 DOS,
[54]91 ACLFileUtility;
[23]92
[65]93 PROCEDURE TCmdLineParameters.writeDetailsTo(aStrings : TStrings);
94 var
95 tmpWindowPosition : TWindowPosition;
96 begin
[78]97 aStrings.Add('''' + commandLine + '''');
98 aStrings.Add('isDebugEnabled: ' + boolToStr(isDebugEnabled));
[65]99 aStrings.Add('parsed infos:');
100
[78]101 aStrings.Add(' showUsageFlag: ' + boolToStr(getShowUsageFlag));
102 aStrings.Add(' searchFlag: ' + boolToStr(getSearchFlag));
103 aStrings.Add(' fileNames: ' + getFileNames);
104 aStrings.Add(' parsedFileNames: ' + getParsedFileNames);
105 aStrings.Add(' searchText: ' + getSearchText);
106 aStrings.Add(' parsedSearchText: ' + getParsedSearchText);
107 aStrings.Add(' globalSearchFlag: ' + boolToStr(getGlobalSearchFlag));
108 aStrings.Add(' language: ' + getLanguage);
109 aStrings.Add(' helpManagerFlag: ' + boolToStr(getHelpManagerFlag));
110 aStrings.Add(' helpManagerWindow: ' + LongWordToStr(getHelpManagerWindow));
111 aStrings.Add(' windowPositionFlag: ' + boolToStr(getWindowPositionFlag));
[65]112
113 tmpWindowPosition := getWindowPosition;
[78]114 aStrings.Add(' windowPosition: '
[65]115 + intToStr(tmpWindowPosition.left) + ', '
116 + intToStr(tmpWindowPosition.bottom) + ', '
117 + intToStr(tmpWindowPosition.width) + ', '
118 + intToStr(tmpWindowPosition.height)
119 );
[78]120 aStrings.Add(' ownerWindow: ' + intToStr(getOwnerWindow));
121 aStrings.Add(' windowTitle: ' + getWindowTitle);
[65]122 end;
123
124
[67]125 Function TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
[25]126 begin
127 helpManagerFlag := aNewValue;
128 result := helpManagerFlag;
129 end;
130
131
[67]132 Procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
[23]133 var
[67]134 tmpState : (WHITESPACE, QUOTE, SWITCH, FILENAME, TEXT);
135 tmpCurrentParsePosition : integer;
136 tmpQuoted : boolean;
[42]137 tmpCurrentChar : char;
[67]138 tmpWhitespace : String;
139 tmpQuote : String;
140 tmpSwitch : String;
[78]141 tmpOwnHelpFileName : String;
[23]142 begin
[76]143 // first adjust logging
[78]144 debugEnabled := false;
[76]145 if GetEnv(ENV_DEBUG) = '' then
146 begin
[78]147 debugEnabled := true;
[76]148 end
149 else
150 begin
151 SetLogAspects(GetEnv(ENV_DEBUG));
152 end;
[25]153
[76]154 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
[23]155
[76]156 // store the original string for debugging
157 commandLine := aCmdLineString;
[23]158
[76]159 // reset the whole object
160 showUsageFlag := false;
161 searchFlag := false;
162 globalSearchFlag := false;
163 language := '';
164 helpManagerFlag := false;
165 helpManagerWindow := 0;
166 windowPositionFlag := false;
167 ownerWindow := 0;
168 windowTitle := '';
[78]169 parsedSearchText := '';
170 parsedFileNames := '';
171 parsedRawFileNames := '';
[23]172
[76]173 try
174 // start parsing
175 tmpState := WHITESPACE;
176 tmpWhitespace := '';
177 tmpSwitch := '';
178 tmpQuote := '';
179 tmpQuoted := false;
180 tmpCurrentParsePosition := 1;
181 while tmpCurrentParsePosition <= length(aCmdLineString) do
182 begin
183 tmpCurrentChar := aCmdLineString[tmpCurrentParsePosition];
[67]184
[76]185 Case tmpCurrentChar of
186 ' ' :
187 begin
188 Case tmpState of
[67]189
[76]190 WHITESPACE :
191 begin
192 tmpWhitespace := tmpWhitespace + tmpCurrentChar;
193 end;
[67]194
[76]195 QUOTE :
196 begin
197 tmpQuote := tmpQuote + tmpCurrentChar;
198 end;
[67]199
[76]200 SWITCH :
201 begin
202 if tmpQuoted then
203 begin
204 tmpSwitch := tmpSwitch + tmpCurrentChar;
205 end
206 else
207 begin
208 parseSwitch(tmpSwitch);
209 tmpState := WHITESPACE;
210 tmpWhitespace := tmpCurrentChar;
211 end
212 end;
[67]213
[76]214 FILENAME :
215 begin
216 if tmpQuoted then
217 begin
[78]218 parsedFileNames := parsedFileNames + tmpCurrentChar;
219 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]220 end
221 else
222 begin
223 tmpState := WHITESPACE;
224 tmpWhitespace := tmpCurrentChar;
225 end
226 end;
[25]227
[76]228 TEXT :
229 begin
230 if tmpQuoted then
231 begin
[78]232 parsedSearchText := parsedSearchText + tmpCurrentChar;
[76]233 end
234 else
235 begin
236 tmpState := WHITESPACE;
237 tmpWhitespace := tmpCurrentChar;
238 end
239 end;
240 end;
241 end;
[67]242
[76]243 '/', '-' :
244 begin
245 Case tmpState of
246 WHITESPACE :
247 begin
248 tmpState := SWITCH;
249 tmpSwitch := '';
250 end;
[67]251
[76]252 QUOTE :
253 begin
254 tmpState := SWITCH;
255 tmpSwitch := '';
256 end;
[67]257
[76]258 SWITCH :
259 begin
260 parseSwitch(tmpSwitch);
261 tmpSwitch := '';
262 end;
[67]263
[76]264 FILENAME :
265 begin
[78]266 parsedFileNames := parsedFileNames + tmpCurrentChar;
267 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]268 end;
[67]269
[76]270 TEXT :
271 begin
[78]272 parsedSearchText := parsedSearchText + tmpCurrentChar;
[76]273 end;
274 end;
275 end;
[42]276
[76]277 '"' :
278 begin
279 if tmpQuoted then
280 begin
281 tmpQuoted := false;
282 Case tmpState of
283 FILENAME :
284 begin
[78]285 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]286 end;
[78]287 TEXT :
288 begin
289 parsedSearchText := parsedSearchText + tmpCurrentChar;
290 end;
[76]291 end;
292 end
293 else
294 begin
[78]295 tmpQuoted := true;
[76]296 Case tmpState of
297 WHITESPACE :
298 begin
299 tmpState := QUOTE;
300 tmpQuote := tmpCurrentChar;
301 end;
302 FILENAME :
303 begin
[78]304 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]305 end;
306 end;
307 end;
308 end;
[67]309
[76]310 // any other char
311 else
312 begin
313 Case tmpState of
[67]314
[76]315 WHITESPACE :
316 begin
[78]317 if length(parsedFileNames) > 0 then
[76]318 begin
319 tmpState := TEXT;
[78]320 parsedSearchText := parsedSearchText + tmpWhitespace + tmpCurrentChar;
[76]321 end
322 else
323 begin
324 tmpState := FILENAME;
[78]325 parsedFileNames := parsedFileNames + tmpCurrentChar;
326 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]327 end;
328 end;
[67]329
[76]330 QUOTE :
331 begin
[78]332 if length(parsedFileNames) > 0 then
[76]333 begin
334 tmpState := TEXT;
[78]335 parsedSearchText := parsedSearchText + tmpQuote + tmpCurrentChar;
[76]336 end
337 else
338 begin
339 tmpState := FILENAME;
[78]340 parsedFileNames := parsedFileNames + tmpCurrentChar;
341 parsedRawFileNames := parsedRawFileNames + tmpQuote + tmpCurrentChar;
[76]342 end;
343 end;
[67]344
[76]345 SWITCH :
346 begin
347 tmpSwitch := tmpSwitch + tmpCurrentChar;
348 end;
[67]349
[76]350 FILENAME :
351 begin
[78]352 parsedFileNames := parsedFileNames + tmpCurrentChar;
353 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
[76]354 end;
355
356 TEXT :
357 begin
[78]358 parsedSearchText := parsedSearchText + tmpCurrentChar;
[76]359 end;
360 end;
361 end;
[42]362 end;
[67]363 inc(tmpCurrentParsePosition);
[42]364 end;
[23]365
[67]366 // ok all chars are processed, but maybe we have something to do
367 Case tmpState of
368 SWITCH :
369 begin
370 parseSwitch(tmpSwitch);
371 end;
[76]372 end;
[42]373 except
374 on e:EParsingFailed do
375 begin
376 showUsageFlag := true;
377 end;
378 end;
379
[78]380 // remove blanks
381 fileNames := StrTrim(getParsedFileNames);
382 searchText := StrTrim(getParsedSearchText);
[42]383
[78]384 if getGlobalSearchFlag
385 AND (getParsedSearchText = '')
386 then
387 begin
388 fileNames := '';
389 searchText := parsedRawFileNames;
390 end
391 else
392 begin
393 if fileNames = '' then
394 begin
395 tmpOwnHelpFileName := FindDefaultLanguageHelpFile('NewView');
396 if FileExists(tmpOwnHelpFileName)
397 then
398 fileNames := tmpOwnHelpFileName;
399 end;
400 end;
401
402 // to be compatible with the old one we have to ignore
403 // the quotes
404 if not getGlobalSearchFlag
405 AND (not getSearchFlag)
406 then
407 begin
408 searchText := StrTrimChars(searchText, ['"']);
409 end;
410
[42]411 LogEvent(LogStartup, 'Parameters parsed');
412 LogEvent(LogStartup, ' Filename(s): "' + fileNames + '"');
413 LogEvent(LogStartup, ' Search Text: "' + searchText + '"');
414 end;
415
416
[67]417 Function TCmdLineParameters.handleSwitchWithValue(const aSwitchString : String; const aSwitch : String; var aValue : String) : Boolean;
[42]418 var
419 tmpText : String;
[67]420 tmpValueStartPos : integer;
[42]421 tmpSwitchLength : integer;
422 begin
423 tmpSwitchLength := Length(aSwitch);
[67]424 tmpText := copy(aSwitchString, 1, tmpSwitchLength);
[42]425 tmpText := lowercase(tmpText);
[23]426
[42]427 if (lowercase(aSwitch) = tmpText) then
428 begin
[67]429 tmpValueStartPos := tmpSwitchLength;
430 inc(tmpValueStartPos);
431 if aSwitchString[tmpValueStartPos] = ':' then
[42]432 begin
[67]433 inc(tmpValueStartPos);
[42]434 end;
[23]435
[67]436 aValue := copy(aSwitchString, tmpValueStartPos, Length(aSwitchString) - tmpValueStartPos+ 1);
[42]437 result := true;
438 exit;
439 end;
440 result := false;
441 end;
[23]442
443
[42]444 Function ParseWindowPositionPart(const aPart: String; const aScreenDimension: longint): longint;
445 Var
446 tmpPart : String;
447 Begin
448 if aPart = '' then
449 raise EParsingFailed.Create('Missing position element');
[23]450
[42]451 if StrEndsWithIgnoringCase(aPart, 'P') then
452 begin
453 tmpPart := copy(aPart, 1, length(aPart)-1);
454 if tmpPart = '' then
455 raise EParsingFailed.Create('Missing position element');
[23]456
[42]457 Result := StrToInt(tmpPart);
458 if Result < 0 then
459 Result := 0;
460 if Result > 100 then
461 Result := 100;
462 Result := Round(Result / 100 * aScreenDimension);
463 end
464 else
465 begin
466 Result := StrToInt(aPart);
467 end;
468 end;
[23]469
[42]470 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
471 Var
472 tmpParts : TStringList;
473 Begin
474 tmpParts := TStringList.Create;
475 StrExtractStrings(tmpParts, aParamValue, [','], '\');
[23]476
[42]477 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
478 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
[23]479
[42]480 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
481 if result.Width < 50 then
482 result.Width := 50;
[23]483
[42]484 result.Height := ParseWindowPositionPart(tmpParts[3], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
485 if result.Height < 50 then
486 result.Height := 50;
487
488 tmpParts.Destroy;
[23]489 end;
490
491
[67]492 Procedure TCmdLineParameters.parseSwitch(aSwitchString : String);
[42]493 var
494 tmpCurrentChar : char;
495 tmpValue : String;
496 begin
497 // lang
[67]498 if handleSwitchWithValue(aSwitchString, 'lang', tmpValue) then
[42]499 begin
500 language := tmpValue;
501 exit;
502 end;
503
504 // title
[67]505 if handleSwitchWithValue(aSwitchString, 'title', tmpValue) then
[42]506 begin
507 windowTitle := tmpValue;
508 exit;
509 end;
510
511 // HM
[67]512 if handleSwitchWithValue(aSwitchString, 'hm', tmpValue) then
[42]513 begin
514 try
515 helpManagerWindow := StrToInt(tmpValue);
516 helpManagerFlag := true;
517 except
518 on e:Exception do
519 begin
520 showUsageFlag := true;
521 end;
522 end;
523 exit;
524 end;
525
526 // owner
[67]527 if handleSwitchWithValue(aSwitchString, 'owner', tmpValue) then
[42]528 begin
529 try
530 ownerWindow := StrToInt(tmpValue);
531 except
532 on e:Exception do
533 begin
534 showUsageFlag := true;
535 end;
536 end;
537 exit;
538 end;
539
540 // pos
[67]541 if handleSwitchWithValue(aSwitchString, 'pos', tmpValue) then
[42]542 begin
543 windowPosition := ParseWindowPosition(tmpValue);
544 windowPositionFlag := true;
545 exit;
546 end;
547
548 // check the next char
[67]549 // TODO check for other invalid chars
550 tmpCurrentChar := aSwitchString[1];
[42]551 Case tmpCurrentChar of
552 'h', 'H', '?' :
553 begin
554 showUsageFlag := true;
555 end;
556
557 's', 'S' :
558 begin
559 searchFlag := true;
560 end;
561
562 'g', 'G' :
563 begin
564 globalSearchFlag := true;
565 end;
566
567 else
568 begin
569 raise EParsingFailed.Create('Unsupported switch');
570 end;
571 end;
[23]572 end;
573
[25]574
[54]575 FUNCTION getOwnHelpFileName: String;
576 begin
577 result := FindDefaultLanguageHelpFile('NewView');
578 end;
579
580
[42]581 FUNCTION nativeOS2GetCmdLineParameter : STRING;
582 VAR
583 tmpPtib : PTIB; // thread information block
584 tmpPpib : PPIB; // process information block
585 tmpCmd : PCHAR;
586 tmpResult : PCHAR;
587
588 BEGIN
589 // ask the system
590 DosGetInfoBlocks(tmpPtib, tmpPpib);
591 tmpCmd := tmpPpib^.pib_pchcmd;
592 // the fist element (null terminated) is the
593 // called command itself
594 // skip to the next null terminated string
595 // these are the parameters
596 tmpResult := tmpCmd + StrLen(tmpCmd) + 1;
597 result := StrPas(tmpResult);
598 END;
[23]599END.
Note: See TracBrowser for help on using the repository browser.