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
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 private
77 PROCEDURE parseSwitch(aCmdLineString : String);
78 end;
79
80 // returns a string containing the whole
81 // command line parametes
82 FUNCTION nativeOS2GetCmdLineParameter : STRING;
83
84
85Implementation
86
87 FUNCTION TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
88 begin
89 helpManagerFlag := aNewValue;
90 result := helpManagerFlag;
91 end;
92
93
94 procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
95 var
96 tmpState : (SWITCH, FILENAME, FILENAME_QUOTE, TEXT);
97 tmpCurrentChar : char;
98 begin
99 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
100
101 // store the original string for debugging
102 commandLine := aCmdLineString;
103
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 := '';
115 fileNames := '';
116 fileNamesRaw := '';
117
118 try
119 // start parsing
120 tmpState := FILENAME;
121 currentParsePosition := 1;
122 while currentParsePosition <= length(aCmdLineString) do
123 begin
124 tmpCurrentChar := aCmdLineString[currentParsePosition];
125
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
138 begin
139 tmpState := TEXT;
140 end;
141 inc(currentParsePosition);
142 end;
143 FILENAME_QUOTE :
144 begin
145 fileNames := fileNames + tmpCurrentChar;
146 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
147 inc(currentParsePosition);
148 end;
149 TEXT :
150 begin
151 searchText := searchText + tmpCurrentChar;
152 inc(currentParsePosition);
153 end;
154 end;
155 end;
156
157 '/', '-' :
158 begin
159 Case tmpState of
160 SWITCH :
161 begin
162 tmpState := SWITCH;
163 parseSwitch(aCmdLineString);
164 end;
165 FILENAME :
166 begin
167 if length(fileNames) < 1 then
168 begin
169 tmpState := SWITCH;
170 parseSwitch(aCmdLineString);
171 end
172 else
173 begin
174 fileNames := fileNames + tmpCurrentChar;
175 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
176 inc(currentParsePosition);
177 end;
178 end;
179 FILENAME_QUOTE :
180 begin
181 fileNames := fileNames + tmpCurrentChar;
182 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
183 inc(currentParsePosition);
184 end;
185 else
186 begin
187 searchText := searchText + tmpCurrentChar;
188 inc(currentParsePosition);
189 end;
190 end;
191 end;
192
193 '"' :
194 begin
195 Case tmpState of
196 SWITCH :
197 begin
198 // syntax error
199 raise EParsingFailed.Create('Unsupported switch');
200 end;
201 FILENAME :
202 begin
203 tmpState := FILENAME_QUOTE;
204 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
205 inc(currentParsePosition);
206 end;
207 FILENAME_QUOTE :
208 begin
209 tmpState := FILENAME;
210 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
211 inc(currentParsePosition);
212 end;
213 TEXT :
214 begin
215 searchText := searchText + tmpCurrentChar;
216 inc(currentParsePosition);
217 end;
218 end;
219 end;
220
221 else
222 begin
223 Case tmpState of
224 SWITCH :
225 begin
226 // syntax error
227 raise EParsingFailed.Create('Unsupported switch');
228 end;
229 FILENAME :
230 begin
231 fileNames := fileNames + tmpCurrentChar;
232 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
233 inc(currentParsePosition);
234 end;
235 FILENAME_QUOTE :
236 begin
237 fileNames := fileNames + tmpCurrentChar;
238 fileNamesRaw := fileNamesRaw + tmpCurrentChar;
239 inc(currentParsePosition);
240 end;
241 else
242 begin
243 searchText := searchText + tmpCurrentChar;
244 inc(currentParsePosition);
245 end;
246 end;
247 end;
248 end;
249 end;
250
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;
285 END;
286
287
288
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);
297
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;
305
306 aValue := readNextPart(aCmdLineString, [' ', '-', '/']);
307 currentParsePosition := currentParsePosition + length(aValue);
308 result := true;
309 exit;
310 end;
311 result := false;
312 end;
313
314
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');
321
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');
327
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;
340
341 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
342 Var
343 tmpParts : TStringList;
344 Begin
345 tmpParts := TStringList.Create;
346 StrExtractStrings(tmpParts, aParamValue, [','], '\');
347
348 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
349 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
350
351 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
352 if result.Width < 50 then
353 result.Width := 50;
354
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;
360 end;
361
362
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;
455 end;
456
457
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;
476END.
Note: See TracBrowser for help on using the repository browser.