source: trunk/NewView/MainForm.pas@ 132

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

changed copyright

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