source: trunk/NewView/MainForm.pas@ 129

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

respect settings for openeing the own help file

  • Property svn:eol-style set to native
File size: 184.7 KB
Line 
1Unit MainForm;
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
7Interface
8
9Uses
10// system is a good unit to be able to open ;)
11// the above line is here so you can use right-mouse open file on "system"
12 OS2Def,
13 SysUtils,
14 Classes,
15 Forms,
16 Graphics,
17 Messages,
18 Buttons,
19 ComCtrls,
20 StdCtrls,
21 ExtCtrls,
22 TabCtrls,
23 Dialogs,
24
25// library
26 ACLString,
27 SharedMemoryUnit,
28 ACLLanguageUnit,
29 GenericThread,
30 CmdLineParameterUnit,
31
32// custom components
33 SplitBar,
34 Outline2,
35 RichTextView,
36 Coolbar2,
37 CustomListBox,
38
39// local
40 HelpFile,
41 HelpTopic,
42 HelpWindowUnit,
43 HelpWindowDimensions,
44 NavigatePointUnit,
45 MiscUnit,
46 HelpManagerUnit,
47 TextSearchQuery,
48 IPFFileFormatUnit,
49 Tabset2Unit;
50
51const
52 // Custom window messages for this form
53 // NOTE! Sibyl uses WM_USER+1 and +2!
54 WM_OPENED = WM_USER + 10;
55 WM_FOLLOWLINK = WM_USER + 11;
56 WM_FOLLOWEXTERNALLINK = WM_USER + 12;
57
58 MAIN_WINDOW_CLASS_NAME = 'NewViewMainForm';
59
60Type
61
62 TMainForm = Class (TForm)
63 VSplitBar: TSplitBar;
64 Notebook: TNoteBook;
65 IndexSearchEdit: TEdit;
66 SearchTextEdit: TEdit;
67 SearchResultsListBox: TListBox;
68 NotesListBox: TListBox;
69 CoolBar: TCoolBar2;
70 MenuItem21: TMenuItem;
71 SaveAsIPFMI: TMenuItem;
72 MenuItem20: TMenuItem;
73 DebugFindBinaryMI: TMenuItem;
74 TopicByNameMI: TMenuItem;
75 DebugTopicByResourceIDMI: TMenuItem;
76 ToolsDebugSep: TMenuItem;
77 DebugSaveLanguageFileMI: TMenuItem;
78 DebugLoadLanguageMI: TMenuItem;
79 TabSet: TTabSet2;
80 NavigateNextMI: TMenuItem;
81 ShowLeftPanelMI: TMenuItem;
82 MenuItem18: TMenuItem;
83 AddNoteButton: TButton;
84 EditNoteButton: TButton;
85 DeleteNoteButton: TButton;
86 GotoNoteButton: TButton;
87 MenuItem23: TMenuItem;
88 MenuItem24: TMenuItem;
89 MenuItem25: TMenuItem;
90 DebugHelpManagerVersionMI: TMenuItem;
91 MenuItem19: TMenuItem;
92 ViewHighlightSearchWordsMI: TMenuItem;
93 MenuItem17: TMenuItem;
94 MenuItem16: TMenuItem;
95 MenuItem15: TMenuItem;
96 FileNewWindowMI: TMenuItem;
97 OpenSpecialMI: TMenuItem;
98 MenuItem14: TMenuItem;
99 SearchPMI: TMenuItem;
100 ViewSourceMI: TMenuItem;
101 FileCloseMI: TMenuItem;
102 MenuItem10: TMenuItem;
103 MenuItem12: TMenuItem;
104 MenuItem13: TMenuItem;
105 StatusPanel: TPanel;
106 ProgressPanel: TPanel;
107 ProgressBar: TProgressBar;
108 DebugShowWordSeparatorsMI: TMenuItem;
109 DebugStressTestMI: TMenuItem;
110 TopicPropertiesPMI: TMenuItem;
111 MenuItem3: TMenuItem;
112 MenuItem2: TMenuItem;
113 MenuItem8: TMenuItem;
114 ToolsOptionsMI: TMenuItem;
115 MenuItem9: TMenuItem;
116 ToolsDebugMenu: TMenuItem;
117 DebugShowParamsMI: TMenuItem;
118 DebugShowCodesMI: TMenuItem;
119 EditGlobalSearchMI: TMenuItem;
120 ViewExpandAllMI: TMenuItem;
121 EditBookmarksMI: TMenuItem;
122 AddBookmarkMI: TMenuItem;
123 ViewPopupMenu: TPopupMenu;
124 SelectAllPMI: TMenuItem;
125 CopyPMI: TMenuItem;
126 ContentsOutline: TOutline2;
127 IndexListBox: TCustomListBox;
128 ViewCollapseAllMI: TMenuItem;
129 MenuItem7: TMenuItem;
130 SystemOpenDialog: TSystemOpenDialog;
131 SearchButton: TButton;
132 MenuItem1: TMenuItem;
133 ViewIndexMI: TMenuItem;
134 ViewContentsMI: TMenuItem;
135 ViewSearchMI: TMenuItem;
136 ViewNotesMI: TMenuItem;
137 ViewRefreshMI: TMenuItem;
138 MenuItem11: TMenuItem;
139 DisplayPanel: TPanel;
140 ButtonImages: TImageList;
141 BookmarksMenu: TMenuItem;
142 MainMenu: TMainMenu;
143 FileMenu: TMenuItem;
144 OpenMI: TMenuItem;
145 FileSaveAsMI: TMenuItem;
146 PrintMI: TMenuItem;
147 FileInformationMI: TMenuItem;
148 MenuItem4: TMenuItem;
149 ExitMI: TMenuItem;
150 EditMenu: TMenuItem;
151 SelectAllMI: TMenuItem;
152 CopyMI: TMenuItem;
153 MenuItem5: TMenuItem;
154 FindMI: TMenuItem;
155 FindNextMI: TMenuItem;
156 NavigateMenu: TMenuItem;
157 NavigateBackMI: TMenuItem;
158 NavigateForwardMI: TMenuItem;
159 MenuItem6: TMenuItem;
160 NavigatePreviousMI: TMenuItem;
161 ToolsMenu: TMenuItem;
162 GlobalSearchMI: TMenuItem;
163 HelpMenu: TMenuItem;
164 HelpMI: TMenuItem;
165 HelpProductInformationMI: TMenuItem;
166 AddNoteMI: TMenuItem;
167
168 Procedure SaveAsIPFMIOnClick (Sender: TObject);
169 Procedure DebugFindBinaryMIOnClick (Sender: TObject);
170 Procedure TopicByNameMIOnClick (Sender: TObject);
171 Procedure CopyLinkLocationPMIOnClick (Sender: TObject);
172 Procedure HelpKeysMIOnClick (Sender: TObject);
173 Procedure MainFormOnCommand (Sender: TObject; Var Command: TCommand);
174 Procedure MainFormOnScan (Sender: TObject; Var KeyCode: TKeyCode);
175 Procedure ShowLeftPanelMIOnClick (Sender: TObject);
176 Procedure CoolBarOnFontChange (Sender: TObject);
177 Procedure NotebookOnFontChange (Sender: TObject);
178 Procedure TabSetOnFontChange (Sender: TObject);
179 Procedure IndexListBoxOnFontChange (Sender: TObject);
180 Procedure NotesListBoxOnFontChange (Sender: TObject);
181 Procedure DisplayPanelOnFontChange (Sender: TObject);
182 Procedure ContentsOutlineOnFontChange (Sender: TObject);
183 Procedure SearchResultsListBoxOnFontChange (Sender: TObject);
184 Procedure DisplayPanelOnDragOver (Sender: TObject; Source: TObject;
185 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
186 Procedure NotesListBoxOnDragOver (Sender: TObject; Source: TObject;
187 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
188 Procedure DisplayPanelOnDragDrop (Sender: TObject; Source: TObject;
189 X: LongInt; Y: LongInt);
190 Procedure NotesListBoxOnDragDrop (Sender: TObject; Source: TObject;
191 X: LongInt; Y: LongInt);
192 Procedure SearchResultsListBoxOnDragDrop (Sender: TObject; Source: TObject;
193 X: LongInt; Y: LongInt);
194 Procedure SearchResultsListBoxOnDragOver (Sender: TObject; Source: TObject;
195 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
196 Procedure IndexListBoxOnDragDrop (Sender: TObject; Source: TObject;
197 X: LongInt; Y: LongInt);
198 Procedure IndexListBoxOnDragOver (Sender: TObject; Source: TObject;
199 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
200 Procedure ContentsOutlineOnDragOver (Sender: TObject; Source: TObject;
201 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
202 Procedure ContentsOutlineOnDragDrop (Sender: TObject; Source: TObject;
203 X: LongInt; Y: LongInt);
204 Procedure MainFormOnDragOver (Sender: TObject; Source: TObject; X: LongInt;
205 Y: LongInt; State: TDragState; Var Accept: Boolean);
206 Procedure MainFormOnDragDrop (Sender: TObject; Source: TObject; X: LongInt;
207 Y: LongInt);
208 Procedure ContentsOutlineOnItemClick (Node: TNode);
209 Procedure DebugLoadLanguageMIOnClick (Sender: TObject);
210 Procedure DebugSaveLanguageFileMIOnClick (Sender: TObject);
211 Procedure SearchResultsListBoxOnClick (Sender: TObject);
212 Procedure VSplitBarOnDblClick (Sender: TObject);
213 Procedure DebugHelpManagerVersionMIOnClick (Sender: TObject);
214 Procedure DebugTopicByResourceIDMIOnClick (Sender: TObject);
215 Procedure ViewHighlightSearchWordsMIOnClick (Sender: TObject);
216 Procedure FileNewWindowMIOnClick (Sender: TObject);
217 Procedure OpenSpecialMIOnClick (Sender: TObject);
218 Procedure NotesListBoxOnScan (Sender: TObject; Var KeyCode: TKeyCode);
219 Procedure ViewPopupMenuOnPopup (Sender: TObject);
220 Procedure SearchPMIOnClick (Sender: TObject);
221 Procedure ViewSourceMIOnClick (Sender: TObject);
222 Procedure PrintMIOnClick (Sender: TObject);
223 Procedure DebugShowWordSeparatorsMIOnClick (Sender: TObject);
224 Procedure DebugStressTestMIOnClick (Sender: TObject);
225 Procedure TopicPropertiesPMIOnClick (Sender: TObject);
226 Procedure NavigateForwardMIOnClick (Sender: TObject);
227 Procedure IndexListBoxOnScan (Sender: TObject; Var KeyCode: TKeyCode);
228 Procedure SearchResultsListBoxOnScan (Sender: TObject;
229 Var KeyCode: TKeyCode);
230 Procedure ContentsOutlineOnScan (Sender: TObject; Var KeyCode: TKeyCode);
231 Procedure ToolsOptionsMIOnClick (Sender: TObject);
232 Procedure EditGlobalSearchMIOnClick (Sender: TObject);
233 Procedure DebugShowParamsMIOnClick (Sender: TObject);
234 Procedure ViewExpandAllMIOnClick (Sender: TObject);
235 Procedure EditBookmarksMIOnClick (Sender: TObject);
236 Procedure CopyPMIOnClick (Sender: TObject);
237 Procedure SelectAllPMIOnClick (Sender: TObject);
238 Procedure AddNoteButtonOnClick (Sender: TObject);
239 Procedure SearchTextEditOnChange (Sender: TObject);
240 Procedure IndexListBoxOnClick (Sender: TObject);
241 Procedure ViewCollapseAllMIOnClick (Sender: TObject);
242 Procedure NotesListBoxOnDblClick (Sender: TObject);
243 Procedure HelpMIOnClick (Sender: TObject);
244 Procedure NotebookOnPageChanged (Sender: TObject);
245 Procedure ViewRefreshMIOnClick (Sender: TObject);
246 Procedure ViewNotesMIOnClick (Sender: TObject);
247 Procedure ViewSearchMIOnClick (Sender: TObject);
248 Procedure ViewIndexMIOnClick (Sender: TObject);
249 Procedure ViewContentsMIOnClick (Sender: TObject);
250 Procedure MainFormOnCloseQuery (Sender: TObject; Var CanClose: Boolean);
251 Procedure GlobalSearchMIOnClick (Sender: TObject);
252 Procedure GotoNoteButtonOnClick (Sender: TObject);
253 Procedure EditNoteButtonOnClick (Sender: TObject);
254 Procedure NotesListBoxOnItemFocus (Sender: TObject; Index: LongInt);
255 Procedure DeleteNoteButtonOnClick (Sender: TObject);
256 Procedure AddBookmarkMIOnClick (Sender: TObject);
257 Procedure AddNoteMIOnClick (Sender: TObject);
258 Procedure FileCloseMIOnClick (Sender: TObject);
259 Procedure CoolBarOnSectionResize (HeaderControl: THeaderControl;
260 section: THeaderSection);
261 Procedure CoolBarOnSectionClick (HeaderControl: THeaderControl;
262 section: THeaderSection);
263 Procedure MainFormOnDestroy (Sender: TObject);
264 Procedure MainFormOnSetupShow (Sender: TObject);
265 Procedure MainFormOnCreate (Sender: TObject);
266 Procedure MainFormOnShow (Sender: TObject);
267 Procedure FindNextMIOnClick (Sender: TObject);
268 Procedure FindMIOnClick (Sender: TObject);
269 Procedure IndexSearchEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
270 Procedure IndexSearchEditOnChange (Sender: TObject);
271 Procedure FileInformationMIOnClick (Sender: TObject);
272 Procedure SearchTextEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
273 Procedure SearchButtonOnClick (Sender: TObject);
274 Procedure FileSaveAsMIOnClick (Sender: TObject);
275 Procedure OptionsMIOnClick (Sender: TObject);
276 Procedure TabSetOnChange (Sender: TObject; NewTab: LongInt;
277 Var AllowChange: Boolean);
278 Procedure NotebookOnSetupShow (Sender: TObject);
279 Procedure NavigateBackMIOnClick (Sender: TObject);
280 Procedure NavigatePreviousMIOnClick (Sender: TObject);
281 Procedure NavigateNextMIOnClick (Sender: TObject);
282 Procedure CopyMIOnClick (Sender: TObject);
283 Procedure SelectAllMIOnClick (Sender: TObject);
284 Procedure DebugShowCodesMIOnClick (Sender: TObject);
285 Procedure HelpProductInformationMIOnClick (Sender: TObject);
286 Procedure OnOverLink ( Sender: TRichTextView; LinkString: String);
287 Procedure OnNotOverLink ( Sender: TRichTextView; LinkString: String);
288 Procedure OnClickLink ( Sender: TRichTextView; LinkString: String);
289 Procedure BackButtonOnClick (Sender: TObject);
290 Procedure RTViewOnSetupShow (Sender: TObject);
291 Procedure OpenMIOnClick (Sender: TObject);
292 Procedure ExitMIOnClick (Sender: TObject);
293
294 Procedure MainFormOnResize (Sender: TObject);
295 Procedure VSplitBarOnChange (NewSplit: LongInt);
296 Protected
297 // Custom window messages ----------------------------------
298
299 // Handle our own WM_OPENED message
300 Procedure WMOpened( Var Msg: TMessage ); Message WM_OPENED;
301 Procedure WMFollowLink( Var Msg: TMessage ); Message WM_FOLLOWLINK;
302 Procedure WMFollowExternalLink( Var Msg: TMessage ); Message WM_FOLLOWEXTERNALLINK;
303
304 // Messages from new help manager OR other instances
305 Procedure NHMDisplayIndex( Var Msg: TMessage ); Message NHM_HELP_INDEX;
306 Procedure NHMDisplayContents( Var Msg: TMessage ); Message NHM_HELP_CONTENTS;
307 Procedure NHMTopicByResourceID( Var Msg: TMessage ); Message NHM_TOPIC_BY_RESOURCE_ID;
308 Procedure NHMTopicByPanelName( Var Msg: TMessage ); Message NHM_TOPIC_BY_PANEL_NAME;
309
310 Procedure NHMTest( Var Msg: TMessage ); Message NHM_TEST;
311
312 Procedure NHMSearch( Var Msg: TMessage ); Message NHM_SEARCH;
313 Procedure NHMGlobalSearch( Var Msg: TMessage ); Message NHM_GLOBAL_SEARCH;
314 Procedure NHMShowUsage( Var Msg: TMessage ); Message NHM_SHOW_USAGE;
315
316 Procedure NHMSetFiles( Var Msg: TMessage ); Message NHM_SET_FILES;
317 Procedure NHMSetTitle( Var Msg: TMessage ); Message NHM_SET_TITLE;
318
319 Protected
320 // GUI events set by code ----------------------------------
321
322 Procedure OnHint( Sender: TObject );
323 Procedure OnWindowClose( Window: THelpWindow );
324 Procedure OnWindowAboutToClose( Window: THelpWindow;
325 var CanClose: boolean );
326 Procedure OnNavigateToMenuItemClick( Sender: TObject );
327 Procedure OnDragOverWindow( Sender: TObject;
328 Source: TObject;
329 X: LongInt;
330 Y: LongInt;
331 State: TDragState;
332 Var Accept: Boolean );
333 Procedure OnDragDropToWindow( Sender: TObject;
334 Source: TObject;
335 X: LongInt;
336 Y: LongInt );
337 Procedure OnWindowFontChange( Sender: TObject );
338 Procedure OnWindowTab( Sender: TObject );
339 Procedure OnWindowBackTab( Sender: TObject );
340
341 Procedure OnException( Sender: TObject;
342 E: Exception );
343 Procedure OnHelp( context: THelpContext;
344 var Result: Boolean );
345
346
347 FShowLeftPanel: boolean;
348
349 Function GetShowLeftPanel: boolean;
350 Procedure SetShowLeftPanel( Value: boolean );
351 Property ShowLeftPanel: boolean read GetShowLeftPanel write SetShowLeftPanel;
352
353 Procedure ShowTab( TabIndex: longint );
354
355 procedure GetClassData(var ClassData: TClassData); override;
356 Public
357
358 // Open the file or list of files in FileNames
359 // Set the window title if given, otherwise get it from first file
360 Function OpenFiles( const FileNames: TStrings;
361 const WindowTitle: string;
362 const DisplayFirstTopic: boolean ): boolean;
363
364 // Open a single file
365 Function OpenFile( const FileName: string;
366 const WindowTitle: string;
367 const DisplayFirstTopic: boolean ): boolean;
368
369 Function OpenAdditionalFiles( const FileNames: TStrings;
370 const DisplayFirstTopic: boolean ): boolean;
371
372 Function OpenAdditionalFile( const FileName: string;
373 const DisplayFirstTopic: boolean ): boolean;
374
375 // open from original helpmgr style file1+file2+file3. ..
376 Function OpenFilesFromTextList( const TextList: string;
377 const DisplayFirstTopic: boolean ): boolean;
378
379 Procedure CloseFile;
380 Function OKToCloseFile: boolean;
381
382 Procedure AddCurrentToMRUFiles;
383
384 Function LoadFiles( const FileNames: TStrings;
385 HelpFiles: TList ): boolean;
386 Procedure DisplayFiles( NewFiles: TList;
387 Var FirstContentsNode: TNode );
388
389 Procedure OpenDroppedFile( Source: TObject );
390
391 Function OpenWindowsHelp( const Filename: string ): boolean;
392
393 function DisplayTopicByResourceID( ID: uint16 ): boolean;
394 function DisplayTopicByName( const TopicName: string ): boolean;
395 function DisplayTopicByGlobalName( const TopicName: string ): boolean;
396
397 Procedure DisplayIndex;
398 Procedure DisplayContents;
399 Procedure DisplaySearch;
400
401 Protected
402 // Startup functions ----------------------------------
403
404 Function pSharedStruct: TPNewHelpMgrSharedStruct;
405 Procedure PositionWindow;
406 Procedure RestoreWindow;
407
408 Procedure CheckEnvironmentVars;
409 Procedure ShowUsage;
410
411 // Loading functions ----------------------------------
412
413 // Most recently used files list
414 Procedure CreateMRUMenuItems;
415 Procedure OnMRUMenuItemClick( Sender: TObject );
416
417 Procedure OnHelpFileLoadProgress( n, outof: integer;
418 message: string );
419
420 // Returns nil if file is not open
421 Function FindOpenHelpFile( FileName: string ): THelpFile;
422
423 // Navigation -------------------------------------------------
424
425 Procedure SaveNavigatePoint;
426 Procedure SaveWindows( SourceList: TList;
427 DestList: TList;
428 Parent: TSavedHelpWindow );
429
430 Procedure UpdateCurrentNavigatePoint;
431 Procedure ClearPageHistory;
432
433 Procedure NavigateToPoint( NavPoint: TNavigatePoint );
434 Procedure NavigateToHistoryIndex( Index: longint );
435
436 Procedure DisplayWindows( WindowList: TList;
437 Parent: THelpWindow );
438 Procedure ShowWindows;
439 Procedure ShowWindowList( WindowList: TList );
440 Procedure CloseWindows;
441
442 Procedure FocusFirstHelpWindow;
443
444 Procedure NavigateBack;
445 Procedure NavigateForward;
446 Procedure NavigatePreviousInContents;
447 Procedure NavigateNextInContents;
448
449 Procedure CreateNavigateToMenuItems;
450
451 // GUI status updates ---------------------------------
452
453 Procedure EnableControls;
454 Procedure EnableSearchButton;
455 Procedure SetStatus( Text: String );
456 Procedure SetProgress( n, outof: integer;
457 message: string );
458 Procedure ResetProgress;
459 Procedure RefreshWindows( WindowList: TList );
460
461 // language stuff
462 // called by callback
463 Procedure OnLanguageEvent( Language: TLanguageFile;
464 const Apply: boolean );
465
466 function ShowCodes: boolean;
467 function ShowWordIndices: boolean;
468
469 // Loading views --------------------------------------
470
471 // Used in loading contents
472 Procedure AddChildNodes( HelpFile: THelpFile;
473 ParentNode: TNode;
474 Level: longint;
475 Var TopicIndex: longint );
476 Procedure LoadContents( Files: TList;
477 Var FirstNode: TNode );
478 Procedure LoadIndex;
479
480 // Note manipulations --------------------------------
481
482 procedure AddNote;
483 Procedure EditNote( NoteIndex: longint );
484 procedure DeleteNote( NoteIndex: longint );
485 Procedure SaveNotes;
486 Procedure SaveNotesForFile( HelpFile: THelpFile );
487 Procedure LoadNotes( HelpFile: THelpFile );
488 Procedure GotoCurrentNote;
489
490 // make sure that note insert positions are not in
491 // the middle of tags due to help file or newview updates.
492 Procedure CorrectNotesPositions( Topic: TTopic;
493 Text: pchar );
494
495 Procedure InsertNotesIntoTopicText( Topic: TTopic;
496 Text: TAString );
497 function FindOriginalNoteCharIndex( NoteCharIndex: longword;
498 Topic: TTopic ): longword;
499 function FindActualNoteCharIndex( NoteCharIndex: longword;
500 MaxNoteIndex: longword;
501 Topic: TTopic ): longword;
502 procedure RefreshNoteInsertInfo( NoteIndex: longword );
503 procedure ClearNotes;
504
505 Procedure EnableNotesControls;
506 Procedure UpdateNotesDisplay;
507
508 Procedure RefreshFontSubstitutions;
509
510 // GUI actions ------------------------------------------
511
512 procedure FileOpen;
513
514 Procedure PrintTopics;
515 function DoPrinting( Parameters: TObject ): TObject;
516 Procedure StopPrinting;
517
518 Procedure DoFind( FindOrigin: TFindOrigin );
519
520 // Bookmarks ------------------------------------------
521
522 Procedure NavigateToBookmark( Bookmark: TBookmark );
523 Procedure BuildBookmarksMenu;
524 Procedure UpdateBookmarksForm;
525 Procedure BookmarksMenuItemClick( Sender: TObject );
526 procedure AddBookmark;
527 procedure ClearBookmarks;
528 procedure SaveBookmarks;
529 procedure SaveBookmarksForFile( HelpFile: THelpFile );
530 procedure LoadBookmarks( HelpFile: THelpFile );
531 procedure OnBookmarksChanged( Sender: TObject );
532
533 // Global search -------------------------------------
534
535 procedure DoGlobalSearch( const SearchText: string );
536 // Called when viewing topics from global search
537 Procedure OnViewGlobalSearchTopic( FileName: string;
538 TopicIndex: longint );
539
540 // Options and appearance -----------------------------
541
542 procedure DoOptions;
543
544 procedure ApplySettings;
545
546 // changes normal or fixed font depending on shift state
547 Procedure SetTopicFont( NewFont: TFont );
548
549 Procedure SetApplicationFont( NewFont: TFont );
550
551 // Retrieve control colours (in case drag'n'drop used to change)
552 Procedure GetColors;
553 // Set the layout of the main form
554 Procedure SetLayout;
555 // Lay out the specified list of help windows
556 Procedure LayoutWindowList( WindowList: TList );
557 // Setup the rich text views in the specified windows (e.g for changing global settings)
558 Procedure SetupViews( WindowList: TList );
559
560 // Topic display -------------------------------------
561
562 // Major display topic function.
563 procedure DisplayTopic( Topic: TTopic );
564
565 Procedure DisplaySelectedIndexTopic;
566 Procedure DisplaySelectedSearchResultTopic;
567 Procedure DisplaySelectedContentsTopic;
568
569 Procedure DisplayTopicInWindow( Window: THelpWindow;
570 FollowAutoLinks: boolean;
571 KeepPosition: boolean );
572
573 function OpenWindow( Topic: TTopic;
574 Group: longint;
575 Parent: THelpWindow;
576 Rect: THelpWindowRect;
577 FollowAutoLinks: boolean ): THelpWindow;
578
579 Procedure RemoveHelpWindowFromParent( Window: THelpWindow );
580
581 Procedure FollowLink( Link: THelpLink;
582 SourceWindow: THelpWindow );
583
584 Function FindTopicByResourceID( ID: uint16 ): TTopic;
585 Function FindTopicByName( const Name: string ): TTopic;
586 Function FindTopicByGlobalName( const Name: string ): TTopic;
587
588 Function FindTopicForLink( Link: THelpLink ): TTopic;
589
590 Function FindWindowFromView( View: TRichTextView; WindowList: TList ): THelpWindow;
591 Function FindWindowFromGroup( Group: longint; WindowList: TList ): THelpWindow;
592 Function FindWindowFromTopic( Topic: TTopic; WindowList: TList ): THelpWindow;
593 Function GetActiveWindow: THelpWindow;
594
595 Procedure DoSearch;
596 Procedure SearchFor( const SearchText: string );
597 Procedure StartupTopicSearch( const SearchText: string );
598
599 // clear search match sequences
600 Procedure ClearAllWordSequences;
601
602 Procedure SetMainCaption;
603
604 // cancel help manager mode
605 Procedure ClearHelpManager;
606 Procedure PostHelpManagerMessage( MessageType: ULONG;
607 Param1: long;
608 Param2: long );
609
610 HelpManagerWindows: TList; // of HWND
611
612 function OwnHelpMode: boolean;
613 CurrentOpenFiles: TList; // current open help files.
614 MRUMenuItems: TList; // most recently used file list
615 NavigateToMenuItems: TList;
616 MainTitle: string;
617
618 // Current topic has the vague meaning that it was the last
619 // topic selected by the user... (?)
620 CurrentTopic: TTopic;
621
622 AllFilesWordSequences: TList; // of lists; one per open file; of possible word sequences
623
624 // use during decode...
625 TopicText: TAString;
626
627 Windows: TList; // top level help windows
628
629 PageHistory: TStringList; // history
630 CurrentHistoryIndex: longint; // where we are in history
631
632 Navigating: boolean; // true while going to a particular history point
633
634 DisplayedIndex: TStringList; // duplicate of index listbox,
635 // for fast case insensitive searching
636 InIndexSearch: boolean; // true while searching index
637 IndexLoaded: boolean;
638
639 ContentsLoaded: boolean;
640
641 StartingUp: boolean; // true while starting
642 SettingFont: boolean;
643 DisplayingTopicWindow: boolean;
644
645 FindText: string; // last text found (Ctrl-F)
646
647 Notes: TList; // Notes in current files.
648
649 Bookmarks: TList;
650 BookmarksMenuItems: TList;
651
652 // while loading... so owe can display progress
653 LoadingFilenameList: TStringList;
654 LoadingFileIndex: integer;
655
656 PrintThread: TGenericThreadManager;
657 procedure OnPrintProgress( n, outof: integer;
658 Message: string );
659 procedure OnPrintComplete( Dummy: TObject );
660 protected
661 // language stuff
662 FileOpenTitle: string;
663 LoadingFileMsg: string;
664 HelpFileError: string;
665 LoadingStatusDisplaying: string;
666 LoadingStatusNotesAndBookmarks: string;
667 LoadingStatusContents: string;
668 LoadingStatusIndex: string;
669 LoadingStatusDone: string;
670
671 AllFilesDesc: string;
672 HelpFilesDesc: string;
673 LanguageFilesDesc: string;
674
675 SaveLanguageTitle: string;
676 OpenLanguageTitle: string;
677 SaveLanguageError: string;
678
679 HelpManagerVersionTitle: string;
680
681 FindResourceIDTitle: string;
682 FindResourceIDPrompt: string;
683 InvalidResourceIDError: string;
684 ResourceIDNotFoundError: string;
685
686 OpenSpecialTitle: string;
687 OpenSpecialPrompt: string;
688
689 PrintTopicTitle: string;
690 NoPrinterError: string;
691 SelectWindowToPrintError: string;
692 PrintingError: string;
693 StoppingPrintMsg: string;
694 PrintStoppedMsg: string;
695 CheckStopPrintTitle: string;
696 CheckStopPrintMsg: string;
697
698 TopicInfoTitle: string;
699 TopicInfoTopicTitle: string;
700 TopicInfoIndex: string;
701 TopicInfoFile: string;
702 TopicInfoResourceIDs: string;
703 TopicInfoNoResourceIDs: string;
704
705 ParameterCountLabel: string;
706
707 NewViewHelpTitle: string;
708 AlreadyNewviewHelp: string;
709 NewViewHelpNotFound: string;
710
711 InvalidLinkErrorTitle: string;
712 InvalidLinkError: string;
713 InvalidResourceIDLinkErrorA: string;
714 InvalidResourceIDLinkErrorB: string;
715
716 OpenedTopicMsg: string;
717
718 AddNoteTitle: string;
719 AddNoteCursorError: string;
720 NoteWithinNoteError: string;
721 LoadNotesTitle: string;
722 LoadNotesError: string;
723 SaveNotesTitle: string;
724 SaveNotesError: string;
725
726 UntitledBookmarkName: string;
727 LoadBookmarksTitle: string;
728 LoadBookmarksError: string;
729 SaveBookmarksTitle: string;
730 SaveBookmarksError: string;
731
732 ApplicationErrorTitle: string;
733 ApplicationErrorA: string;
734 ApplicationErrorB: string;
735 ApplicationErrorC: string;
736
737 EnvironmentVarErrorTitle: string;
738 EnvironmentVarError: string;
739 EnvironmentVarUndefined: string;
740
741 FindTitle: string;
742 FindSelectWindowError: string;
743 FindPrompt: string;
744 TextNotFoundMsg: string;
745
746 FilesInfoTitle: string;
747 FilesInfoOverallTitle: string;
748 FilesInfoFilename: string;
749 FilesInfoFileTitle: string;
750 FilesInfoTopicCount: string;
751 FilesInfoIndexCount: string;
752 FilesInfoDictionaryCount: string;
753 FilesInfoFileSize: string;
754 FilesInfoTotalTopicCount: string;
755 FilesInfoTotalIndexCount: string;
756 FilesInfoTotalFileSize: string;
757
758 SearchTitle: string;
759 SearchSyntaxError: string;
760 SearchingMsg: string;
761 NoSearchMatchesMsg: string;
762 SearchFoundMsgA: string;
763 SearchFoundMsgB: string;
764
765 FileSaveTitle: string;
766 FileSaveSelectWindowError: string;
767 DefaultSaveTopicFilename: string;
768 ReplaceFilePromptA: string;
769 ReplaceFilePromptB: string;
770 UnableToSaveError: string;
771
772 UsageTitle: string;
773 UsageText1: string;
774 UsageText2: string;
775 UsageText3: string;
776 UsageText4: string;
777 UsageText5: string;
778 UsageText6: string;
779 UsageText7: string;
780 UsageText8: string;
781
782 GoBackHint: string;
783
784 SelectAllTitle: string;
785 SelectAllWindowError: string;
786
787 EditNoteMsg: string;
788 ExternalLinkMsg: string;
789 LinkMsg: string;
790 UnknownLinkMsg: string;
791 FootnoteMsg: string;
792
793 ExternalLinkTitle: string;
794 ExternalLinkError: string;
795
796 MRUMultipleFilesHint: string;
797
798 HelpProgramTitle: string;
799 WindowsHelpTitle: string;
800 WindowsHelpPrompt: string;
801
802 ErrorTitle: string;
803
804 FindTopicNameTitle: string;
805 FindTopicNamePrompt: string;
806 TopicNameNotFoundError: string;
807
808 SplitBarDblClickToShow: string;
809 SplitBarDblClickToHide: string;
810
811 End;
812
813Var
814 MainForm: TMainForm;
815 CmdLineParameters : TCmdLineParameters;
816
817Implementation
818
819uses
820 BseDos,
821 BseErr,
822 PMWin,
823 PmShl,
824 Dos,
825 Printers,
826
827 // Library
828 ACLFileIOUtility,
829 ACLUtility,
830 ACLDialogs,
831 RunProgramUnit,
832 StringUtilsUnit,
833 CharUtilsUnit,
834 DebugUnit,
835
836 FileUtilsUnit,
837
838 // Components
839 RichTextPrintUnit,
840 RichTextStyleUnit,
841 RichTextDocumentUnit,
842 ControlsUtility,
843
844 // local: forms
845 InformationFormUnit,
846 OptionsForm,
847 ProductInformationFormUnit,
848 NoteForm,
849 GlobalSearchForm,
850 FileDialogForm,
851 BookmarksFormUnit,
852 PrintDialogUnit,
853
854 // local: others
855 NewViewConstantsUnit,
856 SettingsUnit,
857 VersionUnit,
858 SearchUnit,
859 StartupUnit,
860 GlobalFilelistUnit,
861 WebBrowserUnit,
862 HelpBitmap;
863
864{$R Images}
865
866const
867 // Coolbar button indexes
868 ciOpen = 0;
869 ciPrint = 1;
870 ciNavigator = 2;
871 ciBack = 3;
872 ciForward = 4;
873 ciAddNote = 5;
874 ciAddBookmark = 6;
875 ciPrevious = 7;
876 ciNext = 8;
877 ciGlobalSearch = 9;
878
879 // Page indexes.
880 piContents = 0;
881 piIndex = 1;
882 piSearch = 2;
883 piNotes = 3;
884
885 CrashLogFileName = 'NewView.log';
886
887 _MAX_PATH = 260;
888
889var
890 hNewViewDLL: HMODULE;
891
892 StartMem: longword;
893 LastMem: longword;
894
895 g_ExternalLinkFilename: string;
896 g_ExternalLinkTopic: string;
897 g_ExternalLinkSourceFilename: string;
898 g_ExternalLinkKeepCurrent: boolean; // whether to keep current files open
899
900//
901// ----------------------------------------------------------------------------------------
902// TMainForm implementation
903// ----------------------------------------------------------------------------------------
904//
905
906Procedure TMainForm.SaveAsIPFMIOnClick (Sender: TObject);
907var
908 FileName: string;
909 F: TextFile;
910 H: THelpFile;
911 i: longint;
912 T: TTopic;
913 ResourceIDs: TList;
914 ImageOffsets: TList;
915 ImageOffset: longint;
916 Image: THelpBitmap;
917Begin
918 H := CurrentOpenFiles[ 0 ];
919
920 FileName := ChangeFileExt( ExtractFileName( H.Filename ), '.ipf' );
921 if not DoSaveFileDialog( FileSaveTitle,
922 'IPF' + '|*.ipf',
923 Filename,
924 Settings.LastSaveDirectory,
925 Filename ) then
926 exit;
927 if FileExists( Filename ) then
928 if not DoConfirmDlg( FileSaveTitle,
929 ReplaceFilePromptA
930 + Filename
931 + ReplaceFilePromptB ) then
932 exit;
933
934 ImageOffsets := TList.Create;
935
936 AssignFile( F, FileName );
937 Rewrite( F );
938 WriteLn( F, ':userdoc.' );
939
940 // We can't tell if some levels of the contents were
941 // merged into the text of topics. So we just assume all are visible
942 WriteLn( F, ':docprof toc=123456.' );
943
944 ResourceIDs := TList.Create;
945
946 WriteLn( F, ':title.' + H.Title );
947
948 for i := 0 to H.TopicCount - 1 do
949 begin
950 T := H.Topics[ i ];
951
952 SetProgress( i div 2, H.TopicCount , 'Saving text...' );
953
954 WriteLn( F, '' );
955
956
957 if T.ContentsLevel = 0 then
958 begin
959 // perhaps it means footnote?
960 // Level := 1;
961 Write( F, ':fn id=fn' + IntToStr( i ) + '.' ); // use index as id
962
963 T.SaveToIPF( F, ImageOffsets );
964
965 WriteLn( F, '' );
966 WriteLn( F, ':efn.' );
967 end
968 else
969 begin
970 Write( F, ':h' + IntToStr( T.ContentsLevel ) );
971 Write( F, ' id=' + IntToStr( i ) ); // use index as id
972
973 H.FindResourceIDsForTopic( T, ResourceIDs );
974 if ResourceIDs.Count > 0 then
975 begin
976 Write( F, ' res=' + IntToStr( longint( ResourceIDs[ 0 ] ) ) );
977 end;
978
979 if not T.ShowInContents then
980 Write( F, ' hide' );
981
982 if T.ContentsGroupIndex > 0 then
983 Write( F, ' group=' + IntToStr( T.ContentsGroupIndex ) );
984
985 Write( F, '.' ); // end of header
986 WriteLn( F, T.Title );
987
988 T.SaveToIPF( F, ImageOffsets );
989 end;
990
991
992
993 end;
994
995 ResourceIDs.Destroy;
996
997 WriteLn( F, ':euserdoc.' );
998 System.Close( F );
999
1000 // Now write images
1001
1002 for i := 0 to ImageOffsets.Count - 1 do
1003 begin
1004 ImageOffset := longint( ImageOffsets[ i ] );
1005
1006 SetProgress( i div 2 + ImageOffsets.Count div 2,
1007 ImageOffsets.Count ,
1008 'Saving images...' );
1009
1010 Image := H.GetImage( ImageOffset );
1011
1012 if Image <> nil then
1013 begin
1014 Image.SaveToFile( ExtractFilePath( Filename )
1015 + 'img'
1016 + IntToStr( i )
1017 + '.bmp' );
1018 Image.Destroy;
1019 end;
1020
1021 end;
1022
1023 ResetProgress;
1024 SetStatus( 'Save complete' );
1025 ImageOffsets.Destroy;
1026End;
1027
1028Procedure TMainForm.DebugFindBinaryMIOnClick (Sender: TObject);
1029Var
1030 DataStr: string;
1031 data: array[ 0.. 255 ] of byte;
1032 DataLen: longint;
1033 FileIndex: longint;
1034 HelpFile: THelpFile;
1035 i: longint;
1036 Topic: TTopic;
1037
1038 tmpParts : TStringList;
1039Begin
1040 if not DoInputQuery( 'Binary Find',
1041 'Enter data to find (decimal, separate with spaces)',
1042 DataStr ) then
1043 exit;
1044
1045 tmpParts := TStringList.Create;
1046 StrExtractStringsIgnoreEmpty(tmpParts, DataStr, [' '], #0);
1047 for i := 0 to tmpParts.count-1 do
1048 begin
1049 Data[i] := StrToInt(tmpParts[i]);
1050 end;
1051 DataLen := tmpParts.count;
1052 tmpParts.Destroy;
1053
1054 ShowTab( piSearch );
1055 SearchResultsListBox.Clear;
1056
1057 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
1058 begin
1059 HelpFile := CurrentOpenFiles[ FileIndex ];
1060 for i := 0 to HelpFile.TopicCount -1 do
1061 begin
1062 Topic := HelpFile.Topics[ i ];
1063 if Topic.SearchForData( Addr(Data), DataLen) then
1064 begin
1065 SearchResultsListBox.Items.AddObject( Topic.Title, Topic );
1066 end;
1067
1068 end;
1069
1070 end;
1071
1072End;
1073
1074Procedure TMainForm.TopicByNameMIOnClick (Sender: TObject);
1075var
1076 TopicNameString: string;
1077Begin
1078 if not DoInputQuery( FindTopicNameTitle,
1079 FindTopicNamePrompt,
1080 TopicNameString ) then
1081 exit;
1082
1083 if not DisplayTopicByName( TopicNameString ) then
1084 if not DisplayTopicByGlobalName( TopicNameString ) then
1085 DoErrorDlg( FindTopicNameTitle,
1086 TopicNameNotFoundError );
1087End;
1088
1089Function TMainForm.pSharedStruct: TPNewHelpMgrSharedStruct;
1090begin
1091 Result := TPNewHelpMgrSharedStruct( SharedMemory.Data );
1092end;
1093
1094Procedure TMainForm.CopyLinkLocationPMIOnClick (Sender: TObject);
1095Begin
1096
1097End;
1098
1099Procedure TMainForm.HelpKeysMIOnClick (Sender: TObject);
1100Begin
1101// Application.Help( 10 );
1102End;
1103
1104Procedure TMainForm.MainFormOnCommand (Sender: TObject; Var Command: TCommand);
1105Begin
1106 case Command of
1107 kbF11:
1108 NavigatePreviousInContents;
1109
1110 kbF12:
1111 NavigateNextInContents;
1112
1113 kbF7,
1114 kbCtrlCLeft:
1115 NavigateBack;
1116
1117 kbF8:
1118 NavigateForward;
1119 end;
1120End;
1121
1122Procedure TMainForm.MainFormOnScan (Sender: TObject; Var KeyCode: TKeyCode);
1123Begin
1124End;
1125
1126Procedure TMainForm.ShowLeftPanelMIOnClick (Sender: TObject);
1127Begin
1128 ShowLeftPanel := not ShowLeftPanel;
1129End;
1130
1131Procedure TMainForm.CoolBarOnFontChange (Sender: TObject);
1132Begin
1133 SetApplicationFont( Coolbar.Font );
1134End;
1135
1136Procedure TMainForm.NotebookOnFontChange (Sender: TObject);
1137Begin
1138 SetApplicationFont( Notebook.Font );
1139End;
1140
1141Procedure TMainForm.TabSetOnFontChange (Sender: TObject);
1142Begin
1143 SetApplicationFont( TabSet.Font );
1144End;
1145
1146Procedure TMainForm.IndexListBoxOnFontChange (Sender: TObject);
1147Begin
1148 SetApplicationFont( IndexListBox.Font );
1149End;
1150
1151Procedure TMainForm.NotesListBoxOnFontChange (Sender: TObject);
1152Begin
1153 SetApplicationFont( NotesListBox.Font );
1154End;
1155
1156Procedure TMainForm.DisplayPanelOnFontChange (Sender: TObject);
1157Begin
1158 SetTopicFont( DisplayPanel.Font );
1159End;
1160
1161Procedure TMainForm.SetTopicFont( NewFont: TFont );
1162var
1163 ShiftPressed: boolean;
1164Begin
1165 if SettingFont or StartingUp then
1166 exit;
1167 LogEvent(LogSettings, 'SetTopicFont');
1168
1169 SettingFont := true;
1170
1171 ShiftPressed := ( WinGetKeyState( HWND_DESKTOP,
1172 VK_SHIFT ) and $8000 ) > 0;
1173 if ShiftPressed then
1174 Settings.FixedFont := NewFont
1175 else
1176 Settings.NormalFont := NewFont;
1177
1178 LogEvent(LogSettings, 'Saving settings');
1179
1180 SaveSettings;
1181 LogEvent(LogSettings, 'Applying settings');
1182 ApplySettings;
1183
1184 SettingFont := false;
1185 LogEvent(LogSettings, 'SetTopicFont done');
1186End;
1187
1188Procedure TMainForm.ContentsOutlineOnFontChange (Sender: TObject);
1189Begin
1190 SetApplicationFont( ContentsOutline.Font );
1191End;
1192
1193Procedure TMainForm.SetApplicationFont( NewFont: TFont );
1194Begin
1195 if ( not SettingFont ) and ( not StartingUp ) then
1196 begin
1197 Settings.Fonts[ ApplicationFontIndex ] := NewFont;
1198 SaveSettings;
1199 ApplySettings;
1200 SetLayout;
1201 end;
1202End;
1203
1204Procedure TMainForm.SearchResultsListBoxOnFontChange (Sender: TObject);
1205Begin
1206 SetApplicationFont( SearchResultsListBox.Font );
1207End;
1208
1209Procedure TMainForm.OnDragOverWindow(Sender: TObject; Source: TObject;
1210 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1211Begin
1212 if Source is TExternalDragDropObject then
1213 Accept := true;
1214
1215End;
1216
1217Procedure TMainForm.OnDragDropToWindow(Sender: TObject; Source: TObject;
1218 X: LongInt; Y: LongInt);
1219Begin
1220 OpenDroppedFile( Source );
1221End;
1222
1223Procedure TMainForm.OnWindowTab( Sender: TObject );
1224Begin
1225 OnWindowBackTab( Sender ); // for now
1226End;
1227
1228Procedure TMainForm.OnWindowBackTab( Sender: TObject );
1229Begin
1230 case NoteBook.PageIndex of
1231 piContents:
1232 ContentsOutline.Focus;
1233 piIndex:
1234 IndexListBox.Focus;
1235 piSearch:
1236 SearchResultsListBox.Focus;
1237 piNotes:
1238 NotesListBox.Focus;
1239 end;
1240End;
1241
1242Procedure TMainForm.OnWindowFontChange( Sender: TObject );
1243begin
1244 if not DisplayingTopicWindow then
1245 SetTopicFont( TControl(Sender).Font );
1246end;
1247
1248Procedure TMainForm.DisplayPanelOnDragOver (Sender: TObject; Source: TObject;
1249 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1250Begin
1251 if Source is TExternalDragDropObject then
1252 Accept := true;
1253End;
1254
1255Procedure TMainForm.NotesListBoxOnDragOver (Sender: TObject; Source: TObject;
1256 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1257Begin
1258 if Source is TExternalDragDropObject then
1259 Accept := true;
1260End;
1261
1262Procedure TMainForm.DisplayPanelOnDragDrop (Sender: TObject; Source: TObject;
1263 X: LongInt; Y: LongInt);
1264Begin
1265 OpenDroppedFile( Source );
1266End;
1267
1268Procedure TMainForm.NotesListBoxOnDragDrop (Sender: TObject; Source: TObject;
1269 X: LongInt; Y: LongInt);
1270Begin
1271 OpenDroppedFile( Source );
1272End;
1273
1274Procedure TMainForm.SearchResultsListBoxOnDragDrop (Sender: TObject;
1275 Source: TObject; X: LongInt; Y: LongInt);
1276Begin
1277 OpenDroppedFile( Source );
1278End;
1279
1280Procedure TMainForm.SearchResultsListBoxOnDragOver (Sender: TObject;
1281 Source: TObject; X: LongInt; Y: LongInt; State: TDragState;
1282 Var Accept: Boolean);
1283Begin
1284 if Source is TExternalDragDropObject then
1285 Accept := true;
1286End;
1287
1288Procedure TMainForm.IndexListBoxOnDragDrop (Sender: TObject; Source: TObject;
1289 X: LongInt; Y: LongInt);
1290Begin
1291 OpenDroppedFile( Source );
1292End;
1293
1294Procedure TMainForm.IndexListBoxOnDragOver (Sender: TObject; Source: TObject;
1295 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1296Begin
1297 if Source is TExternalDragDropObject then
1298 Accept := true;
1299End;
1300
1301Procedure TMainForm.ContentsOutlineOnDragOver (Sender: TObject;
1302 Source: TObject; X: LongInt; Y: LongInt; State: TDragState;
1303 Var Accept: Boolean);
1304Begin
1305 if Source is TExternalDragDropObject then
1306 Accept := true;
1307End;
1308
1309Procedure TMainForm.ContentsOutlineOnDragDrop (Sender: TObject;
1310 Source: TObject; X: LongInt; Y: LongInt);
1311Begin
1312 OpenDroppedFile( Source );
1313End;
1314
1315Procedure TMainForm.OpenDroppedFile( Source: TObject );
1316var
1317 DropObject: TExternalDragDropObject;
1318Begin
1319 if not ( Source is TExternalDragDropObject ) then
1320 // probably not needed, but crashes during drag drop completely
1321 // screw PM, so best to be sure!
1322 exit;
1323
1324 DropObject := Source as TExternalDragDropObject;
1325
1326 g_ExternalLinkFileName := AddDirectorySeparator( DropObject.ContainerName )
1327 + DropObject.SourceFilename;
1328 g_ExternalLinkTopic := '';
1329 g_ExternalLinkSourceFilename := ''; // don't care
1330
1331 g_ExternalLinkKeepCurrent := ( WinGetKeyState( HWND_DESKTOP,
1332 VK_SHIFT ) and $8000 ) > 0;
1333 PostMsg( Self.Handle,
1334 WM_FOLLOWEXTERNALLINK,
1335 0,
1336 0 );
1337
1338End;
1339
1340Procedure TMainForm.MainFormOnDragOver (Sender: TObject; Source: TObject;
1341 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1342Begin
1343 Accept := true;
1344End;
1345
1346Procedure TMainForm.MainFormOnDragDrop (Sender: TObject; Source: TObject;
1347 X: LongInt; Y: LongInt);
1348Begin
1349End;
1350
1351Procedure TMainForm.ContentsOutlineOnItemClick (Node: TNode);
1352Begin
1353 DisplaySelectedContentsTopic;
1354End;
1355
1356Procedure TMainForm.SetMainCaption;
1357begin
1358 if ( Trim( MainTitle ) = '' )
1359 or ( StrEqualIgnoringCase( Trim( MainTitle ), HelpProgramTitle ) ) then
1360 // supress "Help - " or "Help - Help"
1361 Caption := HelpProgramTitle
1362 else
1363 Caption := HelpProgramTitle + ' - ' + MainTitle
1364end;
1365
1366Procedure TMainForm.OnLanguageEvent( Language: TLanguageFile;
1367 const Apply: boolean );
1368Begin
1369 // get rid of mru menu items
1370 DestroyListObjects( MRUMenuItems );
1371 MRUMenuItems.Clear;
1372
1373 Language.LoadComponentLanguage( self, Apply );
1374
1375 if Apply then
1376 begin
1377 // copy menu hints to toolbar hints
1378 Coolbar.Sections[ ciOpen ].Hint := OpenMI.Hint;
1379 Coolbar.Sections[ ciPrint ].Hint := PrintMI.Hint;
1380 Coolbar.Sections[ ciNavigator ].Hint := ShowLeftPanelMI.Hint;
1381 Coolbar.Sections[ ciBack ].Hint := NavigateBackMI.Hint;
1382 Coolbar.Sections[ ciForward ].Hint := NavigateForwardMI.Hint;
1383 Coolbar.Sections[ ciAddNote ].Hint := AddNoteMI.Hint;
1384 Coolbar.Sections[ ciAddBookmark ].Hint := AddBookmarkMI.Hint;
1385 Coolbar.Sections[ ciPrevious ].Hint := NavigatePreviousMI.Hint;
1386 Coolbar.Sections[ ciNext ].Hint := NavigateNextMI.Hint;
1387 Coolbar.Sections[ ciGlobalSearch ].Hint := GlobalSearchMI.Hint;
1388 end;
1389
1390 // Load strings referred to by code...
1391 // ----------------------------------------------------------
1392
1393 Language.LL( Apply, FileOpenTitle, 'FileOpenTitle', 'Open Help Files' );
1394 Language.LL( Apply, LoadingFileMsg, 'LoadingFileMsg', 'Loading file ' );
1395 Language.LL( Apply, HelpFileError, 'HelpFileError', 'Could not open ' );
1396 Language.LL( Apply, LoadingStatusDisplaying, 'LoadingStatusDisplaying', 'Displaying...' );
1397 Language.LL( Apply, LoadingStatusNotesAndBookmarks, 'LoadingStatusNotesAndBookmarks', 'Loading notes/bookmarks...' );
1398 Language.LL( Apply, LoadingStatusContents, 'LoadingStatusContents', 'Display contents... ' );
1399 Language.LL( Apply, LoadingStatusIndex, 'LoadingStatusIndex', 'Display index... ' );
1400 Language.LL( Apply, LoadingStatusDone, 'LoadingStatusDone', 'Done' );
1401
1402 Language.LL( Apply, HelpFilesDesc, 'HelpFilesDesc', 'Help Files (*.inf,*.hlp)' );
1403 Language.LL( Apply, AllFilesDesc, 'AllFilesDesc', 'All Files (*)' );
1404 Language.LL( Apply, LanguageFilesDesc, 'LanguageFilesDesc', 'NewView Language Files (*.lng)' );
1405
1406 Language.LL( Apply, SaveLanguageTitle, 'SaveLanguageTitle', 'Save/Update Language File' );
1407 Language.LL( Apply, OpenLanguageTitle, 'OpenLanguageTitle', 'Open Language File' );
1408 Language.LL( Apply, SaveLanguageError, 'SaveLanguageError', 'Error saving language file: ' );
1409
1410 Language.LL( Apply, HelpManagerVersionTitle, 'HelpManagerVersionTitle', 'Help Manager Version' );
1411
1412 Language.LL( Apply, FindResourceIDTitle, 'FindResourceIDTitle', 'Find Resource ID' );
1413 Language.LL( Apply, FindResourceIDPrompt, 'FindResourceIDPrompt', 'Enter the resource ID to find' );
1414 Language.LL( Apply, InvalidResourceIDError, 'InvalidResourceIDError', 'Invalid resource ID entered' );
1415 Language.LL( Apply, ResourceIDNotFoundError, 'ResourceIDNotFoundError', 'Resource ID not found' );
1416
1417 Language.LL( Apply, OpenSpecialTitle, 'OpenSpecialTitle', 'Open Special' );
1418 Language.LL( Apply, OpenSpecialPrompt, 'OpenSpecialPrompt', 'Enter help file name/environment variable name' );
1419
1420 Language.LL( Apply, PrintTopicTitle, 'PrintTopicTitle', 'Print Topic' );
1421 Language.LL( Apply, NoPrinterError, 'NoPrinterError', 'You don''t have a printer configured.' );
1422 Language.LL( Apply, SelectWindowToPrintError, 'SelectWindowToPrintError', 'You must select the window you want to print.' );
1423 Language.LL( Apply, PrintingError, 'PrintingError', 'Error while printing: ' );
1424 Language.LL( Apply, StoppingPrintMsg, 'StoppingPrintMsg', 'Stopping print...' );
1425 Language.LL( Apply, PrintStoppedMsg, 'PrintStoppedMsg', 'Printing stopped' );
1426 Language.LL( Apply, CheckStopPrintTitle, 'CheckStopPrintTitle', 'Stop Print?' );
1427 Language.LL( Apply, CheckStopPrintMsg, 'CheckStopPrintMsg', 'Printing is still in progress. It will be stopped if you close.' );
1428
1429 Language.LL( Apply, TopicInfoTitle, 'TopicInfo.Title', 'Topic Information' );
1430 Language.LL( Apply, TopicInfoTopicTitle, 'TopicInfo.TopicTitle', 'Title: ' );
1431 Language.LL( Apply, TopicInfoIndex, 'TopicInfo.Index', 'Index: ' );
1432 Language.LL( Apply, TopicInfoFile, 'TopicInfo.File', 'File: ' );
1433 Language.LL( Apply, TopicInfoResourceIDs, 'TopicInfo.ResourceIDs', 'Resource IDs:' );
1434 Language.LL( Apply, TopicInfoNoResourceIDs, 'TopicInfo.NoResourceIDs', ' (None)' );
1435
1436 Language.LL( Apply, ParameterCountLabel, 'ParameterCountLabel', 'Parameter Count: ' );
1437
1438 Language.LL( Apply, NewViewHelpTitle, 'NewViewHelpTitle', 'NewView Help' );
1439 Language.LL( Apply, AlreadyNewviewHelp, 'AlreadyNewviewHelp', 'You are already viewing the NewView help file' );
1440 Language.LL( Apply, NewViewHelpNotFound, 'NewViewHelpNotFound', 'Couldn''t find the NewView helpfile: ' );
1441
1442 Language.LL( Apply, InvalidLinkErrorTitle, 'InvalidLinkErrorTitle', 'Invalid Link' );
1443 Language.LL( Apply, InvalidLinkError, 'InvalidLinkError', 'Cannot follow link to nonexistent topic' );
1444 Language.LL( Apply, InvalidResourceIDLinkErrorA, 'InvalidResourceIDLinkErrorA', 'Could not find linked topic (Resource #' );
1445 Language.LL( Apply, InvalidResourceIDLinkErrorB, 'InvalidResourceIDLinkErrorB', '). This may be from another file.' );
1446
1447 Language.LL( Apply, OpenedTopicMsg, 'OpenedTopicMsg', 'Opened topic #' );
1448
1449 Language.LL( Apply, AddNoteTitle, 'AddNoteTitle', 'Add Note' );
1450 Language.LL( Apply, AddNoteCursorError, 'AddNoteCursorError', 'Before adding a note, position the cursor where you want the note to be placed.' );
1451 Language.LL( Apply, NoteWithinNoteError, 'NoteWithinNoteError', 'You can''t add a note within a link or another note' );
1452 Language.LL( Apply, LoadNotesTitle, 'LoadNotesTitle', 'Load Notes' );
1453 Language.LL( Apply, LoadNotesError, 'LoadNotesError', 'Error loading notes from ' );
1454 Language.LL( Apply, SaveNotesTitle, 'SaveNotesTitle', 'Save Notes' );
1455 Language.LL( Apply, SaveNotesError, 'SaveNotesError', 'Error saving notes to ' );
1456
1457 Language.LL( Apply, UntitledBookmarkName, 'UntitledBookmarkName', '(Untitled)' );
1458 Language.LL( Apply, LoadBookmarksTitle, 'LoadBookmarksTitle', 'Load Bookmarks' );
1459 Language.LL( Apply, LoadBookmarksError, 'LoadBookmarksError', 'Could not load bookmarks: ' );
1460 Language.LL( Apply, SaveBookmarksTitle, 'SaveBookmarksTitle', 'Save Bookmarks' );
1461 Language.LL( Apply, SaveBookmarksError, 'SaveBookmarksError', 'Could not save bookmarks: ' );
1462
1463 Language.LL( Apply, ApplicationErrorTitle, 'ApplicationErrorTitle', 'Application Error - Close?' );
1464 Language.LL( Apply, ApplicationErrorA, 'ApplicationErrorA', 'This application has crashed. ' );
1465 Language.LL( Apply, ApplicationErrorB, 'ApplicationErrorB', '(Details logged to ' );
1466 Language.LL( Apply, ApplicationErrorC, 'ApplicationErrorC', 'Close application? ' );
1467
1468 Language.LL( Apply, EnvironmentVarErrorTitle, 'EnvironmentVarErrorTitle', 'Environment Variable Warning' );
1469 Language.LL( Apply, EnvironmentVarError,
1470 'EnvironmentVarError',
1471 'NewView found a problem with environment variables. '
1472 + 'These are used when finding help files. '
1473 + 'You may have problems launching help.' );
1474 Language.LL( Apply, EnvironmentVarUndefined, 'EnvironmentVarUndefined', 'Undefined: ' );
1475
1476 Language.LL( Apply, FindTitle, 'FindTitle', 'Find' );
1477 Language.LL( Apply, FindSelectWindowError, 'FindSelectWindowError', 'Click in a window first' );
1478 Language.LL( Apply, FindPrompt, 'FindPrompt', 'Enter the text to find' );
1479 Language.LL( Apply, TextNotFoundMsg, 'TextNotFoundMsg', 'Text not found' );
1480
1481 Language.LL( Apply, FilesInfoTitle, 'FilesInfoTitle', 'Open Files Information' );
1482 Language.LL( Apply, FilesInfoOverallTitle, 'FilesInfoOverallTitle', 'Title: ' );
1483 Language.LL( Apply, FilesInfoFilename, 'FilesInfoFilename', 'File name: ' );
1484 Language.LL( Apply, FilesInfoFileTitle, 'FilesInfoFileTitle', ' Title: ' );
1485 Language.LL( Apply, FilesInfoTopicCount, 'FilesInfoTopicCount', ' Topic Count: ' );
1486 Language.LL( Apply, FilesInfoIndexCount, 'FilesInfoIndexCount', ' Index Count: ' );
1487 Language.LL( Apply, FilesInfoDictionaryCount, 'FilesInfoDictionaryCount', ' Dictionary Count: ' );
1488 Language.LL( Apply, FilesInfoFileSize, 'FilesInfoFileSize', ' Size: ' );
1489 Language.LL( Apply, FilesInfoTotalTopicCount, 'FilesInfoTotalTopicCount', 'Total Topic Count: ' );
1490 Language.LL( Apply, FilesInfoTotalIndexCount, 'FilesInfoTotalIndexCount', 'Total Index Count: ' );
1491 Language.LL( Apply, FilesInfoTotalFileSize, 'FilesInfoTotalFileSize', 'Total File Size: ' );
1492
1493 Language.LL( Apply, SearchTitle, 'SearchTitle', 'Search' );
1494 Language.LL( Apply, SearchSyntaxError, 'SearchSyntaxError', 'Error in search syntax: ' );
1495 Language.LL( Apply, SearchingMsg, 'SearchingMsg', 'Searching...' );
1496 Language.LL( Apply, NoSearchMatchesMsg, 'NoSearchMatchesMsg', 'No matches found for ' );
1497 Language.LL( Apply, SearchFoundMsgA, 'SearchFoundMsgA', 'Found ' );
1498 Language.LL( Apply, SearchFoundMsgB, 'SearchFoundMsgB', ' matches for ' );
1499
1500 Language.LL( Apply, FileSaveTitle, 'FileSaveTitle', 'Save Topic' );
1501 Language.LL( Apply, FileSaveSelectWindowError, 'FileSaveSelectWindowError', 'Before saving, click in the window you want to save.' );
1502 Language.LL( Apply, DefaultSaveTopicFilename, 'DefaultSaveTopicFilename', 'topic.txt' );
1503
1504 Language.LL( Apply, ReplaceFilePromptA, 'ReplaceFilePromptA', 'Replace existing file ' );
1505 Language.LL( Apply, ReplaceFilePromptB, 'ReplaceFilePromptB', '?' );
1506 Language.LL( Apply, UnableToSaveError, 'UnableToSaveError', 'Unable to save file: ' );
1507
1508 Language.LL( Apply, UsageTitle, 'UsageTitle', 'NewView Command Line' );
1509 Language.LL( Apply, UsageText1, 'UsageText1', 'Usage: ' );
1510 Language.LL( Apply, UsageText2, 'UsageText2', 'NewView <file name> [<topic>]' );
1511 Language.LL( Apply, UsageText3, 'UsageText3', ' /s Do search for <topic>' );
1512 Language.LL( Apply, UsageText4, 'UsageText4', ' /g Do global search for <topic>' );
1513 Language.LL( Apply, UsageText5, 'UsageText5', ' /pos:l,b,w,h Set window position' );
1514 Language.LL( Apply, UsageText6, 'UsageText6', ' /lang:<lang> Load UI language' );
1515 Language.LL( Apply, UsageText7, 'UsageText7', ' /title:<title> Set window title' );
1516 Language.LL( Apply, UsageText8, 'UsageText8', 'See help for details' );
1517
1518 Language.LL( Apply, GoBackHint, 'GoBackHint', 'Go back to ' );
1519
1520 Language.LL( Apply, SelectAllTitle, 'SelectAllTitle', 'Select All' );
1521 Language.LL( Apply, SelectAllWindowError, 'SelectAllWindowError', 'Click in a text window first' );
1522
1523 Language.LL( Apply, EditNoteMsg, 'EditNoteMsg', 'Click to edit note' );
1524 Language.LL( Apply, ExternalLinkMsg, 'ExternalLinkMsg', 'Link to another file' );
1525 Language.LL( Apply, LinkMsg, 'LinkMsg', 'Link to' );
1526 Language.LL( Apply, UnknownLinkMsg, 'UnknownLinkMsg', 'Unknown link' );
1527 Language.LL( Apply, FootnoteMsg, 'FootnoteMsg', 'Footnote' );
1528
1529 Language.LL( Apply, ExternalLinkTitle, 'ExternalLinkTitle', 'File Link' );
1530 Language.LL( Apply, ExternalLinkError, 'ExternalLinkError', 'Sorry, this is a link to another file, which is not currently implemented in NewView' );
1531
1532 Language.LL( Apply, MRUMultipleFilesHint, 'MRUMultipleFilesHint', 'files' );
1533 Language.LL( Apply, HelpProgramTitle, 'HelpProgramTitle', 'Help' );
1534
1535 Language.LL( Apply, WindowsHelpTitle, 'WindowsHelpTitle', 'Windows Help' );
1536 Language.LL( Apply,
1537 WindowsHelpPrompt,
1538 'WindowsHelpPrompt',
1539 'This file is a Windows help file. '
1540 + 'Would you like to start Windows Help viewer?' );
1541
1542 Language.LL( Apply, ErrorTitle, 'ErrorTitle', 'Error' );
1543
1544 Language.LL( Apply, FindTopicNameTitle, 'FindTopicNameTitle', 'Find Topic By Name' );
1545 Language.LL( Apply, FindTopicNamePrompt, 'FindTopicNamePrompt', 'Enter the topic name to search for' );
1546 Language.LL( Apply, TopicNameNotFoundError, 'TopicNameNotFoundError', 'Topic name not found' );
1547 Language.LL( Apply, SplitBarDblClickToShow, 'SplitBarDblClickToShow', 'Double-click to show left panel' );
1548 Language.LL( Apply, SplitBarDblClickToHide, 'SplitBarDblClickToHide', 'Double-click to hide left panel' );
1549
1550 SetMainCaption;
1551 CreateMRUMenuItems;
1552
1553 // ----------------------------------------------------------
1554end;
1555
1556Procedure TMainForm.DebugLoadLanguageMIOnClick (Sender: TObject);
1557Var
1558 Dir: string;
1559 Filename: string;
1560Begin
1561 Dir := GetApplicationDir;
1562 if not DoOpenFileDialog( OpenLanguageTitle,
1563 LanguageFilesDesc
1564 + '|*.lng|'
1565 + AllFilesDesc
1566 + '|*',
1567 '*.lng',
1568 Dir,
1569 Filename ) then
1570 exit;
1571
1572 LoadLanguage( Filename );
1573End;
1574
1575Procedure TMainForm.DebugSaveLanguageFileMIOnClick (Sender: TObject);
1576Var
1577 LanguageFile: TLanguageFile;
1578 Dir: string;
1579 Filename: string;
1580Begin
1581 Dir := GetApplicationDir;
1582 if not DoSaveFileDialog( SaveLanguageTitle,
1583 LanguageFilesDesc
1584 + '|*.lng|'
1585 + AllFilesDesc
1586 + '|*',
1587 '*.lng',
1588 Dir,
1589 Filename ) then
1590 exit;
1591
1592 // get rid of mru menu items so they don't clutter the language file
1593 DestroyListObjects( MRUMenuItems );
1594 MRUMenuItems.Clear;
1595
1596 try
1597 LanguageFile := TLanguageFile.Create( Filename );
1598
1599 UpdateLanguage( LanguageFile );
1600 except
1601 on E: Exception do
1602 begin
1603 DoErrorDlg( SaveLanguageTitle,
1604 SaveLanguageError + E.Message );
1605 exit;
1606 end;
1607 end;
1608
1609 LanguageFile.Destroy;
1610
1611 CreateMRUMenuItems;
1612End;
1613
1614Procedure TMainForm.SearchResultsListBoxOnClick (Sender: TObject);
1615Begin
1616 DisplaySelectedSearchResultTopic;
1617End;
1618
1619Procedure TMainForm.VSplitBarOnDblClick (Sender: TObject);
1620Begin
1621 ShowLeftPanel := not ShowLeftPanel;
1622End;
1623
1624Procedure TMainForm.DebugHelpManagerVersionMIOnClick (Sender: TObject);
1625Begin
1626 DoMessageDlg( HelpManagerVersionTitle,
1627 HelpManagerVersion );
1628End;
1629
1630Procedure TMainForm.DebugTopicByResourceIDMIOnClick (Sender: TObject);
1631var
1632 ResourceIDString: string;
1633 ResourceID: USHORT;
1634Begin
1635 if not DoInputQuery( FindResourceIDTitle,
1636 FindResourceIDPrompt,
1637 ResourceIDString ) then
1638 exit;
1639 try
1640 ResourceID := StrToInt( ResourceIDString );
1641 except
1642 DoErrorDlg( FindResourceIDTitle,
1643 InvalidResourceIDError );
1644 exit;
1645 end;
1646
1647 if not DisplayTopicByResourceID( ResourceID ) then
1648 DoErrorDlg( FindResourceIDTitle,
1649 ResourceIDNotFoundError );
1650End;
1651
1652Procedure TMainForm.ViewHighlightSearchWordsMIOnClick (Sender: TObject);
1653Begin
1654 ViewHighlightSearchWordsMI.Checked := not ViewHighlightSearchWordsMI.Checked;
1655 RefreshWindows( Windows );
1656End;
1657
1658Procedure TMainForm.FileNewWindowMIOnClick (Sender: TObject);
1659Begin
1660 Exec( GetApplicationFilename, '' );
1661End;
1662
1663Function TMainForm.OpenFilesFromTextList( const TextList: string;
1664 const DisplayFirstTopic: boolean ): boolean;
1665var
1666 Filenames: TStringList;
1667begin
1668 Filenames := TStringList.Create;
1669 StrExtractStringsIgnoreEmpty(Filenames, TextList, ['+'], #0);
1670 if Filenames.Count > 0 then
1671 begin
1672 result := OpenFiles( Filenames, '', DisplayFirstTopic );
1673 end
1674 else
1675 begin
1676 CloseFile;
1677 end;
1678 Filenames.Destroy;
1679end;
1680
1681Procedure TMainForm.OpenSpecialMIOnClick (Sender: TObject);
1682var
1683 Parameter: string;
1684Begin
1685 if not OKToCloseFile then
1686 exit;
1687
1688 if DoInputQuery( OpenSpecialTitle,
1689 OpenSpecialPrompt,
1690 Parameter ) then
1691 begin
1692 if OpenFilesFromTextList( Parameter, true ) then
1693 begin
1694 ClearHelpManager;
1695 end;
1696 end;
1697End;
1698
1699Procedure TMainForm.NotesListBoxOnScan (Sender: TObject;
1700 Var KeyCode: TKeyCode);
1701Begin
1702 if KeyCode in [ kbDel, kbBkSp ] then
1703 if NotesListBox.ItemIndex <> -1 then
1704 DeleteNote( NotesListBox.ItemIndex );
1705End;
1706
1707Procedure TMainForm.ViewPopupMenuOnPopup (Sender: TObject);
1708var
1709 Window: THelpWindow;
1710Begin
1711 Window := GetActiveWindow;
1712 if Window = nil then
1713 begin
1714 SearchPMI.Enabled := false;
1715 exit;
1716 end;
1717 SearchPMI.Enabled := Window.View.SelectionLength > 0;
1718End;
1719
1720Procedure TMainForm.SearchPMIOnClick (Sender: TObject);
1721var
1722 Window: THelpWindow;
1723Begin
1724 Window := GetActiveWindow;
1725 if Window = nil then
1726 exit;
1727
1728 SearchFor( Window.View.GetSelectionAsString );
1729end;
1730
1731function TMainForm.DisplayTopicByGlobalName( const TopicName: string ): boolean;
1732var
1733 Topic: TTopic;
1734begin
1735 Topic := FindTopicByGlobalName( TopicName );
1736 if Topic = nil then
1737 begin
1738 Result := false;
1739 exit;
1740 end;
1741
1742 result := true;
1743
1744 DisplayTopic( Topic );
1745end;
1746
1747function TMainForm.DisplayTopicByName( const TopicName: string ): boolean;
1748var
1749 Topic: TTopic;
1750begin
1751 Topic := FindTopicByName( TopicName );
1752 if Topic = nil then
1753 begin
1754 Result := false;
1755 exit;
1756 end;
1757
1758 result := true;
1759
1760 DisplayTopic( Topic );
1761end;
1762
1763function TMainForm.DisplayTopicByResourceID( ID: uint16 ): boolean;
1764var
1765 Topic: TTopic;
1766begin
1767 LogEvent(LogDebug, 'DisplayTopicByResourceID id:' + IntToStr(ID));
1768 Topic := FindTopicByResourceID( ID );
1769 if Topic = nil then
1770 begin
1771 LogEvent(LogDebug, 'DisplayTopicByResourceID - topic not found');
1772 Result := false;
1773 exit;
1774 end;
1775
1776 result := true;
1777
1778 LogEvent(LogDebug, 'DisplayTopicByResourceID topic: "' + Topic.Title + '"');
1779 DisplayTopic( Topic );
1780end;
1781
1782Procedure TMainForm.ViewSourceMIOnClick (Sender: TObject);
1783var
1784 Window: THelpWindow;
1785Begin
1786 Window := GetActiveWindow;
1787 if Window = nil then
1788 exit;
1789 InformationForm.FText := Window.View.Text;
1790 InformationForm.ShowModal;
1791End;
1792
1793Procedure TMainForm.PrintMIOnClick (Sender: TObject);
1794Begin
1795 PrintTopics;
1796End;
1797
1798type
1799 TPrintSingle = class
1800 Topic: TTopic;
1801 end;
1802
1803 TPrintList = class
1804 Topics: TList;
1805 constructor Create;
1806 destructor Destroy; override;
1807 end;
1808
1809 TPrintAll = class
1810 end;
1811
1812constructor TPrintList.Create;
1813begin
1814 Topics := TList.Create;
1815end;
1816
1817destructor TPrintList.Destroy;
1818begin
1819 Topics.Destroy;
1820end;
1821
1822// Recursive
1823Procedure GetTopicsInWindows( Windows: TList;
1824 Topics: TList );
1825var
1826 Window: THelpWindow;
1827 i: longint;
1828begin
1829 for i := 0 to Windows.Count - 1 do
1830 begin
1831 Window := Windows[ i ];
1832 Topics.Add( Window.Topic );
1833 GetTopicsInWindows( Window.ChildWindows, Topics );
1834 end;
1835end;
1836
1837Procedure TMainForm.PrintTopics;
1838var
1839 Window: THelpWindow;
1840 PrintParameters: TObject;
1841Begin
1842 if Printer.Printers.Count = 0 then
1843 begin
1844 DoErrorDlg( PrintTopicTitle,
1845 NoPrinterError );
1846 exit;
1847 end;
1848
1849 if NewViewPrintDialog.ShowModal <> mrOK then
1850 exit;
1851
1852 if PrintThread = nil then
1853 begin
1854 PrintThread := TGenericThreadManager.Create( self );
1855 PrintThread.OnProgressUpdate := OnPrintProgress;
1856 PrintThread.OnJobComplete := OnPrintComplete;
1857
1858 end;
1859
1860 case NewViewPrintDialog.WhatToPrintRadioGroup.ItemIndex of
1861 0:
1862 begin
1863 PrintParameters := TPrintSingle.Create;
1864 Window := GetActiveWindow;
1865 TPrintSingle( PrintParameters ).Topic := Window.Topic;
1866 end;
1867
1868 1:
1869 begin
1870 PrintParameters := TPrintList.Create;
1871 GetTopicsInWindows( Windows,
1872 TPrintList( PrintParameters ).Topics );
1873 end;
1874
1875 2:
1876 begin
1877 PrintParameters := TPrintAll.Create;
1878 end;
1879 end;
1880
1881 PrintThread.StartJob( DoPrinting, PrintParameters );
1882
1883 SetStatus( 'Printing...' );
1884end;
1885
1886procedure PrintTopic( Topic: TTopic;
1887 RichTextSettings: TRichTextSettings;
1888 Var PageY: longint );
1889var
1890 TopicText: TAstring;
1891 TitleText: TAString;
1892 ImageOffsets: TList;
1893 Images: TImageList;
1894begin
1895 TopicText := TAstring.Create;
1896 Images := TImageList.Create( nil );
1897 TitleText := TAString.Create;
1898 ImageOffsets := TList.Create;
1899
1900 TitleText.AddString( '<leftmargin 1><h1>'
1901 + Topic.Title
1902 + '</h>'
1903 + #10
1904 + #10 );
1905 PrintRichText( TitleText.AsPChar,
1906 Images,
1907 RichTextSettings,
1908 PageY );
1909
1910 Topic.GetText( nil, // no highlights
1911 false, // no codes
1912 false, // no word separators
1913 TopicText, // text to print
1914 ImageOffsets, // image offsets
1915 nil ); // no highlight matches required
1916
1917 THelpFile( Topic.HelpFile ).GetImages( ImageOffsets,
1918 Images );
1919
1920 PrintRichText( TopicText.AsPChar,
1921 Images,
1922 RichTextSettings,
1923 PageY );
1924
1925 TitleText.Clear;
1926 TitleText.AddString( #10
1927 + '<leftmargin 1><align center>'
1928 + '--------------------------------------------'
1929 + #10
1930 + #10 );
1931 PrintRichText( TitleText.AsPChar,
1932 Images,
1933 RichTextSettings,
1934 PageY );
1935
1936 ImageOffsets.Destroy;
1937 TitleText.Destroy;
1938 Images.Destroy;
1939 TopicText.Destroy;
1940end;
1941
1942function TMainForm.DoPrinting( Parameters: TObject ): TObject;
1943var
1944 PrintSingle: TPrintSingle;
1945 PrintList: TPrintList;
1946 PageY: longint;
1947 RichTextSettings: TRichTextSettings;
1948 PrinterResolution: longint;
1949 MarginSize: longint;
1950
1951 HelpFile: THelpFile;
1952
1953 FileIndex: longint;
1954 TopicIndex: longint;
1955
1956 TotalTopics: longint;
1957 TotalTopicIndex: longint;
1958begin
1959 PrintSingle := nil;
1960 PrintList := nil;
1961
1962 if Parameters is TPrintSingle then
1963 PrintSingle := Parameters as TPrintSingle
1964 else if Parameters is TPrintList then
1965 PrintList := Parameters as TPrintList;
1966
1967 if Parameters is TPrintSingle then
1968 Printer.Title := PrintSingle.Topic.Title
1969 else
1970 Printer.Title := MainTitle;
1971
1972 Printer.BeginDoc;
1973
1974 PageY := Printer.PageHeight - 1;
1975
1976 RichTextSettings := TRichTextSettings.Create( nil );
1977 RichTextSettings.NormalFont := Settings.NormalFont;
1978 RichTextSettings.FixedFont := Settings.FixedFont;
1979
1980 // set half inch margins
1981 PrinterResolution := Printer.Canvas.HorizontalResolution; // pixels per meter!
1982 MarginSize := Round( PrinterResolution * 0.0125 ); // 12.5 mm = 0.5 inch
1983 RichTextSettings.Margins := Rect( MarginSize,
1984 MarginSize,
1985 MarginSize,
1986 MarginSize );
1987
1988 try
1989 if Parameters is TPrintSingle then
1990 begin
1991 PrintTopic( PrintSingle.Topic, RichTextSettings, PageY );
1992 end
1993
1994 else if Parameters is TPrintList then
1995 begin
1996 for TopicIndex := 0 to PrintList.Topics.Count -1 do
1997 begin
1998 PrintThread.UpdateProgress( TopicIndex, PrintList.Topics.Count, 'Printing' );
1999
2000 PrintTopic( PrintList.Topics[ TopicIndex ] , RichTextSettings, PageY );
2001
2002 if PrintThread.StopRequested then
2003 break;
2004 end
2005 end
2006
2007 else if Parameters is TPrintAll then
2008 begin
2009 // first count up total number of topics.
2010 TotalTopics := 0;
2011 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2012 begin
2013 HelpFile := CurrentOpenFiles[ FileIndex ];
2014 inc( TotalTopics, HelpFile.TopicCount );
2015 end;
2016
2017 TotalTopicIndex := 0;
2018 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2019 begin
2020 HelpFile := CurrentOpenFiles[ FileIndex ];
2021 for TopicIndex := 0 to HelpFile.TopicCount - 1 do
2022 begin
2023 PrintThread.UpdateProgress( TotalTopicIndex, TotalTopics, 'Printing' );
2024 PrintTopic( HelpFile.Topics[ TopicIndex ], RichTextSettings, PageY );
2025 if PrintThread.StopRequested then
2026 break;
2027 inc( TotalTopicIndex );
2028 end;
2029 end;
2030 end;
2031 except
2032 on E: EPrinter do
2033 begin
2034 DoErrorDlg( PrintTopicTitle,
2035 PrintingError + E.Message );
2036 end;
2037 end;
2038
2039 Printer.EndDoc;
2040 result := nil;
2041End;
2042
2043procedure TMainForm.OnPrintProgress( n, outof: integer;
2044 Message: string );
2045begin
2046 SetProgress( n, outof, message );
2047end;
2048
2049procedure TMainForm.OnPrintComplete( Dummy: TObject );
2050begin
2051 SetStatus( 'Printing complete' );
2052 ResetProgress;
2053end;
2054
2055// --------------------------------------------------
2056
2057Procedure TMainForm.DebugShowWordSeparatorsMIOnClick (Sender: TObject);
2058Begin
2059 DebugShowWordSeparatorsMI.Checked := not DebugShowWordSeparatorsMI.Checked;
2060 RefreshWindows( Windows );
2061End;
2062
2063Procedure TMainForm.DebugStressTestMIOnClick (Sender: TObject);
2064var
2065 i: longint;
2066 NString: string;
2067 N: longint;
2068Begin
2069 if not DoInputQuery( 'Stress Test',
2070 'Repititions?',
2071 NString ) then
2072 exit;
2073 N := StrToIntDef( NString, 1 );
2074 for i := 0 to N - 1 do
2075 begin
2076 ContentsOutline.GotoFirstNode;
2077 repeat
2078 DisplaySelectedContentsTopic;
2079 Application.ProcessMessages;
2080 until not ContentsOutline.GotoNextNodeDown;
2081 end;
2082End;
2083
2084// Find topic specified by global name, in all open files
2085Function TMainForm.FindTopicByGlobalName( const Name: string ): TTopic;
2086var
2087 FileIndex: longint;
2088 HelpFile: THelpFile;
2089begin
2090 Result := nil;
2091
2092 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2093 begin
2094 HelpFile := CurrentOpenFiles[ FileIndex ];
2095 Result := HelpFile.FindTopicByGlobalName( Name );
2096 if Result <> nil then
2097 // found
2098 exit;
2099 end;
2100
2101 // not found.
2102 Result := nil;
2103end;
2104
2105// Find topic specified by numeric resource ID, in all open files
2106Function TMainForm.FindTopicByResourceID( ID: uint16 ): TTopic;
2107var
2108 FileIndex: longint;
2109 HelpFile: THelpFile;
2110begin
2111 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2112 begin
2113 HelpFile := CurrentOpenFiles[ FileIndex ];
2114
2115 Result := HelpFile.FindTopicByResourceID( ID );
2116 if Result <> nil then
2117 // found
2118 exit;
2119 end;
2120
2121 // not found.
2122 Result := nil;
2123end;
2124
2125// Find topic specified by text name, in all open files
2126Function TMainForm.FindTopicByName( const Name: string ): TTopic;
2127var
2128 FileIndex: longint;
2129 HelpFile: THelpFile;
2130begin
2131 Result := nil;
2132
2133 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2134 begin
2135 HelpFile := CurrentOpenFiles[ FileIndex ];
2136 Result := HelpFile.FindTopicByLocalName( Name );
2137 if Result <> nil then
2138 // found
2139 exit;
2140 end;
2141
2142 // not found.
2143 Result := nil;
2144end;
2145
2146// Find the target topic for the given link
2147Function TMainForm.FindTopicForLink( Link: THelpLink ): TTopic;
2148var
2149 HelpFile: THelpFile;
2150begin
2151 HelpFile := Link.HelpFile as THelpFile;
2152 if Link is TFootnoteHelpLink then
2153 begin
2154 Result := HelpFile.Topics[ TFootnoteHelpLink( Link ).TopicIndex ];
2155 end
2156 else if Link is TInternalHelpLink then
2157 begin
2158 Result := HelpFile.Topics[ TInternalHelpLink( Link ).TopicIndex ];
2159 end
2160 else if Link is THelpLinkByResourceID then
2161 begin
2162 Result := FindTopicByResourceID( THelpLinkByResourceID( Link ).ResourceID );
2163 end
2164end;
2165
2166Procedure TMainForm.TopicPropertiesPMIOnClick (Sender: TObject);
2167var
2168 Window: THelpWindow;
2169 Topic: TTopic;
2170 HelpFile: THelpFile;
2171 ResourceIDs: TList;
2172 i: longint;
2173Begin
2174 Window := GetActiveWindow;
2175 if Window = nil then
2176 exit;
2177 Topic := Window.Topic;
2178 HelpFile := Topic.HelpFile as THelpFile;
2179
2180 ResourceIDs := TList.Create;
2181 HelpFile.FindResourceIDsForTopic( Topic,
2182 ResourceIDs );
2183
2184 with InformationForm.InformationMemo do
2185 begin
2186 Lines.Clear;
2187 Lines.Add( TopicInfoTitle );
2188 Lines.Add( TopicInfoTopicTitle + Topic.Title );
2189 Lines.Add( TopicInfoIndex + IntToStr( Topic.Index ) );
2190 Lines.Add( TopicInfoFile + HelpFile.Filename );
2191 Lines.Add( TopicInfoResourceIDs );
2192 for i := 0 to ResourceIDs.Count - 1 do
2193 Lines.Add( ' ' + IntToStr( longint( ResourceIDs[ i ] ) ) );
2194 if ResourceIDs.Count = 0 then
2195 Lines.Add( TopicInfoNoResourceIDs );
2196 end;
2197 ResourceIDs.Destroy;
2198
2199 InformationForm.ShowModal;
2200End;
2201Procedure TMainForm.NavigateForwardMIOnClick (Sender: TObject);
2202Begin
2203 NavigateForward;
2204End;
2205
2206Procedure TMainForm.FocusFirstHelpWindow;
2207begin
2208 if Windows.Count > 0 then
2209 THelpWindow( Windows[ 0 ] ).View.Focus;
2210end;
2211
2212Procedure TMainForm.IndexListBoxOnScan (Sender: TObject;
2213 Var KeyCode: TKeyCode);
2214Begin
2215 case KeyCode of
2216 kbTab:
2217 begin
2218 FocusFirstHelpWindow;
2219 KeyCode := kbNull;
2220 end;
2221 kb_VK + VK_NEWLINE:
2222 DisplaySelectedIndexTopic;
2223 end;
2224End;
2225
2226Procedure TMainForm.SearchResultsListBoxOnScan (Sender: TObject;
2227 Var KeyCode: TKeyCode);
2228Begin
2229 case KeyCode of
2230 kbTab:
2231 begin
2232 FocusFirstHelpWindow;
2233 KeyCode := kbNull;
2234 end;
2235
2236 kb_VK + VK_NEWLINE:
2237 DisplaySelectedSearchResultTopic;
2238 end;
2239End;
2240
2241Procedure TMainForm.ContentsOutlineOnScan (Sender: TObject;
2242 Var KeyCode: TKeyCode);
2243Begin
2244 case KeyCode of
2245 kbTab:
2246 begin
2247 FocusFirstHelpWindow;
2248 KeyCode := kbNull;
2249 end;
2250 kb_VK + VK_NEWLINE:
2251 DisplaySelectedContentsTopic;
2252 end;
2253End;
2254
2255Procedure TMainForm.ToolsOptionsMIOnClick (Sender: TObject);
2256Begin
2257 DoOptions;
2258End;
2259
2260Procedure TMainForm.EditGlobalSearchMIOnClick (Sender: TObject);
2261Begin
2262 DoGlobalSearch( '' );
2263End;
2264
2265Procedure TMainForm.ViewExpandAllMIOnClick (Sender: TObject);
2266Begin
2267 DisplayContents;
2268 ContentsOutline.ExpandAll;
2269End;
2270
2271Procedure TMainForm.DebugShowParamsMIOnClick (Sender: TObject);
2272Begin
2273 with InformationForm.InformationMemo do
2274 begin
2275 Lines.Clear;
2276 Lines.Add('');
2277
2278 CmdLineParameters.writeDetailsTo(Lines);
2279 end;
2280
2281 InformationForm.ShowModal;
2282End;
2283
2284Procedure TMainForm.EditBookmarksMIOnClick (Sender: TObject);
2285Begin
2286 BookmarksForm.BookmarkList := Bookmarks;
2287 BookmarksForm.OpenBookmarkCallback := NavigateToBookmark;
2288 BookmarksForm.BookmarksChangedCallback := OnBookmarksChanged;
2289 BookmarksForm.Show;
2290
2291 // Since we are showing a nonmodal dialog, set the PM owner window
2292 // so that the bookmarks form remains on top.
2293 WinSetOwner( BookmarksForm.Frame.Handle,
2294 Frame.Handle );
2295End;
2296
2297Procedure TMainForm.CopyPMIOnClick (Sender: TObject);
2298var
2299 Window: THelpWindow;
2300Begin
2301 Window := GetActiveWindow;
2302 if Window = nil then
2303 exit;
2304 Window.View.CopySelectionToClipboard;
2305End;
2306
2307Procedure TMainForm.SelectAllPMIOnClick (Sender: TObject);
2308var
2309 Window: THelpWindow;
2310Begin
2311 Window := GetActiveWindow;
2312 if Window = nil then
2313 exit;
2314 Window.View.SelectAll;
2315End;
2316
2317Procedure TMainForm.AddNoteButtonOnClick (Sender: TObject);
2318Begin
2319 AddNote;
2320End;
2321
2322Procedure TMainForm.EnableSearchButton;
2323var
2324 CanSearch: boolean;
2325begin
2326 CanSearch := false;
2327 if CurrentOpenFiles.Count > 0 then
2328 if trim( SearchTextEdit.Text ) > '' then
2329 CanSearch := true;
2330 SearchButton.Enabled := CanSearch;
2331end;
2332
2333Procedure TMainForm.SearchTextEditOnChange (Sender: TObject);
2334Begin
2335 EnableSearchButton;
2336End;
2337
2338Procedure TMainForm.OnHint( Sender: TObject );
2339begin
2340 SetStatus( Application.Hint );
2341end;
2342
2343Procedure TMainForm.DisplaySelectedIndexTopic;
2344var
2345 Topic: TTopic;
2346Begin
2347 if IndexListBox.ItemIndex = -1 then
2348 exit;
2349 Topic := DisplayedIndex.Objects[ IndexListBox.ItemIndex ] as TTopic;
2350 DisplayTopic( Topic );
2351End;
2352
2353Procedure TMainForm.IndexListBoxOnClick (Sender: TObject);
2354Begin
2355 DisplaySelectedIndexTopic;
2356End;
2357
2358Procedure TMainForm.ViewCollapseAllMIOnClick (Sender: TObject);
2359Begin
2360 DisplayContents;
2361 ContentsOutline.CollapseAll;
2362 DisplaySelectedContentsTopic;
2363End;
2364
2365Procedure TMainForm.NotesListBoxOnDblClick (Sender: TObject);
2366Begin
2367 GotoCurrentNote;
2368End;
2369
2370function TMainForm.OwnHelpMode: boolean;
2371var
2372 Filename: string;
2373 NamePart: string;
2374begin
2375 result := false;
2376 if CurrentOpenFiles.Count <> 1 then
2377 exit;
2378
2379 Filename := THelpFile( CurrentOpenFiles[ 0 ] ).Filename;
2380 NamePart := ExtractFileName( Filename );
2381 Result := StrStartsWithIgnoringCase('newview', NamePart);
2382end;
2383
2384Procedure TMainForm.HelpMIOnClick (Sender: TObject);
2385Begin
2386 if OwnHelpMode then
2387 begin
2388 DoErrorDlg( NewViewHelpTitle,
2389 AlreadyNewviewHelp );
2390 exit;
2391 end;
2392 Application.HelpContents;
2393End;
2394
2395Procedure TMainForm.NotebookOnPageChanged (Sender: TObject);
2396var
2397 FileIndex: longint;
2398 HelpFile: THelpFile;
2399Begin
2400 EnableControls;
2401 case Notebook.PageIndex of
2402 piContents:
2403 begin
2404 // not really feasible to load contents here, as we rely
2405 // on it for many things
2406 ContentsOutline.Focus;
2407 end;
2408
2409 piIndex:
2410 begin
2411 if not IndexLoaded then
2412 begin
2413 LoadIndex;
2414 end;
2415 IndexSearchEdit.Focus;
2416 end;
2417
2418 piSearch:
2419 begin
2420 SearchButton.Focus;
2421 SearchTextEdit.Focus;
2422 end;
2423
2424 piNotes:
2425 begin
2426 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2427 begin
2428 HelpFile := CurrentOpenFiles[ FileIndex ];
2429 if not HelpFile.NotesLoaded then
2430 LoadNotes( HelpFile );
2431 end;
2432 NotesListBox.Focus;
2433 UpdateNotesDisplay;
2434 end;
2435 end;
2436
2437End;
2438
2439Procedure TMainForm.ViewRefreshMIOnClick (Sender: TObject);
2440Begin
2441 RefreshWindows( Windows );
2442End;
2443
2444Procedure TMainForm.ViewNotesMIOnClick (Sender: TObject);
2445Begin
2446 ShowLeftPanel := true;
2447 TabSet.TabIndex := piNotes;
2448End;
2449
2450Procedure TMainForm.ViewSearchMIOnClick (Sender: TObject);
2451Begin
2452 DisplaySearch;
2453End;
2454
2455Procedure TMainForm.ShowTab( TabIndex: longint );
2456Begin
2457 ShowLeftPanel := true;
2458 TabSet.TabIndex := TabIndex;
2459 NotebookOnPageChanged( self );// focus control etc
2460End;
2461
2462Procedure TMainForm.DisplaySearch;
2463Begin
2464 ShowTab( piSearch );
2465End;
2466
2467Procedure TMainForm.ViewIndexMIOnClick (Sender: TObject);
2468Begin
2469 DisplayIndex;
2470End;
2471
2472Procedure TMainForm.DisplayIndex;
2473Begin
2474 ShowTab( piIndex );
2475End;
2476
2477Procedure TMainForm.ViewContentsMIOnClick (Sender: TObject);
2478Begin
2479 DisplayContents;
2480End;
2481
2482Procedure TMainForm.DisplayContents;
2483Begin
2484 ShowTab( piContents );
2485End;
2486
2487function TMainForm.OpenWindow( Topic: TTopic;
2488 Group: longint;
2489 Parent: THelpWindow;
2490 Rect: THelpWindowRect;
2491 FollowAutoLinks: boolean ): THelpWindow;
2492var
2493 Window: THelpWindow;
2494 DisplayTopicRequired: boolean;
2495begin
2496 Window := nil;
2497
2498 if ( Group <> DefaultGroupIndex ) and ( Parent = nil ) then
2499 begin
2500 // Normal window (not a split window) and a specific group is desired.
2501 // So see if we can find one with that group number
2502 Window := FindWindowFromGroup( Group, Windows );
2503
2504 end
2505 else
2506 begin
2507 // only reuse window if it has the same topic.
2508 Window := FindWindowFromTopic( Topic, Windows );
2509 end;
2510
2511 if Window = nil then
2512 begin
2513 DisplayingTopicWindow := true;
2514
2515 // not found, or want a new one
2516 Window := THelpWindow.Create( Parent = nil );
2517
2518 // add to parent
2519 if Parent = nil then
2520 begin
2521 Window.Parent := DisplayPanel;
2522 Windows.Add( Window );
2523 end
2524 else
2525 begin
2526 Window.Parent := Parent.View;
2527 Parent.ChildWindows.Add( Window );
2528 end;
2529
2530 Window.ParentHelpWindow := Parent;
2531
2532 DisplayingTopicWindow := false;
2533
2534 end
2535 else
2536 begin
2537 // reusing an existing window. Don't change parent
2538 end;
2539
2540 Window.Group := Group;
2541
2542 Window.View.PopupMenu := ViewPopupMenu;
2543
2544 Window.View.Images := Window.Images;
2545
2546 Window.View.OnClickLink := OnClickLink;
2547 Window.View.OnOverLink := OnOverLink;
2548 Window.View.OnNotOverLink := OnNotOverLink;
2549
2550 Window.OnClose := OnWindowClose;
2551 Window.OnCloseQuery := OnWindowAboutToClose;
2552 Window.OnDragOver := OnDragOverWindow;
2553 Window.OnDragDrop := OnDragDropToWindow;
2554 Window.OnFontChange := OnWindowFontChange;
2555 Window.OnTab := OnWindowTab;
2556 Window.OnBackTab := OnWindowBackTab;
2557
2558 // Use the contents rect by default...
2559 Topic.GetContentsWindowRect( Window.Rect );
2560 if Rect <> nil then
2561 begin
2562 // the rect is being overridden, so use it instead
2563 if Rect.Left <> -1 then
2564 Window.Rect.Left := Rect.Left;
2565 if Rect.Bottom <> -1 then
2566 Window.Rect.Bottom := Rect.Bottom;
2567 if Rect.Width <> -1 then
2568 Window.Rect.Width := Rect.Width;
2569 if Rect.Height <> -1 then
2570 Window.Rect.Height := Rect.Height;
2571 end;
2572
2573 if Window.ChildWindows.Count > 0 then
2574 begin
2575 // close existing child windows
2576 DestroyListObjects( Window.ChildWindows );
2577 Window.ChildWindows.Clear;
2578 Window.View.Show; // show the view again
2579 end;
2580
2581 DisplayTopicRequired := Window.Topic <> Topic;
2582 Window.Topic := Topic; // set this now so that SetLayout can log meaninful stuff
2583
2584 // Adjust the window size to it's specified Rect
2585 // Must do this before displaying child windows (DisplayTopicInWindow,
2586 // split window autolinks),
2587 // otherwise they will not size themselves correctly
2588 Window.SetLayout;
2589
2590 if DisplayTopicRequired then
2591 begin
2592 DisplayTopicInWindow( Window, FollowAutoLinks, false );
2593 end;
2594
2595 // Bring this window to the front
2596 Window.BringToFront;
2597
2598 Result := Window;
2599end;
2600
2601// Find an existing help window containing the given richtext view control
2602Function TMainForm.FindWindowFromView( View: TRichTextView;
2603 WindowList: TList ): THelpWindow;
2604var
2605 WindowIndex: longint;
2606begin
2607 for WindowIndex:= 0 to WindowList.Count - 1 do
2608 begin
2609 Result:= WindowList[ WindowIndex ];
2610 if Result.View = View then
2611 exit;
2612 Result:= FindWindowFromView( View, Result.ChildWindows );
2613 if Result <> nil then
2614 exit;
2615 end;
2616 Result:= nil;
2617end;
2618
2619// Find an existing help window with the given group number (if any)
2620Function TMainForm.FindWindowFromGroup( Group: longint; WindowList: TList ): THelpWindow;
2621var
2622 WindowIndex: longint;
2623begin
2624 for WindowIndex:= 0 to WindowList.Count - 1 do
2625 begin
2626 Result:= WindowList[ WindowIndex ];
2627 if Result.Group = Group then
2628 exit;
2629 Result:= FindWindowFromGroup( Group, Result.ChildWindows );
2630 if Result <> nil then
2631 exit;
2632 end;
2633 Result:= nil;
2634end;
2635
2636// Find an existing help window alreadying displaying the given topic
2637Function TMainForm.FindWindowFromTopic( Topic: TTopic; WindowList: TList ): THelpWindow;
2638var
2639 WindowIndex: longint;
2640begin
2641 for WindowIndex:= 0 to WindowList.Count - 1 do
2642 begin
2643 Result:= WindowList[ WindowIndex ];
2644 if Result.Topic = Topic then
2645 exit;
2646 Result:= FindWindowFromTopic( Topic, Result.ChildWindows );
2647 if Result <> nil then
2648 exit;
2649 end;
2650 Result:= nil;
2651end;
2652
2653Procedure TMainForm.RefreshFontSubstitutions;
2654var
2655 FileIndex: longint;
2656 HelpFile: THelpFile;
2657begin
2658 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2659 begin
2660 HelpFile := CurrentOpenFiles[ FileIndex ];
2661
2662 if Settings.FixedFontSubstitution then
2663 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes )
2664 else
2665 HelpFile.SetupFontSubstitutes( '' );
2666 end;
2667end;
2668
2669// Redisplay topics in all windows
2670Procedure TMainForm.RefreshWindows( WindowList: TList );
2671var
2672 WindowIndex: longint;
2673 Window: THelpWindow;
2674begin
2675 for WindowIndex:= 0 to WindowList.Count - 1 do
2676 begin
2677 Window:= WindowList[ WindowIndex ];
2678 DisplayTopicInWindow( Window,
2679 false, // don't follow links!
2680 true ); // keep position
2681 RefreshWindows( Window.ChildWindows );
2682 end;
2683end;
2684
2685Procedure TMainForm.WMFollowExternalLink( Var Msg: TMessage );
2686var
2687 FilePath: string;
2688 Topic: TTopic;
2689begin
2690 // try in same dir as source file
2691 FilePath := AddDirectorySeparator( ExtractFilePath( g_ExternalLinkSourceFilename ) )
2692 + g_ExternalLinkFilename;
2693
2694 if not StrEqualIgnoringCase( FilePath, g_ExternalLinkSourceFilename ) then
2695 begin
2696 // different file - try and open it
2697 if not FileExists( FilePath ) then
2698 // not in same directory, find in help paths
2699 FilePath := FindHelpFile( g_ExternalLinkFilename );
2700
2701 if not FileExists( FilePath ) then
2702 begin
2703 DoErrorDlg( 'Link Error',
2704 'Cannot find linked file '
2705 + g_ExternalLinkFilename );
2706 exit;
2707 end;
2708
2709 if g_ExternalLinkKeepCurrent then
2710 begin
2711 if not OpenAdditionalFile( FilePath, false ) then
2712 exit;
2713 end
2714 else
2715 begin
2716 if not OpenFile( FilePath, '', false ) then
2717 exit;
2718 end;
2719
2720 end;
2721
2722 if g_ExternalLinkTopic = '' then
2723 begin
2724 // specific topic not required.
2725 DisplaySelectedContentsTopic;
2726 exit;
2727 end;
2728
2729 Topic := FindTopicByGlobalName( g_ExternalLinkTopic );
2730 if Topic = nil then
2731 begin
2732 DoErrorDlg( 'Link Error',
2733 'Unable to find topic with global name '
2734 + g_ExternalLinkTopic );
2735 exit;
2736 end;
2737
2738 DisplayTopic( Topic );
2739end;
2740
2741// We are following a link, specified as param1 in msg
2742Procedure TMainForm.WMFollowLink( Var Msg: TMessage );
2743var
2744 NewTopic: TTopic;
2745 Link: THelpLink;
2746 SourceWindow: THelpWindow;
2747begin
2748 Link:= THelpLink( Msg.Param1 );
2749 SourceWindow:= THelpWindow( Msg.Param2 );
2750 NewTopic:= FindTopicForLink( Link );
2751
2752 // remove the link target info from status
2753 SetStatus( '' );
2754
2755 if NewTopic = nil then
2756 begin
2757 // Linked topic not found, this is an error... which kind?
2758
2759 if Link is THelpLinkByResourceID then
2760 begin
2761 // may happen if e.g. PM4.INF is loaded by itself,
2762 // and a link references a resource ID from e.g PM2.INF
2763 DoErrorDlg( InvalidLinkErrorTitle,
2764 InvalidResourceIDLinkErrorA
2765 + IntToStr( THelpLinkByResourceID( Link ).ResourceID )
2766 + InvalidResourceIDLinkErrorB );
2767 end
2768 else
2769 begin
2770 // should never happen, given valid help files
2771 DoErrorDlg( InvalidLinkErrorTitle,
2772 InvalidLinkError );
2773 end;
2774
2775 exit;
2776 end;
2777
2778 UpdateCurrentNavigatePoint;
2779
2780 FollowLink( Link, SourceWindow );
2781
2782 if NewTopic.ShowInContents then
2783 begin
2784 Navigating:= true;
2785 if ContentsOutline.SelectedNode = nil then
2786 ContentsOutline.SetSelectedObject( NewTopic )
2787 else if ContentsOutline.SelectedNode.Data <> NewTopic then
2788 ContentsOutline.SetSelectedObject( NewTopic );
2789 Navigating:= false;
2790 end;
2791 SaveNavigatePoint;
2792 EnableControls;
2793 ShowWindows;
2794
2795end;
2796
2797// Follow the given link from the given window.
2798// ie. open the topic or footnote it points to
2799Procedure TMainForm.FollowLink( Link: THelpLink;
2800 SourceWindow: THelpWindow );
2801var
2802 LinkedTopic: TTopic;
2803 ParentWindow: THelpWindow;
2804 WindowedLink: TWindowedHelpLink;
2805 NewWindow: THelpWIndow;
2806begin
2807 LinkedTopic := FindTopicForLink( Link );
2808
2809 if LinkedTopic = nil then
2810 begin
2811 exit;
2812 end;
2813
2814 if Link is TFootnoteHelpLink then
2815 begin
2816 NewWindow := OpenWindow( LinkedTopic,
2817 DefaultGroupIndex,
2818 nil, // no parent
2819 FootnoteRect,
2820 true );
2821 NewWindow.Caption := TFootnoteHelpLink( Link ).Title;
2822 exit;
2823 end;
2824
2825 WindowedLink := Link as TWindowedHelpLink;
2826
2827 ParentWindow:= nil;
2828 if WindowedLink.Split then
2829 ParentWindow:= SourceWindow;
2830
2831 if WindowedLink.ViewPort then
2832 // link always wants a new window
2833 OpenWindow( LinkedTopic,
2834 DefaultGroupIndex,
2835 ParentWindow,
2836 WindowedLink.Rect,
2837 true )
2838
2839 else if WindowedLink.GroupIndex <> DefaultGroupIndex then
2840 // link overrides group index
2841 OpenWindow( LinkedTopic,
2842 WindowedLink.GroupIndex,
2843 ParentWindow,
2844 WindowedLink.Rect,
2845 true )
2846 else
2847 // no special case
2848 OpenWindow( LinkedTopic,
2849 LinkedTopic.ContentsGroupIndex,
2850 ParentWindow,
2851 WindowedLink.Rect,
2852 true );
2853end;
2854
2855function TMainForm.ShowCodes: boolean;
2856begin
2857 if DebugShowCodesMI = nil then
2858 result := false
2859 else
2860 result := DebugShowCodesMI.Checked;
2861end;
2862
2863function TMainForm.ShowWordIndices: boolean;
2864begin
2865 if DebugShowWordSeparatorsMI = nil then
2866 result := false
2867 else
2868 result := DebugShowWordSeparatorsMI.Checked;
2869end;
2870
2871// Decode and display the topic for the given window.
2872Procedure TMainForm.DisplayTopicInWindow( Window: THelpWindow;
2873 FollowAutoLinks: boolean;
2874 KeepPosition: boolean );
2875var
2876 ImageIndices: TList;
2877 LinkIndex: longint;
2878 Link: THelpLink;
2879 WindowedHelpLink: TWindowedHelpLink;
2880 InternalHelpLink: TInternalHelpLink;
2881 HelpFile: THelpFile;
2882 LinkedTopic: TTopic;
2883 SourceTopic: TTopic;
2884 TopCharIndex: longint;
2885 i: longint;
2886 HighlightWordSequences: TList;
2887 FileIndex: longint;
2888Begin
2889 LogEvent(LogDisplay, 'DisplayTopicInWindow');
2890
2891 SetWaitCursor;
2892
2893 TopCharIndex := Window.View.TopCharIndex;
2894
2895 Window.View.Hide;
2896 Window.View.Clear;
2897 ImageIndices := TList.Create;
2898
2899 HelpFile := TopicFile( Window.Topic );
2900
2901 if ( AllFilesWordSequences.Count > 0 ) // ie we have done a search...
2902 and ViewHighlightSearchWordsMI.Checked then
2903 begin
2904 FileIndex := CurrentOpenFiles.IndexOf( HelpFile );
2905 HighlightWordSequences := AllFilesWordSequences[ FileIndex ];
2906 end
2907 else
2908 begin
2909 HighlightWordSequences := nil;
2910 end;
2911 TopicText.Clear;
2912 Window.Topic.GetText( HighlightWordSequences,
2913 ShowCodes,
2914 ShowWordIndices,
2915 TopicText,
2916 ImageIndices,
2917 Window.Highlights );
2918
2919 HelpFile.GetImages( ImageIndices, Window.Images );
2920
2921 if not HelpFile.NotesLoaded then
2922 LoadNotes( HelpFile );
2923 InsertNotesIntoTopicText( Window.Topic, TopicText );
2924
2925 Window.View.AddText( TopicText.AsPChar );
2926
2927 if KeepPosition then
2928 Window.View.TopCharIndex := TopCharIndex;
2929
2930 Window.View.Show;
2931
2932 if not KeepPosition then
2933 if Window.Highlights.Count > 0 then
2934 // ensure first search match is visible
2935 Window.View.MakeCharVisible( longint( Window.Highlights[ 0 ] ) );
2936
2937 Window.Caption := Window.Topic.Title;
2938 Window.BringToFront;
2939 Window.View.Focus;
2940
2941 // Take a copy of the topic, because the window in question could be changing
2942 // due to recursion!
2943 SourceTopic := Window.Topic;
2944
2945 if FollowAutoLinks then
2946 begin
2947 i := 0;
2948 for LinkIndex:= 0 to SourceTopic.Links.Count - 1 do
2949 begin
2950 Link:= SourceTopic.Links[ LinkIndex ];
2951 if Link is TWindowedHelpLink then
2952 begin
2953 WindowedHelpLink := Link as TWindowedHelpLink;
2954 if WindowedHelpLink.Automatic then
2955 begin
2956 if Link is TInternalHelpLink then
2957 begin
2958 InternalHelpLink := TInternalHelpLink( Link );
2959 LinkedTopic :=
2960 THelpFile( InternalHelpLink.HelpFile ).
2961 Topics[ InternalHelpLink.TopicIndex ];
2962 if LinkedTopic.Index = SourceTopic.Index then
2963 // what the - ? The link wants to open the same topic again
2964 continue;
2965 end;
2966
2967 FollowLink( Link, Window );
2968 Window := Window;
2969
2970 inc( i );
2971 // Note 1: it is possible to crash here if
2972 // e.g. window1 auto-opens window2 which auto-opens window1 with a different topic..
2973 // I can't think of a nice, easy way to detect this
2974 //
2975 // Note 2: If there is no group number specified
2976 // (ie. group = default = 0 ) then behaves as if viewport is set:
2977 // always opens another window.
2978 end;
2979 end;
2980 end;
2981 end;
2982
2983 ClearWaitCursor;
2984
2985 ImageIndices.Destroy;
2986End;
2987
2988Procedure TMainForm.MainFormOnCloseQuery (Sender: TObject;
2989 Var CanClose: Boolean);
2990Begin
2991 LogEvent(LogShutdown, '-------- Shutdown ----------');
2992
2993
2994 if OKToCloseFile then
2995 CloseFile
2996 else
2997 CanClose := false;
2998End;
2999
3000procedure TMainForm.DisplayTopic( Topic: TTopic );
3001begin
3002 if Navigating then
3003 exit;
3004
3005 UpdateCurrentNavigatePoint;
3006
3007 CloseWindows;
3008
3009 CurrentTopic:= Topic;
3010
3011 OpenWindow( CurrentTopic,
3012 CurrentTopic.ContentsGroupIndex,
3013 nil,
3014 nil,
3015 true );
3016 SetStatus( OpenedTopicMsg
3017 + IntToStr( Topic.Index ) );
3018
3019 Navigating:= true;
3020
3021 if ContentsOutline.SelectedNode = nil then
3022 ContentsOutline.SetSelectedObject( Topic )
3023 else if ContentsOutline.SelectedNode.Data <> Topic then
3024 ContentsOutline.SetSelectedObject( Topic );
3025
3026 SaveNavigatePoint;
3027
3028 Navigating:= false;
3029 // find in index...
3030 // find in search results...
3031
3032 EnableControls;
3033
3034 ShowWindows;
3035
3036// if Windows.Count > 0 then
3037// THelpWindow( Windows[ 0 ] ).View.Focus;
3038
3039end;
3040
3041// Make the all current help windows visible
3042Procedure TMainForm.ShowWindows;
3043begin
3044 ShowWindowList( Windows );
3045end;
3046
3047// Make the specified windows visible
3048Procedure TMainForm.ShowWindowList( WindowList: TList );
3049var
3050 i: integer;
3051 Window: THelpWindow;
3052begin
3053 for i := 0 to WindowList.Count - 1 do
3054 begin
3055 Window:= WindowList[ i ];
3056 Window.Show;
3057 ShowWindowList( Window.ChildWindows );
3058 end;
3059end;
3060
3061// Global search -----------------------------------------------------------
3062
3063Procedure TMainForm.GlobalSearchMIOnClick (Sender: TObject);
3064begin
3065 DoGlobalSearch( '' );
3066end;
3067
3068Procedure TMainForm.DoGlobalSearch( const SearchText: string );
3069Begin
3070 EnsureGlobalSearchFormLoaded;
3071
3072 GlobalSearchForm.ViewTopicCallback:= OnViewGlobalSearchTopic;
3073 GlobalSearchForm.Show;
3074 WinSetOwner( GlobalSearchForm.Frame.Handle, Frame.Handle );
3075
3076 if SearchText <> '' then
3077 begin
3078 GlobalSearchForm.SearchTextEdit.Text := SearchText;
3079 GlobalSearchForm.DoSearch;
3080 end;
3081End;
3082
3083Procedure TMainForm.OnViewGlobalSearchTopic( FileName: string;
3084 TopicIndex: longint );
3085var
3086 HelpFile: THelpFile;
3087begin
3088 HelpFile:= FindOpenHelpFile( FileName );
3089
3090 if HelpFile = nil then
3091 begin
3092 if OpenFile( Filename, '', false ) then
3093 begin
3094 HelpFile := CurrentOpenFiles[ 0 ];
3095 ClearHelpManager;
3096 end;
3097 end;
3098
3099 if HelpFile <> nil then
3100 if TopicIndex <> -1 then
3101 DisplayTopic( HelpFile.Topics[ TopicIndex ] );
3102
3103end;
3104
3105// Notes -----------------------------------------------------------
3106
3107Procedure TMainForm.GotoNoteButtonOnClick (Sender: TObject);
3108begin
3109 GotoCurrentNote;
3110end;
3111
3112Procedure TMainForm.EditNoteButtonOnClick (Sender: TObject);
3113Begin
3114 if NotesListBox.ItemIndex = -1 then
3115 exit;
3116 EditNote( NotesListBox.ItemIndex );
3117End;
3118
3119Procedure TMainForm.NotesListBoxOnItemFocus (Sender: TObject; Index: LongInt);
3120var
3121 Note: THelpNote;
3122Begin
3123 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3124 EnableNotesControls;
3125End;
3126
3127Procedure TMainForm.DeleteNoteButtonOnClick (Sender: TObject);
3128Begin
3129 if NotesListBox.ItemIndex = -1 then
3130 exit;
3131 DeleteNote( NotesListBox.ItemIndex );
3132End;
3133
3134Procedure TMainForm.AddBookmarkMIOnClick (Sender: TObject);
3135Begin
3136 AddBookmark;
3137End;
3138
3139Procedure TMainForm.AddNoteMIOnClick (Sender: TObject);
3140Begin
3141 AddNote;
3142End;
3143
3144// -----------------------------------------------------------
3145
3146Procedure TMainForm.FileCloseMIOnClick (Sender: TObject);
3147Begin
3148 if not OKToCloseFile then
3149 exit;
3150
3151 CloseFile;
3152End;
3153
3154Procedure TMainForm.SetStatus( Text: String );
3155begin
3156 StatusPanel.Caption:= Text;
3157 StatusPanel.Refresh;
3158end;
3159
3160Procedure TMainForm.ResetProgress;
3161begin
3162 ProgressBar.Position:= 0;
3163 ProgressBar.Hide;
3164end;
3165
3166Procedure TMainForm.CoolBarOnSectionResize (HeaderControl: THeaderControl;
3167 section: THeaderSection);
3168Begin
3169
3170End;
3171
3172Procedure TMainForm.CoolBarOnSectionClick (HeaderControl: THeaderControl;
3173 section: THeaderSection);
3174Begin
3175 case Section.Index of
3176 ciOpen:
3177 FileOpen;
3178 ciPrint:
3179 PrintTopics;
3180 ciNavigator:
3181 ShowLeftPanel := not ShowLeftPanel;
3182 ciBack:
3183 NavigateBack;
3184 ciForward:
3185 NavigateForward;
3186 ciAddNote:
3187 AddNote;
3188 ciAddBookmark:
3189 AddBookmark;
3190 ciPrevious:
3191 NavigatePreviousInContents;
3192 ciNext:
3193 NavigateNextInContents;
3194 ciGlobalSearch:
3195 DoGlobalSearch( '' );
3196 end;
3197
3198End;
3199
3200// ---------------- Notes ----------------------
3201
3202function TMainForm.FindOriginalNoteCharIndex( NoteCharIndex: longword;
3203 Topic: TTopic ): longword;
3204var
3205 NoteIndex: longint;
3206 Note: THelpNote;
3207begin
3208 Result := NoteCharIndex;
3209 for NoteIndex := 0 to Notes.Count - 1 do
3210 begin
3211 Note := Notes[ NoteIndex ];
3212 if Note.Topic = Topic then
3213 if Note.InsertPoint < NoteCharIndex then
3214 dec( Result, Note.InsertText.Length );
3215 end;
3216end;
3217
3218function TMainForm.FindActualNoteCharIndex( NoteCharIndex: longword;
3219 MaxNoteIndex: longword;
3220 Topic: TTopic ): longword;
3221var
3222 NoteIndex: longint;
3223 Note: THelpNote;
3224begin
3225 NoteIndex:= 0;
3226 Result:= NoteCharIndex;
3227 for NoteIndex:= 0 to MaxNoteIndex - 1 do
3228 begin
3229 Note:= Notes[ NoteIndex ];
3230 if Note.Topic = Topic then
3231 if Note.InsertPoint < NoteCharIndex then
3232 inc( Result, Note.InsertText.Length );
3233 end;
3234end;
3235
3236procedure TMainForm.RefreshNoteInsertInfo( NoteIndex: longword );
3237var
3238 Note: THelpNote;
3239begin
3240 Note:= Notes[ NoteIndex ];
3241
3242 if Note.Topic = nil then
3243 exit;
3244 with Note do
3245 begin
3246 InsertText.AssignString( '<color #'
3247 + IntToHex( Settings.Colors[ NotesTextColorIndex ], 6 )
3248 + '><link note'
3249 + IntToStr( NoteIndex )
3250 + '>' );
3251 InsertText.Add( Text );
3252 InsertText.AddString( '</color></link>' );
3253 end;
3254end;
3255
3256procedure TMainForm.ClearNotes;
3257begin
3258 DestroyListObjects( Notes );
3259 Notes.Clear;
3260end;
3261
3262procedure TMainForm.AddNote;
3263var
3264 Note: THelpNote;
3265 Window: THelpWindow;
3266begin
3267 Window := GetActiveWindow;
3268 if Window = nil then
3269 begin
3270 DoErrorDlg( AddNoteTitle,
3271 AddNoteCursorError );
3272 exit;
3273 end;
3274
3275 if Window.View.CursorIndex = -1 then
3276 begin
3277 DoErrorDlg( AddNoteTitle,
3278 AddNoteCursorError );
3279 exit;
3280 end;
3281
3282 // check that the note position isn't
3283 // within a note already
3284 if Window.View.LinkFromIndex( Window.View.CursorIndex ) <> '' then
3285 begin
3286 DoErrorDlg( AddNoteTitle,
3287 NoteWithinNoteError );
3288 exit;
3289 end;
3290
3291 // ask for note text
3292 NoteForm.DeleteNoteButton.Enabled := false; // can't delete it while creating!
3293 NoteForm.Text.Clear;
3294 if NoteForm.ShowModal <> mrOK then
3295 exit;
3296
3297 // store note data
3298 Note := THelpNote.Create;
3299 Note.Text.Assign( NoteForm.Text );
3300
3301 // compensate for existing notes
3302 if Window.View.CursorIndex <> -1 then
3303 Note.InsertPoint := FindOriginalNoteCharIndex( Window.View.CursorIndex, Window.Topic )
3304 else
3305 Note.InsertPoint := 0;
3306
3307 Note.Topic := Window.Topic;
3308
3309 Notes.Add( Note );
3310
3311 // redisplay topic
3312 DisplayTopicInWindow( Window,
3313 false, // don't follow links!
3314 true ); // keep position
3315 Window.View.SelectionStart := FindActualNoteCharIndex( Note.InsertPoint,
3316 Notes.Count - 1,
3317 Window.Topic );
3318 UpdateNotesDisplay;
3319
3320 SaveNotes;
3321
3322end;
3323
3324procedure TMainForm.DeleteNote( NoteIndex: longint );
3325var
3326 Note: THelpNote;
3327begin
3328 Note := Notes[ NoteIndex ];
3329 Notes.Delete( NoteIndex );
3330
3331 RefreshWindows( Windows );
3332
3333 Note.Destroy;
3334
3335 UpdateNotesDisplay;
3336
3337 SaveNotes;
3338end;
3339
3340Procedure TMainForm.EditNote( NoteIndex: longint );
3341var
3342 Note: THelpNote;
3343begin
3344 Note:= Notes[ NoteIndex ];
3345
3346 NoteForm.Text.Assign( Note.Text );
3347
3348 NoteForm.DeleteNoteButton.Enabled:= true;
3349
3350 if NoteForm.ShowModal = mrCancel then
3351 exit;
3352
3353 if NoteForm.ModalResult = cmDiscard then
3354 begin
3355 DeleteNote( NoteIndex );
3356 exit;
3357 end;
3358
3359 Note.Text.Assign( NoteForm.Text );
3360
3361 RefreshWindows( Windows );
3362
3363 UpdateNotesDisplay;
3364
3365 SaveNotes;
3366end;
3367
3368Procedure TMainForm.GotoCurrentNote;
3369var
3370 Note: THelpNote;
3371Begin
3372 if NotesListBox.ItemIndex = -1 then
3373 exit;
3374 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3375 DisplayTopic( Note.Topic );
3376End;
3377
3378// ---------------- Bookmarks ----------------------
3379
3380procedure TMainForm.OnBookmarksChanged( Sender: TObject );
3381begin
3382 BuildBookmarksMenu;
3383 UpdateBookmarksForm;
3384 SaveBookmarks;
3385end;
3386
3387procedure TMainForm.AddBookmark;
3388var
3389 Bookmark: TBookmark;
3390begin
3391 if Windows.Count = 0 then
3392 exit;
3393
3394 Bookmark := TBookmark.Create;
3395 SaveWindows( Windows, Bookmark.Windows, nil );
3396
3397 if ContentsOutline.SelectedNode <> nil then
3398 begin
3399 Bookmark.ContentsTopic:=
3400 ContentsOutline.SelectedNode.Data as TTopic;
3401 Bookmark.Name := Bookmark.ContentsTopic.Title;
3402 end
3403 else
3404 begin
3405 Bookmark.ContentsTopic:= nil;
3406 // Bookmark.Name := THelpWindow( Windows[ 0 ] ).Title;
3407 end;
3408
3409 Bookmarks.Add( Bookmark );
3410 OnBookmarksChanged( self );
3411end;
3412
3413Procedure TMainForm.BookmarksMenuItemClick( Sender: TObject );
3414var
3415 Tag: longint;
3416 MenuItem: TMenuItem;
3417 Bookmark: TBookmark;
3418begin
3419 MenuItem:= Sender as TMenuItem;
3420 Tag:= MenuItem.Tag;
3421 Bookmark := Bookmarks[ Tag ];
3422
3423 NavigateToBookmark( Bookmark );
3424end;
3425
3426Procedure TMainForm.NavigateToBookmark( Bookmark: TBookmark );
3427Begin
3428 UpdateCurrentNavigatePoint;
3429 NavigateToPoint( Bookmark );
3430 SaveNavigatePoint;
3431End;
3432
3433Procedure TMainForm.BuildBookmarksMenu;
3434var
3435 i: integer;
3436 Bookmark: TBookmark;
3437 MenuItem: TMenuItem;
3438begin
3439 DestroyListObjects( BookmarksMenuItems );
3440 BookmarksMenuItems.Clear;
3441
3442 if Bookmarks.Count > 0 then
3443 begin
3444 MenuItem:= TMenuItem.Create( self );
3445 MenuItem.Caption:= '-';
3446 BookmarksMenu.Add( MenuItem );
3447 BookmarksMenuItems.Add( MenuItem );
3448 end;
3449
3450 for i:= 0 to Bookmarks.Count -1 do
3451 begin
3452 Bookmark := Bookmarks[ i ];
3453 MenuItem:= TMenuItem.Create( self );
3454
3455 MenuItem.Caption:= Bookmark.Name;
3456 MenuItem.OnClick:= BookmarksMenuItemClick;
3457 MenuItem.Tag:= i;
3458 BookmarksMenu.Add( MenuItem );
3459 BookmarksMenuItems.Add( MenuItem );
3460 end;
3461end;
3462
3463Procedure TMainForm.UpdateBookmarksForm;
3464begin
3465 if Assigned( BookmarksForm ) then
3466 BookmarksForm.RefreshList;
3467end;
3468
3469Procedure TMainForm.ClearBookmarks;
3470begin
3471 ClearListAndObjects( Bookmarks );
3472 BuildBookmarksMenu;
3473 if Assigned( BookmarksForm ) then
3474 begin
3475 UpdateBookmarksForm; // clear bookmarks for next show
3476 BookmarksForm.Hide;
3477 end;
3478
3479end;
3480
3481procedure TMainForm.LoadBookmarks( HelpFile: THelpFile );
3482var
3483 Bookmark: TBookmark;
3484 BookmarksFile: TextFile;
3485 BookmarksFileName: string;
3486 S: string;
3487begin
3488 LogEvent(LogSettings, 'Load bookmarks for ' + HelpFile.Filename);
3489
3490 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3491
3492 if not FileExists( BookmarksFileName ) then
3493 exit;
3494
3495 FileMode := fmInput;
3496 AssignFile( BookmarksFile, BookmarksFileName );
3497 try
3498 Reset( BookmarksFile );
3499 try
3500 while not Eof( BookmarksFile ) do
3501 begin
3502 ReadLn( BookmarksFile, s );
3503 if trim( Uppercase( s ) ) = '[BOOKMARK]' then
3504 begin
3505 Bookmark:= TBookmark.Load( BookmarksFile, HelpFile );
3506 Bookmarks.Add( Bookmark );
3507 end;
3508 end;
3509 finally
3510 System.Close( BookmarksFile );
3511 end;
3512 except
3513 on e: exception do
3514 DoErrorDlg( LoadBookmarksTitle,
3515 LoadBookmarksError
3516 + e.message );
3517 end;
3518end;
3519
3520procedure TMainForm.SaveBookmarks;
3521var
3522 FileIndex: integer;
3523 HelpFile: THelpFile;
3524begin
3525 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3526 begin
3527 HelpFile := CurrentOpenFiles[ FileIndex ];
3528 SaveBookmarksForFile( HelpFile );
3529 end;
3530end;
3531
3532procedure TMainForm.SaveNotes;
3533var
3534 FileIndex: integer;
3535 HelpFile: THelpFile;
3536begin
3537 LogEvent(LogSettings, 'Save notes');
3538
3539 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3540 begin
3541 HelpFile := CurrentOpenFiles[ FileIndex ];
3542 SaveNotesForFile( HelpFile );
3543 end;
3544end;
3545
3546procedure TMainForm.SaveBookmarksForFile( HelpFile: THelpFile );
3547var
3548 i: integer;
3549 Bookmark: TBookmark;
3550 BookmarksFile: TextFile;
3551 BookmarksFileName: string;
3552 BookmarkCount: integer;
3553begin
3554 LogEvent(LogSettings, 'Save bookmarks for ' + HelpFile.Filename);
3555
3556 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3557
3558 BookmarkCount:= 0;
3559 for i:= 0 to Bookmarks.Count - 1 do
3560 begin
3561 Bookmark := Bookmarks[ i ];
3562
3563 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3564 inc( BookmarkCount );
3565 end;
3566
3567 if BookmarkCount = 0 then
3568 begin
3569 if FileExists( BookmarksFileName ) then
3570 DeleteFile( BookmarksFileName );
3571 exit;
3572 end;
3573
3574 AssignFile( BookmarksFile, BookmarksFileName );
3575 try
3576 Rewrite( BookmarksFile );
3577 try
3578 for i := 0 to Bookmarks.Count - 1 do
3579 begin
3580 Bookmark:= Bookmarks[ i ];
3581 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3582 begin
3583 WriteLn( BookmarksFile, '[Bookmark]' );
3584 Bookmark.Save( BookmarksFile );
3585 end;
3586 end;
3587 finally
3588 System.Close( BookmarksFile );
3589 end;
3590 except
3591 on e: exception do
3592 DoErrorDlg( SaveBookmarksTitle,
3593 SaveBookmarksError
3594 + e.message );
3595 end;
3596end;
3597
3598// Reads colors back from controls, in case they have changed by
3599// drag and drop
3600Procedure TMainForm.GetColors;
3601begin
3602 with Settings do
3603 begin
3604 Colors[ ContentsBackgroundColorIndex ] := ContentsOutline.Color;
3605 Colors[ ContentsTextColorIndex ] := ContentsOutline.PenColor;
3606 Colors[ IndexBackgroundColorIndex ] := IndexListBox.Color;
3607 Colors[ IndexTextColorIndex ] := IndexListBox.PenColor;
3608 Colors[ SearchBackgroundColorIndex ] := SearchResultsListBox.Color;
3609 Colors[ SearchTextColorIndex ] := SearchResultsListBox.PenColor;
3610 Colors[ NotesListBackgroundColorIndex ] := NotesListBox.Color;
3611 Colors[ NotesListTextColorIndex ] := NotesListBox.PenColor;
3612 end;
3613end;
3614
3615Procedure TMainForm.MainFormOnDestroy (Sender: TObject);
3616Begin
3617 LogEvent(LogShutdown, 'MainFormOnDestroy');
3618
3619 LogEvent(LogSettings, 'Write window position');
3620 WriteWindowPos( self );
3621
3622 LogEvent(LogSettings, 'Update colors');
3623 GetColors;
3624
3625 LogEvent(LogSettings, 'Save settings');
3626 SaveSettings;
3627 LogEvent(LogSettings, 'Save settings done');
3628
3629 // else- don't save position/size if doing own help
3630
3631 TopicText.Destroy;
3632
3633 LogEvent(LogShutdown, 'Destroy MRU menu items');
3634 MRUMenuItems.Destroy;
3635
3636 LogEvent(LogShutdown, 'Destroy navigate to menu items');
3637 NavigateToMenuItems.Destroy;
3638
3639 LogEvent(LogShutdown, 'Destroy pagehistory');
3640 PageHistory.Destroy;
3641
3642 LogEvent(LogShutdown, 'Clear/destroy notes');
3643 ClearNotes;
3644 Notes.Destroy;
3645
3646 LogEvent(LogShutdown, 'Clear/destroy bookmarks');
3647 ClearBookmarks;
3648 Bookmarks.Destroy;
3649
3650 LogEvent(LogShutdown, 'Destroy bookmark menu items');
3651 BookmarksMenuItems.Destroy;
3652
3653 LogEvent(LogShutdown, 'Destroy files/index/windows');
3654 CurrentOpenFiles.Destroy;
3655 DisplayedIndex.Destroy;
3656 Windows.Destroy;
3657
3658 // tell help manager(s) we are stopping.
3659 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
3660
3661 HelpManagerWindows.Destroy;
3662
3663 DestroyListObjects( Settings.MRUList );
3664 Settings.MRUList.Destroy;
3665
3666 // TODO rbri maybe we have to do this
3667 // Parameters.FilenamesParam.Destroy;
3668
3669 if g_CurrentLanguageFile <> nil then
3670 g_CurrentLanguageFile.Destroy;
3671
3672 LogEvent(LogShutdown, 'Close global filelist');
3673 GlobalFilelist.Destroy;
3674
3675 LogEvent(LogShutdown, 'Close shared memory');
3676 SharedMemory.Destroy;
3677
3678 AllFilesWordSequences.Destroy;
3679
3680 LogEvent(LogShutdown, 'MainFormOnDestroy done');
3681End;
3682
3683Procedure TMainForm.MainFormOnSetupShow (Sender: TObject);
3684Begin
3685 LogEvent(LogSettings, 'OnSetupShow');
3686 TabSet.TabIndex := 0;
3687 Notebook.PageIndex := 0;
3688End;
3689
3690Procedure TMainForm.OnException( Sender: TObject;
3691 E: Exception );
3692var
3693 TheText : string;
3694 F: TextFile;
3695 i: integer;
3696 HelpFile: THelpFile;
3697 LogFilename: string;
3698
3699begin
3700 LogFilename := GetLogFilesDir + CrashLogFileName;
3701
3702 LogException( E,
3703 LogFileName,
3704 'NewView',
3705 GetAppVersion,
3706 F );
3707
3708 if CurrentOpenFiles <> nil then
3709 begin
3710 WriteLn( F, 'Loaded files ('
3711 + IntToStr( CurrentOpenFiles.Count )
3712 + '):' );
3713 try
3714 for i := 0 to CurrentOpenFiles.Count - 1 do
3715 begin
3716 HelpFile := CurrentOpenFiles[ i ];
3717 WriteLn( F, HelpFile.Filename );
3718 end;
3719 except
3720 end;
3721 end;
3722 try
3723 if CurrentTopic <> nil then
3724 WriteLn( F, 'Last major topic index: '
3725 + IntToStr( CurrentTopic.Index ) );
3726 except
3727 // ignore exceptions if there isn't a valid current topic
3728 end;
3729 if Windows <> nil then
3730 begin
3731 WriteLn( F, 'Top-level open windows: '
3732 + IntToStr( Windows.Count ) );
3733 end;
3734
3735 System.Close( F );
3736
3737 TheText := ApplicationErrorA + StrCRLF
3738 + StrCRLF
3739 + E.Message + StrCRLF
3740 + ApplicationErrorB
3741 + LogFilename
3742 + ')' + StrCRLF
3743 + StrCRLF
3744 + ApplicationErrorC
3745 + StrCRLF;
3746
3747 if DoYesNoDlg( ApplicationErrorTitle,
3748 TheText ) then
3749 begin
3750 // exit a bit more nicely - remove ourselves from the global filelist.
3751 GlobalFilelist.RemoveWindowFiles( Frame.Handle );
3752 Application.Terminate;
3753 end;
3754end;
3755
3756// give our main window a unique class name we can find
3757procedure TMainForm.GetClassData(var ClassData: TClassData);
3758Begin
3759 inherited GetClassData( ClassData );
3760 ClassData.ClassName := MAIN_WINDOW_CLASS_NAME;
3761End;
3762
3763// Position the window offset from existing top help window (if any)
3764Procedure TMainForm.PositionWindow;
3765var
3766 hTopWindow: HWND;
3767 TopHelpWindowPos: SWP;
3768 Offset: longint;
3769Begin
3770 hTopWindow := FindTopFormWindow( MAIN_WINDOW_CLASS_NAME );
3771
3772 if hTopWindow <> NULLHANDLE then
3773 begin
3774 // found an existing help window, find it's location
3775 if WinQueryWindowPos(
3776 hTopWindow,
3777 TopHelpWindowPos ) then
3778 begin
3779 if ( TopHelpWindowPos.FL and ( SWP_MINIMIZE or SWP_MINIMIZE ) ) > 0 then
3780 Begin
3781 // window is maximized or minimised, so get the restore position from window USHORTs
3782 TopHelpWindowPos.x := WinQueryWindowUShort( hTopWindow, QWS_XRESTORE );
3783 TopHelpWindowPos.Y := WinQueryWindowUShort( hTopWindow, QWS_YRESTORE );
3784 end;
3785
3786 // offset new window by height of title bar + border
3787 Offset := Screen.SystemMetrics( smCyTitleBar )
3788 + Screen.SystemMetrics( smCySizeBorder );
3789 Left := TopHelpWindowPos.x + Offset;
3790 Bottom := TopHelpWindowPos.y - Offset;
3791
3792 // I guess I am leaving width/height out for compatibility...?
3793 end;
3794 end;
3795end;
3796
3797Procedure TMainForm.OnHelp( context: THelpContext;
3798 var Result: Boolean );
3799begin
3800 if OwnHelpMode then
3801 begin
3802 // we are viewing the help file now - display our own help!
3803 PostMsg( Handle, NHM_TOPIC_BY_RESOURCE_ID, context, 0 );
3804 exit;
3805 end;
3806
3807 Application.HelpContext( context );
3808end;
3809
3810Procedure TMainForm.MainFormOnCreate (Sender: TObject);
3811var
3812 tmpCmdLine: AnsiString;
3813Begin
3814 LogEvent(LogStartup, 'MainFormOnCreate');
3815
3816 StartingUp := true;
3817
3818 SharedMemory := AccessSharedMemory;
3819 GlobalFilelist := TGlobalFilelist.Create;
3820
3821 // parse parameters into Parameters object
3822 tmpCmdLine := nativeOS2GetCmdLineParameter;
3823 CmdLineParameters := TCmdLineParameters.Create;
3824 CmdLineParameters.parseCmdLine(tmpCmdLine);
3825
3826 Application.HelpFile := CmdLineParameters.GetOwnHelpFilename; // OWN_HELP_MARKER;
3827 Application.OnHelp := OnHelp;
3828
3829 RegisterForLanguages( OnLanguageEvent );
3830
3831 // if debug is not enabled, get rid of the debug menu and separator.
3832 if not CmdLineParameters.isDebugEnabled then
3833 begin
3834 ToolsDebugSep.Destroy;
3835 ToolsDebugMenu.Destroy;
3836 DebugShowCodesMI := nil;
3837 DebugShowWordSeparatorsMI := nil;
3838 end;
3839
3840 // set up globals for Exec
3841 ExecViaSession := true;
3842 AsynchExec := true;
3843
3844 // set up form icons
3845 Forms.FormIconResourceID := 1;
3846
3847 Application.OnException := OnException;
3848
3849 ContentsOutline.SmoothScroll := false;
3850
3851 LogEvent(LogStartup, 'Choosing default font: Trying WarpSans');
3852
3853 Font := GetNiceDefaultFont;
3854
3855 // Set the menu fonts, because they remember their own specific one
3856 MainMenu.Font := Screen.MenuFont;
3857 ViewPopupMenu.Font := Screen.MenuFont;
3858
3859 // NOTE: SPCC will copy this font to TApplication
3860 // in TApplication.Run
3861
3862 LogEvent(LogStartup, 'Starting NewView: MainFormOnCreate');
3863
3864 Application.OnHint := OnHint;
3865
3866 StartMem := MemAvailBytes;
3867
3868 DisplayedIndex := TStringList.Create;
3869
3870 HelpManagerWindows := TList.Create;
3871
3872 AllFilesWordSequences := TList.Create;
3873
3874 CurrentOpenFiles := TList.Create;
3875 Notes := TList.Create;
3876 Bookmarks := TList.Create;
3877 BookmarksMenuItems := TList.Create;
3878 Windows := TList.Create;
3879
3880 TopicText := TAString.Create;
3881
3882 Navigating := false;
3883 InIndexSearch := false;
3884 SettingFont := false;
3885
3886 PageHistory := TStringList.Create;
3887 CurrentHistoryIndex := -1;
3888
3889 Settings.MRUList := TList.Create;
3890
3891 MRUMenuItems := TList.Create;
3892 NavigateToMenuItems := TList.Create;
3893
3894 LogEvent(LogSettings, 'Loading settings');
3895
3896 LoadSettings;
3897 SetShowLeftPanel( ShowLeftPanel ); // update menu
3898
3899 // load default strings
3900 LogEvent(LogSettings, 'Loading language');
3901
3902 // the user likes to have english
3903 // the normal automatic will fall back to
3904 // the environment setting but in the special
3905 // case we have to start the default
3906 if CmdLineParameters.getLanguage = 'en' then
3907 begin
3908 LoadLanguage('');
3909 end
3910 else
3911 begin
3912 if CmdLineParameters.getLanguage <> '' then
3913 begin
3914 if not LoadAutoLanguage('newview', CmdLineParameters.getLanguage) then
3915 begin
3916 LoadDefaultLanguage('newview');
3917 end
3918 end
3919 else
3920 begin
3921 LoadDefaultLanguage('newview');
3922 end;
3923 end;
3924
3925 LogEvent(LogSettings, 'Applying settings');
3926 ApplySettings;
3927
3928 // default position is centered..
3929 LogEvent(LogSettings, 'Set default position');
3930 if Width > Screen.Width then
3931 Width := Screen.Width;
3932 if Height > Screen.Height then
3933 Height := Screen.Height;
3934 Left := ( Screen.Width - Width ) div 2;
3935 Bottom := ( Screen.Height - Height ) div 2;
3936
3937 LogEvent(LogSettings, 'ReadWindowPos');
3938 ReadWindowPos( Self );
3939
3940 PositionWindow;
3941
3942 LogEvent(LogSettings, 'Creating MRU list');
3943
3944 CreateMRUMenuItems;
3945
3946 CloseFile;
3947
3948 LogEvent(LogStartup, 'OnCreate done');
3949
3950 if CmdLineParameters.getWindowPositionFlag then
3951 begin
3952 SmartSetWindowPos( self,
3953 CmdLineParameters.getWindowPosition.Left,
3954 CmdLineParameters.getWindowPosition.Bottom,
3955 CmdLineParameters.getWindowPosition.Width,
3956 CmdLineParameters.getWindowPosition.Height,
3957 false );
3958 end;
3959
3960 LogEvent(LogStartup, 'MainFormOnCreate Done');
3961End;
3962
3963Procedure TMainForm.ApplySettings;
3964var
3965 ToolbarBitmap: TBitmap;
3966begin
3967 ContentsOutline.Color:= Settings.Colors[ ContentsBackgroundColorIndex ];
3968 ContentsOutline.PenColor:= Settings.Colors[ ContentsTextColorIndex ];
3969 ContentsOutline.TreeLineColor:= Settings.Colors[ ContentsLinesColorIndex ];
3970 IndexListBox.Color:= Settings.Colors[ IndexBackgroundColorIndex ];
3971 IndexListBox.PenColor:= Settings.Colors[ IndexTextColorIndex ];
3972 SearchResultsListBox.Color:= Settings.Colors[ SearchBackgroundColorIndex ];
3973 SearchResultsListBox.PenColor:= Settings.Colors[ SearchTextColorIndex ];
3974 NotesListBox.Color:= Settings.Colors[ NotesListBackgroundColorIndex ];
3975 NotesListBox.PenColor:= Settings.Colors[ NotesListTextColorIndex ];
3976
3977 SettingFont := true;
3978 Notebook.ParentFont := true;
3979 ContentsOutline.ParentFont := true;
3980 IndexListBox.ParentFont := true;
3981 SearchResultsListBox.ParentFont := true;
3982 NotesListBox.ParentFont := true;
3983 TabSet.ParentFont := true;
3984 Coolbar.ParentFont := true;
3985 if Settings.Fonts[ ApplicationFontIndex ] <> nil then
3986 Font := Settings.Fonts[ ApplicationFontIndex ]
3987 else
3988 Font := GetNiceDefaultFont;
3989 SettingFont := false;
3990
3991 Coolbar.BackgroundBitmap := nil;
3992 if FileExists( Settings.ToolbarBackgroundImageFilename ) then
3993 begin
3994 ToolbarBitmap:= TBitmap.Create;
3995 try
3996 ToolbarBitmap.LoadFromFIle( Settings.ToolbarBackgroundImageFilename );
3997 Coolbar.BackgroundBitmap := ToolbarBitmap;
3998 except
3999 end;
4000 ToolbarBitmap.Destroy;
4001 end;
4002
4003 CoolBar.ShowImages := Settings.ToolbarStyle in [ tsImages, tsImagesAndText ];
4004 CoolBar.ShowText := Settings.ToolbarStyle in [ tsText, tsImagesAndText ];
4005
4006 CoolBar.SetMinConstButtonWidth;
4007
4008 DisplayPanel.Color := Settings.Colors[ TopicBackgroundColorIndex ];
4009
4010 SetupViews( Windows );
4011end;
4012
4013// Setup the rich text views in the specified windows (e.g for changing global settings)
4014Procedure TMainForm.SetupViews( WindowList: TList );
4015var
4016 WindowIndex: longint;
4017 Window: THelpWindow;
4018begin
4019 for WindowIndex := 0 to WindowList.Count - 1 do
4020 begin
4021 Window := WindowList[ WindowIndex ];
4022 Window.SetupRTView;
4023 SetupViews( Window.ChildWindows );
4024 end;
4025end;
4026
4027Procedure TMainForm.PostHelpManagerMessage( MessageType: ULONG;
4028 Param1: long;
4029 Param2: long );
4030var
4031 i: longint;
4032begin
4033 for i := 0 to HelpManagerWindows.Count - 1 do
4034 PostMsg( HWND( HelpManagerWindows[ i ] ),
4035 MessageType,
4036 Param1,
4037 Param2 );
4038end;
4039
4040Procedure TMainForm.ClearHelpManager;
4041Begin
4042 if not CmdLineParameters.getHelpManagerFlag then
4043 exit;
4044
4045 // tell the help manager(s) we are no longer playing with them
4046 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
4047
4048 CmdLineParameters.setHelpManagerFlag(false);
4049
4050 HelpManagerWindows.Clear;
4051End;
4052
4053Procedure TMainForm.MainFormOnShow (Sender: TObject);
4054Begin
4055 EnableCallstackLogging( true );
4056
4057 LogEvent(LogStartup, 'MainFormOnShow');
4058
4059 if CmdLineParameters.getOwnerWindow <> NULLHANDLE then
4060 begin
4061 LogEvent(LogStartup, 'Setting owner: '
4062 + IntToStr( CmdLineParameters.getOwnerWindow));
4063 WinSetOwner( Frame.Handle,
4064 CmdLineParameters.getOwnerWindow );
4065
4066 end;
4067
4068 if CmdLineParameters.getHelpManagerFlag then
4069 begin
4070 LogEvent(LogStartup, ' Help Manager Title: '
4071 + StrPasWithLength( pSharedStruct ^. Title,
4072 SHARED_STRUCT_TITLE_SIZE ) );
4073 HelpManagerVersion := StrPasWithLength( pSharedStruct ^. Version,
4074 SHARED_STRUCT_VERSION_SIZE );
4075 LogEvent(LogStartup, ' Help Manager Version: ' + HelpManagerVersion );
4076
4077 end;
4078
4079 CoolBar.SetMinConstButtonWidth;
4080
4081 LogEvent(LogStartup, 'Post WM_OPENED');
4082
4083 ResetProgress;
4084
4085 AddShortcut( kbF11, kbF11 ); // prev in contents
4086 AddShortcut( kbF12, kbF12 ); // next in contents
4087 AddShortcut( kbF7, kbF7 ); // back
4088 AddShortcut( kbF8, kbF8 ); // forward
4089 AddShortcut( kbCtrlCLeft, kbCtrlCLeft ); // back
4090
4091 PostMsg( Handle, WM_OPENED, 0, 0 );
4092End;
4093
4094Procedure TMainForm.DisplaySelectedContentsTopic;
4095var
4096 Topic: TTopic;
4097Begin
4098 if ContentsOutline.SelectedNode = nil then
4099 exit;
4100 Topic := ContentsOutline.SelectedNode.Data as TTopic;
4101 DisplayTopic( Topic );
4102End;
4103
4104// Check that the HELP and BOOKSHELF environment variables
4105// are defined (as they should be on any working OS/2 system).
4106// Show a warning message if not.
4107Procedure TMainForm.CheckEnvironmentVars;
4108var
4109 HelpOK: boolean;
4110 BookshelfOK: boolean;
4111 ErrorText: string;
4112begin
4113 HelpOK := GetEnv( HelpPathEnvironmentVar ) <> '';
4114 BookshelfOK := GetEnv( BookshelfEnvironmentVar ) <> '';
4115 if HelpOK and BookshelfOK then
4116 // all ok.
4117 exit;
4118
4119 // One or both missing
4120
4121 ErrorText := '';
4122 if not BookshelfOK then
4123 ErrorText := ErrorText
4124 + EnvironmentVarUndefined
4125 + BookshelfEnvironmentVar
4126 + StrCRLF;
4127
4128 if not HelpOK then
4129 ErrorText := ErrorText
4130 + EnvironmentVarUndefined
4131 + HelpPathEnvironmentVar
4132 + StrCRLF;
4133
4134 DoWarningDlg( EnvironmentVarErrorTitle,
4135 EnvironmentVarError
4136 + StrCRLF
4137 + StrCRLF
4138 + ErrorText );
4139
4140end;
4141
4142Procedure LoadSupportDLL;
4143begin
4144 try
4145 LoadDLLFunction( 'newview.dll',
4146 'LZWDECOMPRESSBLOCK',
4147 hNewViewDLL,
4148 pointer( LZWDecompressBlock ) );
4149 except
4150 on E: Exception do
4151 begin
4152 DoErrorDlg( 'DLL Error',
4153 E.Message );
4154 LZWDecompressBlock := nil;
4155 end;
4156 end;
4157end;
4158
4159Procedure TMainForm.WMOpened( Var Msg: TMessage );
4160var
4161 Filenames: TStringList;
4162 M1: longword;
4163 OpenFirstTopic: boolean;
4164begin
4165 if Application.HelpFile = '' then
4166 DoErrorDlg( 'NewView Help', 'NewView help file not found' );
4167
4168 LoadSupportDLL;
4169
4170 LogEvent(LogStartup, 'WMOpened: SetLayout');
4171
4172 if CmdLineParameters.getHelpManagerFlag then
4173 FShowLeftPanel := Settings.ShowLeftPanel_Help
4174 else
4175 FShowLeftPanel := Settings.ShowLeftPanel_Standalone;
4176
4177 SetLayout;
4178
4179// ProfileEvent( 'Apply settings' );
4180// ApplySettings;
4181
4182 LogEvent(LogStartup, 'Enable controls');
4183 EnableControls;
4184
4185// ProfileEvent( 'ReadWindowPos' );
4186// ReadWindowPos( Self );
4187
4188 LogEvent(LogStartup, 'Finish paint');
4189 Update;
4190
4191 if not CmdLineParameters.getHelpManagerFlag then
4192 begin
4193 LogEvent(LogStartup, 'Check environment vars');
4194 CheckEnvironmentVars;
4195
4196 if CmdLineParameters.getShowUsageFlag then
4197 begin
4198 LogEvent(LogStartup, 'Showing usage');
4199 ShowUsage;
4200 end;
4201 end;
4202
4203 HelpManagerWindows.Add( pointer( CmdLineParameters.getHelpManagerWindow ) );
4204
4205 if CmdLineParameters.getFileNames(Settings.StartupHelp) <> '' then
4206 begin
4207 // open specified files
4208 Filenames := TStringList.Create;
4209
4210 StrExtractStringsIgnoreEmpty(Filenames, cmdLineParameters.getFileNames(Settings.StartupHelp), ['+'], #0);
4211
4212 LogEvent(LogStartup, 'Call OpenFiles');
4213
4214 OpenFirstTopic := true;
4215
4216 if ( CmdLineParameters.getSearchText <> '' )
4217 OR CmdLineParameters.getSearchFlag
4218 OR CmdLineParameters.getHelpManagerFlag
4219 then
4220 // if we're going to search, don't open first topic
4221 // don't open first topic if we're online help
4222 // in case we are wanting to show a specific topic
4223 // - saves time/flicker
4224 OpenFirstTopic := false;
4225
4226 OpenFiles( Filenames,
4227 CmdLineParameters.getWindowTitle,
4228 OpenFirstTopic );
4229
4230 Filenames.Destroy;
4231
4232 if not CmdLineParameters.getSearchFlag
4233 and not CmdLineParameters.getGlobalSearchFlag
4234 and (CmdLineParameters.getSearchText <> '') then
4235 begin
4236 // search in contents only!
4237 LogEvent(LogStartup, 'Do startup topic search for: "' + CmdLineParameters.getSearchText + '"');
4238
4239 StartupTopicSearch( CmdLineParameters.getSearchText );
4240 end
4241 else if CmdLineParameters.getSearchFlag then
4242 begin
4243 // search in specified files
4244 LogEvent(LogStartup, 'Do search for topic');
4245 DisplaySearch;
4246
4247 SearchFor( CmdLineParameters.getSearchText );
4248 end;
4249 end;
4250
4251 if NOT CmdLineParameters.getShowUsageFlag
4252 AND CmdLineParameters.getGlobalSearchFlag then
4253 begin
4254 // Global search
4255 LogEvent(LogStartup, 'Do global search: ' + CmdLineParameters.getSearchText);
4256 DoGlobalSearch( CmdLineParameters.getSearchText );
4257 end;
4258
4259 LogEvent(LogStartup, 'Open finished');
4260
4261 if CmdLineParameters.getHelpManagerFlag then
4262 begin
4263 // Tell helpmanager(s) our window handle
4264 PostHelpManagerMessage( NHM_VIEWER_READY,
4265 Handle,
4266 0 );
4267 end;
4268
4269 M1:= MemAvail;
4270
4271 StartingUp := false;
4272
4273 LogEvent(LogStartup, 'RUN PROGRAM');
4274end;
4275
4276Procedure TMainForm.MainFormOnResize (Sender: TObject);
4277Begin
4278 if not Visible then
4279 exit;
4280 if Handle = 0 then
4281 exit;
4282
4283 SetLayout;
4284
4285End;
4286
4287Function TMainForm.GetShowLeftPanel: boolean;
4288begin
4289 Result := FShowLeftPanel;
4290end;
4291
4292Procedure TMainForm.SetShowLeftPanel( Value: boolean );
4293begin
4294 ShowLeftPanelMI.Checked := Value;
4295 if Value = FShowLeftPanel then
4296 exit;
4297 FShowLeftPanel := Value;
4298 if FShowLeftPanel then
4299 NotebookOnPageChanged( self ) // make sure page is updated
4300 else
4301 FocusFirstHelpWindow;
4302 EnableControls;
4303 SetLayout;
4304end;
4305
4306Procedure TMainForm.VSplitBarOnChange (NewSplit: LongInt);
4307Begin
4308 if VSplitBar.Left < 30 then
4309 begin
4310 ShowLeftPanel := false
4311 end
4312 else
4313 begin
4314 Settings.LeftPanelWidth := VSplitBar.Left;
4315 ShowLeftPanel := true;
4316 end;
4317 SetLayout;
4318End;
4319
4320// Set the layout of the main form
4321Procedure TMainForm.SetLayout;
4322var
4323 RealClientHeight : longint;
4324 CoolbarSpace: longint;
4325 TextHeight: longint;
4326Begin
4327 TextHeight := Canvas.TextHeight( 'S' );
4328 Tabset.Height := TextHeight + 5;
4329
4330 Coolbar.Visible := Settings.ToolbarStyle <> tsNone;
4331
4332 case Settings.ToolbarStyle of
4333 tsImages:
4334 Coolbar.Height := Coolbar.Sections[ 0 ].Width;
4335 tsText:
4336 Coolbar.Height := TextHeight + 5;
4337 tsImagesAndText:
4338 CoolBar.Height := ButtonImages.GetBitmapReference(0).Width + TextHeight + 10;
4339 end;
4340
4341 CoolbarSpace := Coolbar.Height;
4342 if not Coolbar.Visible then
4343 CoolbarSpace := 0;
4344
4345 StatusPanel.Left:= 0;
4346 StatusPanel.Width:= ClientWidth div 2 - 2;
4347 StatusPanel.Height := TextHeight + 2;
4348
4349 ProgressPanel.Left:= ClientWidth div 2 + 2;
4350 ProgressPanel.Width:= ClientWidth - ProgressPanel.Left;
4351 ProgressPanel.Height := TextHeight + 2;
4352
4353 Notebook.Bottom := StatusPanel.Height + 3;
4354 VSplitBar.Bottom := Notebook.Bottom;
4355 DisplayPanel.Bottom := Notebook.Bottom;
4356
4357 RealClientHeight := ClientHeight
4358 - CoolbarSpace
4359 - Notebook.Bottom;
4360
4361 LogEvent(LogStartup, 'TMainForm.SetLayout');
4362 LogEvent(LogStartup, ' RealClientHeight: ' + IntToStr( RealClientHeight ));
4363
4364 LogEvent(LogStartup, ' Form Width: ' + IntToStr( Width ));
4365 LogEvent(LogStartup, ' Form Height: ' + IntToStr( Height ) );
4366 LogEvent(LogStartup, ' Form ClientWidth: ' + IntToStr( ClientWidth ) );
4367 LogEvent(LogStartup, ' Form ClientHeight: ' + IntToStr( ClientHeight ) );
4368 LogEvent(LogStartup, ' CoolBar.Height: ' + IntToStr( CoolBar.Height ) );
4369 LogEvent(LogStartup, ' CoolBar.Bottom: ' + IntToStr( CoolBar.Bottom ) );
4370
4371 if CurrentOpenFiles.Count > 0 then
4372 VSplitBar.Width := Max( 5, Canvas.TextWidth( ' ' ) )
4373 else
4374 VSplitBar.Width := 0;
4375
4376 VSplitBar.Height := RealClientHeight;
4377
4378 if Settings.LeftPanelWidth > ClientWidth - 50 then
4379 Settings.LeftPanelWidth := ClientWidth - 50;
4380 if Settings.LeftPanelWidth < 50 then
4381 Settings.LeftPanelWidth := 50;
4382
4383 if ShowLeftPanel then
4384 begin
4385 VSplitBar.Left := Settings.LeftPanelWidth;
4386 VSplitBar.Hint := SplitBarDblClickToHide;
4387 end
4388 else
4389 begin
4390 VSplitBar.Left := 0;
4391 VSplitBar.Hint := SplitBarDblClickToShow;
4392 end;
4393
4394 Tabset.Left := 0;
4395 Tabset.Width := VSplitBar.Left;
4396 Tabset.Bottom := ClientHeight
4397 - CoolbarSpace
4398 - Tabset.Height;
4399
4400 Notebook.Left := 0;
4401 Notebook.Width := VSplitBar.Left;
4402 Notebook.Height := RealClientHeight
4403 - Tabset.Height
4404 - 3;
4405
4406 DisplayPanel.Left:= VSplitBar.Left + VSplitBar.Width;
4407 DisplayPanel.Width:= ClientWidth - DisplayPanel.Left;
4408 DisplayPanel.Height := RealClientHeight;
4409 LogEvent(LogStartup, ' DisplayPanel.Width: ' + IntToStr( DisplayPanel.Width ) );
4410 LogEvent(LogStartup, ' DisplayPanel.Height: ' + IntToStr( DisplayPanel.Height ) );
4411 LogEvent(LogStartup, ' DisplayPanel.Bottom: ' + IntToStr( DisplayPanel.Bottom ) );
4412
4413 ProgressBar.Left:= 1;
4414 ProgressBar.Bottom:= 1;
4415 ProgressBar.Width:= ProgressPanel.Width - 2;
4416 ProgressBar.Height:= ProgressPanel.Height - 2;
4417
4418 // Layout the visible help windows also
4419 LayoutWindowList( Windows );
4420End;
4421
4422// Lay out the specified list of help windows
4423Procedure TMainForm.LayoutWindowList( WindowList: TList );
4424var
4425 Window: THelpWindow;
4426 WindowIndex: longint;
4427begin
4428 for WindowIndex:= 0 to WindowList.Count - 1 do
4429 begin
4430 Window:= WindowList[ WindowIndex ];
4431 Window.SetLayout;
4432 end;
4433end;
4434
4435Procedure TMainForm.FindNextMIOnClick (Sender: TObject);
4436begin
4437 if FindText = '' then
4438 begin
4439 FindMIOnClick( sender );
4440 exit;
4441 end;
4442
4443 if GetActiveWindow = nil then
4444 begin
4445 DoErrorDlg( FindTitle,
4446 FindSelectWindowError );
4447 exit;
4448 end;
4449
4450 DoFind( foFromCurrent );
4451end;
4452
4453Procedure TMainForm.DoFind( FindOrigin: TFindOrigin );
4454var
4455 Window: THelpWindow;
4456begin
4457 SetWaitCursor;
4458 Window := GetActiveWindow;
4459 if not Window.View.Find( FindOrigin, FindText ) then
4460 begin
4461 SetStatus( TextNotFoundMsg );
4462 Beep( 1000, 100 );
4463 end;
4464 ClearWaitCursor;
4465End;
4466
4467Procedure TMainForm.FindMIOnClick (Sender: TObject);
4468begin
4469 if GetActiveWindow = nil then
4470 begin
4471 DoErrorDlg( FindTitle,
4472 FindSelectWindowError );
4473 exit;
4474 end;
4475 if not DoInputQuery( FindTitle,
4476 FindPrompt,
4477 FindText ) then
4478 exit;
4479
4480 DoFind( foFromStart );
4481End;
4482
4483Procedure TMainForm.IndexSearchEditOnScan (Sender: TObject;
4484 Var KeyCode: TKeyCode);
4485Begin
4486 case KeyCode of
4487 kbCUp:
4488 begin
4489 if IndexListBox.ItemIndex > 0 then
4490 IndexListBox.ItemIndex:= IndexListBox.ItemIndex - 1;
4491 KeyCode:= kbNull;
4492 end;
4493
4494 kbCDown:
4495 begin
4496 if IndexListBox.ItemIndex < IndexListBox.Items.Count - 1 then
4497 IndexListBox.ItemIndex:= IndexListBox.ItemIndex + 1;
4498 KeyCode:= kbNull;
4499 end;
4500
4501 kb_VK + VK_NEWLINE:
4502 begin
4503 DisplaySelectedIndexTopic;
4504 end;
4505 end;
4506
4507End;
4508
4509Procedure TMainForm.IndexSearchEditOnChange (Sender: TObject);
4510var
4511 MatchIndex: longint;
4512 IndexINdex: longint;
4513 SearchText: string;
4514Begin
4515 if InIndexSearch then
4516 exit;
4517
4518 MatchIndex:= -1;
4519 SearchText:= trim( IndexSearchEdit.Text );
4520 for IndexIndex:= 0 to DisplayedIndex.Count - 1 do
4521 begin
4522 if StrStartsWithIgnoringCase( SearchText, DisplayedIndex[ IndexIndex ] ) then //IndexEntry ) then
4523 begin
4524 MatchIndex:= IndexIndex;
4525 break;
4526 end;
4527 end;
4528
4529 if MatchIndex = -1 then
4530 exit;
4531
4532 InIndexSearch:= true;
4533
4534 if IndexListBox.ItemIndex <> MatchIndex then
4535 IndexListBox.ItemIndex:= MatchIndex;
4536
4537 InIndexSearch:= false;
4538End;
4539
4540Procedure TMainForm.FileInformationMIOnClick (Sender: TObject);
4541var
4542 FileIndex: longint;
4543 HelpFile: THelpFile;
4544
4545 TotalTopicCount: longint;
4546 TotalIndexCount: longint;
4547 TotalFileSize: longint;
4548
4549Begin
4550 TotalTopicCount := 0;
4551 TotalIndexCount := 0;
4552 TotalFileSize := 0;
4553
4554 with InformationForm.InformationMemo do
4555 begin
4556 BeginUpdate;
4557 Lines.Clear;
4558 Lines.Add( FilesInfoTitle );
4559 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4560 begin
4561 HelpFile := CurrentOpenFiles[ FileIndex ];
4562
4563 Lines.Add( FilesInfoFilename + HelpFile.FileName );
4564 Lines.Add( FilesInfoFileTitle
4565 + HelpFile.Title );
4566 Lines.Add( FilesInfoTopicCount
4567 + IntToStr( HelpFile.TopicCount ) );
4568 Lines.Add( FilesInfoIndexCount
4569 + IntToStr( HelpFile.Index.Count ) );
4570 Lines.Add( FilesInfoDictionaryCount
4571 + IntToStr( HelpFile.DictionaryCount ) );
4572 Lines.Add( FilesInfoFileSize
4573 + IntToStr( HelpFile.FileSize ) );
4574
4575 inc( TotalTopicCount, HelpFile.TopicCount );
4576 inc( TotalIndexCount, HelpFile.Index.Count );
4577 inc( TotalFileSize, HelpFile.FileSize );
4578
4579 end;
4580
4581 Lines.Add( '' );
4582 Lines.Add( FilesInfoTotalTopicCount
4583 + IntToStr( TotalTopicCount ) );
4584 Lines.Add( FilesInfoTotalIndexCount
4585 + IntToStr( TotalIndexCount ) );
4586 Lines.Add( FilesInfoTotalFileSize
4587 + IntToStr( TotalFileSize ) );
4588 Lines.Add( '' );
4589
4590 EndUpdate;
4591 end;
4592 InformationForm.ShowModal;
4593End;
4594
4595Procedure TMainForm.DisplaySelectedSearchResultTopic;
4596var
4597 Topic: TTopic;
4598Begin
4599 if SearchResultsListBox.ItemIndex = -1 then
4600 exit;
4601 if SelectedObject( SearchResultsListBox ) = nil then
4602 // the "no results" place holder
4603 exit;
4604 Topic := SelectedObject( SearchResultsListBox ) as TTopic;
4605 DisplayTopic( Topic );
4606End;
4607
4608Procedure TMainForm.SearchTextEditOnScan (Sender: TObject;
4609 Var KeyCode: TKeyCode);
4610Begin
4611 case KeyCode of
4612 kbCUp:
4613 begin
4614 if SearchResultsListBox.ItemIndex > 0 then
4615 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex - 1;
4616 KeyCode := kbNull;
4617 SearchResultsListBox.Focus;
4618 end;
4619
4620 kbCDown:
4621 begin
4622 if SearchResultsListBox.ItemIndex < SearchResultsListBox.Items.Count - 1 then
4623 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex + 1;
4624 KeyCode := kbNull;
4625 SearchResultsListBox.Focus;
4626 end;
4627 end;
4628End;
4629
4630Procedure TMainForm.SearchButtonOnClick (Sender: TObject);
4631Begin
4632 DoSearch;
4633End;
4634
4635// Matches old stupid View algorithm
4636Procedure TMainForm.StartupTopicSearch( const SearchText: string );
4637var
4638 i: longint;
4639 HelpFile: THelpFile;
4640 Topic: TTopic;
4641 // s: string;
4642begin
4643 // search files in order they are open
4644 for i := 0 to CurrentOpenFiles.Count - 1 do
4645 begin
4646 HelpFile := THelpFile( CurrentOpenFiles[ i ] );
4647
4648 // look for a topic whose title starts with the searchtext
4649 Topic := HelpFile.FindTopicByTitleStartsWith( SearchText );
4650
4651 if Topic = nil then
4652 // look for an index entry that starts with the searchtext
4653 Topic := HelpFile.FindTopicByIndexStartsWith( SearchText );
4654
4655 if Topic = nil then
4656 // look for a topic whose title contains the searchtext
4657 Topic := HelpFile.FindTopicByTitleContains( SearchText );
4658
4659 if Topic = nil then
4660 // look for an index entry that contains the searchtext
4661 Topic := HelpFile.FindTopicByIndexContains( SearchText );
4662
4663 if Topic <> nil then
4664 begin
4665 // found something, display it (don't keep searching files)
4666 DisplayTopic( Topic );
4667 exit;
4668 end;
4669 end;
4670 DoErrorDlg( SearchTitle, TextNotFoundMsg );
4671end;
4672
4673Procedure TMainForm.SearchFor( const SearchText: string );
4674begin
4675 SearchTextEdit.Text := SearchText;
4676 DisplaySearch;
4677 SearchResultsListBox.Focus;
4678
4679 // force repaint of everything before we start searching.
4680 Update;
4681
4682 DoSearch;
4683end;
4684
4685Procedure TMainForm.ClearAllWordSequences;
4686var
4687 i: longint;
4688 FileWordSequences: TList;
4689 HelpFile: THelpFile;
4690begin
4691 if AllFilesWordSequences = nil then
4692 exit;
4693
4694 for i := 0 to AllFilesWordSequences.Count - 1 do
4695 begin
4696 FileWordSequences := AllFilesWordSequences[ i ];
4697 HelpFile := CurrentOpenFiles[ i ];
4698 ClearWordSequences( FileWordSequences, HelpFile.DictionaryCount );
4699 FileWordSequences.Destroy;
4700 end;
4701 AllFilesWordSequences.Clear;
4702end;
4703
4704// Perform search for text in searchedit.
4705Procedure TMainForm.DoSearch;
4706var
4707 SearchResults: TList;
4708 SearchText: string;
4709 FileIndex: longint;
4710 HelpFile: THelpFile;
4711 TopicIndex: longint;
4712 Topic: TTopic;
4713 FileWordSequences: TList;
4714 Query: TTextSearchQuery;
4715begin
4716 SearchText := Trim( SearchTextEdit.Text );
4717
4718 SearchResultsListBox.Clear;
4719
4720 if SearchText = '' then
4721 exit;
4722
4723 SearchResultsListBox.Items.Add( SearchingMsg );
4724 SetStatus( SearchingMsg );
4725
4726 try
4727 Query := TTextSearchQuery.Create( SearchText );
4728 except
4729 on e: ESearchSyntaxError do
4730 begin
4731 DoErrorDlg( SearchTitle,
4732 SearchSyntaxError
4733 + e.Message );
4734 exit;
4735 end;
4736 end;
4737
4738 ClearAllWordSequences;
4739
4740 SetWaitCursor;
4741
4742 SearchResults := TList.Create;
4743
4744 // Search open help file
4745 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4746 begin
4747 HelpFile := CurrentOpenFiles[ FileIndex ];
4748
4749 FileWordSequences := TList.Create;
4750
4751 try
4752 SearchHelpFile( HelpFile,
4753 Query,
4754 SearchResults,
4755 FileWordSequences );
4756 except
4757 on E: EHelpFileException do
4758 begin
4759 DoErrorDlg( ErrorTitle, E.Message );
4760 Query.Destroy;
4761 ClearWaitCursor;
4762 exit;
4763 end;
4764 end;
4765
4766 AllFilesWordSequences.Add( FileWordSequences );
4767
4768 end;
4769
4770 // Sort results across all files by relevance
4771 SearchResults.Sort( TopicRelevanceCompare );
4772
4773 // Load topics into search results list.
4774 SearchResultsListBox.BeginUpdate;
4775 SearchResultsListBox.Clear;
4776
4777 for TopicIndex := 0 to SearchResults.Count - 1 do
4778 begin
4779 Topic := SearchResults[ TopicIndex ];
4780 SearchResultsListBox.Items.AddObject( Topic.Title
4781 + ' ['
4782 + IntToStr( Topic.SearchRelevance )
4783 + ']',
4784 Topic );
4785 end;
4786
4787 EnableControls;
4788 if SearchResultsListBox.Items.Count > 0 then
4789 // there are some search matches, so highlight words
4790 ViewHighlightSearchWordsMI.Checked := true;
4791
4792 SearchResultsListBox.ItemIndex := -1;
4793 SearchResultsListBox.EndUpdate;
4794
4795 Query.Destroy;
4796 SearchResults.Destroy;
4797
4798 if SearchResultsListBox.Items.Count > 0 then
4799 begin
4800 SearchResultsListBox.ItemIndex := 0;
4801 end
4802 else
4803 begin
4804 SearchResultsListBox.Items.Add( NoSearchMatchesMsg
4805 + ': '
4806 + SearchText );
4807 RefreshWindows( Windows ); // update to remove old highlights
4808 end;
4809 SetStatus( SearchFoundMsgA
4810 + IntToStr( SearchResultsListBox.Items.Count )
4811 + SearchFoundMsgB
4812 + StrInDoubleQuotes(SearchText)
4813 );
4814
4815 ClearWaitCursor;
4816
4817 DisplaySelectedSearchResultTopic;
4818
4819End;
4820
4821Procedure TMainForm.FileSaveAsMIOnClick (Sender: TObject);
4822var
4823 F: File;
4824 EntryText: PChar;
4825 TextLength: longint;
4826 Window: THelpWindow;
4827 Filename: string;
4828Begin
4829 Window := GetActiveWindow;
4830 if Window = nil then
4831 begin
4832 DoErrorDlg( FileSaveTitle,
4833 FileSaveSelectWindowError );
4834 exit;
4835 end;
4836
4837 if DoSaveFileDialog( FileSaveTitle,
4838 AllFilesDesc + '|*',
4839 DefaultSaveTopicFilename,
4840 Settings.LastSaveDirectory,
4841 Filename ) then
4842 begin
4843 if FileExists( Filename ) then
4844 if not DoConfirmDlg( FileSaveTitle,
4845 ReplaceFilePromptA
4846 + Filename
4847 + ReplaceFilePromptB ) then
4848 exit;
4849 System.Assign( F, Filename );
4850
4851 try
4852 Rewrite( F );
4853 except
4854 on E: Exception do
4855 begin
4856 DoErrorDlg( FileSaveTitle,
4857 UnableToSaveError
4858 + Filename
4859 + ': '
4860 + E.Message );
4861 exit;
4862 end;
4863 end;
4864
4865 // find out length of (plain) text
4866 TextLength := Window.View.CopyTextToBuffer( nil, -1 );
4867
4868 // allocate space
4869 EntryText:= StrAlloc( TextLength );
4870
4871 // get the plain text
4872 Window.View.CopyTextToBuffer( EntryText, TextLength );
4873
4874 // save to file
4875 System.BlockWrite( F, EntryText^, TextLength );
4876
4877 // free space
4878 StrDispose( EntryText );
4879
4880 System.Close( F );
4881 end;
4882End;
4883
4884Procedure TMainForm.OptionsMIOnClick (Sender: TObject);
4885begin
4886 DoOptions;
4887end;
4888
4889Procedure TMainForm.DoOptions;
4890Begin
4891 EnsureOptionsFormLoaded;
4892
4893 GetColors; // in case changed by drag drop
4894
4895 if OptionsForm.ShowModal = mrOK then
4896 begin
4897 ApplySettings;
4898 SetLayout;
4899 RefreshFontSubstitutions;
4900 RefreshWindows( Windows );
4901 end;
4902End;
4903
4904Procedure TMainForm.ShowUsage;
4905begin
4906 DoMessageDlg( UsageTitle,
4907 UsageText1 + StrCRLF
4908 + UsageText2 + StrCRLF
4909 + UsageText3 + StrCRLF
4910 + UsageText4 + StrCRLF
4911 + UsageText5 + StrCRLF
4912 + UsageText6 + StrCRLF
4913 + UsageText7 + StrCRLF
4914 + UsageText8 );
4915end;
4916
4917Procedure TMainForm.TabSetOnChange (Sender: TObject; NewTab: LongInt;
4918 Var AllowChange: Boolean);
4919Begin
4920 NoteBook.PageIndex := NewTab;
4921End;
4922
4923Procedure TMainForm.NotebookOnSetupShow (Sender: TObject);
4924Begin
4925 ContentsOutline.xStretch := xsFrame;
4926 ContentsOutline.yStretch := ysFrame;
4927
4928 IndexSearchEdit.yAlign := yaTop;
4929 IndexSearchEdit.xStretch := xsFrame;
4930 IndexListBox.yStretch := ysFrame;
4931 IndexListBox.xStretch := xsFrame;
4932
4933 SearchTextEdit.yAlign := yaTop;
4934 SearchTextEdit.xStretch := xsFrame;
4935 SearchButton.yAlign := yaTop;
4936 SearchButton.xAlign := xaRight;
4937 SearchResultsListBox.xStretch := xsFrame;
4938 SearchResultsListBox.yStretch := ysFrame;
4939
4940 NotesListBox.xStretch := xsFrame;
4941 NotesListBox.yStretch := ysFrame;
4942End;
4943
4944Procedure TMainForm.EnableControls;
4945var
4946 BackEnabled: boolean;
4947 ForwardEnabled: boolean;
4948 FileOpen: boolean;
4949 WindowOpen: boolean;
4950 AtTop: boolean;
4951 AtBottom: boolean;
4952begin
4953 ViewContentsMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piContents );
4954 ViewIndexMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piIndex );
4955 ViewSearchMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piSearch );
4956 ViewNotesMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piNotes );
4957
4958 BackEnabled := CurrentHistoryIndex > 0;
4959 ForwardEnabled := CurrentHistoryIndex < PageHistory.Count - 1;
4960
4961 FileOpen := CurrentOpenFiles.Count > 0;
4962 WindowOpen := Windows.Count > 0;
4963
4964 ViewContentsMI.Enabled := FileOpen;
4965 ViewIndexMI.Enabled := FileOpen;
4966 ViewSearchMI.Enabled := FileOpen;
4967 ViewNotesMI.Enabled := FileOpen;
4968
4969 ShowLeftPanelMI.Enabled := FileOpen;
4970
4971 Coolbar.Sections[ ciBack ].Disabled := not BackEnabled;
4972 NavigateBackMI.Enabled := BackEnabled;
4973 Coolbar.Sections[ ciForward ].Disabled := not ForwardEnabled;
4974 NavigateForwardMI.Enabled := ForwardEnabled;
4975
4976 FileSaveAsMI.Enabled := FileOpen;
4977
4978 Coolbar.Sections[ ciPrint ].Disabled := not FileOpen;
4979 PrintMI.Enabled := FileOpen;
4980 FileInformationMI.Enabled := FileOpen;
4981
4982 Coolbar.Sections[ ciAddBookmark ].Disabled := not FileOpen;
4983 AddBookmarkMI.Enabled := FileOpen;
4984 EditBookmarksMI.Enabled := FileOpen;
4985 Coolbar.Sections[ ciAddNote ].Disabled := not FileOpen;
4986 AddNoteMI.Enabled := FileOpen;
4987
4988 if ContentsOutline.SelectedNode <> nil then
4989 begin
4990 AtTop := ContentsOutline.NextNodeUp( ContentsOutline.SelectedNode, false ) = nil;
4991 AtBottom := ContentsOutline.NextNodeDown( ContentsOutline.SelectedNode, false ) = nil;
4992 end;
4993
4994 NavigateNextMI.Enabled := FileOpen
4995 and ( ContentsOutline.SelectedNode <> nil )
4996 and ( not AtBottom );
4997 Coolbar.Sections[ ciNext ].Disabled := not NavigateNextMI.Enabled;
4998 NavigatePreviousMI.Enabled := FileOpen
4999 and ( ContentsOutline.SelectedNode <> nil )
5000 and ( not AtTop );
5001 Coolbar.Sections[ ciPrevious ].Disabled := not NavigatePreviousMI.Enabled;
5002
5003 FileCloseMI.Enabled := FileOpen;
5004
5005 FindMI.Enabled := WindowOpen;
5006 FindNextMI.Enabled := WindowOpen;
5007 CopyMI.Enabled := WindowOpen;
5008 SelectAllMI.Enabled := WindowOpen;
5009
5010 ViewExpandAllMI.Enabled := ContentsOutline.ChildCount > 0;
5011 ViewCollapseAllMI.Enabled := ContentsOutline.ChildCount > 0;
5012
5013 DebugTopicByResourceIDMI.Enabled := FileOpen;
5014 TopicByNameMI.Enabled := FileOpen;
5015
5016 ViewHighlightSearchWordsMI.Enabled := SearchResultsListBox.Items.Count > 0;
5017 if not ViewHighlightSearchWordsMI.Enabled then
5018 ViewHighlightSearchWordsMI.Checked := false;
5019
5020 ViewRefreshMI.Enabled := WindowOpen;
5021
5022 EnableSearchButton;
5023 EnableNotesControls;
5024
5025 VSplitBar.Visible := FileOpen;
5026 if not FileOpen then
5027 begin
5028 SetShowLeftPanel( false );
5029 end;
5030
5031
5032end;
5033
5034Procedure TMainForm.NavigateBackMIOnClick (Sender: TObject);
5035begin
5036 NavigateBack;
5037end;
5038
5039Procedure TMainForm.SaveNavigatePoint;
5040var
5041 NavPoint: TNavigatePoint;
5042begin
5043 // delete rest of history.
5044 while CurrentHistoryIndex < PageHistory.Count - 1 do
5045 begin
5046 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex + 1 ] as TNavigatePoint;
5047 NavPoint.Destroy;
5048 PageHistory.Delete( CurrentHistoryIndex + 1 );
5049 end;
5050
5051 NavPoint:= TNavigatePoint.Create;
5052 SaveWindows( Windows, NavPoint.Windows, nil );
5053
5054 if ContentsOutline.SelectedNode <> nil then
5055 NavPoint.ContentsTopic:= ContentsOutline.SelectedNode.Data as TTopic
5056 else
5057 NavPoint.ContentsTopic:= nil;
5058
5059 if CurrentTopic <> nil then
5060 PageHistory.AddObject( CurrentTopic.Title, NavPoint )
5061 else
5062 PageHistory.AddObject( '', NavPoint );
5063
5064 inc( CurrentHistoryIndex );
5065
5066 CreateNavigateToMenuItems;
5067end;
5068
5069Procedure TMainForm.UpdateCurrentNavigatePoint;
5070var
5071 NavPoint: TNavigatePoint;
5072begin
5073 if CurrentHistoryIndex = -1 then
5074 exit;
5075
5076 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5077
5078 DestroyListObjects( NavPoint.Windows );
5079 NavPoint.Windows.Clear;
5080
5081 SaveWindows( Windows, NavPoint.Windows, nil );
5082end;
5083
5084Procedure TMainForm.ClearPageHistory;
5085var
5086 i: longint;
5087 NavPoint: TNavigatePoint;
5088begin
5089 for i := 0 to PageHistory.Count - 1 do
5090 begin
5091 NavPoint := PageHistory.Objects[ i ] as TNavigatePoint;
5092 NavPoint.Destroy;
5093 end;
5094 PageHistory.Clear;
5095 CurrentHistoryIndex := -1;
5096 CreateNavigateToMenuItems;
5097 EnableControls;
5098end;
5099
5100Procedure TMainForm.SaveWindows( SourceList: TList;
5101 DestList: TList;
5102 Parent: TSavedHelpWindow );
5103
5104var
5105 WindowIndex: longint;
5106 Window: THelpWindow;
5107 WindowCopy: TSavedHelpWindow;
5108begin
5109 // limit storage to only what's need since list will be static.
5110 DestList.Capacity := SourceList.Count;
5111 for WindowIndex := 0 to SourceList.Count - 1 do
5112 begin
5113 Window := SourceList[ WindowIndex ];
5114 WindowCopy := TSavedHelpWindow.Create;
5115 WindowCopy.Parent := Parent;
5116 WindowCopy.Rect.Assign( Window.Rect );
5117 WindowCopy.Topic := Window.Topic;
5118 WindowCopy.Group := Window.Group;
5119 WindowCopy.TopCharIndex := Window.View.TopCharIndex;
5120 SaveWindows( Window.ChildWindows, WindowCopy.ChildWindows, WindowCopy );
5121 DestList.Add( WindowCopy );
5122 end;
5123end;
5124
5125Procedure TMainForm.DisplayWindows( WindowList: TList;
5126 Parent: THelpWindow );
5127var
5128 WindowIndex: longint;
5129 WindowCopy: TSavedHelpWindow;
5130 NewWindow: THelpWindow;
5131begin
5132 for WindowIndex := 0 to WindowList.Count - 1 do
5133 begin
5134 WindowCopy := WindowList[ WindowIndex ];
5135 NewWindow := OpenWindow( WindowCopy.Topic,
5136 WindowCopy.Group,
5137 Parent,
5138 WindowCopy.Rect,
5139 false ); // don't follow links
5140 NewWindow.View.TopCharIndex := WindowCopy.TopCharIndex;
5141 DisplayWindows( WindowCopy.ChildWindows, NewWindow );
5142 end;
5143end;
5144
5145Procedure TMainForm.CreateNavigateToMenuItems;
5146var
5147 MenuItem: TMenuItem;
5148 i: integer;
5149begin
5150 // clear existing items
5151 DestroyListObjects( NavigateToMenuItems );
5152 NavigateToMenuItems.Clear;
5153
5154 if CurrentHistoryIndex > 0 then
5155 begin
5156 // We are going to add some items, so
5157 // add a seperator from the rest of the menu first
5158 MenuItem := TMenuItem.Create( self );
5159 MenuItem.Caption:= '-';
5160 NavigateMenu.Add( MenuItem );
5161 NavigateToMenuItems.Add( MenuItem );
5162 end;
5163
5164 i := CurrentHistoryIndex - 1; // don't include the current history item
5165 while ( ( i >= 0 )
5166 and ( i > CurrentHistoryIndex - 10 ) ) do
5167 begin
5168 MenuItem := TMenuItem.Create( self );
5169 MenuItem.Caption := PageHistory[ i ];
5170 MenuItem.Hint := GoBackHint
5171 + StrInDoubleQuotes( PageHistory[ i ] );
5172 MenuItem.OnClick := OnNavigateToMenuItemClick;
5173 MenuItem.Tag := i;
5174
5175 NavigateMenu.Add( MenuItem );
5176 NavigateToMenuItems.Add( MenuItem );
5177 dec( i );
5178 end;
5179end;
5180
5181Procedure TMainForm.NavigateToPoint( NavPoint: TNavigatePoint );
5182begin
5183 Navigating := true;
5184
5185 // close current windows
5186 CloseWindows;
5187
5188 // Display windows for the navigate point
5189 DisplayWindows( NavPoint.Windows, nil );
5190
5191 // Select the contents topic
5192 ContentsOutline.SetSelectedObject( NavPoint.ContentsTopic );
5193
5194 // Update the navigate menu (since a different set of
5195 // back-points are now available)
5196 CreateNavigateToMenuItems;
5197
5198 // Make the topic windows visible
5199 ShowWindows;
5200
5201 // Update back buttons etc...
5202 EnableControls;
5203
5204 Navigating := false;
5205end;
5206
5207Procedure TMainForm.NavigateToHistoryIndex( Index: longint );
5208var
5209 NavPoint: TNavigatePoint;
5210begin
5211 UpdateCurrentNavigatePoint;
5212 CurrentHistoryIndex := Index;
5213 NavPoint := PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5214 NavigateToPoint( NavPoint );
5215end;
5216
5217Procedure TMainForm.NavigateForward;
5218Begin
5219 if CurrentHistoryIndex < PageHistory.Count - 1 then
5220 begin
5221 NavigateToHistoryIndex( CurrentHistoryIndex + 1 );
5222 end;
5223End;
5224
5225Procedure TMainForm.NavigateBack;
5226Begin
5227 if CurrentHistoryIndex > 0 then
5228 begin
5229 NavigateToHistoryIndex( CurrentHistoryIndex - 1 );
5230 end;
5231End;
5232
5233Procedure TMainForm.NavigatePreviousInContents;
5234begin
5235 ContentsOutline.GotoNextNodeUp;
5236 DisplaySelectedContentsTopic;
5237end;
5238
5239Procedure TMainForm.NavigateNextInContents;
5240begin
5241 ContentsOutline.GotoNextNodeDown;
5242 DisplaySelectedContentsTopic;
5243end;
5244
5245Procedure TMainForm.CorrectNotesPositions( Topic: TTopic;
5246 Text: pchar );
5247var
5248 NoteIndex: longint;
5249 Note: THelpNote;
5250 p: pchar;
5251 NextP: pchar;
5252 Element: TTextElement;
5253 TextIndex: longint;
5254begin
5255 NoteIndex := 0;
5256 for NoteIndex := 0 to Notes.Count - 1 do
5257 begin
5258 Note := Notes[ NoteIndex ];
5259 if Note.Topic = Topic then
5260 begin
5261 // this note belongs the the specified topic.
5262 p := Text;
5263
5264 while true do
5265 begin
5266 Element := ExtractNextTextElement( p, NextP );
5267 if Element.ElementType = teTextEnd then
5268 break;
5269 TextIndex := PCharPointerDiff( p, Text );
5270 if TextIndex >= Note.InsertPoint then
5271 begin
5272 // found a safe point to insert
5273 if TextIndex <> Note.InsertPoint then
5274 begin
5275 // correct it.
5276 Note.InsertPoint := TextIndex;
5277 end;
5278 break;
5279 end;
5280
5281 p := NextP;
5282 end;
5283 end;
5284 end;
5285end;
5286
5287Procedure TMainForm.InsertNotesIntoTopicText( Topic: TTopic;
5288 Text: TAString );
5289var
5290 NoteIndex: longint;
5291 Note: THelpNote;
5292 ActualInsertPoint: longword;
5293begin
5294 CorrectNotesPositions( Topic, Text.AsPChar );
5295
5296 for NoteIndex := 0 to Notes.Count - 1 do
5297 begin
5298 Note := Notes[ NoteIndex ];
5299 if Note.Topic = Topic then
5300 begin
5301 // Adjust insert point for any notes we have already inserted.
5302 ActualInsertPoint := FindActualNoteCharIndex( Note.InsertPoint,
5303 NoteIndex,
5304 Topic );
5305 RefreshNoteInsertInfo( NoteIndex );
5306 Text.Insert( ActualInsertPoint, Note.InsertText );
5307 end;
5308 end;
5309end;
5310
5311Procedure TMainForm.NavigatePreviousMIOnClick (Sender: TObject);
5312Begin
5313 NavigatePreviousInContents;
5314End;
5315
5316Procedure TMainForm.NavigateNextMIOnClick (Sender: TObject);
5317Begin
5318 NavigateNextInContents;
5319End;
5320
5321Function TMainForm.GetActiveWindow: THelpWindow;
5322var
5323 View: TRichTextView;
5324 FirstWindow: THelpWindow;
5325begin
5326 Result := nil;
5327 if Screen.ActiveControl is TRichTextView then
5328 begin
5329 View := Screen.ActiveControl as TRichTextView;
5330 Result := FindWindowFromView( View, Windows );
5331 end
5332 else if Windows.Count = 1 then
5333 begin
5334 FirstWindow := Windows[ 0 ];
5335 if FirstWindow.ChildWindows.Count = 0 then
5336 Result := FirstWindow;
5337 end;
5338end;
5339
5340Procedure TMainForm.CopyMIOnClick (Sender: TObject);
5341var
5342 Window: THelpWindow;
5343begin
5344 if ActiveControl = nil then
5345 exit;
5346
5347 if ActiveControl is TEdit then
5348 begin
5349 // this is for the edit controls in the left panel
5350 TEdit( ActiveControl ).CopyToClipboard;
5351 exit;
5352 end;
5353
5354 // else copy from rtv in active help window
5355
5356 Window := GetActiveWindow;
5357 if Window = nil then
5358 exit;
5359
5360 Window.View.CopySelectionToClipboard;
5361End;
5362
5363Procedure TMainForm.SelectAllMIOnClick (Sender: TObject);
5364var
5365 Window: THelpWindow;
5366begin
5367 Window:= GetActiveWindow;
5368 if Window = nil then
5369 begin
5370 DoErrorDlg( SelectAllTitle,
5371 SelectAllWindowError );
5372 exit;
5373 end;
5374 Window.View.SelectAll;
5375End;
5376
5377Procedure TMainForm.DebugShowCodesMIOnClick (Sender: TObject);
5378Begin
5379 DebugShowCodesMI.Checked:= not DebugShowCodesMI.Checked;
5380 RefreshWindows( Windows );
5381End;
5382
5383Procedure TMainForm.HelpProductInformationMIOnClick (Sender: TObject);
5384Begin
5385 EnsureProductInformationFormLoaded;
5386 ProductInformationForm.ShowModal;
5387End;
5388
5389Procedure TMainForm.OnOverLink ( Sender: TRichTextView; LinkString: String);
5390var
5391 Link: THelpLink;
5392 LinkIndex: longint;
5393 Window: THelpWindow;
5394 LinkedTopic: TTopic;
5395 Filename: string;
5396 SourceFile: THelpFile;
5397 URL: string;
5398 LinkDetails: string;
5399 tmpLinkDetails : TStringList;
5400 ProgramInfo : TSerializableStringList;
5401 ProgramPath, ProgramLink : string;
5402Begin
5403 LogEvent(LogDebug, 'OnOverLink: "' + LinkString + '"');
5404
5405 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5406 begin
5407 SetStatus( EditNoteMsg )
5408 end
5409 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5410 begin
5411 ProgramInfo := TSerializableStringList.create;
5412// TODO check param here
5413
5414 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, Length(PARAM_LINK_PROGRAM) + 2));
5415 ProgramPath := ProgramInfo.get(0);
5416 ProgramLink := ProgramInfo.get(1);
5417 TSerializableStringList.destroy;
5418
5419 // call LaunchProgram here to inherit the environment
5420 SetStatus( LinkMsg + ' ' + ProgramPath + ' ' + ProgramLink);
5421 end
5422 else if StrStartsWith(LinkString, PARAM_LINK_URL) then
5423 begin
5424 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2); //
5425
5426 SetStatus( LinkMsg + URL );
5427 end
5428 else if StrStartsWith(LinkString, PARAM_LINK_EXTERNAL) then
5429 begin
5430 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5431
5432 tmpLinkDetails := TStringList.Create;
5433 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5434 LinkIndex := StrToInt(tmpLinkDetails[0]);
5435 tmpLinkDetails.Destroy;
5436
5437 Window := FindWindowFromView( Sender, Windows );
5438 SourceFile := Window.Topic.HelpFile as THelpFile;
5439 Filename := SourceFile.ReferencedFiles[ LinkIndex ];
5440 SetStatus( LinkMsg
5441 + StrInDoubleQuotes( Filename ) );
5442 end
5443 else
5444 begin
5445 Window := FindWindowFromView( Sender, Windows );
5446 LinkIndex := StrToInt( LinkString );
5447 Link := Window.Topic.Links[ LinkIndex ];
5448
5449 if Link is TFootnoteHelpLink then
5450 begin
5451 SetStatus( FootnoteMsg );
5452 end
5453 else
5454 begin
5455 LinkedTopic := FindTopicForLink( Link );
5456
5457 if LinkedTopic <> nil then
5458 begin
5459 SetStatus( LinkMsg
5460 + StrInDoubleQuotes( Trim( LinkedTopic.Title ) ) );
5461 end
5462 else
5463 begin
5464 SetStatus( UnknownLinkMsg );
5465 end;
5466 end;
5467 end;
5468End;
5469
5470Procedure TMainForm.OnNotOverLink ( Sender: TRichTextView; LinkString: String);
5471Begin
5472 SetStatus( '' );
5473end;
5474
5475Procedure TMainForm.OnClickLink ( Sender: TRichTextView; LinkString: String);
5476var
5477 Link: THelpLink;
5478 LinkIndex: longint;
5479 SourceWindow: THelpWindow;
5480 NoteIndex: longint;
5481 Window: THelpWindow;
5482 SourceFile: THelpFile;
5483 ProgramLink: string;
5484 ProgramPath: string;
5485 URL: string;
5486 LinkDetails: string;
5487 tmpLinkDetails : TStringList;
5488 ProgramInfo : TSerializableStringList;
5489Begin
5490 LogEvent(LogDebug, 'OnClickLink: "' + LinkString + '"');
5491
5492 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5493 begin
5494 NoteIndex := StrToInt(StrSubstringFrom(LinkString, Length(PARAM_LINK_NOTE) + 2) );
5495 NotesListBox.ItemIndex := NoteIndex;
5496 EditNote( NoteIndex );
5497 end
5498 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5499 begin
5500 ProgramInfo := TSerializableStringList.create;
5501 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, 9));
5502 ProgramPath := ProgramInfo.get(0);
5503 ProgramLink := ProgramInfo.get(1);
5504 TSerializableStringList.destroy;
5505
5506 // call LaunchProgram here to inherit the environment
5507 LogEvent(LogDisplay, 'LaunchProgram: "' + ProgramPath + '" "' + ProgramLink + '"');
5508 LaunchProgram(ProgramPath, ProgramLink, '');
5509 // TODO i18n
5510 SetStatus( 'Launched ' + ProgramPath );
5511 end
5512 else if StrLeft( LinkString, 3 ) = PARAM_LINK_URL then
5513 begin
5514 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2);
5515
5516 try
5517 LaunchURL(URL);
5518 except
5519 on E:Exception do
5520 begin
5521 DoErrorDlg('Error', E.Message);
5522 end;
5523 else raise;
5524 end;
5525
5526 // TODO i18n
5527 SetStatus('Opened ' + URL );
5528 end
5529 else if StrLeft( LinkString, 8 ) = PARAM_LINK_EXTERNAL then
5530 begin
5531 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5532
5533 tmpLinkDetails := TStringList.Create;
5534 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5535 LinkIndex := StrToInt(tmpLinkDetails[0]);
5536 tmpLinkDetails.Destroy;
5537
5538 Window := FindWindowFromView( Sender, Windows );
5539 SourceFile := Window.Topic.HelpFile as THelpFile;
5540
5541 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5542 g_ExternalLinkTopic := LinkDetails;
5543 g_ExternalLinkSourceFilename := SourceFile.Filename;
5544 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5545
5546 PostMsg( Self.Handle,
5547 WM_FOLLOWEXTERNALLINK,
5548 0,
5549 0 );
5550 end
5551 else
5552 begin
5553 SourceWindow := FindWindowFromView( Sender, Windows );
5554 LinkIndex := StrToInt( LinkString );
5555 Link := SourceWindow.Topic.Links[ LinkIndex ];
5556
5557 PostMsg( Self.Handle,
5558 WM_FOLLOWLINK,
5559 longint( Link ),
5560 longint( SourceWindow ) );
5561
5562 end;
5563End;
5564
5565Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5566 var CanClose: boolean );
5567begin
5568 if Navigating then
5569 exit;
5570
5571 UpdateCurrentNavigatePoint; // Save it before close...
5572
5573 CanClose := true;
5574end;
5575
5576Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5577var
5578 ParentWindow: THelpWindow;
5579 WindowIndex: longint;
5580Begin
5581 if Navigating then
5582 exit;
5583
5584 if Window.ParentHelpWindow = nil then
5585 begin
5586 WindowIndex := Windows.IndexOf( Window );
5587 Windows.Delete( WindowIndex );
5588 end
5589 else
5590 begin
5591 ParentWindow := Window.ParentHelpWindow;
5592 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5593 ParentWindow.ChildWindows.Delete( WindowIndex );
5594 end;
5595end;
5596
5597Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5598Begin
5599 if Navigating then
5600 exit;
5601
5602 RemoveHelpWindowFromParent( Window );
5603
5604 SaveNavigatePoint;
5605 EnableControls;
5606End;
5607
5608Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5609Begin
5610 NavigateBack;
5611End;
5612
5613Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5614Begin
5615End;
5616
5617Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5618Begin
5619 Close;
5620End;
5621
5622Procedure TMainForm.CreateMRUMenuItems;
5623var
5624 MenuItem: TMenuItem;
5625 i: integer;
5626 FileName: string;
5627 FileNameIndex: longint;
5628 MRUText: string;
5629 MRUItem: TMRUItem;
5630begin
5631 DestroyListObjects( MRUMenuItems );
5632 MRUMenuItems.Clear;
5633
5634 // if there are Most Recently Used files
5635 if Settings.MRUList.Count > 0 then
5636 begin
5637 // create a seperator after Exit
5638 MenuItem:= TMenuItem.Create( self );
5639 MenuItem.Name := 'MRUSeparatorMI';
5640 MenuItem.Caption:= '-';
5641 FileMenu.Add( MenuItem );
5642 MRUMenuItems.Add( MenuItem );
5643 end;
5644
5645 // Add items for the MRU files
5646 for i:= 0 to Settings.MRUList.Count -1 do
5647 begin
5648 MRUItem := Settings.MRUList[ i ];
5649
5650 MenuItem := TMenuItem.Create( self );
5651
5652 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5653 MRUText := MRUItem.Title;
5654 if Trim( MRUText ) = '' then
5655 begin
5656 // Take the filenames, less path, as caption...
5657 MRUText := '';
5658 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5659 begin
5660 FileName := MRUItem.Filenames[ FileNameIndex ];
5661 FileName := ExtractFileName( FileName );
5662 FileName := ChangeFileExt( FileName, '' );// remove extension
5663
5664 if FileNameIndex > 0 then
5665 begin
5666 MRUText := MRUText + '+';
5667 end;
5668 MRUText := MRUText + FileName;
5669
5670 // stop after 50 chars
5671 if Length( MRUText ) > 50 then
5672 begin
5673 MRUText := MRUText + '+ ...';
5674 break;
5675 end;
5676 end;
5677 end;
5678
5679 MenuItem.Caption:= '~'
5680 + IntToStr( i + 1 )
5681 + '. '
5682 + MRUText;
5683 if MRUItem.Filenames.Count = 1 then
5684 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5685 else
5686 MenuItem.Hint := MRUItem.Title
5687 + ' ('
5688 + IntToStr( MRUItem.Filenames.Count )
5689 + ' '
5690 + MRUMultipleFilesHint
5691 + ')';
5692
5693 MenuItem.OnClick:= OnMRUMenuItemClick;
5694 MenuItem.Tag:= i;
5695 FileMenu.Add( MenuItem );
5696 MRUMenuItems.Add( MenuItem );
5697 end;
5698end;
5699
5700procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5701var
5702 Tag: longint;
5703 MenuItem: TMenuItem;
5704 MRUItem: TMRUItem;
5705begin
5706 MenuItem:= Sender as TMenuItem;
5707 Tag:= MenuItem.Tag;
5708 MRUItem := Settings.MRUList[ Tag ];
5709 if OpenFiles( MRUItem.FileNames, '', true ) then
5710 begin
5711 ClearHelpManager;
5712 end;
5713end;
5714
5715Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5716var
5717 MenuItem: TMenuItem;
5718 Tag: longint;
5719begin
5720 MenuItem:= Sender as TMenuItem;
5721 Tag:= MenuItem.Tag;
5722 NavigateToHistoryIndex( Tag );
5723end;
5724
5725Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5726 ParentNode: TNode;
5727 Level: longint;
5728 Var TopicIndex: longint );
5729var
5730 Topic: TTopic;
5731 Node: TNode;
5732begin
5733 assert( ParentNode <> nil );
5734 Node := nil;
5735 while TopicIndex < HelpFile.TopicCount do
5736 begin
5737 Topic:= HelpFile.Topics[ TopicIndex ];
5738
5739 if Topic.ShowInContents then
5740 begin
5741 if Topic.ContentsLevel < Level then
5742 break;
5743
5744 if Topic.ContentsLevel = Level then
5745 begin
5746 Node:= ParentNode.AddChild( Topic.Title,
5747 Topic );
5748 inc( TopicIndex );
5749 end
5750 else
5751 begin
5752 assert( Node <> nil );
5753 AddChildNodes( HelpFile,
5754 Node,
5755 Topic.ContentsLevel,
5756 TopicIndex );
5757 Node := nil;
5758 end
5759 end
5760 else
5761 begin
5762 inc( TopicIndex );
5763 end;
5764 end;
5765
5766end;
5767
5768Procedure TMainForm.LoadContents( Files: TList;
5769 Var FirstNode: TNode );
5770var
5771 TopicIndex: longint;
5772 Topic: TTopic;
5773 Node: TNode;
5774 FileIndex: longint;
5775 HelpFile: THelpFile;
5776begin
5777 ContentsOutline.BeginUpdate;
5778 LogEvent(LogStartup, 'Load contents outline');
5779
5780 // we don't clear it first, to allow adding additional files
5781 // into the contents tree
5782
5783 LogEvent(LogStartup, 'Loop files');
5784
5785 FirstNode := nil;
5786
5787 Node := nil;
5788
5789 for FileIndex:= 0 to Files.Count - 1 do
5790 begin
5791 HelpFile := Files[ FileIndex ];
5792 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5793 TopicIndex := 0;
5794 while TopicIndex < HelpFile.TopicCount do
5795 begin
5796 Topic := HelpFile.Topics[ TopicIndex ];
5797 assert( Topic.ContentsLevel >= 0,
5798 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5799 if Topic.ShowInContents then
5800 begin
5801 if Topic.ContentsLevel = 1 then
5802 begin
5803 Node := ContentsOutline.AddChild( Topic.Title,
5804 Topic );
5805 if FirstNode = nil then
5806 FirstNode := node;
5807
5808 inc( TopicIndex );
5809 end
5810 else
5811 begin
5812 // subnodes
5813 assert( Node <> nil, 'No level 1 topic for subnodes!' );
5814 AddChildNodes( HelpFile,
5815 Node,
5816 Topic.ContentsLevel,
5817 TopicIndex );
5818 Node := nil;
5819 end;
5820 end
5821 else
5822 begin
5823 inc( TopicIndex );
5824 end;
5825 end;
5826 end;
5827 LogEvent(LogStartup, ' EndUpdate' );
5828 ContentsOutline.EndUpdate;
5829
5830 if Settings.OpenWithExpandedContents then
5831 begin
5832 LogEvent(LogStartup, ' Expand all contents' );
5833 ContentsOutline.ExpandAll
5834 end
5835 else if ContentsOutline.ChildCount = 1 then
5836 begin
5837 LogEvent(LogStartup, ' Expand first node' );
5838 // Contents has only one top level node... expand it
5839 FirstNode.Expand;
5840 end;
5841
5842 ContentsLoaded := true;
5843 LogEvent(LogStartup, ' Contents loaded' );
5844
5845end;
5846
5847Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5848var
5849 NotesFileName: string;
5850 TopicIndex: longword;
5851 Note: THelpNote;
5852 NoteIndex: longint;
5853
5854 NotesFile: HFile;
5855 OpenAction: ULong;
5856 rc: APIRET;
5857 CName: Cstring;
5858 FileNoteCount: integer;
5859
5860begin
5861 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5862
5863 if not HelpFile.NotesLoaded then
5864 // we never loaded the notes/displayed a topic from this file
5865 // so don't do anything.
5866 exit;
5867
5868 LogEvent(LogStartup, 'Really saving' );
5869
5870 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5871
5872 FileNoteCount := 0;
5873 for NoteIndex := 0 to Notes.Count - 1 do
5874 begin
5875 Note := Notes[ NoteIndex ];
5876
5877 if Note.Topic.HelpFile = HelpFile then
5878 inc( FileNoteCount );
5879 end;
5880
5881 if FileNoteCount = 0 then
5882 begin
5883 // no notes. delete notes file if it already exists.
5884 if FileExists( NotesFileName ) then
5885 DeleteFile( NotesFileName );
5886 exit;
5887 end;
5888
5889 CName:= NotesFileName;
5890 rc:= DosOpen( CName,
5891 NotesFile,
5892 OpenAction,
5893 0, // file size
5894 0, // attrs
5895 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5896 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5897 nil ); // no eas
5898 if rc <> 0 then
5899 begin
5900 DoErrorDlg( SaveNotesTitle,
5901 SaveNotesError
5902 + StrCRLF
5903 + NotesFileName
5904 + StrCRLF
5905 + SysErrorMessage( rc ) );
5906 exit;
5907 end;
5908
5909 for NoteIndex:= 0 to Notes.Count - 1 do
5910 begin
5911 Note:= Notes[ NoteIndex ];
5912
5913 if Note.Topic.HelpFile <> HelpFile then
5914 continue;
5915
5916 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5917
5918 MyWriteLn( NotesFile,
5919 IntToStr( TopicIndex ));
5920 MyWriteLn( NotesFile,
5921 IntToStr( Note.InsertPoint ) );
5922
5923 MyWrite( NotesFile,
5924 Note.Text.AsPChar,
5925 Note.Text.Length );
5926
5927 MyWriteLn( NotesFile,
5928 '' );
5929 MyWriteLn( NotesFile,
5930 '#ENDNOTE#' );
5931
5932 end;
5933
5934 DosClose( NotesFile );
5935end;
5936
5937Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5938var
5939 NotesFileName: string;
5940 TopicIndex: longint;
5941 InsertPoint: longint;
5942 Note: THelpNote;
5943
5944 NotesFile: HFile;
5945 OpenAction: ULong;
5946 rc: APIRET;
5947 CName: Cstring;
5948
5949 Paragraph: TAString;
5950 NotEOF: boolean;
5951 NoteText: TAString;
5952
5953begin
5954 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5955
5956 if HelpFile.NotesLoaded then
5957 exit;
5958
5959 HelpFile.NotesLoaded := true;
5960 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5961
5962 if not FileExists( NotesFileName ) then
5963 // no notes
5964 exit;
5965
5966 CName := NotesFileName;
5967 rc := DosOpen( CName,
5968 NotesFile,
5969 OpenAction,
5970 0, // file size - irrelevant, not creating,
5971 0, // attrs - ''
5972 OPEN_ACTION_OPEN_IF_EXISTS,
5973 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5974 nil ); // no eas
5975 if rc <> 0 then
5976 begin
5977 DoErrorDlg( LoadNotesTitle,
5978 LoadNotesError
5979 + StrCRLF
5980 + NotesFileName
5981 + StrCRLF
5982 + SysErrorMessage( rc ) );
5983 exit;
5984 end;
5985
5986 Paragraph := TAString.Create;
5987 NoteText := TAString.Create;
5988
5989 NotEOF := true;
5990
5991 while NotEOF do
5992 begin
5993 // Read contents index
5994 NotEOF := Paragraph.ReadParagraph( NotesFile );
5995 if not NotEOF then
5996 continue;
5997 try
5998 TopicIndex := StrToInt( Paragraph.AsString );
5999 except
6000 TopicIndex := -1;
6001 end;
6002
6003 // Read insert point
6004 NotEOF := Paragraph.ReadParagraph( NotesFile );
6005 if not NotEOF then
6006 continue;
6007 try
6008 InsertPoint := StrToInt( Paragraph.AsString );
6009 except
6010 InsertPoint := -1;
6011 end;
6012
6013 NoteText.Clear;
6014
6015 while NotEOF do
6016 begin
6017 NotEOF := Paragraph.ReadParagraph( NotesFile );
6018 if Paragraph.SameAs( '#ENDNOTE#' ) then
6019 begin
6020 // found end of note
6021 if ( TopicIndex >= 0 )
6022 and ( InsertPoint >= 0 ) then
6023 begin
6024 Note := THelpNote.Create;
6025 Note.Topic := HelpFile.Topics[ TopicIndex ];
6026 Note.InsertPoint := InsertPoint;
6027
6028 // Remove the last end line
6029 Note.Text.Assign( NoteText );
6030 if Note.Text.Length > 2 then
6031 Note.Text.Delete( Note.Text.Length - 2, 2 );
6032
6033 Notes.Add( Note );
6034 end;
6035 break;
6036 end;
6037 NoteText.Add( Paragraph );
6038 NoteText.AddString( #13 + #10 );
6039 end;
6040
6041 end;
6042 DosClose( NotesFile );
6043
6044 Paragraph.Destroy;
6045 NoteText.Destroy;
6046
6047end;
6048
6049Procedure TMainForm.UpdateNotesDisplay;
6050var
6051 NoteIndex: longint;
6052 Note: THelpNote;
6053 NoteTitle: string;
6054begin
6055 NotesListBox.Clear;
6056 for NoteIndex := 0 to Notes.Count - 1 do
6057 begin
6058 Note := Notes[ NoteIndex ];
6059
6060 if Note.Topic > nil then
6061 NoteTitle := Note.Topic.Title
6062 else
6063 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6064 NotesListBox.Items.AddObject( NoteTitle,
6065 Note );
6066 end;
6067 EnableNotesControls;
6068end;
6069
6070Procedure TMainForm.EnableNotesControls;
6071var
6072 NoteSelected: boolean;
6073begin
6074 NoteSelected:= NotesListBox.ItemIndex <> -1;
6075 EditNoteButton.Enabled:= NoteSelected;
6076 GotoNoteButton.Enabled:= NoteSelected;
6077 DeleteNoteButton.Enabled:= NoteSelected;
6078 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6079end;
6080
6081Function TMainForm.OKToCloseFile: boolean;
6082begin
6083 Result := true;
6084
6085 if PrintThread = nil then
6086 // haven't used print thread yet
6087 exit;
6088
6089 if not PrintThread.IsRunning then
6090 // not currently running
6091 exit;
6092
6093 Result := DoConfirmDlg( CheckStopPrintTitle,
6094 CheckStopPrintMsg );
6095
6096end;
6097
6098Procedure TMainForm.StopPrinting;
6099begin
6100 if PrintThread <> nil then
6101 begin
6102 if PrintThread.IsRunning then
6103 begin
6104 SetStatus( StoppingPrintMsg );
6105 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6106 SetStatus( PrintStoppedMsg );
6107 ResetProgress;
6108 end;
6109 end;
6110end;
6111
6112Procedure TMainForm.CloseFile;
6113var
6114 FileIndex: longint;
6115 HelpFile: THelpFile;
6116 M1: longint;
6117begin
6118 StopPrinting;
6119
6120 LogEvent(LogShutdown, 'Set Caption' );
6121 MainTitle := '';
6122 SetMainCaption;
6123
6124 LogEvent(LogShutdown, 'Close Windows' );
6125 CloseWindows;
6126
6127 LogEvent(LogShutdown, 'Set selected node to nil' );
6128 ContentsOutline.SelectedNode:= Nil;
6129
6130 M1:= MemAvail;
6131
6132 LogEvent(LogShutdown, 'Clear contents outline' );
6133 ContentsOutline.Clear;
6134
6135 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6136 M1:= MemAvail;
6137
6138 DisplayedIndex.Clear;
6139 IndexListBox.Clear;
6140 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6141 M1:= MemAvail;
6142
6143 NotesListBox.Clear;
6144 SearchResultsListBox.Clear;
6145
6146 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6147 M1:= MemAvail;
6148
6149 // First save notes and bookmarks.
6150 // It's important we do this first
6151 // since we scan all notes each time to find the ones
6152 // belonging to this file.
6153 SaveBookmarks;
6154
6155 SaveNotes;
6156
6157 ClearAllWordSequences;
6158
6159 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6160
6161 // Now destroy help files
6162 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6163 begin
6164 HelpFile := CurrentOpenFiles[ FileIndex ];
6165 GlobalFilelist.RemoveFile( Frame.Handle,
6166 HelpFile.Filename );
6167 HelpFile.Free;
6168 end;
6169
6170 CurrentOpenFiles.Clear;
6171
6172 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6173 M1 := MemAvail;
6174
6175 LogEvent(LogShutdown, 'Clear notes' );
6176 ClearNotes;
6177
6178 LogEvent(LogShutdown, 'Clear bookmarks' );
6179 ClearBookmarks;
6180
6181 ClearPageHistory;
6182
6183 LogEvent(LogShutdown, 'Enable controls' );
6184 EnableControls;
6185
6186 LogEvent(LogShutdown, 'CloseFile done' );
6187
6188end;
6189
6190Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6191var
6192 FileIndex: longint;
6193begin
6194 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6195 begin
6196 Result:= CurrentOpenFiles[ FileIndex ];
6197 if StrEqualIgnoringCase( Result.Filename, FileName ) then
6198 // found
6199 exit;
6200 end;
6201 Result:= nil;
6202end;
6203
6204// This rather horrendous looking bit of code simply:
6205
6206// Gets the contents from each file
6207// Sorts it alphabetically.
6208// Merges all the sorted contents and indexes together,
6209// alphabetically.
6210type
6211 TListType = ( ltContents, ltIndex );
6212
6213procedure TMainForm.LoadIndex;
6214var
6215 HelpFile: THelpFile;
6216 TextCompareResult: integer;
6217
6218 FileIndex: longint;
6219
6220 Contents: TList;
6221 ContentsLists: TList; // of tlist
6222 IndexLists: TList; // of tstringlist
6223 ContentsNextIndex: array[ 0..255 ] of longint;
6224 IndexNextIndex: array[ 0..255 ] of longint;
6225 Topic: TTopic;
6226
6227 ListIndex: longint;
6228
6229 pListEntry: pstring;
6230 pLowestEntry: pstring;
6231 pLastEntry: pstring;
6232
6233 LowestEntryListIndex: longint;
6234 LowestEntryListType: TListType;
6235 LowestEntryTopic: TTopic;
6236
6237 Index: TStringList;
6238
6239 i : longint;
6240begin
6241 LogEvent(LogStartup, 'Create index' );
6242
6243 SetWaitCursor;
6244
6245 LogEvent(LogStartup, ' Get/sort lists' );
6246
6247 ProgressBar.Position := 70;
6248 SetStatus( 'Building index... ' );
6249
6250 ContentsLists := TList.Create;
6251 IndexLists := TList.Create;
6252
6253 // collect the contents and index lists from the files
6254 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6255 begin
6256 HelpFile := CurrentOpenFiles[ FileIndex ];
6257 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6258
6259 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6260 begin
6261 Contents := TList.Create;
6262 Contents.Capacity := HelpFile.TopicCount;
6263
6264 // copy [contents] topic list
6265 for i := 0 to HelpFile.TopicCount - 1 do
6266 begin
6267 Topic := HelpFile.Topics[ i ];
6268 if Topic.ShowInContents then
6269 Contents.Add( Topic );
6270 end;
6271
6272 // sort by title
6273 Contents.Sort( TopicTitleCompare );
6274
6275 ContentsLists.Add( Contents );
6276
6277 // initialise list index
6278 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6279 end;
6280
6281 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6282 begin
6283 IndexLists.Add( HelpFile.Index );
6284 IndexNextIndex[ IndexLists.Count - 1 ] := 0;
6285 end;
6286 end;
6287
6288 // Unlike contents, we do clear the index
6289 // (even if we are adding more files) because we need
6290 // to re-merge the whole thing
6291 DisplayedIndex.Clear;
6292 ProgressBar.Position := 80;
6293
6294 LogEvent(LogStartup, ' Merge lists' );
6295
6296 pLastEntry := NullStr;
6297 while true do
6298 begin
6299 pLowestEntry := NullStr;
6300 LowestEntryListIndex := -1;
6301
6302 // Find alphabetically lowest (remaining) topic
6303
6304 // first, look in contents lists
6305 for ListIndex := 0 to ContentsLists.Count - 1 do
6306 begin
6307 Contents := ContentsLists[ ListIndex ];
6308 if ContentsNextIndex[ ListIndex ] < Contents.Count then
6309 begin
6310 // list is not yet finished, get next entry
6311 Topic := Contents[ ContentsNextIndex[ ListIndex ] ];
6312 pListEntry := Topic.TitlePtr;
6313
6314 if pLowestEntry^ <> '' then
6315 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6316 else
6317 TextCompareResult := -1;
6318
6319 if TextCompareResult < 0 then
6320 begin
6321 // this index entry comes before the lowest one so far
6322 pLowestEntry := pListEntry;
6323 LowestEntryListIndex := ListIndex;
6324 LowestEntryListType := ltContents;
6325 LowestEntryTopic := Topic;
6326 end;
6327 end;
6328 end;
6329
6330 // look in indices
6331 for ListIndex := 0 to IndexLists.Count - 1 do
6332 begin
6333 Index := IndexLists[ ListIndex ];
6334 if IndexNextIndex[ ListIndex ] < Index.Count then
6335 begin
6336 // list is not yet finished, get next entry
6337 pListEntry := Index.ValuePtrs[ IndexNextIndex[ ListIndex ] ];
6338
6339 if pLowestEntry^ <> '' then
6340 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6341 else
6342 TextCompareResult := -1;
6343
6344 if TextCompareResult < 0 then
6345 begin
6346 // this index entry comes before the lowest one so far
6347 pLowestEntry := pListEntry;
6348 LowestEntryListIndex := ListIndex;
6349 LowestEntryListType := ltIndex;
6350 LowestEntryTopic := TTopic( Index.Objects[ IndexNextIndex[ ListIndex ] ] );
6351 end;
6352 end;
6353 end;
6354
6355 if LowestEntryListIndex = -1 then
6356 // we're out
6357 break;
6358
6359 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6360 // add, if different from last
6361 DisplayedIndex.AddObject( pLowestEntry^,
6362 LowestEntryTopic );
6363 pLastEntry := pLowestEntry;
6364
6365 if LowestEntryListType = ltContents then
6366 begin
6367 inc( ContentsNextIndex[ LowestEntryListIndex ] );
6368 end
6369 else
6370 begin
6371 // found in one of indices.
6372 // Check for subsequent indented strings
6373 Index := IndexLists[ LowestEntryListIndex ];
6374
6375 i := IndexNextIndex[ LowestEntryListIndex ] + 1;
6376 while i < Index.Count do
6377 begin
6378 pListEntry := Index.ValuePtrs[ i ];
6379 if pListEntry^ = '' then
6380 break;
6381
6382 if pListEntry^[ 1 ] <> ' ' then
6383 // not indented, stop looking
6384 break;
6385
6386 // found one,
6387 Topic := Index.Objects[ i ] as TTopic;
6388 DisplayedIndex.AddObject( pListEntry^,
6389 Topic );
6390 inc( i );
6391 end;
6392 IndexNextIndex[ LowestEntryListIndex ] := i;
6393 end;
6394 end;
6395
6396 ProgressBar.Position := 95;
6397 LogEvent(LogStartup, ' Display index (count = '
6398 + IntToStr( DisplayedIndex.Count )
6399 + ')' );
6400
6401 // Now display the final index list
6402 IndexListBox.Items.Assign( DisplayedIndex );
6403
6404 LogEvent(LogStartup, ' Tidy up' );
6405
6406 IndexLists.Destroy;
6407
6408 DestroyListAndObjects( ContentsLists );
6409
6410 IndexLoaded := true;
6411
6412 ClearWaitCursor;
6413
6414 SetStatus( 'Index loaded' );
6415 LogEvent(LogStartup, ' Done' );
6416end;
6417
6418Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6419 message: string );
6420var
6421 ProgressOnFiles: longint;
6422 Filename: string;
6423 ProgressOnThisFile: longint;
6424
6425begin
6426 Filename := LoadingFilenameList[ LoadingFileIndex ];
6427
6428 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6429 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6430
6431 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6432 100,
6433 LoadingFileMsg
6434 + ExtractFileName( Filename )
6435 + ': '
6436 + message );
6437end;
6438
6439Procedure TMainForm.SetProgress( n, outof: integer;
6440 message: string );
6441begin
6442 ProgressBar.Position := n * 100 div outof;
6443 SetStatus( message );
6444 ProgressBar.Show;
6445end;
6446
6447// Load a single file.
6448Function TMainForm.OpenFile( const FileName: string;
6449 const WindowTitle: string;
6450 const SelectFirstContentsNode: boolean ): boolean;
6451var
6452 FileNames: TStringList;
6453begin
6454 FileNames := TStringList.Create;
6455 FileNames.Add( FileName );
6456 Result := OpenFiles( FileNames,
6457 WindowTitle,
6458 DisplayFirstTopic );
6459 FileNames.Destroy;
6460end;
6461
6462Function TMainForm.OpenAdditionalFile( const FileName: string;
6463 const DisplayFirstTopic: boolean ): boolean;
6464var
6465 FileNames: TStringList;
6466begin
6467 FileNames := TStringList.Create;
6468 FileNames.Add( FileName );
6469 Result := OpenAdditionalFiles( FileNames,
6470 DisplayFirstTopic );
6471 FileNames.Destroy;
6472end;
6473
6474Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6475var
6476 WinHelpDetails: PROGDETAILS;
6477 szFilename: cstring;
6478begin
6479
6480 result := true;
6481 if Settings.ConfirmWinHelp then
6482 result := DoYesNoDlg( WindowsHelpTitle,
6483 WindowsHelpPrompt
6484 + StrCRLF
6485 + FileName );
6486 if not result then
6487 exit;
6488
6489 szFilename := FileName;
6490 with WinHelpDetails do
6491 begin
6492 Length := sizeof( WinHelpDetails );
6493 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6494 progt.fbVisible := SHE_VISIBLE;
6495 pszTitle := ''; // not used?
6496 pszExecutable := 'winhelp.exe';
6497 pszParameters := Addr( szFilename );
6498 pszStartupDir := nil;
6499 pszIcon := nil;
6500 pszEnvironment := nil;
6501 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6502 end;
6503
6504 result := WinStartApp( NULLHANDLE,
6505 WinHelpDetails,
6506 '',
6507 nil,
6508 SAF_INSTALLEDCMDLINE ) <> 0;
6509
6510 // Doesn't work for Dos/Win programs
6511 // RunProgram( 'winhelp.exe', FileName );
6512end;
6513
6514// Load the specified set of help files
6515Function TMainForm.LoadFiles( const FileNames: TStrings;
6516 HelpFiles: TList ): boolean;
6517var
6518 HelpFile: THelpFile;
6519 FileIndex: longint;
6520 FileName: string;
6521 FullFilePath: string;
6522
6523 FileHandlesAdjustNum: LONG;
6524 CurrentMaxFileHandles: ULONG;
6525 RequiredFileHandles: LONG;
6526begin
6527 LogEvent(LogStartup, 'LoadFiles' );
6528
6529 LoadingFilenameList := TStringList.Create;
6530
6531 TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6532
6533 LogEvent(LogStartup, 'Finding files' );
6534
6535 ProgressBar.Show;
6536
6537 // now find full file paths,
6538 // and also the total file size for progress display
6539 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6540 begin
6541 FileName := LoadingFilenameList[ FileIndex ];
6542 LogEvent(LogStartup, ' File: ' + FileName );
6543
6544 // Find the help file, if possible
6545 if Filename = OWN_HELP_MARKER then
6546 begin
6547 FullFilePath := CmdLineParameters.GetOwnHelpFileName;
6548 end
6549 else
6550 begin
6551 FullFilePath := FindHelpFile( Filename );
6552 end;
6553
6554 if FullFilePath <> '' then
6555 begin
6556 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6557 end
6558 else
6559 begin
6560 LogEvent(LogStartup, ' File not found' );
6561 FullFilePath := FileName; // we'll complain later.
6562 end;
6563 LoadingFilenameList[ FileIndex ] := FullFilePath;
6564 end;
6565
6566 // Make sure we have enough file handles
6567
6568 FileHandlesAdjustNum := 0;
6569 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6570 CurrentMaxFileHandles );
6571
6572 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6573 + LoadingFilenameList.Count // new ones
6574 + 40; // some spares.
6575 if CurrentMaxFileHandles < RequiredFileHandles then
6576 begin
6577 // need some more
6578 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6579 DosSetRelMaxFH( FileHandlesAdjustNum,
6580 CurrentMaxFileHandles );
6581 end;
6582
6583 // Now actually load the files
6584 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6585 begin
6586 Filename := LoadingFilenameList[ FileIndex ];
6587 LogEvent(LogStartup, ' Loading: ' + Filename );
6588 try
6589 LoadingFileIndex := FileIndex;
6590
6591 // load the file
6592 HelpFile := THelpFile.Create( FileName );
6593 if Settings.FixedFontSubstitution then
6594 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6595
6596 HelpFiles.Add( HelpFile );
6597
6598 except
6599 on E: Exception do
6600 begin
6601
6602 if E is EWindowsHelpFormatException then
6603 begin
6604 OpenWindowsHelp( Filename );
6605 end
6606 else
6607 begin
6608 DoErrorDlg( FileOpenTitle,
6609 HelpFileError
6610 + FileName
6611 + ': '
6612 + E.Message );
6613 end;
6614
6615 // back out of the load process
6616 Result := false;
6617
6618 DestroyListObjects( HelpFiles );
6619
6620 LoadingFilenameList.Destroy;
6621 ResetProgress;
6622 exit;
6623 end
6624 end;
6625 end;
6626
6627 LoadingFilenameList.Destroy;
6628
6629 Result := true;
6630
6631end;
6632
6633// Add the current list of open files as
6634// a Most Recently Used entry
6635Procedure TMainForm.AddCurrentToMRUFiles;
6636var
6637 Filenames: TStringList;
6638 i: longint;
6639 HelpFile: THelpFile;
6640begin
6641 Filenames := TStringList.Create;
6642
6643 for i := 0 to CurrentOpenFiles.Count - 1 do
6644 begin
6645 HelpFile := CurrentOpenFiles[ i ];
6646 Filenames.Add( HelpFile.Filename );
6647 end;
6648
6649 // update most-recently-used file list
6650 HelpFile := CurrentOpenFiles[ 0 ];
6651 AddToMRUList( HelpFile.Title,
6652 Filenames );
6653
6654 // recreate menu
6655 CreateMRUMenuItems;
6656
6657 Filenames.Destroy;
6658end;
6659
6660// Display the specified set of files
6661Procedure TMainForm.DisplayFiles( NewFiles: TList;
6662 Var FirstContentsNode: TNode );
6663var
6664 HelpFile: THelpFile;
6665 FileIndex: longint;
6666begin
6667 LogEvent(LogStartup, 'DisplayFiles' );
6668 // Now load the various parts of the file(s)
6669 // into the user interface
6670 ProgressBar.Position := 50;
6671 SetStatus( LoadingStatusDisplaying );
6672
6673 // Add our open files in the global filelist
6674 for FileIndex := 0 to NewFiles.Count - 1 do
6675 begin
6676 HelpFile := NewFiles[ FileIndex ];
6677 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6678 // LoadNotes( HelpFile );
6679 LoadBookmarks( HelpFile );
6680 end;
6681
6682 UpdateNotesDisplay;
6683
6684 BuildBookmarksMenu;
6685 UpdateBookmarksForm;
6686
6687 ProgressBar.Position := 55;
6688
6689 ContentsLoaded := false;
6690 IndexLoaded := false;
6691
6692 LoadContents( NewFiles, FirstContentsNode );
6693
6694 ProgressBar.Position := 75;
6695
6696 // LoadIndex;
6697
6698 ProgressBar.Position := 100;
6699 SetStatus( LoadingStatusDone );
6700
6701 LogEvent(LogStartup, 'DisplayFiles Done' );
6702
6703end;
6704
6705Function TMainForm.OpenFiles( const FileNames: TStrings;
6706 const WindowTitle: string;
6707 const DisplayFirstTopic: boolean ): boolean;
6708var
6709 HelpFiles: TList;
6710 FirstContentsNode: TNode;
6711begin
6712 LogEvent(LogStartup, 'OpenFiles' );
6713
6714 if not OKToCloseFile then
6715 exit;
6716
6717 SetWaitCursor;
6718
6719 HelpFiles := TList.Create;
6720
6721 if not LoadFiles( FileNames,
6722 HelpFiles ) then
6723 begin
6724 ClearWaitCursor;
6725 HelpFiles.Destroy;
6726 exit;
6727 end;
6728
6729 Result := true;
6730
6731 SearchResultsListBox.Clear;
6732 PageHistory.Clear;
6733 CurrentHistoryIndex := -1;
6734
6735 // Now that we have successfully loaded the new help file(s)
6736 // close the existing one.
6737 CloseFile;
6738
6739 AssignList( HelpFiles, CurrentOpenFiles );
6740
6741 ProgressBar.Position := 50;
6742 SetStatus( LoadingStatusDisplaying );
6743
6744 AddCurrentToMRUFiles;
6745
6746 if WindowTitle = '' then
6747 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6748 else
6749 MainTitle := WindowTitle;
6750
6751 SetMainCaption;
6752
6753 // Now load the various parts of the file(s)
6754 // into the user interface
6755
6756 ContentsOutline.Clear;
6757
6758 DisplayFiles( HelpFiles,
6759 FirstContentsNode );
6760
6761 if CmdLineParameters.getHelpManagerFlag then
6762 ShowLeftPanel := Settings.ShowLeftPanel_Help
6763 else
6764 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6765
6766 // Select first contents node if there is one
6767 if FirstContentsNode <> nil then
6768 begin
6769 LogEvent(LogStartup, ' Select first node' );
6770 ContentsOutline.SelectedNode := FirstContentsNode;
6771 end;
6772
6773 ClearWaitCursor;
6774
6775 ResetProgress;
6776
6777 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6778
6779 EnableControls;
6780
6781 if DisplayFirstTopic then
6782 begin
6783 LogEvent(LogStartup, 'Display first topic' );
6784 DisplaySelectedContentsTopic;
6785 end;
6786
6787 LogEvent(LogStartup, 'OpenFiles complete' );
6788end;
6789
6790Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6791 const DisplayFirstTopic: boolean ): boolean;
6792var
6793 HelpFiles: TList;
6794 FirstNewContentsNode: TNode;
6795begin
6796 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6797
6798 if not OKToCloseFile then
6799 exit;
6800
6801 SetWaitCursor;
6802
6803 HelpFiles := TList.Create;
6804
6805 if not LoadFiles( FileNames,
6806 HelpFiles ) then
6807 begin
6808 ClearWaitCursor;
6809 HelpFiles.Destroy;
6810 exit;
6811 end;
6812
6813 Result := true;
6814
6815 AddList( HelpFiles, CurrentOpenFiles );
6816
6817 AddCurrentToMRUFiles;
6818
6819 DisplayFiles( HelpFiles,
6820 FirstNewContentsNode );
6821
6822 // Select first contents node of new file
6823 if FirstNewContentsNode <> nil then
6824 ContentsOutline.SelectedNode := FirstNewContentsNode;
6825
6826 HelpFiles.Destroy;
6827
6828 ClearWaitCursor;
6829
6830 ResetProgress;
6831
6832 EnableControls;
6833
6834 if DisplayFirstTopic then
6835 DisplaySelectedContentsTopic;
6836
6837 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6838end;
6839
6840Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6841Begin
6842 FileOpen;
6843end;
6844
6845procedure TMainForm.FileOpen;
6846var
6847 Filenames: TStringList;
6848 KeepCurrentFiles: boolean;
6849 OpenedOK: boolean;
6850begin
6851 if not OKToCloseFile then
6852 exit;
6853
6854 if Settings.UseOriginalDialogs then
6855 begin
6856 SystemOpenDialog.Filename := AddDirectorySeparator( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6857 if not SystemOpenDialog.Execute then
6858 exit;
6859
6860 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6861 // note - sibyl's encapsulation doesn't allow multi-select
6862 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6863 end
6864 else
6865 begin
6866 Filenames := TStringList.Create;
6867 KeepCurrentFiles := false;
6868 if not DoOpenMultiFileDialog( FileOpenTitle,
6869 HelpFilesDesc
6870 + '|*.inf;*.hlp|'
6871 + AllFilesDesc
6872 + '|*.*',
6873 '*.hlp;*.inf',
6874 Settings.LastOpenDirectory,
6875 KeepCurrentFiles,
6876 Filenames ) then
6877 exit;
6878
6879 if KeepCurrentFiles then
6880 OpenedOK := OpenAdditionalFiles( FileNames, true )
6881 else
6882 OpenedOK := OpenFiles( FileNames, '', true );
6883 Filenames.Destroy;
6884 end;
6885
6886 if OpenedOK then
6887 ClearHelpManager;
6888End;
6889
6890Procedure TMainForm.CloseWindows;
6891Begin
6892 DestroyListObjects( Windows );
6893 Windows.Clear;
6894end;
6895
6896// Help manager mode
6897
6898// if window is minimised then restore it
6899// (ideally should go back to maximized - don't know how)
6900Procedure TMainForm.RestoreWindow;
6901Begin
6902 If WindowState = wsMinimized then
6903 WindowState := wsNormal;
6904end;
6905
6906Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6907begin
6908 LogEvent(LogNHM, 'NHMDisplayIndex');
6909 RestoreWindow;
6910 DisplayIndex;
6911 // if nothing is being display already...
6912 if Windows.Count = 0 then
6913 // display first topic
6914 DisplaySelectedContentsTopic;
6915end;
6916
6917Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6918begin
6919 LogEvent(LogNHM, 'NHMDisplayContents');
6920 RestoreWindow;
6921 DisplayContents;
6922 // if nothing is being display already...
6923 if Windows.Count = 0 then
6924 begin
6925 // display first topic
6926 DisplaySelectedContentsTopic;
6927 end;
6928end;
6929
6930Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6931begin
6932 LogEvent(LogNHM, 'NHMTopicByResourceID');
6933 RestoreWindow;
6934 DisplayContents;
6935 DisplayTopicByResourceID( Msg.Param1 );
6936end;
6937
6938Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6939var
6940 pMessageMem: pchar;
6941 PanelName: string;
6942 Topic: TTopic;
6943begin
6944 LogEvent(LogNHM, 'NHMTopicByPanelName');
6945 RestoreWindow;
6946 DisplayContents;
6947
6948 pMessageMem := pchar( Msg.Param1 );
6949 PanelName := StrPas( pMessageMem );
6950 SharedMemory.Free( pMessageMem );
6951
6952 LogEvent(LogNHM, '....NHMTopicByPanelName panel:' + PanelName);
6953 Topic := FindTopicByName( PanelName );
6954 if Topic = nil then
6955 Topic := FindTopicByGlobalName( PanelName );
6956
6957 if Topic <> nil then
6958 DisplayTopic( Topic )
6959 else
6960 SearchFor( PanelName );
6961end;
6962
6963// Sent from other instances starting up (and exiting immediately)
6964
6965Procedure TMainForm.NHMSearch( Var Msg: TMessage );
6966var
6967 pSearchText: pchar;
6968begin
6969 LogEvent(LogNHM, 'NHMSearch');
6970 RestoreWindow;
6971
6972 pSearchText := pstring( Msg.Param1 );
6973 SearchFor( StrPas( pSearchText ) );
6974 SharedMemory.Free( pSearchText );
6975end;
6976
6977Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
6978var
6979 pSearchText: pchar;
6980begin
6981 LogEvent(LogNHM, 'NHMGlobalSearch');
6982 RestoreWindow;
6983
6984 pSearchText := pstring( Msg.Param1 );
6985 DoGlobalSearch( StrPas( pSearchText ) );
6986 SharedMemory.Free( pSearchText );
6987end;
6988
6989Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
6990begin
6991 LogEvent(LogNHM, 'NHMShowUsage');
6992 RestoreWindow;
6993 ShowUsage;
6994end;
6995
6996Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
6997var
6998 pFileNames: pchar;
6999begin
7000 LogEvent(LogNHM, 'NHMSetFiles');
7001 // NOT restoring window here because this is not something the user should see...
7002 pFileNames := pstring( Msg.Param1 );
7003 OpenFilesFromTextList( StrPas( pFileNames ), false );
7004 SharedMemory.Free( pFileNames );
7005end;
7006
7007Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
7008var
7009 pTitle: pchar;
7010begin
7011 LogEvent(LogNHM, 'NHMSetTitle');
7012 pTitle := pstring( Msg.Param1 );
7013 MainTitle := StrPas( pTitle );
7014 SharedMemory.Free( pTitle );
7015
7016 SetMainCaption;
7017end;
7018
7019Procedure TMainForm.NHMTest( Var Msg: TMessage );
7020var
7021 ps: pstring;
7022begin
7023 LogEvent(LogNHM, 'NHMTest');
7024 ps := PString( Msg.Param1 );
7025 ShowMessage( 'Got test message: ' + ps^ );
7026 SharedMemory.Free( ps );
7027end;
7028
7029Initialization
7030 RegisterClasses ([TMainForm, TSplitBar,
7031 TNoteBook,
7032 TEdit, TListBox,
7033 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
7034 TImageList, TPanel, TButton,
7035 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
7036 , TProgressBar, TTabSet2]);
7037End.
Note: See TracBrowser for help on using the repository browser.