source: branches/2.20_branch/NewView/MainForm.pas

Last change on this file was 373, checked in by RBRi, 9 years ago

ignore child nodes before the first root node like the original viewer

  • Property svn:eol-style set to native
File size: 188.1 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-2009 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 aFileNames: TStrings; aHelpFiles: TList) : boolean;
386 Procedure DisplayFiles( NewFiles: TList;
387 Var FirstContentsNode: TNode );
388
389 Procedure OpenDroppedFile( Source: TObject );
390
391 Function OpenWindowsHelp( const Filename: string ): boolean;
392
393 function DisplayTopicByResourceID( ID: uint16 ): boolean;
394 function DisplayTopicByName( const TopicName: string ): boolean;
395 function DisplayTopicByGlobalName( const TopicName: string ): boolean;
396
397 Procedure DisplayIndex;
398 Procedure DisplayContents;
399 Procedure DisplaySearch;
400
401 Protected
402 // Startup functions ----------------------------------
403
404 Function pSharedStruct: TPNewHelpMgrSharedStruct;
405 Procedure PositionWindow;
406 Procedure RestoreWindow;
407
408 Procedure CheckEnvironmentVars;
409 Procedure ShowUsage;
410
411 // Loading functions ----------------------------------
412
413 // Most recently used files list
414 Procedure CreateMRUMenuItems;
415 Procedure OnMRUMenuItemClick( Sender: TObject );
416
417 Procedure OnHelpFileLoadProgress( n, outof: integer;
418 message: string );
419
420 // Returns nil if file is not open
421 Function FindOpenHelpFile( FileName: string ): THelpFile;
422
423 // Navigation -------------------------------------------------
424
425 Procedure SaveNavigatePoint;
426 Procedure SaveWindows( SourceList: TList;
427 DestList: TList;
428 Parent: TSavedHelpWindow );
429
430 Procedure UpdateCurrentNavigatePoint;
431 Procedure ClearPageHistory;
432
433 Procedure NavigateToPoint( NavPoint: TNavigatePoint );
434 Procedure NavigateToHistoryIndex( Index: longint );
435
436 Procedure DisplayWindows( WindowList: TList;
437 Parent: THelpWindow );
438 Procedure ShowWindows;
439 Procedure ShowWindowList( WindowList: TList );
440 Procedure CloseWindows;
441
442 Procedure FocusFirstHelpWindow;
443
444 Procedure NavigateBack;
445 Procedure NavigateForward;
446 Procedure NavigatePreviousInContents;
447 Procedure NavigateNextInContents;
448
449 Procedure CreateNavigateToMenuItems;
450
451 // GUI status updates ---------------------------------
452
453 Procedure EnableControls;
454 Procedure EnableSearchButton;
455 Procedure SetStatus( Text: String );
456 Procedure SetProgress( n, outof: integer;
457 message: string );
458 Procedure ResetProgress;
459 Procedure RefreshWindows( WindowList: TList );
460
461 // language stuff
462 // called by callback
463 Procedure OnLanguageEvent(Language: TLanguageFile; const Apply: boolean );
464
465 function ShowCodes: boolean;
466 function ShowWordIndices: boolean;
467
468 // Loading views --------------------------------------
469
470 // Used in loading contents
471 Procedure AddChildNodes( HelpFile: THelpFile;
472 ParentNode: TNode;
473 Level: longint;
474 Var TopicIndex: longint );
475 Procedure LoadContents( Files: TList;
476 Var FirstNode: TNode );
477 Procedure LoadIndex;
478
479 // Note manipulations --------------------------------
480
481 procedure AddNote;
482 Procedure EditNote( NoteIndex: longint );
483 procedure DeleteNote( NoteIndex: longint );
484 Procedure SaveNotes;
485 Procedure SaveNotesForFile( HelpFile: THelpFile );
486 Procedure LoadNotes( HelpFile: THelpFile );
487 Procedure GotoCurrentNote;
488
489 // make sure that note insert positions are not in
490 // the middle of tags due to help file or newview updates.
491 Procedure CorrectNotesPositions( Topic: TTopic;
492 Text: pchar );
493
494 Procedure InsertNotesIntoTopicText( Topic: TTopic;
495 Text: TAString );
496 function FindOriginalNoteCharIndex( NoteCharIndex: longword;
497 Topic: TTopic ): longword;
498 function FindActualNoteCharIndex( NoteCharIndex: longword;
499 MaxNoteIndex: longword;
500 Topic: TTopic ): longword;
501 procedure RefreshNoteInsertInfo( NoteIndex: longword );
502 procedure ClearNotes;
503
504 Procedure EnableNotesControls;
505 Procedure UpdateNotesDisplay;
506
507 Procedure RefreshFontSubstitutions;
508
509 // GUI actions ------------------------------------------
510
511 procedure FileOpen;
512
513 Procedure PrintTopics;
514 function DoPrinting( Parameters: TObject ): TObject;
515 Procedure StopPrinting;
516
517 Procedure DoFind( FindOrigin: TFindOrigin );
518
519 // Bookmarks ------------------------------------------
520
521 Procedure NavigateToBookmark( Bookmark: TBookmark );
522 Procedure BuildBookmarksMenu;
523 Procedure UpdateBookmarksForm;
524 Procedure BookmarksMenuItemClick( Sender: TObject );
525 procedure AddBookmark;
526 procedure ClearBookmarks;
527 procedure SaveBookmarks;
528 procedure SaveBookmarksForFile( HelpFile: THelpFile );
529 procedure LoadBookmarks( HelpFile: THelpFile );
530 procedure OnBookmarksChanged( Sender: TObject );
531
532 // Global search -------------------------------------
533
534 procedure DoGlobalSearch( const SearchText: string );
535 // Called when viewing topics from global search
536 Procedure OnViewGlobalSearchTopic( FileName: string;
537 TopicIndex: longint );
538
539 // Options and appearance -----------------------------
540
541 procedure DoOptions;
542
543 procedure ApplySettings;
544
545 // changes normal or fixed font depending on shift state
546 Procedure SetTopicFont( NewFont: TFont );
547
548 Procedure SetApplicationFont( NewFont: TFont );
549
550 // Retrieve control colours (in case drag'n'drop used to change)
551 Procedure GetColors;
552 // Set the layout of the main form
553 Procedure SetLayout;
554 // Lay out the specified list of help windows
555 Procedure LayoutWindowList( WindowList: TList );
556 // Setup the rich text views in the specified windows (e.g for changing global settings)
557 Procedure SetupViews( WindowList: TList );
558
559 // Topic display -------------------------------------
560
561 // Major display topic function.
562 procedure DisplayTopic( Topic: TTopic );
563
564 Procedure DisplaySelectedIndexTopic;
565 Procedure DisplaySelectedSearchResultTopic;
566 Procedure DisplaySelectedContentsTopic;
567
568 Procedure DisplayTopicInWindow( Window: THelpWindow;
569 FollowAutoLinks: boolean;
570 KeepPosition: boolean );
571
572 function OpenWindow( Topic: TTopic;
573 Group: longint;
574 Parent: THelpWindow;
575 Rect: THelpWindowRect;
576 FollowAutoLinks: boolean ): THelpWindow;
577
578 Procedure RemoveHelpWindowFromParent( Window: THelpWindow );
579
580 Procedure FollowLink( Link: THelpLink;
581 SourceWindow: THelpWindow );
582
583 Function FindTopicByResourceID( ID: uint16 ): TTopic;
584 Function FindTopicByName( const Name: string ): TTopic;
585 Function FindTopicByGlobalName( const Name: string ): TTopic;
586
587 Function FindTopicForLink( Link: THelpLink ): TTopic;
588
589 Function FindWindowFromView( View: TRichTextView; WindowList: TList ): THelpWindow;
590 Function FindWindowFromGroup( Group: longint; WindowList: TList ): THelpWindow;
591 Function FindWindowFromTopic( Topic: TTopic; WindowList: TList ): THelpWindow;
592 Function GetActiveWindow: THelpWindow;
593
594 Procedure DoSearch;
595 Procedure SearchFor( const SearchText: string );
596 Procedure StartupTopicSearch( const SearchText: string );
597
598 // clear search match sequences
599 Procedure ClearAllWordSequences;
600
601 Procedure SetMainCaption;
602
603 // cancel help manager mode
604 Procedure ClearHelpManager;
605 Procedure PostHelpManagerMessage( MessageType: ULONG;
606 Param1: long;
607 Param2: long );
608
609 HelpManagerWindows: TList; // of HWND
610
611 function OwnHelpMode: boolean;
612 CurrentOpenFiles: TList; // current open help files.
613 MRUMenuItems: TList; // most recently used file list
614 NavigateToMenuItems: TList;
615 MainTitle: string;
616
617 // Current topic has the vague meaning that it was the last
618 // topic selected by the user... (?)
619 CurrentTopic: TTopic;
620
621 AllFilesWordSequences: TList; // of lists; one per open file; of possible word sequences
622
623 // use during decode...
624 TopicText: TAString;
625
626 Windows: TList; // top level help windows
627
628 PageHistory: TStringList; // history
629 CurrentHistoryIndex: longint; // where we are in history
630
631 Navigating: boolean; // true while going to a particular history point
632
633 DisplayedIndex: TStringList; // duplicate of index listbox,
634 // for fast case insensitive searching
635 InIndexSearch: boolean; // true while searching index
636 IndexLoaded: boolean;
637
638 ContentsLoaded: boolean;
639
640 StartingUp: boolean; // true while starting
641 SettingFont: boolean;
642 DisplayingTopicWindow: boolean;
643
644 FindText: string; // last text found (Ctrl-F)
645
646 Notes: TList; // Notes in current files.
647
648 Bookmarks: TList;
649 BookmarksMenuItems: TList;
650
651 // while loading... so owe can display progress
652 LoadingFilenameList: TStringList;
653 LoadingFileIndex: integer;
654
655 PrintThread: TGenericThreadManager;
656 procedure OnPrintProgress( n, outof: integer;
657 Message: string );
658 procedure OnPrintComplete( Dummy: TObject );
659 protected
660 // language stuff
661 FileOpenTitle: string;
662 LoadingFileMsg: string;
663 HelpFileError: string;
664 LoadingStatusDisplaying: string;
665 LoadingStatusNotesAndBookmarks: string;
666 LoadingStatusContents: string;
667 LoadingStatusIndex: string;
668 LoadingStatusDone: string;
669
670 AllFilesDesc: string;
671 HelpFilesDesc: string;
672 LanguageFilesDesc: string;
673
674 SaveLanguageTitle: string;
675 OpenLanguageTitle: string;
676 SaveLanguageError: string;
677
678 HelpManagerVersionTitle: string;
679
680 FindResourceIDTitle: string;
681 FindResourceIDPrompt: string;
682 InvalidResourceIDError: string;
683 ResourceIDNotFoundError: string;
684
685 OpenSpecialTitle: string;
686 OpenSpecialPrompt: string;
687
688 PrintTopicTitle: string;
689 NoPrinterError: string;
690 SelectWindowToPrintError: string;
691 PrintingComplete : string;
692 PrintingError: string;
693 StoppingPrintMsg: string;
694 PrintStoppedMsg: string;
695 CheckStopPrintTitle: string;
696 CheckStopPrintMsg: string;
697
698 TopicInfoTitle: string;
699 TopicInfoTopicTitle: string;
700 TopicInfoIndex: string;
701 TopicInfoFile: string;
702 TopicInfoResourceIDs: string;
703 TopicInfoNoResourceIDs: string;
704
705 ParameterCountLabel: string;
706
707 NewViewHelpTitle: string;
708 AlreadyNewviewHelp: string;
709 NewViewHelpNotFound: string;
710
711 InvalidLinkErrorTitle: string;
712 InvalidLinkError: string;
713 InvalidResourceIDLinkErrorA: string;
714 InvalidResourceIDLinkErrorB: string;
715
716 OpenedTopicMsg: string;
717
718 AddNoteTitle: string;
719 AddNoteCursorError: string;
720 NoteWithinNoteError: string;
721 LoadNotesTitle: string;
722 LoadNotesError: string;
723 SaveNotesTitle: string;
724 SaveNotesError: string;
725
726 UntitledBookmarkName: string;
727 LoadBookmarksTitle: string;
728 LoadBookmarksError: string;
729 SaveBookmarksTitle: string;
730 SaveBookmarksError: string;
731
732 ApplicationErrorTitle: string;
733 ApplicationErrorA: string;
734 ApplicationErrorB: string;
735 ApplicationErrorC: string;
736
737 EnvironmentVarErrorTitle: string;
738 EnvironmentVarError: string;
739 EnvironmentVarUndefined: string;
740
741 FindTitle: string;
742 FindSelectWindowError: string;
743 FindPrompt: string;
744 TextNotFoundMsg: string;
745
746 FilesInfoTitle: string;
747 FilesInfoOverallTitle: string;
748 FilesInfoFilename: string;
749 FilesInfoFileTitle: string;
750 FilesInfoTopicCount: string;
751 FilesInfoIndexCount: string;
752 FilesInfoDictionaryCount: string;
753 FilesInfoFileSize: string;
754 FilesInfoTotalTopicCount: string;
755 FilesInfoTotalIndexCount: string;
756 FilesInfoTotalFileSize: string;
757
758 SearchTitle: string;
759 SearchSyntaxError: string;
760 SearchingMsg: string;
761 NoSearchMatchesMsg: string;
762 SearchFoundMsgA: string;
763 SearchFoundMsgB: string;
764
765 FileSaveTitle: string;
766 FileSaveSelectWindowError: string;
767 DefaultSaveTopicFilename: string;
768 ReplaceFilePromptA: string;
769 ReplaceFilePromptB: string;
770 UnableToSaveError: string;
771
772 UsageTitle: string;
773 UsageText1: string;
774 UsageText2: string;
775 UsageText3: string;
776 UsageText4: string;
777 UsageText5: string;
778 UsageText6: string;
779 UsageText7: string;
780 UsageText8: string;
781
782 GoBackHint: string;
783
784 SelectAllTitle: string;
785 SelectAllWindowError: string;
786
787 EditNoteMsg: string;
788 ExternalLinkMsg: string;
789 LinkMsg: string;
790 UnknownLinkMsg: string;
791 FootnoteMsg: string;
792
793 ExternalLinkTitle: string;
794 ExternalLinkError: string;
795
796 MRUMultipleFilesHint: string;
797
798 HelpProgramTitle: string;
799 WindowsHelpTitle: string;
800 WindowsHelpPrompt: string;
801
802 ErrorTitle: string;
803
804 FindTopicNameTitle: string;
805 FindTopicNamePrompt: string;
806 TopicNameNotFoundError: string;
807
808 SplitBarDblClickToShow: string;
809 SplitBarDblClickToHide: string;
810
811 End;
812
813Var
814 MainForm: TMainForm;
815 CmdLineParameters : TCmdLineParameters;
816
817Implementation
818
819uses
820 BseDos,
821 BseErr,
822 PMWin,
823 PmShl,
824 Dos,
825 Printers,
826
827 // Library
828 ACLFileIOUtility,
829 ACLUtility,
830 ACLDialogs,
831 RunProgramUnit,
832 StringUtilsUnit,
833 CharUtilsUnit,
834 DebugUnit,
835
836 FileUtilsUnit,
837
838 // Components
839 RichTextPrintUnit,
840 RichTextStyleUnit,
841 RichTextDocumentUnit,
842 ControlsUtility,
843
844 // local: forms
845 InformationFormUnit,
846 OptionsForm,
847 ProductInformationFormUnit,
848 NoteForm,
849 GlobalSearchForm,
850 FileDialogForm,
851 BookmarksFormUnit,
852 PrintDialogUnit,
853
854 // local: others
855 NewViewConstantsUnit,
856 SettingsUnit,
857 VersionUnit,
858 SearchUnit,
859 StartupUnit,
860 GlobalFilelistUnit,
861 WebBrowserUnit,
862 HelpBitmap;
863
864{$R Images}
865
866const
867 // Coolbar button indexes
868 ciOpen = 0;
869 ciPrint = 1;
870 ciNavigator = 2;
871 ciBack = 3;
872 ciForward = 4;
873 ciAddNote = 5;
874 ciAddBookmark = 6;
875 ciPrevious = 7;
876 ciNext = 8;
877 ciGlobalSearch = 9;
878
879 // Page indexes.
880 piContents = 0;
881 piIndex = 1;
882 piSearch = 2;
883 piNotes = 3;
884
885 CrashLogFileName = 'NewView.log';
886
887 _MAX_PATH = 260;
888
889var
890 hNewViewDLL: HMODULE;
891
892 StartMem: longword;
893 LastMem: longword;
894
895 g_ExternalLinkFilename: string;
896 g_ExternalLinkTopic: string;
897 g_ExternalLinkSourceFilename: string;
898 g_ExternalLinkKeepCurrent: boolean; // whether to keep current files open
899
900//
901// ----------------------------------------------------------------------------------------
902// TMainForm implementation
903// ----------------------------------------------------------------------------------------
904//
905
906Procedure TMainForm.SaveAsIPFMIOnClick (Sender: TObject);
907var
908 FileName: string;
909 F: TextFile;
910 H: THelpFile;
911 i: longint;
912 T: TTopic;
913 ResourceIDs: TList;
914 ImageOffsets: TList;
915 ImageOffset: longint;
916 Image: THelpBitmap;
917Begin
918 H := CurrentOpenFiles[ 0 ];
919
920 FileName := ChangeFileExt( ExtractFileName( H.Filename ), '.ipf' );
921 if not DoSaveFileDialog( FileSaveTitle,
922 'IPF' + '|*.ipf',
923 Filename,
924 Settings.LastSaveDirectory,
925 Filename ) then
926 exit;
927 if FileExists( Filename ) then
928 if not DoConfirmDlg( FileSaveTitle,
929 ReplaceFilePromptA
930 + Filename
931 + ReplaceFilePromptB ) then
932 exit;
933
934 ImageOffsets := TList.Create;
935
936 AssignFile( F, FileName );
937 Rewrite( F );
938 WriteLn( F, ':userdoc.' );
939
940 // We can't tell if some levels of the contents were
941 // merged into the text of topics. So we just assume all are visible
942 WriteLn( F, ':docprof toc=123456.' );
943
944 ResourceIDs := TList.Create;
945
946 WriteLn( F, ':title.' + H.Title );
947
948 for i := 0 to H.TopicCount - 1 do
949 begin
950 T := H.Topics[ i ];
951
952 SetProgress( i div 2, H.TopicCount , 'Saving text...' );
953
954 WriteLn( F, '' );
955
956
957 if T.ContentsLevel = 0 then
958 begin
959 // perhaps it means footnote?
960 // Level := 1;
961 Write( F, ':fn id=fn' + IntToStr( i ) + '.' ); // use index as id
962
963 T.SaveToIPF( F, ImageOffsets );
964
965 WriteLn( F, '' );
966 WriteLn( F, ':efn.' );
967 end
968 else
969 begin
970 Write( F, ':h' + IntToStr( T.ContentsLevel ) );
971 Write( F, ' id=' + IntToStr( i ) ); // use index as id
972
973 H.FindResourceIDsForTopic( T, ResourceIDs );
974 if ResourceIDs.Count > 0 then
975 begin
976 Write( F, ' res=' + IntToStr( longint( ResourceIDs[ 0 ] ) ) );
977 end;
978
979 if not T.ShowInContents then
980 Write( F, ' hide' );
981
982 if T.ContentsGroupIndex > 0 then
983 Write( F, ' group=' + IntToStr( T.ContentsGroupIndex ) );
984
985 Write( F, '.' ); // end of header
986 WriteLn( F, T.Title );
987
988 T.SaveToIPF( F, ImageOffsets );
989 end;
990
991
992
993 end;
994
995 ResourceIDs.Destroy;
996
997 WriteLn( F, ':euserdoc.' );
998 System.Close( F );
999
1000 // Now write images
1001
1002 for i := 0 to ImageOffsets.Count - 1 do
1003 begin
1004 ImageOffset := longint( ImageOffsets[ i ] );
1005
1006 SetProgress( i div 2 + ImageOffsets.Count div 2,
1007 ImageOffsets.Count ,
1008 'Saving images...' );
1009
1010 Image := H.GetImage( ImageOffset );
1011
1012 if Image <> nil then
1013 begin
1014 Image.SaveToFile( ExtractFilePath( Filename )
1015 + 'img'
1016 + IntToStr( i )
1017 + '.bmp' );
1018 Image.Destroy;
1019 end;
1020
1021 end;
1022
1023 ResetProgress;
1024 SetStatus( 'Save complete' );
1025 ImageOffsets.Destroy;
1026End;
1027
1028Procedure TMainForm.DebugFindBinaryMIOnClick (Sender: TObject);
1029Var
1030 DataStr: string;
1031 data: array[ 0.. 255 ] of byte;
1032 DataLen: longint;
1033 FileIndex: longint;
1034 HelpFile: THelpFile;
1035 i: longint;
1036 Topic: TTopic;
1037
1038 tmpParts : TStringList;
1039Begin
1040 if not DoInputQuery( 'Binary Find',
1041 'Enter data to find (decimal, separate with spaces)',
1042 DataStr ) then
1043 exit;
1044
1045 tmpParts := TStringList.Create;
1046 StrExtractStringsIgnoreEmpty(tmpParts, DataStr, [' '], #0);
1047 for i := 0 to tmpParts.count-1 do
1048 begin
1049 Data[i] := StrToInt(tmpParts[i]);
1050 end;
1051 DataLen := tmpParts.count;
1052 tmpParts.Destroy;
1053
1054 ShowTab( piSearch );
1055 SearchResultsListBox.Clear;
1056
1057 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
1058 begin
1059 HelpFile := CurrentOpenFiles[ FileIndex ];
1060 for i := 0 to HelpFile.TopicCount -1 do
1061 begin
1062 Topic := HelpFile.Topics[ i ];
1063 if Topic.SearchForData( Addr(Data), DataLen) then
1064 begin
1065 SearchResultsListBox.Items.AddObject( Topic.Title, Topic );
1066 end;
1067
1068 end;
1069
1070 end;
1071
1072End;
1073
1074Procedure TMainForm.TopicByNameMIOnClick (Sender: TObject);
1075var
1076 TopicNameString: string;
1077Begin
1078 if not DoInputQuery( FindTopicNameTitle,
1079 FindTopicNamePrompt,
1080 TopicNameString ) then
1081 exit;
1082
1083 if not DisplayTopicByName( TopicNameString ) then
1084 if not DisplayTopicByGlobalName( TopicNameString ) then
1085 DoErrorDlg( FindTopicNameTitle,
1086 TopicNameNotFoundError );
1087End;
1088
1089Function TMainForm.pSharedStruct: TPNewHelpMgrSharedStruct;
1090begin
1091 Result := TPNewHelpMgrSharedStruct( SharedMemory.Data );
1092end;
1093
1094Procedure TMainForm.CopyLinkLocationPMIOnClick (Sender: TObject);
1095Begin
1096
1097End;
1098
1099Procedure TMainForm.HelpKeysMIOnClick (Sender: TObject);
1100Begin
1101// Application.Help( 10 );
1102End;
1103
1104Procedure TMainForm.MainFormOnCommand (Sender: TObject; Var Command: TCommand);
1105Begin
1106 case Command of
1107 kbF11:
1108 NavigatePreviousInContents;
1109
1110 kbF12:
1111 NavigateNextInContents;
1112
1113 kbF7,
1114 kbCtrlCLeft:
1115 NavigateBack;
1116
1117 kbF8:
1118 NavigateForward;
1119 end;
1120End;
1121
1122Procedure TMainForm.MainFormOnScan (Sender: TObject; Var KeyCode: TKeyCode);
1123Begin
1124End;
1125
1126Procedure TMainForm.ShowLeftPanelMIOnClick (Sender: TObject);
1127Begin
1128 ShowLeftPanel := not ShowLeftPanel;
1129End;
1130
1131Procedure TMainForm.CoolBarOnFontChange (Sender: TObject);
1132Begin
1133 SetApplicationFont( Coolbar.Font );
1134End;
1135
1136Procedure TMainForm.NotebookOnFontChange (Sender: TObject);
1137Begin
1138 SetApplicationFont( Notebook.Font );
1139End;
1140
1141Procedure TMainForm.TabSetOnFontChange (Sender: TObject);
1142Begin
1143 SetApplicationFont( TabSet.Font );
1144End;
1145
1146Procedure TMainForm.IndexListBoxOnFontChange (Sender: TObject);
1147Begin
1148 SetApplicationFont( IndexListBox.Font );
1149End;
1150
1151Procedure TMainForm.NotesListBoxOnFontChange (Sender: TObject);
1152Begin
1153 SetApplicationFont( NotesListBox.Font );
1154End;
1155
1156Procedure TMainForm.DisplayPanelOnFontChange (Sender: TObject);
1157Begin
1158 SetTopicFont( DisplayPanel.Font );
1159End;
1160
1161Procedure TMainForm.SetTopicFont( NewFont: TFont );
1162var
1163 ShiftPressed: boolean;
1164Begin
1165 if SettingFont or StartingUp then
1166 exit;
1167 LogEvent(LogSettings, 'SetTopicFont');
1168
1169 SettingFont := true;
1170
1171 ShiftPressed := ( WinGetKeyState( HWND_DESKTOP,
1172 VK_SHIFT ) and $8000 ) > 0;
1173 if ShiftPressed then
1174 Settings.FixedFont := NewFont
1175 else
1176 Settings.NormalFont := NewFont;
1177
1178 LogEvent(LogSettings, 'Saving settings');
1179
1180 SaveSettings;
1181 LogEvent(LogSettings, 'Applying settings');
1182 ApplySettings;
1183
1184 SettingFont := false;
1185 LogEvent(LogSettings, 'SetTopicFont done');
1186End;
1187
1188Procedure TMainForm.ContentsOutlineOnFontChange (Sender: TObject);
1189Begin
1190 SetApplicationFont( ContentsOutline.Font );
1191End;
1192
1193Procedure TMainForm.SetApplicationFont( NewFont: TFont );
1194Begin
1195 if ( not SettingFont ) and ( not StartingUp ) then
1196 begin
1197 Settings.Fonts[ ApplicationFontIndex ] := NewFont;
1198 SaveSettings;
1199 ApplySettings;
1200 SetLayout;
1201 end;
1202End;
1203
1204Procedure TMainForm.SearchResultsListBoxOnFontChange (Sender: TObject);
1205Begin
1206 SetApplicationFont( SearchResultsListBox.Font );
1207End;
1208
1209Procedure TMainForm.OnDragOverWindow(Sender: TObject; Source: TObject;
1210 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1211Begin
1212 if Source is TExternalDragDropObject then
1213 Accept := true;
1214
1215End;
1216
1217Procedure TMainForm.OnDragDropToWindow(Sender: TObject; Source: TObject;
1218 X: LongInt; Y: LongInt);
1219Begin
1220 OpenDroppedFile( Source );
1221End;
1222
1223Procedure TMainForm.OnWindowTab( Sender: TObject );
1224Begin
1225 OnWindowBackTab( Sender ); // for now
1226End;
1227
1228Procedure TMainForm.OnWindowBackTab( Sender: TObject );
1229Begin
1230 case NoteBook.PageIndex of
1231 piContents:
1232 ContentsOutline.Focus;
1233 piIndex:
1234 IndexListBox.Focus;
1235 piSearch:
1236 SearchResultsListBox.Focus;
1237 piNotes:
1238 NotesListBox.Focus;
1239 end;
1240End;
1241
1242Procedure TMainForm.OnWindowFontChange( Sender: TObject );
1243begin
1244 if not DisplayingTopicWindow then
1245 SetTopicFont( TControl(Sender).Font );
1246end;
1247
1248Procedure TMainForm.DisplayPanelOnDragOver (Sender: TObject; Source: TObject;
1249 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1250Begin
1251 if Source is TExternalDragDropObject then
1252 Accept := true;
1253End;
1254
1255Procedure TMainForm.NotesListBoxOnDragOver (Sender: TObject; Source: TObject;
1256 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1257Begin
1258 if Source is TExternalDragDropObject then
1259 Accept := true;
1260End;
1261
1262Procedure TMainForm.DisplayPanelOnDragDrop (Sender: TObject; Source: TObject;
1263 X: LongInt; Y: LongInt);
1264Begin
1265 OpenDroppedFile( Source );
1266End;
1267
1268Procedure TMainForm.NotesListBoxOnDragDrop (Sender: TObject; Source: TObject;
1269 X: LongInt; Y: LongInt);
1270Begin
1271 OpenDroppedFile( Source );
1272End;
1273
1274Procedure TMainForm.SearchResultsListBoxOnDragDrop (Sender: TObject;
1275 Source: TObject; X: LongInt; Y: LongInt);
1276Begin
1277 OpenDroppedFile( Source );
1278End;
1279
1280Procedure TMainForm.SearchResultsListBoxOnDragOver (Sender: TObject;
1281 Source: TObject; X: LongInt; Y: LongInt; State: TDragState;
1282 Var Accept: Boolean);
1283Begin
1284 if Source is TExternalDragDropObject then
1285 Accept := true;
1286End;
1287
1288Procedure TMainForm.IndexListBoxOnDragDrop (Sender: TObject; Source: TObject;
1289 X: LongInt; Y: LongInt);
1290Begin
1291 OpenDroppedFile( Source );
1292End;
1293
1294Procedure TMainForm.IndexListBoxOnDragOver (Sender: TObject; Source: TObject;
1295 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1296Begin
1297 if Source is TExternalDragDropObject then
1298 Accept := true;
1299End;
1300
1301Procedure TMainForm.ContentsOutlineOnDragOver (Sender: TObject;
1302 Source: TObject; X: LongInt; Y: LongInt; State: TDragState;
1303 Var Accept: Boolean);
1304Begin
1305 if Source is TExternalDragDropObject then
1306 Accept := true;
1307End;
1308
1309Procedure TMainForm.ContentsOutlineOnDragDrop (Sender: TObject;
1310 Source: TObject; X: LongInt; Y: LongInt);
1311Begin
1312 OpenDroppedFile( Source );
1313End;
1314
1315Procedure TMainForm.OpenDroppedFile( Source: TObject );
1316var
1317 DropObject: TExternalDragDropObject;
1318Begin
1319 if not ( Source is TExternalDragDropObject ) then
1320 // probably not needed, but crashes during drag drop completely
1321 // screw PM, so best to be sure!
1322 exit;
1323
1324 DropObject := Source as TExternalDragDropObject;
1325
1326 g_ExternalLinkFileName := AddDirectorySeparator( DropObject.ContainerName )
1327 + DropObject.SourceFilename;
1328 g_ExternalLinkTopic := '';
1329 g_ExternalLinkSourceFilename := ''; // don't care
1330
1331 g_ExternalLinkKeepCurrent := ( WinGetKeyState( HWND_DESKTOP,
1332 VK_SHIFT ) and $8000 ) > 0;
1333 PostMsg( Self.Handle,
1334 WM_FOLLOWEXTERNALLINK,
1335 0,
1336 0 );
1337
1338End;
1339
1340Procedure TMainForm.MainFormOnDragOver (Sender: TObject; Source: TObject;
1341 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
1342Begin
1343 Accept := true;
1344End;
1345
1346Procedure TMainForm.MainFormOnDragDrop (Sender: TObject; Source: TObject;
1347 X: LongInt; Y: LongInt);
1348Begin
1349End;
1350
1351Procedure TMainForm.ContentsOutlineOnItemClick (Node: TNode);
1352Begin
1353 DisplaySelectedContentsTopic;
1354End;
1355
1356Procedure TMainForm.SetMainCaption;
1357begin
1358 if ( Trim( MainTitle ) = '' )
1359 or ( StrEqualIgnoringCase( Trim( MainTitle ), HelpProgramTitle ) ) then
1360 // supress "Help - " or "Help - Help"
1361 Caption := HelpProgramTitle
1362 else
1363 Caption := HelpProgramTitle + ' - ' + MainTitle
1364end;
1365
1366Procedure TMainForm.OnLanguageEvent(Language: TLanguageFile; const Apply: boolean);
1367var
1368 tmpPrefix : String;
1369Begin
1370 // get rid of mru menu items
1371 DestroyListObjects( MRUMenuItems );
1372 MRUMenuItems.Clear;
1373
1374 Language.LoadComponentLanguage( self, Apply );
1375
1376 if Apply then
1377 begin
1378 // copy menu hints to toolbar hints
1379 Coolbar.Sections[ ciOpen ].Hint := OpenMI.Hint;
1380 Coolbar.Sections[ ciPrint ].Hint := PrintMI.Hint;
1381 Coolbar.Sections[ ciNavigator ].Hint := ShowLeftPanelMI.Hint;
1382 Coolbar.Sections[ ciBack ].Hint := NavigateBackMI.Hint;
1383 Coolbar.Sections[ ciForward ].Hint := NavigateForwardMI.Hint;
1384 Coolbar.Sections[ ciAddNote ].Hint := AddNoteMI.Hint;
1385 Coolbar.Sections[ ciAddBookmark ].Hint := AddBookmarkMI.Hint;
1386 Coolbar.Sections[ ciPrevious ].Hint := NavigatePreviousMI.Hint;
1387 Coolbar.Sections[ ciNext ].Hint := NavigateNextMI.Hint;
1388 Coolbar.Sections[ ciGlobalSearch ].Hint := GlobalSearchMI.Hint;
1389 end;
1390
1391 // Load strings referred to by code...
1392 // ----------------------------------------------------------
1393 tmpPrefix := 'MainForm' + LANGUAGE_LABEL_DELIMITER;
1394
1395 Language.LL( Apply, FileOpenTitle, tmpPrefix + 'FileOpenTitle', 'Open Help Files' );
1396 Language.LL( Apply, LoadingFileMsg, tmpPrefix + 'LoadingFileMsg', 'Loading file ' );
1397 Language.LL( Apply, HelpFileError, tmpPrefix + 'HelpFileError', 'Could not open ' );
1398 Language.LL( Apply, LoadingStatusDisplaying, tmpPrefix + 'LoadingStatusDisplaying', 'Displaying...' );
1399 Language.LL( Apply, LoadingStatusNotesAndBookmarks, tmpPrefix + 'LoadingStatusNotesAndBookmarks', 'Loading notes/bookmarks...' );
1400 Language.LL( Apply, LoadingStatusContents, tmpPrefix + 'LoadingStatusContents', 'Display contents... ' );
1401 Language.LL( Apply, LoadingStatusIndex, tmpPrefix + 'LoadingStatusIndex', 'Display index... ' );
1402 Language.LL( Apply, LoadingStatusDone, tmpPrefix + 'LoadingStatusDone', 'Done' );
1403
1404 Language.LL( Apply, HelpFilesDesc, tmpPrefix + 'HelpFilesDesc', 'Help Files (*.inf,*.hlp)' );
1405 Language.LL( Apply, AllFilesDesc, tmpPrefix + 'AllFilesDesc', 'All Files (*)' );
1406 Language.LL( Apply, LanguageFilesDesc, tmpPrefix + 'LanguageFilesDesc', 'NewView Language Files (*.lng)' );
1407
1408 Language.LL( Apply, SaveLanguageTitle, tmpPrefix + 'SaveLanguageTitle', 'Save/Update Language File' );
1409 Language.LL( Apply, OpenLanguageTitle, tmpPrefix + 'OpenLanguageTitle', 'Open Language File' );
1410 Language.LL( Apply, SaveLanguageError, tmpPrefix + 'SaveLanguageError', 'Error saving language file: ' );
1411
1412 Language.LL( Apply, HelpManagerVersionTitle, tmpPrefix + 'HelpManagerVersionTitle', 'Help Manager Version' );
1413
1414 Language.LL( Apply, FindResourceIDTitle, tmpPrefix + 'FindResourceIDTitle', 'Find Resource ID' );
1415 Language.LL( Apply, FindResourceIDPrompt, tmpPrefix + 'FindResourceIDPrompt', 'Enter the resource ID to find' );
1416 Language.LL( Apply, InvalidResourceIDError, tmpPrefix + 'InvalidResourceIDError', 'Invalid resource ID entered' );
1417 Language.LL( Apply, ResourceIDNotFoundError, tmpPrefix + 'ResourceIDNotFoundError', 'Resource ID not found' );
1418
1419 Language.LL( Apply, OpenSpecialTitle, tmpPrefix + 'OpenSpecialTitle', 'Open Special' );
1420 Language.LL( Apply, OpenSpecialPrompt, tmpPrefix + 'OpenSpecialPrompt', 'Enter help filename/environment variable name' );
1421
1422 Language.LL( Apply, PrintTopicTitle, tmpPrefix + 'PrintTopicTitle', 'Print Topic' );
1423 Language.LL( Apply, NoPrinterError, tmpPrefix + 'NoPrinterError', 'You don''t have a printer configured.' );
1424 Language.LL( Apply, SelectWindowToPrintError, tmpPrefix + 'SelectWindowToPrintError', 'You must select the window you want to print.' );
1425 Language.LL( Apply, PrintingComplete, tmpPrefix + 'PrintingComplete', 'Printing complete' );
1426 Language.LL( Apply, PrintingError, tmpPrefix + 'PrintingError', 'Error while printing: ' );
1427 Language.LL( Apply, StoppingPrintMsg, tmpPrefix + 'StoppingPrintMsg', 'Stopping print...' );
1428 Language.LL( Apply, PrintStoppedMsg, tmpPrefix + 'PrintStoppedMsg', 'Printing stopped' );
1429 Language.LL( Apply, CheckStopPrintTitle, tmpPrefix + 'CheckStopPrintTitle', 'Stop Print?' );
1430 Language.LL( Apply, CheckStopPrintMsg, tmpPrefix + 'CheckStopPrintMsg', 'Printing is still in progress. It will be stopped if you close.' );
1431
1432 Language.LL( Apply, TopicInfoTitle, tmpPrefix + 'TopicInfo.Title', 'Topic Information' );
1433 Language.LL( Apply, TopicInfoTopicTitle, tmpPrefix + 'TopicInfo.TopicTitle', 'Title: ' );
1434 Language.LL( Apply, TopicInfoIndex, tmpPrefix + 'TopicInfo.Index', 'Index: ' );
1435 Language.LL( Apply, TopicInfoFile, tmpPrefix + 'TopicInfo.File', 'File: ' );
1436 Language.LL( Apply, TopicInfoResourceIDs, tmpPrefix + 'TopicInfo.ResourceIDs', 'Resource IDs:' );
1437 Language.LL( Apply, TopicInfoNoResourceIDs, tmpPrefix + 'TopicInfo.NoResourceIDs', ' (None)' );
1438
1439 Language.LL( Apply, ParameterCountLabel, tmpPrefix + 'ParameterCountLabel', 'Parameter Count: ' );
1440
1441 Language.LL( Apply, NewViewHelpTitle, tmpPrefix + 'NewViewHelpTitle', 'NewView Help' );
1442 Language.LL( Apply, AlreadyNewviewHelp, tmpPrefix + 'AlreadyNewviewHelp', 'You are already viewing the NewView help file' );
1443 Language.LL( Apply, NewViewHelpNotFound, tmpPrefix + 'NewViewHelpNotFound', 'Couldn''t find the NewView helpfile: ' );
1444
1445 Language.LL( Apply, InvalidLinkErrorTitle, tmpPrefix + 'InvalidLinkErrorTitle', 'Invalid Link' );
1446 Language.LL( Apply, InvalidLinkError, tmpPrefix + 'InvalidLinkError', 'Cannot follow link to nonexistent topic' );
1447 Language.LL( Apply, InvalidResourceIDLinkErrorA, tmpPrefix + 'InvalidResourceIDLinkErrorA', 'Could not find linked topic (Resource #' );
1448 Language.LL( Apply, InvalidResourceIDLinkErrorB, tmpPrefix + 'InvalidResourceIDLinkErrorB', '). This may be from another file.' );
1449
1450 Language.LL( Apply, OpenedTopicMsg, tmpPrefix + 'OpenedTopicMsg', 'Opened topic #' );
1451
1452 Language.LL( Apply, AddNoteTitle, tmpPrefix + 'AddNoteTitle', 'Add Note' );
1453 Language.LL( Apply, AddNoteCursorError, tmpPrefix + 'AddNoteCursorError', 'Before adding a note, position the cursor where you want the note to be placed.' );
1454 Language.LL( Apply, NoteWithinNoteError, tmpPrefix + 'NoteWithinNoteError', 'You can''t add a note within a link or another note' );
1455 Language.LL( Apply, LoadNotesTitle, tmpPrefix + 'LoadNotesTitle', 'Load Notes' );
1456 Language.LL( Apply, LoadNotesError, tmpPrefix + 'LoadNotesError', 'Error loading notes from ' );
1457 Language.LL( Apply, SaveNotesTitle, tmpPrefix + 'SaveNotesTitle', 'Save Notes' );
1458 Language.LL( Apply, SaveNotesError, tmpPrefix + 'SaveNotesError', 'Error saving notes to ' );
1459
1460 Language.LL( Apply, UntitledBookmarkName, tmpPrefix + 'UntitledBookmarkName', '(Untitled)' );
1461 Language.LL( Apply, LoadBookmarksTitle, tmpPrefix + 'LoadBookmarksTitle', 'Load Bookmarks' );
1462 Language.LL( Apply, LoadBookmarksError, tmpPrefix + 'LoadBookmarksError', 'Could not load bookmarks: ' );
1463 Language.LL( Apply, SaveBookmarksTitle, tmpPrefix + 'SaveBookmarksTitle', 'Save Bookmarks' );
1464 Language.LL( Apply, SaveBookmarksError, tmpPrefix + 'SaveBookmarksError', 'Could not save bookmarks: ' );
1465
1466 Language.LL( Apply, ApplicationErrorTitle, tmpPrefix + 'ApplicationErrorTitle', 'Application Error - Close?' );
1467 Language.LL( Apply, ApplicationErrorA, tmpPrefix + 'ApplicationErrorA', 'This application has crashed. ' );
1468 Language.LL( Apply, ApplicationErrorB, tmpPrefix + 'ApplicationErrorB', '(Details logged to ' );
1469 Language.LL( Apply, ApplicationErrorC, tmpPrefix + 'ApplicationErrorC', 'Close application? ' );
1470
1471 Language.LL( Apply, EnvironmentVarErrorTitle, tmpPrefix + 'EnvironmentVarErrorTitle', 'Environment Variable Warning' );
1472 Language.LL( Apply, EnvironmentVarError,
1473 tmpPrefix + 'EnvironmentVarError',
1474 'NewView found a problem with environment variables. '
1475 + 'These are used when finding help files. '
1476 + 'You may have problems launching help.' );
1477 Language.LL( Apply, EnvironmentVarUndefined, tmpPrefix + 'EnvironmentVarUndefined', 'Undefined: ' );
1478
1479 Language.LL( Apply, FindTitle, tmpPrefix + 'FindTitle', 'Find' );
1480 Language.LL( Apply, FindSelectWindowError, tmpPrefix + 'FindSelectWindowError', 'Click in a window first' );
1481 Language.LL( Apply, FindPrompt, tmpPrefix + 'FindPrompt', 'Enter the text to find' );
1482 Language.LL( Apply, TextNotFoundMsg, tmpPrefix + 'TextNotFoundMsg', 'Text not found' );
1483
1484 Language.LL( Apply, FilesInfoTitle, tmpPrefix + 'FilesInfoTitle', 'Open Files Information' );
1485 Language.LL( Apply, FilesInfoOverallTitle, tmpPrefix + 'FilesInfoOverallTitle', 'Title: ' );
1486 Language.LL( Apply, FilesInfoFilename, tmpPrefix + 'FilesInfoFilename', 'Filename: ' );
1487 Language.LL( Apply, FilesInfoFileTitle, tmpPrefix + 'FilesInfoFileTitle', ' Title: ' );
1488 Language.LL( Apply, FilesInfoTopicCount, tmpPrefix + 'FilesInfoTopicCount', ' Topic Count: ' );
1489 Language.LL( Apply, FilesInfoIndexCount, tmpPrefix + 'FilesInfoIndexCount', ' Index Count: ' );
1490 Language.LL( Apply, FilesInfoDictionaryCount, tmpPrefix + 'FilesInfoDictionaryCount', ' Dictionary Count: ' );
1491 Language.LL( Apply, FilesInfoFileSize, tmpPrefix + 'FilesInfoFileSize', ' Size: ' );
1492 Language.LL( Apply, FilesInfoTotalTopicCount, tmpPrefix + 'FilesInfoTotalTopicCount', 'Total Topic Count: ' );
1493 Language.LL( Apply, FilesInfoTotalIndexCount, tmpPrefix + 'FilesInfoTotalIndexCount', 'Total Index Count: ' );
1494 Language.LL( Apply, FilesInfoTotalFileSize, tmpPrefix + 'FilesInfoTotalFileSize', 'Total File Size: ' );
1495
1496 Language.LL( Apply, SearchTitle, tmpPrefix + 'SearchTitle', 'Search' );
1497 Language.LL( Apply, SearchSyntaxError, tmpPrefix + 'SearchSyntaxError', 'Error in search syntax: ' );
1498 Language.LL( Apply, SearchingMsg, tmpPrefix + 'SearchingMsg', 'Searching...' );
1499 Language.LL( Apply, NoSearchMatchesMsg, tmpPrefix + 'NoSearchMatchesMsg', 'No matches found for ' );
1500 Language.LL( Apply, SearchFoundMsgA, tmpPrefix + 'SearchFoundMsgA', 'Found ' );
1501 Language.LL( Apply, SearchFoundMsgB, tmpPrefix + 'SearchFoundMsgB', ' matches for ' );
1502
1503 Language.LL( Apply, FileSaveTitle, tmpPrefix + 'FileSaveTitle', 'Save Topic' );
1504 Language.LL( Apply, FileSaveSelectWindowError, tmpPrefix + 'FileSaveSelectWindowError', 'Before saving, click in the window you want to save.' );
1505 Language.LL( Apply, DefaultSaveTopicFilename, tmpPrefix + 'DefaultSaveTopicFilename', 'topic.txt' );
1506
1507 Language.LL( Apply, ReplaceFilePromptA, tmpPrefix + 'ReplaceFilePromptA', 'Replace existing file ' );
1508 Language.LL( Apply, ReplaceFilePromptB, tmpPrefix + 'ReplaceFilePromptB', '?' );
1509 Language.LL( Apply, UnableToSaveError, tmpPrefix + 'UnableToSaveError', 'Unable to save file: ' );
1510
1511 Language.LL( Apply, UsageTitle, tmpPrefix + 'UsageTitle', 'NewView Command Line' );
1512 Language.LL( Apply, UsageText1, tmpPrefix + 'UsageText1', 'Usage: ' );
1513 Language.LL( Apply, UsageText2, tmpPrefix + 'UsageText2', 'NewView <filename> [<topic>]' );
1514 Language.LL( Apply, UsageText3, tmpPrefix + 'UsageText3', ' /s Do search for <topic>' );
1515 Language.LL( Apply, UsageText4, tmpPrefix + 'UsageText4', ' /g Do global search for <topic>' );
1516 Language.LL( Apply, UsageText5, tmpPrefix + 'UsageText5', ' /pos:l,b,w,h Set window position' );
1517 Language.LL( Apply, UsageText6, tmpPrefix + 'UsageText6', ' /lang:<lang> Load UI language' );
1518 Language.LL( Apply, UsageText7, tmpPrefix + 'UsageText7', ' /title:<title> Set window title' );
1519 Language.LL( Apply, UsageText8, tmpPrefix + 'UsageText8', 'See help for details' );
1520
1521 Language.LL( Apply, GoBackHint, tmpPrefix + 'GoBackHint', 'Go back to ' );
1522
1523 Language.LL( Apply, SelectAllTitle, tmpPrefix + 'SelectAllTitle', 'Select All' );
1524 Language.LL( Apply, SelectAllWindowError, tmpPrefix + 'SelectAllWindowError', 'Click in a text window first' );
1525
1526 Language.LL( Apply, EditNoteMsg, tmpPrefix + 'EditNoteMsg', 'Click to edit note' );
1527 Language.LL( Apply, ExternalLinkMsg, tmpPrefix + 'ExternalLinkMsg', 'Link to another file' );
1528 Language.LL( Apply, LinkMsg, tmpPrefix + 'LinkMsg', 'Link to' );
1529 Language.LL( Apply, UnknownLinkMsg, tmpPrefix + 'UnknownLinkMsg', 'Unknown link' );
1530 Language.LL( Apply, FootnoteMsg, tmpPrefix + 'FootnoteMsg', 'Footnote' );
1531
1532 Language.LL( Apply, ExternalLinkTitle, tmpPrefix + 'ExternalLinkTitle', 'File Link' );
1533 Language.LL( Apply, ExternalLinkError, tmpPrefix + 'ExternalLinkError', 'Sorry, this is a link to another file, which is not currently implemented in NewView' );
1534
1535 Language.LL( Apply, MRUMultipleFilesHint, tmpPrefix + 'MRUMultipleFilesHint', 'files' );
1536 Language.LL( Apply, HelpProgramTitle, tmpPrefix + 'HelpProgramTitle', 'Help' );
1537
1538 Language.LL( Apply, WindowsHelpTitle, tmpPrefix + 'WindowsHelpTitle', 'Windows Help' );
1539// TODO
1540 Language.LL( Apply,
1541 WindowsHelpPrompt,
1542 tmpPrefix + 'WindowsHelpPrompt',
1543 'This file is a Windows help file. '
1544 + 'Would you like to start Windows Help viewer?' );
1545
1546 Language.LL( Apply, ErrorTitle, tmpPrefix + 'ErrorTitle', 'Error' );
1547
1548 Language.LL( Apply, FindTopicNameTitle, tmpPrefix + 'FindTopicNameTitle', 'Find Topic By Name' );
1549 Language.LL( Apply, FindTopicNamePrompt, tmpPrefix + 'FindTopicNamePrompt', 'Enter the topic name to search for' );
1550 Language.LL( Apply, TopicNameNotFoundError, tmpPrefix + 'TopicNameNotFoundError', 'Topic name not found' );
1551 Language.LL( Apply, SplitBarDblClickToShow, tmpPrefix + 'SplitBarDblClickToShow', 'Double-click to show left panel' );
1552 Language.LL( Apply, SplitBarDblClickToHide, tmpPrefix + 'SplitBarDblClickToHide', 'Double-click to hide left panel' );
1553
1554 SetMainCaption;
1555 CreateMRUMenuItems;
1556
1557 // ----------------------------------------------------------
1558end;
1559
1560Procedure TMainForm.DebugLoadLanguageMIOnClick (Sender: TObject);
1561Var
1562 Dir: string;
1563 Filename: string;
1564Begin
1565 Dir := GetApplicationDir;
1566 if not DoOpenFileDialog( OpenLanguageTitle,
1567 LanguageFilesDesc
1568 + '|*.lng|'
1569 + AllFilesDesc
1570 + '|*',
1571 '*.lng',
1572 Dir,
1573 Filename ) then
1574 exit;
1575
1576 LoadLanguage( Filename );
1577End;
1578
1579Procedure TMainForm.DebugSaveLanguageFileMIOnClick (Sender: TObject);
1580Var
1581 // LanguageFile: TLanguageFile;
1582 Dir: string;
1583 Filename: string;
1584Begin
1585 Dir := GetApplicationDir;
1586 if not DoSaveFileDialog( SaveLanguageTitle,
1587 LanguageFilesDesc
1588 + '|*.lng|'
1589 + AllFilesDesc
1590 + '|*',
1591 '*.lng',
1592 Dir,
1593 Filename ) then
1594 exit;
1595
1596 // get rid of mru menu items so they don't clutter the language file
1597 DestroyListObjects( MRUMenuItems );
1598 MRUMenuItems.Clear;
1599
1600 try
1601 // first touch all
1602 UpdateLanguage(g_CurrentLanguageFile);
1603 // then save
1604 g_CurrentLanguageFile.writeToFile(Filename);
1605 except
1606 on E: Exception do
1607 begin
1608 DoErrorDlg( SaveLanguageTitle,
1609 SaveLanguageError + E.Message );
1610 exit;
1611 end;
1612 end;
1613
1614 CreateMRUMenuItems;
1615End;
1616
1617Procedure TMainForm.SearchResultsListBoxOnClick (Sender: TObject);
1618Begin
1619 DisplaySelectedSearchResultTopic;
1620End;
1621
1622Procedure TMainForm.VSplitBarOnDblClick (Sender: TObject);
1623Begin
1624 ShowLeftPanel := not ShowLeftPanel;
1625End;
1626
1627Procedure TMainForm.DebugHelpManagerVersionMIOnClick (Sender: TObject);
1628Begin
1629 DoMessageDlg( HelpManagerVersionTitle,
1630 HelpManagerVersion );
1631End;
1632
1633Procedure TMainForm.DebugTopicByResourceIDMIOnClick (Sender: TObject);
1634var
1635 ResourceIDString: string;
1636 ResourceID: USHORT;
1637Begin
1638 if not DoInputQuery( FindResourceIDTitle,
1639 FindResourceIDPrompt,
1640 ResourceIDString ) then
1641 exit;
1642 try
1643 ResourceID := StrToInt( ResourceIDString );
1644 except
1645 DoErrorDlg( FindResourceIDTitle,
1646 InvalidResourceIDError );
1647 exit;
1648 end;
1649
1650 if not DisplayTopicByResourceID( ResourceID ) then
1651 DoErrorDlg( FindResourceIDTitle,
1652 ResourceIDNotFoundError );
1653End;
1654
1655Procedure TMainForm.ViewHighlightSearchWordsMIOnClick (Sender: TObject);
1656Begin
1657 ViewHighlightSearchWordsMI.Checked := not ViewHighlightSearchWordsMI.Checked;
1658 RefreshWindows( Windows );
1659End;
1660
1661Procedure TMainForm.FileNewWindowMIOnClick (Sender: TObject);
1662Begin
1663 Exec( GetApplicationFilename, '' );
1664End;
1665
1666Function TMainForm.OpenFilesFromTextList( const TextList: string;
1667 const DisplayFirstTopic: boolean ): boolean;
1668var
1669 tmpFileNames: TStringList;
1670begin
1671 tmpFileNames := TStringList.Create;
1672
1673 ParseAndExpandFileNames(TextList, tmpFileNames);
1674 if tmpFileNames.Count > 0 then
1675 begin
1676 result := OpenFiles(tmpFileNames, '', DisplayFirstTopic);
1677 end
1678 else
1679 begin
1680 CloseFile;
1681 end;
1682 tmpFileNames.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 writeDebugSetupDetailsTo(Lines);
2285 end;
2286
2287 InformationForm.ShowModal;
2288End;
2289
2290Procedure TMainForm.EditBookmarksMIOnClick (Sender: TObject);
2291Begin
2292 BookmarksForm.BookmarkList := Bookmarks;
2293 BookmarksForm.OpenBookmarkCallback := NavigateToBookmark;
2294 BookmarksForm.BookmarksChangedCallback := OnBookmarksChanged;
2295 BookmarksForm.Show;
2296
2297 // Since we are showing a nonmodal dialog, set the PM owner window
2298 // so that the bookmarks form remains on top.
2299 WinSetOwner( BookmarksForm.Frame.Handle,
2300 Frame.Handle );
2301End;
2302
2303Procedure TMainForm.CopyPMIOnClick (Sender: TObject);
2304var
2305 Window: THelpWindow;
2306Begin
2307 Window := GetActiveWindow;
2308 if Window = nil then
2309 exit;
2310 Window.View.CopySelectionToClipboard;
2311End;
2312
2313Procedure TMainForm.SelectAllPMIOnClick (Sender: TObject);
2314var
2315 Window: THelpWindow;
2316Begin
2317 Window := GetActiveWindow;
2318 if Window = nil then
2319 exit;
2320 Window.View.SelectAll;
2321End;
2322
2323Procedure TMainForm.AddNoteButtonOnClick (Sender: TObject);
2324Begin
2325 AddNote;
2326End;
2327
2328Procedure TMainForm.EnableSearchButton;
2329var
2330 CanSearch: boolean;
2331begin
2332 CanSearch := false;
2333 if CurrentOpenFiles.Count > 0 then
2334 if trim( SearchTextEdit.Text ) > '' then
2335 CanSearch := true;
2336 SearchButton.Enabled := CanSearch;
2337end;
2338
2339Procedure TMainForm.SearchTextEditOnChange (Sender: TObject);
2340Begin
2341 EnableSearchButton;
2342End;
2343
2344Procedure TMainForm.OnHint( Sender: TObject );
2345begin
2346 SetStatus( Application.Hint );
2347end;
2348
2349Procedure TMainForm.DisplaySelectedIndexTopic;
2350var
2351 Topic: TTopic;
2352Begin
2353 if IndexListBox.ItemIndex = -1 then
2354 exit;
2355 Topic := DisplayedIndex.Objects[ IndexListBox.ItemIndex ] as TTopic;
2356 DisplayTopic( Topic );
2357End;
2358
2359Procedure TMainForm.IndexListBoxOnClick (Sender: TObject);
2360Begin
2361 DisplaySelectedIndexTopic;
2362End;
2363
2364Procedure TMainForm.ViewCollapseAllMIOnClick (Sender: TObject);
2365Begin
2366 DisplayContents;
2367 ContentsOutline.CollapseAll;
2368 DisplaySelectedContentsTopic;
2369End;
2370
2371Procedure TMainForm.NotesListBoxOnDblClick (Sender: TObject);
2372Begin
2373 GotoCurrentNote;
2374End;
2375
2376function TMainForm.OwnHelpMode: boolean;
2377var
2378 Filename: string;
2379 NamePart: string;
2380begin
2381 result := false;
2382 if CurrentOpenFiles.Count <> 1 then
2383 exit;
2384
2385 Filename := THelpFile( CurrentOpenFiles[ 0 ] ).Filename;
2386 NamePart := ExtractFileName( Filename );
2387 Result := StrStartsWithIgnoringCase(NamePart, 'newview');
2388end;
2389
2390Procedure TMainForm.HelpMIOnClick (Sender: TObject);
2391Begin
2392 if OwnHelpMode then
2393 begin
2394 DoErrorDlg( NewViewHelpTitle,
2395 AlreadyNewviewHelp );
2396 exit;
2397 end;
2398 Application.HelpContents;
2399End;
2400
2401Procedure TMainForm.NotebookOnPageChanged (Sender: TObject);
2402var
2403 FileIndex: longint;
2404 HelpFile: THelpFile;
2405Begin
2406 EnableControls;
2407 case Notebook.PageIndex of
2408 piContents:
2409 begin
2410 // not really feasible to load contents here, as we rely
2411 // on it for many things
2412 ContentsOutline.Focus;
2413 end;
2414
2415 piIndex:
2416 begin
2417 if not IndexLoaded then
2418 begin
2419 LoadIndex;
2420 end;
2421 IndexSearchEdit.Focus;
2422 end;
2423
2424 piSearch:
2425 begin
2426 SearchButton.Focus;
2427 SearchTextEdit.Focus;
2428 end;
2429
2430 piNotes:
2431 begin
2432 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2433 begin
2434 HelpFile := CurrentOpenFiles[ FileIndex ];
2435 if not HelpFile.NotesLoaded then
2436 LoadNotes( HelpFile );
2437 end;
2438 NotesListBox.Focus;
2439 UpdateNotesDisplay;
2440 end;
2441 end;
2442
2443End;
2444
2445Procedure TMainForm.ViewRefreshMIOnClick (Sender: TObject);
2446Begin
2447 RefreshWindows( Windows );
2448End;
2449
2450Procedure TMainForm.ViewNotesMIOnClick (Sender: TObject);
2451Begin
2452 ShowLeftPanel := true;
2453 TabSet.TabIndex := piNotes;
2454End;
2455
2456Procedure TMainForm.ViewSearchMIOnClick (Sender: TObject);
2457Begin
2458 DisplaySearch;
2459End;
2460
2461Procedure TMainForm.ShowTab( TabIndex: longint );
2462Begin
2463 ShowLeftPanel := true;
2464 TabSet.TabIndex := TabIndex;
2465 NotebookOnPageChanged( self );// focus control etc
2466End;
2467
2468Procedure TMainForm.DisplaySearch;
2469Begin
2470 ShowTab( piSearch );
2471End;
2472
2473Procedure TMainForm.ViewIndexMIOnClick (Sender: TObject);
2474Begin
2475 DisplayIndex;
2476End;
2477
2478Procedure TMainForm.DisplayIndex;
2479Begin
2480 ShowTab( piIndex );
2481End;
2482
2483Procedure TMainForm.ViewContentsMIOnClick (Sender: TObject);
2484Begin
2485 DisplayContents;
2486End;
2487
2488Procedure TMainForm.DisplayContents;
2489Begin
2490 ShowTab( piContents );
2491End;
2492
2493function TMainForm.OpenWindow( Topic: TTopic;
2494 Group: longint;
2495 Parent: THelpWindow;
2496 Rect: THelpWindowRect;
2497 FollowAutoLinks: boolean ): THelpWindow;
2498var
2499 Window: THelpWindow;
2500 DisplayTopicRequired: boolean;
2501begin
2502 Window := nil;
2503
2504 if ( Group <> DefaultGroupIndex ) and ( Parent = nil ) then
2505 begin
2506 // Normal window (not a split window) and a specific group is desired.
2507 // So see if we can find one with that group number
2508 Window := FindWindowFromGroup( Group, Windows );
2509
2510 end
2511 else
2512 begin
2513 // only reuse window if it has the same topic.
2514 Window := FindWindowFromTopic( Topic, Windows );
2515 end;
2516
2517 if Window = nil then
2518 begin
2519 DisplayingTopicWindow := true;
2520
2521 // not found, or want a new one
2522 Window := THelpWindow.Create( Parent = nil );
2523
2524 // add to parent
2525 if Parent = nil then
2526 begin
2527 Window.Parent := DisplayPanel;
2528 Windows.Add( Window );
2529 end
2530 else
2531 begin
2532 Window.Parent := Parent.View;
2533 Parent.ChildWindows.Add( Window );
2534 end;
2535
2536 Window.ParentHelpWindow := Parent;
2537
2538 DisplayingTopicWindow := false;
2539
2540 end
2541 else
2542 begin
2543 // reusing an existing window. Don't change parent
2544 end;
2545
2546 Window.Group := Group;
2547
2548 Window.View.PopupMenu := ViewPopupMenu;
2549
2550 Window.View.Images := Window.Images;
2551
2552 Window.View.OnClickLink := OnClickLink;
2553 Window.View.OnOverLink := OnOverLink;
2554 Window.View.OnNotOverLink := OnNotOverLink;
2555
2556 Window.OnClose := OnWindowClose;
2557 Window.OnCloseQuery := OnWindowAboutToClose;
2558 Window.OnDragOver := OnDragOverWindow;
2559 Window.OnDragDrop := OnDragDropToWindow;
2560 Window.OnFontChange := OnWindowFontChange;
2561 Window.OnTab := OnWindowTab;
2562 Window.OnBackTab := OnWindowBackTab;
2563
2564 // Use the contents rect by default...
2565 Topic.GetContentsWindowRect( Window.Rect );
2566 if Rect <> nil then
2567 begin
2568 // the rect is being overridden, so use it instead
2569 if Rect.Left <> -1 then
2570 Window.Rect.Left := Rect.Left;
2571 if Rect.Bottom <> -1 then
2572 Window.Rect.Bottom := Rect.Bottom;
2573 if Rect.Width <> -1 then
2574 Window.Rect.Width := Rect.Width;
2575 if Rect.Height <> -1 then
2576 Window.Rect.Height := Rect.Height;
2577 end;
2578
2579 if Window.ChildWindows.Count > 0 then
2580 begin
2581 // close existing child windows
2582 DestroyListObjects( Window.ChildWindows );
2583 Window.ChildWindows.Clear;
2584 Window.View.Show; // show the view again
2585 end;
2586
2587 DisplayTopicRequired := Window.Topic <> Topic;
2588 Window.Topic := Topic; // set this now so that SetLayout can log meaninful stuff
2589
2590 // Adjust the window size to it's specified Rect
2591 // Must do this before displaying child windows (DisplayTopicInWindow,
2592 // split window autolinks),
2593 // otherwise they will not size themselves correctly
2594 Window.SetLayout;
2595
2596 if DisplayTopicRequired then
2597 begin
2598 DisplayTopicInWindow( Window, FollowAutoLinks, false );
2599 end;
2600
2601 // Bring this window to the front
2602 Window.BringToFront;
2603
2604 Result := Window;
2605end;
2606
2607// Find an existing help window containing the given richtext view control
2608Function TMainForm.FindWindowFromView( View: TRichTextView;
2609 WindowList: TList ): THelpWindow;
2610var
2611 WindowIndex: longint;
2612begin
2613 for WindowIndex:= 0 to WindowList.Count - 1 do
2614 begin
2615 Result:= WindowList[ WindowIndex ];
2616 if Result.View = View then
2617 exit;
2618 Result:= FindWindowFromView( View, Result.ChildWindows );
2619 if Result <> nil then
2620 exit;
2621 end;
2622 Result:= nil;
2623end;
2624
2625// Find an existing help window with the given group number (if any)
2626Function TMainForm.FindWindowFromGroup( Group: longint; WindowList: TList ): THelpWindow;
2627var
2628 WindowIndex: longint;
2629begin
2630 for WindowIndex:= 0 to WindowList.Count - 1 do
2631 begin
2632 Result:= WindowList[ WindowIndex ];
2633 if Result.Group = Group then
2634 exit;
2635 Result:= FindWindowFromGroup( Group, Result.ChildWindows );
2636 if Result <> nil then
2637 exit;
2638 end;
2639 Result:= nil;
2640end;
2641
2642// Find an existing help window alreadying displaying the given topic
2643Function TMainForm.FindWindowFromTopic( Topic: TTopic; WindowList: TList ): THelpWindow;
2644var
2645 WindowIndex: longint;
2646begin
2647 for WindowIndex:= 0 to WindowList.Count - 1 do
2648 begin
2649 Result:= WindowList[ WindowIndex ];
2650 if Result.Topic = Topic then
2651 exit;
2652 Result:= FindWindowFromTopic( Topic, Result.ChildWindows );
2653 if Result <> nil then
2654 exit;
2655 end;
2656 Result:= nil;
2657end;
2658
2659Procedure TMainForm.RefreshFontSubstitutions;
2660var
2661 FileIndex: longint;
2662 HelpFile: THelpFile;
2663begin
2664 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2665 begin
2666 HelpFile := CurrentOpenFiles[ FileIndex ];
2667
2668 if Settings.FixedFontSubstitution then
2669 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes )
2670 else
2671 HelpFile.SetupFontSubstitutes( '' );
2672 end;
2673end;
2674
2675// Redisplay topics in all windows
2676Procedure TMainForm.RefreshWindows( WindowList: TList );
2677var
2678 WindowIndex: longint;
2679 Window: THelpWindow;
2680begin
2681 for WindowIndex:= 0 to WindowList.Count - 1 do
2682 begin
2683 Window:= WindowList[ WindowIndex ];
2684 DisplayTopicInWindow( Window,
2685 false, // don't follow links!
2686 true ); // keep position
2687 RefreshWindows( Window.ChildWindows );
2688 end;
2689end;
2690
2691Procedure TMainForm.WMFollowExternalLink( Var Msg: TMessage );
2692var
2693 FilePath: string;
2694 Topic: TTopic;
2695begin
2696 // try in same dir as source file
2697 FilePath := AddDirectorySeparator( ExtractFilePath( g_ExternalLinkSourceFilename ) )
2698 + g_ExternalLinkFilename;
2699
2700 if not StrEqualIgnoringCase( FilePath, g_ExternalLinkSourceFilename ) then
2701 begin
2702 // different file - try and open it
2703 if not FileExists( FilePath ) then
2704 // not in same directory, find in help paths
2705 FilePath := FindHelpFile( g_ExternalLinkFilename );
2706
2707 if not FileExists( FilePath ) then
2708 begin
2709 DoErrorDlg( 'Link Error',
2710 'Cannot find linked file '
2711 + g_ExternalLinkFilename );
2712 exit;
2713 end;
2714
2715 if g_ExternalLinkKeepCurrent then
2716 begin
2717 if not OpenAdditionalFile( FilePath, false ) then
2718 exit;
2719 end
2720 else
2721 begin
2722 if not OpenFile( FilePath, '', false ) then
2723 exit;
2724 end;
2725
2726 end;
2727
2728 if g_ExternalLinkTopic = '' then
2729 begin
2730 // specific topic not required.
2731 DisplaySelectedContentsTopic;
2732 exit;
2733 end;
2734
2735 Topic := FindTopicByGlobalName( g_ExternalLinkTopic );
2736 if Topic = nil then
2737 begin
2738 DoErrorDlg( 'Link Error',
2739 'Unable to find topic with global name '
2740 + g_ExternalLinkTopic );
2741 exit;
2742 end;
2743
2744 DisplayTopic( Topic );
2745end;
2746
2747// We are following a link, specified as param1 in msg
2748Procedure TMainForm.WMFollowLink( Var Msg: TMessage );
2749var
2750 NewTopic: TTopic;
2751 Link: THelpLink;
2752 SourceWindow: THelpWindow;
2753begin
2754 Link:= THelpLink( Msg.Param1 );
2755 SourceWindow:= THelpWindow( Msg.Param2 );
2756 NewTopic:= FindTopicForLink( Link );
2757
2758 // remove the link target info from status
2759 SetStatus( '' );
2760
2761 if NewTopic = nil then
2762 begin
2763 // Linked topic not found, this is an error... which kind?
2764
2765 if Link is THelpLinkByResourceID then
2766 begin
2767 // may happen if e.g. PM4.INF is loaded by itself,
2768 // and a link references a resource ID from e.g PM2.INF
2769 DoErrorDlg( InvalidLinkErrorTitle,
2770 InvalidResourceIDLinkErrorA
2771 + IntToStr( THelpLinkByResourceID( Link ).ResourceID )
2772 + InvalidResourceIDLinkErrorB );
2773 end
2774 else
2775 begin
2776 // should never happen, given valid help files
2777 DoErrorDlg( InvalidLinkErrorTitle,
2778 InvalidLinkError );
2779 end;
2780
2781 exit;
2782 end;
2783
2784 UpdateCurrentNavigatePoint;
2785
2786 FollowLink( Link, SourceWindow );
2787
2788 if NewTopic.ShowInContents then
2789 begin
2790 Navigating:= true;
2791 if ContentsOutline.SelectedNode = nil then
2792 ContentsOutline.SetSelectedObject( NewTopic )
2793 else if ContentsOutline.SelectedNode.Data <> NewTopic then
2794 ContentsOutline.SetSelectedObject( NewTopic );
2795 Navigating:= false;
2796 end;
2797 SaveNavigatePoint;
2798 EnableControls;
2799 ShowWindows;
2800
2801end;
2802
2803// Follow the given link from the given window.
2804// ie. open the topic or footnote it points to
2805Procedure TMainForm.FollowLink( Link: THelpLink;
2806 SourceWindow: THelpWindow );
2807var
2808 LinkedTopic: TTopic;
2809 ParentWindow: THelpWindow;
2810 WindowedLink: TWindowedHelpLink;
2811 NewWindow: THelpWIndow;
2812begin
2813 LinkedTopic := FindTopicForLink( Link );
2814
2815 if LinkedTopic = nil then
2816 begin
2817 exit;
2818 end;
2819
2820 if Link is TFootnoteHelpLink then
2821 begin
2822 NewWindow := OpenWindow( LinkedTopic,
2823 DefaultGroupIndex,
2824 nil, // no parent
2825 FootnoteRect,
2826 true );
2827 NewWindow.Caption := TFootnoteHelpLink( Link ).Title;
2828 exit;
2829 end;
2830
2831 WindowedLink := Link as TWindowedHelpLink;
2832
2833 ParentWindow:= nil;
2834 if WindowedLink.Split then
2835 ParentWindow:= SourceWindow;
2836
2837 if WindowedLink.ViewPort then
2838 // link always wants a new window
2839 OpenWindow( LinkedTopic,
2840 DefaultGroupIndex,
2841 ParentWindow,
2842 WindowedLink.Rect,
2843 true )
2844
2845 else if WindowedLink.GroupIndex <> DefaultGroupIndex then
2846 // link overrides group index
2847 OpenWindow( LinkedTopic,
2848 WindowedLink.GroupIndex,
2849 ParentWindow,
2850 WindowedLink.Rect,
2851 true )
2852 else
2853 // no special case
2854 OpenWindow( LinkedTopic,
2855 LinkedTopic.ContentsGroupIndex,
2856 ParentWindow,
2857 WindowedLink.Rect,
2858 true );
2859end;
2860
2861function TMainForm.ShowCodes: boolean;
2862begin
2863 if DebugShowCodesMI = nil then
2864 result := false
2865 else
2866 result := DebugShowCodesMI.Checked;
2867end;
2868
2869function TMainForm.ShowWordIndices: boolean;
2870begin
2871 if DebugShowWordSeparatorsMI = nil then
2872 result := false
2873 else
2874 result := DebugShowWordSeparatorsMI.Checked;
2875end;
2876
2877// Decode and display the topic for the given window.
2878Procedure TMainForm.DisplayTopicInWindow( Window: THelpWindow;
2879 FollowAutoLinks: boolean;
2880 KeepPosition: boolean );
2881var
2882 ImageIndices: TList;
2883 LinkIndex: longint;
2884 Link: THelpLink;
2885 WindowedHelpLink: TWindowedHelpLink;
2886 InternalHelpLink: TInternalHelpLink;
2887 HelpFile: THelpFile;
2888 LinkedTopic: TTopic;
2889 SourceTopic: TTopic;
2890 TopCharIndex: longint;
2891 i: longint;
2892 HighlightWordSequences: TList;
2893 FileIndex: longint;
2894Begin
2895 LogEvent(LogDisplay, 'DisplayTopicInWindow');
2896
2897 SetWaitCursor;
2898
2899 TopCharIndex := Window.View.TopCharIndex;
2900
2901 Window.View.Hide;
2902 Window.View.Clear;
2903 ImageIndices := TList.Create;
2904
2905 HelpFile := TopicFile( Window.Topic );
2906
2907 if ( AllFilesWordSequences.Count > 0 ) // ie we have done a search...
2908 and ViewHighlightSearchWordsMI.Checked then
2909 begin
2910 FileIndex := CurrentOpenFiles.IndexOf( HelpFile );
2911 HighlightWordSequences := AllFilesWordSequences[ FileIndex ];
2912 end
2913 else
2914 begin
2915 HighlightWordSequences := nil;
2916 end;
2917 TopicText.Clear;
2918 Window.Topic.GetText( HighlightWordSequences,
2919 ShowCodes,
2920 ShowWordIndices,
2921 TopicText,
2922 ImageIndices,
2923 Window.Highlights );
2924
2925 HelpFile.GetImages( ImageIndices, Window.Images );
2926
2927 if not HelpFile.NotesLoaded then
2928 LoadNotes( HelpFile );
2929 InsertNotesIntoTopicText( Window.Topic, TopicText );
2930
2931 Window.View.AddText( TopicText.AsPChar );
2932
2933 if KeepPosition then
2934 Window.View.TopCharIndex := TopCharIndex;
2935
2936 Window.View.Show;
2937
2938 if not KeepPosition then
2939 if Window.Highlights.Count > 0 then
2940 // ensure first search match is visible
2941 Window.View.MakeCharVisible( longint( Window.Highlights[ 0 ] ) );
2942
2943 Window.Caption := Window.Topic.Title;
2944 Window.BringToFront;
2945 Window.View.Focus;
2946
2947 // Take a copy of the topic, because the window in question could be changing
2948 // due to recursion!
2949 SourceTopic := Window.Topic;
2950
2951 if FollowAutoLinks then
2952 begin
2953 i := 0;
2954 for LinkIndex:= 0 to SourceTopic.Links.Count - 1 do
2955 begin
2956 Link:= SourceTopic.Links[ LinkIndex ];
2957 if Link is TWindowedHelpLink then
2958 begin
2959 WindowedHelpLink := Link as TWindowedHelpLink;
2960 if WindowedHelpLink.Automatic then
2961 begin
2962 if Link is TInternalHelpLink then
2963 begin
2964 InternalHelpLink := TInternalHelpLink( Link );
2965 LinkedTopic :=
2966 THelpFile( InternalHelpLink.HelpFile ).
2967 Topics[ InternalHelpLink.TopicIndex ];
2968 if LinkedTopic.Index = SourceTopic.Index then
2969 // what the - ? The link wants to open the same topic again
2970 continue;
2971 end;
2972
2973 FollowLink( Link, Window );
2974 Window := Window;
2975
2976 inc( i );
2977 // Note 1: it is possible to crash here if
2978 // e.g. window1 auto-opens window2 which auto-opens window1 with a different topic..
2979 // I can't think of a nice, easy way to detect this
2980 //
2981 // Note 2: If there is no group number specified
2982 // (ie. group = default = 0 ) then behaves as if viewport is set:
2983 // always opens another window.
2984 end;
2985 end;
2986 end;
2987 end;
2988
2989 ClearWaitCursor;
2990
2991 ImageIndices.Destroy;
2992End;
2993
2994Procedure TMainForm.MainFormOnCloseQuery (Sender: TObject;
2995 Var CanClose: Boolean);
2996Begin
2997 LogEvent(LogShutdown, '-------- Shutdown ----------');
2998
2999
3000 if OKToCloseFile then
3001 CloseFile
3002 else
3003 CanClose := false;
3004End;
3005
3006procedure TMainForm.DisplayTopic( Topic: TTopic );
3007begin
3008 if Navigating then
3009 exit;
3010
3011 UpdateCurrentNavigatePoint;
3012
3013 CloseWindows;
3014
3015 CurrentTopic:= Topic;
3016
3017 OpenWindow( CurrentTopic,
3018 CurrentTopic.ContentsGroupIndex,
3019 nil,
3020 nil,
3021 true );
3022 SetStatus( OpenedTopicMsg + 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: ' + IntToStr( CurrentTopic.Index ) );
3730 except
3731 // ignore exceptions if there isn't a valid current topic
3732 end;
3733 if Windows <> nil then
3734 begin
3735 WriteLn( F, 'Top-level open windows: '
3736 + IntToStr( Windows.Count ) );
3737 end;
3738
3739 System.Close( F );
3740
3741 TheText := ApplicationErrorA + StrCRLF
3742 + StrCRLF
3743 + E.Message + StrCRLF
3744 + ApplicationErrorB
3745 + LogFilename
3746 + ')' + StrCRLF
3747 + StrCRLF
3748 + ApplicationErrorC
3749 + StrCRLF;
3750
3751 if DoYesNoDlg( ApplicationErrorTitle,
3752 TheText ) then
3753 begin
3754 // exit a bit more nicely - remove ourselves from the global filelist.
3755 GlobalFilelist.RemoveWindowFiles( Frame.Handle );
3756 Application.Terminate;
3757 end;
3758end;
3759
3760// give our main window a unique class name we can find
3761procedure TMainForm.GetClassData(var ClassData: TClassData);
3762Begin
3763 inherited GetClassData( ClassData );
3764 ClassData.ClassName := MAIN_WINDOW_CLASS_NAME;
3765End;
3766
3767// Position the window offset from existing top help window (if any)
3768Procedure TMainForm.PositionWindow;
3769var
3770 hTopWindow: HWND;
3771 TopHelpWindowPos: SWP;
3772 Offset: longint;
3773Begin
3774 hTopWindow := FindTopFormWindow( MAIN_WINDOW_CLASS_NAME );
3775
3776 if hTopWindow <> NULLHANDLE then
3777 begin
3778 // found an existing help window, find it's location
3779 if WinQueryWindowPos(
3780 hTopWindow,
3781 TopHelpWindowPos ) then
3782 begin
3783 if ( TopHelpWindowPos.FL and ( SWP_MINIMIZE or SWP_MINIMIZE ) ) > 0 then
3784 Begin
3785 // window is maximized or minimised, so get the restore position from window USHORTs
3786 TopHelpWindowPos.x := WinQueryWindowUShort( hTopWindow, QWS_XRESTORE );
3787 TopHelpWindowPos.Y := WinQueryWindowUShort( hTopWindow, QWS_YRESTORE );
3788 end;
3789
3790 // offset new window by height of title bar + border
3791 Offset := Screen.SystemMetrics( smCyTitleBar )
3792 + Screen.SystemMetrics( smCySizeBorder );
3793 Left := TopHelpWindowPos.x + Offset;
3794 Bottom := TopHelpWindowPos.y - Offset;
3795
3796 // I guess I am leaving width/height out for compatibility...?
3797 end;
3798 end;
3799end;
3800
3801Procedure TMainForm.OnHelp( context: THelpContext;
3802 var Result: Boolean );
3803begin
3804 if OwnHelpMode then
3805 begin
3806 // we are viewing the help file now - display our own help!
3807 PostMsg( Handle, NHM_TOPIC_BY_RESOURCE_ID, context, 0 );
3808 exit;
3809 end;
3810
3811 Application.HelpContext( context );
3812end;
3813
3814Procedure TMainForm.MainFormOnCreate (Sender: TObject);
3815var
3816 tmpCmdLine: AnsiString;
3817Begin
3818 LogEvent(LogStartup, 'MainFormOnCreate');
3819
3820 StartingUp := true;
3821
3822 SharedMemory := AccessSharedMemory;
3823 GlobalFilelist := TGlobalFilelist.Create;
3824
3825 // parse parameters into Parameters object
3826 tmpCmdLine := nativeOS2GetCmdLineParameter;
3827 CmdLineParameters := TCmdLineParameters.Create;
3828 CmdLineParameters.parseCmdLine(tmpCmdLine);
3829
3830 Application.HelpFile := CmdLineParameters.GetOwnHelpFilename; // OWN_HELP_MARKER;
3831 Application.OnHelp := OnHelp;
3832
3833 RegisterEventForLanguages( OnLanguageEvent );
3834
3835 // if debug is not enabled, get rid of the debug menu and separator.
3836 if not CmdLineParameters.isDebugEnabled then
3837 begin
3838 ToolsDebugSep.Destroy;
3839 ToolsDebugMenu.Destroy;
3840 DebugShowCodesMI := nil;
3841 DebugShowWordSeparatorsMI := nil;
3842 end;
3843
3844 // set up globals for Exec
3845 ExecViaSession := true;
3846 AsynchExec := true;
3847
3848 // set up form icons
3849 Forms.FormIconResourceID := 1;
3850
3851 Application.OnException := OnException;
3852
3853 ContentsOutline.SmoothScroll := false;
3854
3855 LogEvent(LogStartup, 'Choosing default font: Trying WarpSans');
3856
3857 Font := GetNiceDefaultFont;
3858
3859 // Set the menu fonts, because they remember their own specific one
3860 MainMenu.Font := Screen.MenuFont;
3861 ViewPopupMenu.Font := Screen.MenuFont;
3862
3863 // NOTE: SPCC will copy this font to TApplication
3864 // in TApplication.Run
3865
3866 LogEvent(LogStartup, 'Starting NewView: MainFormOnCreate');
3867
3868 Application.OnHint := OnHint;
3869
3870 StartMem := MemAvailBytes;
3871
3872 DisplayedIndex := TStringList.Create;
3873
3874 HelpManagerWindows := TList.Create;
3875
3876 AllFilesWordSequences := TList.Create;
3877
3878 CurrentOpenFiles := TList.Create;
3879 Notes := TList.Create;
3880 Bookmarks := TList.Create;
3881 BookmarksMenuItems := TList.Create;
3882 Windows := TList.Create;
3883
3884 TopicText := TAString.Create;
3885
3886 Navigating := false;
3887 InIndexSearch := false;
3888 SettingFont := false;
3889
3890 PageHistory := TStringList.Create;
3891 CurrentHistoryIndex := -1;
3892
3893 Settings.MRUList := TList.Create;
3894
3895 MRUMenuItems := TList.Create;
3896 NavigateToMenuItems := TList.Create;
3897
3898 LogEvent(LogSettings, 'Loading settings');
3899
3900 LoadSettings;
3901 SetShowLeftPanel( ShowLeftPanel ); // update menu
3902
3903 // load default strings
3904 LogEvent(LogSettings, 'Loading language');
3905
3906 // the user likes to have english
3907 // the normal automatic will fall back to
3908 // the environment setting but in the special
3909 // case we have to start the default
3910 if CmdLineParameters.getLanguage = 'en' then
3911 begin
3912 LoadLanguage('');
3913 end
3914 else
3915 begin
3916 if CmdLineParameters.getLanguage <> '' then
3917 begin
3918 if not LoadLanguageForSpec('newview', CmdLineParameters.getLanguage) then
3919 begin
3920 LoadDefaultLanguage('newview');
3921 end
3922 end
3923 else
3924 begin
3925 LoadDefaultLanguage('newview');
3926 end;
3927 end;
3928
3929 LogEvent(LogSettings, 'Applying settings');
3930 ApplySettings;
3931
3932 // default position is centered..
3933 LogEvent(LogSettings, 'Set default position');
3934 if Width > Screen.Width then
3935 Width := Screen.Width;
3936 if Height > Screen.Height then
3937 Height := Screen.Height;
3938 Left := ( Screen.Width - Width ) div 2;
3939 Bottom := ( Screen.Height - Height ) div 2;
3940
3941 LogEvent(LogSettings, 'ReadWindowPos');
3942 ReadWindowPos( Self );
3943
3944 PositionWindow;
3945
3946 LogEvent(LogSettings, 'Creating MRU list');
3947
3948 CreateMRUMenuItems;
3949
3950 CloseFile;
3951
3952 LogEvent(LogStartup, 'OnCreate done');
3953
3954 if CmdLineParameters.getWindowPositionFlag then
3955 begin
3956 SmartSetWindowPos( self,
3957 CmdLineParameters.getWindowPosition.Left,
3958 CmdLineParameters.getWindowPosition.Bottom,
3959 CmdLineParameters.getWindowPosition.Width,
3960 CmdLineParameters.getWindowPosition.Height,
3961 false );
3962 end;
3963
3964 LogEvent(LogStartup, 'MainFormOnCreate Done');
3965End;
3966
3967Procedure TMainForm.ApplySettings;
3968var
3969 ToolbarBitmap: TBitmap;
3970begin
3971 ContentsOutline.Color:= Settings.Colors[ ContentsBackgroundColorIndex ];
3972 ContentsOutline.PenColor:= Settings.Colors[ ContentsTextColorIndex ];
3973 ContentsOutline.TreeLineColor:= Settings.Colors[ ContentsLinesColorIndex ];
3974 IndexListBox.Color:= Settings.Colors[ IndexBackgroundColorIndex ];
3975 IndexListBox.PenColor:= Settings.Colors[ IndexTextColorIndex ];
3976 SearchResultsListBox.Color:= Settings.Colors[ SearchBackgroundColorIndex ];
3977 SearchResultsListBox.PenColor:= Settings.Colors[ SearchTextColorIndex ];
3978 NotesListBox.Color:= Settings.Colors[ NotesListBackgroundColorIndex ];
3979 NotesListBox.PenColor:= Settings.Colors[ NotesListTextColorIndex ];
3980
3981 SettingFont := true;
3982 Notebook.ParentFont := true;
3983 ContentsOutline.ParentFont := true;
3984 IndexListBox.ParentFont := true;
3985 SearchResultsListBox.ParentFont := true;
3986 NotesListBox.ParentFont := true;
3987 TabSet.ParentFont := true;
3988 Coolbar.ParentFont := true;
3989 if Settings.Fonts[ ApplicationFontIndex ] <> nil then
3990 Font := Settings.Fonts[ ApplicationFontIndex ]
3991 else
3992 Font := GetNiceDefaultFont;
3993 SettingFont := false;
3994
3995 Coolbar.BackgroundBitmap := nil;
3996 if FileExists( Settings.ToolbarBackgroundImageFilename ) then
3997 begin
3998 ToolbarBitmap:= TBitmap.Create;
3999 try
4000 ToolbarBitmap.LoadFromFIle( Settings.ToolbarBackgroundImageFilename );
4001 Coolbar.BackgroundBitmap := ToolbarBitmap;
4002 except
4003 end;
4004 ToolbarBitmap.Destroy;
4005 end;
4006
4007 CoolBar.ShowImages := Settings.ToolbarStyle in [ tsImages, tsImagesAndText ];
4008 CoolBar.ShowText := Settings.ToolbarStyle in [ tsText, tsImagesAndText ];
4009
4010 CoolBar.SetMinConstButtonWidth;
4011
4012 DisplayPanel.Color := Settings.Colors[ TopicBackgroundColorIndex ];
4013
4014 SetupViews( Windows );
4015end;
4016
4017// Setup the rich text views in the specified windows (e.g for changing global settings)
4018Procedure TMainForm.SetupViews( WindowList: TList );
4019var
4020 WindowIndex: longint;
4021 Window: THelpWindow;
4022begin
4023 for WindowIndex := 0 to WindowList.Count - 1 do
4024 begin
4025 Window := WindowList[ WindowIndex ];
4026 Window.SetupRTView;
4027 SetupViews( Window.ChildWindows );
4028 end;
4029end;
4030
4031Procedure TMainForm.PostHelpManagerMessage( MessageType: ULONG;
4032 Param1: long;
4033 Param2: long );
4034var
4035 i: longint;
4036begin
4037 for i := 0 to HelpManagerWindows.Count - 1 do
4038 PostMsg( HWND( HelpManagerWindows[ i ] ),
4039 MessageType,
4040 Param1,
4041 Param2 );
4042end;
4043
4044Procedure TMainForm.ClearHelpManager;
4045Begin
4046 if not CmdLineParameters.getHelpManagerFlag then
4047 exit;
4048
4049 // tell the help manager(s) we are no longer playing with them
4050 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
4051
4052 CmdLineParameters.setHelpManagerFlag(false);
4053
4054 HelpManagerWindows.Clear;
4055End;
4056
4057Procedure TMainForm.MainFormOnShow (Sender: TObject);
4058Begin
4059 EnableCallstackLogging( true );
4060
4061 LogEvent(LogStartup, 'MainFormOnShow');
4062
4063 if CmdLineParameters.getOwnerWindow <> NULLHANDLE then
4064 begin
4065 LogEvent(LogStartup, 'Setting owner: ' + IntToStr( CmdLineParameters.getOwnerWindow));
4066 WinSetOwner( Frame.Handle, CmdLineParameters.getOwnerWindow );
4067 end;
4068
4069 if CmdLineParameters.getHelpManagerFlag then
4070 begin
4071 LogEvent(LogStartup, ' Help Manager Title: '
4072 + StrPasWithLength( pSharedStruct ^. Title,
4073 SHARED_STRUCT_TITLE_SIZE ) );
4074 HelpManagerVersion := StrPasWithLength( pSharedStruct ^. Version,
4075 SHARED_STRUCT_VERSION_SIZE );
4076 LogEvent(LogStartup, ' Help Manager Version: ' + HelpManagerVersion );
4077
4078 end;
4079
4080 CoolBar.SetMinConstButtonWidth;
4081
4082 ResetProgress;
4083
4084 AddShortcut( kbF11, kbF11 ); // prev in contents
4085 AddShortcut( kbF12, kbF12 ); // next in contents
4086 AddShortcut( kbF7, kbF7 ); // back
4087 AddShortcut( kbF8, kbF8 ); // forward
4088 AddShortcut( kbCtrlCLeft, kbCtrlCLeft ); // back
4089
4090 LogEvent(LogStartup, 'Post WM_OPENED');
4091 PostMsg( Handle, WM_OPENED, 0, 0 );
4092End;
4093
4094Procedure TMainForm.DisplaySelectedContentsTopic;
4095var
4096 Topic: TTopic;
4097Begin
4098 if ContentsOutline.SelectedNode = nil then
4099 exit;
4100 Topic := ContentsOutline.SelectedNode.Data as TTopic;
4101 DisplayTopic( Topic );
4102End;
4103
4104// Check that the HELP and BOOKSHELF environment variables
4105// are defined (as they should be on any working OS/2 system).
4106// Show a warning message if not.
4107Procedure TMainForm.CheckEnvironmentVars;
4108var
4109 HelpOK: boolean;
4110 BookshelfOK: boolean;
4111 ErrorText: string;
4112begin
4113 HelpOK := GetEnv( HelpPathEnvironmentVar ) <> '';
4114 BookshelfOK := GetEnv( BookshelfEnvironmentVar ) <> '';
4115 if HelpOK and BookshelfOK then
4116 // all ok.
4117 exit;
4118
4119 // One or both missing
4120
4121 ErrorText := '';
4122 if not BookshelfOK then
4123 ErrorText := ErrorText
4124 + EnvironmentVarUndefined
4125 + BookshelfEnvironmentVar
4126 + StrCRLF;
4127
4128 if not HelpOK then
4129 ErrorText := ErrorText
4130 + EnvironmentVarUndefined
4131 + HelpPathEnvironmentVar
4132 + StrCRLF;
4133
4134 DoWarningDlg( EnvironmentVarErrorTitle,
4135 EnvironmentVarError
4136 + StrCRLF
4137 + StrCRLF
4138 + ErrorText );
4139
4140end;
4141
4142Procedure LoadSupportDLL;
4143begin
4144 try
4145 LoadDLLFunction( 'newview.dll',
4146 'LZWDECOMPRESSBLOCK',
4147 hNewViewDLL,
4148 pointer( LZWDecompressBlock ) );
4149 except
4150 on E: Exception do
4151 begin
4152 DoErrorDlg( 'DLL Error',
4153 E.Message );
4154 LZWDecompressBlock := nil;
4155 end;
4156 end;
4157end;
4158
4159Procedure TMainForm.WMOpened( Var Msg: TMessage );
4160var
4161 Filenames: TStringList;
4162 M1: longword;
4163 OpenFirstTopic: boolean;
4164 tmpFileNames : AnsiString;
4165begin
4166 if Application.HelpFile = '' then
4167 DoErrorDlg( 'NewView Help', 'NewView help file not found' );
4168
4169 LoadSupportDLL;
4170
4171 LogEvent(LogStartup, 'WMOpened: SetLayout');
4172
4173 // direct access the field to suppress updates done by the setter
4174 if CmdLineParameters.getHelpManagerFlag then
4175 FShowLeftPanel := Settings.ShowLeftPanel_Help
4176 else
4177 FShowLeftPanel := Settings.ShowLeftPanel_Standalone;
4178
4179 SetLayout;
4180
4181// ProfileEvent( 'Apply settings' );
4182// ApplySettings;
4183
4184 LogEvent(LogStartup, 'Enable controls');
4185 EnableControls;
4186
4187// ProfileEvent( 'ReadWindowPos' );
4188// ReadWindowPos( Self );
4189
4190 LogEvent(LogStartup, 'Finish paint');
4191 Update;
4192 LogEvent(LogStartup, 'BringToFront');
4193 MainForm.BringToFront;
4194
4195 if not CmdLineParameters.getHelpManagerFlag then
4196 begin
4197 LogEvent(LogStartup, 'Check environment vars');
4198 CheckEnvironmentVars;
4199
4200 if CmdLineParameters.getShowUsageFlag then
4201 begin
4202 LogEvent(LogStartup, 'Showing usage');
4203 ShowUsage;
4204 end;
4205 end;
4206
4207 HelpManagerWindows.Add( pointer( CmdLineParameters.getHelpManagerWindow ) );
4208
4209 if CmdLineParameters.getShowIndexFlag then
4210 begin
4211 DisplayIndex;
4212 end;
4213
4214 tmpFileNames := CmdLineParameters.getFileNames(Settings.StartupHelp);
4215 if tmpFileNames <> '' then
4216 begin
4217 // open specified files
4218 Filenames := TStringList.Create;
4219
4220 ParseAndExpandFileNames(tmpFileNames, Filenames);
4221 LogEvent(LogStartup, 'Call OpenFiles');
4222
4223 OpenFirstTopic := true;
4224
4225 if ( CmdLineParameters.getSearchText <> '' )
4226 OR CmdLineParameters.getSearchFlag
4227 OR CmdLineParameters.getHelpManagerFlag
4228 then
4229 // if we're going to search, don't open first topic
4230 // don't open first topic if we're online help
4231 // in case we are wanting to show a specific topic
4232 // - saves time/flicker
4233 OpenFirstTopic := false;
4234
4235 OpenFiles( Filenames,
4236 CmdLineParameters.getWindowTitle,
4237 OpenFirstTopic );
4238
4239 Filenames.Destroy;
4240
4241 if not CmdLineParameters.getSearchFlag
4242 and not CmdLineParameters.getGlobalSearchFlag
4243 and (CmdLineParameters.getSearchText <> '') then
4244 begin
4245 // search in contents only!
4246 LogEvent(LogStartup, 'Do startup topic search for: "' + CmdLineParameters.getSearchText + '"');
4247
4248 StartupTopicSearch( CmdLineParameters.getSearchText );
4249 end
4250 else if CmdLineParameters.getSearchFlag then
4251 begin
4252 // search in specified files
4253 LogEvent(LogStartup, 'Do search for topic');
4254 DisplaySearch;
4255
4256 SearchFor( CmdLineParameters.getSearchText );
4257 end;
4258 end;
4259
4260 if NOT CmdLineParameters.getShowUsageFlag
4261 AND CmdLineParameters.getGlobalSearchFlag then
4262 begin
4263 // Global search
4264 LogEvent(LogStartup, 'Do global search: ' + CmdLineParameters.getSearchText);
4265 DoGlobalSearch( CmdLineParameters.getSearchText );
4266 end;
4267
4268 LogEvent(LogStartup, 'Open finished');
4269
4270 if CmdLineParameters.getHelpManagerFlag then
4271 begin
4272 // Tell helpmanager(s) our window handle
4273 PostHelpManagerMessage( NHM_VIEWER_READY,
4274 Handle,
4275 0 );
4276 end;
4277
4278 M1:= MemAvail;
4279
4280 StartingUp := false;
4281
4282 LogEvent(LogStartup, 'RUN PROGRAM');
4283end;
4284
4285
4286Procedure TMainForm.MainFormOnResize (Sender: TObject);
4287Begin
4288 if not Visible then
4289 exit;
4290 if Handle = 0 then
4291 exit;
4292
4293 SetLayout;
4294
4295End;
4296
4297Function TMainForm.GetShowLeftPanel: boolean;
4298begin
4299 Result := FShowLeftPanel;
4300end;
4301
4302Procedure TMainForm.SetShowLeftPanel( Value: boolean );
4303begin
4304 ShowLeftPanelMI.Checked := Value;
4305 if Value = FShowLeftPanel then
4306 exit;
4307 FShowLeftPanel := Value;
4308 if FShowLeftPanel then
4309 NotebookOnPageChanged( self ) // make sure page is updated
4310 else
4311 FocusFirstHelpWindow;
4312 EnableControls;
4313 SetLayout;
4314end;
4315
4316Procedure TMainForm.VSplitBarOnChange (NewSplit: LongInt);
4317Begin
4318 if VSplitBar.Left < 30 then
4319 begin
4320 ShowLeftPanel := false
4321 end
4322 else
4323 begin
4324 Settings.LeftPanelWidth := VSplitBar.Left;
4325 ShowLeftPanel := true;
4326 end;
4327 SetLayout;
4328End;
4329
4330// Set the layout of the main form
4331Procedure TMainForm.SetLayout;
4332var
4333 RealClientHeight : longint;
4334 CoolbarSpace: longint;
4335 TextHeight: longint;
4336Begin
4337 TextHeight := Canvas.TextHeight( 'S' );
4338 Tabset.Height := TextHeight + 5;
4339
4340 Coolbar.Visible := Settings.ToolbarStyle <> tsNone;
4341
4342 case Settings.ToolbarStyle of
4343 tsImages:
4344 Coolbar.Height := Coolbar.Sections[ 0 ].Width;
4345 tsText:
4346 Coolbar.Height := TextHeight + 5;
4347 tsImagesAndText:
4348 CoolBar.Height := ButtonImages.GetBitmapReference(0).Width + TextHeight + 10;
4349 end;
4350
4351 CoolbarSpace := Coolbar.Height;
4352 if not Coolbar.Visible then
4353 CoolbarSpace := 0;
4354
4355 StatusPanel.Left:= 0;
4356 StatusPanel.Width:= ClientWidth div 2 - 2;
4357 StatusPanel.Height := TextHeight + 2;
4358
4359 ProgressPanel.Left:= ClientWidth div 2 + 2;
4360 ProgressPanel.Width:= ClientWidth - ProgressPanel.Left;
4361 ProgressPanel.Height := TextHeight + 2;
4362
4363 Notebook.Bottom := StatusPanel.Height + 3;
4364 VSplitBar.Bottom := Notebook.Bottom;
4365 DisplayPanel.Bottom := Notebook.Bottom;
4366
4367 RealClientHeight := ClientHeight
4368 - CoolbarSpace
4369 - Notebook.Bottom;
4370
4371 LogEvent(LogStartup, 'TMainForm.SetLayout');
4372 LogEvent(LogStartup, ' RealClientHeight: ' + IntToStr( RealClientHeight ));
4373
4374 LogEvent(LogStartup, ' Form Width: ' + IntToStr( Width ));
4375 LogEvent(LogStartup, ' Form Height: ' + IntToStr( Height ) );
4376 LogEvent(LogStartup, ' Form ClientWidth: ' + IntToStr( ClientWidth ) );
4377 LogEvent(LogStartup, ' Form ClientHeight: ' + IntToStr( ClientHeight ) );
4378 LogEvent(LogStartup, ' CoolBar.Height: ' + IntToStr( CoolBar.Height ) );
4379 LogEvent(LogStartup, ' CoolBar.Bottom: ' + IntToStr( CoolBar.Bottom ) );
4380
4381 if CurrentOpenFiles.Count > 0 then
4382 VSplitBar.Width := Max( 5, Canvas.TextWidth( ' ' ) )
4383 else
4384 VSplitBar.Width := 0;
4385
4386 VSplitBar.Height := RealClientHeight;
4387
4388 if Settings.LeftPanelWidth > ClientWidth - 50 then
4389 Settings.LeftPanelWidth := ClientWidth - 50;
4390 if Settings.LeftPanelWidth < 50 then
4391 Settings.LeftPanelWidth := 50;
4392
4393 if ShowLeftPanel then
4394 begin
4395 VSplitBar.Left := Settings.LeftPanelWidth;
4396 VSplitBar.Hint := SplitBarDblClickToHide;
4397 end
4398 else
4399 begin
4400 VSplitBar.Left := 0;
4401 VSplitBar.Hint := SplitBarDblClickToShow;
4402 end;
4403
4404 Tabset.Left := 0;
4405 Tabset.Width := VSplitBar.Left;
4406 Tabset.Bottom := ClientHeight
4407 - CoolbarSpace
4408 - Tabset.Height;
4409
4410 Notebook.Left := 0;
4411 Notebook.Width := VSplitBar.Left;
4412 Notebook.Height := RealClientHeight
4413 - Tabset.Height
4414 - 3;
4415
4416 DisplayPanel.Left:= VSplitBar.Left + VSplitBar.Width;
4417 DisplayPanel.Width:= ClientWidth - DisplayPanel.Left;
4418 DisplayPanel.Height := RealClientHeight;
4419 LogEvent(LogStartup, ' DisplayPanel.Width: ' + IntToStr( DisplayPanel.Width ) );
4420 LogEvent(LogStartup, ' DisplayPanel.Height: ' + IntToStr( DisplayPanel.Height ) );
4421 LogEvent(LogStartup, ' DisplayPanel.Bottom: ' + IntToStr( DisplayPanel.Bottom ) );
4422
4423 ProgressBar.Left:= 1;
4424 ProgressBar.Bottom:= 1;
4425 ProgressBar.Width:= ProgressPanel.Width - 2;
4426 ProgressBar.Height:= ProgressPanel.Height - 2;
4427
4428 // Layout the visible help windows also
4429 LayoutWindowList( Windows );
4430End;
4431
4432// Lay out the specified list of help windows
4433Procedure TMainForm.LayoutWindowList( WindowList: TList );
4434var
4435 Window: THelpWindow;
4436 WindowIndex: longint;
4437begin
4438 for WindowIndex:= 0 to WindowList.Count - 1 do
4439 begin
4440 Window:= WindowList[ WindowIndex ];
4441 Window.SetLayout;
4442 end;
4443end;
4444
4445Procedure TMainForm.FindNextMIOnClick (Sender: TObject);
4446begin
4447 if FindText = '' then
4448 begin
4449 FindMIOnClick( sender );
4450 exit;
4451 end;
4452
4453 if GetActiveWindow = nil then
4454 begin
4455 DoErrorDlg( FindTitle,
4456 FindSelectWindowError );
4457 exit;
4458 end;
4459
4460 DoFind( foFromCurrent );
4461end;
4462
4463Procedure TMainForm.DoFind( FindOrigin: TFindOrigin );
4464var
4465 Window: THelpWindow;
4466begin
4467 SetWaitCursor;
4468 Window := GetActiveWindow;
4469 if not Window.View.Find( FindOrigin, FindText ) then
4470 begin
4471 SetStatus( TextNotFoundMsg );
4472 Beep( 1000, 100 );
4473 end;
4474 ClearWaitCursor;
4475End;
4476
4477Procedure TMainForm.FindMIOnClick (Sender: TObject);
4478begin
4479 if GetActiveWindow = nil then
4480 begin
4481 DoErrorDlg( FindTitle,
4482 FindSelectWindowError );
4483 exit;
4484 end;
4485 if not DoInputQuery( FindTitle,
4486 FindPrompt,
4487 FindText ) then
4488 exit;
4489
4490 DoFind( foFromStart );
4491End;
4492
4493Procedure TMainForm.IndexSearchEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
4494Begin
4495 case KeyCode of
4496 kbCUp:
4497 begin
4498 if IndexListBox.ItemIndex > 0 then
4499 IndexListBox.ItemIndex:= IndexListBox.ItemIndex - 1;
4500 KeyCode:= kbNull;
4501 end;
4502
4503 kbCDown:
4504 begin
4505 if IndexListBox.ItemIndex < IndexListBox.Items.Count - 1 then
4506 IndexListBox.ItemIndex:= IndexListBox.ItemIndex + 1;
4507 KeyCode:= kbNull;
4508 end;
4509
4510 kb_VK + VK_NEWLINE:
4511 begin
4512 DisplaySelectedIndexTopic;
4513 end;
4514 end;
4515
4516End;
4517
4518Procedure TMainForm.IndexSearchEditOnChange (Sender: TObject);
4519var
4520 tmpMatchIndex : longint;
4521 tmpSearchText: string;
4522 i : longint;
4523Begin
4524 if InIndexSearch then
4525 exit;
4526
4527 tmpMatchIndex := -1;
4528 tmpSearchText := trim(IndexSearchEdit.Text);
4529
4530 for i := 0 to DisplayedIndex.Count - 1 do
4531 begin
4532 if StrStartsWithIgnoringCase(DisplayedIndex[i], tmpSearchText) then
4533 begin
4534 tmpMatchIndex := i;
4535 break;
4536 end;
4537 end;
4538
4539 if tmpMatchIndex = -1 then
4540 exit;
4541
4542 InIndexSearch:= true;
4543
4544 if IndexListBox.ItemIndex <> tmpMatchIndex then
4545 IndexListBox.ItemIndex:= tmpMatchIndex;
4546
4547 InIndexSearch:= false;
4548End;
4549
4550Procedure TMainForm.FileInformationMIOnClick (Sender: TObject);
4551var
4552 FileIndex: longint;
4553 HelpFile: THelpFile;
4554
4555 TotalTopicCount: longint;
4556 TotalIndexCount: longint;
4557 TotalFileSize: longint;
4558
4559Begin
4560 TotalTopicCount := 0;
4561 TotalIndexCount := 0;
4562 TotalFileSize := 0;
4563
4564 with InformationForm.InformationMemo do
4565 begin
4566 BeginUpdate;
4567 Lines.Clear;
4568 Lines.Add( FilesInfoTitle );
4569 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4570 begin
4571 HelpFile := CurrentOpenFiles[ FileIndex ];
4572
4573 Lines.Add( FilesInfoFilename + HelpFile.FileName );
4574 Lines.Add( FilesInfoFileTitle
4575 + HelpFile.Title );
4576 Lines.Add( FilesInfoTopicCount
4577 + IntToStr( HelpFile.TopicCount ) );
4578 Lines.Add( FilesInfoIndexCount
4579 + IntToStr( HelpFile.Index.Count ) );
4580 Lines.Add( FilesInfoDictionaryCount
4581 + IntToStr( HelpFile.DictionaryCount ) );
4582 Lines.Add( FilesInfoFileSize
4583 + IntToStr( HelpFile.FileSize ) );
4584
4585 inc( TotalTopicCount, HelpFile.TopicCount );
4586 inc( TotalIndexCount, HelpFile.Index.Count );
4587 inc( TotalFileSize, HelpFile.FileSize );
4588
4589 end;
4590
4591 Lines.Add( '' );
4592 Lines.Add( FilesInfoTotalTopicCount
4593 + IntToStr( TotalTopicCount ) );
4594 Lines.Add( FilesInfoTotalIndexCount
4595 + IntToStr( TotalIndexCount ) );
4596 Lines.Add( FilesInfoTotalFileSize
4597 + IntToStr( TotalFileSize ) );
4598 Lines.Add( '' );
4599
4600 EndUpdate;
4601 end;
4602 InformationForm.ShowModal;
4603End;
4604
4605Procedure TMainForm.DisplaySelectedSearchResultTopic;
4606var
4607 Topic: TTopic;
4608Begin
4609 if SearchResultsListBox.ItemIndex = -1 then
4610 exit;
4611 if SelectedObject( SearchResultsListBox ) = nil then
4612 // the "no results" place holder
4613 exit;
4614 Topic := SelectedObject( SearchResultsListBox ) as TTopic;
4615 DisplayTopic( Topic );
4616End;
4617
4618Procedure TMainForm.SearchTextEditOnScan (Sender: TObject;
4619 Var KeyCode: TKeyCode);
4620Begin
4621 case KeyCode of
4622 kbCUp:
4623 begin
4624 if SearchResultsListBox.ItemIndex > 0 then
4625 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex - 1;
4626 KeyCode := kbNull;
4627 SearchResultsListBox.Focus;
4628 end;
4629
4630 kbCDown:
4631 begin
4632 if SearchResultsListBox.ItemIndex < SearchResultsListBox.Items.Count - 1 then
4633 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex + 1;
4634 KeyCode := kbNull;
4635 SearchResultsListBox.Focus;
4636 end;
4637 end;
4638End;
4639
4640Procedure TMainForm.SearchButtonOnClick (Sender: TObject);
4641Begin
4642 DoSearch;
4643End;
4644
4645// Matches old stupid View algorithm
4646Procedure TMainForm.StartupTopicSearch( const SearchText: string );
4647var
4648 i: longint;
4649 HelpFile: THelpFile;
4650 Topic: TTopic;
4651 // s: string;
4652begin
4653 // search files in order they are open
4654 for i := 0 to CurrentOpenFiles.Count - 1 do
4655 begin
4656 HelpFile := THelpFile( CurrentOpenFiles[ i ] );
4657
4658 // look for a topic whose title starts with the searchtext
4659 Topic := HelpFile.FindTopicByTitleStartsWith( SearchText );
4660
4661 if Topic = nil then
4662 // look for an index entry that starts with the searchtext
4663 Topic := HelpFile.FindTopicByIndexStartsWith( SearchText );
4664
4665 if Topic = nil then
4666 // look for a topic whose title contains the searchtext
4667 Topic := HelpFile.FindTopicByTitleContains( SearchText );
4668
4669 if Topic = nil then
4670 // look for an index entry that contains the searchtext
4671 Topic := HelpFile.FindTopicByIndexContains( SearchText );
4672
4673 if Topic <> nil then
4674 begin
4675 // found something, display it (don't keep searching files)
4676 DisplayTopic( Topic );
4677 exit;
4678 end;
4679 end;
4680 DoErrorDlg( SearchTitle, TextNotFoundMsg );
4681end;
4682
4683Procedure TMainForm.SearchFor( const SearchText: string );
4684begin
4685 SearchTextEdit.Text := SearchText;
4686 DisplaySearch;
4687 SearchResultsListBox.Focus;
4688
4689 // force repaint of everything before we start searching.
4690 Update;
4691
4692 DoSearch;
4693end;
4694
4695Procedure TMainForm.ClearAllWordSequences;
4696var
4697 i: longint;
4698 FileWordSequences: TList;
4699 HelpFile: THelpFile;
4700begin
4701 if AllFilesWordSequences = nil then
4702 exit;
4703
4704 for i := 0 to AllFilesWordSequences.Count - 1 do
4705 begin
4706 FileWordSequences := AllFilesWordSequences[ i ];
4707 HelpFile := CurrentOpenFiles[ i ];
4708 ClearWordSequences( FileWordSequences, HelpFile.DictionaryCount );
4709 FileWordSequences.Destroy;
4710 end;
4711 AllFilesWordSequences.Clear;
4712end;
4713
4714// Perform search for text in searchedit.
4715Procedure TMainForm.DoSearch;
4716var
4717 SearchResults: TList;
4718 SearchText: string;
4719 FileIndex: longint;
4720 HelpFile: THelpFile;
4721 TopicIndex: longint;
4722 Topic: TTopic;
4723 FileWordSequences: TList;
4724 Query: TTextSearchQuery;
4725begin
4726 SearchText := Trim( SearchTextEdit.Text );
4727
4728 SearchResultsListBox.Clear;
4729
4730 if SearchText = '' then
4731 exit;
4732
4733 SearchResultsListBox.Items.Add( SearchingMsg );
4734 SetStatus( SearchingMsg );
4735
4736 try
4737 Query := TTextSearchQuery.Create( SearchText );
4738 except
4739 on e: ESearchSyntaxError do
4740 begin
4741 DoErrorDlg( SearchTitle,
4742 SearchSyntaxError
4743 + e.Message );
4744 exit;
4745 end;
4746 end;
4747
4748 ClearAllWordSequences;
4749
4750 SetWaitCursor;
4751
4752 SearchResults := TList.Create;
4753
4754 // Search open help file
4755 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4756 begin
4757 HelpFile := CurrentOpenFiles[ FileIndex ];
4758
4759 FileWordSequences := TList.Create;
4760
4761 try
4762 SearchHelpFile( HelpFile,
4763 Query,
4764 SearchResults,
4765 FileWordSequences );
4766 except
4767 on E: EHelpFileException do
4768 begin
4769 DoErrorDlg( ErrorTitle, E.Message );
4770 Query.Destroy;
4771 ClearWaitCursor;
4772 exit;
4773 end;
4774 end;
4775
4776 AllFilesWordSequences.Add( FileWordSequences );
4777
4778 end;
4779
4780 // Sort results across all files by relevance
4781 SearchResults.Sort( TopicRelevanceCompare );
4782
4783 // Load topics into search results list.
4784 SearchResultsListBox.BeginUpdate;
4785 SearchResultsListBox.Clear;
4786
4787 for TopicIndex := 0 to SearchResults.Count - 1 do
4788 begin
4789 Topic := SearchResults[ TopicIndex ];
4790 SearchResultsListBox.Items.AddObject( Topic.Title
4791 + ' ['
4792 + IntToStr( Topic.SearchRelevance )
4793 + ']',
4794 Topic );
4795 end;
4796
4797 EnableControls;
4798 if SearchResultsListBox.Items.Count > 0 then
4799 // there are some search matches, so highlight words
4800 ViewHighlightSearchWordsMI.Checked := true;
4801
4802 SearchResultsListBox.ItemIndex := -1;
4803 SearchResultsListBox.EndUpdate;
4804
4805 Query.Destroy;
4806 SearchResults.Destroy;
4807
4808 if SearchResultsListBox.Items.Count > 0 then
4809 begin
4810 SearchResultsListBox.ItemIndex := 0;
4811 end
4812 else
4813 begin
4814 SearchResultsListBox.Items.Add( NoSearchMatchesMsg
4815 + ': '
4816 + SearchText );
4817 RefreshWindows( Windows ); // update to remove old highlights
4818 end;
4819 SetStatus( SearchFoundMsgA
4820 + IntToStr( SearchResultsListBox.Items.Count )
4821 + SearchFoundMsgB
4822 + StrInDoubleQuotes(SearchText)
4823 );
4824
4825 ClearWaitCursor;
4826
4827 DisplaySelectedSearchResultTopic;
4828
4829End;
4830
4831Procedure TMainForm.FileSaveAsMIOnClick (Sender: TObject);
4832var
4833 F: File;
4834 EntryText: PChar;
4835 TextLength: longint;
4836 Window: THelpWindow;
4837 Filename: string;
4838Begin
4839 Window := GetActiveWindow;
4840 if Window = nil then
4841 begin
4842 DoErrorDlg( FileSaveTitle,
4843 FileSaveSelectWindowError );
4844 exit;
4845 end;
4846
4847 if DoSaveFileDialog( FileSaveTitle,
4848 AllFilesDesc + '|*',
4849 DefaultSaveTopicFilename,
4850 Settings.LastSaveDirectory,
4851 Filename ) then
4852 begin
4853 if FileExists( Filename ) then
4854 if not DoConfirmDlg( FileSaveTitle,
4855 ReplaceFilePromptA
4856 + Filename
4857 + ReplaceFilePromptB ) then
4858 exit;
4859 System.Assign( F, Filename );
4860
4861 try
4862 Rewrite( F );
4863 except
4864 on E: Exception do
4865 begin
4866 DoErrorDlg( FileSaveTitle,
4867 UnableToSaveError
4868 + Filename
4869 + ': '
4870 + E.Message );
4871 exit;
4872 end;
4873 end;
4874
4875 // find out length of (plain) text
4876 TextLength := Window.View.CopyTextToBuffer( nil, -1 );
4877
4878 // allocate space
4879 EntryText:= StrAlloc( TextLength );
4880
4881 // get the plain text
4882 Window.View.CopyTextToBuffer( EntryText, TextLength );
4883
4884 // save to file
4885 System.BlockWrite( F, EntryText^, TextLength );
4886
4887 // free space
4888 StrDispose( EntryText );
4889
4890 System.Close( F );
4891 end;
4892End;
4893
4894Procedure TMainForm.OptionsMIOnClick (Sender: TObject);
4895begin
4896 DoOptions;
4897end;
4898
4899Procedure TMainForm.DoOptions;
4900Begin
4901 EnsureOptionsFormLoaded;
4902
4903 GetColors; // in case changed by drag drop
4904
4905 if OptionsForm.ShowModal = mrOK then
4906 begin
4907 ApplySettings;
4908 SetLayout;
4909 RefreshFontSubstitutions;
4910 RefreshWindows( Windows );
4911 end;
4912End;
4913
4914Procedure TMainForm.ShowUsage;
4915begin
4916 DoMessageDlg( UsageTitle,
4917 UsageText1 + StrCRLF
4918 + UsageText2 + StrCRLF
4919 + UsageText3 + StrCRLF
4920 + UsageText4 + StrCRLF
4921 + UsageText5 + StrCRLF
4922 + UsageText6 + StrCRLF
4923 + UsageText7 + StrCRLF
4924 + UsageText8 );
4925end;
4926
4927Procedure TMainForm.TabSetOnChange (Sender: TObject; NewTab: LongInt;
4928 Var AllowChange: Boolean);
4929Begin
4930 NoteBook.PageIndex := NewTab;
4931End;
4932
4933Procedure TMainForm.NotebookOnSetupShow (Sender: TObject);
4934Begin
4935 ContentsOutline.xStretch := xsFrame;
4936 ContentsOutline.yStretch := ysFrame;
4937
4938 IndexSearchEdit.yAlign := yaTop;
4939 IndexSearchEdit.xStretch := xsFrame;
4940 IndexListBox.yStretch := ysFrame;
4941 IndexListBox.xStretch := xsFrame;
4942
4943 SearchTextEdit.yAlign := yaTop;
4944 SearchTextEdit.xStretch := xsFrame;
4945 SearchButton.yAlign := yaTop;
4946 SearchButton.xAlign := xaRight;
4947 SearchResultsListBox.xStretch := xsFrame;
4948 SearchResultsListBox.yStretch := ysFrame;
4949
4950 NotesListBox.xStretch := xsFrame;
4951 NotesListBox.yStretch := ysFrame;
4952End;
4953
4954Procedure TMainForm.EnableControls;
4955var
4956 BackEnabled: boolean;
4957 ForwardEnabled: boolean;
4958 FileOpen: boolean;
4959 WindowOpen: boolean;
4960 AtTop: boolean;
4961 AtBottom: boolean;
4962begin
4963 ViewContentsMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piContents );
4964 ViewIndexMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piIndex );
4965 ViewSearchMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piSearch );
4966 ViewNotesMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piNotes );
4967
4968 BackEnabled := CurrentHistoryIndex > 0;
4969 ForwardEnabled := CurrentHistoryIndex < PageHistory.Count - 1;
4970
4971 FileOpen := CurrentOpenFiles.Count > 0;
4972 WindowOpen := Windows.Count > 0;
4973
4974 ViewContentsMI.Enabled := FileOpen;
4975 ViewIndexMI.Enabled := FileOpen;
4976 ViewSearchMI.Enabled := FileOpen;
4977 ViewNotesMI.Enabled := FileOpen;
4978
4979 ShowLeftPanelMI.Enabled := FileOpen;
4980
4981 Coolbar.Sections[ ciBack ].Disabled := not BackEnabled;
4982 NavigateBackMI.Enabled := BackEnabled;
4983 Coolbar.Sections[ ciForward ].Disabled := not ForwardEnabled;
4984 NavigateForwardMI.Enabled := ForwardEnabled;
4985
4986 FileSaveAsMI.Enabled := FileOpen;
4987
4988 Coolbar.Sections[ ciPrint ].Disabled := not FileOpen;
4989 PrintMI.Enabled := FileOpen;
4990 FileInformationMI.Enabled := FileOpen;
4991
4992 Coolbar.Sections[ ciAddBookmark ].Disabled := not FileOpen;
4993 AddBookmarkMI.Enabled := FileOpen;
4994 EditBookmarksMI.Enabled := FileOpen;
4995 Coolbar.Sections[ ciAddNote ].Disabled := not FileOpen;
4996 AddNoteMI.Enabled := FileOpen;
4997
4998 if ContentsOutline.SelectedNode <> nil then
4999 begin
5000 AtTop := ContentsOutline.NextNodeUp( ContentsOutline.SelectedNode, false ) = nil;
5001 AtBottom := ContentsOutline.NextNodeDown( ContentsOutline.SelectedNode, false ) = nil;
5002 end;
5003
5004 NavigateNextMI.Enabled := FileOpen
5005 and ( ContentsOutline.SelectedNode <> nil )
5006 and ( not AtBottom );
5007 Coolbar.Sections[ ciNext ].Disabled := not NavigateNextMI.Enabled;
5008 NavigatePreviousMI.Enabled := FileOpen
5009 and ( ContentsOutline.SelectedNode <> nil )
5010 and ( not AtTop );
5011 Coolbar.Sections[ ciPrevious ].Disabled := not NavigatePreviousMI.Enabled;
5012
5013 FileCloseMI.Enabled := FileOpen;
5014
5015 FindMI.Enabled := WindowOpen;
5016 FindNextMI.Enabled := WindowOpen;
5017 CopyMI.Enabled := WindowOpen;
5018 SelectAllMI.Enabled := WindowOpen;
5019
5020 ViewExpandAllMI.Enabled := ContentsOutline.ChildCount > 0;
5021 ViewCollapseAllMI.Enabled := ContentsOutline.ChildCount > 0;
5022
5023 DebugTopicByResourceIDMI.Enabled := FileOpen;
5024 TopicByNameMI.Enabled := FileOpen;
5025
5026 ViewHighlightSearchWordsMI.Enabled := SearchResultsListBox.Items.Count > 0;
5027 if not ViewHighlightSearchWordsMI.Enabled then
5028 ViewHighlightSearchWordsMI.Checked := false;
5029
5030 ViewRefreshMI.Enabled := WindowOpen;
5031
5032 EnableSearchButton;
5033 EnableNotesControls;
5034
5035 VSplitBar.Visible := FileOpen;
5036 if not FileOpen then
5037 begin
5038 SetShowLeftPanel( false );
5039 end;
5040
5041
5042end;
5043
5044Procedure TMainForm.NavigateBackMIOnClick (Sender: TObject);
5045begin
5046 NavigateBack;
5047end;
5048
5049Procedure TMainForm.SaveNavigatePoint;
5050var
5051 NavPoint: TNavigatePoint;
5052begin
5053 // delete rest of history.
5054 while CurrentHistoryIndex < PageHistory.Count - 1 do
5055 begin
5056 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex + 1 ] as TNavigatePoint;
5057 NavPoint.Destroy;
5058 PageHistory.Delete( CurrentHistoryIndex + 1 );
5059 end;
5060
5061 NavPoint:= TNavigatePoint.Create;
5062 SaveWindows( Windows, NavPoint.Windows, nil );
5063
5064 if ContentsOutline.SelectedNode <> nil then
5065 NavPoint.ContentsTopic:= ContentsOutline.SelectedNode.Data as TTopic
5066 else
5067 NavPoint.ContentsTopic:= nil;
5068
5069 if CurrentTopic <> nil then
5070 PageHistory.AddObject( CurrentTopic.Title, NavPoint )
5071 else
5072 PageHistory.AddObject( '', NavPoint );
5073
5074 inc( CurrentHistoryIndex );
5075
5076 CreateNavigateToMenuItems;
5077end;
5078
5079Procedure TMainForm.UpdateCurrentNavigatePoint;
5080var
5081 NavPoint: TNavigatePoint;
5082begin
5083 if CurrentHistoryIndex = -1 then
5084 exit;
5085
5086 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5087
5088 DestroyListObjects( NavPoint.Windows );
5089 NavPoint.Windows.Clear;
5090
5091 SaveWindows( Windows, NavPoint.Windows, nil );
5092end;
5093
5094Procedure TMainForm.ClearPageHistory;
5095var
5096 i: longint;
5097 NavPoint: TNavigatePoint;
5098begin
5099 for i := 0 to PageHistory.Count - 1 do
5100 begin
5101 NavPoint := PageHistory.Objects[ i ] as TNavigatePoint;
5102 NavPoint.Destroy;
5103 end;
5104 PageHistory.Clear;
5105 CurrentHistoryIndex := -1;
5106 CreateNavigateToMenuItems;
5107 EnableControls;
5108end;
5109
5110Procedure TMainForm.SaveWindows( SourceList: TList;
5111 DestList: TList;
5112 Parent: TSavedHelpWindow );
5113
5114var
5115 WindowIndex: longint;
5116 Window: THelpWindow;
5117 WindowCopy: TSavedHelpWindow;
5118begin
5119 // limit storage to only what's need since list will be static.
5120 DestList.Capacity := SourceList.Count;
5121 for WindowIndex := 0 to SourceList.Count - 1 do
5122 begin
5123 Window := SourceList[ WindowIndex ];
5124 WindowCopy := TSavedHelpWindow.Create;
5125 WindowCopy.Parent := Parent;
5126 WindowCopy.Rect.Assign( Window.Rect );
5127 WindowCopy.Topic := Window.Topic;
5128 WindowCopy.Group := Window.Group;
5129 WindowCopy.TopCharIndex := Window.View.TopCharIndex;
5130 SaveWindows( Window.ChildWindows, WindowCopy.ChildWindows, WindowCopy );
5131 DestList.Add( WindowCopy );
5132 end;
5133end;
5134
5135Procedure TMainForm.DisplayWindows( WindowList: TList;
5136 Parent: THelpWindow );
5137var
5138 WindowIndex: longint;
5139 WindowCopy: TSavedHelpWindow;
5140 NewWindow: THelpWindow;
5141begin
5142 for WindowIndex := 0 to WindowList.Count - 1 do
5143 begin
5144 WindowCopy := WindowList[ WindowIndex ];
5145 NewWindow := OpenWindow( WindowCopy.Topic,
5146 WindowCopy.Group,
5147 Parent,
5148 WindowCopy.Rect,
5149 false ); // don't follow links
5150 NewWindow.View.TopCharIndex := WindowCopy.TopCharIndex;
5151 DisplayWindows( WindowCopy.ChildWindows, NewWindow );
5152 end;
5153end;
5154
5155Procedure TMainForm.CreateNavigateToMenuItems;
5156var
5157 MenuItem: TMenuItem;
5158 i: integer;
5159begin
5160 // clear existing items
5161 DestroyListObjects( NavigateToMenuItems );
5162 NavigateToMenuItems.Clear;
5163
5164 if CurrentHistoryIndex > 0 then
5165 begin
5166 // We are going to add some items, so
5167 // add a seperator from the rest of the menu first
5168 MenuItem := TMenuItem.Create( self );
5169 MenuItem.Caption:= '-';
5170 NavigateMenu.Add( MenuItem );
5171 NavigateToMenuItems.Add( MenuItem );
5172 end;
5173
5174 i := CurrentHistoryIndex - 1; // don't include the current history item
5175 while ( ( i >= 0 )
5176 and ( i > CurrentHistoryIndex - 10 ) ) do
5177 begin
5178 MenuItem := TMenuItem.Create( self );
5179 MenuItem.Caption := PageHistory[ i ];
5180 MenuItem.Hint := GoBackHint
5181 + StrInDoubleQuotes( PageHistory[ i ] );
5182 MenuItem.OnClick := OnNavigateToMenuItemClick;
5183 MenuItem.Tag := i;
5184
5185 NavigateMenu.Add( MenuItem );
5186 NavigateToMenuItems.Add( MenuItem );
5187 dec( i );
5188 end;
5189end;
5190
5191Procedure TMainForm.NavigateToPoint( NavPoint: TNavigatePoint );
5192begin
5193 Navigating := true;
5194
5195 // close current windows
5196 CloseWindows;
5197
5198 // Display windows for the navigate point
5199 DisplayWindows( NavPoint.Windows, nil );
5200
5201 // Select the contents topic
5202 ContentsOutline.SetSelectedObject( NavPoint.ContentsTopic );
5203
5204 // Update the navigate menu (since a different set of
5205 // back-points are now available)
5206 CreateNavigateToMenuItems;
5207
5208 // Make the topic windows visible
5209 ShowWindows;
5210
5211 // Update back buttons etc...
5212 EnableControls;
5213
5214 Navigating := false;
5215end;
5216
5217Procedure TMainForm.NavigateToHistoryIndex( Index: longint );
5218var
5219 NavPoint: TNavigatePoint;
5220begin
5221 UpdateCurrentNavigatePoint;
5222 CurrentHistoryIndex := Index;
5223 NavPoint := PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5224 NavigateToPoint( NavPoint );
5225end;
5226
5227Procedure TMainForm.NavigateForward;
5228Begin
5229 if CurrentHistoryIndex < PageHistory.Count - 1 then
5230 begin
5231 NavigateToHistoryIndex( CurrentHistoryIndex + 1 );
5232 end;
5233End;
5234
5235Procedure TMainForm.NavigateBack;
5236Begin
5237 if CurrentHistoryIndex > 0 then
5238 begin
5239 NavigateToHistoryIndex( CurrentHistoryIndex - 1 );
5240 end;
5241End;
5242
5243Procedure TMainForm.NavigatePreviousInContents;
5244begin
5245 ContentsOutline.GotoNextNodeUp;
5246 DisplaySelectedContentsTopic;
5247end;
5248
5249Procedure TMainForm.NavigateNextInContents;
5250begin
5251 ContentsOutline.GotoNextNodeDown;
5252 DisplaySelectedContentsTopic;
5253end;
5254
5255Procedure TMainForm.CorrectNotesPositions( Topic: TTopic;
5256 Text: pchar );
5257var
5258 NoteIndex: longint;
5259 Note: THelpNote;
5260 p: pchar;
5261 NextP: pchar;
5262 Element: TTextElement;
5263 TextIndex: longint;
5264begin
5265 NoteIndex := 0;
5266 for NoteIndex := 0 to Notes.Count - 1 do
5267 begin
5268 Note := Notes[ NoteIndex ];
5269 if Note.Topic = Topic then
5270 begin
5271 // this note belongs the the specified topic.
5272 p := Text;
5273
5274 while true do
5275 begin
5276 Element := ExtractNextTextElement( p, NextP );
5277 if Element.ElementType = teTextEnd then
5278 break;
5279 TextIndex := PCharPointerDiff( p, Text );
5280 if TextIndex >= Note.InsertPoint then
5281 begin
5282 // found a safe point to insert
5283 if TextIndex <> Note.InsertPoint then
5284 begin
5285 // correct it.
5286 Note.InsertPoint := TextIndex;
5287 end;
5288 break;
5289 end;
5290
5291 p := NextP;
5292 end;
5293 end;
5294 end;
5295end;
5296
5297Procedure TMainForm.InsertNotesIntoTopicText( Topic: TTopic;
5298 Text: TAString );
5299var
5300 NoteIndex: longint;
5301 Note: THelpNote;
5302 ActualInsertPoint: longword;
5303begin
5304 CorrectNotesPositions( Topic, Text.AsPChar );
5305
5306 for NoteIndex := 0 to Notes.Count - 1 do
5307 begin
5308 Note := Notes[ NoteIndex ];
5309 if Note.Topic = Topic then
5310 begin
5311 // Adjust insert point for any notes we have already inserted.
5312 ActualInsertPoint := FindActualNoteCharIndex( Note.InsertPoint,
5313 NoteIndex,
5314 Topic );
5315 RefreshNoteInsertInfo( NoteIndex );
5316 Text.Insert( ActualInsertPoint, Note.InsertText );
5317 end;
5318 end;
5319end;
5320
5321Procedure TMainForm.NavigatePreviousMIOnClick (Sender: TObject);
5322Begin
5323 NavigatePreviousInContents;
5324End;
5325
5326Procedure TMainForm.NavigateNextMIOnClick (Sender: TObject);
5327Begin
5328 NavigateNextInContents;
5329End;
5330
5331Function TMainForm.GetActiveWindow: THelpWindow;
5332var
5333 View: TRichTextView;
5334 FirstWindow: THelpWindow;
5335begin
5336 Result := nil;
5337 if Screen.ActiveControl is TRichTextView then
5338 begin
5339 View := Screen.ActiveControl as TRichTextView;
5340 Result := FindWindowFromView( View, Windows );
5341 end
5342 else if Windows.Count = 1 then
5343 begin
5344 FirstWindow := Windows[ 0 ];
5345 if FirstWindow.ChildWindows.Count = 0 then
5346 Result := FirstWindow;
5347 end;
5348end;
5349
5350Procedure TMainForm.CopyMIOnClick (Sender: TObject);
5351var
5352 Window: THelpWindow;
5353begin
5354 if ActiveControl = nil then
5355 exit;
5356
5357 if ActiveControl is TEdit then
5358 begin
5359 // this is for the edit controls in the left panel
5360 TEdit( ActiveControl ).CopyToClipboard;
5361 exit;
5362 end;
5363
5364 // else copy from rtv in active help window
5365
5366 Window := GetActiveWindow;
5367 if Window = nil then
5368 exit;
5369
5370 Window.View.CopySelectionToClipboard;
5371End;
5372
5373Procedure TMainForm.SelectAllMIOnClick (Sender: TObject);
5374var
5375 Window: THelpWindow;
5376begin
5377 Window:= GetActiveWindow;
5378 if Window = nil then
5379 begin
5380 DoErrorDlg( SelectAllTitle,
5381 SelectAllWindowError );
5382 exit;
5383 end;
5384 Window.View.SelectAll;
5385End;
5386
5387Procedure TMainForm.DebugShowCodesMIOnClick (Sender: TObject);
5388Begin
5389 DebugShowCodesMI.Checked:= not DebugShowCodesMI.Checked;
5390 RefreshWindows( Windows );
5391End;
5392
5393Procedure TMainForm.HelpProductInformationMIOnClick (Sender: TObject);
5394Begin
5395 EnsureProductInformationFormLoaded;
5396 ProductInformationForm.ShowModal;
5397End;
5398
5399Procedure TMainForm.OnOverLink ( Sender: TRichTextView; LinkString: String);
5400var
5401 Link: THelpLink;
5402 LinkIndex: longint;
5403 Window: THelpWindow;
5404 LinkedTopic: TTopic;
5405 Filename: string;
5406 SourceFile: THelpFile;
5407 URL: string;
5408 LinkDetails: string;
5409 tmpLinkDetails : TStringList;
5410 ProgramInfo : TSerializableStringList;
5411 ProgramPath, ProgramLink : string;
5412Begin
5413 LogEvent(LogDebug, 'OnOverLink: "' + LinkString + '"');
5414
5415 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5416 begin
5417 SetStatus( EditNoteMsg )
5418 end
5419 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5420 begin
5421 ProgramInfo := TSerializableStringList.create;
5422// TODO check param here
5423
5424 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, Length(PARAM_LINK_PROGRAM) + 2));
5425 ProgramPath := ProgramInfo.get(0);
5426 ProgramLink := ProgramInfo.get(1);
5427 TSerializableStringList.destroy;
5428
5429 // call LaunchProgram here to inherit the environment
5430 SetStatus( LinkMsg + ' ' + ProgramPath + ' ' + ProgramLink);
5431 end
5432 else if StrStartsWith(LinkString, PARAM_LINK_URL) then
5433 begin
5434 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2); //
5435
5436 SetStatus( LinkMsg + URL );
5437 end
5438 else if StrStartsWith(LinkString, PARAM_LINK_EXTERNAL) then
5439 begin
5440 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5441
5442 tmpLinkDetails := TStringList.Create;
5443 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5444 LinkIndex := StrToInt(tmpLinkDetails[0]);
5445 tmpLinkDetails.Destroy;
5446
5447 Window := FindWindowFromView( Sender, Windows );
5448 SourceFile := Window.Topic.HelpFile as THelpFile;
5449 Filename := SourceFile.ReferencedFiles[ LinkIndex ];
5450 SetStatus( LinkMsg
5451 + StrInDoubleQuotes( Filename ) );
5452 end
5453 else
5454 begin
5455 Window := FindWindowFromView( Sender, Windows );
5456 LinkIndex := StrToInt( LinkString );
5457 Link := Window.Topic.Links[ LinkIndex ];
5458
5459 if Link is TFootnoteHelpLink then
5460 begin
5461 SetStatus( FootnoteMsg );
5462 end
5463 else
5464 begin
5465 LinkedTopic := FindTopicForLink( Link );
5466
5467 if LinkedTopic <> nil then
5468 begin
5469 SetStatus( LinkMsg
5470 + StrInDoubleQuotes( Trim( LinkedTopic.Title ) ) );
5471 end
5472 else
5473 begin
5474 SetStatus( UnknownLinkMsg );
5475 end;
5476 end;
5477 end;
5478End;
5479
5480Procedure TMainForm.OnNotOverLink ( Sender: TRichTextView; LinkString: String);
5481Begin
5482 SetStatus( '' );
5483end;
5484
5485Procedure TMainForm.OnClickLink ( Sender: TRichTextView; LinkString: String);
5486var
5487 Link: THelpLink;
5488 LinkIndex: longint;
5489 SourceWindow: THelpWindow;
5490 NoteIndex: longint;
5491 Window: THelpWindow;
5492 SourceFile: THelpFile;
5493 ProgramLink: string;
5494 ProgramPath: string;
5495 URL: string;
5496 LinkDetails: string;
5497 tmpLinkDetails : TStringList;
5498 ProgramInfo : TSerializableStringList;
5499Begin
5500 LogEvent(LogDebug, 'OnClickLink: "' + LinkString + '"');
5501
5502 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5503 begin
5504 NoteIndex := StrToInt(StrSubstringFrom(LinkString, Length(PARAM_LINK_NOTE) + 2) );
5505 NotesListBox.ItemIndex := NoteIndex;
5506 EditNote( NoteIndex );
5507 end
5508 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5509 begin
5510 ProgramInfo := TSerializableStringList.create;
5511 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, 9));
5512 ProgramPath := ProgramInfo.get(0);
5513 ProgramLink := ProgramInfo.get(1);
5514 TSerializableStringList.destroy;
5515
5516 // call LaunchProgram here to inherit the environment
5517 LogEvent(LogDisplay, 'LaunchProgram: "' + ProgramPath + '" "' + ProgramLink + '"');
5518 LaunchProgram(ProgramPath, ProgramLink, '');
5519 // TODO i18n
5520 SetStatus( 'Launched ' + ProgramPath );
5521 end
5522 else if StrLeft( LinkString, 3 ) = PARAM_LINK_URL then
5523 begin
5524 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2);
5525
5526 try
5527 LaunchURL(URL);
5528 except
5529 on E:Exception do
5530 begin
5531 DoErrorDlg('Error', E.Message);
5532 end;
5533 else raise;
5534 end;
5535
5536 // TODO i18n
5537 SetStatus('Opened ' + URL );
5538 end
5539 else if StrLeft( LinkString, 8 ) = PARAM_LINK_EXTERNAL then
5540 begin
5541 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5542
5543 tmpLinkDetails := TStringList.Create;
5544 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5545 LinkIndex := StrToInt(tmpLinkDetails[0]);
5546 tmpLinkDetails.Destroy;
5547
5548 Window := FindWindowFromView( Sender, Windows );
5549 SourceFile := Window.Topic.HelpFile as THelpFile;
5550
5551 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5552 g_ExternalLinkTopic := LinkDetails;
5553 g_ExternalLinkSourceFilename := SourceFile.Filename;
5554 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5555
5556 PostMsg( Self.Handle,
5557 WM_FOLLOWEXTERNALLINK,
5558 0,
5559 0 );
5560 end
5561 else
5562 begin
5563 SourceWindow := FindWindowFromView( Sender, Windows );
5564 LinkIndex := StrToInt( LinkString );
5565 Link := SourceWindow.Topic.Links[ LinkIndex ];
5566
5567 PostMsg( Self.Handle,
5568 WM_FOLLOWLINK,
5569 longint( Link ),
5570 longint( SourceWindow ) );
5571
5572 end;
5573End;
5574
5575Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5576 var CanClose: boolean );
5577begin
5578 if Navigating then
5579 exit;
5580
5581 UpdateCurrentNavigatePoint; // Save it before close...
5582
5583 CanClose := true;
5584end;
5585
5586Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5587var
5588 ParentWindow: THelpWindow;
5589 WindowIndex: longint;
5590Begin
5591 if Navigating then
5592 exit;
5593
5594 if Window.ParentHelpWindow = nil then
5595 begin
5596 WindowIndex := Windows.IndexOf( Window );
5597 Windows.Delete( WindowIndex );
5598 end
5599 else
5600 begin
5601 ParentWindow := Window.ParentHelpWindow;
5602 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5603 ParentWindow.ChildWindows.Delete( WindowIndex );
5604 end;
5605end;
5606
5607Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5608Begin
5609 if Navigating then
5610 exit;
5611
5612 RemoveHelpWindowFromParent( Window );
5613
5614 SaveNavigatePoint;
5615 EnableControls;
5616End;
5617
5618Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5619Begin
5620 NavigateBack;
5621End;
5622
5623Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5624Begin
5625End;
5626
5627Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5628Begin
5629 Close;
5630End;
5631
5632Procedure TMainForm.CreateMRUMenuItems;
5633var
5634 MenuItem: TMenuItem;
5635 i: integer;
5636 FileName: string;
5637 FileNameIndex: longint;
5638 MRUText: string;
5639 MRUItem: TMRUItem;
5640begin
5641 DestroyListObjects( MRUMenuItems );
5642 MRUMenuItems.Clear;
5643
5644 // if there are Most Recently Used files
5645 if Settings.MRUList.Count > 0 then
5646 begin
5647 // create a seperator after Exit
5648 MenuItem:= TMenuItem.Create( self );
5649 MenuItem.Name := 'MRUSeparatorMI';
5650 MenuItem.Caption:= '-';
5651 FileMenu.Add( MenuItem );
5652 MRUMenuItems.Add( MenuItem );
5653 end;
5654
5655 // Add items for the MRU files
5656 for i:= 0 to Settings.MRUList.Count -1 do
5657 begin
5658 MRUItem := Settings.MRUList[ i ];
5659
5660 MenuItem := TMenuItem.Create( self );
5661
5662 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5663 MRUText := MRUItem.Title;
5664 if Trim( MRUText ) = '' then
5665 begin
5666 // Take the filenames, less path, as caption...
5667 MRUText := '';
5668 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5669 begin
5670 FileName := MRUItem.Filenames[ FileNameIndex ];
5671 FileName := ExtractFileName( FileName );
5672 FileName := ChangeFileExt( FileName, '' );// remove extension
5673
5674 if FileNameIndex > 0 then
5675 begin
5676 MRUText := MRUText + HELP_FILE_DELIMITER;
5677 end;
5678 MRUText := MRUText + FileName;
5679
5680 // stop after 50 chars
5681 if Length( MRUText ) > 50 then
5682 begin
5683 MRUText := MRUText + HELP_FILE_DELIMITER + ' ...';
5684 break;
5685 end;
5686 end;
5687 end;
5688
5689 MenuItem.Caption:= '~'
5690 + IntToStr( i + 1 )
5691 + '. '
5692 + MRUText;
5693 if MRUItem.Filenames.Count = 1 then
5694 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5695 else
5696 MenuItem.Hint := MRUItem.Title
5697 + ' ('
5698 + IntToStr( MRUItem.Filenames.Count )
5699 + ' '
5700 + MRUMultipleFilesHint
5701 + ')';
5702
5703 MenuItem.OnClick:= OnMRUMenuItemClick;
5704 MenuItem.Tag:= i;
5705 FileMenu.Add( MenuItem );
5706 MRUMenuItems.Add( MenuItem );
5707 end;
5708end;
5709
5710procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5711var
5712 Tag: longint;
5713 MenuItem: TMenuItem;
5714 MRUItem: TMRUItem;
5715begin
5716 MenuItem:= Sender as TMenuItem;
5717 Tag:= MenuItem.Tag;
5718 MRUItem := Settings.MRUList[ Tag ];
5719// RBRi woher kommt die liste?
5720 if OpenFiles( MRUItem.FileNames, '', true ) then
5721 begin
5722 ClearHelpManager;
5723 end;
5724end;
5725
5726Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5727var
5728 MenuItem: TMenuItem;
5729 Tag: longint;
5730begin
5731 MenuItem:= Sender as TMenuItem;
5732 Tag:= MenuItem.Tag;
5733 NavigateToHistoryIndex( Tag );
5734end;
5735
5736Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5737 ParentNode: TNode;
5738 Level: longint;
5739 Var TopicIndex: longint );
5740var
5741 Topic: TTopic;
5742 Node: TNode;
5743begin
5744 assert( ParentNode <> nil );
5745 Node := nil;
5746 while TopicIndex < HelpFile.TopicCount do
5747 begin
5748 Topic:= HelpFile.Topics[ TopicIndex ];
5749
5750 if Topic.ShowInContents then
5751 begin
5752 if Topic.ContentsLevel < Level then
5753 break;
5754
5755 if Topic.ContentsLevel = Level then
5756 begin
5757 Node:= ParentNode.AddChild( Topic.Title,
5758 Topic );
5759 inc( TopicIndex );
5760 end
5761 else
5762 begin
5763 assert( Node <> nil );
5764 AddChildNodes( HelpFile,
5765 Node,
5766 Topic.ContentsLevel,
5767 TopicIndex );
5768 Node := nil;
5769 end
5770 end
5771 else
5772 begin
5773 inc( TopicIndex );
5774 end;
5775 end;
5776
5777end;
5778
5779Procedure TMainForm.LoadContents( Files: TList;
5780 Var FirstNode: TNode );
5781var
5782 TopicIndex: longint;
5783 Topic: TTopic;
5784 Node: TNode;
5785 FileIndex: longint;
5786 HelpFile: THelpFile;
5787begin
5788 ContentsOutline.BeginUpdate;
5789 LogEvent(LogStartup, 'Load contents outline');
5790
5791 // we don't clear it first, to allow adding additional files
5792 // into the contents tree
5793
5794 LogEvent(LogStartup, 'Loop files');
5795
5796 FirstNode := nil;
5797
5798 Node := nil;
5799
5800 for FileIndex:= 0 to Files.Count - 1 do
5801 begin
5802 HelpFile := Files[ FileIndex ];
5803 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5804 TopicIndex := 0;
5805 while TopicIndex < HelpFile.TopicCount do
5806 begin
5807 Topic := HelpFile.Topics[ TopicIndex ];
5808 assert( Topic.ContentsLevel >= 0,
5809 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5810 if Topic.ShowInContents then
5811 begin
5812 if Topic.ContentsLevel = 1 then
5813 begin
5814 Node := ContentsOutline.AddChild( Topic.Title,
5815 Topic );
5816 if FirstNode = nil then
5817 FirstNode := node;
5818
5819 inc( TopicIndex );
5820 end
5821 else
5822 begin
5823 // subnodes
5824 // ignore child nodes before the first root node
5825 // the org viewer does the same
5826 if Node = nil then
5827 begin
5828 inc( TopicIndex );
5829 end
5830 else
5831 begin
5832 AddChildNodes( HelpFile, Node, Topic.ContentsLevel, TopicIndex );
5833 Node := nil;
5834 end;
5835 end;
5836 end
5837 else
5838 begin
5839 inc( TopicIndex );
5840 end;
5841 end;
5842 end;
5843 LogEvent(LogStartup, ' EndUpdate' );
5844 ContentsOutline.EndUpdate;
5845
5846 if Settings.OpenWithExpandedContents then
5847 begin
5848 LogEvent(LogStartup, ' Expand all contents' );
5849 ContentsOutline.ExpandAll
5850 end
5851 else if ContentsOutline.ChildCount = 1 then
5852 begin
5853 LogEvent(LogStartup, ' Expand first node' );
5854 // Contents has only one top level node... expand it
5855 FirstNode.Expand;
5856 end;
5857
5858 ContentsLoaded := true;
5859 LogEvent(LogStartup, ' Contents loaded' );
5860
5861end;
5862
5863Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5864var
5865 NotesFileName: string;
5866 TopicIndex: longword;
5867 Note: THelpNote;
5868 NoteIndex: longint;
5869
5870 NotesFile: HFile;
5871 OpenAction: ULong;
5872 rc: APIRET;
5873 CName: Cstring;
5874 FileNoteCount: integer;
5875
5876begin
5877 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5878
5879 if not HelpFile.NotesLoaded then
5880 // we never loaded the notes/displayed a topic from this file
5881 // so don't do anything.
5882 exit;
5883
5884 LogEvent(LogStartup, 'Really saving' );
5885
5886 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5887
5888 FileNoteCount := 0;
5889 for NoteIndex := 0 to Notes.Count - 1 do
5890 begin
5891 Note := Notes[ NoteIndex ];
5892
5893 if Note.Topic.HelpFile = HelpFile then
5894 inc( FileNoteCount );
5895 end;
5896
5897 if FileNoteCount = 0 then
5898 begin
5899 // no notes. delete notes file if it already exists.
5900 if FileExists( NotesFileName ) then
5901 DeleteFile( NotesFileName );
5902 exit;
5903 end;
5904
5905 CName:= NotesFileName;
5906 rc:= DosOpen( CName,
5907 NotesFile,
5908 OpenAction,
5909 0, // file size
5910 0, // attrs
5911 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5912 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5913 nil ); // no eas
5914 if rc <> 0 then
5915 begin
5916 DoErrorDlg( SaveNotesTitle,
5917 SaveNotesError
5918 + StrCRLF
5919 + NotesFileName
5920 + StrCRLF
5921 + SysErrorMessage( rc ) );
5922 exit;
5923 end;
5924
5925 for NoteIndex:= 0 to Notes.Count - 1 do
5926 begin
5927 Note:= Notes[ NoteIndex ];
5928
5929 if Note.Topic.HelpFile <> HelpFile then
5930 continue;
5931
5932 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5933
5934 MyWriteLn( NotesFile,
5935 IntToStr( TopicIndex ));
5936 MyWriteLn( NotesFile,
5937 IntToStr( Note.InsertPoint ) );
5938
5939 MyWrite( NotesFile,
5940 Note.Text.AsPChar,
5941 Note.Text.Length );
5942
5943 MyWriteLn( NotesFile,
5944 '' );
5945 MyWriteLn( NotesFile,
5946 '#ENDNOTE#' );
5947
5948 end;
5949
5950 DosClose( NotesFile );
5951end;
5952
5953Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5954var
5955 NotesFileName: string;
5956 TopicIndex: longint;
5957 InsertPoint: longint;
5958 Note: THelpNote;
5959
5960 NotesFile: HFile;
5961 OpenAction: ULong;
5962 rc: APIRET;
5963 CName: Cstring;
5964
5965 Paragraph: TAString;
5966 NotEOF: boolean;
5967 NoteText: TAString;
5968
5969begin
5970 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5971
5972 if HelpFile.NotesLoaded then
5973 exit;
5974
5975 HelpFile.NotesLoaded := true;
5976 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5977
5978 if not FileExists( NotesFileName ) then
5979 // no notes
5980 exit;
5981
5982 CName := NotesFileName;
5983 rc := DosOpen( CName,
5984 NotesFile,
5985 OpenAction,
5986 0, // file size - irrelevant, not creating,
5987 0, // attrs - ''
5988 OPEN_ACTION_OPEN_IF_EXISTS,
5989 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5990 nil ); // no eas
5991 if rc <> 0 then
5992 begin
5993 DoErrorDlg( LoadNotesTitle,
5994 LoadNotesError
5995 + StrCRLF
5996 + NotesFileName
5997 + StrCRLF
5998 + SysErrorMessage( rc ) );
5999 exit;
6000 end;
6001
6002 Paragraph := TAString.Create;
6003 NoteText := TAString.Create;
6004
6005 NotEOF := true;
6006
6007 while NotEOF do
6008 begin
6009 // Read contents index
6010 NotEOF := Paragraph.ReadParagraph( NotesFile );
6011 if not NotEOF then
6012 continue;
6013 try
6014 TopicIndex := StrToInt( Paragraph.AsString );
6015 except
6016 TopicIndex := -1;
6017 end;
6018
6019 // Read insert point
6020 NotEOF := Paragraph.ReadParagraph( NotesFile );
6021 if not NotEOF then
6022 continue;
6023 try
6024 InsertPoint := StrToInt( Paragraph.AsString );
6025 except
6026 InsertPoint := -1;
6027 end;
6028
6029 NoteText.Clear;
6030
6031 while NotEOF do
6032 begin
6033 NotEOF := Paragraph.ReadParagraph( NotesFile );
6034 if Paragraph.SameAs( '#ENDNOTE#' ) then
6035 begin
6036 // found end of note
6037 if ( TopicIndex >= 0 )
6038 and ( InsertPoint >= 0 ) then
6039 begin
6040 Note := THelpNote.Create;
6041 Note.Topic := HelpFile.Topics[ TopicIndex ];
6042 Note.InsertPoint := InsertPoint;
6043
6044 // Remove the last end line
6045 Note.Text.Assign( NoteText );
6046 if Note.Text.Length > 2 then
6047 Note.Text.Delete( Note.Text.Length - 2, 2 );
6048
6049 Notes.Add( Note );
6050 end;
6051 break;
6052 end;
6053 NoteText.Add( Paragraph );
6054 NoteText.AddString( #13 + #10 );
6055 end;
6056
6057 end;
6058 DosClose( NotesFile );
6059
6060 Paragraph.Destroy;
6061 NoteText.Destroy;
6062
6063end;
6064
6065Procedure TMainForm.UpdateNotesDisplay;
6066var
6067 NoteIndex: longint;
6068 Note: THelpNote;
6069 NoteTitle: string;
6070begin
6071 NotesListBox.Clear;
6072 for NoteIndex := 0 to Notes.Count - 1 do
6073 begin
6074 Note := Notes[ NoteIndex ];
6075
6076 if Note.Topic > nil then
6077 NoteTitle := Note.Topic.Title
6078 else
6079 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6080 NotesListBox.Items.AddObject( NoteTitle,
6081 Note );
6082 end;
6083 EnableNotesControls;
6084end;
6085
6086Procedure TMainForm.EnableNotesControls;
6087var
6088 NoteSelected: boolean;
6089begin
6090 NoteSelected:= NotesListBox.ItemIndex <> -1;
6091 EditNoteButton.Enabled:= NoteSelected;
6092 GotoNoteButton.Enabled:= NoteSelected;
6093 DeleteNoteButton.Enabled:= NoteSelected;
6094 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6095end;
6096
6097Function TMainForm.OKToCloseFile: boolean;
6098begin
6099 Result := true;
6100
6101 if PrintThread = nil then
6102 // haven't used print thread yet
6103 exit;
6104
6105 if not PrintThread.IsRunning then
6106 // not currently running
6107 exit;
6108
6109 Result := DoConfirmDlg( CheckStopPrintTitle,
6110 CheckStopPrintMsg );
6111
6112end;
6113
6114Procedure TMainForm.StopPrinting;
6115begin
6116 if PrintThread <> nil then
6117 begin
6118 if PrintThread.IsRunning then
6119 begin
6120 SetStatus( StoppingPrintMsg );
6121 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6122 SetStatus( PrintStoppedMsg );
6123 ResetProgress;
6124 end;
6125 end;
6126end;
6127
6128Procedure TMainForm.CloseFile;
6129var
6130 FileIndex: longint;
6131 HelpFile: THelpFile;
6132 M1: longint;
6133begin
6134 StopPrinting;
6135
6136 LogEvent(LogShutdown, 'Set Caption' );
6137 MainTitle := '';
6138 SetMainCaption;
6139
6140 LogEvent(LogShutdown, 'Close Windows' );
6141 CloseWindows;
6142
6143 LogEvent(LogShutdown, 'Set selected node to nil' );
6144 ContentsOutline.SelectedNode:= Nil;
6145
6146 M1:= MemAvail;
6147
6148 LogEvent(LogShutdown, 'Clear contents outline' );
6149 ContentsOutline.Clear;
6150
6151 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6152 M1:= MemAvail;
6153
6154 DisplayedIndex.Clear;
6155 IndexListBox.Clear;
6156 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6157 M1:= MemAvail;
6158
6159 NotesListBox.Clear;
6160 SearchResultsListBox.Clear;
6161
6162 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6163 M1:= MemAvail;
6164
6165 // First save notes and bookmarks.
6166 // It's important we do this first
6167 // since we scan all notes each time to find the ones
6168 // belonging to this file.
6169 SaveBookmarks;
6170
6171 SaveNotes;
6172
6173 ClearAllWordSequences;
6174
6175 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6176
6177 // Now destroy help files
6178 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6179 begin
6180 HelpFile := CurrentOpenFiles[ FileIndex ];
6181 GlobalFilelist.RemoveFile( Frame.Handle,
6182 HelpFile.Filename );
6183 HelpFile.Free;
6184 end;
6185
6186 CurrentOpenFiles.Clear;
6187
6188 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6189 M1 := MemAvail;
6190
6191 LogEvent(LogShutdown, 'Clear notes' );
6192 ClearNotes;
6193
6194 LogEvent(LogShutdown, 'Clear bookmarks' );
6195 ClearBookmarks;
6196
6197 ClearPageHistory;
6198
6199 LogEvent(LogShutdown, 'Enable controls' );
6200 EnableControls;
6201
6202 LogEvent(LogShutdown, 'CloseFile done' );
6203
6204end;
6205
6206Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6207var
6208 FileIndex: longint;
6209begin
6210 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6211 begin
6212 Result:= CurrentOpenFiles[ FileIndex ];
6213 if StrEqualIgnoringCase( Result.Filename, FileName ) then
6214 // found
6215 exit;
6216 end;
6217 Result:= nil;
6218end;
6219
6220// This rather horrendous looking bit of code simply:
6221
6222// Gets the contents from each file
6223// Sorts it alphabetically.
6224// Merges all the sorted contents and indexes together,
6225// alphabetically.
6226type
6227 TListType = ( ltContents, ltIndex );
6228
6229procedure TMainForm.LoadIndex;
6230var
6231 tmpHelpFile: THelpFile;
6232 tmpTextCompareResult: integer;
6233
6234 FileIndex: longint;
6235
6236 Contents: TList;
6237 ContentsLists: TList; // of tlist
6238 tmpIndexLists: TList; // of tstringlist
6239 ContentsNextIndex: array[ 0..255 ] of longint;
6240 IndexNextIndex: array[ 0..255 ] of longint;
6241 Topic: TTopic;
6242
6243 pListEntry: pstring;
6244 pLowestEntry: pstring;
6245 pLastEntry: pstring;
6246
6247 tmpLowestEntryListIndex: longint;
6248 tmpLowestEntryListType: TListType;
6249 tmpLowestEntryTopic: TTopic;
6250
6251 tmpIndex: TStringList;
6252
6253 i : longint;
6254begin
6255 LogEvent(LogStartup, 'Create index' );
6256
6257 SetWaitCursor;
6258
6259 LogEvent(LogStartup, ' Get/sort lists' );
6260
6261 ProgressBar.Position := 70;
6262 SetStatus( 'Building index... ' );
6263
6264 ContentsLists := TList.Create;
6265 tmpIndexLists := TList.Create;
6266
6267 // collect the contents and index lists from the files
6268 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6269 begin
6270 tmpHelpFile := CurrentOpenFiles[ FileIndex ];
6271 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6272
6273 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6274 begin
6275 Contents := TList.Create;
6276 Contents.Capacity := tmpHelpFile.TopicCount;
6277
6278 // copy [contents] topic list
6279 for i := 0 to tmpHelpFile.TopicCount - 1 do
6280 begin
6281 Topic := tmpHelpFile.Topics[ i ];
6282 if Topic.ShowInContents then
6283 Contents.Add( Topic );
6284 end;
6285
6286 // sort by title
6287 Contents.Sort( TopicTitleCompare );
6288
6289 ContentsLists.Add( Contents );
6290
6291 // initialise list index
6292 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6293 end;
6294
6295 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6296 begin
6297 tmpIndexLists.Add(tmpHelpFile.Index.GetLabels);
6298 IndexNextIndex[ tmpIndexLists.Count - 1 ] := 0;
6299 end;
6300 end;
6301
6302 // Unlike contents, we do clear the index
6303 // (even if we are adding more files) because we need
6304 // to re-merge the whole thing
6305 DisplayedIndex.Clear;
6306 ProgressBar.Position := 80;
6307
6308 LogEvent(LogStartup, ' Merge lists' );
6309
6310 pLastEntry := NullStr;
6311 while true do
6312 begin
6313 pLowestEntry := NullStr;
6314 tmpLowestEntryListIndex := -1;
6315
6316 // Find alphabetically lowest (remaining) topic
6317
6318 // first, look in contents lists
6319 LogEvent(LogDebug, ' Merge contents' );
6320 for i := 0 to ContentsLists.Count - 1 do
6321 begin
6322 Contents := ContentsLists[i];
6323 if ContentsNextIndex[i] < Contents.Count then
6324 begin
6325 // list is not yet finished, get next entry
6326 Topic := Contents[ ContentsNextIndex[i] ];
6327 pListEntry := Topic.TitlePtr;
6328
6329 if pLowestEntry^ <> '' then
6330 tmpTextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6331 else
6332 tmpTextCompareResult := -1;
6333
6334 if tmpTextCompareResult < 0 then
6335 begin
6336 // this index entry comes before the lowest one so far
6337 pLowestEntry := pListEntry;
6338 tmpLowestEntryListIndex := i;
6339 tmpLowestEntryListType := ltContents;
6340 tmpLowestEntryTopic := Topic;
6341 end;
6342 end;
6343 end;
6344
6345 // look in indices
6346 LogEvent(LogDebug, ' Merge indices' );
6347 for i := 0 to tmpIndexLists.Count - 1 do
6348 begin
6349 LogEvent(LogDebug, ' Merge indices ' + IntToStr(i) );
6350 tmpIndex := tmpIndexLists[i];
6351 if IndexNextIndex[i] < tmpIndex.Count then
6352 begin
6353 // list is not yet finished, get next entry
6354 pListEntry := tmpIndex.ValuePtrs[ IndexNextIndex[i] ];
6355
6356 if pLowestEntry^ <> '' then
6357 tmpTextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6358 else
6359 tmpTextCompareResult := -1;
6360
6361 if tmpTextCompareResult < 0 then
6362 begin
6363 // this index entry comes before the lowest one so far
6364 pLowestEntry := pListEntry;
6365 tmpLowestEntryListIndex := i;
6366 tmpLowestEntryListType := ltIndex;
6367
6368 LogEvent(LogDebug, ' Merge indices ' + tmpIndex.Objects[ IndexNextIndex[i] ].ClassName);
6369 tmpLowestEntryTopic := TIndexEntry( tmpIndex.Objects[ IndexNextIndex[i] ] ).getTopic;
6370 end;
6371 end;
6372 end;
6373
6374 if tmpLowestEntryListIndex = -1 then
6375 // we're out
6376 break;
6377
6378 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6379 // add, if different from last
6380 DisplayedIndex.AddObject( pLowestEntry^, tmpLowestEntryTopic );
6381 pLastEntry := pLowestEntry;
6382
6383 if tmpLowestEntryListType = ltContents then
6384 begin
6385 inc( ContentsNextIndex[ tmpLowestEntryListIndex ] );
6386 end
6387 else
6388 begin
6389 // found in one of indices.
6390 // Check for subsequent indented strings
6391 tmpIndex := tmpIndexLists[ tmpLowestEntryListIndex ];
6392
6393 i := IndexNextIndex[ tmpLowestEntryListIndex ] + 1;
6394 while i < tmpIndex.Count do
6395 begin
6396 pListEntry := tmpIndex.ValuePtrs[ i ];
6397 if pListEntry^ = '' then
6398 break;
6399
6400 if pListEntry^[ 1 ] <> ' ' then
6401 // not indented, stop looking
6402 break;
6403
6404 // found one,
6405 Topic := TIndexEntry(tmpIndex.Objects[ i ]).getTopic;
6406 DisplayedIndex.AddObject( pListEntry^,
6407 Topic );
6408 inc( i );
6409 end;
6410 IndexNextIndex[ tmpLowestEntryListIndex ] := i;
6411 end;
6412 end;
6413
6414 ProgressBar.Position := 95;
6415 LogEvent(LogStartup, ' Display index (count = '
6416 + IntToStr( DisplayedIndex.Count )
6417 + ')' );
6418
6419 // Now display the final index list
6420 IndexListBox.Items.Assign( DisplayedIndex );
6421
6422 LogEvent(LogStartup, ' Tidy up' );
6423
6424 tmpIndexLists.Destroy;
6425
6426 DestroyListAndObjects( ContentsLists );
6427
6428 IndexLoaded := true;
6429
6430 ClearWaitCursor;
6431
6432 SetStatus( 'Index loaded' );
6433 LogEvent(LogStartup, ' Done' );
6434end;
6435
6436Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6437 message: string );
6438var
6439 ProgressOnFiles: longint;
6440 Filename: string;
6441 ProgressOnThisFile: longint;
6442
6443begin
6444 Filename := LoadingFilenameList[ LoadingFileIndex ];
6445
6446 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6447 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6448
6449 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6450 100,
6451 LoadingFileMsg
6452 + ExtractFileName( Filename )
6453 + ': '
6454 + message );
6455end;
6456
6457Procedure TMainForm.SetProgress( n, outof: integer;
6458 message: string );
6459begin
6460 ProgressBar.Position := n * 100 div outof;
6461 SetStatus( message );
6462 ProgressBar.Show;
6463end;
6464
6465// Load a single file.
6466Function TMainForm.OpenFile( const FileName: string;
6467 const WindowTitle: string;
6468 const SelectFirstContentsNode: boolean ): boolean;
6469var
6470 tmpFileNames: TStringList;
6471begin
6472 tmpFileNames := TStringList.Create;
6473 ParseAndExpandFileNames(FileName, tmpFileNames);
6474 Result := OpenFiles( tmpFileNames,
6475 WindowTitle,
6476 DisplayFirstTopic );
6477 tmpFileNames.Destroy;
6478end;
6479
6480Function TMainForm.OpenAdditionalFile( const FileName: string;
6481 const DisplayFirstTopic: boolean ): boolean;
6482var
6483 tmpFileNames: TStringList;
6484begin
6485 tmpFileNames := TStringList.Create;
6486 ParseAndExpandFileNames(FileName, tmpFileNames);
6487 Result := OpenAdditionalFiles(tmpFileNames, DisplayFirstTopic );
6488 tmpFileNames.Destroy;
6489end;
6490
6491Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6492var
6493 WinHelpDetails: PROGDETAILS;
6494 szFilename: cstring;
6495begin
6496
6497 result := true;
6498 if Settings.ConfirmWinHelp then
6499 result := DoYesNoDlg( WindowsHelpTitle,
6500 WindowsHelpPrompt
6501 + StrCRLF
6502 + FileName );
6503 if not result then
6504 exit;
6505
6506 szFilename := FileName;
6507 with WinHelpDetails do
6508 begin
6509 Length := sizeof( WinHelpDetails );
6510 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6511 progt.fbVisible := SHE_VISIBLE;
6512 pszTitle := ''; // not used?
6513 pszExecutable := 'winhelp.exe';
6514 pszParameters := Addr( szFilename );
6515 pszStartupDir := nil;
6516 pszIcon := nil;
6517 pszEnvironment := nil;
6518 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6519 end;
6520
6521 result := WinStartApp( NULLHANDLE,
6522 WinHelpDetails,
6523 '',
6524 nil,
6525 SAF_INSTALLEDCMDLINE ) <> 0;
6526
6527 // Doesn't work for Dos/Win programs
6528 // RunProgram( 'winhelp.exe', FileName );
6529end;
6530
6531// Load the specified set of help files
6532Function TMainForm.LoadFiles(const aFileNames: TStrings; aHelpFiles: TList) : boolean;
6533var
6534 HelpFile: THelpFile;
6535 FileIndex, i: longint;
6536 FileName: string;
6537 FullFilePath: string;
6538
6539 FileHandlesAdjustNum: LONG;
6540 CurrentMaxFileHandles: ULONG;
6541 RequiredFileHandles: LONG;
6542begin
6543 LogEvent(LogStartup, 'LoadFiles' );
6544
6545 LoadingFilenameList := TStringList.Create;
6546
6547// RBRi TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6548 for i := 0 to aFileNames.Count - 1 do
6549 begin
6550 LoadingFilenameList.Add(aFileNames[i]);
6551 end;
6552
6553 LogEvent(LogStartup, 'Finding files' );
6554
6555 ProgressBar.Show;
6556
6557 // now find full file paths,
6558 // and also the total file size for progress display
6559 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6560 begin
6561 FileName := LoadingFilenameList[ FileIndex ];
6562 LogEvent(LogStartup, ' File: ' + FileName );
6563
6564 // Find the help file, if possible
6565 if Filename = OWN_HELP_MARKER then
6566 begin
6567 FullFilePath := CmdLineParameters.GetOwnHelpFileName;
6568 end
6569 else
6570 begin
6571 FullFilePath := FindHelpFile( Filename );
6572 end;
6573
6574 if FullFilePath <> '' then
6575 begin
6576 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6577 end
6578 else
6579 begin
6580 LogEvent(LogStartup, ' File not found' );
6581 FullFilePath := FileName; // we'll complain later.
6582 end;
6583 LoadingFilenameList[ FileIndex ] := FullFilePath;
6584 end;
6585
6586 // Make sure we have enough file handles
6587
6588 FileHandlesAdjustNum := 0;
6589 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6590 CurrentMaxFileHandles );
6591
6592 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6593 + LoadingFilenameList.Count // new ones
6594 + 40; // some spares.
6595 if CurrentMaxFileHandles < RequiredFileHandles then
6596 begin
6597 // need some more
6598 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6599 DosSetRelMaxFH( FileHandlesAdjustNum,
6600 CurrentMaxFileHandles );
6601 end;
6602
6603 // Now actually load the files
6604 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6605 begin
6606 Filename := LoadingFilenameList[ FileIndex ];
6607 LogEvent(LogStartup, ' Loading: ' + Filename );
6608 try
6609 LoadingFileIndex := FileIndex;
6610
6611 // load the file
6612 HelpFile := THelpFile.Create( FileName );
6613 if Settings.FixedFontSubstitution then
6614 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6615
6616 aHelpFiles.Add( HelpFile );
6617
6618 except
6619 on E: Exception do
6620 begin
6621
6622 if E is EWindowsHelpFormatException then
6623 begin
6624 OpenWindowsHelp( Filename );
6625 end
6626 else
6627 begin
6628 DoErrorDlg( FileOpenTitle,
6629 HelpFileError
6630 + FileName
6631 + ': '
6632 + E.Message );
6633 end;
6634
6635 // back out of the load process
6636 Result := false;
6637
6638 DestroyListObjects( aHelpFiles );
6639
6640 LoadingFilenameList.Destroy;
6641 ResetProgress;
6642 exit;
6643 end
6644 end;
6645 end;
6646
6647 LoadingFilenameList.Destroy;
6648
6649 Result := true;
6650
6651end;
6652
6653// Add the current list of open files as
6654// a Most Recently Used entry
6655Procedure TMainForm.AddCurrentToMRUFiles;
6656var
6657 tmpFilenames: TStringList;
6658 i: longint;
6659 tmpHelpFile: THelpFile;
6660begin
6661 tmpFilenames := TStringList.Create;
6662
6663 if CurrentOpenFiles.Count > 0 then
6664 begin
6665 for i := 0 to CurrentOpenFiles.Count - 1 do
6666 begin
6667 tmpHelpFile := CurrentOpenFiles[ i ];
6668 tmpFilenames.Add(tmpHelpFile.Filename);
6669 end;
6670
6671 // update most-recently-used file list
6672 tmpHelpFile := CurrentOpenFiles[ 0 ];
6673 AddToMRUList(tmpHelpFile.Title, tmpFilenames);
6674 end;
6675
6676 // recreate menu
6677 CreateMRUMenuItems;
6678
6679 tmpFilenames.Destroy;
6680end;
6681
6682// Display the specified set of files
6683Procedure TMainForm.DisplayFiles( NewFiles: TList;
6684 Var FirstContentsNode: TNode );
6685var
6686 HelpFile: THelpFile;
6687 FileIndex: longint;
6688begin
6689 LogEvent(LogStartup, 'DisplayFiles' );
6690 // Now load the various parts of the file(s)
6691 // into the user interface
6692 ProgressBar.Position := 50;
6693 SetStatus( LoadingStatusDisplaying );
6694
6695 // Add our open files in the global filelist
6696 for FileIndex := 0 to NewFiles.Count - 1 do
6697 begin
6698 HelpFile := NewFiles[ FileIndex ];
6699 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6700 // LoadNotes( HelpFile );
6701 LoadBookmarks( HelpFile );
6702 end;
6703
6704 UpdateNotesDisplay;
6705
6706 BuildBookmarksMenu;
6707 UpdateBookmarksForm;
6708
6709 ProgressBar.Position := 55;
6710
6711 ContentsLoaded := false;
6712 IndexLoaded := false;
6713
6714 LoadContents( NewFiles, FirstContentsNode );
6715
6716 ProgressBar.Position := 75;
6717
6718 // LoadIndex;
6719
6720 ProgressBar.Position := 100;
6721 SetStatus( LoadingStatusDone );
6722
6723 LogEvent(LogStartup, 'DisplayFiles Done' );
6724
6725end;
6726
6727Function TMainForm.OpenFiles( const FileNames: TStrings;
6728 const WindowTitle: string;
6729 const DisplayFirstTopic: boolean ): boolean;
6730var
6731 tmpHelpFiles: TList;
6732 FirstContentsNode: TNode;
6733begin
6734 LogEvent(LogStartup, 'OpenFiles' );
6735
6736 if not OKToCloseFile then
6737 exit;
6738
6739 SetWaitCursor;
6740
6741 tmpHelpFiles := TList.Create;
6742
6743// RBRi Translate
6744 if not LoadFiles(FileNames, tmpHelpFiles) then
6745 begin
6746 ClearWaitCursor;
6747 tmpHelpFiles.Destroy;
6748 exit;
6749 end;
6750
6751 Result := true;
6752
6753 SearchResultsListBox.Clear;
6754 PageHistory.Clear;
6755 CurrentHistoryIndex := -1;
6756
6757 // Now that we have successfully loaded the new help file(s)
6758 // close the existing one.
6759 CloseFile;
6760
6761 AssignList(tmpHelpFiles, CurrentOpenFiles );
6762
6763 ProgressBar.Position := 50;
6764 SetStatus( LoadingStatusDisplaying );
6765
6766 AddCurrentToMRUFiles;
6767
6768 if WindowTitle = '' then
6769 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6770 else
6771 MainTitle := WindowTitle;
6772
6773 SetMainCaption;
6774
6775 // Now load the various parts of the file(s)
6776 // into the user interface
6777
6778 ContentsOutline.Clear;
6779
6780 DisplayFiles( tmpHelpFiles,
6781 FirstContentsNode );
6782
6783 if CmdLineParameters.getHelpManagerFlag then
6784 ShowLeftPanel := Settings.ShowLeftPanel_Help
6785 else
6786 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6787
6788 // Select first contents node if there is one
6789 if FirstContentsNode <> nil then
6790 begin
6791 LogEvent(LogStartup, ' Select first node' );
6792 ContentsOutline.SelectedNode := FirstContentsNode;
6793 end;
6794
6795 ClearWaitCursor;
6796
6797 ResetProgress;
6798
6799 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6800
6801 EnableControls;
6802
6803 if DisplayFirstTopic then
6804 begin
6805 LogEvent(LogStartup, 'Display first topic' );
6806 DisplaySelectedContentsTopic;
6807 end;
6808
6809 LogEvent(LogStartup, 'OpenFiles complete' );
6810end;
6811
6812Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6813 const DisplayFirstTopic: boolean ): boolean;
6814var
6815 HelpFiles: TList;
6816 FirstNewContentsNode: TNode;
6817begin
6818 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6819
6820 if not OKToCloseFile then
6821 exit;
6822
6823 SetWaitCursor;
6824
6825 HelpFiles := TList.Create;
6826
6827 if not LoadFiles( FileNames,
6828 HelpFiles ) then
6829 begin
6830 ClearWaitCursor;
6831 HelpFiles.Destroy;
6832 exit;
6833 end;
6834
6835 Result := true;
6836
6837 AddList( HelpFiles, CurrentOpenFiles );
6838
6839 AddCurrentToMRUFiles;
6840
6841 DisplayFiles( HelpFiles,
6842 FirstNewContentsNode );
6843
6844 // Select first contents node of new file
6845 if FirstNewContentsNode <> nil then
6846 ContentsOutline.SelectedNode := FirstNewContentsNode;
6847
6848 HelpFiles.Destroy;
6849
6850 ClearWaitCursor;
6851
6852 ResetProgress;
6853
6854 EnableControls;
6855
6856 if DisplayFirstTopic then
6857 DisplaySelectedContentsTopic;
6858
6859 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6860end;
6861
6862Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6863Begin
6864 FileOpen;
6865end;
6866
6867procedure TMainForm.FileOpen;
6868var
6869 Filenames: TStringList;
6870 KeepCurrentFiles: boolean;
6871 OpenedOK: boolean;
6872begin
6873 if not OKToCloseFile then
6874 exit;
6875
6876 if Settings.UseOriginalDialogs then
6877 begin
6878 SystemOpenDialog.Filename := AddDirectorySeparator( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6879 if not SystemOpenDialog.Execute then
6880 exit;
6881
6882 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6883 // note - sibyl's encapsulation doesn't allow multi-select
6884 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6885 end
6886 else
6887 begin
6888 Filenames := TStringList.Create;
6889 KeepCurrentFiles := false;
6890 if not DoOpenMultiFileDialog( FileOpenTitle,
6891 HelpFilesDesc
6892 + '|*.inf;*.hlp|'
6893 + AllFilesDesc
6894 + '|*.*',
6895 '*.hlp;*.inf',
6896 Settings.LastOpenDirectory,
6897 KeepCurrentFiles,
6898 Filenames ) then
6899 exit;
6900
6901 // no ParseAndExpandFileNames call required here
6902 // this is the result of a file dialog
6903 // no environment vars here
6904 if KeepCurrentFiles then
6905 OpenedOK := OpenAdditionalFiles( FileNames, true )
6906 else
6907 OpenedOK := OpenFiles( FileNames, '', true );
6908 Filenames.Destroy;
6909 end;
6910
6911 if OpenedOK then
6912 ClearHelpManager;
6913End;
6914
6915Procedure TMainForm.CloseWindows;
6916Begin
6917 DestroyListObjects( Windows );
6918 Windows.Clear;
6919end;
6920
6921// Help manager mode
6922
6923// if window is minimised then restore it
6924// (ideally should go back to maximized - don't know how)
6925Procedure TMainForm.RestoreWindow;
6926Begin
6927 If WindowState = wsMinimized then
6928 WindowState := wsNormal;
6929end;
6930
6931
6932Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6933begin
6934 LogEvent(LogNHM, 'NHMDisplayIndex');
6935 CmdLineParameters.addNhmDebugMessage('NHMDisplayIndex');
6936 RestoreWindow;
6937 DisplayIndex;
6938 // if nothing is being display already...
6939 if Windows.Count = 0 then
6940 // display first topic
6941 DisplaySelectedContentsTopic;
6942end;
6943
6944Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6945begin
6946 LogEvent(LogNHM, 'NHMDisplayContents');
6947 CmdLineParameters.addNhmDebugMessage('NHMDisplayContents');
6948 RestoreWindow;
6949 DisplayContents;
6950 // if nothing is being display already...
6951 if Windows.Count = 0 then
6952 begin
6953 // display first topic
6954 DisplaySelectedContentsTopic;
6955 end;
6956end;
6957
6958Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6959begin
6960 LogEvent(LogNHM, 'NHMTopicByResourceID');
6961 RestoreWindow;
6962 if ShowLeftPanel then
6963 begin
6964 DisplayContents;
6965 end;
6966 CmdLineParameters.addNhmDebugMessage('NHMTopicByResourceID ' + IntToStr(Msg.Param1));
6967 DisplayTopicByResourceID( Msg.Param1 );
6968end;
6969
6970Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6971var
6972 pMessageMem: pchar;
6973 PanelName: string;
6974 Topic: TTopic;
6975begin
6976 LogEvent(LogNHM, 'NHMTopicByPanelName');
6977 RestoreWindow;
6978 if ShowLeftPanel then
6979 DisplayContents;
6980
6981 pMessageMem := pchar( Msg.Param1 );
6982 PanelName := StrPas( pMessageMem );
6983 SharedMemory.Free( pMessageMem );
6984
6985 LogEvent(LogNHM, '....NHMTopicByPanelName panel:' + PanelName);
6986 CmdLineParameters.addNhmDebugMessage('NHMTopicByPanelName ' + PanelName);
6987 Topic := FindTopicByName( PanelName );
6988 if Topic = nil then
6989 Topic := FindTopicByGlobalName( PanelName );
6990
6991 if Topic <> nil then
6992 DisplayTopic( Topic )
6993 else
6994 SearchFor( PanelName );
6995end;
6996
6997// Sent from other instances starting up (and exiting immediately)
6998
6999Procedure TMainForm.NHMSearch( Var Msg: TMessage );
7000var
7001 pSearchText: pchar;
7002 tmpSearchText : String;
7003begin
7004 LogEvent(LogNHM, 'NHMSearch');
7005 RestoreWindow;
7006
7007 pSearchText := pstring( Msg.Param1 );
7008 tmpSearchText := StrPas(pSearchText);
7009 CmdLineParameters.addNhmDebugMessage('NHMSearch ' + tmpSearchText);
7010 SearchFor(tmpSearchText);
7011 SharedMemory.Free( pSearchText );
7012end;
7013
7014Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
7015var
7016 pSearchText: pchar;
7017 tmpSearchText : String;
7018begin
7019 LogEvent(LogNHM, 'NHMGlobalSearch');
7020 RestoreWindow;
7021
7022 pSearchText := pstring( Msg.Param1 );
7023 tmpSearchText := StrPas(pSearchText);
7024 CmdLineParameters.addNhmDebugMessage('NHMGlobalSearch ' + tmpSearchText);
7025 DoGlobalSearch(tmpSearchText);
7026 SharedMemory.Free( pSearchText );
7027end;
7028
7029Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
7030begin
7031 LogEvent(LogNHM, 'NHMShowUsage');
7032 CmdLineParameters.addNhmDebugMessage('NHMShowUsage');
7033 RestoreWindow;
7034 ShowUsage;
7035end;
7036
7037Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
7038var
7039 pFileNames: pchar;
7040 tmpFileNames : String;
7041begin
7042 LogEvent(LogNHM, 'NHMSetFiles');
7043
7044 // NOT restoring window here because this is not something the user should see...
7045 pFileNames := pstring( Msg.Param1 );
7046 tmpFileNames := StrPas(pFileNames);
7047 CmdLineParameters.addNhmDebugMessage('NHMSetFiles ' + tmpFileNames);
7048 OpenFilesFromTextList(tmpFileNames, false);
7049 SharedMemory.Free( pFileNames );
7050end;
7051
7052Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
7053var
7054 pTitle: pchar;
7055begin
7056 LogEvent(LogNHM, 'NHMSetTitle');
7057
7058 pTitle := pstring( Msg.Param1 );
7059 MainTitle := StrPas( pTitle );
7060 SharedMemory.Free( pTitle );
7061 CmdLineParameters.addNhmDebugMessage('NHMSetTitle ' + MainTitle);
7062 SetMainCaption;
7063end;
7064
7065Procedure TMainForm.NHMTest( Var Msg: TMessage );
7066var
7067 ps: pstring;
7068begin
7069 LogEvent(LogNHM, 'NHMTest');
7070 ps := PString( Msg.Param1 );
7071 ShowMessage( 'Got test message: ' + ps^ );
7072 SharedMemory.Free( ps );
7073end;
7074
7075Initialization
7076 RegisterClasses ([TMainForm, TSplitBar,
7077 TNoteBook,
7078 TEdit, TListBox,
7079 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
7080 TImageList, TPanel, TButton,
7081 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
7082 , TProgressBar, TTabSet2]);
7083End.
Note: See TracBrowser for help on using the repository browser.