source: trunk/NewView/MainForm.pas@ 78

Last change on this file since 78 was 78, checked in by RBRi, 19 years ago

method name refactoring

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