source: trunk/NewView/MainForm.pas

Last change on this file was 493, checked in by ataylor, 21 months ago

Undo TForm changes (rollback r492). Opening when window is system-modal now
simply clears system-modality for the lifetime of the NewView application, and
restores it on exit.

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