source: trunk/NewView/MainForm.pas@ 468

Last change on this file since 468 was 468, checked in by ataylor, 3 years ago

Improve status bar height logic.

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