source: trunk/NewView/MainForm.pas@ 228

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

refactoring for language handling

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