source: trunk/NewView/MainForm.pas@ 120

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

changed to use StringUtilsUnit

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