source: trunk/NewView/MainForm.pas@ 488

Last change on this file since 488 was 488, checked in by ataylor, 23 months ago

Small fix to positioning logic when existing window is open.

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