source: trunk/NewView/MainForm.pas@ 101

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

another DisplayContents fix (problem with ArchiveViewer

  • Property svn:eol-style set to native
File size: 183.7 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 not 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 // the user likes to have english
3895 // the normal automatic will fall back to
3896 // the environment setting but in the special
3897 // case we have to start the default
3898 if CmdLineParameters.getLanguage = 'en' then
3899 begin
3900 LoadLanguage('');
3901 end
3902 else
3903 begin
3904 if CmdLineParameters.getLanguage <> '' then
3905 begin
3906 if not LoadAutoLanguage('newview', CmdLineParameters.getLanguage) then
3907 begin
3908 LoadDefaultLanguage('newview');
3909 end
3910 end
3911 else
3912 begin
3913 LoadDefaultLanguage('newview');
3914 end;
3915 end;
3916
3917 LogEvent(LogSettings, 'Applying settings');
3918 ApplySettings;
3919
3920 // default position is centered..
3921 LogEvent(LogSettings, 'Set default position');
3922 if Width > Screen.Width then
3923 Width := Screen.Width;
3924 if Height > Screen.Height then
3925 Height := Screen.Height;
3926 Left := ( Screen.Width - Width ) div 2;
3927 Bottom := ( Screen.Height - Height ) div 2;
3928
3929 LogEvent(LogSettings, 'ReadWindowPos');
3930 ReadWindowPos( Self );
3931
3932 PositionWindow;
3933
3934 LogEvent(LogSettings, 'Creating MRU list');
3935
3936 CreateMRUMenuItems;
3937
3938 CloseFile;
3939
3940 LogEvent(LogStartup, 'OnCreate done');
3941
3942 if CmdLineParameters.getWindowPositionFlag then
3943 begin
3944 SmartSetWindowPos( self,
3945 CmdLineParameters.getWindowPosition.Left,
3946 CmdLineParameters.getWindowPosition.Bottom,
3947 CmdLineParameters.getWindowPosition.Width,
3948 CmdLineParameters.getWindowPosition.Height,
3949 false );
3950 end;
3951
3952 LogEvent(LogStartup, 'MainFormOnCreate Done');
3953End;
3954
3955Procedure TMainForm.ApplySettings;
3956var
3957 ToolbarBitmap: TBitmap;
3958begin
3959 ContentsOutline.Color:= Settings.Colors[ ContentsBackgroundColorIndex ];
3960 ContentsOutline.PenColor:= Settings.Colors[ ContentsTextColorIndex ];
3961 ContentsOutline.TreeLineColor:= Settings.Colors[ ContentsLinesColorIndex ];
3962 IndexListBox.Color:= Settings.Colors[ IndexBackgroundColorIndex ];
3963 IndexListBox.PenColor:= Settings.Colors[ IndexTextColorIndex ];
3964 SearchResultsListBox.Color:= Settings.Colors[ SearchBackgroundColorIndex ];
3965 SearchResultsListBox.PenColor:= Settings.Colors[ SearchTextColorIndex ];
3966 NotesListBox.Color:= Settings.Colors[ NotesListBackgroundColorIndex ];
3967 NotesListBox.PenColor:= Settings.Colors[ NotesListTextColorIndex ];
3968
3969 SettingFont := true;
3970 Notebook.ParentFont := true;
3971 ContentsOutline.ParentFont := true;
3972 IndexListBox.ParentFont := true;
3973 SearchResultsListBox.ParentFont := true;
3974 NotesListBox.ParentFont := true;
3975 TabSet.ParentFont := true;
3976 Coolbar.ParentFont := true;
3977 if Settings.Fonts[ ApplicationFontIndex ] <> nil then
3978 Font := Settings.Fonts[ ApplicationFontIndex ]
3979 else
3980 Font := GetNiceDefaultFont;
3981 SettingFont := false;
3982
3983 Coolbar.BackgroundBitmap := nil;
3984 if FileExists( Settings.ToolbarBackgroundImageFilename ) then
3985 begin
3986 ToolbarBitmap:= TBitmap.Create;
3987 try
3988 ToolbarBitmap.LoadFromFIle( Settings.ToolbarBackgroundImageFilename );
3989 Coolbar.BackgroundBitmap := ToolbarBitmap;
3990 except
3991 end;
3992 ToolbarBitmap.Destroy;
3993 end;
3994
3995 CoolBar.ShowImages := Settings.ToolbarStyle in [ tsImages, tsImagesAndText ];
3996 CoolBar.ShowText := Settings.ToolbarStyle in [ tsText, tsImagesAndText ];
3997
3998 CoolBar.SetMinConstButtonWidth;
3999
4000 DisplayPanel.Color := Settings.Colors[ TopicBackgroundColorIndex ];
4001
4002 SetupViews( Windows );
4003end;
4004
4005// Setup the rich text views in the specified windows (e.g for changing global settings)
4006Procedure TMainForm.SetupViews( WindowList: TList );
4007var
4008 WindowIndex: longint;
4009 Window: THelpWindow;
4010begin
4011 for WindowIndex := 0 to WindowList.Count - 1 do
4012 begin
4013 Window := WindowList[ WindowIndex ];
4014 Window.SetupRTView;
4015 SetupViews( Window.ChildWindows );
4016 end;
4017end;
4018
4019Procedure TMainForm.PostHelpManagerMessage( MessageType: ULONG;
4020 Param1: long;
4021 Param2: long );
4022var
4023 i: longint;
4024begin
4025 for i := 0 to HelpManagerWindows.Count - 1 do
4026 PostMsg( HWND( HelpManagerWindows[ i ] ),
4027 MessageType,
4028 Param1,
4029 Param2 );
4030end;
4031
4032Procedure TMainForm.ClearHelpManager;
4033Begin
4034 if not CmdLineParameters.getHelpManagerFlag then
4035 exit;
4036
4037 // tell the help manager(s) we are no longer playing with them
4038 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
4039
4040 CmdLineParameters.setHelpManagerFlag(false);
4041
4042 HelpManagerWindows.Clear;
4043End;
4044
4045Procedure TMainForm.MainFormOnShow (Sender: TObject);
4046Begin
4047 EnableCallstackLogging( true );
4048
4049 LogEvent(LogStartup, 'MainFormOnShow');
4050
4051 if CmdLineParameters.getOwnerWindow <> NULLHANDLE then
4052 begin
4053 LogEvent(LogStartup, 'Setting owner: '
4054 + IntToStr( CmdLineParameters.getOwnerWindow));
4055 WinSetOwner( Frame.Handle,
4056 CmdLineParameters.getOwnerWindow );
4057
4058 end;
4059
4060 if CmdLineParameters.getHelpManagerFlag then
4061 begin
4062 LogEvent(LogStartup, ' Help Manager Title: '
4063 + StrNPas( pSharedStruct ^. Title,
4064 SHARED_STRUCT_TITLE_SIZE ) );
4065 HelpManagerVersion := StrNPas( pSharedStruct ^. Version,
4066 SHARED_STRUCT_VERSION_SIZE );
4067 LogEvent(LogStartup, ' Help Manager Version: ' + HelpManagerVersion );
4068
4069 end;
4070
4071 CoolBar.SetMinConstButtonWidth;
4072
4073 LogEvent(LogStartup, 'Post WM_OPENED');
4074
4075 ResetProgress;
4076
4077 AddShortcut( kbF11, kbF11 ); // prev in contents
4078 AddShortcut( kbF12, kbF12 ); // next in contents
4079 AddShortcut( kbF7, kbF7 ); // back
4080 AddShortcut( kbF8, kbF8 ); // forward
4081 AddShortcut( kbCtrlCLeft, kbCtrlCLeft ); // back
4082
4083 PostMsg( Handle, WM_OPENED, 0, 0 );
4084End;
4085
4086Procedure TMainForm.DisplaySelectedContentsTopic;
4087var
4088 Topic: TTopic;
4089Begin
4090 if ContentsOutline.SelectedNode = nil then
4091 exit;
4092 Topic := ContentsOutline.SelectedNode.Data as TTopic;
4093 DisplayTopic( Topic );
4094End;
4095
4096// Check that the HELP and BOOKSHELF environment variables
4097// are defined (as they should be on any working OS/2 system).
4098// Show a warning message if not.
4099Procedure TMainForm.CheckEnvironmentVars;
4100var
4101 HelpOK: boolean;
4102 BookshelfOK: boolean;
4103 ErrorText: string;
4104begin
4105 HelpOK := GetEnv( HelpPathEnvironmentVar ) <> '';
4106 BookshelfOK := GetEnv( BookshelfEnvironmentVar ) <> '';
4107 if HelpOK and BookshelfOK then
4108 // all ok.
4109 exit;
4110
4111 // One or both missing
4112
4113 ErrorText := '';
4114 if not BookshelfOK then
4115 ErrorText := ErrorText
4116 + EnvironmentVarUndefined
4117 + BookshelfEnvironmentVar
4118 + EndLine;
4119
4120 if not HelpOK then
4121 ErrorText := ErrorText
4122 + EnvironmentVarUndefined
4123 + HelpPathEnvironmentVar
4124 + EndLine;
4125
4126 DoWarningDlg( EnvironmentVarErrorTitle,
4127 EnvironmentVarError
4128 + EndLine
4129 + EndLine
4130 + ErrorText );
4131
4132end;
4133
4134Procedure LoadSupportDLL;
4135begin
4136 try
4137 LoadDLLFunction( 'newview.dll',
4138 'LZWDECOMPRESSBLOCK',
4139 hNewViewDLL,
4140 pointer( LZWDecompressBlock ) );
4141 except
4142 on E: Exception do
4143 begin
4144 DoErrorDlg( 'DLL Error',
4145 E.Message );
4146 LZWDecompressBlock := nil;
4147 end;
4148 end;
4149end;
4150
4151Procedure TMainForm.WMOpened( Var Msg: TMessage );
4152var
4153 Filenames: TStringList;
4154 M1: longword;
4155 OpenFirstTopic: boolean;
4156begin
4157 if Application.HelpFile = '' then
4158 DoErrorDlg( 'NewView Help', 'NewView help file not found' );
4159
4160 LoadSupportDLL;
4161
4162 LogEvent(LogStartup, 'WMOpened: SetLayout');
4163
4164 if CmdLineParameters.getHelpManagerFlag then
4165 FShowLeftPanel := Settings.ShowLeftPanel_Help
4166 else
4167 FShowLeftPanel := Settings.ShowLeftPanel_Standalone;
4168
4169 SetLayout;
4170
4171// ProfileEvent( 'Apply settings' );
4172// ApplySettings;
4173
4174 LogEvent(LogStartup, 'Enable controls');
4175 EnableControls;
4176
4177// ProfileEvent( 'ReadWindowPos' );
4178// ReadWindowPos( Self );
4179
4180 LogEvent(LogStartup, 'Finish paint');
4181 Update;
4182
4183 if not CmdLineParameters.getHelpManagerFlag then
4184 begin
4185 LogEvent(LogStartup, 'Check environment vars');
4186 CheckEnvironmentVars;
4187
4188 if CmdLineParameters.getShowUsageFlag then
4189 begin
4190 LogEvent(LogStartup, 'Showing usage');
4191 ShowUsage;
4192 end;
4193 end;
4194
4195 HelpManagerWindows.Add( pointer( CmdLineParameters.getHelpManagerWindow ) );
4196
4197 if CmdLineParameters.getFileNames <> '' then
4198 begin
4199 // open specified files
4200 Filenames := TStringList.Create;
4201
4202 // TODO use StrExtractStrings
4203 StringToList(cmdLineParameters.getFileNames, Filenames, '+' );
4204
4205 LogEvent(LogStartup, 'Call OpenFiles');
4206
4207 OpenFirstTopic := true;
4208
4209 if ( CmdLineParameters.getSearchText <> '' )
4210 OR CmdLineParameters.getSearchFlag
4211 OR CmdLineParameters.getHelpManagerFlag
4212 then
4213 // if we're going to search, don't open first topic
4214 // don't open first topic if we're online help
4215 // in case we are wanting to show a specific topic
4216 // - saves time/flicker
4217 OpenFirstTopic := false;
4218
4219 OpenFiles( Filenames,
4220 CmdLineParameters.getWindowTitle,
4221 OpenFirstTopic );
4222
4223 Filenames.Destroy;
4224
4225 if not CmdLineParameters.getSearchFlag
4226 and not CmdLineParameters.getGlobalSearchFlag
4227 and (CmdLineParameters.getSearchText <> '') then
4228 begin
4229 // search in contents only!
4230 LogEvent(LogStartup, 'Do startup topic search for: "' + CmdLineParameters.getSearchText + '"');
4231
4232 StartupTopicSearch( CmdLineParameters.getSearchText );
4233 end
4234 else if CmdLineParameters.getSearchFlag then
4235 begin
4236 // search in specified files
4237 LogEvent(LogStartup, 'Do search for topic');
4238 DisplaySearch;
4239
4240 SearchFor( CmdLineParameters.getSearchText );
4241 end;
4242 end;
4243
4244 if NOT CmdLineParameters.getShowUsageFlag
4245 AND CmdLineParameters.getGlobalSearchFlag then
4246 begin
4247 // Global search
4248 LogEvent(LogStartup, 'Do global search: ' + CmdLineParameters.getSearchText);
4249 DoGlobalSearch( CmdLineParameters.getSearchText );
4250 end;
4251
4252 LogEvent(LogStartup, 'Open finished');
4253
4254 if CmdLineParameters.getHelpManagerFlag then
4255 begin
4256 // Tell helpmanager(s) our window handle
4257 PostHelpManagerMessage( NHM_VIEWER_READY,
4258 Handle,
4259 0 );
4260 end;
4261
4262 M1:= MemAvail;
4263
4264 StartingUp := false;
4265
4266 LogEvent(LogStartup, 'RUN PROGRAM');
4267end;
4268
4269Procedure TMainForm.MainFormOnResize (Sender: TObject);
4270Begin
4271 if not Visible then
4272 exit;
4273 if Handle = 0 then
4274 exit;
4275
4276 SetLayout;
4277
4278End;
4279
4280Function TMainForm.GetShowLeftPanel: boolean;
4281begin
4282 Result := FShowLeftPanel;
4283end;
4284
4285Procedure TMainForm.SetShowLeftPanel( Value: boolean );
4286begin
4287 ShowLeftPanelMI.Checked := Value;
4288 if Value = FShowLeftPanel then
4289 exit;
4290 FShowLeftPanel := Value;
4291 if FShowLeftPanel then
4292 NotebookOnPageChanged( self ) // make sure page is updated
4293 else
4294 FocusFirstHelpWindow;
4295 EnableControls;
4296 SetLayout;
4297end;
4298
4299Procedure TMainForm.VSplitBarOnChange (NewSplit: LongInt);
4300Begin
4301 if VSplitBar.Left < 30 then
4302 begin
4303 ShowLeftPanel := false
4304 end
4305 else
4306 begin
4307 Settings.LeftPanelWidth := VSplitBar.Left;
4308 ShowLeftPanel := true;
4309 end;
4310 SetLayout;
4311End;
4312
4313// Set the layout of the main form
4314Procedure TMainForm.SetLayout;
4315var
4316 RealClientHeight : longint;
4317 CoolbarSpace: longint;
4318 TextHeight: longint;
4319Begin
4320 TextHeight := Canvas.TextHeight( 'S' );
4321 Tabset.Height := TextHeight + 5;
4322
4323 Coolbar.Visible := Settings.ToolbarStyle <> tsNone;
4324
4325 case Settings.ToolbarStyle of
4326 tsImages:
4327 Coolbar.Height := Coolbar.Sections[ 0 ].Width;
4328 tsText:
4329 Coolbar.Height := TextHeight + 5;
4330 tsImagesAndText:
4331 CoolBar.Height := ButtonImages.GetBitmapReference(0).Width + TextHeight + 10;
4332 end;
4333
4334 CoolbarSpace := Coolbar.Height;
4335 if not Coolbar.Visible then
4336 CoolbarSpace := 0;
4337
4338 StatusPanel.Left:= 0;
4339 StatusPanel.Width:= ClientWidth div 2 - 2;
4340 StatusPanel.Height := TextHeight + 2;
4341
4342 ProgressPanel.Left:= ClientWidth div 2 + 2;
4343 ProgressPanel.Width:= ClientWidth - ProgressPanel.Left;
4344 ProgressPanel.Height := TextHeight + 2;
4345
4346 Notebook.Bottom := StatusPanel.Height + 3;
4347 VSplitBar.Bottom := Notebook.Bottom;
4348 DisplayPanel.Bottom := Notebook.Bottom;
4349
4350 RealClientHeight := ClientHeight
4351 - CoolbarSpace
4352 - Notebook.Bottom;
4353
4354 LogEvent(LogStartup, 'TMainForm.SetLayout');
4355 LogEvent(LogStartup, ' RealClientHeight: ' + IntToStr( RealClientHeight ));
4356
4357 LogEvent(LogStartup, ' Form Width: ' + IntToStr( Width ));
4358 LogEvent(LogStartup, ' Form Height: ' + IntToStr( Height ) );
4359 LogEvent(LogStartup, ' Form ClientWidth: ' + IntToStr( ClientWidth ) );
4360 LogEvent(LogStartup, ' Form ClientHeight: ' + IntToStr( ClientHeight ) );
4361 LogEvent(LogStartup, ' CoolBar.Height: ' + IntToStr( CoolBar.Height ) );
4362 LogEvent(LogStartup, ' CoolBar.Bottom: ' + IntToStr( CoolBar.Bottom ) );
4363
4364 if CurrentOpenFiles.Count > 0 then
4365 VSplitBar.Width := Max( 5, Canvas.TextWidth( ' ' ) )
4366 else
4367 VSplitBar.Width := 0;
4368
4369 VSplitBar.Height := RealClientHeight;
4370
4371 if Settings.LeftPanelWidth > ClientWidth - 50 then
4372 Settings.LeftPanelWidth := ClientWidth - 50;
4373 if Settings.LeftPanelWidth < 50 then
4374 Settings.LeftPanelWidth := 50;
4375
4376 if ShowLeftPanel then
4377 begin
4378 VSplitBar.Left := Settings.LeftPanelWidth;
4379 VSplitBar.Hint := SplitBarDblClickToHide;
4380 end
4381 else
4382 begin
4383 VSplitBar.Left := 0;
4384 VSplitBar.Hint := SplitBarDblClickToShow;
4385 end;
4386
4387 Tabset.Left := 0;
4388 Tabset.Width := VSplitBar.Left;
4389 Tabset.Bottom := ClientHeight
4390 - CoolbarSpace
4391 - Tabset.Height;
4392
4393 Notebook.Left := 0;
4394 Notebook.Width := VSplitBar.Left;
4395 Notebook.Height := RealClientHeight
4396 - Tabset.Height
4397 - 3;
4398
4399 DisplayPanel.Left:= VSplitBar.Left + VSplitBar.Width;
4400 DisplayPanel.Width:= ClientWidth - DisplayPanel.Left;
4401 DisplayPanel.Height := RealClientHeight;
4402 LogEvent(LogStartup, ' DisplayPanel.Width: ' + IntToStr( DisplayPanel.Width ) );
4403 LogEvent(LogStartup, ' DisplayPanel.Height: ' + IntToStr( DisplayPanel.Height ) );
4404 LogEvent(LogStartup, ' DisplayPanel.Bottom: ' + IntToStr( DisplayPanel.Bottom ) );
4405
4406 ProgressBar.Left:= 1;
4407 ProgressBar.Bottom:= 1;
4408 ProgressBar.Width:= ProgressPanel.Width - 2;
4409 ProgressBar.Height:= ProgressPanel.Height - 2;
4410
4411 // Layout the visible help windows also
4412 LayoutWindowList( Windows );
4413End;
4414
4415// Lay out the specified list of help windows
4416Procedure TMainForm.LayoutWindowList( WindowList: TList );
4417var
4418 Window: THelpWindow;
4419 WindowIndex: longint;
4420begin
4421 for WindowIndex:= 0 to WindowList.Count - 1 do
4422 begin
4423 Window:= WindowList[ WindowIndex ];
4424 Window.SetLayout;
4425 end;
4426end;
4427
4428Procedure TMainForm.FindNextMIOnClick (Sender: TObject);
4429begin
4430 if FindText = '' then
4431 begin
4432 FindMIOnClick( sender );
4433 exit;
4434 end;
4435
4436 if GetActiveWindow = nil then
4437 begin
4438 DoErrorDlg( FindTitle,
4439 FindSelectWindowError );
4440 exit;
4441 end;
4442
4443 DoFind( foFromCurrent );
4444end;
4445
4446Procedure TMainForm.DoFind( FindOrigin: TFindOrigin );
4447var
4448 Window: THelpWindow;
4449begin
4450 SetWaitCursor;
4451 Window := GetActiveWindow;
4452 if not Window.View.Find( FindOrigin, FindText ) then
4453 begin
4454 SetStatus( TextNotFoundMsg );
4455 Beep( 1000, 100 );
4456 end;
4457 ClearWaitCursor;
4458End;
4459
4460Procedure TMainForm.FindMIOnClick (Sender: TObject);
4461begin
4462 if GetActiveWindow = nil then
4463 begin
4464 DoErrorDlg( FindTitle,
4465 FindSelectWindowError );
4466 exit;
4467 end;
4468 if not DoInputQuery( FindTitle,
4469 FindPrompt,
4470 FindText ) then
4471 exit;
4472
4473 DoFind( foFromStart );
4474End;
4475
4476Procedure TMainForm.IndexSearchEditOnScan (Sender: TObject;
4477 Var KeyCode: TKeyCode);
4478Begin
4479 case KeyCode of
4480 kbCUp:
4481 begin
4482 if IndexListBox.ItemIndex > 0 then
4483 IndexListBox.ItemIndex:= IndexListBox.ItemIndex - 1;
4484 KeyCode:= kbNull;
4485 end;
4486
4487 kbCDown:
4488 begin
4489 if IndexListBox.ItemIndex < IndexListBox.Items.Count - 1 then
4490 IndexListBox.ItemIndex:= IndexListBox.ItemIndex + 1;
4491 KeyCode:= kbNull;
4492 end;
4493
4494 kb_VK + VK_NEWLINE:
4495 begin
4496 DisplaySelectedIndexTopic;
4497 end;
4498 end;
4499
4500End;
4501
4502Procedure TMainForm.IndexSearchEditOnChange (Sender: TObject);
4503var
4504 MatchIndex: longint;
4505 IndexINdex: longint;
4506 SearchText: string;
4507Begin
4508 if InIndexSearch then
4509 exit;
4510
4511 MatchIndex:= -1;
4512 SearchText:= trim( IndexSearchEdit.Text );
4513 for IndexIndex:= 0 to DisplayedIndex.Count - 1 do
4514 begin
4515 if StrStarts( SearchText, DisplayedIndex[ IndexIndex ] ) then //IndexEntry ) then
4516 begin
4517 MatchIndex:= IndexIndex;
4518 break;
4519 end;
4520 end;
4521
4522 if MatchIndex = -1 then
4523 exit;
4524
4525 InIndexSearch:= true;
4526
4527 if IndexListBox.ItemIndex <> MatchIndex then
4528 IndexListBox.ItemIndex:= MatchIndex;
4529
4530 InIndexSearch:= false;
4531End;
4532
4533Procedure TMainForm.FileInformationMIOnClick (Sender: TObject);
4534var
4535 FileIndex: longint;
4536 HelpFile: THelpFile;
4537
4538 TotalTopicCount: longint;
4539 TotalIndexCount: longint;
4540 TotalFileSize: longint;
4541
4542Begin
4543 TotalTopicCount := 0;
4544 TotalIndexCount := 0;
4545 TotalFileSize := 0;
4546
4547 with InformationForm.InformationMemo do
4548 begin
4549 BeginUpdate;
4550 Lines.Clear;
4551 Lines.Add( FilesInfoTitle );
4552 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4553 begin
4554 HelpFile := CurrentOpenFiles[ FileIndex ];
4555
4556 Lines.Add( FilesInfoFilename + HelpFile.FileName );
4557 Lines.Add( FilesInfoFileTitle
4558 + HelpFile.Title );
4559 Lines.Add( FilesInfoTopicCount
4560 + IntToStr( HelpFile.TopicCount ) );
4561 Lines.Add( FilesInfoIndexCount
4562 + IntToStr( HelpFile.Index.Count ) );
4563 Lines.Add( FilesInfoDictionaryCount
4564 + IntToStr( HelpFile.DictionaryCount ) );
4565 Lines.Add( FilesInfoFileSize
4566 + IntToStr( HelpFile.FileSize ) );
4567
4568 inc( TotalTopicCount, HelpFile.TopicCount );
4569 inc( TotalIndexCount, HelpFile.Index.Count );
4570 inc( TotalFileSize, HelpFile.FileSize );
4571
4572 end;
4573
4574 Lines.Add( '' );
4575 Lines.Add( FilesInfoTotalTopicCount
4576 + IntToStr( TotalTopicCount ) );
4577 Lines.Add( FilesInfoTotalIndexCount
4578 + IntToStr( TotalIndexCount ) );
4579 Lines.Add( FilesInfoTotalFileSize
4580 + IntToStr( TotalFileSize ) );
4581 Lines.Add( '' );
4582
4583 EndUpdate;
4584 end;
4585 InformationForm.ShowModal;
4586End;
4587
4588Procedure TMainForm.DisplaySelectedSearchResultTopic;
4589var
4590 Topic: TTopic;
4591Begin
4592 if SearchResultsListBox.ItemIndex = -1 then
4593 exit;
4594 if SelectedObject( SearchResultsListBox ) = nil then
4595 // the "no results" place holder
4596 exit;
4597 Topic := SelectedObject( SearchResultsListBox ) as TTopic;
4598 DisplayTopic( Topic );
4599End;
4600
4601Procedure TMainForm.SearchTextEditOnScan (Sender: TObject;
4602 Var KeyCode: TKeyCode);
4603Begin
4604 case KeyCode of
4605 kbCUp:
4606 begin
4607 if SearchResultsListBox.ItemIndex > 0 then
4608 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex - 1;
4609 KeyCode := kbNull;
4610 SearchResultsListBox.Focus;
4611 end;
4612
4613 kbCDown:
4614 begin
4615 if SearchResultsListBox.ItemIndex < SearchResultsListBox.Items.Count - 1 then
4616 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex + 1;
4617 KeyCode := kbNull;
4618 SearchResultsListBox.Focus;
4619 end;
4620 end;
4621End;
4622
4623Procedure TMainForm.SearchButtonOnClick (Sender: TObject);
4624Begin
4625 DoSearch;
4626End;
4627
4628// Matches old stupid View algorithm
4629Procedure TMainForm.StartupTopicSearch( const SearchText: string );
4630var
4631 i: longint;
4632 HelpFile: THelpFile;
4633 Topic: TTopic;
4634 // s: string;
4635begin
4636 // search files in order they are open
4637 for i := 0 to CurrentOpenFiles.Count - 1 do
4638 begin
4639 HelpFile := THelpFile( CurrentOpenFiles[ i ] );
4640
4641 // look for a topic whose title starts with the searchtext
4642 Topic := HelpFile.FindTopicByTitleStartsWith( SearchText );
4643
4644 if Topic = nil then
4645 // look for an index entry that starts with the searchtext
4646 Topic := HelpFile.FindTopicByIndexStartsWith( SearchText );
4647
4648 if Topic = nil then
4649 // look for a topic whose title contains the searchtext
4650 Topic := HelpFile.FindTopicByTitleContains( SearchText );
4651
4652 if Topic = nil then
4653 // look for an index entry that contains the searchtext
4654 Topic := HelpFile.FindTopicByIndexContains( SearchText );
4655
4656 if Topic <> nil then
4657 begin
4658 // found something, display it (don't keep searching files)
4659 DisplayTopic( Topic );
4660 exit;
4661 end;
4662 end;
4663 DoErrorDlg( SearchTitle, TextNotFoundMsg );
4664end;
4665
4666Procedure TMainForm.SearchFor( const SearchText: string );
4667begin
4668 SearchTextEdit.Text := SearchText;
4669 DisplaySearch;
4670 SearchResultsListBox.Focus;
4671
4672 // force repaint of everything before we start searching.
4673 Update;
4674
4675 DoSearch;
4676end;
4677
4678Procedure TMainForm.ClearAllWordSequences;
4679var
4680 i: longint;
4681 FileWordSequences: TList;
4682 HelpFile: THelpFile;
4683begin
4684 if AllFilesWordSequences = nil then
4685 exit;
4686
4687 for i := 0 to AllFilesWordSequences.Count - 1 do
4688 begin
4689 FileWordSequences := AllFilesWordSequences[ i ];
4690 HelpFile := CurrentOpenFiles[ i ];
4691 ClearWordSequences( FileWordSequences, HelpFile.DictionaryCount );
4692 FileWordSequences.Destroy;
4693 end;
4694 AllFilesWordSequences.Clear;
4695end;
4696
4697// Perform search for text in searchedit.
4698Procedure TMainForm.DoSearch;
4699var
4700 SearchResults: TList;
4701 SearchText: string;
4702 FileIndex: longint;
4703 HelpFile: THelpFile;
4704 TopicIndex: longint;
4705 Topic: TTopic;
4706 FileWordSequences: TList;
4707 Query: TTextSearchQuery;
4708begin
4709 SearchText := Trim( SearchTextEdit.Text );
4710
4711 SearchResultsListBox.Clear;
4712
4713 if SearchText = '' then
4714 exit;
4715
4716 SearchResultsListBox.Items.Add( SearchingMsg );
4717 SetStatus( SearchingMsg );
4718
4719 try
4720 Query := TTextSearchQuery.Create( SearchText );
4721 except
4722 on e: ESearchSyntaxError do
4723 begin
4724 DoErrorDlg( SearchTitle,
4725 SearchSyntaxError
4726 + e.Message );
4727 exit;
4728 end;
4729 end;
4730
4731 ClearAllWordSequences;
4732
4733 SetWaitCursor;
4734
4735 SearchResults := TList.Create;
4736
4737 // Search open help file
4738 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4739 begin
4740 HelpFile := CurrentOpenFiles[ FileIndex ];
4741
4742 FileWordSequences := TList.Create;
4743
4744 try
4745 SearchHelpFile( HelpFile,
4746 Query,
4747 SearchResults,
4748 FileWordSequences );
4749 except
4750 on E: EHelpFileException do
4751 begin
4752 DoErrorDlg( ErrorTitle, E.Message );
4753 Query.Destroy;
4754 ClearWaitCursor;
4755 exit;
4756 end;
4757 end;
4758
4759 AllFilesWordSequences.Add( FileWordSequences );
4760
4761 end;
4762
4763 // Sort results across all files by relevance
4764 SearchResults.Sort( TopicRelevanceCompare );
4765
4766 // Load topics into search results list.
4767 SearchResultsListBox.BeginUpdate;
4768 SearchResultsListBox.Clear;
4769
4770 for TopicIndex := 0 to SearchResults.Count - 1 do
4771 begin
4772 Topic := SearchResults[ TopicIndex ];
4773 SearchResultsListBox.Items.AddObject( Topic.Title
4774 + ' ['
4775 + IntToStr( Topic.SearchRelevance )
4776 + ']',
4777 Topic );
4778 end;
4779
4780 EnableControls;
4781 if SearchResultsListBox.Items.Count > 0 then
4782 // there are some search matches, so highlight words
4783 ViewHighlightSearchWordsMI.Checked := true;
4784
4785 SearchResultsListBox.ItemIndex := -1;
4786 SearchResultsListBox.EndUpdate;
4787
4788 Query.Destroy;
4789 SearchResults.Destroy;
4790
4791 if SearchResultsListBox.Items.Count > 0 then
4792 begin
4793 SearchResultsListBox.ItemIndex := 0;
4794 end
4795 else
4796 begin
4797 SearchResultsListBox.Items.Add( NoSearchMatchesMsg
4798 + ': '
4799 + SearchText );
4800 RefreshWindows( Windows ); // update to remove old highlights
4801 end;
4802 SetStatus( SearchFoundMsgA
4803 + IntToStr( SearchResultsListBox.Items.Count )
4804 + SearchFoundMsgB
4805 + StrDoubleQuote( SearchText ) );
4806
4807 ClearWaitCursor;
4808
4809 DisplaySelectedSearchResultTopic;
4810
4811End;
4812
4813Procedure TMainForm.FileSaveAsMIOnClick (Sender: TObject);
4814var
4815 F: File;
4816 EntryText: PChar;
4817 TextLength: longint;
4818 Window: THelpWindow;
4819 Filename: string;
4820Begin
4821 Window := GetActiveWindow;
4822 if Window = nil then
4823 begin
4824 DoErrorDlg( FileSaveTitle,
4825 FileSaveSelectWindowError );
4826 exit;
4827 end;
4828
4829 if DoSaveFileDialog( FileSaveTitle,
4830 AllFilesDesc + '|*',
4831 DefaultSaveTopicFilename,
4832 Settings.LastSaveDirectory,
4833 Filename ) then
4834 begin
4835 if FileExists( Filename ) then
4836 if not DoConfirmDlg( FileSaveTitle,
4837 ReplaceFilePromptA
4838 + Filename
4839 + ReplaceFilePromptB ) then
4840 exit;
4841 System.Assign( F, Filename );
4842
4843 try
4844 Rewrite( F );
4845 except
4846 on E: Exception do
4847 begin
4848 DoErrorDlg( FileSaveTitle,
4849 UnableToSaveError
4850 + Filename
4851 + ': '
4852 + E.Message );
4853 exit;
4854 end;
4855 end;
4856
4857 // find out length of (plain) text
4858 TextLength := Window.View.CopyTextToBuffer( nil, -1 );
4859
4860 // allocate space
4861 EntryText:= StrAlloc( TextLength );
4862
4863 // get the plain text
4864 Window.View.CopyTextToBuffer( EntryText, TextLength );
4865
4866 // save to file
4867 System.BlockWrite( F, EntryText^, TextLength );
4868
4869 // free space
4870 StrDispose( EntryText );
4871
4872 System.Close( F );
4873 end;
4874End;
4875
4876Procedure TMainForm.OptionsMIOnClick (Sender: TObject);
4877begin
4878 DoOptions;
4879end;
4880
4881Procedure TMainForm.DoOptions;
4882Begin
4883 EnsureOptionsFormLoaded;
4884
4885 GetColors; // in case changed by drag drop
4886
4887 if OptionsForm.ShowModal = mrOK then
4888 begin
4889 ApplySettings;
4890 SetLayout;
4891 RefreshFontSubstitutions;
4892 RefreshWindows( Windows );
4893 end;
4894End;
4895
4896Procedure TMainForm.ShowUsage;
4897begin
4898 DoMessageDlg( UsageTitle,
4899 UsageText1 + EndLine
4900 + UsageText2 + EndLine
4901 + UsageText3 + EndLine
4902 + UsageText4 + EndLine
4903 + UsageText5 + EndLine
4904 + UsageText6 + EndLine
4905 + UsageText7 + EndLine
4906 + UsageText8 );
4907end;
4908
4909Procedure TMainForm.TabSetOnChange (Sender: TObject; NewTab: LongInt;
4910 Var AllowChange: Boolean);
4911Begin
4912 NoteBook.PageIndex := NewTab;
4913End;
4914
4915Procedure TMainForm.NotebookOnSetupShow (Sender: TObject);
4916Begin
4917 ContentsOutline.xStretch := xsFrame;
4918 ContentsOutline.yStretch := ysFrame;
4919
4920 IndexSearchEdit.yAlign := yaTop;
4921 IndexSearchEdit.xStretch := xsFrame;
4922 IndexListBox.yStretch := ysFrame;
4923 IndexListBox.xStretch := xsFrame;
4924
4925 SearchTextEdit.yAlign := yaTop;
4926 SearchTextEdit.xStretch := xsFrame;
4927 SearchButton.yAlign := yaTop;
4928 SearchButton.xAlign := xaRight;
4929 SearchResultsListBox.xStretch := xsFrame;
4930 SearchResultsListBox.yStretch := ysFrame;
4931
4932 NotesListBox.xStretch := xsFrame;
4933 NotesListBox.yStretch := ysFrame;
4934End;
4935
4936Procedure TMainForm.EnableControls;
4937var
4938 BackEnabled: boolean;
4939 ForwardEnabled: boolean;
4940 FileOpen: boolean;
4941 WindowOpen: boolean;
4942 AtTop: boolean;
4943 AtBottom: boolean;
4944begin
4945 ViewContentsMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piContents );
4946 ViewIndexMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piIndex );
4947 ViewSearchMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piSearch );
4948 ViewNotesMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piNotes );
4949
4950 BackEnabled := CurrentHistoryIndex > 0;
4951 ForwardEnabled := CurrentHistoryIndex < PageHistory.Count - 1;
4952
4953 FileOpen := CurrentOpenFiles.Count > 0;
4954 WindowOpen := Windows.Count > 0;
4955
4956 ViewContentsMI.Enabled := FileOpen;
4957 ViewIndexMI.Enabled := FileOpen;
4958 ViewSearchMI.Enabled := FileOpen;
4959 ViewNotesMI.Enabled := FileOpen;
4960
4961 ShowLeftPanelMI.Enabled := FileOpen;
4962
4963 Coolbar.Sections[ ciBack ].Disabled := not BackEnabled;
4964 NavigateBackMI.Enabled := BackEnabled;
4965 Coolbar.Sections[ ciForward ].Disabled := not ForwardEnabled;
4966 NavigateForwardMI.Enabled := ForwardEnabled;
4967
4968 FileSaveAsMI.Enabled := FileOpen;
4969
4970 Coolbar.Sections[ ciPrint ].Disabled := not FileOpen;
4971 PrintMI.Enabled := FileOpen;
4972 FileInformationMI.Enabled := FileOpen;
4973
4974 Coolbar.Sections[ ciAddBookmark ].Disabled := not FileOpen;
4975 AddBookmarkMI.Enabled := FileOpen;
4976 EditBookmarksMI.Enabled := FileOpen;
4977 Coolbar.Sections[ ciAddNote ].Disabled := not FileOpen;
4978 AddNoteMI.Enabled := FileOpen;
4979
4980 if ContentsOutline.SelectedNode <> nil then
4981 begin
4982 AtTop := ContentsOutline.NextNodeUp( ContentsOutline.SelectedNode, false ) = nil;
4983 AtBottom := ContentsOutline.NextNodeDown( ContentsOutline.SelectedNode, false ) = nil;
4984 end;
4985
4986 NavigateNextMI.Enabled := FileOpen
4987 and ( ContentsOutline.SelectedNode <> nil )
4988 and ( not AtBottom );
4989 Coolbar.Sections[ ciNext ].Disabled := not NavigateNextMI.Enabled;
4990 NavigatePreviousMI.Enabled := FileOpen
4991 and ( ContentsOutline.SelectedNode <> nil )
4992 and ( not AtTop );
4993 Coolbar.Sections[ ciPrevious ].Disabled := not NavigatePreviousMI.Enabled;
4994
4995 FileCloseMI.Enabled := FileOpen;
4996
4997 FindMI.Enabled := WindowOpen;
4998 FindNextMI.Enabled := WindowOpen;
4999 CopyMI.Enabled := WindowOpen;
5000 SelectAllMI.Enabled := WindowOpen;
5001
5002 ViewExpandAllMI.Enabled := ContentsOutline.ChildCount > 0;
5003 ViewCollapseAllMI.Enabled := ContentsOutline.ChildCount > 0;
5004
5005 DebugTopicByResourceIDMI.Enabled := FileOpen;
5006 TopicByNameMI.Enabled := FileOpen;
5007
5008 ViewHighlightSearchWordsMI.Enabled := SearchResultsListBox.Items.Count > 0;
5009 if not ViewHighlightSearchWordsMI.Enabled then
5010 ViewHighlightSearchWordsMI.Checked := false;
5011
5012 ViewRefreshMI.Enabled := WindowOpen;
5013
5014 EnableSearchButton;
5015 EnableNotesControls;
5016
5017 VSplitBar.Visible := FileOpen;
5018 if not FileOpen then
5019 begin
5020 SetShowLeftPanel( false );
5021 end;
5022
5023
5024end;
5025
5026Procedure TMainForm.NavigateBackMIOnClick (Sender: TObject);
5027begin
5028 NavigateBack;
5029end;
5030
5031Procedure TMainForm.SaveNavigatePoint;
5032var
5033 NavPoint: TNavigatePoint;
5034begin
5035 // delete rest of history.
5036 while CurrentHistoryIndex < PageHistory.Count - 1 do
5037 begin
5038 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex + 1 ] as TNavigatePoint;
5039 NavPoint.Destroy;
5040 PageHistory.Delete( CurrentHistoryIndex + 1 );
5041 end;
5042
5043 NavPoint:= TNavigatePoint.Create;
5044 SaveWindows( Windows, NavPoint.Windows, nil );
5045
5046 if ContentsOutline.SelectedNode <> nil then
5047 NavPoint.ContentsTopic:= ContentsOutline.SelectedNode.Data as TTopic
5048 else
5049 NavPoint.ContentsTopic:= nil;
5050
5051 if CurrentTopic <> nil then
5052 PageHistory.AddObject( CurrentTopic.Title, NavPoint )
5053 else
5054 PageHistory.AddObject( '', NavPoint );
5055
5056 inc( CurrentHistoryIndex );
5057
5058 CreateNavigateToMenuItems;
5059end;
5060
5061Procedure TMainForm.UpdateCurrentNavigatePoint;
5062var
5063 NavPoint: TNavigatePoint;
5064begin
5065 if CurrentHistoryIndex = -1 then
5066 exit;
5067
5068 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5069
5070 DestroyListObjects( NavPoint.Windows );
5071 NavPoint.Windows.Clear;
5072
5073 SaveWindows( Windows, NavPoint.Windows, nil );
5074end;
5075
5076Procedure TMainForm.ClearPageHistory;
5077var
5078 i: longint;
5079 NavPoint: TNavigatePoint;
5080begin
5081 for i := 0 to PageHistory.Count - 1 do
5082 begin
5083 NavPoint := PageHistory.Objects[ i ] as TNavigatePoint;
5084 NavPoint.Destroy;
5085 end;
5086 PageHistory.Clear;
5087 CurrentHistoryIndex := -1;
5088 CreateNavigateToMenuItems;
5089 EnableControls;
5090end;
5091
5092Procedure TMainForm.SaveWindows( SourceList: TList;
5093 DestList: TList;
5094 Parent: TSavedHelpWindow );
5095
5096var
5097 WindowIndex: longint;
5098 Window: THelpWindow;
5099 WindowCopy: TSavedHelpWindow;
5100begin
5101 // limit storage to only what's need since list will be static.
5102 DestList.Capacity := SourceList.Count;
5103 for WindowIndex := 0 to SourceList.Count - 1 do
5104 begin
5105 Window := SourceList[ WindowIndex ];
5106 WindowCopy := TSavedHelpWindow.Create;
5107 WindowCopy.Parent := Parent;
5108 WindowCopy.Rect.Assign( Window.Rect );
5109 WindowCopy.Topic := Window.Topic;
5110 WindowCopy.Group := Window.Group;
5111 WindowCopy.TopCharIndex := Window.View.TopCharIndex;
5112 SaveWindows( Window.ChildWindows, WindowCopy.ChildWindows, WindowCopy );
5113 DestList.Add( WindowCopy );
5114 end;
5115end;
5116
5117Procedure TMainForm.DisplayWindows( WindowList: TList;
5118 Parent: THelpWindow );
5119var
5120 WindowIndex: longint;
5121 WindowCopy: TSavedHelpWindow;
5122 NewWindow: THelpWindow;
5123begin
5124 for WindowIndex := 0 to WindowList.Count - 1 do
5125 begin
5126 WindowCopy := WindowList[ WindowIndex ];
5127 NewWindow := OpenWindow( WindowCopy.Topic,
5128 WindowCopy.Group,
5129 Parent,
5130 WindowCopy.Rect,
5131 false ); // don't follow links
5132 NewWindow.View.TopCharIndex := WindowCopy.TopCharIndex;
5133 DisplayWindows( WindowCopy.ChildWindows, NewWindow );
5134 end;
5135end;
5136
5137Procedure TMainForm.CreateNavigateToMenuItems;
5138var
5139 MenuItem: TMenuItem;
5140 i: integer;
5141begin
5142 // clear existing items
5143 DestroyListObjects( NavigateToMenuItems );
5144 NavigateToMenuItems.Clear;
5145
5146 if CurrentHistoryIndex > 0 then
5147 begin
5148 // We are going to add some items, so
5149 // add a seperator from the rest of the menu first
5150 MenuItem := TMenuItem.Create( self );
5151 MenuItem.Caption:= '-';
5152 NavigateMenu.Add( MenuItem );
5153 NavigateToMenuItems.Add( MenuItem );
5154 end;
5155
5156 i := CurrentHistoryIndex - 1; // don't include the current history item
5157 while ( ( i >= 0 )
5158 and ( i > CurrentHistoryIndex - 10 ) ) do
5159 begin
5160 MenuItem := TMenuItem.Create( self );
5161 MenuItem.Caption := PageHistory[ i ];
5162 MenuItem.Hint := GoBackHint
5163 + StrDoubleQuote( PageHistory[ i ] );
5164 MenuItem.OnClick := OnNavigateToMenuItemClick;
5165 MenuItem.Tag := i;
5166
5167 NavigateMenu.Add( MenuItem );
5168 NavigateToMenuItems.Add( MenuItem );
5169 dec( i );
5170 end;
5171end;
5172
5173Procedure TMainForm.NavigateToPoint( NavPoint: TNavigatePoint );
5174begin
5175 Navigating := true;
5176
5177 // close current windows
5178 CloseWindows;
5179
5180 // Display windows for the navigate point
5181 DisplayWindows( NavPoint.Windows, nil );
5182
5183 // Select the contents topic
5184 ContentsOutline.SetSelectedObject( NavPoint.ContentsTopic );
5185
5186 // Update the navigate menu (since a different set of
5187 // back-points are now available)
5188 CreateNavigateToMenuItems;
5189
5190 // Make the topic windows visible
5191 ShowWindows;
5192
5193 // Update back buttons etc...
5194 EnableControls;
5195
5196 Navigating := false;
5197end;
5198
5199Procedure TMainForm.NavigateToHistoryIndex( Index: longint );
5200var
5201 NavPoint: TNavigatePoint;
5202begin
5203 UpdateCurrentNavigatePoint;
5204 CurrentHistoryIndex := Index;
5205 NavPoint := PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5206 NavigateToPoint( NavPoint );
5207end;
5208
5209Procedure TMainForm.NavigateForward;
5210Begin
5211 if CurrentHistoryIndex < PageHistory.Count - 1 then
5212 begin
5213 NavigateToHistoryIndex( CurrentHistoryIndex + 1 );
5214 end;
5215End;
5216
5217Procedure TMainForm.NavigateBack;
5218Begin
5219 if CurrentHistoryIndex > 0 then
5220 begin
5221 NavigateToHistoryIndex( CurrentHistoryIndex - 1 );
5222 end;
5223End;
5224
5225Procedure TMainForm.NavigatePreviousInContents;
5226begin
5227 ContentsOutline.GotoNextNodeUp;
5228 DisplaySelectedContentsTopic;
5229end;
5230
5231Procedure TMainForm.NavigateNextInContents;
5232begin
5233 ContentsOutline.GotoNextNodeDown;
5234 DisplaySelectedContentsTopic;
5235end;
5236
5237Procedure TMainForm.CorrectNotesPositions( Topic: TTopic;
5238 Text: pchar );
5239var
5240 NoteIndex: longint;
5241 Note: THelpNote;
5242 p: pchar;
5243 NextP: pchar;
5244 Element: TTextElement;
5245 TextIndex: longint;
5246begin
5247 NoteIndex := 0;
5248 for NoteIndex := 0 to Notes.Count - 1 do
5249 begin
5250 Note := Notes[ NoteIndex ];
5251 if Note.Topic = Topic then
5252 begin
5253 // this note belongs the the specified topic.
5254 p := Text;
5255
5256 while true do
5257 begin
5258 Element := ExtractNextTextElement( p, NextP );
5259 if Element.ElementType = teTextEnd then
5260 break;
5261 TextIndex := PCharDiff( p, Text );
5262 if TextIndex >= Note.InsertPoint then
5263 begin
5264 // found a safe point to insert
5265 if TextIndex <> Note.InsertPoint then
5266 begin
5267 // correct it.
5268 Note.InsertPoint := TextIndex;
5269 end;
5270 break;
5271 end;
5272
5273 p := NextP;
5274 end;
5275 end;
5276 end;
5277end;
5278
5279Procedure TMainForm.InsertNotesIntoTopicText( Topic: TTopic;
5280 Text: TAString );
5281var
5282 NoteIndex: longint;
5283 Note: THelpNote;
5284 ActualInsertPoint: longword;
5285begin
5286 CorrectNotesPositions( Topic, Text.AsPChar );
5287
5288 for NoteIndex := 0 to Notes.Count - 1 do
5289 begin
5290 Note := Notes[ NoteIndex ];
5291 if Note.Topic = Topic then
5292 begin
5293 // Adjust insert point for any notes we have already inserted.
5294 ActualInsertPoint := FindActualNoteCharIndex( Note.InsertPoint,
5295 NoteIndex,
5296 Topic );
5297 RefreshNoteInsertInfo( NoteIndex );
5298 Text.Insert( ActualInsertPoint, Note.InsertText );
5299 end;
5300 end;
5301end;
5302
5303Procedure TMainForm.NavigatePreviousMIOnClick (Sender: TObject);
5304Begin
5305 NavigatePreviousInContents;
5306End;
5307
5308Procedure TMainForm.NavigateNextMIOnClick (Sender: TObject);
5309Begin
5310 NavigateNextInContents;
5311End;
5312
5313Function TMainForm.GetActiveWindow: THelpWindow;
5314var
5315 View: TRichTextView;
5316 FirstWindow: THelpWindow;
5317begin
5318 Result := nil;
5319 if Screen.ActiveControl is TRichTextView then
5320 begin
5321 View := Screen.ActiveControl as TRichTextView;
5322 Result := FindWindowFromView( View, Windows );
5323 end
5324 else if Windows.Count = 1 then
5325 begin
5326 FirstWindow := Windows[ 0 ];
5327 if FirstWindow.ChildWindows.Count = 0 then
5328 Result := FirstWindow;
5329 end;
5330end;
5331
5332Procedure TMainForm.CopyMIOnClick (Sender: TObject);
5333var
5334 Window: THelpWindow;
5335begin
5336 if ActiveControl = nil then
5337 exit;
5338
5339 if ActiveControl is TEdit then
5340 begin
5341 // this is for the edit controls in the left panel
5342 TEdit( ActiveControl ).CopyToClipboard;
5343 exit;
5344 end;
5345
5346 // else copy from rtv in active help window
5347
5348 Window := GetActiveWindow;
5349 if Window = nil then
5350 exit;
5351
5352 Window.View.CopySelectionToClipboard;
5353End;
5354
5355Procedure TMainForm.SelectAllMIOnClick (Sender: TObject);
5356var
5357 Window: THelpWindow;
5358begin
5359 Window:= GetActiveWindow;
5360 if Window = nil then
5361 begin
5362 DoErrorDlg( SelectAllTitle,
5363 SelectAllWindowError );
5364 exit;
5365 end;
5366 Window.View.SelectAll;
5367End;
5368
5369Procedure TMainForm.DebugShowCodesMIOnClick (Sender: TObject);
5370Begin
5371 DebugShowCodesMI.Checked:= not DebugShowCodesMI.Checked;
5372 RefreshWindows( Windows );
5373End;
5374
5375Procedure TMainForm.HelpProductInformationMIOnClick (Sender: TObject);
5376Begin
5377 EnsureProductInformationFormLoaded;
5378 ProductInformationForm.ShowModal;
5379End;
5380
5381Procedure TMainForm.OnOverLink ( Sender: TRichTextView; LinkString: String);
5382var
5383 Link: THelpLink;
5384 LinkIndex: longint;
5385 Window: THelpWindow;
5386 LinkedTopic: TTopic;
5387 Filename: string;
5388 SourceFile: THelpFile;
5389 LinkedProgram: string;
5390 URL: string;
5391 LinkDetails: string;
5392 ProgramInfo : TSerializableStringList;
5393 ProgramPath, ProgramLink : string;
5394Begin
5395 if StrLeft( LinkString, 4 ) = 'note' then
5396 begin
5397 SetStatus( EditNoteMsg )
5398 end
5399 else if StrLeft( LinkString, 7 ) = 'program' then
5400 begin
5401 ProgramInfo := TSerializableStringList.create;
5402 ProgramInfo.readValuesFromSerializedString(StrRightFrom( LinkString, 9 ));
5403 ProgramPath := ProgramInfo.get(0);
5404 ProgramLink := ProgramInfo.get(1);
5405 TSerializableStringList.destroy;
5406 // call LaunchProgram here to inherit the environment
5407
5408 LinkedProgram := StrRightFrom( LinkString, 9 );
5409 SetStatus( LinkMsg + ' ' + ProgramPath + ' ' + ProgramLink);
5410 end
5411 else if StrLeft( LinkString, 3 ) = 'url' then
5412 begin
5413 URL := StrRightFrom( LinkString, 5 );
5414 SetStatus( LinkMsg
5415 + URL );
5416 end
5417 else if StrLeft( LinkString, 8 ) = 'external' then
5418 begin
5419 LinkDetails := StrRightFrom( LinkString, 10 );
5420 LinkIndex := StrToInt( ExtractNextValue( LinkDetails, ' ' ) );
5421 Window := FindWindowFromView( Sender, Windows );
5422 SourceFile := Window.Topic.HelpFile as THelpFile;
5423 Filename := SourceFile.ReferencedFiles[ LinkIndex ];
5424 SetStatus( LinkMsg
5425 + StrDoubleQuote( Filename ) );
5426 end
5427 else
5428 begin
5429 Window := FindWindowFromView( Sender, Windows );
5430 LinkIndex := StrToInt( LinkString );
5431 Link := Window.Topic.Links[ LinkIndex ];
5432
5433 if Link is TFootnoteHelpLink then
5434 begin
5435 SetStatus( FootnoteMsg );
5436 end
5437 else
5438 begin
5439 LinkedTopic := FindTopicForLink( Link );
5440
5441 if LinkedTopic <> nil then
5442 begin
5443 SetStatus( LinkMsg
5444 + StrDoubleQuote( Trim( LinkedTopic.Title ) ) );
5445 end
5446 else
5447 begin
5448 SetStatus( UnknownLinkMsg );
5449 end;
5450 end;
5451 end;
5452End;
5453
5454Procedure TMainForm.OnNotOverLink ( Sender: TRichTextView; LinkString: String);
5455Begin
5456 SetStatus( '' );
5457end;
5458
5459Procedure TMainForm.OnClickLink ( Sender: TRichTextView; LinkString: String);
5460var
5461 Link: THelpLink;
5462 LinkIndex: longint;
5463 SourceWindow: THelpWindow;
5464 NoteIndex: longint;
5465 Window: THelpWindow;
5466 SourceFile: THelpFile;
5467 ProgramLink: string;
5468 ProgramPath: string;
5469 URL: string;
5470 LinkDetails: string;
5471 ProgramInfo : TSerializableStringList;
5472Begin
5473 if StrLeft( LinkString, 4 ) = 'note' then
5474 begin
5475 NoteIndex := StrToInt( StrRightFrom( LinkString, 5 ) );
5476 NotesListBox.ItemIndex := NoteIndex;
5477 EditNote( NoteIndex );
5478 end
5479 else if StrLeft( LinkString, 7 ) = 'program' then
5480 begin
5481 ProgramInfo := TSerializableStringList.create;
5482 ProgramInfo.readValuesFromSerializedString(StrRightFrom( LinkString, 9 ));
5483 ProgramPath := ProgramInfo.get(0);
5484 ProgramLink := ProgramInfo.get(1);
5485 TSerializableStringList.destroy;
5486 // call LaunchProgram here to inherit the environment
5487 LogEvent(LogDisplay, 'LaunchProgram: "' + ProgramPath + '" "' + ProgramLink + '"');
5488 LaunchProgram(ProgramPath, ProgramLink, '');
5489 SetStatus( 'Launched ' + ProgramPath );
5490 end
5491 else if StrLeft( LinkString, 3 ) = 'url' then
5492 begin
5493 URL := StrRightFrom(LinkString, 5);
5494
5495 try
5496 LaunchURL(URL);
5497 except
5498 on E:Exception do
5499 begin
5500 DoErrorDlg('Error', E.Message);
5501 end;
5502 else raise;
5503 end;
5504
5505 SetStatus('Opened ' + URL );
5506 end
5507 else if StrLeft( LinkString, 8 ) = 'external' then
5508 begin
5509 LinkDetails := StrRightFrom( LinkString, 10 );
5510 LinkIndex := StrToInt( ExtractNextValue( LinkDetails, ' ' ) );
5511 Window := FindWindowFromView( Sender, Windows );
5512 SourceFile := Window.Topic.HelpFile as THelpFile;
5513
5514 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5515 g_ExternalLinkTopic := LinkDetails;
5516 g_ExternalLinkSourceFilename := SourceFile.Filename;
5517 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5518
5519 PostMsg( Self.Handle,
5520 WM_FOLLOWEXTERNALLINK,
5521 0,
5522 0 );
5523 end
5524 else
5525 begin
5526 SourceWindow := FindWindowFromView( Sender, Windows );
5527 LinkIndex := StrToInt( LinkString );
5528 Link := SourceWindow.Topic.Links[ LinkIndex ];
5529
5530 PostMsg( Self.Handle,
5531 WM_FOLLOWLINK,
5532 longint( Link ),
5533 longint( SourceWindow ) );
5534
5535 end;
5536End;
5537
5538Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5539 var CanClose: boolean );
5540begin
5541 if Navigating then
5542 exit;
5543
5544 UpdateCurrentNavigatePoint; // Save it before close...
5545
5546 CanClose := true;
5547end;
5548
5549Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5550var
5551 ParentWindow: THelpWindow;
5552 WindowIndex: longint;
5553Begin
5554 if Navigating then
5555 exit;
5556
5557 if Window.ParentHelpWindow = nil then
5558 begin
5559 WindowIndex := Windows.IndexOf( Window );
5560 Windows.Delete( WindowIndex );
5561 end
5562 else
5563 begin
5564 ParentWindow := Window.ParentHelpWindow;
5565 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5566 ParentWindow.ChildWindows.Delete( WindowIndex );
5567 end;
5568end;
5569
5570Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5571Begin
5572 if Navigating then
5573 exit;
5574
5575 RemoveHelpWindowFromParent( Window );
5576
5577 SaveNavigatePoint;
5578 EnableControls;
5579End;
5580
5581Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5582Begin
5583 NavigateBack;
5584End;
5585
5586Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5587Begin
5588End;
5589
5590Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5591Begin
5592 Close;
5593End;
5594
5595Procedure TMainForm.CreateMRUMenuItems;
5596var
5597 MenuItem: TMenuItem;
5598 i: integer;
5599 FileName: string;
5600 FileNameIndex: longint;
5601 MRUText: string;
5602 MRUItem: TMRUItem;
5603begin
5604 DestroyListObjects( MRUMenuItems );
5605 MRUMenuItems.Clear;
5606
5607 // if there are Most Recently Used files
5608 if Settings.MRUList.Count > 0 then
5609 begin
5610 // create a seperator after Exit
5611 MenuItem:= TMenuItem.Create( self );
5612 MenuItem.Name := 'MRUSeparatorMI';
5613 MenuItem.Caption:= '-';
5614 FileMenu.Add( MenuItem );
5615 MRUMenuItems.Add( MenuItem );
5616 end;
5617
5618 // Add items for the MRU files
5619 for i:= 0 to Settings.MRUList.Count -1 do
5620 begin
5621 MRUItem := Settings.MRUList[ i ];
5622
5623 MenuItem := TMenuItem.Create( self );
5624
5625 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5626 MRUText := MRUItem.Title;
5627 if Trim( MRUText ) = '' then
5628 begin
5629 // Take the filenames, less path, as caption...
5630 MRUText := '';
5631 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5632 begin
5633 FileName := MRUItem.Filenames[ FileNameIndex ];
5634 FileName := ExtractFileName( FileName );
5635 FileName := ChangeFileExt( FileName, '' );// remove extension
5636 AddToListString( MRUText,
5637 FileName,
5638 '+' );
5639
5640 // stop after 50 chars
5641 if Length( MRUText ) > 50 then
5642 begin
5643 MRUText := MRUText + '+ ...';
5644 break;
5645 end;
5646 end;
5647 end;
5648
5649 MenuItem.Caption:= '~'
5650 + IntToStr( i + 1 )
5651 + '. '
5652 + MRUText;
5653 if MRUItem.Filenames.Count = 1 then
5654 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5655 else
5656 MenuItem.Hint := MRUItem.Title
5657 + ' ('
5658 + IntToStr( MRUItem.Filenames.Count )
5659 + ' '
5660 + MRUMultipleFilesHint
5661 + ')';
5662
5663 MenuItem.OnClick:= OnMRUMenuItemClick;
5664 MenuItem.Tag:= i;
5665 FileMenu.Add( MenuItem );
5666 MRUMenuItems.Add( MenuItem );
5667 end;
5668end;
5669
5670procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5671var
5672 Tag: longint;
5673 MenuItem: TMenuItem;
5674 MRUItem: TMRUItem;
5675begin
5676 MenuItem:= Sender as TMenuItem;
5677 Tag:= MenuItem.Tag;
5678 MRUItem := Settings.MRUList[ Tag ];
5679 if OpenFiles( MRUItem.FileNames, '', true ) then
5680 begin
5681 ClearHelpManager;
5682 end;
5683end;
5684
5685Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5686var
5687 MenuItem: TMenuItem;
5688 Tag: longint;
5689begin
5690 MenuItem:= Sender as TMenuItem;
5691 Tag:= MenuItem.Tag;
5692 NavigateToHistoryIndex( Tag );
5693end;
5694
5695Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5696 ParentNode: TNode;
5697 Level: longint;
5698 Var TopicIndex: longint );
5699var
5700 Topic: TTopic;
5701 Node: TNode;
5702begin
5703 assert( ParentNode <> nil );
5704 Node := nil;
5705 while TopicIndex < HelpFile.TopicCount do
5706 begin
5707 Topic:= HelpFile.Topics[ TopicIndex ];
5708
5709 if Topic.ShowInContents then
5710 begin
5711 if Topic.ContentsLevel < Level then
5712 break;
5713
5714 if Topic.ContentsLevel = Level then
5715 begin
5716 Node:= ParentNode.AddChild( Topic.Title,
5717 Topic );
5718 inc( TopicIndex );
5719 end
5720 else
5721 begin
5722 assert( Node <> nil );
5723 AddChildNodes( HelpFile,
5724 Node,
5725 Topic.ContentsLevel,
5726 TopicIndex );
5727 Node := nil;
5728 end
5729 end
5730 else
5731 begin
5732 inc( TopicIndex );
5733 end;
5734 end;
5735
5736end;
5737
5738Procedure TMainForm.LoadContents( Files: TList;
5739 Var FirstNode: TNode );
5740var
5741 TopicIndex: longint;
5742 Topic: TTopic;
5743 Node: TNode;
5744 FileIndex: longint;
5745 HelpFile: THelpFile;
5746begin
5747 ContentsOutline.BeginUpdate;
5748 LogEvent(LogStartup, 'Load contents outline');
5749
5750 // we don't clear it first, to allow adding additional files
5751 // into the contents tree
5752
5753 LogEvent(LogStartup, 'Loop files');
5754
5755 FirstNode := nil;
5756
5757 Node := nil;
5758
5759 for FileIndex:= 0 to Files.Count - 1 do
5760 begin
5761 HelpFile := Files[ FileIndex ];
5762 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5763 TopicIndex := 0;
5764 while TopicIndex < HelpFile.TopicCount do
5765 begin
5766 Topic := HelpFile.Topics[ TopicIndex ];
5767 assert( Topic.ContentsLevel >= 0,
5768 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5769 if Topic.ShowInContents then
5770 begin
5771 if Topic.ContentsLevel = 1 then
5772 begin
5773 Node := ContentsOutline.AddChild( Topic.Title,
5774 Topic );
5775 if FirstNode = nil then
5776 FirstNode := node;
5777
5778 inc( TopicIndex );
5779 end
5780 else
5781 begin
5782 // subnodes
5783 assert( Node <> nil, 'No level 1 topic for subnodes!' );
5784 AddChildNodes( HelpFile,
5785 Node,
5786 Topic.ContentsLevel,
5787 TopicIndex );
5788 Node := nil;
5789 end;
5790 end
5791 else
5792 begin
5793 inc( TopicIndex );
5794 end;
5795 end;
5796 end;
5797 LogEvent(LogStartup, ' EndUpdate' );
5798 ContentsOutline.EndUpdate;
5799
5800 if Settings.OpenWithExpandedContents then
5801 begin
5802 LogEvent(LogStartup, ' Expand all contents' );
5803 ContentsOutline.ExpandAll
5804 end
5805 else if ContentsOutline.ChildCount = 1 then
5806 begin
5807 LogEvent(LogStartup, ' Expand first node' );
5808 // Contents has only one top level node... expand it
5809 FirstNode.Expand;
5810 end;
5811
5812 ContentsLoaded := true;
5813 LogEvent(LogStartup, ' Contents loaded' );
5814
5815end;
5816
5817Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5818var
5819 NotesFileName: string;
5820 TopicIndex: longword;
5821 Note: THelpNote;
5822 NoteIndex: longint;
5823
5824 NotesFile: HFile;
5825 OpenAction: ULong;
5826 rc: APIRET;
5827 CName: Cstring;
5828 FileNoteCount: integer;
5829
5830begin
5831 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5832
5833 if not HelpFile.NotesLoaded then
5834 // we never loaded the notes/displayed a topic from this file
5835 // so don't do anything.
5836 exit;
5837
5838 LogEvent(LogStartup, 'Really saving' );
5839
5840 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5841
5842 FileNoteCount := 0;
5843 for NoteIndex := 0 to Notes.Count - 1 do
5844 begin
5845 Note := Notes[ NoteIndex ];
5846
5847 if Note.Topic.HelpFile = HelpFile then
5848 inc( FileNoteCount );
5849 end;
5850
5851 if FileNoteCount = 0 then
5852 begin
5853 // no notes. delete notes file if it already exists.
5854 if FileExists( NotesFileName ) then
5855 DeleteFile( NotesFileName );
5856 exit;
5857 end;
5858
5859 CName:= NotesFileName;
5860 rc:= DosOpen( CName,
5861 NotesFile,
5862 OpenAction,
5863 0, // file size
5864 0, // attrs
5865 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5866 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5867 nil ); // no eas
5868 if rc <> 0 then
5869 begin
5870 DoErrorDlg( SaveNotesTitle,
5871 SaveNotesError
5872 + EndLine
5873 + NotesFileName
5874 + EndLine
5875 + SysErrorMessage( rc ) );
5876 exit;
5877 end;
5878
5879 for NoteIndex:= 0 to Notes.Count - 1 do
5880 begin
5881 Note:= Notes[ NoteIndex ];
5882
5883 if Note.Topic.HelpFile <> HelpFile then
5884 continue;
5885
5886 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5887
5888 MyWriteLn( NotesFile,
5889 IntToStr( TopicIndex ));
5890 MyWriteLn( NotesFile,
5891 IntToStr( Note.InsertPoint ) );
5892
5893 MyWrite( NotesFile,
5894 Note.Text.AsPChar,
5895 Note.Text.Length );
5896
5897 MyWriteLn( NotesFile,
5898 '' );
5899 MyWriteLn( NotesFile,
5900 '#ENDNOTE#' );
5901
5902 end;
5903
5904 DosClose( NotesFile );
5905end;
5906
5907Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5908var
5909 NotesFileName: string;
5910 TopicIndex: longint;
5911 InsertPoint: longint;
5912 Note: THelpNote;
5913
5914 NotesFile: HFile;
5915 OpenAction: ULong;
5916 rc: APIRET;
5917 CName: Cstring;
5918
5919 Paragraph: TAString;
5920 NotEOF: boolean;
5921 NoteText: TAString;
5922
5923begin
5924 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5925
5926 if HelpFile.NotesLoaded then
5927 exit;
5928
5929 HelpFile.NotesLoaded := true;
5930 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5931
5932 if not FileExists( NotesFileName ) then
5933 // no notes
5934 exit;
5935
5936 CName := NotesFileName;
5937 rc := DosOpen( CName,
5938 NotesFile,
5939 OpenAction,
5940 0, // file size - irrelevant, not creating,
5941 0, // attrs - ''
5942 OPEN_ACTION_OPEN_IF_EXISTS,
5943 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5944 nil ); // no eas
5945 if rc <> 0 then
5946 begin
5947 DoErrorDlg( LoadNotesTitle,
5948 LoadNotesError
5949 + EndLine
5950 + NotesFileName
5951 + EndLine
5952 + SysErrorMessage( rc ) );
5953 exit;
5954 end;
5955
5956 Paragraph := TAString.Create;
5957 NoteText := TAString.Create;
5958
5959 NotEOF := true;
5960
5961 while NotEOF do
5962 begin
5963 // Read contents index
5964 NotEOF := Paragraph.ReadParagraph( NotesFile );
5965 if not NotEOF then
5966 continue;
5967 try
5968 TopicIndex := StrToInt( Paragraph.AsString );
5969 except
5970 TopicIndex := -1;
5971 end;
5972
5973 // Read insert point
5974 NotEOF := Paragraph.ReadParagraph( NotesFile );
5975 if not NotEOF then
5976 continue;
5977 try
5978 InsertPoint := StrToInt( Paragraph.AsString );
5979 except
5980 InsertPoint := -1;
5981 end;
5982
5983 NoteText.Clear;
5984
5985 while NotEOF do
5986 begin
5987 NotEOF := Paragraph.ReadParagraph( NotesFile );
5988 if Paragraph.SameAs( '#ENDNOTE#' ) then
5989 begin
5990 // found end of note
5991 if ( TopicIndex >= 0 )
5992 and ( InsertPoint >= 0 ) then
5993 begin
5994 Note := THelpNote.Create;
5995 Note.Topic := HelpFile.Topics[ TopicIndex ];
5996 Note.InsertPoint := InsertPoint;
5997
5998 // Remove the last end line
5999 Note.Text.Assign( NoteText );
6000 if Note.Text.Length > 2 then
6001 Note.Text.Delete( Note.Text.Length - 2, 2 );
6002
6003 Notes.Add( Note );
6004 end;
6005 break;
6006 end;
6007 NoteText.Add( Paragraph );
6008 NoteText.AddString( #13 + #10 );
6009 end;
6010
6011 end;
6012 DosClose( NotesFile );
6013
6014 Paragraph.Destroy;
6015 NoteText.Destroy;
6016
6017end;
6018
6019Procedure TMainForm.UpdateNotesDisplay;
6020var
6021 NoteIndex: longint;
6022 Note: THelpNote;
6023 NoteTitle: string;
6024begin
6025 NotesListBox.Clear;
6026 for NoteIndex := 0 to Notes.Count - 1 do
6027 begin
6028 Note := Notes[ NoteIndex ];
6029
6030 if Note.Topic > nil then
6031 NoteTitle := Note.Topic.Title
6032 else
6033 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6034 NotesListBox.Items.AddObject( NoteTitle,
6035 Note );
6036 end;
6037 EnableNotesControls;
6038end;
6039
6040Procedure TMainForm.EnableNotesControls;
6041var
6042 NoteSelected: boolean;
6043begin
6044 NoteSelected:= NotesListBox.ItemIndex <> -1;
6045 EditNoteButton.Enabled:= NoteSelected;
6046 GotoNoteButton.Enabled:= NoteSelected;
6047 DeleteNoteButton.Enabled:= NoteSelected;
6048 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6049end;
6050
6051Function TMainForm.OKToCloseFile: boolean;
6052begin
6053 Result := true;
6054
6055 if PrintThread = nil then
6056 // haven't used print thread yet
6057 exit;
6058
6059 if not PrintThread.IsRunning then
6060 // not currently running
6061 exit;
6062
6063 Result := DoConfirmDlg( CheckStopPrintTitle,
6064 CheckStopPrintMsg );
6065
6066end;
6067
6068Procedure TMainForm.StopPrinting;
6069begin
6070 if PrintThread <> nil then
6071 begin
6072 if PrintThread.IsRunning then
6073 begin
6074 SetStatus( StoppingPrintMsg );
6075 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6076 SetStatus( PrintStoppedMsg );
6077 ResetProgress;
6078 end;
6079 end;
6080end;
6081
6082Procedure TMainForm.CloseFile;
6083var
6084 FileIndex: longint;
6085 HelpFile: THelpFile;
6086 M1: longint;
6087begin
6088 StopPrinting;
6089
6090 LogEvent(LogShutdown, 'Set Caption' );
6091 MainTitle := '';
6092 SetMainCaption;
6093
6094 LogEvent(LogShutdown, 'Close Windows' );
6095 CloseWindows;
6096
6097 LogEvent(LogShutdown, 'Set selected node to nil' );
6098 ContentsOutline.SelectedNode:= Nil;
6099
6100 M1:= MemAvail;
6101
6102 LogEvent(LogShutdown, 'Clear contents outline' );
6103 ContentsOutline.Clear;
6104
6105 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6106 M1:= MemAvail;
6107
6108 DisplayedIndex.Clear;
6109 IndexListBox.Clear;
6110 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6111 M1:= MemAvail;
6112
6113 NotesListBox.Clear;
6114 SearchResultsListBox.Clear;
6115
6116 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6117 M1:= MemAvail;
6118
6119 // First save notes and bookmarks.
6120 // It's important we do this first
6121 // since we scan all notes each time to find the ones
6122 // belonging to this file.
6123 SaveBookmarks;
6124
6125 SaveNotes;
6126
6127 ClearAllWordSequences;
6128
6129 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6130
6131 // Now destroy help files
6132 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6133 begin
6134 HelpFile := CurrentOpenFiles[ FileIndex ];
6135 GlobalFilelist.RemoveFile( Frame.Handle,
6136 HelpFile.Filename );
6137 HelpFile.Free;
6138 end;
6139
6140 CurrentOpenFiles.Clear;
6141
6142 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6143 M1 := MemAvail;
6144
6145 LogEvent(LogShutdown, 'Clear notes' );
6146 ClearNotes;
6147
6148 LogEvent(LogShutdown, 'Clear bookmarks' );
6149 ClearBookmarks;
6150
6151 ClearPageHistory;
6152
6153 LogEvent(LogShutdown, 'Enable controls' );
6154 EnableControls;
6155
6156 LogEvent(LogShutdown, 'CloseFile done' );
6157
6158end;
6159
6160Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6161var
6162 FileIndex: longint;
6163begin
6164 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6165 begin
6166 Result:= CurrentOpenFiles[ FileIndex ];
6167 if StringsSame( Result.Filename, FileName ) then
6168 // found
6169 exit;
6170 end;
6171 Result:= nil;
6172end;
6173
6174// This rather horrendous looking bit of code simply:
6175
6176// Gets the contents from each file
6177// Sorts it alphabetically.
6178// Merges all the sorted contents and indexes together,
6179// alphabetically.
6180type
6181 TListType = ( ltContents, ltIndex );
6182
6183procedure TMainForm.LoadIndex;
6184var
6185 HelpFile: THelpFile;
6186 TextCompareResult: integer;
6187
6188 FileIndex: longint;
6189
6190 Contents: TList;
6191 ContentsLists: TList; // of tlist
6192 IndexLists: TList; // of tstringlist
6193 ContentsNextIndex: array[ 0..255 ] of longint;
6194 IndexNextIndex: array[ 0..255 ] of longint;
6195 Topic: TTopic;
6196
6197 ListIndex: longint;
6198
6199 pListEntry: pstring;
6200 pLowestEntry: pstring;
6201 pLastEntry: pstring;
6202
6203 LowestEntryListIndex: longint;
6204 LowestEntryListType: TListType;
6205 LowestEntryTopic: TTopic;
6206
6207 Index: TStringList;
6208
6209 i : longint;
6210begin
6211 LogEvent(LogStartup, 'Create index' );
6212
6213 SetWaitCursor;
6214
6215 LogEvent(LogStartup, ' Get/sort lists' );
6216
6217 ProgressBar.Position := 70;
6218 SetStatus( 'Building index... ' );
6219
6220 ContentsLists := TList.Create;
6221 IndexLists := TList.Create;
6222
6223 // collect the contents and index lists from the files
6224 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6225 begin
6226 HelpFile := CurrentOpenFiles[ FileIndex ];
6227 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6228
6229 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6230 begin
6231 Contents := TList.Create;
6232 Contents.Capacity := HelpFile.TopicCount;
6233
6234 // copy [contents] topic list
6235 for i := 0 to HelpFile.TopicCount - 1 do
6236 begin
6237 Topic := HelpFile.Topics[ i ];
6238 if Topic.ShowInContents then
6239 Contents.Add( Topic );
6240 end;
6241
6242 // sort by title
6243 Contents.Sort( TopicTitleCompare );
6244
6245 ContentsLists.Add( Contents );
6246
6247 // initialise list index
6248 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6249 end;
6250
6251 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6252 begin
6253 IndexLists.Add( HelpFile.Index );
6254 IndexNextIndex[ IndexLists.Count - 1 ] := 0;
6255 end;
6256 end;
6257
6258 // Unlike contents, we do clear the index
6259 // (even if we are adding more files) because we need
6260 // to re-merge the whole thing
6261 DisplayedIndex.Clear;
6262 ProgressBar.Position := 80;
6263
6264 LogEvent(LogStartup, ' Merge lists' );
6265
6266 pLastEntry := NullStr;
6267 while true do
6268 begin
6269 pLowestEntry := NullStr;
6270 LowestEntryListIndex := -1;
6271
6272 // Find alphabetically lowest (remaining) topic
6273
6274 // first, look in contents lists
6275 for ListIndex := 0 to ContentsLists.Count - 1 do
6276 begin
6277 Contents := ContentsLists[ ListIndex ];
6278 if ContentsNextIndex[ ListIndex ] < Contents.Count then
6279 begin
6280 // list is not yet finished, get next entry
6281 Topic := Contents[ ContentsNextIndex[ ListIndex ] ];
6282 pListEntry := Topic.TitlePtr;
6283
6284 if pLowestEntry^ <> '' then
6285 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6286 else
6287 TextCompareResult := -1;
6288
6289 if TextCompareResult < 0 then
6290 begin
6291 // this index entry comes before the lowest one so far
6292 pLowestEntry := pListEntry;
6293 LowestEntryListIndex := ListIndex;
6294 LowestEntryListType := ltContents;
6295 LowestEntryTopic := Topic;
6296 end;
6297 end;
6298 end;
6299
6300 // look in indices
6301 for ListIndex := 0 to IndexLists.Count - 1 do
6302 begin
6303 Index := IndexLists[ ListIndex ];
6304 if IndexNextIndex[ ListIndex ] < Index.Count then
6305 begin
6306 // list is not yet finished, get next entry
6307 pListEntry := Index.ValuePtrs[ IndexNextIndex[ ListIndex ] ];
6308
6309 if pLowestEntry^ <> '' then
6310 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6311 else
6312 TextCompareResult := -1;
6313
6314 if TextCompareResult < 0 then
6315 begin
6316 // this index entry comes before the lowest one so far
6317 pLowestEntry := pListEntry;
6318 LowestEntryListIndex := ListIndex;
6319 LowestEntryListType := ltIndex;
6320 LowestEntryTopic := TTopic( Index.Objects[ IndexNextIndex[ ListIndex ] ] );
6321 end;
6322 end;
6323 end;
6324
6325 if LowestEntryListIndex = -1 then
6326 // we're out
6327 break;
6328
6329 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6330 // add, if different from last
6331 DisplayedIndex.AddObject( pLowestEntry^,
6332 LowestEntryTopic );
6333 pLastEntry := pLowestEntry;
6334
6335 if LowestEntryListType = ltContents then
6336 begin
6337 inc( ContentsNextIndex[ LowestEntryListIndex ] );
6338 end
6339 else
6340 begin
6341 // found in one of indices.
6342 // Check for subsequent indented strings
6343 Index := IndexLists[ LowestEntryListIndex ];
6344
6345 i := IndexNextIndex[ LowestEntryListIndex ] + 1;
6346 while i < Index.Count do
6347 begin
6348 pListEntry := Index.ValuePtrs[ i ];
6349 if pListEntry^ = '' then
6350 break;
6351
6352 if pListEntry^[ 1 ] <> ' ' then
6353 // not indented, stop looking
6354 break;
6355
6356 // found one,
6357 Topic := Index.Objects[ i ] as TTopic;
6358 DisplayedIndex.AddObject( pListEntry^,
6359 Topic );
6360 inc( i );
6361 end;
6362 IndexNextIndex[ LowestEntryListIndex ] := i;
6363 end;
6364 end;
6365
6366 ProgressBar.Position := 95;
6367 LogEvent(LogStartup, ' Display index (count = '
6368 + IntToStr( DisplayedIndex.Count )
6369 + ')' );
6370
6371 // Now display the final index list
6372 IndexListBox.Items.Assign( DisplayedIndex );
6373
6374 LogEvent(LogStartup, ' Tidy up' );
6375
6376 IndexLists.Destroy;
6377
6378 DestroyListAndObjects( ContentsLists );
6379
6380 IndexLoaded := true;
6381
6382 ClearWaitCursor;
6383
6384 SetStatus( 'Index loaded' );
6385 LogEvent(LogStartup, ' Done' );
6386end;
6387
6388Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6389 message: string );
6390var
6391 ProgressOnFiles: longint;
6392 Filename: string;
6393 ProgressOnThisFile: longint;
6394
6395begin
6396 Filename := LoadingFilenameList[ LoadingFileIndex ];
6397
6398 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6399 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6400
6401 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6402 100,
6403 LoadingFileMsg
6404 + ExtractFileName( Filename )
6405 + ': '
6406 + message );
6407end;
6408
6409Procedure TMainForm.SetProgress( n, outof: integer;
6410 message: string );
6411begin
6412 ProgressBar.Position := n * 100 div outof;
6413 SetStatus( message );
6414 ProgressBar.Show;
6415end;
6416
6417// Load a single file.
6418Function TMainForm.OpenFile( const FileName: string;
6419 const WindowTitle: string;
6420 const SelectFirstContentsNode: boolean ): boolean;
6421var
6422 FileNames: TStringList;
6423begin
6424 FileNames := TStringList.Create;
6425 FileNames.Add( FileName );
6426 Result := OpenFiles( FileNames,
6427 WindowTitle,
6428 DisplayFirstTopic );
6429 FileNames.Destroy;
6430end;
6431
6432Function TMainForm.OpenAdditionalFile( const FileName: string;
6433 const DisplayFirstTopic: boolean ): boolean;
6434var
6435 FileNames: TStringList;
6436begin
6437 FileNames := TStringList.Create;
6438 FileNames.Add( FileName );
6439 Result := OpenAdditionalFiles( FileNames,
6440 DisplayFirstTopic );
6441 FileNames.Destroy;
6442end;
6443
6444Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6445var
6446 WinHelpDetails: PROGDETAILS;
6447 szFilename: cstring;
6448begin
6449
6450 result := true;
6451 if Settings.ConfirmWinHelp then
6452 result := DoYesNoDlg( WindowsHelpTitle,
6453 WindowsHelpPrompt
6454 + EndLine
6455 + FileName );
6456 if not result then
6457 exit;
6458
6459 szFilename := FileName;
6460 with WinHelpDetails do
6461 begin
6462 Length := sizeof( WinHelpDetails );
6463 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6464 progt.fbVisible := SHE_VISIBLE;
6465 pszTitle := ''; // not used?
6466 pszExecutable := 'winhelp.exe';
6467 pszParameters := Addr( szFilename );
6468 pszStartupDir := nil;
6469 pszIcon := nil;
6470 pszEnvironment := nil;
6471 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6472 end;
6473
6474 result := WinStartApp( NULLHANDLE,
6475 WinHelpDetails,
6476 '',
6477 nil,
6478 SAF_INSTALLEDCMDLINE ) <> 0;
6479
6480 // Doesn't work for Dos/Win programs
6481 // RunProgram( 'winhelp.exe', FileName );
6482end;
6483
6484// Load the specified set of help files
6485Function TMainForm.LoadFiles( const FileNames: TStrings;
6486 HelpFiles: TList ): boolean;
6487var
6488 HelpFile: THelpFile;
6489 FileIndex: longint;
6490 FileName: string;
6491 FullFilePath: string;
6492
6493 FileHandlesAdjustNum: LONG;
6494 CurrentMaxFileHandles: ULONG;
6495 RequiredFileHandles: LONG;
6496begin
6497 LogEvent(LogStartup, 'LoadFiles' );
6498
6499 LoadingFilenameList := TStringList.Create;
6500
6501 TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6502
6503 LogEvent(LogStartup, 'Finding files' );
6504
6505 ProgressBar.Show;
6506
6507 // now find full file paths,
6508 // and also the total file size for progress display
6509 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6510 begin
6511 FileName := LoadingFilenameList[ FileIndex ];
6512 LogEvent(LogStartup, ' File: ' + FileName );
6513
6514 // Find the help file, if possible
6515 if Filename = OWN_HELP_MARKER then
6516 begin
6517 FullFilePath := CmdLineParameters.GetOwnHelpFileName;
6518 end
6519 else
6520 begin
6521 FullFilePath := FindHelpFile( Filename );
6522 end;
6523
6524 if FullFilePath <> '' then
6525 begin
6526 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6527 end
6528 else
6529 begin
6530 LogEvent(LogStartup, ' File not found' );
6531 FullFilePath := FileName; // we'll complain later.
6532 end;
6533 LoadingFilenameList[ FileIndex ] := FullFilePath;
6534 end;
6535
6536 // Make sure we have enough file handles
6537
6538 FileHandlesAdjustNum := 0;
6539 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6540 CurrentMaxFileHandles );
6541
6542 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6543 + LoadingFilenameList.Count // new ones
6544 + 40; // some spares.
6545 if CurrentMaxFileHandles < RequiredFileHandles then
6546 begin
6547 // need some more
6548 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6549 DosSetRelMaxFH( FileHandlesAdjustNum,
6550 CurrentMaxFileHandles );
6551 end;
6552
6553 // Now actually load the files
6554 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6555 begin
6556 Filename := LoadingFilenameList[ FileIndex ];
6557 LogEvent(LogStartup, ' Loading: ' + Filename );
6558 try
6559 LoadingFileIndex := FileIndex;
6560
6561 // load the file
6562 HelpFile := THelpFile.Create( FileName );
6563 if Settings.FixedFontSubstitution then
6564 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6565
6566 HelpFiles.Add( HelpFile );
6567
6568 except
6569 on E: Exception do
6570 begin
6571
6572 if E is EWindowsHelpFormatException then
6573 begin
6574 OpenWindowsHelp( Filename );
6575 end
6576 else
6577 begin
6578 DoErrorDlg( FileOpenTitle,
6579 HelpFileError
6580 + FileName
6581 + ': '
6582 + E.Message );
6583 end;
6584
6585 // back out of the load process
6586 Result := false;
6587
6588 DestroyListObjects( HelpFiles );
6589
6590 LoadingFilenameList.Destroy;
6591 ResetProgress;
6592 exit;
6593 end
6594 end;
6595 end;
6596
6597 LoadingFilenameList.Destroy;
6598
6599 Result := true;
6600
6601end;
6602
6603// Add the current list of open files as
6604// a Most Recently Used entry
6605Procedure TMainForm.AddCurrentToMRUFiles;
6606var
6607 Filenames: TStringList;
6608 i: longint;
6609 HelpFile: THelpFile;
6610begin
6611 Filenames := TStringList.Create;
6612
6613 for i := 0 to CurrentOpenFiles.Count - 1 do
6614 begin
6615 HelpFile := CurrentOpenFiles[ i ];
6616 Filenames.Add( HelpFile.Filename );
6617 end;
6618
6619 // update most-recently-used file list
6620 HelpFile := CurrentOpenFiles[ 0 ];
6621 AddToMRUList( HelpFile.Title,
6622 Filenames );
6623
6624 // recreate menu
6625 CreateMRUMenuItems;
6626
6627 Filenames.Destroy;
6628end;
6629
6630// Display the specified set of files
6631Procedure TMainForm.DisplayFiles( NewFiles: TList;
6632 Var FirstContentsNode: TNode );
6633var
6634 HelpFile: THelpFile;
6635 FileIndex: longint;
6636begin
6637 LogEvent(LogStartup, 'DisplayFiles' );
6638 // Now load the various parts of the file(s)
6639 // into the user interface
6640 ProgressBar.Position := 50;
6641 SetStatus( LoadingStatusDisplaying );
6642
6643 // Add our open files in the global filelist
6644 for FileIndex := 0 to NewFiles.Count - 1 do
6645 begin
6646 HelpFile := NewFiles[ FileIndex ];
6647 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6648 // LoadNotes( HelpFile );
6649 LoadBookmarks( HelpFile );
6650 end;
6651
6652 UpdateNotesDisplay;
6653
6654 BuildBookmarksMenu;
6655 UpdateBookmarksForm;
6656
6657 ProgressBar.Position := 55;
6658
6659 ContentsLoaded := false;
6660 IndexLoaded := false;
6661
6662 LoadContents( NewFiles, FirstContentsNode );
6663
6664 ProgressBar.Position := 75;
6665
6666 // LoadIndex;
6667
6668 ProgressBar.Position := 100;
6669 SetStatus( LoadingStatusDone );
6670
6671 LogEvent(LogStartup, 'DisplayFiles Done' );
6672
6673end;
6674
6675Function TMainForm.OpenFiles( const FileNames: TStrings;
6676 const WindowTitle: string;
6677 const DisplayFirstTopic: boolean ): boolean;
6678var
6679 HelpFiles: TList;
6680 FirstContentsNode: TNode;
6681begin
6682 LogEvent(LogStartup, 'OpenFiles' );
6683
6684 if not OKToCloseFile then
6685 exit;
6686
6687 SetWaitCursor;
6688
6689 HelpFiles := TList.Create;
6690
6691 if not LoadFiles( FileNames,
6692 HelpFiles ) then
6693 begin
6694 ClearWaitCursor;
6695 HelpFiles.Destroy;
6696 exit;
6697 end;
6698
6699 Result := true;
6700
6701 SearchResultsListBox.Clear;
6702 PageHistory.Clear;
6703 CurrentHistoryIndex := -1;
6704
6705 // Now that we have successfully loaded the new help file(s)
6706 // close the existing one.
6707 CloseFile;
6708
6709 AssignList( HelpFiles, CurrentOpenFiles );
6710
6711 ProgressBar.Position := 50;
6712 SetStatus( LoadingStatusDisplaying );
6713
6714 AddCurrentToMRUFiles;
6715
6716 if WindowTitle = '' then
6717 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6718 else
6719 MainTitle := WindowTitle;
6720
6721 SetMainCaption;
6722
6723 // Now load the various parts of the file(s)
6724 // into the user interface
6725
6726 ContentsOutline.Clear;
6727
6728 DisplayFiles( HelpFiles,
6729 FirstContentsNode );
6730
6731 if CmdLineParameters.getHelpManagerFlag then
6732 ShowLeftPanel := Settings.ShowLeftPanel_Help
6733 else
6734 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6735
6736 // Select first contents node if there is one
6737 if FirstContentsNode <> nil then
6738 begin
6739 LogEvent(LogStartup, ' Select first node' );
6740 ContentsOutline.SelectedNode := FirstContentsNode;
6741 end;
6742
6743 ClearWaitCursor;
6744
6745 ResetProgress;
6746
6747 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6748
6749 EnableControls;
6750
6751 if DisplayFirstTopic then
6752 begin
6753 LogEvent(LogStartup, 'Display first topic' );
6754 DisplaySelectedContentsTopic;
6755 end;
6756
6757 LogEvent(LogStartup, 'OpenFiles complete' );
6758end;
6759
6760Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6761 const DisplayFirstTopic: boolean ): boolean;
6762var
6763 HelpFiles: TList;
6764 FirstNewContentsNode: TNode;
6765begin
6766 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6767
6768 if not OKToCloseFile then
6769 exit;
6770
6771 SetWaitCursor;
6772
6773 HelpFiles := TList.Create;
6774
6775 if not LoadFiles( FileNames,
6776 HelpFiles ) then
6777 begin
6778 ClearWaitCursor;
6779 HelpFiles.Destroy;
6780 exit;
6781 end;
6782
6783 Result := true;
6784
6785 AddList( HelpFiles, CurrentOpenFiles );
6786
6787 AddCurrentToMRUFiles;
6788
6789 DisplayFiles( HelpFiles,
6790 FirstNewContentsNode );
6791
6792 // Select first contents node of new file
6793 if FirstNewContentsNode <> nil then
6794 ContentsOutline.SelectedNode := FirstNewContentsNode;
6795
6796 HelpFiles.Destroy;
6797
6798 ClearWaitCursor;
6799
6800 ResetProgress;
6801
6802 EnableControls;
6803
6804 if DisplayFirstTopic then
6805 DisplaySelectedContentsTopic;
6806
6807 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6808end;
6809
6810Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6811Begin
6812 FileOpen;
6813end;
6814
6815procedure TMainForm.FileOpen;
6816var
6817 Filenames: TStringList;
6818 KeepCurrentFiles: boolean;
6819 OpenedOK: boolean;
6820begin
6821 if not OKToCloseFile then
6822 exit;
6823
6824 if Settings.UseOriginalDialogs then
6825 begin
6826 SystemOpenDialog.Filename := AddDirectorySeparator( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6827 if not SystemOpenDialog.Execute then
6828 exit;
6829
6830 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6831 // note - sibyl's encapsulation doesn't allow multi-select
6832 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6833 end
6834 else
6835 begin
6836 Filenames := TStringList.Create;
6837 KeepCurrentFiles := false;
6838 if not DoOpenMultiFileDialog( FileOpenTitle,
6839 HelpFilesDesc
6840 + '|*.inf;*.hlp|'
6841 + AllFilesDesc
6842 + '|*.*',
6843 '*.hlp;*.inf',
6844 Settings.LastOpenDirectory,
6845 KeepCurrentFiles,
6846 Filenames ) then
6847 exit;
6848
6849 if KeepCurrentFiles then
6850 OpenedOK := OpenAdditionalFiles( FileNames, true )
6851 else
6852 OpenedOK := OpenFiles( FileNames, '', true );
6853 Filenames.Destroy;
6854 end;
6855
6856 if OpenedOK then
6857 ClearHelpManager;
6858End;
6859
6860Procedure TMainForm.CloseWindows;
6861Begin
6862 DestroyListObjects( Windows );
6863 Windows.Clear;
6864end;
6865
6866// Help manager mode
6867
6868// if window is minimised then restore it
6869// (ideally should go back to maximized - don't know how)
6870Procedure TMainForm.RestoreWindow;
6871Begin
6872 If WindowState = wsMinimized then
6873 WindowState := wsNormal;
6874end;
6875
6876Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6877begin
6878 LogEvent(LogNHM, 'NHMDisplayIndex');
6879 RestoreWindow;
6880 DisplayIndex;
6881 // if nothing is being display already...
6882 if Windows.Count = 0 then
6883 // display first topic
6884 DisplaySelectedContentsTopic;
6885end;
6886
6887Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6888begin
6889 LogEvent(LogNHM, 'NHMDisplayContents');
6890 RestoreWindow;
6891 DisplayContents;
6892 // if nothing is being display already...
6893 if Windows.Count = 0 then
6894 begin
6895 // display first topic
6896 DisplaySelectedContentsTopic;
6897 end;
6898end;
6899
6900Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6901begin
6902 LogEvent(LogNHM, 'NHMTopicByResourceID');
6903 RestoreWindow;
6904 DisplayContents;
6905 DisplayTopicByResourceID( Msg.Param1 );
6906end;
6907
6908Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6909var
6910 pMessageMem: pchar;
6911 PanelName: string;
6912 Topic: TTopic;
6913begin
6914 LogEvent(LogNHM, 'NHMTopicByPanelName');
6915 RestoreWindow;
6916 DisplayContents;
6917
6918 pMessageMem := pchar( Msg.Param1 );
6919 PanelName := StrPas( pMessageMem );
6920 SharedMemory.Free( pMessageMem );
6921
6922 LogEvent(LogNHM, '....NHMTopicByPanelName panel:' + PanelName);
6923 Topic := FindTopicByName( PanelName );
6924 if Topic = nil then
6925 Topic := FindTopicByGlobalName( PanelName );
6926
6927 if Topic <> nil then
6928 DisplayTopic( Topic )
6929 else
6930 SearchFor( PanelName );
6931end;
6932
6933// Sent from other instances starting up (and exiting immediately)
6934
6935Procedure TMainForm.NHMSearch( Var Msg: TMessage );
6936var
6937 pSearchText: pchar;
6938begin
6939 LogEvent(LogNHM, 'NHMSearch');
6940 RestoreWindow;
6941
6942 pSearchText := pstring( Msg.Param1 );
6943 SearchFor( StrPas( pSearchText ) );
6944 SharedMemory.Free( pSearchText );
6945end;
6946
6947Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
6948var
6949 pSearchText: pchar;
6950begin
6951 LogEvent(LogNHM, 'NHMGlobalSearch');
6952 RestoreWindow;
6953
6954 pSearchText := pstring( Msg.Param1 );
6955 DoGlobalSearch( StrPas( pSearchText ) );
6956 SharedMemory.Free( pSearchText );
6957end;
6958
6959Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
6960begin
6961 LogEvent(LogNHM, 'NHMShowUsage');
6962 RestoreWindow;
6963 ShowUsage;
6964end;
6965
6966Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
6967var
6968 pFileNames: pchar;
6969begin
6970 LogEvent(LogNHM, 'NHMSetFiles');
6971 // NOT restoring window here because this is not something the user should see...
6972 pFileNames := pstring( Msg.Param1 );
6973 OpenFilesFromTextList( StrPas( pFileNames ), false );
6974 SharedMemory.Free( pFileNames );
6975end;
6976
6977Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
6978var
6979 pTitle: pchar;
6980begin
6981 LogEvent(LogNHM, 'NHMSetTitle');
6982 pTitle := pstring( Msg.Param1 );
6983 MainTitle := StrPas( pTitle );
6984 SharedMemory.Free( pTitle );
6985
6986 SetMainCaption;
6987end;
6988
6989Procedure TMainForm.NHMTest( Var Msg: TMessage );
6990var
6991 ps: pstring;
6992begin
6993 LogEvent(LogNHM, 'NHMTest');
6994 ps := PString( Msg.Param1 );
6995 ShowMessage( 'Got test message: ' + ps^ );
6996 SharedMemory.Free( ps );
6997end;
6998
6999Initialization
7000 RegisterClasses ([TMainForm, TSplitBar,
7001 TNoteBook,
7002 TEdit, TListBox,
7003 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
7004 TImageList, TPanel, TButton,
7005 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
7006 , TProgressBar, TTabSet2]);
7007End.
Note: See TracBrowser for help on using the repository browser.