source: trunk/NewView/MainForm.pas@ 343

Last change on this file since 343 was 342, checked in by RBRi, 16 years ago

index is a real object now
support for env variables to make glossary simulation work

  • 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-2007 Ronald Brill (rbri at rbri dot de)
6// This software is released under the Gnu Public License - see readme.txt
7
8Interface
9
10Uses
11// system is a good unit to be able to open ;)
12// the above line is here so you can use right-mouse open file on "system"
13 OS2Def,
14 SysUtils,
15 Classes,
16 Forms,
17 Graphics,
18 Messages,
19 Buttons,
20 ComCtrls,
21 StdCtrls,
22 ExtCtrls,
23 TabCtrls,
24 Dialogs,
25
26// library
27 ACLString,
28 SharedMemoryUnit,
29 ACLLanguageUnit,
30 GenericThread,
31 CmdLineParameterUnit,
32
33// custom components
34 SplitBar,
35 Outline2,
36 RichTextView,
37 Coolbar2,
38 CustomListBox,
39
40// local
41 HelpFile,
42 HelpTopic,
43 HelpWindowUnit,
44 HelpWindowDimensions,
45 NavigatePointUnit,
46 MiscUnit,
47 HelpManagerUnit,
48 TextSearchQuery,
49 IPFFileFormatUnit,
50 Tabset2Unit;
51
52const
53 // Custom window messages for this form
54 // NOTE! Sibyl uses WM_USER+1 and +2!
55 WM_OPENED = WM_USER + 10;
56 WM_FOLLOWLINK = WM_USER + 11;
57 WM_FOLLOWEXTERNALLINK = WM_USER + 12;
58
59 MAIN_WINDOW_CLASS_NAME = 'NewViewMainForm';
60
61Type
62
63 TMainForm = Class (TForm)
64 VSplitBar: TSplitBar;
65 Notebook: TNoteBook;
66 IndexSearchEdit: TEdit;
67 SearchTextEdit: TEdit;
68 SearchResultsListBox: TListBox;
69 NotesListBox: TListBox;
70 CoolBar: TCoolBar2;
71 MenuItem21: TMenuItem;
72 SaveAsIPFMI: TMenuItem;
73 MenuItem20: TMenuItem;
74 DebugFindBinaryMI: TMenuItem;
75 TopicByNameMI: TMenuItem;
76 DebugTopicByResourceIDMI: TMenuItem;
77 ToolsDebugSep: TMenuItem;
78 DebugSaveLanguageFileMI: TMenuItem;
79 DebugLoadLanguageMI: TMenuItem;
80 TabSet: TTabSet2;
81 NavigateNextMI: TMenuItem;
82 ShowLeftPanelMI: TMenuItem;
83 MenuItem18: TMenuItem;
84 AddNoteButton: TButton;
85 EditNoteButton: TButton;
86 DeleteNoteButton: TButton;
87 GotoNoteButton: TButton;
88 MenuItem23: TMenuItem;
89 MenuItem24: TMenuItem;
90 MenuItem25: TMenuItem;
91 DebugHelpManagerVersionMI: TMenuItem;
92 MenuItem19: TMenuItem;
93 ViewHighlightSearchWordsMI: TMenuItem;
94 MenuItem17: TMenuItem;
95 MenuItem16: TMenuItem;
96 MenuItem15: TMenuItem;
97 FileNewWindowMI: TMenuItem;
98 OpenSpecialMI: TMenuItem;
99 MenuItem14: TMenuItem;
100 SearchPMI: TMenuItem;
101 ViewSourceMI: TMenuItem;
102 FileCloseMI: TMenuItem;
103 MenuItem10: TMenuItem;
104 MenuItem12: TMenuItem;
105 MenuItem13: TMenuItem;
106 StatusPanel: TPanel;
107 ProgressPanel: TPanel;
108 ProgressBar: TProgressBar;
109 DebugShowWordSeparatorsMI: TMenuItem;
110 DebugStressTestMI: TMenuItem;
111 TopicPropertiesPMI: TMenuItem;
112 MenuItem3: TMenuItem;
113 MenuItem2: TMenuItem;
114 MenuItem8: TMenuItem;
115 ToolsOptionsMI: TMenuItem;
116 MenuItem9: TMenuItem;
117 ToolsDebugMenu: TMenuItem;
118 DebugShowParamsMI: TMenuItem;
119 DebugShowCodesMI: TMenuItem;
120 EditGlobalSearchMI: TMenuItem;
121 ViewExpandAllMI: TMenuItem;
122 EditBookmarksMI: TMenuItem;
123 AddBookmarkMI: TMenuItem;
124 ViewPopupMenu: TPopupMenu;
125 SelectAllPMI: TMenuItem;
126 CopyPMI: TMenuItem;
127 ContentsOutline: TOutline2;
128 IndexListBox: TCustomListBox;
129 ViewCollapseAllMI: TMenuItem;
130 MenuItem7: TMenuItem;
131 SystemOpenDialog: TSystemOpenDialog;
132 SearchButton: TButton;
133 MenuItem1: TMenuItem;
134 ViewIndexMI: TMenuItem;
135 ViewContentsMI: TMenuItem;
136 ViewSearchMI: TMenuItem;
137 ViewNotesMI: TMenuItem;
138 ViewRefreshMI: TMenuItem;
139 MenuItem11: TMenuItem;
140 DisplayPanel: TPanel;
141 ButtonImages: TImageList;
142 BookmarksMenu: TMenuItem;
143 MainMenu: TMainMenu;
144 FileMenu: TMenuItem;
145 OpenMI: TMenuItem;
146 FileSaveAsMI: TMenuItem;
147 PrintMI: TMenuItem;
148 FileInformationMI: TMenuItem;
149 MenuItem4: TMenuItem;
150 ExitMI: TMenuItem;
151 EditMenu: TMenuItem;
152 SelectAllMI: TMenuItem;
153 CopyMI: TMenuItem;
154 MenuItem5: TMenuItem;
155 FindMI: TMenuItem;
156 FindNextMI: TMenuItem;
157 NavigateMenu: TMenuItem;
158 NavigateBackMI: TMenuItem;
159 NavigateForwardMI: TMenuItem;
160 MenuItem6: TMenuItem;
161 NavigatePreviousMI: TMenuItem;
162 ToolsMenu: TMenuItem;
163 GlobalSearchMI: TMenuItem;
164 HelpMenu: TMenuItem;
165 HelpMI: TMenuItem;
166 HelpProductInformationMI: TMenuItem;
167 AddNoteMI: TMenuItem;
168
169 Procedure SaveAsIPFMIOnClick (Sender: TObject);
170 Procedure DebugFindBinaryMIOnClick (Sender: TObject);
171 Procedure TopicByNameMIOnClick (Sender: TObject);
172 Procedure CopyLinkLocationPMIOnClick (Sender: TObject);
173 Procedure HelpKeysMIOnClick (Sender: TObject);
174 Procedure MainFormOnCommand (Sender: TObject; Var Command: TCommand);
175 Procedure MainFormOnScan (Sender: TObject; Var KeyCode: TKeyCode);
176 Procedure ShowLeftPanelMIOnClick (Sender: TObject);
177 Procedure CoolBarOnFontChange (Sender: TObject);
178 Procedure NotebookOnFontChange (Sender: TObject);
179 Procedure TabSetOnFontChange (Sender: TObject);
180 Procedure IndexListBoxOnFontChange (Sender: TObject);
181 Procedure NotesListBoxOnFontChange (Sender: TObject);
182 Procedure DisplayPanelOnFontChange (Sender: TObject);
183 Procedure ContentsOutlineOnFontChange (Sender: TObject);
184 Procedure SearchResultsListBoxOnFontChange (Sender: TObject);
185 Procedure DisplayPanelOnDragOver (Sender: TObject; Source: TObject;
186 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
187 Procedure NotesListBoxOnDragOver (Sender: TObject; Source: TObject;
188 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
189 Procedure DisplayPanelOnDragDrop (Sender: TObject; Source: TObject;
190 X: LongInt; Y: LongInt);
191 Procedure NotesListBoxOnDragDrop (Sender: TObject; Source: TObject;
192 X: LongInt; Y: LongInt);
193 Procedure SearchResultsListBoxOnDragDrop (Sender: TObject; Source: TObject;
194 X: LongInt; Y: LongInt);
195 Procedure SearchResultsListBoxOnDragOver (Sender: TObject; Source: TObject;
196 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
197 Procedure IndexListBoxOnDragDrop (Sender: TObject; Source: TObject;
198 X: LongInt; Y: LongInt);
199 Procedure IndexListBoxOnDragOver (Sender: TObject; Source: TObject;
200 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
201 Procedure ContentsOutlineOnDragOver (Sender: TObject; Source: TObject;
202 X: LongInt; Y: LongInt; State: TDragState; Var Accept: Boolean);
203 Procedure ContentsOutlineOnDragDrop (Sender: TObject; Source: TObject;
204 X: LongInt; Y: LongInt);
205 Procedure MainFormOnDragOver (Sender: TObject; Source: TObject; X: LongInt;
206 Y: LongInt; State: TDragState; Var Accept: Boolean);
207 Procedure MainFormOnDragDrop (Sender: TObject; Source: TObject; X: LongInt;
208 Y: LongInt);
209 Procedure ContentsOutlineOnItemClick (Node: TNode);
210 Procedure DebugLoadLanguageMIOnClick (Sender: TObject);
211 Procedure DebugSaveLanguageFileMIOnClick (Sender: TObject);
212 Procedure SearchResultsListBoxOnClick (Sender: TObject);
213 Procedure VSplitBarOnDblClick (Sender: TObject);
214 Procedure DebugHelpManagerVersionMIOnClick (Sender: TObject);
215 Procedure DebugTopicByResourceIDMIOnClick (Sender: TObject);
216 Procedure ViewHighlightSearchWordsMIOnClick (Sender: TObject);
217 Procedure FileNewWindowMIOnClick (Sender: TObject);
218 Procedure OpenSpecialMIOnClick (Sender: TObject);
219 Procedure NotesListBoxOnScan (Sender: TObject; Var KeyCode: TKeyCode);
220 Procedure ViewPopupMenuOnPopup (Sender: TObject);
221 Procedure SearchPMIOnClick (Sender: TObject);
222 Procedure ViewSourceMIOnClick (Sender: TObject);
223 Procedure PrintMIOnClick (Sender: TObject);
224 Procedure DebugShowWordSeparatorsMIOnClick (Sender: TObject);
225 Procedure DebugStressTestMIOnClick (Sender: TObject);
226 Procedure TopicPropertiesPMIOnClick (Sender: TObject);
227 Procedure NavigateForwardMIOnClick (Sender: TObject);
228 Procedure IndexListBoxOnScan (Sender: TObject; Var KeyCode: TKeyCode);
229 Procedure SearchResultsListBoxOnScan (Sender: TObject;
230 Var KeyCode: TKeyCode);
231 Procedure ContentsOutlineOnScan (Sender: TObject; Var KeyCode: TKeyCode);
232 Procedure ToolsOptionsMIOnClick (Sender: TObject);
233 Procedure EditGlobalSearchMIOnClick (Sender: TObject);
234 Procedure DebugShowParamsMIOnClick (Sender: TObject);
235 Procedure ViewExpandAllMIOnClick (Sender: TObject);
236 Procedure EditBookmarksMIOnClick (Sender: TObject);
237 Procedure CopyPMIOnClick (Sender: TObject);
238 Procedure SelectAllPMIOnClick (Sender: TObject);
239 Procedure AddNoteButtonOnClick (Sender: TObject);
240 Procedure SearchTextEditOnChange (Sender: TObject);
241 Procedure IndexListBoxOnClick (Sender: TObject);
242 Procedure ViewCollapseAllMIOnClick (Sender: TObject);
243 Procedure NotesListBoxOnDblClick (Sender: TObject);
244 Procedure HelpMIOnClick (Sender: TObject);
245 Procedure NotebookOnPageChanged (Sender: TObject);
246 Procedure ViewRefreshMIOnClick (Sender: TObject);
247 Procedure ViewNotesMIOnClick (Sender: TObject);
248 Procedure ViewSearchMIOnClick (Sender: TObject);
249 Procedure ViewIndexMIOnClick (Sender: TObject);
250 Procedure ViewContentsMIOnClick (Sender: TObject);
251 Procedure MainFormOnCloseQuery (Sender: TObject; Var CanClose: Boolean);
252 Procedure GlobalSearchMIOnClick (Sender: TObject);
253 Procedure GotoNoteButtonOnClick (Sender: TObject);
254 Procedure EditNoteButtonOnClick (Sender: TObject);
255 Procedure NotesListBoxOnItemFocus (Sender: TObject; Index: LongInt);
256 Procedure DeleteNoteButtonOnClick (Sender: TObject);
257 Procedure AddBookmarkMIOnClick (Sender: TObject);
258 Procedure AddNoteMIOnClick (Sender: TObject);
259 Procedure FileCloseMIOnClick (Sender: TObject);
260 Procedure CoolBarOnSectionResize (HeaderControl: THeaderControl;
261 section: THeaderSection);
262 Procedure CoolBarOnSectionClick (HeaderControl: THeaderControl;
263 section: THeaderSection);
264 Procedure MainFormOnDestroy (Sender: TObject);
265 Procedure MainFormOnSetupShow (Sender: TObject);
266 Procedure MainFormOnCreate (Sender: TObject);
267 Procedure MainFormOnShow (Sender: TObject);
268 Procedure FindNextMIOnClick (Sender: TObject);
269 Procedure FindMIOnClick (Sender: TObject);
270 Procedure IndexSearchEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
271 Procedure IndexSearchEditOnChange (Sender: TObject);
272 Procedure FileInformationMIOnClick (Sender: TObject);
273 Procedure SearchTextEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
274 Procedure SearchButtonOnClick (Sender: TObject);
275 Procedure FileSaveAsMIOnClick (Sender: TObject);
276 Procedure OptionsMIOnClick (Sender: TObject);
277 Procedure TabSetOnChange (Sender: TObject; NewTab: LongInt;
278 Var AllowChange: Boolean);
279 Procedure NotebookOnSetupShow (Sender: TObject);
280 Procedure NavigateBackMIOnClick (Sender: TObject);
281 Procedure NavigatePreviousMIOnClick (Sender: TObject);
282 Procedure NavigateNextMIOnClick (Sender: TObject);
283 Procedure CopyMIOnClick (Sender: TObject);
284 Procedure SelectAllMIOnClick (Sender: TObject);
285 Procedure DebugShowCodesMIOnClick (Sender: TObject);
286 Procedure HelpProductInformationMIOnClick (Sender: TObject);
287 Procedure OnOverLink ( Sender: TRichTextView; LinkString: String);
288 Procedure OnNotOverLink ( Sender: TRichTextView; LinkString: String);
289 Procedure OnClickLink ( Sender: TRichTextView; LinkString: String);
290 Procedure BackButtonOnClick (Sender: TObject);
291 Procedure RTViewOnSetupShow (Sender: TObject);
292 Procedure OpenMIOnClick (Sender: TObject);
293 Procedure ExitMIOnClick (Sender: TObject);
294
295 Procedure MainFormOnResize (Sender: TObject);
296 Procedure VSplitBarOnChange (NewSplit: LongInt);
297 Protected
298 // Custom window messages ----------------------------------
299
300 // Handle our own WM_OPENED message
301 Procedure WMOpened( Var Msg: TMessage ); Message WM_OPENED;
302 Procedure WMFollowLink( Var Msg: TMessage ); Message WM_FOLLOWLINK;
303 Procedure WMFollowExternalLink( Var Msg: TMessage ); Message WM_FOLLOWEXTERNALLINK;
304
305 // Messages from new help manager OR other instances
306 Procedure NHMDisplayIndex( Var Msg: TMessage ); Message NHM_HELP_INDEX;
307 Procedure NHMDisplayContents( Var Msg: TMessage ); Message NHM_HELP_CONTENTS;
308 Procedure NHMTopicByResourceID( Var Msg: TMessage ); Message NHM_TOPIC_BY_RESOURCE_ID;
309 Procedure NHMTopicByPanelName( Var Msg: TMessage ); Message NHM_TOPIC_BY_PANEL_NAME;
310
311 Procedure NHMTest( Var Msg: TMessage ); Message NHM_TEST;
312
313 Procedure NHMSearch( Var Msg: TMessage ); Message NHM_SEARCH;
314 Procedure NHMGlobalSearch( Var Msg: TMessage ); Message NHM_GLOBAL_SEARCH;
315 Procedure NHMShowUsage( Var Msg: TMessage ); Message NHM_SHOW_USAGE;
316
317 Procedure NHMSetFiles( Var Msg: TMessage ); Message NHM_SET_FILES;
318 Procedure NHMSetTitle( Var Msg: TMessage ); Message NHM_SET_TITLE;
319
320 Protected
321 // GUI events set by code ----------------------------------
322
323 Procedure OnHint( Sender: TObject );
324 Procedure OnWindowClose( Window: THelpWindow );
325 Procedure OnWindowAboutToClose( Window: THelpWindow;
326 var CanClose: boolean );
327 Procedure OnNavigateToMenuItemClick( Sender: TObject );
328 Procedure OnDragOverWindow( Sender: TObject;
329 Source: TObject;
330 X: LongInt;
331 Y: LongInt;
332 State: TDragState;
333 Var Accept: Boolean );
334 Procedure OnDragDropToWindow( Sender: TObject;
335 Source: TObject;
336 X: LongInt;
337 Y: LongInt );
338 Procedure OnWindowFontChange( Sender: TObject );
339 Procedure OnWindowTab( Sender: TObject );
340 Procedure OnWindowBackTab( Sender: TObject );
341
342 Procedure OnException( Sender: TObject;
343 E: Exception );
344 Procedure OnHelp( context: THelpContext;
345 var Result: Boolean );
346
347
348 FShowLeftPanel: boolean;
349
350 Function GetShowLeftPanel: boolean;
351 Procedure SetShowLeftPanel( Value: boolean );
352 Property ShowLeftPanel: boolean read GetShowLeftPanel write SetShowLeftPanel;
353
354 Procedure ShowTab( TabIndex: longint );
355
356 procedure GetClassData(var ClassData: TClassData); override;
357 Public
358
359 // Open the file or list of files in FileNames
360 // Set the window title if given, otherwise get it from first file
361 Function OpenFiles( const FileNames: TStrings;
362 const WindowTitle: string;
363 const DisplayFirstTopic: boolean ): boolean;
364
365 // Open a single file
366 Function OpenFile( const FileName: string;
367 const WindowTitle: string;
368 const DisplayFirstTopic: boolean ): boolean;
369
370 Function OpenAdditionalFiles( const FileNames: TStrings;
371 const DisplayFirstTopic: boolean ): boolean;
372
373 Function OpenAdditionalFile( const FileName: string;
374 const DisplayFirstTopic: boolean ): boolean;
375
376 // open from original helpmgr style file1+file2+file3. ..
377 Function OpenFilesFromTextList( const TextList: string;
378 const DisplayFirstTopic: boolean ): boolean;
379
380 Procedure CloseFile;
381 Function OKToCloseFile: boolean;
382
383 Procedure AddCurrentToMRUFiles;
384
385 Function LoadFiles(const 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
3023 + IntToStr( Topic.Index ) );
3024
3025 Navigating:= true;
3026
3027 if ContentsOutline.SelectedNode = nil then
3028 ContentsOutline.SetSelectedObject( Topic )
3029 else if ContentsOutline.SelectedNode.Data <> Topic then
3030 ContentsOutline.SetSelectedObject( Topic );
3031
3032 SaveNavigatePoint;
3033
3034 Navigating:= false;
3035 // find in index...
3036 // find in search results...
3037
3038 EnableControls;
3039
3040 ShowWindows;
3041
3042// if Windows.Count > 0 then
3043// THelpWindow( Windows[ 0 ] ).View.Focus;
3044
3045end;
3046
3047// Make the all current help windows visible
3048Procedure TMainForm.ShowWindows;
3049begin
3050 ShowWindowList( Windows );
3051end;
3052
3053// Make the specified windows visible
3054Procedure TMainForm.ShowWindowList( WindowList: TList );
3055var
3056 i: integer;
3057 Window: THelpWindow;
3058begin
3059 for i := 0 to WindowList.Count - 1 do
3060 begin
3061 Window:= WindowList[ i ];
3062 Window.Show;
3063 ShowWindowList( Window.ChildWindows );
3064 end;
3065end;
3066
3067// Global search -----------------------------------------------------------
3068
3069Procedure TMainForm.GlobalSearchMIOnClick (Sender: TObject);
3070begin
3071 DoGlobalSearch( '' );
3072end;
3073
3074Procedure TMainForm.DoGlobalSearch( const SearchText: string );
3075Begin
3076 EnsureGlobalSearchFormLoaded;
3077
3078 GlobalSearchForm.ViewTopicCallback:= OnViewGlobalSearchTopic;
3079 GlobalSearchForm.Show;
3080 WinSetOwner( GlobalSearchForm.Frame.Handle, Frame.Handle );
3081
3082 if SearchText <> '' then
3083 begin
3084 GlobalSearchForm.SearchTextEdit.Text := SearchText;
3085 GlobalSearchForm.DoSearch;
3086 end;
3087End;
3088
3089Procedure TMainForm.OnViewGlobalSearchTopic( FileName: string;
3090 TopicIndex: longint );
3091var
3092 HelpFile: THelpFile;
3093begin
3094 HelpFile:= FindOpenHelpFile( FileName );
3095
3096 if HelpFile = nil then
3097 begin
3098 if OpenFile( Filename, '', false ) then
3099 begin
3100 HelpFile := CurrentOpenFiles[ 0 ];
3101 ClearHelpManager;
3102 end;
3103 end;
3104
3105 if HelpFile <> nil then
3106 if TopicIndex <> -1 then
3107 DisplayTopic( HelpFile.Topics[ TopicIndex ] );
3108
3109end;
3110
3111// Notes -----------------------------------------------------------
3112
3113Procedure TMainForm.GotoNoteButtonOnClick (Sender: TObject);
3114begin
3115 GotoCurrentNote;
3116end;
3117
3118Procedure TMainForm.EditNoteButtonOnClick (Sender: TObject);
3119Begin
3120 if NotesListBox.ItemIndex = -1 then
3121 exit;
3122 EditNote( NotesListBox.ItemIndex );
3123End;
3124
3125Procedure TMainForm.NotesListBoxOnItemFocus (Sender: TObject; Index: LongInt);
3126var
3127 Note: THelpNote;
3128Begin
3129 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3130 EnableNotesControls;
3131End;
3132
3133Procedure TMainForm.DeleteNoteButtonOnClick (Sender: TObject);
3134Begin
3135 if NotesListBox.ItemIndex = -1 then
3136 exit;
3137 DeleteNote( NotesListBox.ItemIndex );
3138End;
3139
3140Procedure TMainForm.AddBookmarkMIOnClick (Sender: TObject);
3141Begin
3142 AddBookmark;
3143End;
3144
3145Procedure TMainForm.AddNoteMIOnClick (Sender: TObject);
3146Begin
3147 AddNote;
3148End;
3149
3150// -----------------------------------------------------------
3151
3152Procedure TMainForm.FileCloseMIOnClick (Sender: TObject);
3153Begin
3154 if not OKToCloseFile then
3155 exit;
3156
3157 CloseFile;
3158End;
3159
3160Procedure TMainForm.SetStatus( Text: String );
3161begin
3162 StatusPanel.Caption:= Text;
3163 StatusPanel.Refresh;
3164end;
3165
3166Procedure TMainForm.ResetProgress;
3167begin
3168 ProgressBar.Position:= 0;
3169 ProgressBar.Hide;
3170end;
3171
3172Procedure TMainForm.CoolBarOnSectionResize (HeaderControl: THeaderControl;
3173 section: THeaderSection);
3174Begin
3175
3176End;
3177
3178Procedure TMainForm.CoolBarOnSectionClick (HeaderControl: THeaderControl;
3179 section: THeaderSection);
3180Begin
3181 case Section.Index of
3182 ciOpen:
3183 FileOpen;
3184 ciPrint:
3185 PrintTopics;
3186 ciNavigator:
3187 ShowLeftPanel := not ShowLeftPanel;
3188 ciBack:
3189 NavigateBack;
3190 ciForward:
3191 NavigateForward;
3192 ciAddNote:
3193 AddNote;
3194 ciAddBookmark:
3195 AddBookmark;
3196 ciPrevious:
3197 NavigatePreviousInContents;
3198 ciNext:
3199 NavigateNextInContents;
3200 ciGlobalSearch:
3201 DoGlobalSearch( '' );
3202 end;
3203
3204End;
3205
3206// ---------------- Notes ----------------------
3207
3208function TMainForm.FindOriginalNoteCharIndex( NoteCharIndex: longword;
3209 Topic: TTopic ): longword;
3210var
3211 NoteIndex: longint;
3212 Note: THelpNote;
3213begin
3214 Result := NoteCharIndex;
3215 for NoteIndex := 0 to Notes.Count - 1 do
3216 begin
3217 Note := Notes[ NoteIndex ];
3218 if Note.Topic = Topic then
3219 if Note.InsertPoint < NoteCharIndex then
3220 dec( Result, Note.InsertText.Length );
3221 end;
3222end;
3223
3224function TMainForm.FindActualNoteCharIndex( NoteCharIndex: longword;
3225 MaxNoteIndex: longword;
3226 Topic: TTopic ): longword;
3227var
3228 NoteIndex: longint;
3229 Note: THelpNote;
3230begin
3231 NoteIndex:= 0;
3232 Result:= NoteCharIndex;
3233 for NoteIndex:= 0 to MaxNoteIndex - 1 do
3234 begin
3235 Note:= Notes[ NoteIndex ];
3236 if Note.Topic = Topic then
3237 if Note.InsertPoint < NoteCharIndex then
3238 inc( Result, Note.InsertText.Length );
3239 end;
3240end;
3241
3242procedure TMainForm.RefreshNoteInsertInfo( NoteIndex: longword );
3243var
3244 Note: THelpNote;
3245begin
3246 Note:= Notes[ NoteIndex ];
3247
3248 if Note.Topic = nil then
3249 exit;
3250 with Note do
3251 begin
3252 InsertText.AssignString( '<color #'
3253 + IntToHex( Settings.Colors[ NotesTextColorIndex ], 6 )
3254 + '><link note'
3255 + IntToStr( NoteIndex )
3256 + '>' );
3257 InsertText.Add( Text );
3258 InsertText.AddString( '</color></link>' );
3259 end;
3260end;
3261
3262procedure TMainForm.ClearNotes;
3263begin
3264 DestroyListObjects( Notes );
3265 Notes.Clear;
3266end;
3267
3268procedure TMainForm.AddNote;
3269var
3270 Note: THelpNote;
3271 Window: THelpWindow;
3272begin
3273 Window := GetActiveWindow;
3274 if Window = nil then
3275 begin
3276 DoErrorDlg( AddNoteTitle,
3277 AddNoteCursorError );
3278 exit;
3279 end;
3280
3281 if Window.View.CursorIndex = -1 then
3282 begin
3283 DoErrorDlg( AddNoteTitle,
3284 AddNoteCursorError );
3285 exit;
3286 end;
3287
3288 // check that the note position isn't
3289 // within a note already
3290 if Window.View.LinkFromIndex( Window.View.CursorIndex ) <> '' then
3291 begin
3292 DoErrorDlg( AddNoteTitle,
3293 NoteWithinNoteError );
3294 exit;
3295 end;
3296
3297 // ask for note text
3298 NoteForm.DeleteNoteButton.Enabled := false; // can't delete it while creating!
3299 NoteForm.Text.Clear;
3300 if NoteForm.ShowModal <> mrOK then
3301 exit;
3302
3303 // store note data
3304 Note := THelpNote.Create;
3305 Note.Text.Assign( NoteForm.Text );
3306
3307 // compensate for existing notes
3308 if Window.View.CursorIndex <> -1 then
3309 Note.InsertPoint := FindOriginalNoteCharIndex( Window.View.CursorIndex, Window.Topic )
3310 else
3311 Note.InsertPoint := 0;
3312
3313 Note.Topic := Window.Topic;
3314
3315 Notes.Add( Note );
3316
3317 // redisplay topic
3318 DisplayTopicInWindow( Window,
3319 false, // don't follow links!
3320 true ); // keep position
3321 Window.View.SelectionStart := FindActualNoteCharIndex( Note.InsertPoint,
3322 Notes.Count - 1,
3323 Window.Topic );
3324 UpdateNotesDisplay;
3325
3326 SaveNotes;
3327
3328end;
3329
3330procedure TMainForm.DeleteNote( NoteIndex: longint );
3331var
3332 Note: THelpNote;
3333begin
3334 Note := Notes[ NoteIndex ];
3335 Notes.Delete( NoteIndex );
3336
3337 RefreshWindows( Windows );
3338
3339 Note.Destroy;
3340
3341 UpdateNotesDisplay;
3342
3343 SaveNotes;
3344end;
3345
3346Procedure TMainForm.EditNote( NoteIndex: longint );
3347var
3348 Note: THelpNote;
3349begin
3350 Note:= Notes[ NoteIndex ];
3351
3352 NoteForm.Text.Assign( Note.Text );
3353
3354 NoteForm.DeleteNoteButton.Enabled:= true;
3355
3356 if NoteForm.ShowModal = mrCancel then
3357 exit;
3358
3359 if NoteForm.ModalResult = cmDiscard then
3360 begin
3361 DeleteNote( NoteIndex );
3362 exit;
3363 end;
3364
3365 Note.Text.Assign( NoteForm.Text );
3366
3367 RefreshWindows( Windows );
3368
3369 UpdateNotesDisplay;
3370
3371 SaveNotes;
3372end;
3373
3374Procedure TMainForm.GotoCurrentNote;
3375var
3376 Note: THelpNote;
3377Begin
3378 if NotesListBox.ItemIndex = -1 then
3379 exit;
3380 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3381 DisplayTopic( Note.Topic );
3382End;
3383
3384// ---------------- Bookmarks ----------------------
3385
3386procedure TMainForm.OnBookmarksChanged( Sender: TObject );
3387begin
3388 BuildBookmarksMenu;
3389 UpdateBookmarksForm;
3390 SaveBookmarks;
3391end;
3392
3393procedure TMainForm.AddBookmark;
3394var
3395 Bookmark: TBookmark;
3396begin
3397 if Windows.Count = 0 then
3398 exit;
3399
3400 Bookmark := TBookmark.Create;
3401 SaveWindows( Windows, Bookmark.Windows, nil );
3402
3403 if ContentsOutline.SelectedNode <> nil then
3404 begin
3405 Bookmark.ContentsTopic:=
3406 ContentsOutline.SelectedNode.Data as TTopic;
3407 Bookmark.Name := Bookmark.ContentsTopic.Title;
3408 end
3409 else
3410 begin
3411 Bookmark.ContentsTopic:= nil;
3412 // Bookmark.Name := THelpWindow( Windows[ 0 ] ).Title;
3413 end;
3414
3415 Bookmarks.Add( Bookmark );
3416 OnBookmarksChanged( self );
3417end;
3418
3419Procedure TMainForm.BookmarksMenuItemClick( Sender: TObject );
3420var
3421 Tag: longint;
3422 MenuItem: TMenuItem;
3423 Bookmark: TBookmark;
3424begin
3425 MenuItem:= Sender as TMenuItem;
3426 Tag:= MenuItem.Tag;
3427 Bookmark := Bookmarks[ Tag ];
3428
3429 NavigateToBookmark( Bookmark );
3430end;
3431
3432Procedure TMainForm.NavigateToBookmark( Bookmark: TBookmark );
3433Begin
3434 UpdateCurrentNavigatePoint;
3435 NavigateToPoint( Bookmark );
3436 SaveNavigatePoint;
3437End;
3438
3439Procedure TMainForm.BuildBookmarksMenu;
3440var
3441 i: integer;
3442 Bookmark: TBookmark;
3443 MenuItem: TMenuItem;
3444begin
3445 DestroyListObjects( BookmarksMenuItems );
3446 BookmarksMenuItems.Clear;
3447
3448 if Bookmarks.Count > 0 then
3449 begin
3450 MenuItem:= TMenuItem.Create( self );
3451 MenuItem.Caption:= '-';
3452 BookmarksMenu.Add( MenuItem );
3453 BookmarksMenuItems.Add( MenuItem );
3454 end;
3455
3456 for i:= 0 to Bookmarks.Count -1 do
3457 begin
3458 Bookmark := Bookmarks[ i ];
3459 MenuItem:= TMenuItem.Create( self );
3460
3461 MenuItem.Caption:= Bookmark.Name;
3462 MenuItem.OnClick:= BookmarksMenuItemClick;
3463 MenuItem.Tag:= i;
3464 BookmarksMenu.Add( MenuItem );
3465 BookmarksMenuItems.Add( MenuItem );
3466 end;
3467end;
3468
3469Procedure TMainForm.UpdateBookmarksForm;
3470begin
3471 if Assigned( BookmarksForm ) then
3472 BookmarksForm.RefreshList;
3473end;
3474
3475Procedure TMainForm.ClearBookmarks;
3476begin
3477 ClearListAndObjects( Bookmarks );
3478 BuildBookmarksMenu;
3479 if Assigned( BookmarksForm ) then
3480 begin
3481 UpdateBookmarksForm; // clear bookmarks for next show
3482 BookmarksForm.Hide;
3483 end;
3484
3485end;
3486
3487procedure TMainForm.LoadBookmarks( HelpFile: THelpFile );
3488var
3489 Bookmark: TBookmark;
3490 BookmarksFile: TextFile;
3491 BookmarksFileName: string;
3492 S: string;
3493begin
3494 LogEvent(LogSettings, 'Load bookmarks for ' + HelpFile.Filename);
3495
3496 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3497
3498 if not FileExists( BookmarksFileName ) then
3499 exit;
3500
3501 FileMode := fmInput;
3502 AssignFile( BookmarksFile, BookmarksFileName );
3503 try
3504 Reset( BookmarksFile );
3505 try
3506 while not Eof( BookmarksFile ) do
3507 begin
3508 ReadLn( BookmarksFile, s );
3509 if trim( Uppercase( s ) ) = '[BOOKMARK]' then
3510 begin
3511 Bookmark:= TBookmark.Load( BookmarksFile, HelpFile );
3512 Bookmarks.Add( Bookmark );
3513 end;
3514 end;
3515 finally
3516 System.Close( BookmarksFile );
3517 end;
3518 except
3519 on e: exception do
3520 DoErrorDlg( LoadBookmarksTitle,
3521 LoadBookmarksError
3522 + e.message );
3523 end;
3524end;
3525
3526procedure TMainForm.SaveBookmarks;
3527var
3528 FileIndex: integer;
3529 HelpFile: THelpFile;
3530begin
3531 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3532 begin
3533 HelpFile := CurrentOpenFiles[ FileIndex ];
3534 SaveBookmarksForFile( HelpFile );
3535 end;
3536end;
3537
3538procedure TMainForm.SaveNotes;
3539var
3540 FileIndex: integer;
3541 HelpFile: THelpFile;
3542begin
3543 LogEvent(LogSettings, 'Save notes');
3544
3545 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3546 begin
3547 HelpFile := CurrentOpenFiles[ FileIndex ];
3548 SaveNotesForFile( HelpFile );
3549 end;
3550end;
3551
3552procedure TMainForm.SaveBookmarksForFile( HelpFile: THelpFile );
3553var
3554 i: integer;
3555 Bookmark: TBookmark;
3556 BookmarksFile: TextFile;
3557 BookmarksFileName: string;
3558 BookmarkCount: integer;
3559begin
3560 LogEvent(LogSettings, 'Save bookmarks for ' + HelpFile.Filename);
3561
3562 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3563
3564 BookmarkCount:= 0;
3565 for i:= 0 to Bookmarks.Count - 1 do
3566 begin
3567 Bookmark := Bookmarks[ i ];
3568
3569 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3570 inc( BookmarkCount );
3571 end;
3572
3573 if BookmarkCount = 0 then
3574 begin
3575 if FileExists( BookmarksFileName ) then
3576 DeleteFile( BookmarksFileName );
3577 exit;
3578 end;
3579
3580 AssignFile( BookmarksFile, BookmarksFileName );
3581 try
3582 Rewrite( BookmarksFile );
3583 try
3584 for i := 0 to Bookmarks.Count - 1 do
3585 begin
3586 Bookmark:= Bookmarks[ i ];
3587 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3588 begin
3589 WriteLn( BookmarksFile, '[Bookmark]' );
3590 Bookmark.Save( BookmarksFile );
3591 end;
3592 end;
3593 finally
3594 System.Close( BookmarksFile );
3595 end;
3596 except
3597 on e: exception do
3598 DoErrorDlg( SaveBookmarksTitle,
3599 SaveBookmarksError
3600 + e.message );
3601 end;
3602end;
3603
3604// Reads colors back from controls, in case they have changed by
3605// drag and drop
3606Procedure TMainForm.GetColors;
3607begin
3608 with Settings do
3609 begin
3610 Colors[ ContentsBackgroundColorIndex ] := ContentsOutline.Color;
3611 Colors[ ContentsTextColorIndex ] := ContentsOutline.PenColor;
3612 Colors[ IndexBackgroundColorIndex ] := IndexListBox.Color;
3613 Colors[ IndexTextColorIndex ] := IndexListBox.PenColor;
3614 Colors[ SearchBackgroundColorIndex ] := SearchResultsListBox.Color;
3615 Colors[ SearchTextColorIndex ] := SearchResultsListBox.PenColor;
3616 Colors[ NotesListBackgroundColorIndex ] := NotesListBox.Color;
3617 Colors[ NotesListTextColorIndex ] := NotesListBox.PenColor;
3618 end;
3619end;
3620
3621Procedure TMainForm.MainFormOnDestroy (Sender: TObject);
3622Begin
3623 LogEvent(LogShutdown, 'MainFormOnDestroy');
3624
3625 LogEvent(LogSettings, 'Write window position');
3626 WriteWindowPos( self );
3627
3628 LogEvent(LogSettings, 'Update colors');
3629 GetColors;
3630
3631 LogEvent(LogSettings, 'Save settings');
3632 SaveSettings;
3633 LogEvent(LogSettings, 'Save settings done');
3634
3635 // else- don't save position/size if doing own help
3636
3637 TopicText.Destroy;
3638
3639 LogEvent(LogShutdown, 'Destroy MRU menu items');
3640 MRUMenuItems.Destroy;
3641
3642 LogEvent(LogShutdown, 'Destroy navigate to menu items');
3643 NavigateToMenuItems.Destroy;
3644
3645 LogEvent(LogShutdown, 'Destroy pagehistory');
3646 PageHistory.Destroy;
3647
3648 LogEvent(LogShutdown, 'Clear/destroy notes');
3649 ClearNotes;
3650 Notes.Destroy;
3651
3652 LogEvent(LogShutdown, 'Clear/destroy bookmarks');
3653 ClearBookmarks;
3654 Bookmarks.Destroy;
3655
3656 LogEvent(LogShutdown, 'Destroy bookmark menu items');
3657 BookmarksMenuItems.Destroy;
3658
3659 LogEvent(LogShutdown, 'Destroy files/index/windows');
3660 CurrentOpenFiles.Destroy;
3661 DisplayedIndex.Destroy;
3662 Windows.Destroy;
3663
3664 // tell help manager(s) we are stopping.
3665 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
3666
3667 HelpManagerWindows.Destroy;
3668
3669 DestroyListObjects( Settings.MRUList );
3670 Settings.MRUList.Destroy;
3671
3672 // TODO rbri maybe we have to do this
3673 // Parameters.FilenamesParam.Destroy;
3674
3675 if g_CurrentLanguageFile <> nil then
3676 g_CurrentLanguageFile.Destroy;
3677
3678 LogEvent(LogShutdown, 'Close global filelist');
3679 GlobalFilelist.Destroy;
3680
3681 LogEvent(LogShutdown, 'Close shared memory');
3682 SharedMemory.Destroy;
3683
3684 AllFilesWordSequences.Destroy;
3685
3686 LogEvent(LogShutdown, 'MainFormOnDestroy done');
3687End;
3688
3689Procedure TMainForm.MainFormOnSetupShow (Sender: TObject);
3690Begin
3691 LogEvent(LogSettings, 'OnSetupShow');
3692 TabSet.TabIndex := 0;
3693 Notebook.PageIndex := 0;
3694End;
3695
3696Procedure TMainForm.OnException( Sender: TObject;
3697 E: Exception );
3698var
3699 TheText : string;
3700 F: TextFile;
3701 i: integer;
3702 HelpFile: THelpFile;
3703 LogFilename: string;
3704
3705begin
3706 LogFilename := GetLogFilesDir + CrashLogFileName;
3707
3708 LogException( E,
3709 LogFileName,
3710 'NewView',
3711 GetAppVersion,
3712 F );
3713
3714 if CurrentOpenFiles <> nil then
3715 begin
3716 WriteLn( F, 'Loaded files ('
3717 + IntToStr( CurrentOpenFiles.Count )
3718 + '):' );
3719 try
3720 for i := 0 to CurrentOpenFiles.Count - 1 do
3721 begin
3722 HelpFile := CurrentOpenFiles[ i ];
3723 WriteLn( F, HelpFile.Filename );
3724 end;
3725 except
3726 end;
3727 end;
3728 try
3729 if CurrentTopic <> nil then
3730 WriteLn( F, 'Last major topic index: '
3731 + IntToStr( CurrentTopic.Index ) );
3732 except
3733 // ignore exceptions if there isn't a valid current topic
3734 end;
3735 if Windows <> nil then
3736 begin
3737 WriteLn( F, 'Top-level open windows: '
3738 + IntToStr( Windows.Count ) );
3739 end;
3740
3741 System.Close( F );
3742
3743 TheText := ApplicationErrorA + StrCRLF
3744 + StrCRLF
3745 + E.Message + StrCRLF
3746 + ApplicationErrorB
3747 + LogFilename
3748 + ')' + StrCRLF
3749 + StrCRLF
3750 + ApplicationErrorC
3751 + StrCRLF;
3752
3753 if DoYesNoDlg( ApplicationErrorTitle,
3754 TheText ) then
3755 begin
3756 // exit a bit more nicely - remove ourselves from the global filelist.
3757 GlobalFilelist.RemoveWindowFiles( Frame.Handle );
3758 Application.Terminate;
3759 end;
3760end;
3761
3762// give our main window a unique class name we can find
3763procedure TMainForm.GetClassData(var ClassData: TClassData);
3764Begin
3765 inherited GetClassData( ClassData );
3766 ClassData.ClassName := MAIN_WINDOW_CLASS_NAME;
3767End;
3768
3769// Position the window offset from existing top help window (if any)
3770Procedure TMainForm.PositionWindow;
3771var
3772 hTopWindow: HWND;
3773 TopHelpWindowPos: SWP;
3774 Offset: longint;
3775Begin
3776 hTopWindow := FindTopFormWindow( MAIN_WINDOW_CLASS_NAME );
3777
3778 if hTopWindow <> NULLHANDLE then
3779 begin
3780 // found an existing help window, find it's location
3781 if WinQueryWindowPos(
3782 hTopWindow,
3783 TopHelpWindowPos ) then
3784 begin
3785 if ( TopHelpWindowPos.FL and ( SWP_MINIMIZE or SWP_MINIMIZE ) ) > 0 then
3786 Begin
3787 // window is maximized or minimised, so get the restore position from window USHORTs
3788 TopHelpWindowPos.x := WinQueryWindowUShort( hTopWindow, QWS_XRESTORE );
3789 TopHelpWindowPos.Y := WinQueryWindowUShort( hTopWindow, QWS_YRESTORE );
3790 end;
3791
3792 // offset new window by height of title bar + border
3793 Offset := Screen.SystemMetrics( smCyTitleBar )
3794 + Screen.SystemMetrics( smCySizeBorder );
3795 Left := TopHelpWindowPos.x + Offset;
3796 Bottom := TopHelpWindowPos.y - Offset;
3797
3798 // I guess I am leaving width/height out for compatibility...?
3799 end;
3800 end;
3801end;
3802
3803Procedure TMainForm.OnHelp( context: THelpContext;
3804 var Result: Boolean );
3805begin
3806 if OwnHelpMode then
3807 begin
3808 // we are viewing the help file now - display our own help!
3809 PostMsg( Handle, NHM_TOPIC_BY_RESOURCE_ID, context, 0 );
3810 exit;
3811 end;
3812
3813 Application.HelpContext( context );
3814end;
3815
3816Procedure TMainForm.MainFormOnCreate (Sender: TObject);
3817var
3818 tmpCmdLine: AnsiString;
3819Begin
3820 LogEvent(LogStartup, 'MainFormOnCreate');
3821
3822 StartingUp := true;
3823
3824 SharedMemory := AccessSharedMemory;
3825 GlobalFilelist := TGlobalFilelist.Create;
3826
3827 // parse parameters into Parameters object
3828 tmpCmdLine := nativeOS2GetCmdLineParameter;
3829 CmdLineParameters := TCmdLineParameters.Create;
3830 CmdLineParameters.parseCmdLine(tmpCmdLine);
3831
3832 Application.HelpFile := CmdLineParameters.GetOwnHelpFilename; // OWN_HELP_MARKER;
3833 Application.OnHelp := OnHelp;
3834
3835 RegisterEventForLanguages( OnLanguageEvent );
3836
3837 // if debug is not enabled, get rid of the debug menu and separator.
3838 if not CmdLineParameters.isDebugEnabled then
3839 begin
3840 ToolsDebugSep.Destroy;
3841 ToolsDebugMenu.Destroy;
3842 DebugShowCodesMI := nil;
3843 DebugShowWordSeparatorsMI := nil;
3844 end;
3845
3846 // set up globals for Exec
3847 ExecViaSession := true;
3848 AsynchExec := true;
3849
3850 // set up form icons
3851 Forms.FormIconResourceID := 1;
3852
3853 Application.OnException := OnException;
3854
3855 ContentsOutline.SmoothScroll := false;
3856
3857 LogEvent(LogStartup, 'Choosing default font: Trying WarpSans');
3858
3859 Font := GetNiceDefaultFont;
3860
3861 // Set the menu fonts, because they remember their own specific one
3862 MainMenu.Font := Screen.MenuFont;
3863 ViewPopupMenu.Font := Screen.MenuFont;
3864
3865 // NOTE: SPCC will copy this font to TApplication
3866 // in TApplication.Run
3867
3868 LogEvent(LogStartup, 'Starting NewView: MainFormOnCreate');
3869
3870 Application.OnHint := OnHint;
3871
3872 StartMem := MemAvailBytes;
3873
3874 DisplayedIndex := TStringList.Create;
3875
3876 HelpManagerWindows := TList.Create;
3877
3878 AllFilesWordSequences := TList.Create;
3879
3880 CurrentOpenFiles := TList.Create;
3881 Notes := TList.Create;
3882 Bookmarks := TList.Create;
3883 BookmarksMenuItems := TList.Create;
3884 Windows := TList.Create;
3885
3886 TopicText := TAString.Create;
3887
3888 Navigating := false;
3889 InIndexSearch := false;
3890 SettingFont := false;
3891
3892 PageHistory := TStringList.Create;
3893 CurrentHistoryIndex := -1;
3894
3895 Settings.MRUList := TList.Create;
3896
3897 MRUMenuItems := TList.Create;
3898 NavigateToMenuItems := TList.Create;
3899
3900 LogEvent(LogSettings, 'Loading settings');
3901
3902 LoadSettings;
3903 SetShowLeftPanel( ShowLeftPanel ); // update menu
3904
3905 // load default strings
3906 LogEvent(LogSettings, 'Loading language');
3907
3908 // the user likes to have english
3909 // the normal automatic will fall back to
3910 // the environment setting but in the special
3911 // case we have to start the default
3912 if CmdLineParameters.getLanguage = 'en' then
3913 begin
3914 LoadLanguage('');
3915 end
3916 else
3917 begin
3918 if CmdLineParameters.getLanguage <> '' then
3919 begin
3920 if not LoadLanguageForSpec('newview', CmdLineParameters.getLanguage) then
3921 begin
3922 LoadDefaultLanguage('newview');
3923 end
3924 end
3925 else
3926 begin
3927 LoadDefaultLanguage('newview');
3928 end;
3929 end;
3930
3931 LogEvent(LogSettings, 'Applying settings');
3932 ApplySettings;
3933
3934 // default position is centered..
3935 LogEvent(LogSettings, 'Set default position');
3936 if Width > Screen.Width then
3937 Width := Screen.Width;
3938 if Height > Screen.Height then
3939 Height := Screen.Height;
3940 Left := ( Screen.Width - Width ) div 2;
3941 Bottom := ( Screen.Height - Height ) div 2;
3942
3943 LogEvent(LogSettings, 'ReadWindowPos');
3944 ReadWindowPos( Self );
3945
3946 PositionWindow;
3947
3948 LogEvent(LogSettings, 'Creating MRU list');
3949
3950 CreateMRUMenuItems;
3951
3952 CloseFile;
3953
3954 LogEvent(LogStartup, 'OnCreate done');
3955
3956 if CmdLineParameters.getWindowPositionFlag then
3957 begin
3958 SmartSetWindowPos( self,
3959 CmdLineParameters.getWindowPosition.Left,
3960 CmdLineParameters.getWindowPosition.Bottom,
3961 CmdLineParameters.getWindowPosition.Width,
3962 CmdLineParameters.getWindowPosition.Height,
3963 false );
3964 end;
3965
3966 LogEvent(LogStartup, 'MainFormOnCreate Done');
3967End;
3968
3969Procedure TMainForm.ApplySettings;
3970var
3971 ToolbarBitmap: TBitmap;
3972begin
3973 ContentsOutline.Color:= Settings.Colors[ ContentsBackgroundColorIndex ];
3974 ContentsOutline.PenColor:= Settings.Colors[ ContentsTextColorIndex ];
3975 ContentsOutline.TreeLineColor:= Settings.Colors[ ContentsLinesColorIndex ];
3976 IndexListBox.Color:= Settings.Colors[ IndexBackgroundColorIndex ];
3977 IndexListBox.PenColor:= Settings.Colors[ IndexTextColorIndex ];
3978 SearchResultsListBox.Color:= Settings.Colors[ SearchBackgroundColorIndex ];
3979 SearchResultsListBox.PenColor:= Settings.Colors[ SearchTextColorIndex ];
3980 NotesListBox.Color:= Settings.Colors[ NotesListBackgroundColorIndex ];
3981 NotesListBox.PenColor:= Settings.Colors[ NotesListTextColorIndex ];
3982
3983 SettingFont := true;
3984 Notebook.ParentFont := true;
3985 ContentsOutline.ParentFont := true;
3986 IndexListBox.ParentFont := true;
3987 SearchResultsListBox.ParentFont := true;
3988 NotesListBox.ParentFont := true;
3989 TabSet.ParentFont := true;
3990 Coolbar.ParentFont := true;
3991 if Settings.Fonts[ ApplicationFontIndex ] <> nil then
3992 Font := Settings.Fonts[ ApplicationFontIndex ]
3993 else
3994 Font := GetNiceDefaultFont;
3995 SettingFont := false;
3996
3997 Coolbar.BackgroundBitmap := nil;
3998 if FileExists( Settings.ToolbarBackgroundImageFilename ) then
3999 begin
4000 ToolbarBitmap:= TBitmap.Create;
4001 try
4002 ToolbarBitmap.LoadFromFIle( Settings.ToolbarBackgroundImageFilename );
4003 Coolbar.BackgroundBitmap := ToolbarBitmap;
4004 except
4005 end;
4006 ToolbarBitmap.Destroy;
4007 end;
4008
4009 CoolBar.ShowImages := Settings.ToolbarStyle in [ tsImages, tsImagesAndText ];
4010 CoolBar.ShowText := Settings.ToolbarStyle in [ tsText, tsImagesAndText ];
4011
4012 CoolBar.SetMinConstButtonWidth;
4013
4014 DisplayPanel.Color := Settings.Colors[ TopicBackgroundColorIndex ];
4015
4016 SetupViews( Windows );
4017end;
4018
4019// Setup the rich text views in the specified windows (e.g for changing global settings)
4020Procedure TMainForm.SetupViews( WindowList: TList );
4021var
4022 WindowIndex: longint;
4023 Window: THelpWindow;
4024begin
4025 for WindowIndex := 0 to WindowList.Count - 1 do
4026 begin
4027 Window := WindowList[ WindowIndex ];
4028 Window.SetupRTView;
4029 SetupViews( Window.ChildWindows );
4030 end;
4031end;
4032
4033Procedure TMainForm.PostHelpManagerMessage( MessageType: ULONG;
4034 Param1: long;
4035 Param2: long );
4036var
4037 i: longint;
4038begin
4039 for i := 0 to HelpManagerWindows.Count - 1 do
4040 PostMsg( HWND( HelpManagerWindows[ i ] ),
4041 MessageType,
4042 Param1,
4043 Param2 );
4044end;
4045
4046Procedure TMainForm.ClearHelpManager;
4047Begin
4048 if not CmdLineParameters.getHelpManagerFlag then
4049 exit;
4050
4051 // tell the help manager(s) we are no longer playing with them
4052 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
4053
4054 CmdLineParameters.setHelpManagerFlag(false);
4055
4056 HelpManagerWindows.Clear;
4057End;
4058
4059Procedure TMainForm.MainFormOnShow (Sender: TObject);
4060Begin
4061 EnableCallstackLogging( true );
4062
4063 LogEvent(LogStartup, 'MainFormOnShow');
4064
4065 if CmdLineParameters.getOwnerWindow <> NULLHANDLE then
4066 begin
4067 LogEvent(LogStartup, 'Setting owner: ' + IntToStr( CmdLineParameters.getOwnerWindow));
4068 WinSetOwner( Frame.Handle, CmdLineParameters.getOwnerWindow );
4069 end;
4070
4071 if CmdLineParameters.getHelpManagerFlag then
4072 begin
4073 LogEvent(LogStartup, ' Help Manager Title: '
4074 + StrPasWithLength( pSharedStruct ^. Title,
4075 SHARED_STRUCT_TITLE_SIZE ) );
4076 HelpManagerVersion := StrPasWithLength( pSharedStruct ^. Version,
4077 SHARED_STRUCT_VERSION_SIZE );
4078 LogEvent(LogStartup, ' Help Manager Version: ' + HelpManagerVersion );
4079
4080 end;
4081
4082 CoolBar.SetMinConstButtonWidth;
4083
4084 ResetProgress;
4085
4086 AddShortcut( kbF11, kbF11 ); // prev in contents
4087 AddShortcut( kbF12, kbF12 ); // next in contents
4088 AddShortcut( kbF7, kbF7 ); // back
4089 AddShortcut( kbF8, kbF8 ); // forward
4090 AddShortcut( kbCtrlCLeft, kbCtrlCLeft ); // back
4091
4092 LogEvent(LogStartup, 'Post WM_OPENED');
4093 PostMsg( Handle, WM_OPENED, 0, 0 );
4094End;
4095
4096Procedure TMainForm.DisplaySelectedContentsTopic;
4097var
4098 Topic: TTopic;
4099Begin
4100 if ContentsOutline.SelectedNode = nil then
4101 exit;
4102 Topic := ContentsOutline.SelectedNode.Data as TTopic;
4103 DisplayTopic( Topic );
4104End;
4105
4106// Check that the HELP and BOOKSHELF environment variables
4107// are defined (as they should be on any working OS/2 system).
4108// Show a warning message if not.
4109Procedure TMainForm.CheckEnvironmentVars;
4110var
4111 HelpOK: boolean;
4112 BookshelfOK: boolean;
4113 ErrorText: string;
4114begin
4115 HelpOK := GetEnv( HelpPathEnvironmentVar ) <> '';
4116 BookshelfOK := GetEnv( BookshelfEnvironmentVar ) <> '';
4117 if HelpOK and BookshelfOK then
4118 // all ok.
4119 exit;
4120
4121 // One or both missing
4122
4123 ErrorText := '';
4124 if not BookshelfOK then
4125 ErrorText := ErrorText
4126 + EnvironmentVarUndefined
4127 + BookshelfEnvironmentVar
4128 + StrCRLF;
4129
4130 if not HelpOK then
4131 ErrorText := ErrorText
4132 + EnvironmentVarUndefined
4133 + HelpPathEnvironmentVar
4134 + StrCRLF;
4135
4136 DoWarningDlg( EnvironmentVarErrorTitle,
4137 EnvironmentVarError
4138 + StrCRLF
4139 + StrCRLF
4140 + ErrorText );
4141
4142end;
4143
4144Procedure LoadSupportDLL;
4145begin
4146 try
4147 LoadDLLFunction( 'newview.dll',
4148 'LZWDECOMPRESSBLOCK',
4149 hNewViewDLL,
4150 pointer( LZWDecompressBlock ) );
4151 except
4152 on E: Exception do
4153 begin
4154 DoErrorDlg( 'DLL Error',
4155 E.Message );
4156 LZWDecompressBlock := nil;
4157 end;
4158 end;
4159end;
4160
4161Procedure TMainForm.WMOpened( Var Msg: TMessage );
4162var
4163 Filenames: TStringList;
4164 M1: longword;
4165 OpenFirstTopic: boolean;
4166 tmpFileNames : AnsiString;
4167begin
4168 if Application.HelpFile = '' then
4169 DoErrorDlg( 'NewView Help', 'NewView help file not found' );
4170
4171 LoadSupportDLL;
4172
4173 LogEvent(LogStartup, 'WMOpened: SetLayout');
4174
4175 // direct access the field to suppress updates done by the setter
4176 if CmdLineParameters.getHelpManagerFlag then
4177 FShowLeftPanel := Settings.ShowLeftPanel_Help
4178 else
4179 FShowLeftPanel := Settings.ShowLeftPanel_Standalone;
4180
4181 SetLayout;
4182
4183// ProfileEvent( 'Apply settings' );
4184// ApplySettings;
4185
4186 LogEvent(LogStartup, 'Enable controls');
4187 EnableControls;
4188
4189// ProfileEvent( 'ReadWindowPos' );
4190// ReadWindowPos( Self );
4191
4192 LogEvent(LogStartup, 'Finish paint');
4193 Update;
4194 LogEvent(LogStartup, 'BringToFront');
4195 MainForm.BringToFront;
4196
4197 if not CmdLineParameters.getHelpManagerFlag then
4198 begin
4199 LogEvent(LogStartup, 'Check environment vars');
4200 CheckEnvironmentVars;
4201
4202 if CmdLineParameters.getShowUsageFlag then
4203 begin
4204 LogEvent(LogStartup, 'Showing usage');
4205 ShowUsage;
4206 end;
4207 end;
4208
4209 HelpManagerWindows.Add( pointer( CmdLineParameters.getHelpManagerWindow ) );
4210
4211 if CmdLineParameters.getShowIndexFlag then
4212 begin
4213 DisplayIndex;
4214 end;
4215
4216 tmpFileNames := CmdLineParameters.getFileNames(Settings.StartupHelp);
4217 if tmpFileNames <> '' then
4218 begin
4219 // open specified files
4220 Filenames := TStringList.Create;
4221
4222 ParseAndExpandFileNames(tmpFileNames, Filenames);
4223 LogEvent(LogStartup, 'Call OpenFiles');
4224
4225 OpenFirstTopic := true;
4226
4227 if ( CmdLineParameters.getSearchText <> '' )
4228 OR CmdLineParameters.getSearchFlag
4229 OR CmdLineParameters.getHelpManagerFlag
4230 then
4231 // if we're going to search, don't open first topic
4232 // don't open first topic if we're online help
4233 // in case we are wanting to show a specific topic
4234 // - saves time/flicker
4235 OpenFirstTopic := false;
4236
4237 OpenFiles( Filenames,
4238 CmdLineParameters.getWindowTitle,
4239 OpenFirstTopic );
4240
4241 Filenames.Destroy;
4242
4243 if not CmdLineParameters.getSearchFlag
4244 and not CmdLineParameters.getGlobalSearchFlag
4245 and (CmdLineParameters.getSearchText <> '') then
4246 begin
4247 // search in contents only!
4248 LogEvent(LogStartup, 'Do startup topic search for: "' + CmdLineParameters.getSearchText + '"');
4249
4250 StartupTopicSearch( CmdLineParameters.getSearchText );
4251 end
4252 else if CmdLineParameters.getSearchFlag then
4253 begin
4254 // search in specified files
4255 LogEvent(LogStartup, 'Do search for topic');
4256 DisplaySearch;
4257
4258 SearchFor( CmdLineParameters.getSearchText );
4259 end;
4260 end;
4261
4262 if NOT CmdLineParameters.getShowUsageFlag
4263 AND CmdLineParameters.getGlobalSearchFlag then
4264 begin
4265 // Global search
4266 LogEvent(LogStartup, 'Do global search: ' + CmdLineParameters.getSearchText);
4267 DoGlobalSearch( CmdLineParameters.getSearchText );
4268 end;
4269
4270 LogEvent(LogStartup, 'Open finished');
4271
4272 if CmdLineParameters.getHelpManagerFlag then
4273 begin
4274 // Tell helpmanager(s) our window handle
4275 PostHelpManagerMessage( NHM_VIEWER_READY,
4276 Handle,
4277 0 );
4278 end;
4279
4280 M1:= MemAvail;
4281
4282 StartingUp := false;
4283
4284 LogEvent(LogStartup, 'RUN PROGRAM');
4285end;
4286
4287
4288Procedure TMainForm.MainFormOnResize (Sender: TObject);
4289Begin
4290 if not Visible then
4291 exit;
4292 if Handle = 0 then
4293 exit;
4294
4295 SetLayout;
4296
4297End;
4298
4299Function TMainForm.GetShowLeftPanel: boolean;
4300begin
4301 Result := FShowLeftPanel;
4302end;
4303
4304Procedure TMainForm.SetShowLeftPanel( Value: boolean );
4305begin
4306 ShowLeftPanelMI.Checked := Value;
4307 if Value = FShowLeftPanel then
4308 exit;
4309 FShowLeftPanel := Value;
4310 if FShowLeftPanel then
4311 NotebookOnPageChanged( self ) // make sure page is updated
4312 else
4313 FocusFirstHelpWindow;
4314 EnableControls;
4315 SetLayout;
4316end;
4317
4318Procedure TMainForm.VSplitBarOnChange (NewSplit: LongInt);
4319Begin
4320 if VSplitBar.Left < 30 then
4321 begin
4322 ShowLeftPanel := false
4323 end
4324 else
4325 begin
4326 Settings.LeftPanelWidth := VSplitBar.Left;
4327 ShowLeftPanel := true;
4328 end;
4329 SetLayout;
4330End;
4331
4332// Set the layout of the main form
4333Procedure TMainForm.SetLayout;
4334var
4335 RealClientHeight : longint;
4336 CoolbarSpace: longint;
4337 TextHeight: longint;
4338Begin
4339 TextHeight := Canvas.TextHeight( 'S' );
4340 Tabset.Height := TextHeight + 5;
4341
4342 Coolbar.Visible := Settings.ToolbarStyle <> tsNone;
4343
4344 case Settings.ToolbarStyle of
4345 tsImages:
4346 Coolbar.Height := Coolbar.Sections[ 0 ].Width;
4347 tsText:
4348 Coolbar.Height := TextHeight + 5;
4349 tsImagesAndText:
4350 CoolBar.Height := ButtonImages.GetBitmapReference(0).Width + TextHeight + 10;
4351 end;
4352
4353 CoolbarSpace := Coolbar.Height;
4354 if not Coolbar.Visible then
4355 CoolbarSpace := 0;
4356
4357 StatusPanel.Left:= 0;
4358 StatusPanel.Width:= ClientWidth div 2 - 2;
4359 StatusPanel.Height := TextHeight + 2;
4360
4361 ProgressPanel.Left:= ClientWidth div 2 + 2;
4362 ProgressPanel.Width:= ClientWidth - ProgressPanel.Left;
4363 ProgressPanel.Height := TextHeight + 2;
4364
4365 Notebook.Bottom := StatusPanel.Height + 3;
4366 VSplitBar.Bottom := Notebook.Bottom;
4367 DisplayPanel.Bottom := Notebook.Bottom;
4368
4369 RealClientHeight := ClientHeight
4370 - CoolbarSpace
4371 - Notebook.Bottom;
4372
4373 LogEvent(LogStartup, 'TMainForm.SetLayout');
4374 LogEvent(LogStartup, ' RealClientHeight: ' + IntToStr( RealClientHeight ));
4375
4376 LogEvent(LogStartup, ' Form Width: ' + IntToStr( Width ));
4377 LogEvent(LogStartup, ' Form Height: ' + IntToStr( Height ) );
4378 LogEvent(LogStartup, ' Form ClientWidth: ' + IntToStr( ClientWidth ) );
4379 LogEvent(LogStartup, ' Form ClientHeight: ' + IntToStr( ClientHeight ) );
4380 LogEvent(LogStartup, ' CoolBar.Height: ' + IntToStr( CoolBar.Height ) );
4381 LogEvent(LogStartup, ' CoolBar.Bottom: ' + IntToStr( CoolBar.Bottom ) );
4382
4383 if CurrentOpenFiles.Count > 0 then
4384 VSplitBar.Width := Max( 5, Canvas.TextWidth( ' ' ) )
4385 else
4386 VSplitBar.Width := 0;
4387
4388 VSplitBar.Height := RealClientHeight;
4389
4390 if Settings.LeftPanelWidth > ClientWidth - 50 then
4391 Settings.LeftPanelWidth := ClientWidth - 50;
4392 if Settings.LeftPanelWidth < 50 then
4393 Settings.LeftPanelWidth := 50;
4394
4395 if ShowLeftPanel then
4396 begin
4397 VSplitBar.Left := Settings.LeftPanelWidth;
4398 VSplitBar.Hint := SplitBarDblClickToHide;
4399 end
4400 else
4401 begin
4402 VSplitBar.Left := 0;
4403 VSplitBar.Hint := SplitBarDblClickToShow;
4404 end;
4405
4406 Tabset.Left := 0;
4407 Tabset.Width := VSplitBar.Left;
4408 Tabset.Bottom := ClientHeight
4409 - CoolbarSpace
4410 - Tabset.Height;
4411
4412 Notebook.Left := 0;
4413 Notebook.Width := VSplitBar.Left;
4414 Notebook.Height := RealClientHeight
4415 - Tabset.Height
4416 - 3;
4417
4418 DisplayPanel.Left:= VSplitBar.Left + VSplitBar.Width;
4419 DisplayPanel.Width:= ClientWidth - DisplayPanel.Left;
4420 DisplayPanel.Height := RealClientHeight;
4421 LogEvent(LogStartup, ' DisplayPanel.Width: ' + IntToStr( DisplayPanel.Width ) );
4422 LogEvent(LogStartup, ' DisplayPanel.Height: ' + IntToStr( DisplayPanel.Height ) );
4423 LogEvent(LogStartup, ' DisplayPanel.Bottom: ' + IntToStr( DisplayPanel.Bottom ) );
4424
4425 ProgressBar.Left:= 1;
4426 ProgressBar.Bottom:= 1;
4427 ProgressBar.Width:= ProgressPanel.Width - 2;
4428 ProgressBar.Height:= ProgressPanel.Height - 2;
4429
4430 // Layout the visible help windows also
4431 LayoutWindowList( Windows );
4432End;
4433
4434// Lay out the specified list of help windows
4435Procedure TMainForm.LayoutWindowList( WindowList: TList );
4436var
4437 Window: THelpWindow;
4438 WindowIndex: longint;
4439begin
4440 for WindowIndex:= 0 to WindowList.Count - 1 do
4441 begin
4442 Window:= WindowList[ WindowIndex ];
4443 Window.SetLayout;
4444 end;
4445end;
4446
4447Procedure TMainForm.FindNextMIOnClick (Sender: TObject);
4448begin
4449 if FindText = '' then
4450 begin
4451 FindMIOnClick( sender );
4452 exit;
4453 end;
4454
4455 if GetActiveWindow = nil then
4456 begin
4457 DoErrorDlg( FindTitle,
4458 FindSelectWindowError );
4459 exit;
4460 end;
4461
4462 DoFind( foFromCurrent );
4463end;
4464
4465Procedure TMainForm.DoFind( FindOrigin: TFindOrigin );
4466var
4467 Window: THelpWindow;
4468begin
4469 SetWaitCursor;
4470 Window := GetActiveWindow;
4471 if not Window.View.Find( FindOrigin, FindText ) then
4472 begin
4473 SetStatus( TextNotFoundMsg );
4474 Beep( 1000, 100 );
4475 end;
4476 ClearWaitCursor;
4477End;
4478
4479Procedure TMainForm.FindMIOnClick (Sender: TObject);
4480begin
4481 if GetActiveWindow = nil then
4482 begin
4483 DoErrorDlg( FindTitle,
4484 FindSelectWindowError );
4485 exit;
4486 end;
4487 if not DoInputQuery( FindTitle,
4488 FindPrompt,
4489 FindText ) then
4490 exit;
4491
4492 DoFind( foFromStart );
4493End;
4494
4495Procedure TMainForm.IndexSearchEditOnScan (Sender: TObject; Var KeyCode: TKeyCode);
4496Begin
4497 case KeyCode of
4498 kbCUp:
4499 begin
4500 if IndexListBox.ItemIndex > 0 then
4501 IndexListBox.ItemIndex:= IndexListBox.ItemIndex - 1;
4502 KeyCode:= kbNull;
4503 end;
4504
4505 kbCDown:
4506 begin
4507 if IndexListBox.ItemIndex < IndexListBox.Items.Count - 1 then
4508 IndexListBox.ItemIndex:= IndexListBox.ItemIndex + 1;
4509 KeyCode:= kbNull;
4510 end;
4511
4512 kb_VK + VK_NEWLINE:
4513 begin
4514 DisplaySelectedIndexTopic;
4515 end;
4516 end;
4517
4518End;
4519
4520Procedure TMainForm.IndexSearchEditOnChange (Sender: TObject);
4521var
4522 tmpMatchIndex : longint;
4523 tmpSearchText: string;
4524 i : longint;
4525Begin
4526 if InIndexSearch then
4527 exit;
4528
4529 tmpMatchIndex := -1;
4530 tmpSearchText := trim(IndexSearchEdit.Text);
4531
4532 for i := 0 to DisplayedIndex.Count - 1 do
4533 begin
4534 if StrStartsWithIgnoringCase(DisplayedIndex[i], tmpSearchText) then
4535 begin
4536 tmpMatchIndex := i;
4537 break;
4538 end;
4539 end;
4540
4541 if tmpMatchIndex = -1 then
4542 exit;
4543
4544 InIndexSearch:= true;
4545
4546 if IndexListBox.ItemIndex <> tmpMatchIndex then
4547 IndexListBox.ItemIndex:= tmpMatchIndex;
4548
4549 InIndexSearch:= false;
4550End;
4551
4552Procedure TMainForm.FileInformationMIOnClick (Sender: TObject);
4553var
4554 FileIndex: longint;
4555 HelpFile: THelpFile;
4556
4557 TotalTopicCount: longint;
4558 TotalIndexCount: longint;
4559 TotalFileSize: longint;
4560
4561Begin
4562 TotalTopicCount := 0;
4563 TotalIndexCount := 0;
4564 TotalFileSize := 0;
4565
4566 with InformationForm.InformationMemo do
4567 begin
4568 BeginUpdate;
4569 Lines.Clear;
4570 Lines.Add( FilesInfoTitle );
4571 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4572 begin
4573 HelpFile := CurrentOpenFiles[ FileIndex ];
4574
4575 Lines.Add( FilesInfoFilename + HelpFile.FileName );
4576 Lines.Add( FilesInfoFileTitle
4577 + HelpFile.Title );
4578 Lines.Add( FilesInfoTopicCount
4579 + IntToStr( HelpFile.TopicCount ) );
4580 Lines.Add( FilesInfoIndexCount
4581 + IntToStr( HelpFile.Index.Count ) );
4582 Lines.Add( FilesInfoDictionaryCount
4583 + IntToStr( HelpFile.DictionaryCount ) );
4584 Lines.Add( FilesInfoFileSize
4585 + IntToStr( HelpFile.FileSize ) );
4586
4587 inc( TotalTopicCount, HelpFile.TopicCount );
4588 inc( TotalIndexCount, HelpFile.Index.Count );
4589 inc( TotalFileSize, HelpFile.FileSize );
4590
4591 end;
4592
4593 Lines.Add( '' );
4594 Lines.Add( FilesInfoTotalTopicCount
4595 + IntToStr( TotalTopicCount ) );
4596 Lines.Add( FilesInfoTotalIndexCount
4597 + IntToStr( TotalIndexCount ) );
4598 Lines.Add( FilesInfoTotalFileSize
4599 + IntToStr( TotalFileSize ) );
4600 Lines.Add( '' );
4601
4602 EndUpdate;
4603 end;
4604 InformationForm.ShowModal;
4605End;
4606
4607Procedure TMainForm.DisplaySelectedSearchResultTopic;
4608var
4609 Topic: TTopic;
4610Begin
4611 if SearchResultsListBox.ItemIndex = -1 then
4612 exit;
4613 if SelectedObject( SearchResultsListBox ) = nil then
4614 // the "no results" place holder
4615 exit;
4616 Topic := SelectedObject( SearchResultsListBox ) as TTopic;
4617 DisplayTopic( Topic );
4618End;
4619
4620Procedure TMainForm.SearchTextEditOnScan (Sender: TObject;
4621 Var KeyCode: TKeyCode);
4622Begin
4623 case KeyCode of
4624 kbCUp:
4625 begin
4626 if SearchResultsListBox.ItemIndex > 0 then
4627 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex - 1;
4628 KeyCode := kbNull;
4629 SearchResultsListBox.Focus;
4630 end;
4631
4632 kbCDown:
4633 begin
4634 if SearchResultsListBox.ItemIndex < SearchResultsListBox.Items.Count - 1 then
4635 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex + 1;
4636 KeyCode := kbNull;
4637 SearchResultsListBox.Focus;
4638 end;
4639 end;
4640End;
4641
4642Procedure TMainForm.SearchButtonOnClick (Sender: TObject);
4643Begin
4644 DoSearch;
4645End;
4646
4647// Matches old stupid View algorithm
4648Procedure TMainForm.StartupTopicSearch( const SearchText: string );
4649var
4650 i: longint;
4651 HelpFile: THelpFile;
4652 Topic: TTopic;
4653 // s: string;
4654begin
4655 // search files in order they are open
4656 for i := 0 to CurrentOpenFiles.Count - 1 do
4657 begin
4658 HelpFile := THelpFile( CurrentOpenFiles[ i ] );
4659
4660 // look for a topic whose title starts with the searchtext
4661 Topic := HelpFile.FindTopicByTitleStartsWith( SearchText );
4662
4663 if Topic = nil then
4664 // look for an index entry that starts with the searchtext
4665 Topic := HelpFile.FindTopicByIndexStartsWith( SearchText );
4666
4667 if Topic = nil then
4668 // look for a topic whose title contains the searchtext
4669 Topic := HelpFile.FindTopicByTitleContains( SearchText );
4670
4671 if Topic = nil then
4672 // look for an index entry that contains the searchtext
4673 Topic := HelpFile.FindTopicByIndexContains( SearchText );
4674
4675 if Topic <> nil then
4676 begin
4677 // found something, display it (don't keep searching files)
4678 DisplayTopic( Topic );
4679 exit;
4680 end;
4681 end;
4682 DoErrorDlg( SearchTitle, TextNotFoundMsg );
4683end;
4684
4685Procedure TMainForm.SearchFor( const SearchText: string );
4686begin
4687 SearchTextEdit.Text := SearchText;
4688 DisplaySearch;
4689 SearchResultsListBox.Focus;
4690
4691 // force repaint of everything before we start searching.
4692 Update;
4693
4694 DoSearch;
4695end;
4696
4697Procedure TMainForm.ClearAllWordSequences;
4698var
4699 i: longint;
4700 FileWordSequences: TList;
4701 HelpFile: THelpFile;
4702begin
4703 if AllFilesWordSequences = nil then
4704 exit;
4705
4706 for i := 0 to AllFilesWordSequences.Count - 1 do
4707 begin
4708 FileWordSequences := AllFilesWordSequences[ i ];
4709 HelpFile := CurrentOpenFiles[ i ];
4710 ClearWordSequences( FileWordSequences, HelpFile.DictionaryCount );
4711 FileWordSequences.Destroy;
4712 end;
4713 AllFilesWordSequences.Clear;
4714end;
4715
4716// Perform search for text in searchedit.
4717Procedure TMainForm.DoSearch;
4718var
4719 SearchResults: TList;
4720 SearchText: string;
4721 FileIndex: longint;
4722 HelpFile: THelpFile;
4723 TopicIndex: longint;
4724 Topic: TTopic;
4725 FileWordSequences: TList;
4726 Query: TTextSearchQuery;
4727begin
4728 SearchText := Trim( SearchTextEdit.Text );
4729
4730 SearchResultsListBox.Clear;
4731
4732 if SearchText = '' then
4733 exit;
4734
4735 SearchResultsListBox.Items.Add( SearchingMsg );
4736 SetStatus( SearchingMsg );
4737
4738 try
4739 Query := TTextSearchQuery.Create( SearchText );
4740 except
4741 on e: ESearchSyntaxError do
4742 begin
4743 DoErrorDlg( SearchTitle,
4744 SearchSyntaxError
4745 + e.Message );
4746 exit;
4747 end;
4748 end;
4749
4750 ClearAllWordSequences;
4751
4752 SetWaitCursor;
4753
4754 SearchResults := TList.Create;
4755
4756 // Search open help file
4757 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4758 begin
4759 HelpFile := CurrentOpenFiles[ FileIndex ];
4760
4761 FileWordSequences := TList.Create;
4762
4763 try
4764 SearchHelpFile( HelpFile,
4765 Query,
4766 SearchResults,
4767 FileWordSequences );
4768 except
4769 on E: EHelpFileException do
4770 begin
4771 DoErrorDlg( ErrorTitle, E.Message );
4772 Query.Destroy;
4773 ClearWaitCursor;
4774 exit;
4775 end;
4776 end;
4777
4778 AllFilesWordSequences.Add( FileWordSequences );
4779
4780 end;
4781
4782 // Sort results across all files by relevance
4783 SearchResults.Sort( TopicRelevanceCompare );
4784
4785 // Load topics into search results list.
4786 SearchResultsListBox.BeginUpdate;
4787 SearchResultsListBox.Clear;
4788
4789 for TopicIndex := 0 to SearchResults.Count - 1 do
4790 begin
4791 Topic := SearchResults[ TopicIndex ];
4792 SearchResultsListBox.Items.AddObject( Topic.Title
4793 + ' ['
4794 + IntToStr( Topic.SearchRelevance )
4795 + ']',
4796 Topic );
4797 end;
4798
4799 EnableControls;
4800 if SearchResultsListBox.Items.Count > 0 then
4801 // there are some search matches, so highlight words
4802 ViewHighlightSearchWordsMI.Checked := true;
4803
4804 SearchResultsListBox.ItemIndex := -1;
4805 SearchResultsListBox.EndUpdate;
4806
4807 Query.Destroy;
4808 SearchResults.Destroy;
4809
4810 if SearchResultsListBox.Items.Count > 0 then
4811 begin
4812 SearchResultsListBox.ItemIndex := 0;
4813 end
4814 else
4815 begin
4816 SearchResultsListBox.Items.Add( NoSearchMatchesMsg
4817 + ': '
4818 + SearchText );
4819 RefreshWindows( Windows ); // update to remove old highlights
4820 end;
4821 SetStatus( SearchFoundMsgA
4822 + IntToStr( SearchResultsListBox.Items.Count )
4823 + SearchFoundMsgB
4824 + StrInDoubleQuotes(SearchText)
4825 );
4826
4827 ClearWaitCursor;
4828
4829 DisplaySelectedSearchResultTopic;
4830
4831End;
4832
4833Procedure TMainForm.FileSaveAsMIOnClick (Sender: TObject);
4834var
4835 F: File;
4836 EntryText: PChar;
4837 TextLength: longint;
4838 Window: THelpWindow;
4839 Filename: string;
4840Begin
4841 Window := GetActiveWindow;
4842 if Window = nil then
4843 begin
4844 DoErrorDlg( FileSaveTitle,
4845 FileSaveSelectWindowError );
4846 exit;
4847 end;
4848
4849 if DoSaveFileDialog( FileSaveTitle,
4850 AllFilesDesc + '|*',
4851 DefaultSaveTopicFilename,
4852 Settings.LastSaveDirectory,
4853 Filename ) then
4854 begin
4855 if FileExists( Filename ) then
4856 if not DoConfirmDlg( FileSaveTitle,
4857 ReplaceFilePromptA
4858 + Filename
4859 + ReplaceFilePromptB ) then
4860 exit;
4861 System.Assign( F, Filename );
4862
4863 try
4864 Rewrite( F );
4865 except
4866 on E: Exception do
4867 begin
4868 DoErrorDlg( FileSaveTitle,
4869 UnableToSaveError
4870 + Filename
4871 + ': '
4872 + E.Message );
4873 exit;
4874 end;
4875 end;
4876
4877 // find out length of (plain) text
4878 TextLength := Window.View.CopyTextToBuffer( nil, -1 );
4879
4880 // allocate space
4881 EntryText:= StrAlloc( TextLength );
4882
4883 // get the plain text
4884 Window.View.CopyTextToBuffer( EntryText, TextLength );
4885
4886 // save to file
4887 System.BlockWrite( F, EntryText^, TextLength );
4888
4889 // free space
4890 StrDispose( EntryText );
4891
4892 System.Close( F );
4893 end;
4894End;
4895
4896Procedure TMainForm.OptionsMIOnClick (Sender: TObject);
4897begin
4898 DoOptions;
4899end;
4900
4901Procedure TMainForm.DoOptions;
4902Begin
4903 EnsureOptionsFormLoaded;
4904
4905 GetColors; // in case changed by drag drop
4906
4907 if OptionsForm.ShowModal = mrOK then
4908 begin
4909 ApplySettings;
4910 SetLayout;
4911 RefreshFontSubstitutions;
4912 RefreshWindows( Windows );
4913 end;
4914End;
4915
4916Procedure TMainForm.ShowUsage;
4917begin
4918 DoMessageDlg( UsageTitle,
4919 UsageText1 + StrCRLF
4920 + UsageText2 + StrCRLF
4921 + UsageText3 + StrCRLF
4922 + UsageText4 + StrCRLF
4923 + UsageText5 + StrCRLF
4924 + UsageText6 + StrCRLF
4925 + UsageText7 + StrCRLF
4926 + UsageText8 );
4927end;
4928
4929Procedure TMainForm.TabSetOnChange (Sender: TObject; NewTab: LongInt;
4930 Var AllowChange: Boolean);
4931Begin
4932 NoteBook.PageIndex := NewTab;
4933End;
4934
4935Procedure TMainForm.NotebookOnSetupShow (Sender: TObject);
4936Begin
4937 ContentsOutline.xStretch := xsFrame;
4938 ContentsOutline.yStretch := ysFrame;
4939
4940 IndexSearchEdit.yAlign := yaTop;
4941 IndexSearchEdit.xStretch := xsFrame;
4942 IndexListBox.yStretch := ysFrame;
4943 IndexListBox.xStretch := xsFrame;
4944
4945 SearchTextEdit.yAlign := yaTop;
4946 SearchTextEdit.xStretch := xsFrame;
4947 SearchButton.yAlign := yaTop;
4948 SearchButton.xAlign := xaRight;
4949 SearchResultsListBox.xStretch := xsFrame;
4950 SearchResultsListBox.yStretch := ysFrame;
4951
4952 NotesListBox.xStretch := xsFrame;
4953 NotesListBox.yStretch := ysFrame;
4954End;
4955
4956Procedure TMainForm.EnableControls;
4957var
4958 BackEnabled: boolean;
4959 ForwardEnabled: boolean;
4960 FileOpen: boolean;
4961 WindowOpen: boolean;
4962 AtTop: boolean;
4963 AtBottom: boolean;
4964begin
4965 ViewContentsMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piContents );
4966 ViewIndexMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piIndex );
4967 ViewSearchMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piSearch );
4968 ViewNotesMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piNotes );
4969
4970 BackEnabled := CurrentHistoryIndex > 0;
4971 ForwardEnabled := CurrentHistoryIndex < PageHistory.Count - 1;
4972
4973 FileOpen := CurrentOpenFiles.Count > 0;
4974 WindowOpen := Windows.Count > 0;
4975
4976 ViewContentsMI.Enabled := FileOpen;
4977 ViewIndexMI.Enabled := FileOpen;
4978 ViewSearchMI.Enabled := FileOpen;
4979 ViewNotesMI.Enabled := FileOpen;
4980
4981 ShowLeftPanelMI.Enabled := FileOpen;
4982
4983 Coolbar.Sections[ ciBack ].Disabled := not BackEnabled;
4984 NavigateBackMI.Enabled := BackEnabled;
4985 Coolbar.Sections[ ciForward ].Disabled := not ForwardEnabled;
4986 NavigateForwardMI.Enabled := ForwardEnabled;
4987
4988 FileSaveAsMI.Enabled := FileOpen;
4989
4990 Coolbar.Sections[ ciPrint ].Disabled := not FileOpen;
4991 PrintMI.Enabled := FileOpen;
4992 FileInformationMI.Enabled := FileOpen;
4993
4994 Coolbar.Sections[ ciAddBookmark ].Disabled := not FileOpen;
4995 AddBookmarkMI.Enabled := FileOpen;
4996 EditBookmarksMI.Enabled := FileOpen;
4997 Coolbar.Sections[ ciAddNote ].Disabled := not FileOpen;
4998 AddNoteMI.Enabled := FileOpen;
4999
5000 if ContentsOutline.SelectedNode <> nil then
5001 begin
5002 AtTop := ContentsOutline.NextNodeUp( ContentsOutline.SelectedNode, false ) = nil;
5003 AtBottom := ContentsOutline.NextNodeDown( ContentsOutline.SelectedNode, false ) = nil;
5004 end;
5005
5006 NavigateNextMI.Enabled := FileOpen
5007 and ( ContentsOutline.SelectedNode <> nil )
5008 and ( not AtBottom );
5009 Coolbar.Sections[ ciNext ].Disabled := not NavigateNextMI.Enabled;
5010 NavigatePreviousMI.Enabled := FileOpen
5011 and ( ContentsOutline.SelectedNode <> nil )
5012 and ( not AtTop );
5013 Coolbar.Sections[ ciPrevious ].Disabled := not NavigatePreviousMI.Enabled;
5014
5015 FileCloseMI.Enabled := FileOpen;
5016
5017 FindMI.Enabled := WindowOpen;
5018 FindNextMI.Enabled := WindowOpen;
5019 CopyMI.Enabled := WindowOpen;
5020 SelectAllMI.Enabled := WindowOpen;
5021
5022 ViewExpandAllMI.Enabled := ContentsOutline.ChildCount > 0;
5023 ViewCollapseAllMI.Enabled := ContentsOutline.ChildCount > 0;
5024
5025 DebugTopicByResourceIDMI.Enabled := FileOpen;
5026 TopicByNameMI.Enabled := FileOpen;
5027
5028 ViewHighlightSearchWordsMI.Enabled := SearchResultsListBox.Items.Count > 0;
5029 if not ViewHighlightSearchWordsMI.Enabled then
5030 ViewHighlightSearchWordsMI.Checked := false;
5031
5032 ViewRefreshMI.Enabled := WindowOpen;
5033
5034 EnableSearchButton;
5035 EnableNotesControls;
5036
5037 VSplitBar.Visible := FileOpen;
5038 if not FileOpen then
5039 begin
5040 SetShowLeftPanel( false );
5041 end;
5042
5043
5044end;
5045
5046Procedure TMainForm.NavigateBackMIOnClick (Sender: TObject);
5047begin
5048 NavigateBack;
5049end;
5050
5051Procedure TMainForm.SaveNavigatePoint;
5052var
5053 NavPoint: TNavigatePoint;
5054begin
5055 // delete rest of history.
5056 while CurrentHistoryIndex < PageHistory.Count - 1 do
5057 begin
5058 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex + 1 ] as TNavigatePoint;
5059 NavPoint.Destroy;
5060 PageHistory.Delete( CurrentHistoryIndex + 1 );
5061 end;
5062
5063 NavPoint:= TNavigatePoint.Create;
5064 SaveWindows( Windows, NavPoint.Windows, nil );
5065
5066 if ContentsOutline.SelectedNode <> nil then
5067 NavPoint.ContentsTopic:= ContentsOutline.SelectedNode.Data as TTopic
5068 else
5069 NavPoint.ContentsTopic:= nil;
5070
5071 if CurrentTopic <> nil then
5072 PageHistory.AddObject( CurrentTopic.Title, NavPoint )
5073 else
5074 PageHistory.AddObject( '', NavPoint );
5075
5076 inc( CurrentHistoryIndex );
5077
5078 CreateNavigateToMenuItems;
5079end;
5080
5081Procedure TMainForm.UpdateCurrentNavigatePoint;
5082var
5083 NavPoint: TNavigatePoint;
5084begin
5085 if CurrentHistoryIndex = -1 then
5086 exit;
5087
5088 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5089
5090 DestroyListObjects( NavPoint.Windows );
5091 NavPoint.Windows.Clear;
5092
5093 SaveWindows( Windows, NavPoint.Windows, nil );
5094end;
5095
5096Procedure TMainForm.ClearPageHistory;
5097var
5098 i: longint;
5099 NavPoint: TNavigatePoint;
5100begin
5101 for i := 0 to PageHistory.Count - 1 do
5102 begin
5103 NavPoint := PageHistory.Objects[ i ] as TNavigatePoint;
5104 NavPoint.Destroy;
5105 end;
5106 PageHistory.Clear;
5107 CurrentHistoryIndex := -1;
5108 CreateNavigateToMenuItems;
5109 EnableControls;
5110end;
5111
5112Procedure TMainForm.SaveWindows( SourceList: TList;
5113 DestList: TList;
5114 Parent: TSavedHelpWindow );
5115
5116var
5117 WindowIndex: longint;
5118 Window: THelpWindow;
5119 WindowCopy: TSavedHelpWindow;
5120begin
5121 // limit storage to only what's need since list will be static.
5122 DestList.Capacity := SourceList.Count;
5123 for WindowIndex := 0 to SourceList.Count - 1 do
5124 begin
5125 Window := SourceList[ WindowIndex ];
5126 WindowCopy := TSavedHelpWindow.Create;
5127 WindowCopy.Parent := Parent;
5128 WindowCopy.Rect.Assign( Window.Rect );
5129 WindowCopy.Topic := Window.Topic;
5130 WindowCopy.Group := Window.Group;
5131 WindowCopy.TopCharIndex := Window.View.TopCharIndex;
5132 SaveWindows( Window.ChildWindows, WindowCopy.ChildWindows, WindowCopy );
5133 DestList.Add( WindowCopy );
5134 end;
5135end;
5136
5137Procedure TMainForm.DisplayWindows( WindowList: TList;
5138 Parent: THelpWindow );
5139var
5140 WindowIndex: longint;
5141 WindowCopy: TSavedHelpWindow;
5142 NewWindow: THelpWindow;
5143begin
5144 for WindowIndex := 0 to WindowList.Count - 1 do
5145 begin
5146 WindowCopy := WindowList[ WindowIndex ];
5147 NewWindow := OpenWindow( WindowCopy.Topic,
5148 WindowCopy.Group,
5149 Parent,
5150 WindowCopy.Rect,
5151 false ); // don't follow links
5152 NewWindow.View.TopCharIndex := WindowCopy.TopCharIndex;
5153 DisplayWindows( WindowCopy.ChildWindows, NewWindow );
5154 end;
5155end;
5156
5157Procedure TMainForm.CreateNavigateToMenuItems;
5158var
5159 MenuItem: TMenuItem;
5160 i: integer;
5161begin
5162 // clear existing items
5163 DestroyListObjects( NavigateToMenuItems );
5164 NavigateToMenuItems.Clear;
5165
5166 if CurrentHistoryIndex > 0 then
5167 begin
5168 // We are going to add some items, so
5169 // add a seperator from the rest of the menu first
5170 MenuItem := TMenuItem.Create( self );
5171 MenuItem.Caption:= '-';
5172 NavigateMenu.Add( MenuItem );
5173 NavigateToMenuItems.Add( MenuItem );
5174 end;
5175
5176 i := CurrentHistoryIndex - 1; // don't include the current history item
5177 while ( ( i >= 0 )
5178 and ( i > CurrentHistoryIndex - 10 ) ) do
5179 begin
5180 MenuItem := TMenuItem.Create( self );
5181 MenuItem.Caption := PageHistory[ i ];
5182 MenuItem.Hint := GoBackHint
5183 + StrInDoubleQuotes( PageHistory[ i ] );
5184 MenuItem.OnClick := OnNavigateToMenuItemClick;
5185 MenuItem.Tag := i;
5186
5187 NavigateMenu.Add( MenuItem );
5188 NavigateToMenuItems.Add( MenuItem );
5189 dec( i );
5190 end;
5191end;
5192
5193Procedure TMainForm.NavigateToPoint( NavPoint: TNavigatePoint );
5194begin
5195 Navigating := true;
5196
5197 // close current windows
5198 CloseWindows;
5199
5200 // Display windows for the navigate point
5201 DisplayWindows( NavPoint.Windows, nil );
5202
5203 // Select the contents topic
5204 ContentsOutline.SetSelectedObject( NavPoint.ContentsTopic );
5205
5206 // Update the navigate menu (since a different set of
5207 // back-points are now available)
5208 CreateNavigateToMenuItems;
5209
5210 // Make the topic windows visible
5211 ShowWindows;
5212
5213 // Update back buttons etc...
5214 EnableControls;
5215
5216 Navigating := false;
5217end;
5218
5219Procedure TMainForm.NavigateToHistoryIndex( Index: longint );
5220var
5221 NavPoint: TNavigatePoint;
5222begin
5223 UpdateCurrentNavigatePoint;
5224 CurrentHistoryIndex := Index;
5225 NavPoint := PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5226 NavigateToPoint( NavPoint );
5227end;
5228
5229Procedure TMainForm.NavigateForward;
5230Begin
5231 if CurrentHistoryIndex < PageHistory.Count - 1 then
5232 begin
5233 NavigateToHistoryIndex( CurrentHistoryIndex + 1 );
5234 end;
5235End;
5236
5237Procedure TMainForm.NavigateBack;
5238Begin
5239 if CurrentHistoryIndex > 0 then
5240 begin
5241 NavigateToHistoryIndex( CurrentHistoryIndex - 1 );
5242 end;
5243End;
5244
5245Procedure TMainForm.NavigatePreviousInContents;
5246begin
5247 ContentsOutline.GotoNextNodeUp;
5248 DisplaySelectedContentsTopic;
5249end;
5250
5251Procedure TMainForm.NavigateNextInContents;
5252begin
5253 ContentsOutline.GotoNextNodeDown;
5254 DisplaySelectedContentsTopic;
5255end;
5256
5257Procedure TMainForm.CorrectNotesPositions( Topic: TTopic;
5258 Text: pchar );
5259var
5260 NoteIndex: longint;
5261 Note: THelpNote;
5262 p: pchar;
5263 NextP: pchar;
5264 Element: TTextElement;
5265 TextIndex: longint;
5266begin
5267 NoteIndex := 0;
5268 for NoteIndex := 0 to Notes.Count - 1 do
5269 begin
5270 Note := Notes[ NoteIndex ];
5271 if Note.Topic = Topic then
5272 begin
5273 // this note belongs the the specified topic.
5274 p := Text;
5275
5276 while true do
5277 begin
5278 Element := ExtractNextTextElement( p, NextP );
5279 if Element.ElementType = teTextEnd then
5280 break;
5281 TextIndex := PCharPointerDiff( p, Text );
5282 if TextIndex >= Note.InsertPoint then
5283 begin
5284 // found a safe point to insert
5285 if TextIndex <> Note.InsertPoint then
5286 begin
5287 // correct it.
5288 Note.InsertPoint := TextIndex;
5289 end;
5290 break;
5291 end;
5292
5293 p := NextP;
5294 end;
5295 end;
5296 end;
5297end;
5298
5299Procedure TMainForm.InsertNotesIntoTopicText( Topic: TTopic;
5300 Text: TAString );
5301var
5302 NoteIndex: longint;
5303 Note: THelpNote;
5304 ActualInsertPoint: longword;
5305begin
5306 CorrectNotesPositions( Topic, Text.AsPChar );
5307
5308 for NoteIndex := 0 to Notes.Count - 1 do
5309 begin
5310 Note := Notes[ NoteIndex ];
5311 if Note.Topic = Topic then
5312 begin
5313 // Adjust insert point for any notes we have already inserted.
5314 ActualInsertPoint := FindActualNoteCharIndex( Note.InsertPoint,
5315 NoteIndex,
5316 Topic );
5317 RefreshNoteInsertInfo( NoteIndex );
5318 Text.Insert( ActualInsertPoint, Note.InsertText );
5319 end;
5320 end;
5321end;
5322
5323Procedure TMainForm.NavigatePreviousMIOnClick (Sender: TObject);
5324Begin
5325 NavigatePreviousInContents;
5326End;
5327
5328Procedure TMainForm.NavigateNextMIOnClick (Sender: TObject);
5329Begin
5330 NavigateNextInContents;
5331End;
5332
5333Function TMainForm.GetActiveWindow: THelpWindow;
5334var
5335 View: TRichTextView;
5336 FirstWindow: THelpWindow;
5337begin
5338 Result := nil;
5339 if Screen.ActiveControl is TRichTextView then
5340 begin
5341 View := Screen.ActiveControl as TRichTextView;
5342 Result := FindWindowFromView( View, Windows );
5343 end
5344 else if Windows.Count = 1 then
5345 begin
5346 FirstWindow := Windows[ 0 ];
5347 if FirstWindow.ChildWindows.Count = 0 then
5348 Result := FirstWindow;
5349 end;
5350end;
5351
5352Procedure TMainForm.CopyMIOnClick (Sender: TObject);
5353var
5354 Window: THelpWindow;
5355begin
5356 if ActiveControl = nil then
5357 exit;
5358
5359 if ActiveControl is TEdit then
5360 begin
5361 // this is for the edit controls in the left panel
5362 TEdit( ActiveControl ).CopyToClipboard;
5363 exit;
5364 end;
5365
5366 // else copy from rtv in active help window
5367
5368 Window := GetActiveWindow;
5369 if Window = nil then
5370 exit;
5371
5372 Window.View.CopySelectionToClipboard;
5373End;
5374
5375Procedure TMainForm.SelectAllMIOnClick (Sender: TObject);
5376var
5377 Window: THelpWindow;
5378begin
5379 Window:= GetActiveWindow;
5380 if Window = nil then
5381 begin
5382 DoErrorDlg( SelectAllTitle,
5383 SelectAllWindowError );
5384 exit;
5385 end;
5386 Window.View.SelectAll;
5387End;
5388
5389Procedure TMainForm.DebugShowCodesMIOnClick (Sender: TObject);
5390Begin
5391 DebugShowCodesMI.Checked:= not DebugShowCodesMI.Checked;
5392 RefreshWindows( Windows );
5393End;
5394
5395Procedure TMainForm.HelpProductInformationMIOnClick (Sender: TObject);
5396Begin
5397 EnsureProductInformationFormLoaded;
5398 ProductInformationForm.ShowModal;
5399End;
5400
5401Procedure TMainForm.OnOverLink ( Sender: TRichTextView; LinkString: String);
5402var
5403 Link: THelpLink;
5404 LinkIndex: longint;
5405 Window: THelpWindow;
5406 LinkedTopic: TTopic;
5407 Filename: string;
5408 SourceFile: THelpFile;
5409 URL: string;
5410 LinkDetails: string;
5411 tmpLinkDetails : TStringList;
5412 ProgramInfo : TSerializableStringList;
5413 ProgramPath, ProgramLink : string;
5414Begin
5415 LogEvent(LogDebug, 'OnOverLink: "' + LinkString + '"');
5416
5417 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5418 begin
5419 SetStatus( EditNoteMsg )
5420 end
5421 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5422 begin
5423 ProgramInfo := TSerializableStringList.create;
5424// TODO check param here
5425
5426 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, Length(PARAM_LINK_PROGRAM) + 2));
5427 ProgramPath := ProgramInfo.get(0);
5428 ProgramLink := ProgramInfo.get(1);
5429 TSerializableStringList.destroy;
5430
5431 // call LaunchProgram here to inherit the environment
5432 SetStatus( LinkMsg + ' ' + ProgramPath + ' ' + ProgramLink);
5433 end
5434 else if StrStartsWith(LinkString, PARAM_LINK_URL) then
5435 begin
5436 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2); //
5437
5438 SetStatus( LinkMsg + URL );
5439 end
5440 else if StrStartsWith(LinkString, PARAM_LINK_EXTERNAL) then
5441 begin
5442 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5443
5444 tmpLinkDetails := TStringList.Create;
5445 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5446 LinkIndex := StrToInt(tmpLinkDetails[0]);
5447 tmpLinkDetails.Destroy;
5448
5449 Window := FindWindowFromView( Sender, Windows );
5450 SourceFile := Window.Topic.HelpFile as THelpFile;
5451 Filename := SourceFile.ReferencedFiles[ LinkIndex ];
5452 SetStatus( LinkMsg
5453 + StrInDoubleQuotes( Filename ) );
5454 end
5455 else
5456 begin
5457 Window := FindWindowFromView( Sender, Windows );
5458 LinkIndex := StrToInt( LinkString );
5459 Link := Window.Topic.Links[ LinkIndex ];
5460
5461 if Link is TFootnoteHelpLink then
5462 begin
5463 SetStatus( FootnoteMsg );
5464 end
5465 else
5466 begin
5467 LinkedTopic := FindTopicForLink( Link );
5468
5469 if LinkedTopic <> nil then
5470 begin
5471 SetStatus( LinkMsg
5472 + StrInDoubleQuotes( Trim( LinkedTopic.Title ) ) );
5473 end
5474 else
5475 begin
5476 SetStatus( UnknownLinkMsg );
5477 end;
5478 end;
5479 end;
5480End;
5481
5482Procedure TMainForm.OnNotOverLink ( Sender: TRichTextView; LinkString: String);
5483Begin
5484 SetStatus( '' );
5485end;
5486
5487Procedure TMainForm.OnClickLink ( Sender: TRichTextView; LinkString: String);
5488var
5489 Link: THelpLink;
5490 LinkIndex: longint;
5491 SourceWindow: THelpWindow;
5492 NoteIndex: longint;
5493 Window: THelpWindow;
5494 SourceFile: THelpFile;
5495 ProgramLink: string;
5496 ProgramPath: string;
5497 URL: string;
5498 LinkDetails: string;
5499 tmpLinkDetails : TStringList;
5500 ProgramInfo : TSerializableStringList;
5501Begin
5502 LogEvent(LogDebug, 'OnClickLink: "' + LinkString + '"');
5503
5504 if StrStartsWith(LinkString, PARAM_LINK_NOTE) then
5505 begin
5506 NoteIndex := StrToInt(StrSubstringFrom(LinkString, Length(PARAM_LINK_NOTE) + 2) );
5507 NotesListBox.ItemIndex := NoteIndex;
5508 EditNote( NoteIndex );
5509 end
5510 else if StrStartsWith(LinkString, PARAM_LINK_PROGRAM) then
5511 begin
5512 ProgramInfo := TSerializableStringList.create;
5513 ProgramInfo.readValuesFromSerializedString(StrSubstringFrom(LinkString, 9));
5514 ProgramPath := ProgramInfo.get(0);
5515 ProgramLink := ProgramInfo.get(1);
5516 TSerializableStringList.destroy;
5517
5518 // call LaunchProgram here to inherit the environment
5519 LogEvent(LogDisplay, 'LaunchProgram: "' + ProgramPath + '" "' + ProgramLink + '"');
5520 LaunchProgram(ProgramPath, ProgramLink, '');
5521 // TODO i18n
5522 SetStatus( 'Launched ' + ProgramPath );
5523 end
5524 else if StrLeft( LinkString, 3 ) = PARAM_LINK_URL then
5525 begin
5526 URL := StrSubstringFrom(LinkString, Length(PARAM_LINK_URL) + 2);
5527
5528 try
5529 LaunchURL(URL);
5530 except
5531 on E:Exception do
5532 begin
5533 DoErrorDlg('Error', E.Message);
5534 end;
5535 else raise;
5536 end;
5537
5538 // TODO i18n
5539 SetStatus('Opened ' + URL );
5540 end
5541 else if StrLeft( LinkString, 8 ) = PARAM_LINK_EXTERNAL then
5542 begin
5543 LinkDetails := StrSubstringFrom(LinkString, Length(PARAM_LINK_EXTERNAL) + 2);
5544
5545 tmpLinkDetails := TStringList.Create;
5546 StrExtractStrings(tmpLinkDetails, LinkDetails, [' '], #0);
5547 LinkIndex := StrToInt(tmpLinkDetails[0]);
5548 tmpLinkDetails.Destroy;
5549
5550 Window := FindWindowFromView( Sender, Windows );
5551 SourceFile := Window.Topic.HelpFile as THelpFile;
5552
5553 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5554 g_ExternalLinkTopic := LinkDetails;
5555 g_ExternalLinkSourceFilename := SourceFile.Filename;
5556 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5557
5558 PostMsg( Self.Handle,
5559 WM_FOLLOWEXTERNALLINK,
5560 0,
5561 0 );
5562 end
5563 else
5564 begin
5565 SourceWindow := FindWindowFromView( Sender, Windows );
5566 LinkIndex := StrToInt( LinkString );
5567 Link := SourceWindow.Topic.Links[ LinkIndex ];
5568
5569 PostMsg( Self.Handle,
5570 WM_FOLLOWLINK,
5571 longint( Link ),
5572 longint( SourceWindow ) );
5573
5574 end;
5575End;
5576
5577Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5578 var CanClose: boolean );
5579begin
5580 if Navigating then
5581 exit;
5582
5583 UpdateCurrentNavigatePoint; // Save it before close...
5584
5585 CanClose := true;
5586end;
5587
5588Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5589var
5590 ParentWindow: THelpWindow;
5591 WindowIndex: longint;
5592Begin
5593 if Navigating then
5594 exit;
5595
5596 if Window.ParentHelpWindow = nil then
5597 begin
5598 WindowIndex := Windows.IndexOf( Window );
5599 Windows.Delete( WindowIndex );
5600 end
5601 else
5602 begin
5603 ParentWindow := Window.ParentHelpWindow;
5604 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5605 ParentWindow.ChildWindows.Delete( WindowIndex );
5606 end;
5607end;
5608
5609Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5610Begin
5611 if Navigating then
5612 exit;
5613
5614 RemoveHelpWindowFromParent( Window );
5615
5616 SaveNavigatePoint;
5617 EnableControls;
5618End;
5619
5620Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5621Begin
5622 NavigateBack;
5623End;
5624
5625Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5626Begin
5627End;
5628
5629Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5630Begin
5631 Close;
5632End;
5633
5634Procedure TMainForm.CreateMRUMenuItems;
5635var
5636 MenuItem: TMenuItem;
5637 i: integer;
5638 FileName: string;
5639 FileNameIndex: longint;
5640 MRUText: string;
5641 MRUItem: TMRUItem;
5642begin
5643 DestroyListObjects( MRUMenuItems );
5644 MRUMenuItems.Clear;
5645
5646 // if there are Most Recently Used files
5647 if Settings.MRUList.Count > 0 then
5648 begin
5649 // create a seperator after Exit
5650 MenuItem:= TMenuItem.Create( self );
5651 MenuItem.Name := 'MRUSeparatorMI';
5652 MenuItem.Caption:= '-';
5653 FileMenu.Add( MenuItem );
5654 MRUMenuItems.Add( MenuItem );
5655 end;
5656
5657 // Add items for the MRU files
5658 for i:= 0 to Settings.MRUList.Count -1 do
5659 begin
5660 MRUItem := Settings.MRUList[ i ];
5661
5662 MenuItem := TMenuItem.Create( self );
5663
5664 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5665 MRUText := MRUItem.Title;
5666 if Trim( MRUText ) = '' then
5667 begin
5668 // Take the filenames, less path, as caption...
5669 MRUText := '';
5670 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5671 begin
5672 FileName := MRUItem.Filenames[ FileNameIndex ];
5673 FileName := ExtractFileName( FileName );
5674 FileName := ChangeFileExt( FileName, '' );// remove extension
5675
5676 if FileNameIndex > 0 then
5677 begin
5678 MRUText := MRUText + HELP_FILE_DELIMITER;
5679 end;
5680 MRUText := MRUText + FileName;
5681
5682 // stop after 50 chars
5683 if Length( MRUText ) > 50 then
5684 begin
5685 MRUText := MRUText + HELP_FILE_DELIMITER + ' ...';
5686 break;
5687 end;
5688 end;
5689 end;
5690
5691 MenuItem.Caption:= '~'
5692 + IntToStr( i + 1 )
5693 + '. '
5694 + MRUText;
5695 if MRUItem.Filenames.Count = 1 then
5696 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5697 else
5698 MenuItem.Hint := MRUItem.Title
5699 + ' ('
5700 + IntToStr( MRUItem.Filenames.Count )
5701 + ' '
5702 + MRUMultipleFilesHint
5703 + ')';
5704
5705 MenuItem.OnClick:= OnMRUMenuItemClick;
5706 MenuItem.Tag:= i;
5707 FileMenu.Add( MenuItem );
5708 MRUMenuItems.Add( MenuItem );
5709 end;
5710end;
5711
5712procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5713var
5714 Tag: longint;
5715 MenuItem: TMenuItem;
5716 MRUItem: TMRUItem;
5717begin
5718 MenuItem:= Sender as TMenuItem;
5719 Tag:= MenuItem.Tag;
5720 MRUItem := Settings.MRUList[ Tag ];
5721// RBRi woher kommt die liste?
5722 if OpenFiles( MRUItem.FileNames, '', true ) then
5723 begin
5724 ClearHelpManager;
5725 end;
5726end;
5727
5728Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5729var
5730 MenuItem: TMenuItem;
5731 Tag: longint;
5732begin
5733 MenuItem:= Sender as TMenuItem;
5734 Tag:= MenuItem.Tag;
5735 NavigateToHistoryIndex( Tag );
5736end;
5737
5738Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5739 ParentNode: TNode;
5740 Level: longint;
5741 Var TopicIndex: longint );
5742var
5743 Topic: TTopic;
5744 Node: TNode;
5745begin
5746 assert( ParentNode <> nil );
5747 Node := nil;
5748 while TopicIndex < HelpFile.TopicCount do
5749 begin
5750 Topic:= HelpFile.Topics[ TopicIndex ];
5751
5752 if Topic.ShowInContents then
5753 begin
5754 if Topic.ContentsLevel < Level then
5755 break;
5756
5757 if Topic.ContentsLevel = Level then
5758 begin
5759 Node:= ParentNode.AddChild( Topic.Title,
5760 Topic );
5761 inc( TopicIndex );
5762 end
5763 else
5764 begin
5765 assert( Node <> nil );
5766 AddChildNodes( HelpFile,
5767 Node,
5768 Topic.ContentsLevel,
5769 TopicIndex );
5770 Node := nil;
5771 end
5772 end
5773 else
5774 begin
5775 inc( TopicIndex );
5776 end;
5777 end;
5778
5779end;
5780
5781Procedure TMainForm.LoadContents( Files: TList;
5782 Var FirstNode: TNode );
5783var
5784 TopicIndex: longint;
5785 Topic: TTopic;
5786 Node: TNode;
5787 FileIndex: longint;
5788 HelpFile: THelpFile;
5789begin
5790 ContentsOutline.BeginUpdate;
5791 LogEvent(LogStartup, 'Load contents outline');
5792
5793 // we don't clear it first, to allow adding additional files
5794 // into the contents tree
5795
5796 LogEvent(LogStartup, 'Loop files');
5797
5798 FirstNode := nil;
5799
5800 Node := nil;
5801
5802 for FileIndex:= 0 to Files.Count - 1 do
5803 begin
5804 HelpFile := Files[ FileIndex ];
5805 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5806 TopicIndex := 0;
5807 while TopicIndex < HelpFile.TopicCount do
5808 begin
5809 Topic := HelpFile.Topics[ TopicIndex ];
5810 assert( Topic.ContentsLevel >= 0,
5811 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5812 if Topic.ShowInContents then
5813 begin
5814 if Topic.ContentsLevel = 1 then
5815 begin
5816 Node := ContentsOutline.AddChild( Topic.Title,
5817 Topic );
5818 if FirstNode = nil then
5819 FirstNode := node;
5820
5821 inc( TopicIndex );
5822 end
5823 else
5824 begin
5825 // subnodes
5826 assert( Node <> nil, 'No level 1 topic for subnodes!' );
5827 AddChildNodes( HelpFile,
5828 Node,
5829 Topic.ContentsLevel,
5830 TopicIndex );
5831 Node := nil;
5832 end;
5833 end
5834 else
5835 begin
5836 inc( TopicIndex );
5837 end;
5838 end;
5839 end;
5840 LogEvent(LogStartup, ' EndUpdate' );
5841 ContentsOutline.EndUpdate;
5842
5843 if Settings.OpenWithExpandedContents then
5844 begin
5845 LogEvent(LogStartup, ' Expand all contents' );
5846 ContentsOutline.ExpandAll
5847 end
5848 else if ContentsOutline.ChildCount = 1 then
5849 begin
5850 LogEvent(LogStartup, ' Expand first node' );
5851 // Contents has only one top level node... expand it
5852 FirstNode.Expand;
5853 end;
5854
5855 ContentsLoaded := true;
5856 LogEvent(LogStartup, ' Contents loaded' );
5857
5858end;
5859
5860Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5861var
5862 NotesFileName: string;
5863 TopicIndex: longword;
5864 Note: THelpNote;
5865 NoteIndex: longint;
5866
5867 NotesFile: HFile;
5868 OpenAction: ULong;
5869 rc: APIRET;
5870 CName: Cstring;
5871 FileNoteCount: integer;
5872
5873begin
5874 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5875
5876 if not HelpFile.NotesLoaded then
5877 // we never loaded the notes/displayed a topic from this file
5878 // so don't do anything.
5879 exit;
5880
5881 LogEvent(LogStartup, 'Really saving' );
5882
5883 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5884
5885 FileNoteCount := 0;
5886 for NoteIndex := 0 to Notes.Count - 1 do
5887 begin
5888 Note := Notes[ NoteIndex ];
5889
5890 if Note.Topic.HelpFile = HelpFile then
5891 inc( FileNoteCount );
5892 end;
5893
5894 if FileNoteCount = 0 then
5895 begin
5896 // no notes. delete notes file if it already exists.
5897 if FileExists( NotesFileName ) then
5898 DeleteFile( NotesFileName );
5899 exit;
5900 end;
5901
5902 CName:= NotesFileName;
5903 rc:= DosOpen( CName,
5904 NotesFile,
5905 OpenAction,
5906 0, // file size
5907 0, // attrs
5908 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5909 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5910 nil ); // no eas
5911 if rc <> 0 then
5912 begin
5913 DoErrorDlg( SaveNotesTitle,
5914 SaveNotesError
5915 + StrCRLF
5916 + NotesFileName
5917 + StrCRLF
5918 + SysErrorMessage( rc ) );
5919 exit;
5920 end;
5921
5922 for NoteIndex:= 0 to Notes.Count - 1 do
5923 begin
5924 Note:= Notes[ NoteIndex ];
5925
5926 if Note.Topic.HelpFile <> HelpFile then
5927 continue;
5928
5929 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5930
5931 MyWriteLn( NotesFile,
5932 IntToStr( TopicIndex ));
5933 MyWriteLn( NotesFile,
5934 IntToStr( Note.InsertPoint ) );
5935
5936 MyWrite( NotesFile,
5937 Note.Text.AsPChar,
5938 Note.Text.Length );
5939
5940 MyWriteLn( NotesFile,
5941 '' );
5942 MyWriteLn( NotesFile,
5943 '#ENDNOTE#' );
5944
5945 end;
5946
5947 DosClose( NotesFile );
5948end;
5949
5950Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5951var
5952 NotesFileName: string;
5953 TopicIndex: longint;
5954 InsertPoint: longint;
5955 Note: THelpNote;
5956
5957 NotesFile: HFile;
5958 OpenAction: ULong;
5959 rc: APIRET;
5960 CName: Cstring;
5961
5962 Paragraph: TAString;
5963 NotEOF: boolean;
5964 NoteText: TAString;
5965
5966begin
5967 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5968
5969 if HelpFile.NotesLoaded then
5970 exit;
5971
5972 HelpFile.NotesLoaded := true;
5973 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5974
5975 if not FileExists( NotesFileName ) then
5976 // no notes
5977 exit;
5978
5979 CName := NotesFileName;
5980 rc := DosOpen( CName,
5981 NotesFile,
5982 OpenAction,
5983 0, // file size - irrelevant, not creating,
5984 0, // attrs - ''
5985 OPEN_ACTION_OPEN_IF_EXISTS,
5986 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5987 nil ); // no eas
5988 if rc <> 0 then
5989 begin
5990 DoErrorDlg( LoadNotesTitle,
5991 LoadNotesError
5992 + StrCRLF
5993 + NotesFileName
5994 + StrCRLF
5995 + SysErrorMessage( rc ) );
5996 exit;
5997 end;
5998
5999 Paragraph := TAString.Create;
6000 NoteText := TAString.Create;
6001
6002 NotEOF := true;
6003
6004 while NotEOF do
6005 begin
6006 // Read contents index
6007 NotEOF := Paragraph.ReadParagraph( NotesFile );
6008 if not NotEOF then
6009 continue;
6010 try
6011 TopicIndex := StrToInt( Paragraph.AsString );
6012 except
6013 TopicIndex := -1;
6014 end;
6015
6016 // Read insert point
6017 NotEOF := Paragraph.ReadParagraph( NotesFile );
6018 if not NotEOF then
6019 continue;
6020 try
6021 InsertPoint := StrToInt( Paragraph.AsString );
6022 except
6023 InsertPoint := -1;
6024 end;
6025
6026 NoteText.Clear;
6027
6028 while NotEOF do
6029 begin
6030 NotEOF := Paragraph.ReadParagraph( NotesFile );
6031 if Paragraph.SameAs( '#ENDNOTE#' ) then
6032 begin
6033 // found end of note
6034 if ( TopicIndex >= 0 )
6035 and ( InsertPoint >= 0 ) then
6036 begin
6037 Note := THelpNote.Create;
6038 Note.Topic := HelpFile.Topics[ TopicIndex ];
6039 Note.InsertPoint := InsertPoint;
6040
6041 // Remove the last end line
6042 Note.Text.Assign( NoteText );
6043 if Note.Text.Length > 2 then
6044 Note.Text.Delete( Note.Text.Length - 2, 2 );
6045
6046 Notes.Add( Note );
6047 end;
6048 break;
6049 end;
6050 NoteText.Add( Paragraph );
6051 NoteText.AddString( #13 + #10 );
6052 end;
6053
6054 end;
6055 DosClose( NotesFile );
6056
6057 Paragraph.Destroy;
6058 NoteText.Destroy;
6059
6060end;
6061
6062Procedure TMainForm.UpdateNotesDisplay;
6063var
6064 NoteIndex: longint;
6065 Note: THelpNote;
6066 NoteTitle: string;
6067begin
6068 NotesListBox.Clear;
6069 for NoteIndex := 0 to Notes.Count - 1 do
6070 begin
6071 Note := Notes[ NoteIndex ];
6072
6073 if Note.Topic > nil then
6074 NoteTitle := Note.Topic.Title
6075 else
6076 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6077 NotesListBox.Items.AddObject( NoteTitle,
6078 Note );
6079 end;
6080 EnableNotesControls;
6081end;
6082
6083Procedure TMainForm.EnableNotesControls;
6084var
6085 NoteSelected: boolean;
6086begin
6087 NoteSelected:= NotesListBox.ItemIndex <> -1;
6088 EditNoteButton.Enabled:= NoteSelected;
6089 GotoNoteButton.Enabled:= NoteSelected;
6090 DeleteNoteButton.Enabled:= NoteSelected;
6091 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6092end;
6093
6094Function TMainForm.OKToCloseFile: boolean;
6095begin
6096 Result := true;
6097
6098 if PrintThread = nil then
6099 // haven't used print thread yet
6100 exit;
6101
6102 if not PrintThread.IsRunning then
6103 // not currently running
6104 exit;
6105
6106 Result := DoConfirmDlg( CheckStopPrintTitle,
6107 CheckStopPrintMsg );
6108
6109end;
6110
6111Procedure TMainForm.StopPrinting;
6112begin
6113 if PrintThread <> nil then
6114 begin
6115 if PrintThread.IsRunning then
6116 begin
6117 SetStatus( StoppingPrintMsg );
6118 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6119 SetStatus( PrintStoppedMsg );
6120 ResetProgress;
6121 end;
6122 end;
6123end;
6124
6125Procedure TMainForm.CloseFile;
6126var
6127 FileIndex: longint;
6128 HelpFile: THelpFile;
6129 M1: longint;
6130begin
6131 StopPrinting;
6132
6133 LogEvent(LogShutdown, 'Set Caption' );
6134 MainTitle := '';
6135 SetMainCaption;
6136
6137 LogEvent(LogShutdown, 'Close Windows' );
6138 CloseWindows;
6139
6140 LogEvent(LogShutdown, 'Set selected node to nil' );
6141 ContentsOutline.SelectedNode:= Nil;
6142
6143 M1:= MemAvail;
6144
6145 LogEvent(LogShutdown, 'Clear contents outline' );
6146 ContentsOutline.Clear;
6147
6148 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6149 M1:= MemAvail;
6150
6151 DisplayedIndex.Clear;
6152 IndexListBox.Clear;
6153 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6154 M1:= MemAvail;
6155
6156 NotesListBox.Clear;
6157 SearchResultsListBox.Clear;
6158
6159 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6160 M1:= MemAvail;
6161
6162 // First save notes and bookmarks.
6163 // It's important we do this first
6164 // since we scan all notes each time to find the ones
6165 // belonging to this file.
6166 SaveBookmarks;
6167
6168 SaveNotes;
6169
6170 ClearAllWordSequences;
6171
6172 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6173
6174 // Now destroy help files
6175 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6176 begin
6177 HelpFile := CurrentOpenFiles[ FileIndex ];
6178 GlobalFilelist.RemoveFile( Frame.Handle,
6179 HelpFile.Filename );
6180 HelpFile.Free;
6181 end;
6182
6183 CurrentOpenFiles.Clear;
6184
6185 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6186 M1 := MemAvail;
6187
6188 LogEvent(LogShutdown, 'Clear notes' );
6189 ClearNotes;
6190
6191 LogEvent(LogShutdown, 'Clear bookmarks' );
6192 ClearBookmarks;
6193
6194 ClearPageHistory;
6195
6196 LogEvent(LogShutdown, 'Enable controls' );
6197 EnableControls;
6198
6199 LogEvent(LogShutdown, 'CloseFile done' );
6200
6201end;
6202
6203Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6204var
6205 FileIndex: longint;
6206begin
6207 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6208 begin
6209 Result:= CurrentOpenFiles[ FileIndex ];
6210 if StrEqualIgnoringCase( Result.Filename, FileName ) then
6211 // found
6212 exit;
6213 end;
6214 Result:= nil;
6215end;
6216
6217// This rather horrendous looking bit of code simply:
6218
6219// Gets the contents from each file
6220// Sorts it alphabetically.
6221// Merges all the sorted contents and indexes together,
6222// alphabetically.
6223type
6224 TListType = ( ltContents, ltIndex );
6225
6226procedure TMainForm.LoadIndex;
6227var
6228 tmpHelpFile: THelpFile;
6229 tmpTextCompareResult: integer;
6230
6231 FileIndex: longint;
6232
6233 Contents: TList;
6234 ContentsLists: TList; // of tlist
6235 tmpIndexLists: TList; // of tstringlist
6236 ContentsNextIndex: array[ 0..255 ] of longint;
6237 IndexNextIndex: array[ 0..255 ] of longint;
6238 Topic: TTopic;
6239
6240 pListEntry: pstring;
6241 pLowestEntry: pstring;
6242 pLastEntry: pstring;
6243
6244 tmpLowestEntryListIndex: longint;
6245 tmpLowestEntryListType: TListType;
6246 tmpLowestEntryTopic: TTopic;
6247
6248 tmpIndex: TStringList;
6249
6250 i : longint;
6251begin
6252 LogEvent(LogStartup, 'Create index' );
6253
6254 SetWaitCursor;
6255
6256 LogEvent(LogStartup, ' Get/sort lists' );
6257
6258 ProgressBar.Position := 70;
6259 SetStatus( 'Building index... ' );
6260
6261 ContentsLists := TList.Create;
6262 tmpIndexLists := TList.Create;
6263
6264 // collect the contents and index lists from the files
6265 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6266 begin
6267 tmpHelpFile := CurrentOpenFiles[ FileIndex ];
6268 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6269
6270 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6271 begin
6272 Contents := TList.Create;
6273 Contents.Capacity := tmpHelpFile.TopicCount;
6274
6275 // copy [contents] topic list
6276 for i := 0 to tmpHelpFile.TopicCount - 1 do
6277 begin
6278 Topic := tmpHelpFile.Topics[ i ];
6279 if Topic.ShowInContents then
6280 Contents.Add( Topic );
6281 end;
6282
6283 // sort by title
6284 Contents.Sort( TopicTitleCompare );
6285
6286 ContentsLists.Add( Contents );
6287
6288 // initialise list index
6289 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6290 end;
6291
6292 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6293 begin
6294 tmpIndexLists.Add(tmpHelpFile.Index.GetLabels);
6295 IndexNextIndex[ tmpIndexLists.Count - 1 ] := 0;
6296 end;
6297 end;
6298
6299 // Unlike contents, we do clear the index
6300 // (even if we are adding more files) because we need
6301 // to re-merge the whole thing
6302 DisplayedIndex.Clear;
6303 ProgressBar.Position := 80;
6304
6305 LogEvent(LogStartup, ' Merge lists' );
6306
6307 pLastEntry := NullStr;
6308 while true do
6309 begin
6310 pLowestEntry := NullStr;
6311 tmpLowestEntryListIndex := -1;
6312
6313 // Find alphabetically lowest (remaining) topic
6314
6315 // first, look in contents lists
6316 LogEvent(LogDebug, ' Merge contents' );
6317 for i := 0 to ContentsLists.Count - 1 do
6318 begin
6319 Contents := ContentsLists[i];
6320 if ContentsNextIndex[i] < Contents.Count then
6321 begin
6322 // list is not yet finished, get next entry
6323 Topic := Contents[ ContentsNextIndex[i] ];
6324 pListEntry := Topic.TitlePtr;
6325
6326 if pLowestEntry^ <> '' then
6327 tmpTextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6328 else
6329 tmpTextCompareResult := -1;
6330
6331 if tmpTextCompareResult < 0 then
6332 begin
6333 // this index entry comes before the lowest one so far
6334 pLowestEntry := pListEntry;
6335 tmpLowestEntryListIndex := i;
6336 tmpLowestEntryListType := ltContents;
6337 tmpLowestEntryTopic := Topic;
6338 end;
6339 end;
6340 end;
6341
6342 // look in indices
6343 LogEvent(LogDebug, ' Merge indices' );
6344 for i := 0 to tmpIndexLists.Count - 1 do
6345 begin
6346 LogEvent(LogDebug, ' Merge indices ' + IntToStr(i) );
6347 tmpIndex := tmpIndexLists[i];
6348 if IndexNextIndex[i] < tmpIndex.Count then
6349 begin
6350 // list is not yet finished, get next entry
6351 pListEntry := tmpIndex.ValuePtrs[ IndexNextIndex[i] ];
6352
6353 if pLowestEntry^ <> '' then
6354 tmpTextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6355 else
6356 tmpTextCompareResult := -1;
6357
6358 if tmpTextCompareResult < 0 then
6359 begin
6360 // this index entry comes before the lowest one so far
6361 pLowestEntry := pListEntry;
6362 tmpLowestEntryListIndex := i;
6363 tmpLowestEntryListType := ltIndex;
6364
6365 LogEvent(LogDebug, ' Merge indices ' + tmpIndex.Objects[ IndexNextIndex[i] ].ClassName);
6366 tmpLowestEntryTopic := TIndexEntry( tmpIndex.Objects[ IndexNextIndex[i] ] ).getTopic;
6367 end;
6368 end;
6369 end;
6370
6371 if tmpLowestEntryListIndex = -1 then
6372 // we're out
6373 break;
6374
6375 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6376 // add, if different from last
6377 DisplayedIndex.AddObject( pLowestEntry^, tmpLowestEntryTopic );
6378 pLastEntry := pLowestEntry;
6379
6380 if tmpLowestEntryListType = ltContents then
6381 begin
6382 inc( ContentsNextIndex[ tmpLowestEntryListIndex ] );
6383 end
6384 else
6385 begin
6386 // found in one of indices.
6387 // Check for subsequent indented strings
6388 tmpIndex := tmpIndexLists[ tmpLowestEntryListIndex ];
6389
6390 i := IndexNextIndex[ tmpLowestEntryListIndex ] + 1;
6391 while i < tmpIndex.Count do
6392 begin
6393 pListEntry := tmpIndex.ValuePtrs[ i ];
6394 if pListEntry^ = '' then
6395 break;
6396
6397 if pListEntry^[ 1 ] <> ' ' then
6398 // not indented, stop looking
6399 break;
6400
6401 // found one,
6402 Topic := TIndexEntry(tmpIndex.Objects[ i ]).getTopic;
6403 DisplayedIndex.AddObject( pListEntry^,
6404 Topic );
6405 inc( i );
6406 end;
6407 IndexNextIndex[ tmpLowestEntryListIndex ] := i;
6408 end;
6409 end;
6410
6411 ProgressBar.Position := 95;
6412 LogEvent(LogStartup, ' Display index (count = '
6413 + IntToStr( DisplayedIndex.Count )
6414 + ')' );
6415
6416 // Now display the final index list
6417 IndexListBox.Items.Assign( DisplayedIndex );
6418
6419 LogEvent(LogStartup, ' Tidy up' );
6420
6421 tmpIndexLists.Destroy;
6422
6423 DestroyListAndObjects( ContentsLists );
6424
6425 IndexLoaded := true;
6426
6427 ClearWaitCursor;
6428
6429 SetStatus( 'Index loaded' );
6430 LogEvent(LogStartup, ' Done' );
6431end;
6432
6433Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6434 message: string );
6435var
6436 ProgressOnFiles: longint;
6437 Filename: string;
6438 ProgressOnThisFile: longint;
6439
6440begin
6441 Filename := LoadingFilenameList[ LoadingFileIndex ];
6442
6443 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6444 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6445
6446 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6447 100,
6448 LoadingFileMsg
6449 + ExtractFileName( Filename )
6450 + ': '
6451 + message );
6452end;
6453
6454Procedure TMainForm.SetProgress( n, outof: integer;
6455 message: string );
6456begin
6457 ProgressBar.Position := n * 100 div outof;
6458 SetStatus( message );
6459 ProgressBar.Show;
6460end;
6461
6462// Load a single file.
6463Function TMainForm.OpenFile( const FileName: string;
6464 const WindowTitle: string;
6465 const SelectFirstContentsNode: boolean ): boolean;
6466var
6467 tmpFileNames: TStringList;
6468begin
6469 tmpFileNames := TStringList.Create;
6470 ParseAndExpandFileNames(FileName, tmpFileNames);
6471 Result := OpenFiles( tmpFileNames,
6472 WindowTitle,
6473 DisplayFirstTopic );
6474 tmpFileNames.Destroy;
6475end;
6476
6477Function TMainForm.OpenAdditionalFile( const FileName: string;
6478 const DisplayFirstTopic: boolean ): boolean;
6479var
6480 tmpFileNames: TStringList;
6481begin
6482 tmpFileNames := TStringList.Create;
6483 ParseAndExpandFileNames(FileName, tmpFileNames);
6484 Result := OpenAdditionalFiles(tmpFileNames, DisplayFirstTopic );
6485 tmpFileNames.Destroy;
6486end;
6487
6488Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6489var
6490 WinHelpDetails: PROGDETAILS;
6491 szFilename: cstring;
6492begin
6493
6494 result := true;
6495 if Settings.ConfirmWinHelp then
6496 result := DoYesNoDlg( WindowsHelpTitle,
6497 WindowsHelpPrompt
6498 + StrCRLF
6499 + FileName );
6500 if not result then
6501 exit;
6502
6503 szFilename := FileName;
6504 with WinHelpDetails do
6505 begin
6506 Length := sizeof( WinHelpDetails );
6507 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6508 progt.fbVisible := SHE_VISIBLE;
6509 pszTitle := ''; // not used?
6510 pszExecutable := 'winhelp.exe';
6511 pszParameters := Addr( szFilename );
6512 pszStartupDir := nil;
6513 pszIcon := nil;
6514 pszEnvironment := nil;
6515 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6516 end;
6517
6518 result := WinStartApp( NULLHANDLE,
6519 WinHelpDetails,
6520 '',
6521 nil,
6522 SAF_INSTALLEDCMDLINE ) <> 0;
6523
6524 // Doesn't work for Dos/Win programs
6525 // RunProgram( 'winhelp.exe', FileName );
6526end;
6527
6528// Load the specified set of help files
6529Function TMainForm.LoadFiles(const aFileNames: TStrings; aHelpFiles: TList) : boolean;
6530var
6531 HelpFile: THelpFile;
6532 FileIndex, i: longint;
6533 FileName: string;
6534 FullFilePath: string;
6535
6536 FileHandlesAdjustNum: LONG;
6537 CurrentMaxFileHandles: ULONG;
6538 RequiredFileHandles: LONG;
6539begin
6540 LogEvent(LogStartup, 'LoadFiles' );
6541
6542 LoadingFilenameList := TStringList.Create;
6543
6544// RBRi TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6545 for i := 0 to aFileNames.Count - 1 do
6546 begin
6547 LoadingFilenameList.Add(aFileNames[i]);
6548 end;
6549
6550 LogEvent(LogStartup, 'Finding files' );
6551
6552 ProgressBar.Show;
6553
6554 // now find full file paths,
6555 // and also the total file size for progress display
6556 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6557 begin
6558 FileName := LoadingFilenameList[ FileIndex ];
6559 LogEvent(LogStartup, ' File: ' + FileName );
6560
6561 // Find the help file, if possible
6562 if Filename = OWN_HELP_MARKER then
6563 begin
6564 FullFilePath := CmdLineParameters.GetOwnHelpFileName;
6565 end
6566 else
6567 begin
6568 FullFilePath := FindHelpFile( Filename );
6569 end;
6570
6571 if FullFilePath <> '' then
6572 begin
6573 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6574 end
6575 else
6576 begin
6577 LogEvent(LogStartup, ' File not found' );
6578 FullFilePath := FileName; // we'll complain later.
6579 end;
6580 LoadingFilenameList[ FileIndex ] := FullFilePath;
6581 end;
6582
6583 // Make sure we have enough file handles
6584
6585 FileHandlesAdjustNum := 0;
6586 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6587 CurrentMaxFileHandles );
6588
6589 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6590 + LoadingFilenameList.Count // new ones
6591 + 40; // some spares.
6592 if CurrentMaxFileHandles < RequiredFileHandles then
6593 begin
6594 // need some more
6595 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6596 DosSetRelMaxFH( FileHandlesAdjustNum,
6597 CurrentMaxFileHandles );
6598 end;
6599
6600 // Now actually load the files
6601 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6602 begin
6603 Filename := LoadingFilenameList[ FileIndex ];
6604 LogEvent(LogStartup, ' Loading: ' + Filename );
6605 try
6606 LoadingFileIndex := FileIndex;
6607
6608 // load the file
6609 HelpFile := THelpFile.Create( FileName );
6610 if Settings.FixedFontSubstitution then
6611 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6612
6613 aHelpFiles.Add( HelpFile );
6614
6615 except
6616 on E: Exception do
6617 begin
6618
6619 if E is EWindowsHelpFormatException then
6620 begin
6621 OpenWindowsHelp( Filename );
6622 end
6623 else
6624 begin
6625 DoErrorDlg( FileOpenTitle,
6626 HelpFileError
6627 + FileName
6628 + ': '
6629 + E.Message );
6630 end;
6631
6632 // back out of the load process
6633 Result := false;
6634
6635 DestroyListObjects( aHelpFiles );
6636
6637 LoadingFilenameList.Destroy;
6638 ResetProgress;
6639 exit;
6640 end
6641 end;
6642 end;
6643
6644 LoadingFilenameList.Destroy;
6645
6646 Result := true;
6647
6648end;
6649
6650// Add the current list of open files as
6651// a Most Recently Used entry
6652Procedure TMainForm.AddCurrentToMRUFiles;
6653var
6654 tmpFilenames: TStringList;
6655 i: longint;
6656 tmpHelpFile: THelpFile;
6657begin
6658 tmpFilenames := TStringList.Create;
6659
6660 if CurrentOpenFiles.Count > 0 then
6661 begin
6662 for i := 0 to CurrentOpenFiles.Count - 1 do
6663 begin
6664 tmpHelpFile := CurrentOpenFiles[ i ];
6665 tmpFilenames.Add(tmpHelpFile.Filename);
6666 end;
6667
6668 // update most-recently-used file list
6669 tmpHelpFile := CurrentOpenFiles[ 0 ];
6670 AddToMRUList(tmpHelpFile.Title, tmpFilenames);
6671 end;
6672
6673 // recreate menu
6674 CreateMRUMenuItems;
6675
6676 tmpFilenames.Destroy;
6677end;
6678
6679// Display the specified set of files
6680Procedure TMainForm.DisplayFiles( NewFiles: TList;
6681 Var FirstContentsNode: TNode );
6682var
6683 HelpFile: THelpFile;
6684 FileIndex: longint;
6685begin
6686 LogEvent(LogStartup, 'DisplayFiles' );
6687 // Now load the various parts of the file(s)
6688 // into the user interface
6689 ProgressBar.Position := 50;
6690 SetStatus( LoadingStatusDisplaying );
6691
6692 // Add our open files in the global filelist
6693 for FileIndex := 0 to NewFiles.Count - 1 do
6694 begin
6695 HelpFile := NewFiles[ FileIndex ];
6696 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6697 // LoadNotes( HelpFile );
6698 LoadBookmarks( HelpFile );
6699 end;
6700
6701 UpdateNotesDisplay;
6702
6703 BuildBookmarksMenu;
6704 UpdateBookmarksForm;
6705
6706 ProgressBar.Position := 55;
6707
6708 ContentsLoaded := false;
6709 IndexLoaded := false;
6710
6711 LoadContents( NewFiles, FirstContentsNode );
6712
6713 ProgressBar.Position := 75;
6714
6715 // LoadIndex;
6716
6717 ProgressBar.Position := 100;
6718 SetStatus( LoadingStatusDone );
6719
6720 LogEvent(LogStartup, 'DisplayFiles Done' );
6721
6722end;
6723
6724Function TMainForm.OpenFiles( const FileNames: TStrings;
6725 const WindowTitle: string;
6726 const DisplayFirstTopic: boolean ): boolean;
6727var
6728 tmpHelpFiles: TList;
6729 FirstContentsNode: TNode;
6730begin
6731 LogEvent(LogStartup, 'OpenFiles' );
6732
6733 if not OKToCloseFile then
6734 exit;
6735
6736 SetWaitCursor;
6737
6738 tmpHelpFiles := TList.Create;
6739
6740// RBRi Translate
6741 if not LoadFiles(FileNames, tmpHelpFiles) then
6742 begin
6743 ClearWaitCursor;
6744 tmpHelpFiles.Destroy;
6745 exit;
6746 end;
6747
6748 Result := true;
6749
6750 SearchResultsListBox.Clear;
6751 PageHistory.Clear;
6752 CurrentHistoryIndex := -1;
6753
6754 // Now that we have successfully loaded the new help file(s)
6755 // close the existing one.
6756 CloseFile;
6757
6758 AssignList(tmpHelpFiles, CurrentOpenFiles );
6759
6760 ProgressBar.Position := 50;
6761 SetStatus( LoadingStatusDisplaying );
6762
6763 AddCurrentToMRUFiles;
6764
6765 if WindowTitle = '' then
6766 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6767 else
6768 MainTitle := WindowTitle;
6769
6770 SetMainCaption;
6771
6772 // Now load the various parts of the file(s)
6773 // into the user interface
6774
6775 ContentsOutline.Clear;
6776
6777 DisplayFiles( tmpHelpFiles,
6778 FirstContentsNode );
6779
6780 if CmdLineParameters.getHelpManagerFlag then
6781 ShowLeftPanel := Settings.ShowLeftPanel_Help
6782 else
6783 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6784
6785 // Select first contents node if there is one
6786 if FirstContentsNode <> nil then
6787 begin
6788 LogEvent(LogStartup, ' Select first node' );
6789 ContentsOutline.SelectedNode := FirstContentsNode;
6790 end;
6791
6792 ClearWaitCursor;
6793
6794 ResetProgress;
6795
6796 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6797
6798 EnableControls;
6799
6800 if DisplayFirstTopic then
6801 begin
6802 LogEvent(LogStartup, 'Display first topic' );
6803 DisplaySelectedContentsTopic;
6804 end;
6805
6806 LogEvent(LogStartup, 'OpenFiles complete' );
6807end;
6808
6809Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6810 const DisplayFirstTopic: boolean ): boolean;
6811var
6812 HelpFiles: TList;
6813 FirstNewContentsNode: TNode;
6814begin
6815 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6816
6817 if not OKToCloseFile then
6818 exit;
6819
6820 SetWaitCursor;
6821
6822 HelpFiles := TList.Create;
6823
6824 if not LoadFiles( FileNames,
6825 HelpFiles ) then
6826 begin
6827 ClearWaitCursor;
6828 HelpFiles.Destroy;
6829 exit;
6830 end;
6831
6832 Result := true;
6833
6834 AddList( HelpFiles, CurrentOpenFiles );
6835
6836 AddCurrentToMRUFiles;
6837
6838 DisplayFiles( HelpFiles,
6839 FirstNewContentsNode );
6840
6841 // Select first contents node of new file
6842 if FirstNewContentsNode <> nil then
6843 ContentsOutline.SelectedNode := FirstNewContentsNode;
6844
6845 HelpFiles.Destroy;
6846
6847 ClearWaitCursor;
6848
6849 ResetProgress;
6850
6851 EnableControls;
6852
6853 if DisplayFirstTopic then
6854 DisplaySelectedContentsTopic;
6855
6856 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6857end;
6858
6859Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6860Begin
6861 FileOpen;
6862end;
6863
6864procedure TMainForm.FileOpen;
6865var
6866 Filenames: TStringList;
6867 KeepCurrentFiles: boolean;
6868 OpenedOK: boolean;
6869begin
6870 if not OKToCloseFile then
6871 exit;
6872
6873 if Settings.UseOriginalDialogs then
6874 begin
6875 SystemOpenDialog.Filename := AddDirectorySeparator( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6876 if not SystemOpenDialog.Execute then
6877 exit;
6878
6879 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6880 // note - sibyl's encapsulation doesn't allow multi-select
6881 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6882 end
6883 else
6884 begin
6885 Filenames := TStringList.Create;
6886 KeepCurrentFiles := false;
6887 if not DoOpenMultiFileDialog( FileOpenTitle,
6888 HelpFilesDesc
6889 + '|*.inf;*.hlp|'
6890 + AllFilesDesc
6891 + '|*.*',
6892 '*.hlp;*.inf',
6893 Settings.LastOpenDirectory,
6894 KeepCurrentFiles,
6895 Filenames ) then
6896 exit;
6897
6898 // no ParseAndExpandFileNames call required here
6899 // this is the result of a file dialog
6900 // no environment vars here
6901 if KeepCurrentFiles then
6902 OpenedOK := OpenAdditionalFiles( FileNames, true )
6903 else
6904 OpenedOK := OpenFiles( FileNames, '', true );
6905 Filenames.Destroy;
6906 end;
6907
6908 if OpenedOK then
6909 ClearHelpManager;
6910End;
6911
6912Procedure TMainForm.CloseWindows;
6913Begin
6914 DestroyListObjects( Windows );
6915 Windows.Clear;
6916end;
6917
6918// Help manager mode
6919
6920// if window is minimised then restore it
6921// (ideally should go back to maximized - don't know how)
6922Procedure TMainForm.RestoreWindow;
6923Begin
6924 If WindowState = wsMinimized then
6925 WindowState := wsNormal;
6926end;
6927
6928
6929Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6930begin
6931 LogEvent(LogNHM, 'NHMDisplayIndex');
6932 CmdLineParameters.addNhmDebugMessage('NHMDisplayIndex');
6933 RestoreWindow;
6934 DisplayIndex;
6935 // if nothing is being display already...
6936 if Windows.Count = 0 then
6937 // display first topic
6938 DisplaySelectedContentsTopic;
6939end;
6940
6941Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6942begin
6943 LogEvent(LogNHM, 'NHMDisplayContents');
6944 CmdLineParameters.addNhmDebugMessage('NHMDisplayContents');
6945 RestoreWindow;
6946 DisplayContents;
6947 // if nothing is being display already...
6948 if Windows.Count = 0 then
6949 begin
6950 // display first topic
6951 DisplaySelectedContentsTopic;
6952 end;
6953end;
6954
6955Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6956begin
6957 LogEvent(LogNHM, 'NHMTopicByResourceID');
6958 RestoreWindow;
6959 if ShowLeftPanel then
6960 begin
6961 DisplayContents;
6962 end;
6963 CmdLineParameters.addNhmDebugMessage('NHMTopicByResourceID ' + IntToStr(Msg.Param1));
6964 DisplayTopicByResourceID( Msg.Param1 );
6965end;
6966
6967Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6968var
6969 pMessageMem: pchar;
6970 PanelName: string;
6971 Topic: TTopic;
6972begin
6973 LogEvent(LogNHM, 'NHMTopicByPanelName');
6974 RestoreWindow;
6975 if ShowLeftPanel then
6976 DisplayContents;
6977
6978 pMessageMem := pchar( Msg.Param1 );
6979 PanelName := StrPas( pMessageMem );
6980 SharedMemory.Free( pMessageMem );
6981
6982 LogEvent(LogNHM, '....NHMTopicByPanelName panel:' + PanelName);
6983 CmdLineParameters.addNhmDebugMessage('NHMTopicByPanelName ' + PanelName);
6984 Topic := FindTopicByName( PanelName );
6985 if Topic = nil then
6986 Topic := FindTopicByGlobalName( PanelName );
6987
6988 if Topic <> nil then
6989 DisplayTopic( Topic )
6990 else
6991 SearchFor( PanelName );
6992end;
6993
6994// Sent from other instances starting up (and exiting immediately)
6995
6996Procedure TMainForm.NHMSearch( Var Msg: TMessage );
6997var
6998 pSearchText: pchar;
6999 tmpSearchText : String;
7000begin
7001 LogEvent(LogNHM, 'NHMSearch');
7002 RestoreWindow;
7003
7004 pSearchText := pstring( Msg.Param1 );
7005 tmpSearchText := StrPas(pSearchText);
7006 CmdLineParameters.addNhmDebugMessage('NHMSearch ' + tmpSearchText);
7007 SearchFor(tmpSearchText);
7008 SharedMemory.Free( pSearchText );
7009end;
7010
7011Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
7012var
7013 pSearchText: pchar;
7014 tmpSearchText : String;
7015begin
7016 LogEvent(LogNHM, 'NHMGlobalSearch');
7017 RestoreWindow;
7018
7019 pSearchText := pstring( Msg.Param1 );
7020 tmpSearchText := StrPas(pSearchText);
7021 CmdLineParameters.addNhmDebugMessage('NHMGlobalSearch ' + tmpSearchText);
7022 DoGlobalSearch(tmpSearchText);
7023 SharedMemory.Free( pSearchText );
7024end;
7025
7026Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
7027begin
7028 LogEvent(LogNHM, 'NHMShowUsage');
7029 CmdLineParameters.addNhmDebugMessage('NHMShowUsage');
7030 RestoreWindow;
7031 ShowUsage;
7032end;
7033
7034Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
7035var
7036 pFileNames: pchar;
7037 tmpFileNames : String;
7038begin
7039 LogEvent(LogNHM, 'NHMSetFiles');
7040
7041 // NOT restoring window here because this is not something the user should see...
7042 pFileNames := pstring( Msg.Param1 );
7043 tmpFileNames := StrPas(pFileNames);
7044 CmdLineParameters.addNhmDebugMessage('NHMSetFiles ' + tmpFileNames);
7045 OpenFilesFromTextList(tmpFileNames, false);
7046 SharedMemory.Free( pFileNames );
7047end;
7048
7049Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
7050var
7051 pTitle: pchar;
7052begin
7053 LogEvent(LogNHM, 'NHMSetTitle');
7054
7055 pTitle := pstring( Msg.Param1 );
7056 MainTitle := StrPas( pTitle );
7057 SharedMemory.Free( pTitle );
7058 CmdLineParameters.addNhmDebugMessage('NHMSetTitle ' + MainTitle);
7059 SetMainCaption;
7060end;
7061
7062Procedure TMainForm.NHMTest( Var Msg: TMessage );
7063var
7064 ps: pstring;
7065begin
7066 LogEvent(LogNHM, 'NHMTest');
7067 ps := PString( Msg.Param1 );
7068 ShowMessage( 'Got test message: ' + ps^ );
7069 SharedMemory.Free( ps );
7070end;
7071
7072Initialization
7073 RegisterClasses ([TMainForm, TSplitBar,
7074 TNoteBook,
7075 TEdit, TListBox,
7076 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
7077 TImageList, TPanel, TButton,
7078 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
7079 , TProgressBar, TTabSet2]);
7080End.
Note: See TracBrowser for help on using the repository browser.