source: trunk/NewView/MainForm.pas@ 64

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

another refactoring step for cleaning up the command line handling

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