source: trunk/NewView/CmdLineParameterUnit.pas@ 80

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

improved log handling

  • Property svn:eol-style set to native
File size: 17.7 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
22CONST
23 ENV_DEBUG = 'NEWVIEW_DEBUG';
24
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 : HWND;
45 windowPositionFlag: boolean;
46 windowPosition: TWindowPosition;
47 ownerWindow : integer;
48 windowTitle : string;
49 parsedFileNames : string;
50 parsedRawFileNames : string;
51 fileNames : string;
52 parsedSearchText : string;
53 searchText : string;
54 debugEnabled : boolean;
55
56 FUNCTION handleSwitchWithValue(const aSwitchString : String; const aSwitch : String; var aValue : String) : Boolean;
57 PROCEDURE parseSwitch(aSwitchString : String);
58 PROPERTY getParsedFileNames : string read parsedFileNames;
59 PROPERTY getParsedSearchText : string read parsedSearchText;
60
61 public
62 PROPERTY isDebugEnabled : boolean read debugEnabled;
63 PROPERTY getShowUsageFlag : boolean read showUsageFlag;
64 PROPERTY getSearchFlag : boolean read searchFlag;
65 PROPERTY getGlobalSearchFlag : boolean read globalSearchFlag;
66 PROPERTY getLanguage : string read language;
67 PROPERTY getHelpManagerFlag : boolean read helpManagerFlag;
68 FUNCTION setHelpManagerFlag(aNewValue : boolean) : boolean;
69 PROPERTY getHelpManagerWindow : HWND read helpManagerWindow;
70 PROPERTY getWindowPositionFlag : boolean read windowPositionFlag;
71 PROPERTY getWindowPosition : TWindowPosition read windowPosition;
72 PROPERTY getOwnerWindow : integer read ownerWindow;
73 PROPERTY getWindowTitle : string read windowTitle;
74 PROPERTY getFileNames : string read fileNames;
75 PROPERTY getSearchText : string read searchText;
76
77 PROCEDURE writeDetailsTo(aStrings : TStrings);
78 PROCEDURE logDetails;
79 PROCEDURE parseCmdLine(aCmdLineString : String);
80 end;
81
82 FUNCTION getOwnHelpFileName: String;
83
84 // returns a string containing the whole
85 // command line parametes
86 FUNCTION nativeOS2GetCmdLineParameter : String;
87
88
89Implementation
90uses
91 DOS,
92 ACLFileUtility;
93
94 PROCEDURE TCmdLineParameters.writeDetailsTo(aStrings : TStrings);
95 var
96 tmpWindowPosition : TWindowPosition;
97 begin
98 aStrings.Add('''' + commandLine + '''');
99 aStrings.Add('isDebugEnabled: ' + boolToStr(isDebugEnabled));
100 aStrings.Add('parsed infos:');
101
102 aStrings.Add(' showUsageFlag: ' + boolToStr(getShowUsageFlag));
103 aStrings.Add(' searchFlag: ' + boolToStr(getSearchFlag));
104 aStrings.Add(' fileNames: ' + getFileNames);
105 aStrings.Add(' parsedFileNames: ' + getParsedFileNames);
106 aStrings.Add(' searchText: ' + getSearchText);
107 aStrings.Add(' parsedSearchText: ' + getParsedSearchText);
108 aStrings.Add(' globalSearchFlag: ' + boolToStr(getGlobalSearchFlag));
109 aStrings.Add(' language: ' + getLanguage);
110 aStrings.Add(' helpManagerFlag: ' + boolToStr(getHelpManagerFlag));
111 aStrings.Add(' helpManagerWindow: ' + LongWordToStr(getHelpManagerWindow));
112 aStrings.Add(' windowPositionFlag: ' + boolToStr(getWindowPositionFlag));
113
114 tmpWindowPosition := getWindowPosition;
115 aStrings.Add(' windowPosition: '
116 + intToStr(tmpWindowPosition.left) + ', '
117 + intToStr(tmpWindowPosition.bottom) + ', '
118 + intToStr(tmpWindowPosition.width) + ', '
119 + intToStr(tmpWindowPosition.height)
120 );
121 aStrings.Add(' ownerWindow: ' + intToStr(getOwnerWindow));
122 aStrings.Add(' windowTitle: ' + getWindowTitle);
123 end;
124
125
126 PROCEDURE TCmdLineParameters.LogDetails;
127 var
128 tmpWindowPosition : TWindowPosition;
129 begin
130 LogEvent(LogStartup, '''' + commandLine + '''');
131 LogEvent(LogStartup, 'isDebugEnabled: ' + boolToStr(isDebugEnabled));
132 LogEvent(LogStartup, 'parsed infos:');
133
134 LogEvent(LogStartup, ' showUsageFlag: ' + boolToStr(getShowUsageFlag));
135 LogEvent(LogStartup, ' searchFlag: ' + boolToStr(getSearchFlag));
136 LogEvent(LogStartup, ' fileNames: ' + getFileNames);
137 LogEvent(LogStartup, ' parsedFileNames: ' + getParsedFileNames);
138 LogEvent(LogStartup, ' searchText: ' + getSearchText);
139 LogEvent(LogStartup, ' parsedSearchText: ' + getParsedSearchText);
140 LogEvent(LogStartup, ' globalSearchFlag: ' + boolToStr(getGlobalSearchFlag));
141 LogEvent(LogStartup, ' language: ' + getLanguage);
142 LogEvent(LogStartup, ' helpManagerFlag: ' + boolToStr(getHelpManagerFlag));
143 LogEvent(LogStartup, ' helpManagerWindow: ' + LongWordToStr(getHelpManagerWindow));
144 LogEvent(LogStartup, ' windowPositionFlag: ' + boolToStr(getWindowPositionFlag));
145
146 tmpWindowPosition := getWindowPosition;
147 LogEvent(LogStartup, ' windowPosition: '
148 + intToStr(tmpWindowPosition.left) + ', '
149 + intToStr(tmpWindowPosition.bottom) + ', '
150 + intToStr(tmpWindowPosition.width) + ', '
151 + intToStr(tmpWindowPosition.height)
152 );
153 LogEvent(LogStartup, ' ownerWindow: ' + intToStr(getOwnerWindow));
154 LogEvent(LogStartup, ' windowTitle: ' + getWindowTitle);
155 end;
156
157
158 Function TCmdLineParameters.setHelpManagerFlag(aNewValue : boolean) : boolean;
159 begin
160 helpManagerFlag := aNewValue;
161 result := helpManagerFlag;
162 end;
163
164
165 Procedure TCmdLineParameters.parseCmdLine(aCmdLineString : String);
166 var
167 tmpState : (WHITESPACE, QUOTE, SWITCH, FILENAME, TEXT);
168 tmpCurrentParsePosition : integer;
169 tmpQuoted : boolean;
170 tmpCurrentChar : char;
171 tmpWhitespace : String;
172 tmpQuote : String;
173 tmpSwitch : String;
174 tmpOwnHelpFileName : String;
175 begin
176 // first adjust logging
177 debugEnabled := false;
178 if GetEnv(ENV_DEBUG) = '' then
179 begin
180 debugEnabled := true;
181 end
182 else
183 begin
184 SetLogAspects(GetEnv(ENV_DEBUG));
185 end;
186
187 LogEvent(LogStartup, 'ParseCommandLine: "' + aCmdLineString + '"');
188
189 // store the original string for debugging
190 commandLine := aCmdLineString;
191
192 // reset the whole object
193 showUsageFlag := false;
194 searchFlag := false;
195 globalSearchFlag := false;
196 language := '';
197 helpManagerFlag := false;
198 helpManagerWindow := 0;
199 windowPositionFlag := false;
200 ownerWindow := 0;
201 windowTitle := '';
202 parsedSearchText := '';
203 parsedFileNames := '';
204 parsedRawFileNames := '';
205
206 try
207 // start parsing
208 tmpState := WHITESPACE;
209 tmpWhitespace := '';
210 tmpSwitch := '';
211 tmpQuote := '';
212 tmpQuoted := false;
213 tmpCurrentParsePosition := 1;
214 while tmpCurrentParsePosition <= length(aCmdLineString) do
215 begin
216 tmpCurrentChar := aCmdLineString[tmpCurrentParsePosition];
217
218 Case tmpCurrentChar of
219 ' ' :
220 begin
221 Case tmpState of
222
223 WHITESPACE :
224 begin
225 tmpWhitespace := tmpWhitespace + tmpCurrentChar;
226 end;
227
228 QUOTE :
229 begin
230 tmpQuote := tmpQuote + tmpCurrentChar;
231 end;
232
233 SWITCH :
234 begin
235 if tmpQuoted then
236 begin
237 tmpSwitch := tmpSwitch + tmpCurrentChar;
238 end
239 else
240 begin
241 parseSwitch(tmpSwitch);
242 tmpState := WHITESPACE;
243 tmpWhitespace := tmpCurrentChar;
244 end
245 end;
246
247 FILENAME :
248 begin
249 if tmpQuoted then
250 begin
251 parsedFileNames := parsedFileNames + tmpCurrentChar;
252 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
253 end
254 else
255 begin
256 tmpState := WHITESPACE;
257 tmpWhitespace := tmpCurrentChar;
258 end
259 end;
260
261 TEXT :
262 begin
263 if tmpQuoted then
264 begin
265 parsedSearchText := parsedSearchText + tmpCurrentChar;
266 end
267 else
268 begin
269 tmpState := WHITESPACE;
270 tmpWhitespace := tmpCurrentChar;
271 end
272 end;
273 end;
274 end;
275
276 '/', '-' :
277 begin
278 Case tmpState of
279 WHITESPACE :
280 begin
281 tmpState := SWITCH;
282 tmpSwitch := '';
283 end;
284
285 QUOTE :
286 begin
287 tmpState := SWITCH;
288 tmpSwitch := '';
289 end;
290
291 SWITCH :
292 begin
293 parseSwitch(tmpSwitch);
294 tmpSwitch := '';
295 end;
296
297 FILENAME :
298 begin
299 parsedFileNames := parsedFileNames + tmpCurrentChar;
300 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
301 end;
302
303 TEXT :
304 begin
305 parsedSearchText := parsedSearchText + tmpCurrentChar;
306 end;
307 end;
308 end;
309
310 '"' :
311 begin
312 if tmpQuoted then
313 begin
314 tmpQuoted := false;
315 Case tmpState of
316 FILENAME :
317 begin
318 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
319 end;
320 TEXT :
321 begin
322 parsedSearchText := parsedSearchText + tmpCurrentChar;
323 end;
324 end;
325 end
326 else
327 begin
328 tmpQuoted := true;
329 Case tmpState of
330 WHITESPACE :
331 begin
332 tmpState := QUOTE;
333 tmpQuote := tmpCurrentChar;
334 end;
335 FILENAME :
336 begin
337 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
338 end;
339 end;
340 end;
341 end;
342
343 // any other char
344 else
345 begin
346 Case tmpState of
347
348 WHITESPACE :
349 begin
350 if length(parsedFileNames) > 0 then
351 begin
352 tmpState := TEXT;
353 parsedSearchText := parsedSearchText + tmpWhitespace + tmpCurrentChar;
354 end
355 else
356 begin
357 tmpState := FILENAME;
358 parsedFileNames := parsedFileNames + tmpCurrentChar;
359 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
360 end;
361 end;
362
363 QUOTE :
364 begin
365 if length(parsedFileNames) > 0 then
366 begin
367 tmpState := TEXT;
368 parsedSearchText := parsedSearchText + tmpQuote + tmpCurrentChar;
369 end
370 else
371 begin
372 tmpState := FILENAME;
373 parsedFileNames := parsedFileNames + tmpCurrentChar;
374 parsedRawFileNames := parsedRawFileNames + tmpQuote + tmpCurrentChar;
375 end;
376 end;
377
378 SWITCH :
379 begin
380 tmpSwitch := tmpSwitch + tmpCurrentChar;
381 end;
382
383 FILENAME :
384 begin
385 parsedFileNames := parsedFileNames + tmpCurrentChar;
386 parsedRawFileNames := parsedRawFileNames + tmpCurrentChar;
387 end;
388
389 TEXT :
390 begin
391 parsedSearchText := parsedSearchText + tmpCurrentChar;
392 end;
393 end;
394 end;
395 end;
396 inc(tmpCurrentParsePosition);
397 end;
398
399 // ok all chars are processed, but maybe we have something to do
400 Case tmpState of
401 SWITCH :
402 begin
403 parseSwitch(tmpSwitch);
404 end;
405 end;
406 except
407 on e:EParsingFailed do
408 begin
409 showUsageFlag := true;
410 end;
411 end;
412
413 // remove blanks
414 fileNames := StrTrim(getParsedFileNames);
415 searchText := StrTrim(getParsedSearchText);
416
417 if getGlobalSearchFlag
418 AND (getParsedSearchText = '')
419 then
420 begin
421 fileNames := '';
422 searchText := parsedRawFileNames;
423 end
424 else
425 begin
426 if fileNames = '' then
427 begin
428 tmpOwnHelpFileName := FindDefaultLanguageHelpFile('NewView');
429 if FileExists(tmpOwnHelpFileName)
430 then
431 fileNames := tmpOwnHelpFileName;
432 end;
433 end;
434
435 // to be compatible with the old one we have to ignore
436 // the quotes
437 if not getGlobalSearchFlag
438 AND (not getSearchFlag)
439 then
440 begin
441 searchText := StrTrimChars(searchText, ['"']);
442 end;
443
444 LogEvent(LogStartup, 'Parameters parsed');
445 LogDetails;
446 end;
447
448
449 Function TCmdLineParameters.handleSwitchWithValue(const aSwitchString : String; const aSwitch : String; var aValue : String) : Boolean;
450 var
451 tmpText : String;
452 tmpValueStartPos : integer;
453 tmpSwitchLength : integer;
454 begin
455 tmpSwitchLength := Length(aSwitch);
456 tmpText := copy(aSwitchString, 1, tmpSwitchLength);
457 tmpText := lowercase(tmpText);
458
459 if (lowercase(aSwitch) = tmpText) then
460 begin
461 tmpValueStartPos := tmpSwitchLength;
462 inc(tmpValueStartPos);
463 if aSwitchString[tmpValueStartPos] = ':' then
464 begin
465 inc(tmpValueStartPos);
466 end;
467
468 aValue := copy(aSwitchString, tmpValueStartPos, Length(aSwitchString) - tmpValueStartPos+ 1);
469 result := true;
470 exit;
471 end;
472 result := false;
473 end;
474
475
476 Function ParseWindowPositionPart(const aPart: String; const aScreenDimension: longint): longint;
477 Var
478 tmpPart : String;
479 Begin
480 if aPart = '' then
481 raise EParsingFailed.Create('Missing position element');
482
483 if StrEndsWithIgnoringCase(aPart, 'P') then
484 begin
485 tmpPart := copy(aPart, 1, length(aPart)-1);
486 if tmpPart = '' then
487 raise EParsingFailed.Create('Missing position element');
488
489 Result := StrToInt(tmpPart);
490 if Result < 0 then
491 Result := 0;
492 if Result > 100 then
493 Result := 100;
494 Result := Round(Result / 100 * aScreenDimension);
495 end
496 else
497 begin
498 Result := StrToInt(aPart);
499 end;
500 end;
501
502 Function ParseWindowPosition(const aParamValue: String): TWindowPosition;
503 Var
504 tmpParts : TStringList;
505 Begin
506 tmpParts := TStringList.Create;
507 StrExtractStrings(tmpParts, aParamValue, [','], '\');
508
509 result.Left := ParseWindowPositionPart(tmpParts[0], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
510 result.Bottom := ParseWindowPositionPart(tmpParts[1], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
511
512 result.Width := ParseWindowPositionPart(tmpParts[2], WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN));
513 if result.Width < 50 then
514 result.Width := 50;
515
516 result.Height := ParseWindowPositionPart(tmpParts[3], WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN));
517 if result.Height < 50 then
518 result.Height := 50;
519
520 tmpParts.Destroy;
521 end;
522
523
524 Procedure TCmdLineParameters.parseSwitch(aSwitchString : String);
525 var
526 tmpCurrentChar : char;
527 tmpValue : String;
528 begin
529 // lang
530 if handleSwitchWithValue(aSwitchString, 'lang', tmpValue) then
531 begin
532 language := tmpValue;
533 exit;
534 end;
535
536 // title
537 if handleSwitchWithValue(aSwitchString, 'title', tmpValue) then
538 begin
539 windowTitle := tmpValue;
540 exit;
541 end;
542
543 // HM
544 if handleSwitchWithValue(aSwitchString, 'hm', tmpValue) then
545 begin
546 try
547 helpManagerWindow := StrToInt(tmpValue);
548 helpManagerFlag := true;
549 except
550 on e:Exception do
551 begin
552 showUsageFlag := true;
553 end;
554 end;
555 exit;
556 end;
557
558 // owner
559 if handleSwitchWithValue(aSwitchString, 'owner', tmpValue) then
560 begin
561 try
562 ownerWindow := StrToInt(tmpValue);
563 except
564 on e:Exception do
565 begin
566 showUsageFlag := true;
567 end;
568 end;
569 exit;
570 end;
571
572 // pos
573 if handleSwitchWithValue(aSwitchString, 'pos', tmpValue) then
574 begin
575 windowPosition := ParseWindowPosition(tmpValue);
576 windowPositionFlag := true;
577 exit;
578 end;
579
580 // check the next char
581 // TODO check for other invalid chars
582 tmpCurrentChar := aSwitchString[1];
583 Case tmpCurrentChar of
584 'h', 'H', '?' :
585 begin
586 showUsageFlag := true;
587 end;
588
589 's', 'S' :
590 begin
591 searchFlag := true;
592 end;
593
594 'g', 'G' :
595 begin
596 globalSearchFlag := true;
597 end;
598
599 else
600 begin
601 raise EParsingFailed.Create('Unsupported switch');
602 end;
603 end;
604 end;
605
606
607 FUNCTION getOwnHelpFileName: String;
608 begin
609 result := FindDefaultLanguageHelpFile('NewView');
610 end;
611
612
613 FUNCTION nativeOS2GetCmdLineParameter : STRING;
614 VAR
615 tmpPtib : PTIB; // thread information block
616 tmpPpib : PPIB; // process information block
617 tmpCmd : PCHAR;
618 tmpResult : PCHAR;
619
620 BEGIN
621 // ask the system
622 DosGetInfoBlocks(tmpPtib, tmpPpib);
623 tmpCmd := tmpPpib^.pib_pchcmd;
624 // the fist element (null terminated) is the
625 // called command itself
626 // skip to the next null terminated string
627 // these are the parameters
628 tmpResult := tmpCmd + StrLen(tmpCmd) + 1;
629 result := StrPas(tmpResult);
630 END;
631END.
Note: See TracBrowser for help on using the repository browser.