source: trunk/NewView/MainForm.pas@ 91

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

file util refactoring and many more unit tests

  • Property svn:eol-style set to native
File size: 183.2 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 LaunchURL( URL );
5477 SetStatus( 'Opened '
5478 + URL );
5479 end
5480 else if StrLeft( LinkString, 8 ) = 'external' then
5481 begin
5482 LinkDetails := StrRightFrom( LinkString, 10 );
5483 LinkIndex := StrToInt( ExtractNextValue( LinkDetails, ' ' ) );
5484 Window := FindWindowFromView( Sender, Windows );
5485 SourceFile := Window.Topic.HelpFile as THelpFile;
5486
5487 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5488 g_ExternalLinkTopic := LinkDetails;
5489 g_ExternalLinkSourceFilename := SourceFile.Filename;
5490 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5491
5492 PostMsg( Self.Handle,
5493 WM_FOLLOWEXTERNALLINK,
5494 0,
5495 0 );
5496 end
5497 else
5498 begin
5499 SourceWindow := FindWindowFromView( Sender, Windows );
5500 LinkIndex := StrToInt( LinkString );
5501 Link := SourceWindow.Topic.Links[ LinkIndex ];
5502
5503 PostMsg( Self.Handle,
5504 WM_FOLLOWLINK,
5505 longint( Link ),
5506 longint( SourceWindow ) );
5507
5508 end;
5509End;
5510
5511Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5512 var CanClose: boolean );
5513begin
5514 if Navigating then
5515 exit;
5516
5517 UpdateCurrentNavigatePoint; // Save it before close...
5518
5519 CanClose := true;
5520end;
5521
5522Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5523var
5524 ParentWindow: THelpWindow;
5525 WindowIndex: longint;
5526Begin
5527 if Navigating then
5528 exit;
5529
5530 if Window.ParentHelpWindow = nil then
5531 begin
5532 WindowIndex := Windows.IndexOf( Window );
5533 Windows.Delete( WindowIndex );
5534 end
5535 else
5536 begin
5537 ParentWindow := Window.ParentHelpWindow;
5538 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5539 ParentWindow.ChildWindows.Delete( WindowIndex );
5540 end;
5541end;
5542
5543Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5544Begin
5545 if Navigating then
5546 exit;
5547
5548 RemoveHelpWindowFromParent( Window );
5549
5550 SaveNavigatePoint;
5551 EnableControls;
5552End;
5553
5554Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5555Begin
5556 NavigateBack;
5557End;
5558
5559Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5560Begin
5561End;
5562
5563Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5564Begin
5565 Close;
5566End;
5567
5568Procedure TMainForm.CreateMRUMenuItems;
5569var
5570 MenuItem: TMenuItem;
5571 i: integer;
5572 FileName: string;
5573 FileNameIndex: longint;
5574 MRUText: string;
5575 MRUItem: TMRUItem;
5576begin
5577 DestroyListObjects( MRUMenuItems );
5578 MRUMenuItems.Clear;
5579
5580 // if there are Most Recently Used files
5581 if Settings.MRUList.Count > 0 then
5582 begin
5583 // create a seperator after Exit
5584 MenuItem:= TMenuItem.Create( self );
5585 MenuItem.Name := 'MRUSeparatorMI';
5586 MenuItem.Caption:= '-';
5587 FileMenu.Add( MenuItem );
5588 MRUMenuItems.Add( MenuItem );
5589 end;
5590
5591 // Add items for the MRU files
5592 for i:= 0 to Settings.MRUList.Count -1 do
5593 begin
5594 MRUItem := Settings.MRUList[ i ];
5595
5596 MenuItem := TMenuItem.Create( self );
5597
5598 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5599 MRUText := MRUItem.Title;
5600 if Trim( MRUText ) = '' then
5601 begin
5602 // Take the filenames, less path, as caption...
5603 MRUText := '';
5604 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5605 begin
5606 FileName := MRUItem.Filenames[ FileNameIndex ];
5607 FileName := ExtractFileName( FileName );
5608 FileName := ChangeFileExt( FileName, '' );// remove extension
5609 AddToListString( MRUText,
5610 FileName,
5611 '+' );
5612
5613 // stop after 50 chars
5614 if Length( MRUText ) > 50 then
5615 begin
5616 MRUText := MRUText + '+ ...';
5617 break;
5618 end;
5619 end;
5620 end;
5621
5622 MenuItem.Caption:= '~'
5623 + IntToStr( i + 1 )
5624 + '. '
5625 + MRUText;
5626 if MRUItem.Filenames.Count = 1 then
5627 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5628 else
5629 MenuItem.Hint := MRUItem.Title
5630 + ' ('
5631 + IntToStr( MRUItem.Filenames.Count )
5632 + ' '
5633 + MRUMultipleFilesHint
5634 + ')';
5635
5636 MenuItem.OnClick:= OnMRUMenuItemClick;
5637 MenuItem.Tag:= i;
5638 FileMenu.Add( MenuItem );
5639 MRUMenuItems.Add( MenuItem );
5640 end;
5641end;
5642
5643procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5644var
5645 Tag: longint;
5646 MenuItem: TMenuItem;
5647 MRUItem: TMRUItem;
5648begin
5649 MenuItem:= Sender as TMenuItem;
5650 Tag:= MenuItem.Tag;
5651 MRUItem := Settings.MRUList[ Tag ];
5652 if OpenFiles( MRUItem.FileNames, '', true ) then
5653 begin
5654 ClearHelpManager;
5655 end;
5656end;
5657
5658Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5659var
5660 MenuItem: TMenuItem;
5661 Tag: longint;
5662begin
5663 MenuItem:= Sender as TMenuItem;
5664 Tag:= MenuItem.Tag;
5665 NavigateToHistoryIndex( Tag );
5666end;
5667
5668Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5669 ParentNode: TNode;
5670 Level: longint;
5671 Var TopicIndex: longint );
5672var
5673 Topic: TTopic;
5674 Node: TNode;
5675begin
5676 assert( ParentNode <> nil );
5677 Node := nil;
5678 while TopicIndex < HelpFile.TopicCount do
5679 begin
5680 Topic:= HelpFile.Topics[ TopicIndex ];
5681
5682 if Topic.ShowInContents then
5683 begin
5684 if Topic.ContentsLevel < Level then
5685 break;
5686
5687 if Topic.ContentsLevel = Level then
5688 begin
5689 Node:= ParentNode.AddChild( Topic.Title,
5690 Topic );
5691 inc( TopicIndex );
5692 end
5693 else
5694 begin
5695 assert( Node <> nil );
5696 AddChildNodes( HelpFile,
5697 Node,
5698 Topic.ContentsLevel,
5699 TopicIndex );
5700 Node := nil;
5701 end
5702 end
5703 else
5704 begin
5705 inc( TopicIndex );
5706 end;
5707 end;
5708
5709end;
5710
5711Procedure TMainForm.LoadContents( Files: TList;
5712 Var FirstNode: TNode );
5713var
5714 TopicIndex: longint;
5715 Topic: TTopic;
5716 Node: TNode;
5717 FileIndex: longint;
5718 HelpFile: THelpFile;
5719begin
5720 ContentsOutline.BeginUpdate;
5721 LogEvent(LogStartup, 'Load contents outline');
5722
5723 // we don't clear it first, to allow adding additional files
5724 // into the contents tree
5725
5726 LogEvent(LogStartup, 'Loop files');
5727
5728 FirstNode := nil;
5729
5730 Node := nil;
5731
5732 for FileIndex:= 0 to Files.Count - 1 do
5733 begin
5734 HelpFile := Files[ FileIndex ];
5735 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5736 TopicIndex := 0;
5737 while TopicIndex < HelpFile.TopicCount do
5738 begin
5739 Topic := HelpFile.Topics[ TopicIndex ];
5740 assert( Topic.ContentsLevel >= 0,
5741 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5742 if Topic.ShowInContents then
5743 begin
5744 if Topic.ContentsLevel = 1 then
5745 begin
5746 Node := ContentsOutline.AddChild( Topic.Title,
5747 Topic );
5748 if FirstNode = nil then
5749 FirstNode := node;
5750
5751 inc( TopicIndex );
5752 end
5753 else
5754 begin
5755 // subnodes
5756 assert( Node <> nil, 'No level 1 topic for subnodes!' );
5757 AddChildNodes( HelpFile,
5758 Node,
5759 Topic.ContentsLevel,
5760 TopicIndex );
5761 Node := nil;
5762 end;
5763 end
5764 else
5765 begin
5766 inc( TopicIndex );
5767 end;
5768 end;
5769 end;
5770 LogEvent(LogStartup, ' EndUpdate' );
5771 ContentsOutline.EndUpdate;
5772
5773 if Settings.OpenWithExpandedContents then
5774 begin
5775 LogEvent(LogStartup, ' Expand all contents' );
5776 ContentsOutline.ExpandAll
5777 end
5778 else if ContentsOutline.ChildCount = 1 then
5779 begin
5780 LogEvent(LogStartup, ' Expand first node' );
5781 // Contents has only one top level node... expand it
5782 FirstNode.Expand;
5783 end;
5784
5785 ContentsLoaded := true;
5786 LogEvent(LogStartup, ' Contents loaded' );
5787
5788end;
5789
5790Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5791var
5792 NotesFileName: string;
5793 TopicIndex: longword;
5794 Note: THelpNote;
5795 NoteIndex: longint;
5796
5797 NotesFile: HFile;
5798 OpenAction: ULong;
5799 rc: APIRET;
5800 CName: Cstring;
5801 FileNoteCount: integer;
5802
5803begin
5804 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5805
5806 if not HelpFile.NotesLoaded then
5807 // we never loaded the notes/displayed a topic from this file
5808 // so don't do anything.
5809 exit;
5810
5811 LogEvent(LogStartup, 'Really saving' );
5812
5813 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5814
5815 FileNoteCount := 0;
5816 for NoteIndex := 0 to Notes.Count - 1 do
5817 begin
5818 Note := Notes[ NoteIndex ];
5819
5820 if Note.Topic.HelpFile = HelpFile then
5821 inc( FileNoteCount );
5822 end;
5823
5824 if FileNoteCount = 0 then
5825 begin
5826 // no notes. delete notes file if it already exists.
5827 if FileExists( NotesFileName ) then
5828 DeleteFile( NotesFileName );
5829 exit;
5830 end;
5831
5832 CName:= NotesFileName;
5833 rc:= DosOpen( CName,
5834 NotesFile,
5835 OpenAction,
5836 0, // file size
5837 0, // attrs
5838 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5839 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5840 nil ); // no eas
5841 if rc <> 0 then
5842 begin
5843 DoErrorDlg( SaveNotesTitle,
5844 SaveNotesError
5845 + EndLine
5846 + NotesFileName
5847 + EndLine
5848 + SysErrorMessage( rc ) );
5849 exit;
5850 end;
5851
5852 for NoteIndex:= 0 to Notes.Count - 1 do
5853 begin
5854 Note:= Notes[ NoteIndex ];
5855
5856 if Note.Topic.HelpFile <> HelpFile then
5857 continue;
5858
5859 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5860
5861 MyWriteLn( NotesFile,
5862 IntToStr( TopicIndex ));
5863 MyWriteLn( NotesFile,
5864 IntToStr( Note.InsertPoint ) );
5865
5866 MyWrite( NotesFile,
5867 Note.Text.AsPChar,
5868 Note.Text.Length );
5869
5870 MyWriteLn( NotesFile,
5871 '' );
5872 MyWriteLn( NotesFile,
5873 '#ENDNOTE#' );
5874
5875 end;
5876
5877 DosClose( NotesFile );
5878end;
5879
5880Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5881var
5882 NotesFileName: string;
5883 TopicIndex: longint;
5884 InsertPoint: longint;
5885 Note: THelpNote;
5886
5887 NotesFile: HFile;
5888 OpenAction: ULong;
5889 rc: APIRET;
5890 CName: Cstring;
5891
5892 Paragraph: TAString;
5893 NotEOF: boolean;
5894 NoteText: TAString;
5895
5896begin
5897 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5898
5899 if HelpFile.NotesLoaded then
5900 exit;
5901
5902 HelpFile.NotesLoaded := true;
5903 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5904
5905 if not FileExists( NotesFileName ) then
5906 // no notes
5907 exit;
5908
5909 CName := NotesFileName;
5910 rc := DosOpen( CName,
5911 NotesFile,
5912 OpenAction,
5913 0, // file size - irrelevant, not creating,
5914 0, // attrs - ''
5915 OPEN_ACTION_OPEN_IF_EXISTS,
5916 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5917 nil ); // no eas
5918 if rc <> 0 then
5919 begin
5920 DoErrorDlg( LoadNotesTitle,
5921 LoadNotesError
5922 + EndLine
5923 + NotesFileName
5924 + EndLine
5925 + SysErrorMessage( rc ) );
5926 exit;
5927 end;
5928
5929 Paragraph := TAString.Create;
5930 NoteText := TAString.Create;
5931
5932 NotEOF := true;
5933
5934 while NotEOF do
5935 begin
5936 // Read contents index
5937 NotEOF := Paragraph.ReadParagraph( NotesFile );
5938 if not NotEOF then
5939 continue;
5940 try
5941 TopicIndex := StrToInt( Paragraph.AsString );
5942 except
5943 TopicIndex := -1;
5944 end;
5945
5946 // Read insert point
5947 NotEOF := Paragraph.ReadParagraph( NotesFile );
5948 if not NotEOF then
5949 continue;
5950 try
5951 InsertPoint := StrToInt( Paragraph.AsString );
5952 except
5953 InsertPoint := -1;
5954 end;
5955
5956 NoteText.Clear;
5957
5958 while NotEOF do
5959 begin
5960 NotEOF := Paragraph.ReadParagraph( NotesFile );
5961 if Paragraph.SameAs( '#ENDNOTE#' ) then
5962 begin
5963 // found end of note
5964 if ( TopicIndex >= 0 )
5965 and ( InsertPoint >= 0 ) then
5966 begin
5967 Note := THelpNote.Create;
5968 Note.Topic := HelpFile.Topics[ TopicIndex ];
5969 Note.InsertPoint := InsertPoint;
5970
5971 // Remove the last end line
5972 Note.Text.Assign( NoteText );
5973 if Note.Text.Length > 2 then
5974 Note.Text.Delete( Note.Text.Length - 2, 2 );
5975
5976 Notes.Add( Note );
5977 end;
5978 break;
5979 end;
5980 NoteText.Add( Paragraph );
5981 NoteText.AddString( #13 + #10 );
5982 end;
5983
5984 end;
5985 DosClose( NotesFile );
5986
5987 Paragraph.Destroy;
5988 NoteText.Destroy;
5989
5990end;
5991
5992Procedure TMainForm.UpdateNotesDisplay;
5993var
5994 NoteIndex: longint;
5995 Note: THelpNote;
5996 NoteTitle: string;
5997begin
5998 NotesListBox.Clear;
5999 for NoteIndex := 0 to Notes.Count - 1 do
6000 begin
6001 Note := Notes[ NoteIndex ];
6002
6003 if Note.Topic > nil then
6004 NoteTitle := Note.Topic.Title
6005 else
6006 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6007 NotesListBox.Items.AddObject( NoteTitle,
6008 Note );
6009 end;
6010 EnableNotesControls;
6011end;
6012
6013Procedure TMainForm.EnableNotesControls;
6014var
6015 NoteSelected: boolean;
6016begin
6017 NoteSelected:= NotesListBox.ItemIndex <> -1;
6018 EditNoteButton.Enabled:= NoteSelected;
6019 GotoNoteButton.Enabled:= NoteSelected;
6020 DeleteNoteButton.Enabled:= NoteSelected;
6021 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6022end;
6023
6024Function TMainForm.OKToCloseFile: boolean;
6025begin
6026 Result := true;
6027
6028 if PrintThread = nil then
6029 // haven't used print thread yet
6030 exit;
6031
6032 if not PrintThread.IsRunning then
6033 // not currently running
6034 exit;
6035
6036 Result := DoConfirmDlg( CheckStopPrintTitle,
6037 CheckStopPrintMsg );
6038
6039end;
6040
6041Procedure TMainForm.StopPrinting;
6042begin
6043 if PrintThread <> nil then
6044 begin
6045 if PrintThread.IsRunning then
6046 begin
6047 SetStatus( StoppingPrintMsg );
6048 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6049 SetStatus( PrintStoppedMsg );
6050 ResetProgress;
6051 end;
6052 end;
6053end;
6054
6055Procedure TMainForm.CloseFile;
6056var
6057 FileIndex: longint;
6058 HelpFile: THelpFile;
6059 M1: longint;
6060begin
6061 StopPrinting;
6062
6063 LogEvent(LogShutdown, 'Set Caption' );
6064 MainTitle := '';
6065 SetMainCaption;
6066
6067 LogEvent(LogShutdown, 'Close Windows' );
6068 CloseWindows;
6069
6070 LogEvent(LogShutdown, 'Set selected node to nil' );
6071 ContentsOutline.SelectedNode:= Nil;
6072
6073 M1:= MemAvail;
6074
6075 LogEvent(LogShutdown, 'Clear contents outline' );
6076 ContentsOutline.Clear;
6077
6078 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6079 M1:= MemAvail;
6080
6081 DisplayedIndex.Clear;
6082 IndexListBox.Clear;
6083 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6084 M1:= MemAvail;
6085
6086 NotesListBox.Clear;
6087 SearchResultsListBox.Clear;
6088
6089 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6090 M1:= MemAvail;
6091
6092 // First save notes and bookmarks.
6093 // It's important we do this first
6094 // since we scan all notes each time to find the ones
6095 // belonging to this file.
6096 SaveBookmarks;
6097
6098 SaveNotes;
6099
6100 ClearAllWordSequences;
6101
6102 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6103
6104 // Now destroy help files
6105 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6106 begin
6107 HelpFile := CurrentOpenFiles[ FileIndex ];
6108 GlobalFilelist.RemoveFile( Frame.Handle,
6109 HelpFile.Filename );
6110 HelpFile.Free;
6111 end;
6112
6113 CurrentOpenFiles.Clear;
6114
6115 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6116 M1 := MemAvail;
6117
6118 LogEvent(LogShutdown, 'Clear notes' );
6119 ClearNotes;
6120
6121 LogEvent(LogShutdown, 'Clear bookmarks' );
6122 ClearBookmarks;
6123
6124 ClearPageHistory;
6125
6126 LogEvent(LogShutdown, 'Enable controls' );
6127 EnableControls;
6128
6129 LogEvent(LogShutdown, 'CloseFile done' );
6130
6131end;
6132
6133Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6134var
6135 FileIndex: longint;
6136begin
6137 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6138 begin
6139 Result:= CurrentOpenFiles[ FileIndex ];
6140 if StringsSame( Result.Filename, FileName ) then
6141 // found
6142 exit;
6143 end;
6144 Result:= nil;
6145end;
6146
6147// This rather horrendous looking bit of code simply:
6148
6149// Gets the contents from each file
6150// Sorts it alphabetically.
6151// Merges all the sorted contents and indexes together,
6152// alphabetically.
6153type
6154 TListType = ( ltContents, ltIndex );
6155
6156procedure TMainForm.LoadIndex;
6157var
6158 HelpFile: THelpFile;
6159 TextCompareResult: integer;
6160
6161 FileIndex: longint;
6162
6163 Contents: TList;
6164 ContentsLists: TList; // of tlist
6165 IndexLists: TList; // of tstringlist
6166 ContentsNextIndex: array[ 0..255 ] of longint;
6167 IndexNextIndex: array[ 0..255 ] of longint;
6168 Topic: TTopic;
6169
6170 ListIndex: longint;
6171
6172 pListEntry: pstring;
6173 pLowestEntry: pstring;
6174 pLastEntry: pstring;
6175
6176 LowestEntryListIndex: longint;
6177 LowestEntryListType: TListType;
6178 LowestEntryTopic: TTopic;
6179
6180 Index: TStringList;
6181
6182 i : longint;
6183begin
6184 LogEvent(LogStartup, 'Create index' );
6185
6186 SetWaitCursor;
6187
6188 LogEvent(LogStartup, ' Get/sort lists' );
6189
6190 ProgressBar.Position := 70;
6191 SetStatus( 'Building index... ' );
6192
6193 ContentsLists := TList.Create;
6194 IndexLists := TList.Create;
6195
6196 // collect the contents and index lists from the files
6197 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6198 begin
6199 HelpFile := CurrentOpenFiles[ FileIndex ];
6200 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6201
6202 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6203 begin
6204 Contents := TList.Create;
6205 Contents.Capacity := HelpFile.TopicCount;
6206
6207 // copy [contents] topic list
6208 for i := 0 to HelpFile.TopicCount - 1 do
6209 begin
6210 Topic := HelpFile.Topics[ i ];
6211 if Topic.ShowInContents then
6212 Contents.Add( Topic );
6213 end;
6214
6215 // sort by title
6216 Contents.Sort( TopicTitleCompare );
6217
6218 ContentsLists.Add( Contents );
6219
6220 // initialise list index
6221 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6222 end;
6223
6224 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6225 begin
6226 IndexLists.Add( HelpFile.Index );
6227 IndexNextIndex[ IndexLists.Count - 1 ] := 0;
6228 end;
6229 end;
6230
6231 // Unlike contents, we do clear the index
6232 // (even if we are adding more files) because we need
6233 // to re-merge the whole thing
6234 DisplayedIndex.Clear;
6235 ProgressBar.Position := 80;
6236
6237 LogEvent(LogStartup, ' Merge lists' );
6238
6239 pLastEntry := NullStr;
6240 while true do
6241 begin
6242 pLowestEntry := NullStr;
6243 LowestEntryListIndex := -1;
6244
6245 // Find alphabetically lowest (remaining) topic
6246
6247 // first, look in contents lists
6248 for ListIndex := 0 to ContentsLists.Count - 1 do
6249 begin
6250 Contents := ContentsLists[ ListIndex ];
6251 if ContentsNextIndex[ ListIndex ] < Contents.Count then
6252 begin
6253 // list is not yet finished, get next entry
6254 Topic := Contents[ ContentsNextIndex[ ListIndex ] ];
6255 pListEntry := Topic.TitlePtr;
6256
6257 if pLowestEntry^ <> '' then
6258 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6259 else
6260 TextCompareResult := -1;
6261
6262 if TextCompareResult < 0 then
6263 begin
6264 // this index entry comes before the lowest one so far
6265 pLowestEntry := pListEntry;
6266 LowestEntryListIndex := ListIndex;
6267 LowestEntryListType := ltContents;
6268 LowestEntryTopic := Topic;
6269 end;
6270 end;
6271 end;
6272
6273 // look in indices
6274 for ListIndex := 0 to IndexLists.Count - 1 do
6275 begin
6276 Index := IndexLists[ ListIndex ];
6277 if IndexNextIndex[ ListIndex ] < Index.Count then
6278 begin
6279 // list is not yet finished, get next entry
6280 pListEntry := Index.ValuePtrs[ IndexNextIndex[ ListIndex ] ];
6281
6282 if pLowestEntry^ <> '' then
6283 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6284 else
6285 TextCompareResult := -1;
6286
6287 if TextCompareResult < 0 then
6288 begin
6289 // this index entry comes before the lowest one so far
6290 pLowestEntry := pListEntry;
6291 LowestEntryListIndex := ListIndex;
6292 LowestEntryListType := ltIndex;
6293 LowestEntryTopic := TTopic( Index.Objects[ IndexNextIndex[ ListIndex ] ] );
6294 end;
6295 end;
6296 end;
6297
6298 if LowestEntryListIndex = -1 then
6299 // we're out
6300 break;
6301
6302 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6303 // add, if different from last
6304 DisplayedIndex.AddObject( pLowestEntry^,
6305 LowestEntryTopic );
6306 pLastEntry := pLowestEntry;
6307
6308 if LowestEntryListType = ltContents then
6309 begin
6310 inc( ContentsNextIndex[ LowestEntryListIndex ] );
6311 end
6312 else
6313 begin
6314 // found in one of indices.
6315 // Check for subsequent indented strings
6316 Index := IndexLists[ LowestEntryListIndex ];
6317
6318 i := IndexNextIndex[ LowestEntryListIndex ] + 1;
6319 while i < Index.Count do
6320 begin
6321 pListEntry := Index.ValuePtrs[ i ];
6322 if pListEntry^ = '' then
6323 break;
6324
6325 if pListEntry^[ 1 ] <> ' ' then
6326 // not indented, stop looking
6327 break;
6328
6329 // found one,
6330 Topic := Index.Objects[ i ] as TTopic;
6331 DisplayedIndex.AddObject( pListEntry^,
6332 Topic );
6333 inc( i );
6334 end;
6335 IndexNextIndex[ LowestEntryListIndex ] := i;
6336 end;
6337 end;
6338
6339 ProgressBar.Position := 95;
6340 LogEvent(LogStartup, ' Display index (count = '
6341 + IntToStr( DisplayedIndex.Count )
6342 + ')' );
6343
6344 // Now display the final index list
6345 IndexListBox.Items.Assign( DisplayedIndex );
6346
6347 LogEvent(LogStartup, ' Tidy up' );
6348
6349 IndexLists.Destroy;
6350
6351 DestroyListAndObjects( ContentsLists );
6352
6353 IndexLoaded := true;
6354
6355 ClearWaitCursor;
6356
6357 SetStatus( 'Index loaded' );
6358 LogEvent(LogStartup, ' Done' );
6359end;
6360
6361Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6362 message: string );
6363var
6364 ProgressOnFiles: longint;
6365 Filename: string;
6366 ProgressOnThisFile: longint;
6367
6368begin
6369 Filename := LoadingFilenameList[ LoadingFileIndex ];
6370
6371 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6372 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6373
6374 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6375 100,
6376 LoadingFileMsg
6377 + ExtractFileName( Filename )
6378 + ': '
6379 + message );
6380end;
6381
6382Procedure TMainForm.SetProgress( n, outof: integer;
6383 message: string );
6384begin
6385 ProgressBar.Position := n * 100 div outof;
6386 SetStatus( message );
6387 ProgressBar.Show;
6388end;
6389
6390// Load a single file.
6391Function TMainForm.OpenFile( const FileName: string;
6392 const WindowTitle: string;
6393 const SelectFirstContentsNode: boolean ): boolean;
6394var
6395 FileNames: TStringList;
6396begin
6397 FileNames := TStringList.Create;
6398 FileNames.Add( FileName );
6399 Result := OpenFiles( FileNames,
6400 WindowTitle,
6401 DisplayFirstTopic );
6402 FileNames.Destroy;
6403end;
6404
6405Function TMainForm.OpenAdditionalFile( const FileName: string;
6406 const DisplayFirstTopic: boolean ): boolean;
6407var
6408 FileNames: TStringList;
6409begin
6410 FileNames := TStringList.Create;
6411 FileNames.Add( FileName );
6412 Result := OpenAdditionalFiles( FileNames,
6413 DisplayFirstTopic );
6414 FileNames.Destroy;
6415end;
6416
6417Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6418var
6419 WinHelpDetails: PROGDETAILS;
6420 szFilename: cstring;
6421begin
6422
6423 result := true;
6424 if Settings.ConfirmWinHelp then
6425 result := DoYesNoDlg( WindowsHelpTitle,
6426 WindowsHelpPrompt
6427 + EndLine
6428 + FileName );
6429 if not result then
6430 exit;
6431
6432 szFilename := FileName;
6433 with WinHelpDetails do
6434 begin
6435 Length := sizeof( WinHelpDetails );
6436 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6437 progt.fbVisible := SHE_VISIBLE;
6438 pszTitle := ''; // not used?
6439 pszExecutable := 'winhelp.exe';
6440 pszParameters := Addr( szFilename );
6441 pszStartupDir := nil;
6442 pszIcon := nil;
6443 pszEnvironment := nil;
6444 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6445 end;
6446
6447 result := WinStartApp( NULLHANDLE,
6448 WinHelpDetails,
6449 '',
6450 nil,
6451 SAF_INSTALLEDCMDLINE ) <> 0;
6452
6453 // Doesn't work for Dos/Win programs
6454 // RunProgram( 'winhelp.exe', FileName );
6455end;
6456
6457// Load the specified set of help files
6458Function TMainForm.LoadFiles( const FileNames: TStrings;
6459 HelpFiles: TList ): boolean;
6460var
6461 HelpFile: THelpFile;
6462 FileIndex: longint;
6463 FileName: string;
6464 FullFilePath: string;
6465
6466 FileHandlesAdjustNum: LONG;
6467 CurrentMaxFileHandles: ULONG;
6468 RequiredFileHandles: LONG;
6469begin
6470 LogEvent(LogStartup, 'LoadFiles' );
6471
6472 LoadingFilenameList := TStringList.Create;
6473
6474 TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6475
6476 LogEvent(LogStartup, 'Finding files' );
6477
6478 ProgressBar.Show;
6479
6480 // now find full file paths,
6481 // and also the total file size for progress display
6482 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6483 begin
6484 FileName := LoadingFilenameList[ FileIndex ];
6485 LogEvent(LogStartup, ' File: ' + FileName );
6486
6487 // Find the help file, if possible
6488 if Filename = OWN_HELP_MARKER then
6489 begin
6490 FullFilePath := CmdLineParameters.GetOwnHelpFileName;
6491 end
6492 else
6493 begin
6494 FullFilePath := FindHelpFile( Filename );
6495 end;
6496
6497 if FullFilePath <> '' then
6498 begin
6499 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6500 end
6501 else
6502 begin
6503 LogEvent(LogStartup, ' File not found' );
6504 FullFilePath := FileName; // we'll complain later.
6505 end;
6506 LoadingFilenameList[ FileIndex ] := FullFilePath;
6507 end;
6508
6509 // Make sure we have enough file handles
6510
6511 FileHandlesAdjustNum := 0;
6512 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6513 CurrentMaxFileHandles );
6514
6515 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6516 + LoadingFilenameList.Count // new ones
6517 + 40; // some spares.
6518 if CurrentMaxFileHandles < RequiredFileHandles then
6519 begin
6520 // need some more
6521 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6522 DosSetRelMaxFH( FileHandlesAdjustNum,
6523 CurrentMaxFileHandles );
6524 end;
6525
6526 // Now actually load the files
6527 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6528 begin
6529 Filename := LoadingFilenameList[ FileIndex ];
6530 LogEvent(LogStartup, ' Loading: ' + Filename );
6531 try
6532 LoadingFileIndex := FileIndex;
6533
6534 // load the file
6535 HelpFile := THelpFile.Create( FileName );
6536 if Settings.FixedFontSubstitution then
6537 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6538
6539 HelpFiles.Add( HelpFile );
6540
6541 except
6542 on E: Exception do
6543 begin
6544
6545 if E is EWindowsHelpFormatException then
6546 begin
6547 OpenWindowsHelp( Filename );
6548 end
6549 else
6550 begin
6551 DoErrorDlg( FileOpenTitle,
6552 HelpFileError
6553 + FileName
6554 + ': '
6555 + E.Message );
6556 end;
6557
6558 // back out of the load process
6559 Result := false;
6560
6561 DestroyListObjects( HelpFiles );
6562
6563 LoadingFilenameList.Destroy;
6564 ResetProgress;
6565 exit;
6566 end
6567 end;
6568 end;
6569
6570 LoadingFilenameList.Destroy;
6571
6572 Result := true;
6573
6574end;
6575
6576// Add the current list of open files as
6577// a Most Recently Used entry
6578Procedure TMainForm.AddCurrentToMRUFiles;
6579var
6580 Filenames: TStringList;
6581 i: longint;
6582 HelpFile: THelpFile;
6583begin
6584 Filenames := TStringList.Create;
6585
6586 for i := 0 to CurrentOpenFiles.Count - 1 do
6587 begin
6588 HelpFile := CurrentOpenFiles[ i ];
6589 Filenames.Add( HelpFile.Filename );
6590 end;
6591
6592 // update most-recently-used file list
6593 HelpFile := CurrentOpenFiles[ 0 ];
6594 AddToMRUList( HelpFile.Title,
6595 Filenames );
6596
6597 // recreate menu
6598 CreateMRUMenuItems;
6599
6600 Filenames.Destroy;
6601end;
6602
6603// Display the specified set of files
6604Procedure TMainForm.DisplayFiles( NewFiles: TList;
6605 Var FirstContentsNode: TNode );
6606var
6607 HelpFile: THelpFile;
6608 FileIndex: longint;
6609begin
6610 LogEvent(LogStartup, 'DisplayFiles' );
6611 // Now load the various parts of the file(s)
6612 // into the user interface
6613 ProgressBar.Position := 50;
6614 SetStatus( LoadingStatusDisplaying );
6615
6616 // Add our open files in the global filelist
6617 for FileIndex := 0 to NewFiles.Count - 1 do
6618 begin
6619 HelpFile := NewFiles[ FileIndex ];
6620 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6621 // LoadNotes( HelpFile );
6622 LoadBookmarks( HelpFile );
6623 end;
6624
6625 UpdateNotesDisplay;
6626
6627 BuildBookmarksMenu;
6628 UpdateBookmarksForm;
6629
6630 ProgressBar.Position := 55;
6631
6632 ContentsLoaded := false;
6633 IndexLoaded := false;
6634
6635 LoadContents( NewFiles, FirstContentsNode );
6636
6637 ProgressBar.Position := 75;
6638
6639 // LoadIndex;
6640
6641 ProgressBar.Position := 100;
6642 SetStatus( LoadingStatusDone );
6643
6644 LogEvent(LogStartup, 'DisplayFiles Done' );
6645
6646end;
6647
6648Function TMainForm.OpenFiles( const FileNames: TStrings;
6649 const WindowTitle: string;
6650 const DisplayFirstTopic: boolean ): boolean;
6651var
6652 HelpFiles: TList;
6653 FirstContentsNode: TNode;
6654begin
6655 LogEvent(LogStartup, 'OpenFiles' );
6656
6657 if not OKToCloseFile then
6658 exit;
6659
6660 SetWaitCursor;
6661
6662 HelpFiles := TList.Create;
6663
6664 if not LoadFiles( FileNames,
6665 HelpFiles ) then
6666 begin
6667 ClearWaitCursor;
6668 HelpFiles.Destroy;
6669 exit;
6670 end;
6671
6672 Result := true;
6673
6674 SearchResultsListBox.Clear;
6675 PageHistory.Clear;
6676 CurrentHistoryIndex := -1;
6677
6678 // Now that we have successfully loaded the new help file(s)
6679 // close the existing one.
6680 CloseFile;
6681
6682 AssignList( HelpFiles, CurrentOpenFiles );
6683
6684 ProgressBar.Position := 50;
6685 SetStatus( LoadingStatusDisplaying );
6686
6687 AddCurrentToMRUFiles;
6688
6689 if WindowTitle = '' then
6690 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6691 else
6692 MainTitle := WindowTitle;
6693
6694 SetMainCaption;
6695
6696 // Now load the various parts of the file(s)
6697 // into the user interface
6698
6699 ContentsOutline.Clear;
6700
6701 DisplayFiles( HelpFiles,
6702 FirstContentsNode );
6703
6704 if CmdLineParameters.getHelpManagerFlag then
6705 ShowLeftPanel := Settings.ShowLeftPanel_Help
6706 else
6707 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6708
6709 // Select first contents node if there is one
6710 if FirstContentsNode <> nil then
6711 begin
6712 LogEvent(LogStartup, ' Select first node' );
6713 ContentsOutline.SelectedNode := FirstContentsNode;
6714 end;
6715
6716 ClearWaitCursor;
6717
6718 ResetProgress;
6719
6720 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6721
6722 EnableControls;
6723
6724 if DisplayFirstTopic then
6725 begin
6726 LogEvent(LogStartup, 'Display first topic' );
6727 DisplaySelectedContentsTopic;
6728 end;
6729
6730 LogEvent(LogStartup, 'OpenFiles complete' );
6731end;
6732
6733Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6734 const DisplayFirstTopic: boolean ): boolean;
6735var
6736 HelpFiles: TList;
6737 FirstNewContentsNode: TNode;
6738begin
6739 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6740
6741 if not OKToCloseFile then
6742 exit;
6743
6744 SetWaitCursor;
6745
6746 HelpFiles := TList.Create;
6747
6748 if not LoadFiles( FileNames,
6749 HelpFiles ) then
6750 begin
6751 ClearWaitCursor;
6752 HelpFiles.Destroy;
6753 exit;
6754 end;
6755
6756 Result := true;
6757
6758 AddList( HelpFiles, CurrentOpenFiles );
6759
6760 AddCurrentToMRUFiles;
6761
6762 DisplayFiles( HelpFiles,
6763 FirstNewContentsNode );
6764
6765 // Select first contents node of new file
6766 if FirstNewContentsNode <> nil then
6767 ContentsOutline.SelectedNode := FirstNewContentsNode;
6768
6769 HelpFiles.Destroy;
6770
6771 ClearWaitCursor;
6772
6773 ResetProgress;
6774
6775 EnableControls;
6776
6777 if DisplayFirstTopic then
6778 DisplaySelectedContentsTopic;
6779
6780 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6781end;
6782
6783Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6784Begin
6785 FileOpen;
6786end;
6787
6788procedure TMainForm.FileOpen;
6789var
6790 Filenames: TStringList;
6791 KeepCurrentFiles: boolean;
6792 OpenedOK: boolean;
6793begin
6794 if not OKToCloseFile then
6795 exit;
6796
6797 if Settings.UseOriginalDialogs then
6798 begin
6799 SystemOpenDialog.Filename := AddDirectorySeparator( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6800 if not SystemOpenDialog.Execute then
6801 exit;
6802
6803 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6804 // note - sibyl's encapsulation doesn't allow multi-select
6805 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6806 end
6807 else
6808 begin
6809 Filenames := TStringList.Create;
6810 KeepCurrentFiles := false;
6811 if not DoOpenMultiFileDialog( FileOpenTitle,
6812 HelpFilesDesc
6813 + '|*.inf;*.hlp|'
6814 + AllFilesDesc
6815 + '|*.*',
6816 '*.hlp;*.inf',
6817 Settings.LastOpenDirectory,
6818 KeepCurrentFiles,
6819 Filenames ) then
6820 exit;
6821
6822 if KeepCurrentFiles then
6823 OpenedOK := OpenAdditionalFiles( FileNames, true )
6824 else
6825 OpenedOK := OpenFiles( FileNames, '', true );
6826 Filenames.Destroy;
6827 end;
6828
6829 if OpenedOK then
6830 ClearHelpManager;
6831End;
6832
6833Procedure TMainForm.CloseWindows;
6834Begin
6835 DestroyListObjects( Windows );
6836 Windows.Clear;
6837end;
6838
6839// Help manager mode
6840
6841// if window is minimised then restore it
6842// (ideally should go back to maximized - don't know how)
6843Procedure TMainForm.RestoreWindow;
6844Begin
6845 If WindowState = wsMinimized then
6846 WindowState := wsNormal;
6847end;
6848
6849Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6850begin
6851 LogEvent(LogNHM, 'NHMDisplayIndex');
6852 RestoreWindow;
6853 DisplayIndex;
6854 // if nothing is being display already...
6855 if Windows.Count = 0 then
6856 // display first topic
6857 DisplaySelectedContentsTopic;
6858end;
6859
6860Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6861begin
6862 LogEvent(LogNHM, 'NHMDisplayContents');
6863 RestoreWindow;
6864 DisplayContents;
6865 // if nothing is being display already...
6866 if Windows.Count = 0 then
6867 begin
6868 // display first topic
6869 DisplaySelectedContentsTopic;
6870 end;
6871end;
6872
6873Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6874begin
6875 LogEvent(LogNHM, 'NHMTopicByResourceID');
6876 RestoreWindow;
6877 DisplayContents;
6878 DisplayTopicByResourceID( Msg.Param1 );
6879end;
6880
6881Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6882var
6883 pMessageMem: pchar;
6884 PanelName: string;
6885 Topic: TTopic;
6886begin
6887 LogEvent(LogNHM, 'NHMTopicByPanelName');
6888 RestoreWindow;
6889
6890 pMessageMem := pchar( Msg.Param1 );
6891 PanelName := StrPas( pMessageMem );
6892 SharedMemory.Free( pMessageMem );
6893
6894 LogEvent(LogNHM, '....NHMTopicByPanelName panel:' + PanelName);
6895 Topic := FindTopicByName( PanelName );
6896 if Topic = nil then
6897 Topic := FindTopicByGlobalName( PanelName );
6898
6899 if Topic <> nil then
6900 DisplayTopic( Topic )
6901 else
6902 SearchFor( PanelName );
6903end;
6904
6905// Sent from other instances starting up (and exiting immediately)
6906
6907Procedure TMainForm.NHMSearch( Var Msg: TMessage );
6908var
6909 pSearchText: pchar;
6910begin
6911 LogEvent(LogNHM, 'NHMSearch');
6912 RestoreWindow;
6913
6914 pSearchText := pstring( Msg.Param1 );
6915 SearchFor( StrPas( pSearchText ) );
6916 SharedMemory.Free( pSearchText );
6917end;
6918
6919Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
6920var
6921 pSearchText: pchar;
6922begin
6923 LogEvent(LogNHM, 'NHMGlobalSearch');
6924 RestoreWindow;
6925
6926 pSearchText := pstring( Msg.Param1 );
6927 DoGlobalSearch( StrPas( pSearchText ) );
6928 SharedMemory.Free( pSearchText );
6929end;
6930
6931Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
6932begin
6933 LogEvent(LogNHM, 'NHMShowUsage');
6934 RestoreWindow;
6935 ShowUsage;
6936end;
6937
6938Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
6939var
6940 pFileNames: pchar;
6941begin
6942 LogEvent(LogNHM, 'NHMSetFiles');
6943 // NOT restoring window here because this is not something the user should see...
6944 pFileNames := pstring( Msg.Param1 );
6945 OpenFilesFromTextList( StrPas( pFileNames ), false );
6946 SharedMemory.Free( pFileNames );
6947end;
6948
6949Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
6950var
6951 pTitle: pchar;
6952begin
6953 LogEvent(LogNHM, 'NHMSetTitle');
6954 pTitle := pstring( Msg.Param1 );
6955 MainTitle := StrPas( pTitle );
6956 SharedMemory.Free( pTitle );
6957
6958 SetMainCaption;
6959end;
6960
6961Procedure TMainForm.NHMTest( Var Msg: TMessage );
6962var
6963 ps: pstring;
6964begin
6965 LogEvent(LogNHM, 'NHMTest');
6966 ps := PString( Msg.Param1 );
6967 ShowMessage( 'Got test message: ' + ps^ );
6968 SharedMemory.Free( ps );
6969end;
6970
6971Initialization
6972 RegisterClasses ([TMainForm, TSplitBar,
6973 TNoteBook,
6974 TEdit, TListBox,
6975 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
6976 TImageList, TPanel, TButton,
6977 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
6978 , TProgressBar, TTabSet2]);
6979End.
Note: See TracBrowser for help on using the repository browser.