source: trunk/NewView/MainForm.pas@ 265

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

support -i option

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