source: trunk/NewView/MainForm.pas@ 60

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

log output fixed

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