source: trunk/NewView/CmdLineParameterUnit.pas@ 45

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

+ store the raw filenames (including quotes) also to allow sime more intelligent parameter handling

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