source: trunk/NewView/StartupUnit.pas@ 18

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

+ newview source

  • Property svn:eol-style set to native
File size: 13.3 KB
Line 
1Unit StartupUnit;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2003 Aaron Lawrence (aaronl at consultant dot com)
5// This software is released under the Gnu Public License - see readme.txt
6
7// Code related to startup and finding help files.
8// Shared between NewView.exe and ViewStub.exe
9
10Interface
11
12uses
13 OS2Def,
14 Classes,
15 ACLString,
16 GlobalFilelistUnit,
17 SharedMemoryUnit;
18
19const
20 OWN_HELP_MARKER = '[NVHELP]';
21
22type
23 TWindowPosition = record
24 Left: longint;
25 Bottom: longint;
26 Width: longint;
27 Height: longint;
28 end;
29
30 TCommandLineParameters = record
31 ShowUsageFlag: boolean; // *
32 TopicParam: string; // *
33 FilenamesParam: TAString;
34 SearchText: string;
35 SearchFlag: boolean;
36 GlobalSearchText: string; // *
37 GlobalSearchFlag: boolean; // *
38 OwnerWindow: HWND;
39 HelpManagerWindow: HWND;
40 IsHelpManager: boolean;
41 WindowTitle: string;
42 Position: TWindowPosition;
43 SetPosition: boolean;
44 Language: string;
45 end;
46 // * posted to re-used windows
47
48Procedure ParseCommandLineParameters;
49
50function AccessSharedMemory: TSuballocatedSharedMemory;
51
52// Returns true if the program should be started as normal.
53// False if it should immediately exit.
54function Startup: boolean;
55
56function GetOwnHelpFileName: string;
57
58// Look for any items that are actually specifiying environment
59// variables, and expand them to the contents of the variables
60Procedure TranslateIPFEnvironmentVars( Items: TStrings;
61 ExpandedItems: TStrings );
62
63// Given a filename, which may or may not contain a path or extension,
64// finds the actual file. This can involve searching
65// the help and bookshelf paths.
66Function FindHelpFile( FileName: string ): string;
67
68var
69 Parameters: TCommandLineParameters;
70 SharedMemory: TSubAllocatedSharedMemory;
71 GlobalFilelist: TGlobalFilelist;
72
73Implementation
74
75uses
76 //Forms,
77 Dos, SysUtils, PMWin,
78 ACLUtility, ACLStringUtility, ACLFileUtility, AStringUtilityUnit, ACLProfile,
79 HelpManagerUnit;
80
81// Look for any items that are actually specifiying environment
82// variables, and expand them to the contents of the variables
83Procedure TranslateIPFEnvironmentVars( Items: TStrings;
84 ExpandedItems: TStrings );
85var
86 i: longint;
87 Item: string;
88 EnvironmentVarValue: string;
89begin
90 ProfileEvent( 'Translating environment vars' );
91 for i := 0 to Items.Count - 1 do
92 begin
93 Item := Items[ i ];
94
95 Item := StrUnQuote( Item ); // remove single quotes
96 Item := StrUnDoubleQuote( Item ); // remove double quotes
97
98 ProfileEvent( ' Item: ' + Item );
99 EnvironmentVarValue := GetEnv( Uppercase( Item ) );
100 if DosError = 0 then
101 begin
102 // environment var exists - use it's value
103 ProfileEvent( ' Translated: ' + EnvironmentVarValue );
104 while EnvironmentVarValue <> '' do
105 begin
106 Item := ExtractNextValue( EnvironmentVarValue, '+' );
107 ExpandedItems.Add( Item );
108 end;
109 end
110 else
111 begin
112 // not an environment var
113 ExpandedItems.Add( Item );
114 end;
115 end;
116end;
117
118// Given a filename, which may or may not contain a path or extension,
119// finds the actual file. This can involve searching
120// the help and bookshelf paths.
121Function FindHelpFile( FileName: string ): string;
122var
123 AlternativeFileName: string;
124begin
125 if FileName = OWN_HELP_MARKER then
126 begin
127 Result := GetOwnHelpFileName;
128 exit;
129 end;
130
131 Result := '';
132
133 AlternativeFileName := '';
134 if ExtractFileExt( Filename ) = '' then
135 begin
136 Filename := ChangeFileExt( Filename, '.inf' );
137 AlternativeFileName := ChangeFileExt( Filename, '.hlp' );
138 end;
139
140 if ExtractFilePath( FileName ) <> '' then
141 begin
142 // Path specified; just see if it exists
143
144 // expand out relative paths
145 Filename := ExpandFileName( FileName );
146 AlternativeFilename := ExpandFileName( AlternativeFilename );
147
148 if FileExists( Filename ) then
149 Result := Filename
150 else if FileExists( AlternativeFilename ) then
151 Result := AlternativeFilename;
152
153 end
154 else
155 begin
156 // Path not specified; search current
157 if FileExists( ExpandFileName( FileName ) ) then
158 begin
159 Result := ExpandFileName( FileName );
160 exit;
161 end;
162
163 if FileExists( ExpandFileName( AlternativeFilename ) ) then
164 begin
165 Result := ExpandFileName( AlternativeFilename );
166 exit;
167 end;
168
169 // Search help paths
170
171 if not SearchHelpPaths( FileName,
172 Result,
173 false // don't search our app dir
174 ) then
175 begin
176 // Didn't find as specified or as .inf, try .hlp
177 if AlternativeFilename <> '' then
178 begin
179 if not SearchHelpPaths( AlternativeFileName,
180 Result,
181 false // don't search our app dir
182 ) then
183 begin
184 Result := '';
185 end;
186 end;
187 end;
188 end;
189end;
190
191function GetOwnHelpFileName: string;
192begin
193 Result := FindDefaultLanguageHelpFile( 'NewView' );
194end;
195
196// Extract a single element of a window position spec
197// - take a value from comma-separated list
198// - convert to numeric
199// - if the number ends with P then take as
200// a percentage of given dimension
201Function ExtractPositionElement( Var ParamValue: string;
202 ScreenDimension: longint ): longint;
203var
204 Element: string;
205begin
206 Element := ExtractNextValue( ParamValue, ',' );
207 if Element = '' then
208 raise Exception.Create( 'Missing position element' );
209 if StrEnds( 'P', Element ) then
210 begin
211 Delete( Element, Length( Element ), 1 );
212 if Element = '' then
213 raise Exception.Create( 'Missing position element' );
214 Result := StrToInt( Element );
215 if Result < 0 then
216 Result := 0;
217 if Result > 100 then
218 Result := 100;
219 Result := Round( Result / 100 * ScreenDimension );
220 end
221 else
222 begin
223 Result := StrToInt( Element );
224 end;
225end;
226
227Function SystemMetrics(sm:LONG):LongInt;
228Begin
229 Result := WinQuerySysValue(HWND_DESKTOP,sm);
230end;
231
232// Extract a specified window position:
233// X,Y,W,H
234Function ExtractPositionSpec( ParamValue: string;
235 Var Position: TWindowPosition ): boolean;
236begin
237 try
238 Position.Left := ExtractPositionElement( ParamValue, SystemMetrics(SV_CXSCREEN) );
239 Position.Bottom := ExtractPositionElement( ParamValue, SystemMetrics(SV_CYSCREEN) );
240 Position.Width := ExtractPositionElement( ParamValue, SystemMetrics(SV_CXSCREEN) );
241 if Position.Width < 50 then
242 Position.Width := 50;
243 Position.Height := ExtractPositionElement( ParamValue, SystemMetrics(SV_CYSCREEN) );
244 if Position.Height < 50 then
245
246 Position.Height := 50;
247 Result := true;
248 except
249 Result := false;
250 end;
251end;
252
253// Parse command line parameters newview was launched with.
254// Store them into the Parameters. variables for later processing.
255Procedure ParseCommandLineParameters;
256var
257 ParamIndex: longint;
258 Param: string;
259 ParamValue: string;
260begin
261 ProfileEvent( 'ParseCommandLineParameters started' );
262
263 Parameters.FilenamesParam := TAString.Create;
264 Parameters.TopicParam := '';
265 Parameters.ShowUsageFlag := false;
266 Parameters.GlobalSearchFlag := false;
267 Parameters.SearchFlag := false;
268 Parameters.OwnerWindow := 0;
269 Parameters.IsHelpManager := false;
270 Parameters.HelpManagerWindow := 0;
271 Parameters.WindowTitle := '';
272 Parameters.SetPosition := false;
273 Parameters.Language := '';
274
275 for ParamIndex := 1 to ParamCount do
276 begin
277 Param := ParamStr( ParamIndex );
278 if MatchFlagParam( Param, '?' )
279 or MatchFlagParam( Param, 'H' )
280 or MatchFlagParam( Param, 'HELP' ) then
281 begin
282 Parameters.ShowUsageFlag := true
283 end
284 else if MatchValueParam( Param, 'LANG', Parameters.Language ) then
285 begin
286 end
287 else if MatchValueParam( Param, 'G', Parameters.GlobalSearchText ) then
288 begin
289 Parameters.GlobalSearchFlag := true;
290 end
291 else if MatchValueParam( Param, 'S', Parameters.SearchText ) then
292 begin
293 Parameters.SearchFlag := true;
294 end
295 else if MatchValueParam( Param, 'HM', ParamValue ) then
296 begin
297 try
298 Parameters.HelpManagerWindow := StrToInt( ParamValue );
299 Parameters.IsHelpManager := true;
300 except
301 // ignore invalid window value
302 end;
303 end
304 else if MatchValueParam( Param, 'OWNER', ParamValue ) then
305 begin
306 Parameters.OwnerWindow := StrToInt( ParamValue );
307 end
308 else if MatchValueParam( Param, 'TITLE', ParamValue ) then
309 begin
310 Parameters.WindowTitle := ParamValue;
311 end
312 else if MatchFlagParam( Param, 'PROFILE' ) then
313 begin
314 StartProfile( GetLogFilesDir + 'newview.prf' );
315 end
316 else if MatchValueParam( Param, 'POS', ParamValue ) then
317 begin
318 // set window position/size
319 if ExtractPositionSpec( ParamValue,
320 Parameters.Position ) then
321 begin
322 Parameters.SetPosition := true;
323 end
324 else
325 begin
326 // invalid...
327 Parameters.ShowUsageFlag := true;
328 end;
329 end
330 else
331 begin
332 if Parameters.FilenamesParam.Length = 0 then
333 begin
334 // filename(s)
335 AString_ParamStr( ParamIndex, Parameters.FilenamesParam );
336 end
337 else
338 begin
339 // search (topic) parameter... append all remaining thingies
340 if Parameters.TopicParam <> '' then
341 begin
342 Parameters.TopicParam := Parameters.TopicParam + ' ';
343 end;
344 Parameters.TopicParam := Parameters.TopicParam + Param;
345 end;
346 end;
347 end;
348
349 ProfileEvent( 'Parameters parsed' );
350 ProfileEvent( ' Filenames: '
351 + Parameters.FilenamesParam.AsString );
352 ProfileEvent( ' Topic: '
353 + Parameters.TopicParam );
354
355 // params will be acted on later...
356 ProfileEvent( '...done' );
357
358end;
359
360// If another instance already has the files open
361// activate it and return true.
362function FindExistingWindow: HWND;
363var
364 FileItems: TStringList;
365 Filenames: TStringList;
366 FullFilePath: string;
367 i: longint;
368
369 FileWindow: HWND;
370begin
371 Result := NULLHANDLE;
372
373 if Parameters.FilenamesParam.Length = 0 then
374 // not loading files; nothing to check
375 exit;
376
377 FileItems := TStringList.Create;
378 Filenames := TStringList.Create;
379
380 AStringToList( Parameters.FilenamesParam, FileItems, '+' );
381 TranslateIPFEnvironmentVars( FileItems, FileNames );
382
383 for i := 0 to FileNames.Count - 1 do
384 begin
385 FullFilePath := FindHelpFile( Filenames[ i ] );
386 if FullFilePath <> '' then
387 begin
388 FileWindow := GlobalFilelist.FindFile( FullFilePath );
389
390 if FileWindow = NULLHANDLE then
391 begin
392 // not found - stop searching.
393 Result := NULLHANDLE; // no match
394 break;
395 end;
396
397 // found it
398
399 // is it the same as any previous match?
400 if Result <> NULLHANDLE then
401 begin
402 if FileWindow <> Result then
403 begin
404 // no, so we don't have a match.
405 // NOTE: We just excluded something: if the same file is
406 // open in multiple windows then we may not check all combinations
407 Result := NULLHANDLE; // no match
408 break;
409 end;
410 end
411 else
412 begin
413 // no match yet - store this one
414 Result := FileWindow;
415 end;
416
417 end;
418 end;
419
420 Filenames.Destroy;
421 FileItems.Destroy;
422
423end;
424
425function AccessSharedMemory: TSuballocatedSharedMemory;
426begin
427 Result := TSuballocatedSharedMemory.Create( SharedMemName,
428 SharedMemSize,
429 SharedMemReserveSize );
430end;
431
432procedure PostNewViewTextMessage( Window: HWND;
433 MessageType: ULONG;
434 s: string );
435var
436 ps: pchar;
437begin
438 SharedMemory.Allocate( ps, length( s ) + 1 );
439 ps ^ := s;
440 WinPostMsg( Window,
441 MessageType,
442 LONG( ps ),
443 0 );
444end;
445
446function Startup: boolean;
447var
448 ExistingWindow: HWND;
449begin
450 // open shared memory
451 SharedMemory := AccessSharedMemory;
452
453 // get access to the system-global filelist
454 GlobalFilelist := TGlobalFilelist.Create;
455
456 // parse parameters into Parameters object
457 ParseCommandLineParameters;
458
459 ExistingWindow := FindExistingWindow;
460
461 if ExistingWindow <> NULLHANDLE then
462 begin
463 // want to exit without running fully
464 Result := false;
465
466 // destroy global list - nobody else will
467 GlobalFilelist.Destroy;
468 Parameters.FilenamesParam.Destroy;
469
470 WinSetFocus( HWND_DESKTOP, ExistingWindow );
471
472 if Parameters.TopicParam <> '' then
473 begin
474 PostNewViewTextMessage( ExistingWindow,
475 NHM_SEARCH,
476 Parameters.TopicParam );
477 end;
478
479 if Parameters.GlobalSearchFlag then
480 begin
481 PostNewViewTextMessage( ExistingWindow,
482 NHM_GLOBAL_SEARCH,
483 Parameters.GlobalSearchText );
484 end;
485
486 if Parameters.ShowUsageFlag then
487 begin
488 WinPostMsg( ExistingWindow,
489 NHM_SHOW_USAGE,
490 0,
491 0 );
492 end;
493
494 if Parameters.IsHelpManager then
495 begin
496 // tell the new help manager instance to talk to the
497 // other viewer
498 WinPostMsg( Parameters.HelpManagerWindow,
499 NHM_VIEWER_READY,
500 ExistingWindow,
501 0 );
502 end;
503
504 end
505 else
506 begin
507 // run as normal
508 Result := true;
509 end;
510end;
511
512Initialization
513End.
Note: See TracBrowser for help on using the repository browser.