source: branches/2.19.1/NewView/MainForm.pas@ 265

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

fixes for 2.19

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