source: trunk/NewView/CmdLineParameterUnit.pas@ 42

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

% command line parser

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