source: trunk/NewView/CmdLineParameterUnit.pas@ 122

Last change on this file since 122 was 122, checked in by RBRi, 18 years ago

more format fixes

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