source: 2.19_branch/NewView/MainForm.pas@ 376

Last change on this file since 376 was 332, checked in by RBRi, 17 years ago

small format update

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