source: trunk/NewView/CmdLineParameterUnit.pas@ 109

Last change on this file since 109 was 109, checked in by RBRi, 18 years ago

updates for AnsiString usage

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