source: trunk/NewView/CmdLineParameterUnit.pas@ 54

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

refactoring to simplify command line handling in MainForm
some tests fixed

  • Property svn:eol-style set to native
File size: 14.2 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
22 CONST
23 SUCCESS = 0;
24 ERROR_UNMATCHED_QUOTE = -1;
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;
44 helpManagerWindow : integer;
45 windowPositionFlag: boolean;
46 windowPosition: TWindowPosition;
47 ownerWindow : integer;
48 windowTitle : string;
[25]49 fileNames : string;
[45]50 fileNamesRaw : string;
[42]51 searchText : string;
[23]52
[42]53 currentParsePosition : integer;
54
55 FUNCTION ReadNextPart(const aParseString : String; const aSetOfDelimiterChars : TSetOfChars): String;
56 FUNCTION handleParamWithValue(const aCmdLineString : String; const aSwitch : String; var aValue : String) : Boolean;
57
[23]58 public
[42]59 PROPERTY getCommandLine : String read commandLine;
[32]60 PROPERTY getShowUsageFlag : boolean read showUsageFlag;
[42]61 PROPERTY getSearchFlag : boolean read searchFlag;
62 PROPERTY getGlobalSearchFlag : boolean read globalSearchFlag;
[32]63 PROPERTY getLanguage : string read language;
64 PROPERTY getHelpManagerFlag : boolean read helpManagerFlag;
[25]65 FUNCTION setHelpManagerFlag(aNewValue : boolean) : boolean;
[32]66 PROPERTY getHelpManagerWindow : integer read helpManagerWindow;
67 PROPERTY getWindowPositionFlag : boolean read windowPositionFlag;
68 PROPERTY getWindowPosition : TWindowPosition read windowPosition;
69 PROPERTY getOwnerWindow : integer read ownerWindow;
70 PROPERTY getWindowTitle : string read windowTitle;
71 PROPERTY getFileNames : string read fileNames;
[45]72 PROPERTY getFileNamesRaw : string read fileNamesRaw;
[42]73 PROPERTY getSearchText : string read searchText;
74
75 PROCEDURE parseCmdLine(aCmdLineString : String);
[54]76
77 FUNCTION getInterpretedFileNames: String;
78 FUNCTION getInterpretedSearchText: String;
[42]79 private
80 PROCEDURE parseSwitch(aCmdLineString : String);
[23]81 end;
82
[54]83 FUNCTION getOwnHelpFileName: String;
84
[42]85 // returns a string containing the whole
86 // command line parametes
[54]87 FUNCTION nativeOS2GetCmdLineParameter : String;
[23]88
89
90Implementation
[54]91uses
92 ACLFileUtility;
[23]93
[54]94 FUNCTION TCmdLineParameters.getInterpretedFileNames: String;
95 var
96 tmpOwnHelpFileName : String;
97 begin
98 result := getFileNames;
99
100 if getGlobalSearchFlag
101 AND (getSearchText = '')
102 then
103 begin
104 result := '';
105 exit;
106 end;
107
108
109 tmpOwnHelpFileName := FindDefaultLanguageHelpFile('NewView');
110 if (result = '') AND
111 FileExists(tmpOwnHelpFileName)
112 then
113 result := tmpOwnHelpFileName;
114 end;
115
116
117 FUNCTION TCmdLineParameters.getInterpretedSearchText: String;
118 begin
119 result := getSearchText;
120
121 if getGlobalSearchFlag
122 AND (result = '')
123 then
124 result := getFileNamesRaw;
125 end;
126
127
[25]128 FUNCTION TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
129 begin
130 helpManagerFlag := aNewValue;
131 result := helpManagerFlag;
132 end;
133
134
[42]135 procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
[23]136 var
[42]137 tmpState : (SWITCH, FILENAME, FILENAME_QUOTE, TEXT);
138 tmpCurrentChar : char;
[23]139 begin
[42]140 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
[25]141
[42]142 // store the original string for debugging
143 commandLine := aCmdLineString;
[23]144
[42]145 // reset the whole object
146 showUsageFlag := false;
147 searchFlag := false;
148 globalSearchFlag := false;
149 language := '';
150 helpManagerFlag := false;
151 helpManagerWindow := 0;
152 windowPositionFlag := false;
153 ownerWindow := 0;
154 windowTitle := '';
155 searchText := '';
[45]156 fileNames := '';
157 fileNamesRaw := '';
[23]158
[42]159 try
160 // start parsing
161 tmpState := FILENAME;
162 currentParsePosition := 1;
163 while currentParsePosition <= length(aCmdLineString) do
164 begin
165 tmpCurrentChar := aCmdLineString[currentParsePosition];
[23]166
[42]167 Case tmpCurrentChar of
168 ' ' :
169 begin
170 Case tmpState of
171 SWITCH :
172 begin
173 tmpState := FILENAME;
174 inc(currentParsePosition);
175 end;
176 FILENAME :
177 begin
178 if length(fileNames) > 0 then
[23]179 begin
[42]180 tmpState := TEXT;
[23]181 end;
[42]182 inc(currentParsePosition);
183 end;
184 FILENAME_QUOTE :
185 begin
[45]186 fileNames := fileNames + tmpCurrentChar;
187 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]188 inc(currentParsePosition);
189 end;
190 TEXT :
191 begin
192 searchText := searchText + tmpCurrentChar;
193 inc(currentParsePosition);
194 end;
[23]195 end;
[42]196 end;
[25]197
[42]198 '/', '-' :
199 begin
[23]200 Case tmpState of
[42]201 SWITCH :
[23]202 begin
[42]203 tmpState := SWITCH;
204 parseSwitch(aCmdLineString);
[23]205 end;
[42]206 FILENAME :
[23]207 begin
[42]208 if length(fileNames) < 1 then
209 begin
210 tmpState := SWITCH;
211 parseSwitch(aCmdLineString);
212 end
213 else
214 begin
[45]215 fileNames := fileNames + tmpCurrentChar;
216 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]217 inc(currentParsePosition);
218 end;
[23]219 end;
[42]220 FILENAME_QUOTE :
[23]221 begin
[45]222 fileNames := fileNames + tmpCurrentChar;
223 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]224 inc(currentParsePosition);
[23]225 end;
[42]226 else
227 begin
228 searchText := searchText + tmpCurrentChar;
229 inc(currentParsePosition);
230 end;
[23]231 end;
[42]232 end;
[23]233
[42]234 '"' :
235 begin
[23]236 Case tmpState of
[42]237 SWITCH :
[23]238 begin
[42]239 // syntax error
240 raise EParsingFailed.Create('Unsupported switch');
[23]241 end;
[42]242 FILENAME :
[23]243 begin
[42]244 tmpState := FILENAME_QUOTE;
[45]245 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]246 inc(currentParsePosition);
[23]247 end;
[42]248 FILENAME_QUOTE :
[23]249 begin
[42]250 tmpState := FILENAME;
[45]251 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]252 inc(currentParsePosition);
[23]253 end;
[42]254 TEXT :
[23]255 begin
[42]256 searchText := searchText + tmpCurrentChar;
257 inc(currentParsePosition);
[23]258 end;
[42]259 end;
260 end;
261
262 else
263 begin
264 Case tmpState of
265 SWITCH :
[23]266 begin
[42]267 // syntax error
268 raise EParsingFailed.Create('Unsupported switch');
[23]269 end;
[42]270 FILENAME :
[23]271 begin
[42]272 fileNames := fileNames + tmpCurrentChar;
[45]273 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]274 inc(currentParsePosition);
[23]275 end;
[42]276 FILENAME_QUOTE :
[23]277 begin
[45]278 fileNames := fileNames + tmpCurrentChar;
279 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
[42]280 inc(currentParsePosition);
[23]281 end;
[42]282 else
283 begin
284 searchText := searchText + tmpCurrentChar;
285 inc(currentParsePosition);
[23]286 end;
[42]287 end;
288 end;
289 end;
290 end;
[23]291
[42]292 except
293 on e:EParsingFailed do
294 begin
295 showUsageFlag := true;
296 end;
297 end;
298
299 // remove leading blanks from search text
300 searchText := StrTrim(searchText);
301
302 LogEvent(LogStartup, 'Parameters parsed');
303 LogEvent(LogStartup, ' Filename(s): "' + fileNames + '"');
304 LogEvent(LogStartup, ' Search Text: "' + searchText + '"');
305 end;
306
307
308 FUNCTION TCmdLineParameters.ReadNextPart(const aParseString : String; const aSetOfDelimiterChars : TSetOfChars): String;
309 VAR
310 i : integer;
311 tmpChar : char;
312 BEGIN
313 result := '';
314 for i:= currentParsePosition to length(aParseString) do
315 begin
316 tmpChar := aParseString[i];
317 if tmpChar in aSetOfDelimiterChars then
318 begin
319 i := length(aParseString); // stop parsing
320 end
321 else
322 begin
323 result := result + tmpChar;
324 end;
325 end;
[23]326 END;
327
328
329
[42]330 Function TCmdLineParameters.handleParamWithValue(const aCmdLineString : String; const aSwitch : String; var aValue : String) : Boolean;
331 var
332 tmpText : String;
333 tmpSwitchLength : integer;
334 begin
335 tmpSwitchLength := Length(aSwitch);
336 tmpText := copy(aCmdLineString, currentParsePosition + 1, tmpSwitchLength);
337 tmpText := lowercase(tmpText);
[23]338
[42]339 if (lowercase(aSwitch) = tmpText) then
340 begin
341 currentParsePosition := currentParsePosition + 1 + tmpSwitchLength;
342 if aCmdLineString[currentParsePosition] = ':' then
343 begin
344 inc(currentParsePosition);
345 end;
[23]346
[42]347 aValue := readNextPart(aCmdLineString, [' ', '-', '/']);
348 currentParsePosition := currentParsePosition + length(aValue);
349 result := true;
350 exit;
351 end;
352 result := false;
353 end;
[23]354
355
[42]356 Function ParseWindowPositionPart(const aPart: String; const aScreenDimension: longint): longint;
357 Var
358 tmpPart : String;
359 Begin
360 if aPart = '' then
361 raise EParsingFailed.Create('Missing position element');
[23]362
[42]363 if StrEndsWithIgnoringCase(aPart, 'P') then
364 begin
365 tmpPart := copy(aPart, 1, length(aPart)-1);
366 if tmpPart = '' then
367 raise EParsingFailed.Create('Missing position element');
[23]368
[42]369 Result := StrToInt(tmpPart);
370 if Result < 0 then
371 Result := 0;
372 if Result > 100 then
373 Result := 100;
374 Result := Round(Result / 100 * aScreenDimension);
375 end
376 else
377 begin
378 Result := StrToInt(aPart);
379 end;
380 end;
[23]381
[42]382 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
383 Var
384 tmpParts : TStringList;
385 Begin
386 tmpParts := TStringList.Create;
387 StrExtractStrings(tmpParts, aParamValue, [','], '\');
[23]388
[42]389 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
390 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
[23]391
[42]392 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
393 if result.Width < 50 then
394 result.Width := 50;
[23]395
[42]396 result.Height := ParseWindowPositionPart(tmpParts[3], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
397 if result.Height < 50 then
398 result.Height := 50;
399
400 tmpParts.Destroy;
[23]401 end;
402
403
[42]404 Procedure TCmdLineParameters.parseSwitch(aCmdLineString : String);
405 var
406 tmpCurrentChar : char;
407 tmpText : String;
408 tmpValue : String;
409 begin
410 // lang
411 if handleParamWithValue(aCmdLineString, 'lang', tmpValue) then
412 begin
413 language := tmpValue;
414 exit;
415 end;
416
417 // title
418 if handleParamWithValue(aCmdLineString, 'title', tmpValue) then
419 begin
420 windowTitle := tmpValue;
421 exit;
422 end;
423
424 // HM
425 if handleParamWithValue(aCmdLineString, 'hm', tmpValue) then
426 begin
427 try
428 helpManagerWindow := StrToInt(tmpValue);
429 helpManagerFlag := true;
430 except
431 on e:Exception do
432 begin
433 showUsageFlag := true;
434 end;
435 end;
436 exit;
437 end;
438
439 // owner
440 if handleParamWithValue(aCmdLineString, 'owner', tmpValue) then
441 begin
442 try
443 ownerWindow := StrToInt(tmpValue);
444 except
445 on e:Exception do
446 begin
447 showUsageFlag := true;
448 end;
449 end;
450 exit;
451 end;
452
453 // pos
454 if handleParamWithValue(aCmdLineString, 'pos', tmpValue) then
455 begin
456 windowPosition := ParseWindowPosition(tmpValue);
457 windowPositionFlag := true;
458 exit;
459 end;
460
461 // check the next char
462 tmpCurrentChar := aCmdLineString[currentParsePosition + 1];
463 Case tmpCurrentChar of
464 'h', 'H', '?' :
465 begin
466 currentParsePosition := currentParsePosition + 2;
467 showUsageFlag := true;
468
469 // check for 'help'
470 tmpText := copy(aCmdLineString, currentParsePosition, 3);
471 tmpText := lowercase(tmpText);
472
473 if ('elp' = tmpText) then
474 begin
475 currentParsePosition := currentParsePosition + 3;
476 end;
477 end;
478
479 's', 'S' :
480 begin
481 currentParsePosition := currentParsePosition + 2;
482 searchFlag := true;
483 end;
484
485 'g', 'G' :
486 begin
487 currentParsePosition := currentParsePosition + 2;
488 globalSearchFlag := true;
489 end;
490
491 else
492 begin
493 raise EParsingFailed.Create('Unsupported switch');
494 end;
495 end;
[23]496 end;
497
[25]498
[54]499 FUNCTION getOwnHelpFileName: String;
500 begin
501 result := FindDefaultLanguageHelpFile('NewView');
502 end;
503
504
[42]505 FUNCTION nativeOS2GetCmdLineParameter : STRING;
506 VAR
507 tmpPtib : PTIB; // thread information block
508 tmpPpib : PPIB; // process information block
509 tmpCmd : PCHAR;
510 tmpResult : PCHAR;
511
512 BEGIN
513 // ask the system
514 DosGetInfoBlocks(tmpPtib, tmpPpib);
515 tmpCmd := tmpPpib^.pib_pchcmd;
516 // the fist element (null terminated) is the
517 // called command itself
518 // skip to the next null terminated string
519 // these are the parameters
520 tmpResult := tmpCmd + StrLen(tmpCmd) + 1;
521 result := StrPas(tmpResult);
522 END;
[23]523END.
Note: See TracBrowser for help on using the repository browser.