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
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 searchText : string;
51
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
57 public
58 PROPERTY getCommandLine : String read commandLine;
59 PROPERTY getShowUsageFlag : boolean read showUsageFlag;
60 PROPERTY getSearchFlag : boolean read searchFlag;
61 PROPERTY getGlobalSearchFlag : boolean read globalSearchFlag;
62 PROPERTY getLanguage : string read language;
63 PROPERTY getHelpManagerFlag : boolean read helpManagerFlag;
64 FUNCTION setHelpManagerFlag(aNewValue : boolean) : boolean;
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;
71 PROPERTY getSearchText : string read searchText;
72
73 PROCEDURE parseCmdLine(aCmdLineString : String);
74 private
75 PROCEDURE parseSwitch(aCmdLineString : String);
76 end;
77
78 // returns a string containing the whole
79 // command line parametes
80 FUNCTION nativeOS2GetCmdLineParameter : STRING;
81
82
83Implementation
84
85 FUNCTION TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
86 begin
87 helpManagerFlag := aNewValue;
88 result := helpManagerFlag;
89 end;
90
91
92 procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
93 var
94 tmpState : (SWITCH, FILENAME, FILENAME_QUOTE, TEXT);
95 tmpCurrentChar : char;
96 begin
97 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
98
99 // store the original string for debugging
100 commandLine := aCmdLineString;
101
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 := '';
114
115 try
116 // start parsing
117 tmpState := FILENAME;
118 currentParsePosition := 1;
119 while currentParsePosition <= length(aCmdLineString) do
120 begin
121 tmpCurrentChar := aCmdLineString[currentParsePosition];
122
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
135 begin
136 tmpState := TEXT;
137 end;
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;
150 end;
151 end;
152
153 '/', '-' :
154 begin
155 Case tmpState of
156 SWITCH :
157 begin
158 tmpState := SWITCH;
159 parseSwitch(aCmdLineString);
160 end;
161 FILENAME :
162 begin
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;
173 end;
174 FILENAME_QUOTE :
175 begin
176 filenames := filenames + tmpCurrentChar;
177 inc(currentParsePosition);
178 end;
179 else
180 begin
181 searchText := searchText + tmpCurrentChar;
182 inc(currentParsePosition);
183 end;
184 end;
185 end;
186
187 '"' :
188 begin
189 Case tmpState of
190 SWITCH :
191 begin
192 // syntax error
193 raise EParsingFailed.Create('Unsupported switch');
194 end;
195 FILENAME :
196 begin
197 tmpState := FILENAME_QUOTE;
198 inc(currentParsePosition);
199 end;
200 FILENAME_QUOTE :
201 begin
202 tmpState := FILENAME;
203 inc(currentParsePosition);
204 end;
205 TEXT :
206 begin
207 searchText := searchText + tmpCurrentChar;
208 inc(currentParsePosition);
209 end;
210 end;
211 end;
212
213 else
214 begin
215 Case tmpState of
216 SWITCH :
217 begin
218 // syntax error
219 raise EParsingFailed.Create('Unsupported switch');
220 end;
221 FILENAME :
222 begin
223 fileNames := fileNames + tmpCurrentChar;
224 inc(currentParsePosition);
225 end;
226 FILENAME_QUOTE :
227 begin
228 filenames := filenames + tmpCurrentChar;
229 inc(currentParsePosition);
230 end;
231 else
232 begin
233 searchText := searchText + tmpCurrentChar;
234 inc(currentParsePosition);
235 end;
236 end;
237 end;
238 end;
239 end;
240
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;
275 END;
276
277
278
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);
287
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;
295
296 aValue := readNextPart(aCmdLineString, [' ', '-', '/']);
297 currentParsePosition := currentParsePosition + length(aValue);
298 result := true;
299 exit;
300 end;
301 result := false;
302 end;
303
304
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');
311
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');
317
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;
330
331 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
332 Var
333 tmpParts : TStringList;
334 Begin
335 tmpParts := TStringList.Create;
336 StrExtractStrings(tmpParts, aParamValue, [','], '\');
337
338 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
339 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
340
341 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
342 if result.Width < 50 then
343 result.Width := 50;
344
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;
350 end;
351
352
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;
445 end;
446
447
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;
466END.
Note: See TracBrowser for help on using the repository browser.