source: trunk/NewView/MainForm.pas@ 92

Last change on this file since 92 was 92, checked in by RBRi, 19 years ago

again small refactoring

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