source: trunk/NewView/MainForm.pas@ 252

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

fix for #33
fix usage of StrStartsWithIgnoringCase

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