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
Line 
1Unit CmdLineParameterUnit;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2006 Ronald Brill (rbri at rbri dot de)
5// This software is released under the GNU Public License - see readme.txt
6
7// Helper functions to address the command line parameters newview
8// is started with
9
10Interface
11
12uses
13 Os2Def,
14 BseTib,
15 BseDos,
16 SysUtils,
17 Classes,
18 PMWIN,
19 StringUtilsUnit,
20 DebugUnit;
21
22 CONST
23 SUCCESS = 0;
24 ERROR_UNMATCHED_QUOTE = -1;
25
26 TYPE EParsingFailed=CLASS(Exception);
27
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
38 commandLine : String;
39 showUsageFlag : boolean;
40 searchFlag : boolean;
41 globalSearchFlag : boolean;
42 language : string;
43 helpManagerFlag : boolean;
44 helpManagerWindow : integer;
45 windowPositionFlag: boolean;
46 windowPosition: TWindowPosition;
47 ownerWindow : integer;
48 windowTitle : string;
49 fileNames : string;
50 fileNamesRaw : string;
51 searchText : string;
52
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
58 public
59 PROPERTY getCommandLine : String read commandLine;
60 PROPERTY getShowUsageFlag : boolean read showUsageFlag;
61 PROPERTY getSearchFlag : boolean read searchFlag;
62 PROPERTY getGlobalSearchFlag : boolean read globalSearchFlag;
63 PROPERTY getLanguage : string read language;
64 PROPERTY getHelpManagerFlag : boolean read helpManagerFlag;
65 FUNCTION setHelpManagerFlag(aNewValue : boolean) : boolean;
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;
72 PROPERTY getFileNamesRaw : string read fileNamesRaw;
73 PROPERTY getSearchText : string read searchText;
74
75 PROCEDURE parseCmdLine(aCmdLineString : String);
76
77 FUNCTION getInterpretedFileNames: String;
78 FUNCTION getInterpretedSearchText: String;
79 private
80 PROCEDURE parseSwitch(aCmdLineString : String);
81 end;
82
83 FUNCTION getOwnHelpFileName: String;
84
85 // returns a string containing the whole
86 // command line parametes
87 FUNCTION nativeOS2GetCmdLineParameter : String;
88
89
90Implementation
91uses
92 ACLFileUtility;
93
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
128 FUNCTION TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
129 begin
130 helpManagerFlag := aNewValue;
131 result := helpManagerFlag;
132 end;
133
134
135 procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
136 var
137 tmpState : (SWITCH, FILENAME, FILENAME_QUOTE, TEXT);
138 tmpCurrentChar : char;
139 begin
140 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
141
142 // store the original string for debugging
143 commandLine := aCmdLineString;
144
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 := '';
156 fileNames := '';
157 fileNamesRaw := '';
158
159 try
160 // start parsing
161 tmpState := FILENAME;
162 currentParsePosition := 1;
163 while currentParsePosition <= length(aCmdLineString) do
164 begin
165 tmpCurrentChar := aCmdLineString[currentParsePosition];
166
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
179 begin
180 tmpState := TEXT;
181 end;
182 inc(currentParsePosition);
183 end;
184 FILENAME_QUOTE :
185 begin
186 fileNames := fileNames + tmpCurrentChar;
187 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
188 inc(currentParsePosition);
189 end;
190 TEXT :
191 begin
192 searchText := searchText + tmpCurrentChar;
193 inc(currentParsePosition);
194 end;
195 end;
196 end;
197
198 '/', '-' :
199 begin
200 Case tmpState of
201 SWITCH :
202 begin
203 tmpState := SWITCH;
204 parseSwitch(aCmdLineString);
205 end;
206 FILENAME :
207 begin
208 if length(fileNames) < 1 then
209 begin
210 tmpState := SWITCH;
211 parseSwitch(aCmdLineString);
212 end
213 else
214 begin
215 fileNames := fileNames + tmpCurrentChar;
216 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
217 inc(currentParsePosition);
218 end;
219 end;
220 FILENAME_QUOTE :
221 begin
222 fileNames := fileNames + tmpCurrentChar;
223 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
224 inc(currentParsePosition);
225 end;
226 else
227 begin
228 searchText := searchText + tmpCurrentChar;
229 inc(currentParsePosition);
230 end;
231 end;
232 end;
233
234 '"' :
235 begin
236 Case tmpState of
237 SWITCH :
238 begin
239 // syntax error
240 raise EParsingFailed.Create('Unsupported switch');
241 end;
242 FILENAME :
243 begin
244 tmpState := FILENAME_QUOTE;
245 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
246 inc(currentParsePosition);
247 end;
248 FILENAME_QUOTE :
249 begin
250 tmpState := FILENAME;
251 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
252 inc(currentParsePosition);
253 end;
254 TEXT :
255 begin
256 searchText := searchText + tmpCurrentChar;
257 inc(currentParsePosition);
258 end;
259 end;
260 end;
261
262 else
263 begin
264 Case tmpState of
265 SWITCH :
266 begin
267 // syntax error
268 raise EParsingFailed.Create('Unsupported switch');
269 end;
270 FILENAME :
271 begin
272 fileNames := fileNames + tmpCurrentChar;
273 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
274 inc(currentParsePosition);
275 end;
276 FILENAME_QUOTE :
277 begin
278 fileNames := fileNames + tmpCurrentChar;
279 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
280 inc(currentParsePosition);
281 end;
282 else
283 begin
284 searchText := searchText + tmpCurrentChar;
285 inc(currentParsePosition);
286 end;
287 end;
288 end;
289 end;
290 end;
291
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;
326 END;
327
328
329
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);
338
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;
346
347 aValue := readNextPart(aCmdLineString, [' ', '-', '/']);
348 currentParsePosition := currentParsePosition + length(aValue);
349 result := true;
350 exit;
351 end;
352 result := false;
353 end;
354
355
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');
362
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');
368
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;
381
382 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
383 Var
384 tmpParts : TStringList;
385 Begin
386 tmpParts := TStringList.Create;
387 StrExtractStrings(tmpParts, aParamValue, [','], '\');
388
389 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
390 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
391
392 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
393 if result.Width < 50 then
394 result.Width := 50;
395
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;
401 end;
402
403
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;
496 end;
497
498
499 FUNCTION getOwnHelpFileName: String;
500 begin
501 result := FindDefaultLanguageHelpFile('NewView');
502 end;
503
504
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;
523END.
Note: See TracBrowser for help on using the repository browser.