source: trunk/NewView/MainForm.pas@ 81

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