source: trunk/NewView/MainForm.pas@ 54

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

refactoring to simplify command line handling in MainForm
some tests fixed

  • Property svn:eol-style set to native
File size: 183.2 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
2282 tmpWindowPosition := CmdLineParameters.getWindowPosition;
2283 Lines.Add('getWindowPosition: ');
2284 Lines.Add(' left: ' + intToStr(tmpWindowPosition.left));
2285 Lines.Add(' bottom: ' + intToStr(tmpWindowPosition.bottom));
2286 Lines.Add(' width: ' + intToStr(tmpWindowPosition.width));
2287 Lines.Add(' height: ' + intToStr(tmpWindowPosition.height));
2288 Lines.Add('getOwnerWindow: ' + intToStr(CmdLineParameters.getOwnerWindow));
2289 Lines.Add('getWindowTitle: ' + CmdLineParameters.getWindowTitle);
2290 Lines.Add('getFileNames: ' + CmdLineParameters.getFileNames);
2291 end;
2292
2293 InformationForm.ShowModal;
2294End;
2295
2296Procedure TMainForm.EditBookmarksMIOnClick (Sender: TObject);
2297Begin
2298 BookmarksForm.BookmarkList := Bookmarks;
2299 BookmarksForm.OpenBookmarkCallback := NavigateToBookmark;
2300 BookmarksForm.BookmarksChangedCallback := OnBookmarksChanged;
2301 BookmarksForm.Show;
2302
2303 // Since we are showing a nonmodal dialog, set the PM owner window
2304 // so that the bookmarks form remains on top.
2305 WinSetOwner( BookmarksForm.Frame.Handle,
2306 Frame.Handle );
2307End;
2308
2309Procedure TMainForm.CopyPMIOnClick (Sender: TObject);
2310var
2311 Window: THelpWindow;
2312Begin
2313 Window := GetActiveWindow;
2314 if Window = nil then
2315 exit;
2316 Window.View.CopySelectionToClipboard;
2317End;
2318
2319Procedure TMainForm.SelectAllPMIOnClick (Sender: TObject);
2320var
2321 Window: THelpWindow;
2322Begin
2323 Window := GetActiveWindow;
2324 if Window = nil then
2325 exit;
2326 Window.View.SelectAll;
2327End;
2328
2329Procedure TMainForm.AddNoteButtonOnClick (Sender: TObject);
2330Begin
2331 AddNote;
2332End;
2333
2334Procedure TMainForm.EnableSearchButton;
2335var
2336 CanSearch: boolean;
2337begin
2338 CanSearch := false;
2339 if CurrentOpenFiles.Count > 0 then
2340 if trim( SearchTextEdit.Text ) > '' then
2341 CanSearch := true;
2342 SearchButton.Enabled := CanSearch;
2343end;
2344
2345Procedure TMainForm.SearchTextEditOnChange (Sender: TObject);
2346Begin
2347 EnableSearchButton;
2348End;
2349
2350Procedure TMainForm.OnHint( Sender: TObject );
2351begin
2352 SetStatus( Application.Hint );
2353end;
2354
2355Procedure TMainForm.DisplaySelectedIndexTopic;
2356var
2357 Topic: TTopic;
2358Begin
2359 if IndexListBox.ItemIndex = -1 then
2360 exit;
2361 Topic := DisplayedIndex.Objects[ IndexListBox.ItemIndex ] as TTopic;
2362 DisplayTopic( Topic );
2363End;
2364
2365Procedure TMainForm.IndexListBoxOnClick (Sender: TObject);
2366Begin
2367 DisplaySelectedIndexTopic;
2368End;
2369
2370Procedure TMainForm.ViewCollapseAllMIOnClick (Sender: TObject);
2371Begin
2372 DisplayContents;
2373 ContentsOutline.CollapseAll;
2374 DisplaySelectedContentsTopic;
2375End;
2376
2377Procedure TMainForm.NotesListBoxOnDblClick (Sender: TObject);
2378Begin
2379 GotoCurrentNote;
2380End;
2381
2382function TMainForm.OwnHelpMode: boolean;
2383var
2384 Filename: string;
2385 NamePart: string;
2386begin
2387 result := false;
2388 if CurrentOpenFiles.Count <> 1 then
2389 exit;
2390
2391 Filename := THelpFile( CurrentOpenFiles[ 0 ] ).Filename;
2392 NamePart := ExtractFileName( Filename );
2393 Result := StrStarts( 'newview', NamePart );
2394end;
2395
2396Procedure TMainForm.HelpMIOnClick (Sender: TObject);
2397Begin
2398 if OwnHelpMode then
2399 begin
2400 DoErrorDlg( NewViewHelpTitle,
2401 AlreadyNewviewHelp );
2402 exit;
2403 end;
2404 Application.HelpContents;
2405End;
2406
2407Procedure TMainForm.NotebookOnPageChanged (Sender: TObject);
2408var
2409 FileIndex: longint;
2410 HelpFile: THelpFile;
2411Begin
2412 EnableControls;
2413 case Notebook.PageIndex of
2414 piContents:
2415 begin
2416 // not really feasible to load contents here, as we rely
2417 // on it for many things
2418 ContentsOutline.Focus;
2419 end;
2420
2421 piIndex:
2422 begin
2423 if not IndexLoaded then
2424 begin
2425 LoadIndex;
2426 end;
2427 IndexSearchEdit.Focus;
2428 end;
2429
2430 piSearch:
2431 begin
2432 SearchButton.Focus;
2433 SearchTextEdit.Focus;
2434 end;
2435
2436 piNotes:
2437 begin
2438 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2439 begin
2440 HelpFile := CurrentOpenFiles[ FileIndex ];
2441 if not HelpFile.NotesLoaded then
2442 LoadNotes( HelpFile );
2443 end;
2444 NotesListBox.Focus;
2445 UpdateNotesDisplay;
2446 end;
2447 end;
2448
2449End;
2450
2451Procedure TMainForm.ViewRefreshMIOnClick (Sender: TObject);
2452Begin
2453 RefreshWindows( Windows );
2454End;
2455
2456Procedure TMainForm.ViewNotesMIOnClick (Sender: TObject);
2457Begin
2458 ShowLeftPanel := true;
2459 TabSet.TabIndex := piNotes;
2460End;
2461
2462Procedure TMainForm.ViewSearchMIOnClick (Sender: TObject);
2463Begin
2464 DisplaySearch;
2465End;
2466
2467Procedure TMainForm.ShowTab( TabIndex: longint );
2468Begin
2469 ShowLeftPanel := true;
2470 TabSet.TabIndex := TabIndex;
2471 NotebookOnPageChanged( self );// focus control etc
2472End;
2473
2474Procedure TMainForm.DisplaySearch;
2475Begin
2476 ShowTab( piSearch );
2477End;
2478
2479Procedure TMainForm.ViewIndexMIOnClick (Sender: TObject);
2480Begin
2481 DisplayIndex;
2482End;
2483
2484Procedure TMainForm.DisplayIndex;
2485Begin
2486 ShowTab( piIndex );
2487End;
2488
2489Procedure TMainForm.ViewContentsMIOnClick (Sender: TObject);
2490Begin
2491 DisplayContents;
2492End;
2493
2494Procedure TMainForm.DisplayContents;
2495Begin
2496 ShowTab( piContents );
2497End;
2498
2499function TMainForm.OpenWindow( Topic: TTopic;
2500 Group: longint;
2501 Parent: THelpWindow;
2502 Rect: THelpWindowRect;
2503 FollowAutoLinks: boolean ): THelpWindow;
2504var
2505 Window: THelpWindow;
2506 DisplayTopicRequired: boolean;
2507begin
2508 Window := nil;
2509
2510 if ( Group <> DefaultGroupIndex ) and ( Parent = nil ) then
2511 begin
2512 // Normal window (not a split window) and a specific group is desired.
2513 // So see if we can find one with that group number
2514 Window := FindWindowFromGroup( Group, Windows );
2515
2516 end
2517 else
2518 begin
2519 // only reuse window if it has the same topic.
2520 Window := FindWindowFromTopic( Topic, Windows );
2521 end;
2522
2523 if Window = nil then
2524 begin
2525 DisplayingTopicWindow := true;
2526
2527 // not found, or want a new one
2528 Window := THelpWindow.Create( Parent = nil );
2529
2530 // add to parent
2531 if Parent = nil then
2532 begin
2533 Window.Parent := DisplayPanel;
2534 Windows.Add( Window );
2535 end
2536 else
2537 begin
2538 Window.Parent := Parent.View;
2539 Parent.ChildWindows.Add( Window );
2540 end;
2541
2542 Window.ParentHelpWindow := Parent;
2543
2544 DisplayingTopicWindow := false;
2545
2546 end
2547 else
2548 begin
2549 // reusing an existing window. Don't change parent
2550 end;
2551
2552 Window.Group := Group;
2553
2554 Window.View.PopupMenu := ViewPopupMenu;
2555
2556 Window.View.Images := Window.Images;
2557
2558 Window.View.OnClickLink := OnClickLink;
2559 Window.View.OnOverLink := OnOverLink;
2560 Window.View.OnNotOverLink := OnNotOverLink;
2561
2562 Window.OnClose := OnWindowClose;
2563 Window.OnCloseQuery := OnWindowAboutToClose;
2564 Window.OnDragOver := OnDragOverWindow;
2565 Window.OnDragDrop := OnDragDropToWindow;
2566 Window.OnFontChange := OnWindowFontChange;
2567 Window.OnTab := OnWindowTab;
2568 Window.OnBackTab := OnWindowBackTab;
2569
2570 // Use the contents rect by default...
2571 Topic.GetContentsWindowRect( Window.Rect );
2572 if Rect <> nil then
2573 begin
2574 // the rect is being overridden, so use it instead
2575 if Rect.Left <> -1 then
2576 Window.Rect.Left := Rect.Left;
2577 if Rect.Bottom <> -1 then
2578 Window.Rect.Bottom := Rect.Bottom;
2579 if Rect.Width <> -1 then
2580 Window.Rect.Width := Rect.Width;
2581 if Rect.Height <> -1 then
2582 Window.Rect.Height := Rect.Height;
2583 end;
2584
2585 if Window.ChildWindows.Count > 0 then
2586 begin
2587 // close existing child windows
2588 DestroyListObjects( Window.ChildWindows );
2589 Window.ChildWindows.Clear;
2590 Window.View.Show; // show the view again
2591 end;
2592
2593 DisplayTopicRequired := Window.Topic <> Topic;
2594 Window.Topic := Topic; // set this now so that SetLayout can log meaninful stuff
2595
2596 // Adjust the window size to it's specified Rect
2597 // Must do this before displaying child windows (DisplayTopicInWindow,
2598 // split window autolinks),
2599 // otherwise they will not size themselves correctly
2600 Window.SetLayout;
2601
2602 if DisplayTopicRequired then
2603 begin
2604 DisplayTopicInWindow( Window, FollowAutoLinks, false );
2605 end;
2606
2607 // Bring this window to the front
2608 Window.BringToFront;
2609
2610 Result := Window;
2611end;
2612
2613// Find an existing help window containing the given richtext view control
2614Function TMainForm.FindWindowFromView( View: TRichTextView;
2615 WindowList: TList ): THelpWindow;
2616var
2617 WindowIndex: longint;
2618begin
2619 for WindowIndex:= 0 to WindowList.Count - 1 do
2620 begin
2621 Result:= WindowList[ WindowIndex ];
2622 if Result.View = View then
2623 exit;
2624 Result:= FindWindowFromView( View, Result.ChildWindows );
2625 if Result <> nil then
2626 exit;
2627 end;
2628 Result:= nil;
2629end;
2630
2631// Find an existing help window with the given group number (if any)
2632Function TMainForm.FindWindowFromGroup( Group: longint; WindowList: TList ): THelpWindow;
2633var
2634 WindowIndex: longint;
2635begin
2636 for WindowIndex:= 0 to WindowList.Count - 1 do
2637 begin
2638 Result:= WindowList[ WindowIndex ];
2639 if Result.Group = Group then
2640 exit;
2641 Result:= FindWindowFromGroup( Group, Result.ChildWindows );
2642 if Result <> nil then
2643 exit;
2644 end;
2645 Result:= nil;
2646end;
2647
2648// Find an existing help window alreadying displaying the given topic
2649Function TMainForm.FindWindowFromTopic( Topic: TTopic; WindowList: TList ): THelpWindow;
2650var
2651 WindowIndex: longint;
2652begin
2653 for WindowIndex:= 0 to WindowList.Count - 1 do
2654 begin
2655 Result:= WindowList[ WindowIndex ];
2656 if Result.Topic = Topic then
2657 exit;
2658 Result:= FindWindowFromTopic( Topic, Result.ChildWindows );
2659 if Result <> nil then
2660 exit;
2661 end;
2662 Result:= nil;
2663end;
2664
2665Procedure TMainForm.RefreshFontSubstitutions;
2666var
2667 FileIndex: longint;
2668 HelpFile: THelpFile;
2669begin
2670 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
2671 begin
2672 HelpFile := CurrentOpenFiles[ FileIndex ];
2673
2674 if Settings.FixedFontSubstitution then
2675 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes )
2676 else
2677 HelpFile.SetupFontSubstitutes( '' );
2678 end;
2679end;
2680
2681// Redisplay topics in all windows
2682Procedure TMainForm.RefreshWindows( WindowList: TList );
2683var
2684 WindowIndex: longint;
2685 Window: THelpWindow;
2686begin
2687 for WindowIndex:= 0 to WindowList.Count - 1 do
2688 begin
2689 Window:= WindowList[ WindowIndex ];
2690 DisplayTopicInWindow( Window,
2691 false, // don't follow links!
2692 true ); // keep position
2693 RefreshWindows( Window.ChildWindows );
2694 end;
2695end;
2696
2697Procedure TMainForm.WMFollowExternalLink( Var Msg: TMessage );
2698var
2699 FilePath: string;
2700 Topic: TTopic;
2701begin
2702 // try in same dir as source file
2703 FilePath := AddSlash( ExtractFilePath( g_ExternalLinkSourceFilename ) )
2704 + g_ExternalLinkFilename;
2705
2706 if not StringsSame( FilePath, g_ExternalLinkSourceFilename ) then
2707 begin
2708 // different file - try and open it
2709 if not FileExists( FilePath ) then
2710 // not in same directory, find in help paths
2711 FilePath := FindHelpFile( g_ExternalLinkFilename );
2712
2713 if not FileExists( FilePath ) then
2714 begin
2715 DoErrorDlg( 'Link Error',
2716 'Cannot find linked file '
2717 + g_ExternalLinkFilename );
2718 exit;
2719 end;
2720
2721 if g_ExternalLinkKeepCurrent then
2722 begin
2723 if not OpenAdditionalFile( FilePath, false ) then
2724 exit;
2725 end
2726 else
2727 begin
2728 if not OpenFile( FilePath, '', false ) then
2729 exit;
2730 end;
2731
2732 end;
2733
2734 if g_ExternalLinkTopic = '' then
2735 begin
2736 // specific topic not required.
2737 DisplaySelectedContentsTopic;
2738 exit;
2739 end;
2740
2741 Topic := FindTopicByGlobalName( g_ExternalLinkTopic );
2742 if Topic = nil then
2743 begin
2744 DoErrorDlg( 'Link Error',
2745 'Unable to find topic with global name '
2746 + g_ExternalLinkTopic );
2747 exit;
2748 end;
2749
2750 DisplayTopic( Topic );
2751end;
2752
2753// We are following a link, specified as param1 in msg
2754Procedure TMainForm.WMFollowLink( Var Msg: TMessage );
2755var
2756 NewTopic: TTopic;
2757 Link: THelpLink;
2758 SourceWindow: THelpWindow;
2759begin
2760 Link:= THelpLink( Msg.Param1 );
2761 SourceWindow:= THelpWindow( Msg.Param2 );
2762 NewTopic:= FindTopicForLink( Link );
2763
2764 // remove the link target info from status
2765 SetStatus( '' );
2766
2767 if NewTopic = nil then
2768 begin
2769 // Linked topic not found, this is an error... which kind?
2770
2771 if Link is THelpLinkByResourceID then
2772 begin
2773 // may happen if e.g. PM4.INF is loaded by itself,
2774 // and a link references a resource ID from e.g PM2.INF
2775 DoErrorDlg( InvalidLinkErrorTitle,
2776 InvalidResourceIDLinkErrorA
2777 + IntToStr( THelpLinkByResourceID( Link ).ResourceID )
2778 + InvalidResourceIDLinkErrorB );
2779 end
2780 else
2781 begin
2782 // should never happen, given valid help files
2783 DoErrorDlg( InvalidLinkErrorTitle,
2784 InvalidLinkError );
2785 end;
2786
2787 exit;
2788 end;
2789
2790 UpdateCurrentNavigatePoint;
2791
2792 FollowLink( Link, SourceWindow );
2793
2794 if NewTopic.ShowInContents then
2795 begin
2796 Navigating:= true;
2797 if ContentsOutline.SelectedNode = nil then
2798 ContentsOutline.SetSelectedObject( NewTopic )
2799 else if ContentsOutline.SelectedNode.Data <> NewTopic then
2800 ContentsOutline.SetSelectedObject( NewTopic );
2801 Navigating:= false;
2802 end;
2803 SaveNavigatePoint;
2804 EnableControls;
2805 ShowWindows;
2806
2807end;
2808
2809// Follow the given link from the given window.
2810// ie. open the topic or footnote it points to
2811Procedure TMainForm.FollowLink( Link: THelpLink;
2812 SourceWindow: THelpWindow );
2813var
2814 LinkedTopic: TTopic;
2815 ParentWindow: THelpWindow;
2816 WindowedLink: TWindowedHelpLink;
2817 NewWindow: THelpWIndow;
2818begin
2819 LinkedTopic := FindTopicForLink( Link );
2820
2821 if LinkedTopic = nil then
2822 begin
2823 exit;
2824 end;
2825
2826 if Link is TFootnoteHelpLink then
2827 begin
2828 NewWindow := OpenWindow( LinkedTopic,
2829 DefaultGroupIndex,
2830 nil, // no parent
2831 FootnoteRect,
2832 true );
2833 NewWindow.Caption := TFootnoteHelpLink( Link ).Title;
2834 exit;
2835 end;
2836
2837 WindowedLink := Link as TWindowedHelpLink;
2838
2839 ParentWindow:= nil;
2840 if WindowedLink.Split then
2841 ParentWindow:= SourceWindow;
2842
2843 if WindowedLink.ViewPort then
2844 // link always wants a new window
2845 OpenWindow( LinkedTopic,
2846 DefaultGroupIndex,
2847 ParentWindow,
2848 WindowedLink.Rect,
2849 true )
2850
2851 else if WindowedLink.GroupIndex <> DefaultGroupIndex then
2852 // link overrides group index
2853 OpenWindow( LinkedTopic,
2854 WindowedLink.GroupIndex,
2855 ParentWindow,
2856 WindowedLink.Rect,
2857 true )
2858 else
2859 // no special case
2860 OpenWindow( LinkedTopic,
2861 LinkedTopic.ContentsGroupIndex,
2862 ParentWindow,
2863 WindowedLink.Rect,
2864 true );
2865end;
2866
2867function TMainForm.ShowCodes: boolean;
2868begin
2869 if DebugShowCodesMI = nil then
2870 result := false
2871 else
2872 result := DebugShowCodesMI.Checked;
2873end;
2874
2875function TMainForm.ShowWordIndices: boolean;
2876begin
2877 if DebugShowWordSeparatorsMI = nil then
2878 result := false
2879 else
2880 result := DebugShowWordSeparatorsMI.Checked;
2881end;
2882
2883// Decode and display the topic for the given window.
2884Procedure TMainForm.DisplayTopicInWindow( Window: THelpWindow;
2885 FollowAutoLinks: boolean;
2886 KeepPosition: boolean );
2887var
2888 ImageIndices: TList;
2889 LinkIndex: longint;
2890 Link: THelpLink;
2891 WindowedHelpLink: TWindowedHelpLink;
2892 InternalHelpLink: TInternalHelpLink;
2893 HelpFile: THelpFile;
2894 LinkedTopic: TTopic;
2895 SourceTopic: TTopic;
2896 TopCharIndex: longint;
2897 i: longint;
2898 HighlightWordSequences: TList;
2899 FileIndex: longint;
2900Begin
2901 LogEvent(LogDisplay, 'DisplayTopicInWindow');
2902
2903 SetWaitCursor;
2904
2905 TopCharIndex := Window.View.TopCharIndex;
2906
2907 Window.View.Hide;
2908 Window.View.Clear;
2909 ImageIndices := TList.Create;
2910
2911 HelpFile := TopicFile( Window.Topic );
2912
2913 if ( AllFilesWordSequences.Count > 0 ) // ie we have done a search...
2914 and ViewHighlightSearchWordsMI.Checked then
2915 begin
2916 FileIndex := CurrentOpenFiles.IndexOf( HelpFile );
2917 HighlightWordSequences := AllFilesWordSequences[ FileIndex ];
2918 end
2919 else
2920 begin
2921 HighlightWordSequences := nil;
2922 end;
2923 TopicText.Clear;
2924 Window.Topic.GetText( HighlightWordSequences,
2925 ShowCodes,
2926 ShowWordIndices,
2927 TopicText,
2928 ImageIndices,
2929 Window.Highlights );
2930
2931 HelpFile.GetImages( ImageIndices, Window.Images );
2932
2933 if not HelpFile.NotesLoaded then
2934 LoadNotes( HelpFile );
2935 InsertNotesIntoTopicText( Window.Topic, TopicText );
2936
2937 Window.View.AddText( TopicText.AsPChar );
2938
2939 if KeepPosition then
2940 Window.View.TopCharIndex := TopCharIndex;
2941
2942 Window.View.Show;
2943
2944 if not KeepPosition then
2945 if Window.Highlights.Count > 0 then
2946 // ensure first search match is visible
2947 Window.View.MakeCharVisible( longint( Window.Highlights[ 0 ] ) );
2948
2949 Window.Caption := Window.Topic.Title;
2950 Window.BringToFront;
2951 Window.View.Focus;
2952
2953 // Take a copy of the topic, because the window in question could be changing
2954 // due to recursion!
2955 SourceTopic := Window.Topic;
2956
2957 if FollowAutoLinks then
2958 begin
2959 i := 0;
2960 for LinkIndex:= 0 to SourceTopic.Links.Count - 1 do
2961 begin
2962 Link:= SourceTopic.Links[ LinkIndex ];
2963 if Link is TWindowedHelpLink then
2964 begin
2965 WindowedHelpLink := Link as TWindowedHelpLink;
2966 if WindowedHelpLink.Automatic then
2967 begin
2968 if Link is TInternalHelpLink then
2969 begin
2970 InternalHelpLink := TInternalHelpLink( Link );
2971 LinkedTopic :=
2972 THelpFile( InternalHelpLink.HelpFile ).
2973 Topics[ InternalHelpLink.TopicIndex ];
2974 if LinkedTopic.Index = SourceTopic.Index then
2975 // what the - ? The link wants to open the same topic again
2976 continue;
2977 end;
2978
2979 FollowLink( Link, Window );
2980 Window := Window;
2981
2982 inc( i );
2983 // Note 1: it is possible to crash here if
2984 // e.g. window1 auto-opens window2 which auto-opens window1 with a different topic..
2985 // I can't think of a nice, easy way to detect this
2986 //
2987 // Note 2: If there is no group number specified
2988 // (ie. group = default = 0 ) then behaves as if viewport is set:
2989 // always opens another window.
2990 end;
2991 end;
2992 end;
2993 end;
2994
2995 ClearWaitCursor;
2996
2997 ImageIndices.Destroy;
2998End;
2999
3000Procedure TMainForm.MainFormOnCloseQuery (Sender: TObject;
3001 Var CanClose: Boolean);
3002Begin
3003 LogEvent(LogShutdown, '-------- Shutdown ----------');
3004
3005
3006 if OKToCloseFile then
3007 CloseFile
3008 else
3009 CanClose := false;
3010End;
3011
3012procedure TMainForm.DisplayTopic( Topic: TTopic );
3013begin
3014 if Navigating then
3015 exit;
3016
3017 UpdateCurrentNavigatePoint;
3018
3019 CloseWindows;
3020
3021 CurrentTopic:= Topic;
3022
3023 OpenWindow( CurrentTopic,
3024 CurrentTopic.ContentsGroupIndex,
3025 nil,
3026 nil,
3027 true );
3028 SetStatus( OpenedTopicMsg
3029 + IntToStr( Topic.Index ) );
3030
3031 Navigating:= true;
3032
3033 if ContentsOutline.SelectedNode = nil then
3034 ContentsOutline.SetSelectedObject( Topic )
3035 else if ContentsOutline.SelectedNode.Data <> Topic then
3036 ContentsOutline.SetSelectedObject( Topic );
3037
3038 SaveNavigatePoint;
3039
3040 Navigating:= false;
3041 // find in index...
3042 // find in search results...
3043
3044 EnableControls;
3045
3046 ShowWindows;
3047
3048// if Windows.Count > 0 then
3049// THelpWindow( Windows[ 0 ] ).View.Focus;
3050
3051end;
3052
3053// Make the all current help windows visible
3054Procedure TMainForm.ShowWindows;
3055begin
3056 ShowWindowList( Windows );
3057end;
3058
3059// Make the specified windows visible
3060Procedure TMainForm.ShowWindowList( WindowList: TList );
3061var
3062 i: integer;
3063 Window: THelpWindow;
3064begin
3065 for i := 0 to WindowList.Count - 1 do
3066 begin
3067 Window:= WindowList[ i ];
3068 Window.Show;
3069 ShowWindowList( Window.ChildWindows );
3070 end;
3071end;
3072
3073// Global search -----------------------------------------------------------
3074
3075Procedure TMainForm.GlobalSearchMIOnClick (Sender: TObject);
3076begin
3077 DoGlobalSearch( '' );
3078end;
3079
3080Procedure TMainForm.DoGlobalSearch( const SearchText: string );
3081Begin
3082 EnsureGlobalSearchFormLoaded;
3083
3084 GlobalSearchForm.ViewTopicCallback:= OnViewGlobalSearchTopic;
3085 GlobalSearchForm.Show;
3086 WinSetOwner( GlobalSearchForm.Frame.Handle, Frame.Handle );
3087
3088 if SearchText <> '' then
3089 begin
3090 GlobalSearchForm.SearchTextEdit.Text := SearchText;
3091 GlobalSearchForm.DoSearch;
3092 end;
3093End;
3094
3095Procedure TMainForm.OnViewGlobalSearchTopic( FileName: string;
3096 TopicIndex: longint );
3097var
3098 HelpFile: THelpFile;
3099begin
3100 HelpFile:= FindOpenHelpFile( FileName );
3101
3102 if HelpFile = nil then
3103 begin
3104 if OpenFile( Filename, '', false ) then
3105 begin
3106 HelpFile := CurrentOpenFiles[ 0 ];
3107 ClearHelpManager;
3108 end;
3109 end;
3110
3111 if HelpFile <> nil then
3112 if TopicIndex <> -1 then
3113 DisplayTopic( HelpFile.Topics[ TopicIndex ] );
3114
3115end;
3116
3117// Notes -----------------------------------------------------------
3118
3119Procedure TMainForm.GotoNoteButtonOnClick (Sender: TObject);
3120begin
3121 GotoCurrentNote;
3122end;
3123
3124Procedure TMainForm.EditNoteButtonOnClick (Sender: TObject);
3125Begin
3126 if NotesListBox.ItemIndex = -1 then
3127 exit;
3128 EditNote( NotesListBox.ItemIndex );
3129End;
3130
3131Procedure TMainForm.NotesListBoxOnItemFocus (Sender: TObject; Index: LongInt);
3132var
3133 Note: THelpNote;
3134Begin
3135 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3136 EnableNotesControls;
3137End;
3138
3139Procedure TMainForm.DeleteNoteButtonOnClick (Sender: TObject);
3140Begin
3141 if NotesListBox.ItemIndex = -1 then
3142 exit;
3143 DeleteNote( NotesListBox.ItemIndex );
3144End;
3145
3146Procedure TMainForm.AddBookmarkMIOnClick (Sender: TObject);
3147Begin
3148 AddBookmark;
3149End;
3150
3151Procedure TMainForm.AddNoteMIOnClick (Sender: TObject);
3152Begin
3153 AddNote;
3154End;
3155
3156// -----------------------------------------------------------
3157
3158Procedure TMainForm.FileCloseMIOnClick (Sender: TObject);
3159Begin
3160 if not OKToCloseFile then
3161 exit;
3162
3163 CloseFile;
3164End;
3165
3166Procedure TMainForm.SetStatus( Text: String );
3167begin
3168 StatusPanel.Caption:= Text;
3169 StatusPanel.Refresh;
3170end;
3171
3172Procedure TMainForm.ResetProgress;
3173begin
3174 ProgressBar.Position:= 0;
3175 ProgressBar.Hide;
3176end;
3177
3178Procedure TMainForm.CoolBarOnSectionResize (HeaderControl: THeaderControl;
3179 section: THeaderSection);
3180Begin
3181
3182End;
3183
3184Procedure TMainForm.CoolBarOnSectionClick (HeaderControl: THeaderControl;
3185 section: THeaderSection);
3186Begin
3187 case Section.Index of
3188 ciOpen:
3189 FileOpen;
3190 ciBack:
3191 NavigateBack;
3192 ciForward:
3193 NavigateForward;
3194 ciPrint:
3195 PrintTopics;
3196 ciAddNote:
3197 AddNote;
3198 ciAddBookmark:
3199 AddBookmark;
3200 ciPrevious:
3201 NavigatePreviousInContents;
3202 ciNext:
3203 NavigateNextInContents;
3204 ciGlobalSearch:
3205 DoGlobalSearch( '' );
3206 end;
3207
3208End;
3209
3210// ---------------- Notes ----------------------
3211
3212function TMainForm.FindOriginalNoteCharIndex( NoteCharIndex: longword;
3213 Topic: TTopic ): longword;
3214var
3215 NoteIndex: longint;
3216 Note: THelpNote;
3217begin
3218 Result := NoteCharIndex;
3219 for NoteIndex := 0 to Notes.Count - 1 do
3220 begin
3221 Note := Notes[ NoteIndex ];
3222 if Note.Topic = Topic then
3223 if Note.InsertPoint < NoteCharIndex then
3224 dec( Result, Note.InsertText.Length );
3225 end;
3226end;
3227
3228function TMainForm.FindActualNoteCharIndex( NoteCharIndex: longword;
3229 MaxNoteIndex: longword;
3230 Topic: TTopic ): longword;
3231var
3232 NoteIndex: longint;
3233 Note: THelpNote;
3234begin
3235 NoteIndex:= 0;
3236 Result:= NoteCharIndex;
3237 for NoteIndex:= 0 to MaxNoteIndex - 1 do
3238 begin
3239 Note:= Notes[ NoteIndex ];
3240 if Note.Topic = Topic then
3241 if Note.InsertPoint < NoteCharIndex then
3242 inc( Result, Note.InsertText.Length );
3243 end;
3244end;
3245
3246procedure TMainForm.RefreshNoteInsertInfo( NoteIndex: longword );
3247var
3248 Note: THelpNote;
3249begin
3250 Note:= Notes[ NoteIndex ];
3251
3252 if Note.Topic = nil then
3253 exit;
3254 with Note do
3255 begin
3256 InsertText.AssignString( '<color #'
3257 + IntToHex( Settings.Colors[ NotesTextColorIndex ], 6 )
3258 + '><link note'
3259 + IntToStr( NoteIndex )
3260 + '>' );
3261 InsertText.Add( Text );
3262 InsertText.AddString( '</color></link>' );
3263 end;
3264end;
3265
3266procedure TMainForm.ClearNotes;
3267begin
3268 DestroyListObjects( Notes );
3269 Notes.Clear;
3270end;
3271
3272procedure TMainForm.AddNote;
3273var
3274 Note: THelpNote;
3275 Window: THelpWindow;
3276begin
3277 Window := GetActiveWindow;
3278 if Window = nil then
3279 begin
3280 DoErrorDlg( AddNoteTitle,
3281 AddNoteCursorError );
3282 exit;
3283 end;
3284
3285 if Window.View.CursorIndex = -1 then
3286 begin
3287 DoErrorDlg( AddNoteTitle,
3288 AddNoteCursorError );
3289 exit;
3290 end;
3291
3292 // check that the note position isn't
3293 // within a note already
3294 if Window.View.LinkFromIndex( Window.View.CursorIndex ) <> '' then
3295 begin
3296 DoErrorDlg( AddNoteTitle,
3297 NoteWithinNoteError );
3298 exit;
3299 end;
3300
3301 // ask for note text
3302 NoteForm.DeleteNoteButton.Enabled := false; // can't delete it while creating!
3303 NoteForm.Text.Clear;
3304 if NoteForm.ShowModal <> mrOK then
3305 exit;
3306
3307 // store note data
3308 Note := THelpNote.Create;
3309 Note.Text.Assign( NoteForm.Text );
3310
3311 // compensate for existing notes
3312 if Window.View.CursorIndex <> -1 then
3313 Note.InsertPoint := FindOriginalNoteCharIndex( Window.View.CursorIndex, Window.Topic )
3314 else
3315 Note.InsertPoint := 0;
3316
3317 Note.Topic := Window.Topic;
3318
3319 Notes.Add( Note );
3320
3321 // redisplay topic
3322 DisplayTopicInWindow( Window,
3323 false, // don't follow links!
3324 true ); // keep position
3325 Window.View.SelectionStart := FindActualNoteCharIndex( Note.InsertPoint,
3326 Notes.Count - 1,
3327 Window.Topic );
3328 UpdateNotesDisplay;
3329
3330 SaveNotes;
3331
3332end;
3333
3334procedure TMainForm.DeleteNote( NoteIndex: longint );
3335var
3336 Note: THelpNote;
3337begin
3338 Note := Notes[ NoteIndex ];
3339 Notes.Delete( NoteIndex );
3340
3341 RefreshWindows( Windows );
3342
3343 Note.Destroy;
3344
3345 UpdateNotesDisplay;
3346
3347 SaveNotes;
3348end;
3349
3350Procedure TMainForm.EditNote( NoteIndex: longint );
3351var
3352 Note: THelpNote;
3353begin
3354 Note:= Notes[ NoteIndex ];
3355
3356 NoteForm.Text.Assign( Note.Text );
3357
3358 NoteForm.DeleteNoteButton.Enabled:= true;
3359
3360 if NoteForm.ShowModal = mrCancel then
3361 exit;
3362
3363 if NoteForm.ModalResult = cmDiscard then
3364 begin
3365 DeleteNote( NoteIndex );
3366 exit;
3367 end;
3368
3369 Note.Text.Assign( NoteForm.Text );
3370
3371 RefreshWindows( Windows );
3372
3373 UpdateNotesDisplay;
3374
3375 SaveNotes;
3376end;
3377
3378Procedure TMainForm.GotoCurrentNote;
3379var
3380 Note: THelpNote;
3381Begin
3382 if NotesListBox.ItemIndex = -1 then
3383 exit;
3384 Note:= NotesListBox.Items.Objects[ NotesListBox.ItemIndex ] as THelpNote;
3385 DisplayTopic( Note.Topic );
3386End;
3387
3388// ---------------- Bookmarks ----------------------
3389
3390procedure TMainForm.OnBookmarksChanged( Sender: TObject );
3391begin
3392 BuildBookmarksMenu;
3393 UpdateBookmarksForm;
3394 SaveBookmarks;
3395end;
3396
3397procedure TMainForm.AddBookmark;
3398var
3399 Bookmark: TBookmark;
3400begin
3401 if Windows.Count = 0 then
3402 exit;
3403
3404 Bookmark := TBookmark.Create;
3405 SaveWindows( Windows, Bookmark.Windows, nil );
3406
3407 if ContentsOutline.SelectedNode <> nil then
3408 begin
3409 Bookmark.ContentsTopic:=
3410 ContentsOutline.SelectedNode.Data as TTopic;
3411 Bookmark.Name := Bookmark.ContentsTopic.Title;
3412 end
3413 else
3414 begin
3415 Bookmark.ContentsTopic:= nil;
3416 // Bookmark.Name := THelpWindow( Windows[ 0 ] ).Title;
3417 end;
3418
3419 Bookmarks.Add( Bookmark );
3420 OnBookmarksChanged( self );
3421end;
3422
3423Procedure TMainForm.BookmarksMenuItemClick( Sender: TObject );
3424var
3425 Tag: longint;
3426 MenuItem: TMenuItem;
3427 Bookmark: TBookmark;
3428begin
3429 MenuItem:= Sender as TMenuItem;
3430 Tag:= MenuItem.Tag;
3431 Bookmark := Bookmarks[ Tag ];
3432
3433 NavigateToBookmark( Bookmark );
3434end;
3435
3436Procedure TMainForm.NavigateToBookmark( Bookmark: TBookmark );
3437Begin
3438 UpdateCurrentNavigatePoint;
3439 NavigateToPoint( Bookmark );
3440 SaveNavigatePoint;
3441End;
3442
3443Procedure TMainForm.BuildBookmarksMenu;
3444var
3445 i: integer;
3446 Bookmark: TBookmark;
3447 MenuItem: TMenuItem;
3448begin
3449 DestroyListObjects( BookmarksMenuItems );
3450 BookmarksMenuItems.Clear;
3451
3452 if Bookmarks.Count > 0 then
3453 begin
3454 MenuItem:= TMenuItem.Create( self );
3455 MenuItem.Caption:= '-';
3456 BookmarksMenu.Add( MenuItem );
3457 BookmarksMenuItems.Add( MenuItem );
3458 end;
3459
3460 for i:= 0 to Bookmarks.Count -1 do
3461 begin
3462 Bookmark := Bookmarks[ i ];
3463 MenuItem:= TMenuItem.Create( self );
3464
3465 MenuItem.Caption:= Bookmark.Name;
3466 MenuItem.OnClick:= BookmarksMenuItemClick;
3467 MenuItem.Tag:= i;
3468 BookmarksMenu.Add( MenuItem );
3469 BookmarksMenuItems.Add( MenuItem );
3470 end;
3471end;
3472
3473Procedure TMainForm.UpdateBookmarksForm;
3474begin
3475 if Assigned( BookmarksForm ) then
3476 BookmarksForm.RefreshList;
3477end;
3478
3479Procedure TMainForm.ClearBookmarks;
3480begin
3481 ClearListAndObjects( Bookmarks );
3482 BuildBookmarksMenu;
3483 if Assigned( BookmarksForm ) then
3484 begin
3485 UpdateBookmarksForm; // clear bookmarks for next show
3486 BookmarksForm.Hide;
3487 end;
3488
3489end;
3490
3491procedure TMainForm.LoadBookmarks( HelpFile: THelpFile );
3492var
3493 Bookmark: TBookmark;
3494 BookmarksFile: TextFile;
3495 BookmarksFileName: string;
3496 S: string;
3497begin
3498 LogEvent(LogSettings, 'Load bookmarks for ' + HelpFile.Filename);
3499
3500 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3501
3502 if not FileExists( BookmarksFileName ) then
3503 exit;
3504
3505 FileMode := fmInput;
3506 AssignFile( BookmarksFile, BookmarksFileName );
3507 try
3508 Reset( BookmarksFile );
3509 try
3510 while not Eof( BookmarksFile ) do
3511 begin
3512 ReadLn( BookmarksFile, s );
3513 if trim( Uppercase( s ) ) = '[BOOKMARK]' then
3514 begin
3515 Bookmark:= TBookmark.Load( BookmarksFile, HelpFile );
3516 Bookmarks.Add( Bookmark );
3517 end;
3518 end;
3519 finally
3520 System.Close( BookmarksFile );
3521 end;
3522 except
3523 on e: exception do
3524 DoErrorDlg( LoadBookmarksTitle,
3525 LoadBookmarksError
3526 + e.message );
3527 end;
3528end;
3529
3530procedure TMainForm.SaveBookmarks;
3531var
3532 FileIndex: integer;
3533 HelpFile: THelpFile;
3534begin
3535 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3536 begin
3537 HelpFile := CurrentOpenFiles[ FileIndex ];
3538 SaveBookmarksForFile( HelpFile );
3539 end;
3540end;
3541
3542procedure TMainForm.SaveNotes;
3543var
3544 FileIndex: integer;
3545 HelpFile: THelpFile;
3546begin
3547 LogEvent(LogSettings, 'Save notes');
3548
3549 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
3550 begin
3551 HelpFile := CurrentOpenFiles[ FileIndex ];
3552 SaveNotesForFile( HelpFile );
3553 end;
3554end;
3555
3556procedure TMainForm.SaveBookmarksForFile( HelpFile: THelpFile );
3557var
3558 i: integer;
3559 Bookmark: TBookmark;
3560 BookmarksFile: TextFile;
3561 BookmarksFileName: string;
3562 BookmarkCount: integer;
3563begin
3564 LogEvent(LogSettings, 'Save bookmarks for ' + HelpFile.Filename);
3565
3566 BookmarksFileName:= ChangeFileExt( HelpFile.FileName, '.bmk' );
3567
3568 BookmarkCount:= 0;
3569 for i:= 0 to Bookmarks.Count - 1 do
3570 begin
3571 Bookmark := Bookmarks[ i ];
3572
3573 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3574 inc( BookmarkCount );
3575 end;
3576
3577 if BookmarkCount = 0 then
3578 begin
3579 if FileExists( BookmarksFileName ) then
3580 DeleteFile( BookmarksFileName );
3581 exit;
3582 end;
3583
3584 AssignFile( BookmarksFile, BookmarksFileName );
3585 try
3586 Rewrite( BookmarksFile );
3587 try
3588 for i := 0 to Bookmarks.Count - 1 do
3589 begin
3590 Bookmark:= Bookmarks[ i ];
3591 if Bookmark.ContentsTopic.HelpFile = HelpFile then
3592 begin
3593 WriteLn( BookmarksFile, '[Bookmark]' );
3594 Bookmark.Save( BookmarksFile );
3595 end;
3596 end;
3597 finally
3598 System.Close( BookmarksFile );
3599 end;
3600 except
3601 on e: exception do
3602 DoErrorDlg( SaveBookmarksTitle,
3603 SaveBookmarksError
3604 + e.message );
3605 end;
3606end;
3607
3608// Reads colors back from controls, in case they have changed by
3609// drag and drop
3610Procedure TMainForm.GetColors;
3611begin
3612 with Settings do
3613 begin
3614 Colors[ ContentsBackgroundColorIndex ] := ContentsOutline.Color;
3615 Colors[ ContentsTextColorIndex ] := ContentsOutline.PenColor;
3616 Colors[ IndexBackgroundColorIndex ] := IndexListBox.Color;
3617 Colors[ IndexTextColorIndex ] := IndexListBox.PenColor;
3618 Colors[ SearchBackgroundColorIndex ] := SearchResultsListBox.Color;
3619 Colors[ SearchTextColorIndex ] := SearchResultsListBox.PenColor;
3620 Colors[ NotesListBackgroundColorIndex ] := NotesListBox.Color;
3621 Colors[ NotesListTextColorIndex ] := NotesListBox.PenColor;
3622 end;
3623end;
3624
3625Procedure TMainForm.MainFormOnDestroy (Sender: TObject);
3626Begin
3627 LogEvent(LogShutdown, 'MainFormOnDestroy');
3628
3629 LogEvent(LogSettings, 'Write window position');
3630 WriteWindowPos( self );
3631
3632 LogEvent(LogSettings, 'Update colors');
3633 GetColors;
3634
3635 LogEvent(LogSettings, 'Save settings');
3636 SaveSettings;
3637 LogEvent(LogSettings, 'Save settings done');
3638
3639 // else- don't save position/size if doing own help
3640
3641 TopicText.Destroy;
3642
3643 LogEvent(LogShutdown, 'Destroy MRU menu items');
3644 MRUMenuItems.Destroy;
3645
3646 LogEvent(LogShutdown, 'Destroy navigate to menu items');
3647 NavigateToMenuItems.Destroy;
3648
3649 LogEvent(LogShutdown, 'Destroy pagehistory');
3650 PageHistory.Destroy;
3651
3652 LogEvent(LogShutdown, 'Clear/destroy notes');
3653 ClearNotes;
3654 Notes.Destroy;
3655
3656 LogEvent(LogShutdown, 'Clear/destroy bookmarks');
3657 ClearBookmarks;
3658 Bookmarks.Destroy;
3659
3660 LogEvent(LogShutdown, 'Destroy bookmark menu items');
3661 BookmarksMenuItems.Destroy;
3662
3663 LogEvent(LogShutdown, 'Destroy files/index/windows');
3664 CurrentOpenFiles.Destroy;
3665 DisplayedIndex.Destroy;
3666 Windows.Destroy;
3667
3668 // tell help manager(s) we are stopping.
3669 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
3670
3671 HelpManagerWindows.Destroy;
3672
3673 DestroyListObjects( Settings.MRUList );
3674 Settings.MRUList.Destroy;
3675
3676 // TODO rbri maybe we have to do this
3677 // Parameters.FilenamesParam.Destroy;
3678
3679 if g_CurrentLanguageFile <> nil then
3680 g_CurrentLanguageFile.Destroy;
3681
3682 LogEvent(LogShutdown, 'Close global filelist');
3683 GlobalFilelist.Destroy;
3684
3685 LogEvent(LogShutdown, 'Close shared memory');
3686 SharedMemory.Destroy;
3687
3688 AllFilesWordSequences.Destroy;
3689
3690 LogEvent(LogShutdown, 'MainFormOnDestroy done');
3691End;
3692
3693Procedure TMainForm.MainFormOnSetupShow (Sender: TObject);
3694Begin
3695 LogEvent(LogSettings, 'OnSetupShow');
3696 TabSet.TabIndex := 0;
3697 Notebook.PageIndex := 0;
3698End;
3699
3700Procedure TMainForm.OnException( Sender: TObject;
3701 E: Exception );
3702var
3703 TheText : string;
3704 F: TextFile;
3705 i: integer;
3706 HelpFile: THelpFile;
3707 LogFilename: string;
3708
3709begin
3710 LogFilename := GetLogFilesDir + CrashLogFileName;
3711
3712 LogException( E,
3713 LogFileName,
3714 'NewView',
3715 GetAppVersion,
3716 F );
3717
3718 if CurrentOpenFiles <> nil then
3719 begin
3720 WriteLn( F, 'Loaded files ('
3721 + IntToStr( CurrentOpenFiles.Count )
3722 + '):' );
3723 try
3724 for i := 0 to CurrentOpenFiles.Count - 1 do
3725 begin
3726 HelpFile := CurrentOpenFiles[ i ];
3727 WriteLn( F, HelpFile.Filename );
3728 end;
3729 except
3730 end;
3731 end;
3732 try
3733 if CurrentTopic <> nil then
3734 WriteLn( F, 'Last major topic index: '
3735 + IntToStr( CurrentTopic.Index ) );
3736 except
3737 // ignore exceptions if there isn't a valid current topic
3738 end;
3739 if Windows <> nil then
3740 begin
3741 WriteLn( F, 'Top-level open windows: '
3742 + IntToStr( Windows.Count ) );
3743 end;
3744
3745 System.Close( F );
3746
3747 TheText := ApplicationErrorA + EndLine
3748 + EndLine
3749 + E.Message + EndLine
3750 + ApplicationErrorB
3751 + LogFilename
3752 + ')' + EndLine
3753 + EndLine
3754 + ApplicationErrorC
3755 + EndLine;
3756
3757 if DoYesNoDlg( ApplicationErrorTitle,
3758 TheText ) then
3759 begin
3760 // exit a bit more nicely - remove ourselves from the global filelist.
3761 GlobalFilelist.RemoveWindowFiles( Frame.Handle );
3762 Application.Terminate;
3763 end;
3764end;
3765
3766// give our main window a unique class name we can find
3767procedure TMainForm.GetClassData(var ClassData: TClassData);
3768Begin
3769 inherited GetClassData( ClassData );
3770 ClassData.ClassName := MAIN_WINDOW_CLASS_NAME;
3771End;
3772
3773// Position the window offset from existing top help window (if any)
3774Procedure TMainForm.PositionWindow;
3775var
3776 hTopWindow: HWND;
3777 TopHelpWindowPos: SWP;
3778 Offset: longint;
3779Begin
3780 hTopWindow := FindTopFormWindow( MAIN_WINDOW_CLASS_NAME );
3781
3782 if hTopWindow <> NULLHANDLE then
3783 begin
3784 // found an existing help window, find it's location
3785 if WinQueryWindowPos(
3786 hTopWindow,
3787 TopHelpWindowPos ) then
3788 begin
3789 if ( TopHelpWindowPos.FL and ( SWP_MINIMIZE or SWP_MINIMIZE ) ) > 0 then
3790 Begin
3791 // window is maximized or minimised, so get the restore position from window USHORTs
3792 TopHelpWindowPos.x := WinQueryWindowUShort( hTopWindow, QWS_XRESTORE );
3793 TopHelpWindowPos.Y := WinQueryWindowUShort( hTopWindow, QWS_YRESTORE );
3794 end;
3795
3796 // offset new window by height of title bar + border
3797 Offset := Screen.SystemMetrics( smCyTitleBar )
3798 + Screen.SystemMetrics( smCySizeBorder );
3799 Left := TopHelpWindowPos.x + Offset;
3800 Bottom := TopHelpWindowPos.y - Offset;
3801
3802 // I guess I am leaving width/height out for compatibility...?
3803 end;
3804 end;
3805end;
3806
3807Procedure TMainForm.OnHelp( context: THelpContext;
3808 var Result: Boolean );
3809begin
3810 if OwnHelpMode then
3811 begin
3812 // we are viewing the help file now - display our own help!
3813 PostMsg( Handle, NHM_TOPIC_BY_RESOURCE_ID, context, 0 );
3814 exit;
3815 end;
3816
3817 Application.HelpContext( context );
3818end;
3819
3820Procedure TMainForm.MainFormOnCreate (Sender: TObject);
3821var
3822 tmpCmdLine: String;
3823Begin
3824 LogEvent(LogStartup, 'MainFormOnCreate');
3825
3826 StartingUp := true;
3827
3828 Application.HelpFile := GetOwnHelpFilename; // OWN_HELP_MARKER;
3829 Application.OnHelp := OnHelp;
3830
3831 SharedMemory := AccessSharedMemory;
3832 GlobalFilelist := TGlobalFilelist.Create;
3833
3834 // parse parameters into Parameters object
3835 tmpCmdLine := nativeOS2GetCmdLineParameter;
3836 CmdLineParameters := TCmdLineParameters.Create;
3837 CmdLineParameters.parseCmdLine(tmpCmdLine);
3838
3839 RegisterForLanguages( OnLanguageEvent );
3840
3841 // if debug is not enabled, get rid of the debug menu and separator.
3842 if GetEnv( 'NEWVIEW_DEBUG' ) = '' then
3843 begin
3844 ToolsDebugSep.Destroy;
3845 ToolsDebugMenu.Destroy;
3846 DebugShowCodesMI := nil;
3847 DebugShowWordSeparatorsMI := nil;
3848 end;
3849
3850 // set up globals for Exec
3851 ExecViaSession := true;
3852 AsynchExec := true;
3853
3854 // set up form icons
3855 Forms.FormIconResourceID := 1;
3856
3857 Application.OnException := OnException;
3858
3859 ContentsOutline.SmoothScroll := false;
3860
3861 LogEvent(LogStartup, 'Choosing default font: Trying WarpSans');
3862
3863 Font := GetNiceDefaultFont;
3864
3865 // Set the menu fonts, because they remember their own specific one
3866 MainMenu.Font := Screen.MenuFont;
3867 ViewPopupMenu.Font := Screen.MenuFont;
3868
3869 // NOTE: SPCC will copy this font to TApplication
3870 // in TApplication.Run
3871
3872 LogEvent(LogStartup, 'Starting NewView: MainFormOnCreate');
3873
3874 Application.OnHint := OnHint;
3875
3876 StartMem := MemAvailBytes;
3877
3878 DisplayedIndex := TStringList.Create;
3879
3880 HelpManagerWindows := TList.Create;
3881
3882 AllFilesWordSequences := TList.Create;
3883
3884 CurrentOpenFiles := TList.Create;
3885 Notes := TList.Create;
3886 Bookmarks := TList.Create;
3887 BookmarksMenuItems := TList.Create;
3888 Windows := TList.Create;
3889
3890 TopicText := TAString.Create;
3891
3892 Navigating := false;
3893 InIndexSearch := false;
3894 SettingFont := false;
3895
3896 PageHistory := TStringList.Create;
3897 CurrentHistoryIndex := -1;
3898
3899 Settings.MRUList := TList.Create;
3900
3901 MRUMenuItems := TList.Create;
3902 NavigateToMenuItems := TList.Create;
3903
3904 LogEvent(LogSettings, 'Loading settings');
3905
3906 LoadSettings;
3907 SetShowLeftPanel( ShowLeftPanel ); // update menu
3908
3909 // load default strings
3910 LogEvent(LogSettings, 'Loading language');
3911
3912 if CmdLineParameters.getLanguage <> '' then
3913 LoadAutoLanguage( 'newview', CmdLineParameters.getLanguage )
3914 else
3915 LoadDefaultLanguage( 'newview' );
3916
3917 LogEvent(LogSettings, 'Applying settings');
3918 ApplySettings;
3919
3920 // default position is centered..
3921 LogEvent(LogSettings, 'Set default position');
3922 if Width > Screen.Width then
3923 Width := Screen.Width;
3924 if Height > Screen.Height then
3925 Height := Screen.Height;
3926 Left := ( Screen.Width - Width ) div 2;
3927 Bottom := ( Screen.Height - Height ) div 2;
3928
3929 LogEvent(LogSettings, 'ReadWindowPos');
3930 ReadWindowPos( Self );
3931
3932 PositionWindow;
3933
3934 LogEvent(LogSettings, 'Creating MRU list');
3935
3936 CreateMRUMenuItems;
3937
3938 CloseFile;
3939
3940 LogEvent(LogStartup, 'OnCreate done');
3941
3942 if CmdLineParameters.getWindowPositionFlag then
3943 begin
3944 SmartSetWindowPos( self,
3945 CmdLineParameters.getWindowPosition.Left,
3946 CmdLineParameters.getWindowPosition.Bottom,
3947 CmdLineParameters.getWindowPosition.Width,
3948 CmdLineParameters.getWindowPosition.Height,
3949 false );
3950 end;
3951
3952 LogEvent(LogStartup, 'MainFormOnCreate Done');
3953End;
3954
3955Procedure TMainForm.ApplySettings;
3956var
3957 ToolbarBitmap: TBitmap;
3958begin
3959 ContentsOutline.Color:= Settings.Colors[ ContentsBackgroundColorIndex ];
3960 ContentsOutline.PenColor:= Settings.Colors[ ContentsTextColorIndex ];
3961 ContentsOutline.TreeLineColor:= Settings.Colors[ ContentsLinesColorIndex ];
3962 IndexListBox.Color:= Settings.Colors[ IndexBackgroundColorIndex ];
3963 IndexListBox.PenColor:= Settings.Colors[ IndexTextColorIndex ];
3964 SearchResultsListBox.Color:= Settings.Colors[ SearchBackgroundColorIndex ];
3965 SearchResultsListBox.PenColor:= Settings.Colors[ SearchTextColorIndex ];
3966 NotesListBox.Color:= Settings.Colors[ NotesListBackgroundColorIndex ];
3967 NotesListBox.PenColor:= Settings.Colors[ NotesListTextColorIndex ];
3968
3969 SettingFont := true;
3970 Notebook.ParentFont := true;
3971 ContentsOutline.ParentFont := true;
3972 IndexListBox.ParentFont := true;
3973 SearchResultsListBox.ParentFont := true;
3974 NotesListBox.ParentFont := true;
3975 TabSet.ParentFont := true;
3976 Coolbar.ParentFont := true;
3977 if Settings.Fonts[ ApplicationFontIndex ] <> nil then
3978 Font := Settings.Fonts[ ApplicationFontIndex ]
3979 else
3980 Font := GetNiceDefaultFont;
3981 SettingFont := false;
3982
3983 Coolbar.BackgroundBitmap := nil;
3984 if FileExists( Settings.ToolbarBackgroundImageFilename ) then
3985 begin
3986 ToolbarBitmap:= TBitmap.Create;
3987 try
3988 ToolbarBitmap.LoadFromFIle( Settings.ToolbarBackgroundImageFilename );
3989 Coolbar.BackgroundBitmap := ToolbarBitmap;
3990 except
3991 end;
3992 ToolbarBitmap.Destroy;
3993 end;
3994
3995 CoolBar.ShowImages := Settings.ToolbarStyle in [ tsImages, tsImagesAndText ];
3996 CoolBar.ShowText := Settings.ToolbarStyle in [ tsText, tsImagesAndText ];
3997
3998 CoolBar.SetMinConstButtonWidth;
3999
4000 DisplayPanel.Color := Settings.Colors[ TopicBackgroundColorIndex ];
4001
4002 SetupViews( Windows );
4003end;
4004
4005// Setup the rich text views in the specified windows (e.g for changing global settings)
4006Procedure TMainForm.SetupViews( WindowList: TList );
4007var
4008 WindowIndex: longint;
4009 Window: THelpWindow;
4010begin
4011 for WindowIndex := 0 to WindowList.Count - 1 do
4012 begin
4013 Window := WindowList[ WindowIndex ];
4014 Window.SetupRTView;
4015 SetupViews( Window.ChildWindows );
4016 end;
4017end;
4018
4019Procedure TMainForm.PostHelpManagerMessage( MessageType: ULONG;
4020 Param1: long;
4021 Param2: long );
4022var
4023 i: longint;
4024begin
4025 for i := 0 to HelpManagerWindows.Count - 1 do
4026 PostMsg( HWND( HelpManagerWindows[ i ] ),
4027 MessageType,
4028 Param1,
4029 Param2 );
4030end;
4031
4032Procedure TMainForm.ClearHelpManager;
4033Begin
4034 if not CmdLineParameters.getHelpManagerFlag then
4035 exit;
4036
4037 // tell the help manager(s) we are no longer playing with them
4038 PostHelpManagerMessage( NHM_FORGET_VIEWER, 0, 0 );
4039
4040 CmdLineParameters.setHelpManagerFlag(false);
4041
4042 HelpManagerWindows.Clear;
4043End;
4044
4045Procedure TMainForm.MainFormOnShow (Sender: TObject);
4046Begin
4047 EnableCallstackLogging( true );
4048
4049 LogEvent(LogStartup, 'MainFormOnShow');
4050
4051 if CmdLineParameters.getOwnerWindow <> NULLHANDLE then
4052 begin
4053 LogEvent(LogStartup, 'Setting owner: '
4054 + IntToStr( CmdLineParameters.getOwnerWindow));
4055 WinSetOwner( Frame.Handle,
4056 CmdLineParameters.getOwnerWindow );
4057
4058 end;
4059
4060 if CmdLineParameters.getHelpManagerFlag then
4061 begin
4062 LogEvent(LogStartup, ' Help Manager Title: '
4063 + StrNPas( pSharedStruct ^. Title,
4064 SHARED_STRUCT_TITLE_SIZE ) );
4065 HelpManagerVersion := StrNPas( pSharedStruct ^. Version,
4066 SHARED_STRUCT_VERSION_SIZE );
4067 LogEvent(LogStartup, ' Help Manager Version: ' + HelpManagerVersion );
4068
4069 end;
4070
4071 CoolBar.SetMinConstButtonWidth;
4072
4073 LogEvent(LogStartup, 'Post WM_OPENED');
4074
4075 ResetProgress;
4076
4077 AddShortcut( kbF11, kbF11 ); // prev in contents
4078 AddShortcut( kbF12, kbF12 ); // next in contents
4079 AddShortcut( kbF7, kbF7 ); // back
4080 AddShortcut( kbF8, kbF8 ); // forward
4081 AddShortcut( kbCtrlCLeft, kbCtrlCLeft ); // back
4082
4083 PostMsg( Handle, WM_OPENED, 0, 0 );
4084End;
4085
4086Procedure TMainForm.DisplaySelectedContentsTopic;
4087var
4088 Topic: TTopic;
4089Begin
4090 if ContentsOutline.SelectedNode = nil then
4091 exit;
4092 Topic := ContentsOutline.SelectedNode.Data as TTopic;
4093 DisplayTopic( Topic );
4094End;
4095
4096// Check that the HELP and BOOKSHELF environment variables
4097// are defined (as they should be on any working OS/2 system).
4098// Show a warning message if not.
4099Procedure TMainForm.CheckEnvironmentVars;
4100var
4101 HelpOK: boolean;
4102 BookshelfOK: boolean;
4103 ErrorText: string;
4104begin
4105 HelpOK := GetEnv( HelpPathEnvironmentVar ) <> '';
4106 BookshelfOK := GetEnv( BookshelfEnvironmentVar ) <> '';
4107 if HelpOK and BookshelfOK then
4108 // all ok.
4109 exit;
4110
4111 // One or both missing
4112
4113 ErrorText := '';
4114 if not BookshelfOK then
4115 ErrorText := ErrorText
4116 + EnvironmentVarUndefined
4117 + BookshelfEnvironmentVar
4118 + EndLine;
4119
4120 if not HelpOK then
4121 ErrorText := ErrorText
4122 + EnvironmentVarUndefined
4123 + HelpPathEnvironmentVar
4124 + EndLine;
4125
4126 DoWarningDlg( EnvironmentVarErrorTitle,
4127 EnvironmentVarError
4128 + EndLine
4129 + EndLine
4130 + ErrorText );
4131
4132end;
4133
4134Procedure LoadSupportDLL;
4135begin
4136 try
4137 LoadDLLFunction( 'newview.dll',
4138 'LZWDECOMPRESSBLOCK',
4139 hNewViewDLL,
4140 pointer( LZWDecompressBlock ) );
4141 except
4142 on E: Exception do
4143 begin
4144 DoErrorDlg( 'DLL Error',
4145 E.Message );
4146 LZWDecompressBlock := nil;
4147 end;
4148 end;
4149end;
4150
4151Procedure TMainForm.WMOpened( Var Msg: TMessage );
4152var
4153 Filenames: TStringList;
4154 M1: longword;
4155 OpenFirstTopic: boolean;
4156begin
4157 if Application.HelpFile = '' then
4158 DoErrorDlg( 'NewView Help', 'NewView help file not found' );
4159
4160 LoadSupportDLL;
4161
4162 LogEvent(LogStartup, 'WMOpened: SetLayout');
4163
4164 if CmdLineParameters.getHelpManagerFlag then
4165 FShowLeftPanel := Settings.ShowLeftPanel_Help
4166 else
4167 FShowLeftPanel := Settings.ShowLeftPanel_Standalone;
4168
4169 SetLayout;
4170
4171// ProfileEvent( 'Apply settings' );
4172// ApplySettings;
4173
4174 LogEvent(LogStartup, 'Enable controls');
4175 EnableControls;
4176
4177// ProfileEvent( 'ReadWindowPos' );
4178// ReadWindowPos( Self );
4179
4180 LogEvent(LogStartup, 'Finish paint');
4181 Update;
4182
4183 if not CmdLineParameters.getHelpManagerFlag then
4184 begin
4185 LogEvent(LogStartup, 'Check environment vars');
4186 CheckEnvironmentVars;
4187
4188 if CmdLineParameters.getShowUsageFlag then
4189 begin
4190 LogEvent(LogStartup, 'Showing usage');
4191 ShowUsage;
4192 end;
4193 end;
4194
4195 HelpManagerWindows.Add( pointer( CmdLineParameters.getHelpManagerWindow ) );
4196
4197 if CmdLineParameters.getInterpretedFileNames <> '' then
4198 begin
4199 // open specified files
4200 Filenames := TStringList.Create;
4201
4202 // TODO use StrExtractStrings
4203 StringToList(cmdLineParameters.getInterpretedFileNames, Filenames, '+' );
4204
4205 LogEvent(LogStartup, 'Call OpenFiles');
4206
4207 OpenFirstTopic := true;
4208
4209 if ( CmdLineParameters.getInterpretedSearchText <> '' )
4210 OR CmdLineParameters.getSearchFlag
4211 OR CmdLineParameters.getHelpManagerFlag
4212 then
4213 // if we're going to search, don't open first topic
4214 // don't open first topic if we're online help
4215 // in case we are wanting to show a specific topic
4216 // - saves time/flicker
4217 OpenFirstTopic := false;
4218
4219 OpenFiles( Filenames,
4220 CmdLineParameters.getWindowTitle,
4221 OpenFirstTopic );
4222
4223 Filenames.Destroy;
4224
4225 if not CmdLineParameters.getSearchFlag
4226 and not CmdLineParameters.getGlobalSearchFlag
4227 and (CmdLineParameters.getInterpretedSearchText <> '') then
4228 begin
4229 // search in contents only!
4230 LogEvent(LogStartup, 'Do startup topic search');
4231
4232 StartupTopicSearch( CmdLineParameters.getSearchText );
4233 end
4234 else if CmdLineParameters.getSearchFlag then
4235 begin
4236 // search in specified files
4237 LogEvent(LogStartup, 'Do search for topic');
4238 DisplaySearch;
4239
4240 SearchFor( CmdLineParameters.getInterpretedSearchText );
4241 end;
4242 end;
4243
4244 if NOT CmdLineParameters.getShowUsageFlag
4245 AND CmdLineParameters.getGlobalSearchFlag then
4246 begin
4247 // Global search
4248 LogEvent(LogStartup, 'Do global search: ' + CmdLineParameters.getFileNamesRaw );
4249 DoGlobalSearch( CmdLineParameters.getInterpretedSearchText );
4250 end;
4251
4252 LogEvent(LogStartup, 'Open finished');
4253
4254 if CmdLineParameters.getHelpManagerFlag then
4255 begin
4256 // Tell helpmanager(s) our window handle
4257 PostHelpManagerMessage( NHM_VIEWER_READY,
4258 Handle,
4259 0 );
4260 end;
4261
4262 M1:= MemAvail;
4263
4264 StartingUp := false;
4265
4266 LogEvent(LogStartup, 'RUN PROGRAM');
4267end;
4268
4269Procedure TMainForm.MainFormOnResize (Sender: TObject);
4270Begin
4271 if not Visible then
4272 exit;
4273 if Handle = 0 then
4274 exit;
4275
4276 SetLayout;
4277
4278End;
4279
4280Function TMainForm.GetShowLeftPanel: boolean;
4281begin
4282 Result := FShowLeftPanel;
4283end;
4284
4285Procedure TMainForm.SetShowLeftPanel( Value: boolean );
4286begin
4287 ShowLeftPanelMI.Checked := Value;
4288 if Value = FShowLeftPanel then
4289 exit;
4290 FShowLeftPanel := Value;
4291 if FShowLeftPanel then
4292 NotebookOnPageChanged( self ) // make sure page is updated
4293 else
4294 FocusFirstHelpWindow;
4295 EnableControls;
4296 SetLayout;
4297end;
4298
4299Procedure TMainForm.VSplitBarOnChange (NewSplit: LongInt);
4300Begin
4301 if VSplitBar.Left < 30 then
4302 begin
4303 ShowLeftPanel := false
4304 end
4305 else
4306 begin
4307 Settings.LeftPanelWidth := VSplitBar.Left;
4308 ShowLeftPanel := true;
4309 end;
4310 SetLayout;
4311End;
4312
4313// Set the layout of the main form
4314Procedure TMainForm.SetLayout;
4315var
4316 RealClientHeight : longint;
4317 CoolbarSpace: longint;
4318 TextHeight: longint;
4319Begin
4320 TextHeight := Canvas.TextHeight( 'S' );
4321 Tabset.Height := TextHeight + 5;
4322
4323 Coolbar.Visible := Settings.ToolbarStyle <> tsNone;
4324
4325 case Settings.ToolbarStyle of
4326 tsImages:
4327 Coolbar.Height := Coolbar.Sections[ 0 ].Width;
4328 tsText:
4329 Coolbar.Height := TextHeight + 5;
4330 tsImagesAndText:
4331 CoolBar.Height := ButtonImages.GetBitmapReference(0).Width + TextHeight + 10;
4332 end;
4333
4334 CoolbarSpace := Coolbar.Height;
4335 if not Coolbar.Visible then
4336 CoolbarSpace := 0;
4337
4338 StatusPanel.Left:= 0;
4339 StatusPanel.Width:= ClientWidth div 2 - 2;
4340 StatusPanel.Height := TextHeight + 2;
4341
4342 ProgressPanel.Left:= ClientWidth div 2 + 2;
4343 ProgressPanel.Width:= ClientWidth - ProgressPanel.Left;
4344 ProgressPanel.Height := TextHeight + 2;
4345
4346 Notebook.Bottom := StatusPanel.Height + 3;
4347 VSplitBar.Bottom := Notebook.Bottom;
4348 DisplayPanel.Bottom := Notebook.Bottom;
4349
4350 RealClientHeight := ClientHeight
4351 - CoolbarSpace
4352 - Notebook.Bottom;
4353
4354 LogEvent(LogStartup, 'TMainForm.SetLayout');
4355 LogEvent(LogStartup, ' RealClientHeight: ' + IntToStr( RealClientHeight ));
4356
4357 LogEvent(LogStartup, ' Form Width: ' + IntToStr( Width ));
4358 LogEvent(LogStartup, ' Form Height: ' + IntToStr( Height ) );
4359 LogEvent(LogStartup, ' Form ClientWidth: ' + IntToStr( ClientWidth ) );
4360 LogEvent(LogStartup, ' Form ClientHeight: ' + IntToStr( ClientHeight ) );
4361 LogEvent(LogStartup, ' CoolBar.Height: ' + IntToStr( CoolBar.Height ) );
4362 LogEvent(LogStartup, ' CoolBar.Bottom: ' + IntToStr( CoolBar.Bottom ) );
4363
4364 if CurrentOpenFiles.Count > 0 then
4365 VSplitBar.Width := Max( 5, Canvas.TextWidth( ' ' ) )
4366 else
4367 VSplitBar.Width := 0;
4368
4369 VSplitBar.Height := RealClientHeight;
4370
4371 if Settings.LeftPanelWidth > ClientWidth - 50 then
4372 Settings.LeftPanelWidth := ClientWidth - 50;
4373 if Settings.LeftPanelWidth < 50 then
4374 Settings.LeftPanelWidth := 50;
4375
4376 if ShowLeftPanel then
4377 begin
4378 VSplitBar.Left := Settings.LeftPanelWidth;
4379 VSplitBar.Hint := SplitBarDblClickToHide;
4380 end
4381 else
4382 begin
4383 VSplitBar.Left := 0;
4384 VSplitBar.Hint := SplitBarDblClickToShow;
4385 end;
4386
4387 Tabset.Left := 0;
4388 Tabset.Width := VSplitBar.Left;
4389 Tabset.Bottom := ClientHeight
4390 - CoolbarSpace
4391 - Tabset.Height;
4392
4393 Notebook.Left := 0;
4394 Notebook.Width := VSplitBar.Left;
4395 Notebook.Height := RealClientHeight
4396 - Tabset.Height
4397 - 3;
4398
4399 DisplayPanel.Left:= VSplitBar.Left + VSplitBar.Width;
4400 DisplayPanel.Width:= ClientWidth - DisplayPanel.Left;
4401 DisplayPanel.Height := RealClientHeight;
4402 LogEvent(LogStartup, ' DisplayPanel.Width: ' + IntToStr( DisplayPanel.Width ) );
4403 LogEvent(LogStartup, ' DisplayPanel.Height: ' + IntToStr( DisplayPanel.Height ) );
4404 LogEvent(LogStartup, ' DisplayPanel.Bottom: ' + IntToStr( DisplayPanel.Bottom ) );
4405
4406 ProgressBar.Left:= 1;
4407 ProgressBar.Bottom:= 1;
4408 ProgressBar.Width:= ProgressPanel.Width - 2;
4409 ProgressBar.Height:= ProgressPanel.Height - 2;
4410
4411 // Layout the visible help windows also
4412 LayoutWindowList( Windows );
4413End;
4414
4415// Lay out the specified list of help windows
4416Procedure TMainForm.LayoutWindowList( WindowList: TList );
4417var
4418 Window: THelpWindow;
4419 WindowIndex: longint;
4420begin
4421 for WindowIndex:= 0 to WindowList.Count - 1 do
4422 begin
4423 Window:= WindowList[ WindowIndex ];
4424 Window.SetLayout;
4425 end;
4426end;
4427
4428Procedure TMainForm.FindNextMIOnClick (Sender: TObject);
4429begin
4430 if FindText = '' then
4431 begin
4432 FindMIOnClick( sender );
4433 exit;
4434 end;
4435
4436 if GetActiveWindow = nil then
4437 begin
4438 DoErrorDlg( FindTitle,
4439 FindSelectWindowError );
4440 exit;
4441 end;
4442
4443 DoFind( foFromCurrent );
4444end;
4445
4446Procedure TMainForm.DoFind( FindOrigin: TFindOrigin );
4447var
4448 Window: THelpWindow;
4449begin
4450 SetWaitCursor;
4451 Window := GetActiveWindow;
4452 if not Window.View.Find( FindOrigin, FindText ) then
4453 begin
4454 SetStatus( TextNotFoundMsg );
4455 Beep( 1000, 100 );
4456 end;
4457 ClearWaitCursor;
4458End;
4459
4460Procedure TMainForm.FindMIOnClick (Sender: TObject);
4461begin
4462 if GetActiveWindow = nil then
4463 begin
4464 DoErrorDlg( FindTitle,
4465 FindSelectWindowError );
4466 exit;
4467 end;
4468 if not DoInputQuery( FindTitle,
4469 FindPrompt,
4470 FindText ) then
4471 exit;
4472
4473 DoFind( foFromStart );
4474End;
4475
4476Procedure TMainForm.IndexSearchEditOnScan (Sender: TObject;
4477 Var KeyCode: TKeyCode);
4478Begin
4479 case KeyCode of
4480 kbCUp:
4481 begin
4482 if IndexListBox.ItemIndex > 0 then
4483 IndexListBox.ItemIndex:= IndexListBox.ItemIndex - 1;
4484 KeyCode:= kbNull;
4485 end;
4486
4487 kbCDown:
4488 begin
4489 if IndexListBox.ItemIndex < IndexListBox.Items.Count - 1 then
4490 IndexListBox.ItemIndex:= IndexListBox.ItemIndex + 1;
4491 KeyCode:= kbNull;
4492 end;
4493
4494 kb_VK + VK_NEWLINE:
4495 begin
4496 DisplaySelectedIndexTopic;
4497 end;
4498 end;
4499
4500End;
4501
4502Procedure TMainForm.IndexSearchEditOnChange (Sender: TObject);
4503var
4504 MatchIndex: longint;
4505 IndexINdex: longint;
4506 SearchText: string;
4507Begin
4508 if InIndexSearch then
4509 exit;
4510
4511 MatchIndex:= -1;
4512 SearchText:= trim( IndexSearchEdit.Text );
4513 for IndexIndex:= 0 to DisplayedIndex.Count - 1 do
4514 begin
4515 if StrStarts( SearchText, DisplayedIndex[ IndexIndex ] ) then //IndexEntry ) then
4516 begin
4517 MatchIndex:= IndexIndex;
4518 break;
4519 end;
4520 end;
4521
4522 if MatchIndex = -1 then
4523 exit;
4524
4525 InIndexSearch:= true;
4526
4527 if IndexListBox.ItemIndex <> MatchIndex then
4528 IndexListBox.ItemIndex:= MatchIndex;
4529
4530 InIndexSearch:= false;
4531End;
4532
4533Procedure TMainForm.FileInformationMIOnClick (Sender: TObject);
4534var
4535 FileIndex: longint;
4536 HelpFile: THelpFile;
4537
4538 TotalTopicCount: longint;
4539 TotalIndexCount: longint;
4540 TotalFileSize: longint;
4541
4542Begin
4543 TotalTopicCount := 0;
4544 TotalIndexCount := 0;
4545 TotalFileSize := 0;
4546
4547 with InformationForm.InformationMemo do
4548 begin
4549 BeginUpdate;
4550 Lines.Clear;
4551 Lines.Add( FilesInfoTitle );
4552 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4553 begin
4554 HelpFile := CurrentOpenFiles[ FileIndex ];
4555
4556 Lines.Add( FilesInfoFilename + HelpFile.FileName );
4557 Lines.Add( FilesInfoFileTitle
4558 + HelpFile.Title );
4559 Lines.Add( FilesInfoTopicCount
4560 + IntToStr( HelpFile.TopicCount ) );
4561 Lines.Add( FilesInfoIndexCount
4562 + IntToStr( HelpFile.Index.Count ) );
4563 Lines.Add( FilesInfoDictionaryCount
4564 + IntToStr( HelpFile.DictionaryCount ) );
4565 Lines.Add( FilesInfoFileSize
4566 + IntToStr( HelpFile.FileSize ) );
4567
4568 inc( TotalTopicCount, HelpFile.TopicCount );
4569 inc( TotalIndexCount, HelpFile.Index.Count );
4570 inc( TotalFileSize, HelpFile.FileSize );
4571
4572 end;
4573
4574 Lines.Add( '' );
4575 Lines.Add( FilesInfoTotalTopicCount
4576 + IntToStr( TotalTopicCount ) );
4577 Lines.Add( FilesInfoTotalIndexCount
4578 + IntToStr( TotalIndexCount ) );
4579 Lines.Add( FilesInfoTotalFileSize
4580 + IntToStr( TotalFileSize ) );
4581 Lines.Add( '' );
4582
4583 EndUpdate;
4584 end;
4585 InformationForm.ShowModal;
4586End;
4587
4588Procedure TMainForm.DisplaySelectedSearchResultTopic;
4589var
4590 Topic: TTopic;
4591Begin
4592 if SearchResultsListBox.ItemIndex = -1 then
4593 exit;
4594 if SelectedObject( SearchResultsListBox ) = nil then
4595 // the "no results" place holder
4596 exit;
4597 Topic := SelectedObject( SearchResultsListBox ) as TTopic;
4598 DisplayTopic( Topic );
4599End;
4600
4601Procedure TMainForm.SearchTextEditOnScan (Sender: TObject;
4602 Var KeyCode: TKeyCode);
4603Begin
4604 case KeyCode of
4605 kbCUp:
4606 begin
4607 if SearchResultsListBox.ItemIndex > 0 then
4608 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex - 1;
4609 KeyCode := kbNull;
4610 SearchResultsListBox.Focus;
4611 end;
4612
4613 kbCDown:
4614 begin
4615 if SearchResultsListBox.ItemIndex < SearchResultsListBox.Items.Count - 1 then
4616 SearchResultsListBox.ItemIndex := SearchResultsListBox.ItemIndex + 1;
4617 KeyCode := kbNull;
4618 SearchResultsListBox.Focus;
4619 end;
4620 end;
4621End;
4622
4623Procedure TMainForm.SearchButtonOnClick (Sender: TObject);
4624Begin
4625 DoSearch;
4626End;
4627
4628// Matches old stupid View algorithm
4629Procedure TMainForm.StartupTopicSearch( const SearchText: string );
4630var
4631 i: longint;
4632 HelpFile: THelpFile;
4633 Topic: TTopic;
4634 // s: string;
4635begin
4636 // search files in order they are open
4637 for i := 0 to CurrentOpenFiles.Count - 1 do
4638 begin
4639 HelpFile := THelpFile( CurrentOpenFiles[ i ] );
4640
4641 // look for a topic whose title starts with the searchtext
4642 Topic := HelpFile.FindTopicByTitleStartsWith( SearchText );
4643
4644 if Topic = nil then
4645 // look for an index entry that starts with the searchtext
4646 Topic := HelpFile.FindTopicByIndexStartsWith( SearchText );
4647
4648 if Topic = nil then
4649 // look for a topic whose title contains the searchtext
4650 Topic := HelpFile.FindTopicByTitleContains( SearchText );
4651
4652 if Topic = nil then
4653 // look for an index entry that contains the searchtext
4654 Topic := HelpFile.FindTopicByIndexContains( SearchText );
4655
4656 if Topic <> nil then
4657 begin
4658 // found something, display it (don't keep searching files)
4659 DisplayTopic( Topic );
4660 exit;
4661 end;
4662 end;
4663 DoErrorDlg( SearchTitle, TextNotFoundMsg );
4664end;
4665
4666Procedure TMainForm.SearchFor( const SearchText: string );
4667begin
4668 SearchTextEdit.Text := SearchText;
4669 DisplaySearch;
4670 SearchResultsListBox.Focus;
4671
4672 // force repaint of everything before we start searching.
4673 Update;
4674
4675 DoSearch;
4676end;
4677
4678Procedure TMainForm.ClearAllWordSequences;
4679var
4680 i: longint;
4681 FileWordSequences: TList;
4682 HelpFile: THelpFile;
4683begin
4684 if AllFilesWordSequences = nil then
4685 exit;
4686
4687 for i := 0 to AllFilesWordSequences.Count - 1 do
4688 begin
4689 FileWordSequences := AllFilesWordSequences[ i ];
4690 HelpFile := CurrentOpenFiles[ i ];
4691 ClearWordSequences( FileWordSequences, HelpFile.DictionaryCount );
4692 FileWordSequences.Destroy;
4693 end;
4694 AllFilesWordSequences.Clear;
4695end;
4696
4697// Perform search for text in searchedit.
4698Procedure TMainForm.DoSearch;
4699var
4700 SearchResults: TList;
4701 SearchText: string;
4702 FileIndex: longint;
4703 HelpFile: THelpFile;
4704 TopicIndex: longint;
4705 Topic: TTopic;
4706 FileWordSequences: TList;
4707 Query: TTextSearchQuery;
4708begin
4709 SearchText := Trim( SearchTextEdit.Text );
4710
4711 SearchResultsListBox.Clear;
4712
4713 if SearchText = '' then
4714 exit;
4715
4716 SearchResultsListBox.Items.Add( SearchingMsg );
4717 SetStatus( SearchingMsg );
4718
4719 try
4720 Query := TTextSearchQuery.Create( SearchText );
4721 except
4722 on e: ESearchSyntaxError do
4723 begin
4724 DoErrorDlg( SearchTitle,
4725 SearchSyntaxError
4726 + e.Message );
4727 exit;
4728 end;
4729 end;
4730
4731 ClearAllWordSequences;
4732
4733 SetWaitCursor;
4734
4735 SearchResults := TList.Create;
4736
4737 // Search open help file
4738 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
4739 begin
4740 HelpFile := CurrentOpenFiles[ FileIndex ];
4741
4742 FileWordSequences := TList.Create;
4743
4744 try
4745 SearchHelpFile( HelpFile,
4746 Query,
4747 SearchResults,
4748 FileWordSequences );
4749 except
4750 on E: EHelpFileException do
4751 begin
4752 DoErrorDlg( ErrorTitle, E.Message );
4753 Query.Destroy;
4754 ClearWaitCursor;
4755 exit;
4756 end;
4757 end;
4758
4759 AllFilesWordSequences.Add( FileWordSequences );
4760
4761 end;
4762
4763 // Sort results across all files by relevance
4764 SearchResults.Sort( TopicRelevanceCompare );
4765
4766 // Load topics into search results list.
4767 SearchResultsListBox.BeginUpdate;
4768 SearchResultsListBox.Clear;
4769
4770 for TopicIndex := 0 to SearchResults.Count - 1 do
4771 begin
4772 Topic := SearchResults[ TopicIndex ];
4773 SearchResultsListBox.Items.AddObject( Topic.Title
4774 + ' ['
4775 + IntToStr( Topic.SearchRelevance )
4776 + ']',
4777 Topic );
4778 end;
4779
4780 EnableControls;
4781 if SearchResultsListBox.Items.Count > 0 then
4782 // there are some search matches, so highlight words
4783 ViewHighlightSearchWordsMI.Checked := true;
4784
4785 SearchResultsListBox.ItemIndex := -1;
4786 SearchResultsListBox.EndUpdate;
4787
4788 Query.Destroy;
4789 SearchResults.Destroy;
4790
4791 if SearchResultsListBox.Items.Count > 0 then
4792 begin
4793 SearchResultsListBox.ItemIndex := 0;
4794 end
4795 else
4796 begin
4797 SearchResultsListBox.Items.Add( NoSearchMatchesMsg
4798 + ': '
4799 + SearchText );
4800 RefreshWindows( Windows ); // update to remove old highlights
4801 end;
4802 SetStatus( SearchFoundMsgA
4803 + IntToStr( SearchResultsListBox.Items.Count )
4804 + SearchFoundMsgB
4805 + StrDoubleQuote( SearchText ) );
4806
4807 ClearWaitCursor;
4808
4809 DisplaySelectedSearchResultTopic;
4810
4811End;
4812
4813Procedure TMainForm.FileSaveAsMIOnClick (Sender: TObject);
4814var
4815 F: File;
4816 EntryText: PChar;
4817 TextLength: longint;
4818 Window: THelpWindow;
4819 Filename: string;
4820Begin
4821 Window := GetActiveWindow;
4822 if Window = nil then
4823 begin
4824 DoErrorDlg( FileSaveTitle,
4825 FileSaveSelectWindowError );
4826 exit;
4827 end;
4828
4829 if DoSaveFileDialog( FileSaveTitle,
4830 AllFilesDesc + '|*',
4831 DefaultSaveTopicFilename,
4832 Settings.LastSaveDirectory,
4833 Filename ) then
4834 begin
4835 if FileExists( Filename ) then
4836 if not DoConfirmDlg( FileSaveTitle,
4837 ReplaceFilePromptA
4838 + Filename
4839 + ReplaceFilePromptB ) then
4840 exit;
4841 System.Assign( F, Filename );
4842
4843 try
4844 Rewrite( F );
4845 except
4846 on E: Exception do
4847 begin
4848 DoErrorDlg( FileSaveTitle,
4849 UnableToSaveError
4850 + Filename
4851 + ': '
4852 + E.Message );
4853 exit;
4854 end;
4855 end;
4856
4857 // find out length of (plain) text
4858 TextLength := Window.View.CopyTextToBuffer( nil, -1 );
4859
4860 // allocate space
4861 EntryText:= StrAlloc( TextLength );
4862
4863 // get the plain text
4864 Window.View.CopyTextToBuffer( EntryText, TextLength );
4865
4866 // save to file
4867 System.BlockWrite( F, EntryText^, TextLength );
4868
4869 // free space
4870 StrDispose( EntryText );
4871
4872 System.Close( F );
4873 end;
4874End;
4875
4876Procedure TMainForm.OptionsMIOnClick (Sender: TObject);
4877begin
4878 DoOptions;
4879end;
4880
4881Procedure TMainForm.DoOptions;
4882Begin
4883 EnsureOptionsFormLoaded;
4884
4885 GetColors; // in case changed by drag drop
4886
4887 if OptionsForm.ShowModal = mrOK then
4888 begin
4889 ApplySettings;
4890 SetLayout;
4891 RefreshFontSubstitutions;
4892 RefreshWindows( Windows );
4893 end;
4894End;
4895
4896Procedure TMainForm.ShowUsage;
4897begin
4898 DoMessageDlg( UsageTitle,
4899 UsageText1 + EndLine
4900 + UsageText2 + EndLine
4901 + UsageText3 + EndLine
4902 + UsageText4 + EndLine
4903 + UsageText5 + EndLine
4904 + UsageText6 + EndLine
4905 + UsageText7 + EndLine
4906 + UsageText8 );
4907end;
4908
4909Procedure TMainForm.TabSetOnChange (Sender: TObject; NewTab: LongInt;
4910 Var AllowChange: Boolean);
4911Begin
4912 NoteBook.PageIndex := NewTab;
4913End;
4914
4915Procedure TMainForm.NotebookOnSetupShow (Sender: TObject);
4916Begin
4917 ContentsOutline.xStretch := xsFrame;
4918 ContentsOutline.yStretch := ysFrame;
4919
4920 IndexSearchEdit.yAlign := yaTop;
4921 IndexSearchEdit.xStretch := xsFrame;
4922 IndexListBox.yStretch := ysFrame;
4923 IndexListBox.xStretch := xsFrame;
4924
4925 SearchTextEdit.yAlign := yaTop;
4926 SearchTextEdit.xStretch := xsFrame;
4927 SearchButton.yAlign := yaTop;
4928 SearchButton.xAlign := xaRight;
4929 SearchResultsListBox.xStretch := xsFrame;
4930 SearchResultsListBox.yStretch := ysFrame;
4931
4932 NotesListBox.xStretch := xsFrame;
4933 NotesListBox.yStretch := ysFrame;
4934End;
4935
4936Procedure TMainForm.EnableControls;
4937var
4938 BackEnabled: boolean;
4939 ForwardEnabled: boolean;
4940 FileOpen: boolean;
4941 WindowOpen: boolean;
4942 AtTop: boolean;
4943 AtBottom: boolean;
4944begin
4945 ViewContentsMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piContents );
4946 ViewIndexMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piIndex );
4947 ViewSearchMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piSearch );
4948 ViewNotesMI.Checked := ShowLeftPanel and ( Notebook.PageIndex = piNotes );
4949
4950 BackEnabled := CurrentHistoryIndex > 0;
4951 ForwardEnabled := CurrentHistoryIndex < PageHistory.Count - 1;
4952
4953 FileOpen := CurrentOpenFiles.Count > 0;
4954 WindowOpen := Windows.Count > 0;
4955
4956 ViewContentsMI.Enabled := FileOpen;
4957 ViewIndexMI.Enabled := FileOpen;
4958 ViewSearchMI.Enabled := FileOpen;
4959 ViewNotesMI.Enabled := FileOpen;
4960
4961 ShowLeftPanelMI.Enabled := FileOpen;
4962
4963 Coolbar.Sections[ ciBack ].Disabled := not BackEnabled;
4964 NavigateBackMI.Enabled := BackEnabled;
4965 Coolbar.Sections[ ciForward ].Disabled := not ForwardEnabled;
4966 NavigateForwardMI.Enabled := ForwardEnabled;
4967
4968 FileSaveAsMI.Enabled := FileOpen;
4969
4970 Coolbar.Sections[ ciPrint ].Disabled := not FileOpen;
4971 PrintMI.Enabled := FileOpen;
4972 FileInformationMI.Enabled := FileOpen;
4973
4974 Coolbar.Sections[ ciAddBookmark ].Disabled := not FileOpen;
4975 AddBookmarkMI.Enabled := FileOpen;
4976 EditBookmarksMI.Enabled := FileOpen;
4977 Coolbar.Sections[ ciAddNote ].Disabled := not FileOpen;
4978 AddNoteMI.Enabled := FileOpen;
4979
4980 if ContentsOutline.SelectedNode <> nil then
4981 begin
4982 AtTop := ContentsOutline.NextNodeUp( ContentsOutline.SelectedNode, false ) = nil;
4983 AtBottom := ContentsOutline.NextNodeDown( ContentsOutline.SelectedNode, false ) = nil;
4984 end;
4985
4986 NavigateNextMI.Enabled := FileOpen
4987 and ( ContentsOutline.SelectedNode <> nil )
4988 and ( not AtBottom );
4989 Coolbar.Sections[ ciNext ].Disabled := not NavigateNextMI.Enabled;
4990 NavigatePreviousMI.Enabled := FileOpen
4991 and ( ContentsOutline.SelectedNode <> nil )
4992 and ( not AtTop );
4993 Coolbar.Sections[ ciPrevious ].Disabled := not NavigatePreviousMI.Enabled;
4994
4995 FileCloseMI.Enabled := FileOpen;
4996
4997 FindMI.Enabled := WindowOpen;
4998 FindNextMI.Enabled := WindowOpen;
4999 CopyMI.Enabled := WindowOpen;
5000 SelectAllMI.Enabled := WindowOpen;
5001
5002 ViewExpandAllMI.Enabled := ContentsOutline.ChildCount > 0;
5003 ViewCollapseAllMI.Enabled := ContentsOutline.ChildCount > 0;
5004
5005 DebugTopicByResourceIDMI.Enabled := FileOpen;
5006 TopicByNameMI.Enabled := FileOpen;
5007
5008 ViewHighlightSearchWordsMI.Enabled := SearchResultsListBox.Items.Count > 0;
5009 if not ViewHighlightSearchWordsMI.Enabled then
5010 ViewHighlightSearchWordsMI.Checked := false;
5011
5012 ViewRefreshMI.Enabled := WindowOpen;
5013
5014 EnableSearchButton;
5015 EnableNotesControls;
5016
5017 VSplitBar.Visible := FileOpen;
5018 if not FileOpen then
5019 begin
5020 SetShowLeftPanel( false );
5021 end;
5022
5023
5024end;
5025
5026Procedure TMainForm.NavigateBackMIOnClick (Sender: TObject);
5027begin
5028 NavigateBack;
5029end;
5030
5031Procedure TMainForm.SaveNavigatePoint;
5032var
5033 NavPoint: TNavigatePoint;
5034begin
5035 // delete rest of history.
5036 while CurrentHistoryIndex < PageHistory.Count - 1 do
5037 begin
5038 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex + 1 ] as TNavigatePoint;
5039 NavPoint.Destroy;
5040 PageHistory.Delete( CurrentHistoryIndex + 1 );
5041 end;
5042
5043 NavPoint:= TNavigatePoint.Create;
5044 SaveWindows( Windows, NavPoint.Windows, nil );
5045
5046 if ContentsOutline.SelectedNode <> nil then
5047 NavPoint.ContentsTopic:= ContentsOutline.SelectedNode.Data as TTopic
5048 else
5049 NavPoint.ContentsTopic:= nil;
5050
5051 if CurrentTopic <> nil then
5052 PageHistory.AddObject( CurrentTopic.Title, NavPoint )
5053 else
5054 PageHistory.AddObject( '', NavPoint );
5055
5056 inc( CurrentHistoryIndex );
5057
5058 CreateNavigateToMenuItems;
5059end;
5060
5061Procedure TMainForm.UpdateCurrentNavigatePoint;
5062var
5063 NavPoint: TNavigatePoint;
5064begin
5065 if CurrentHistoryIndex = -1 then
5066 exit;
5067
5068 NavPoint:= PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5069
5070 DestroyListObjects( NavPoint.Windows );
5071 NavPoint.Windows.Clear;
5072
5073 SaveWindows( Windows, NavPoint.Windows, nil );
5074end;
5075
5076Procedure TMainForm.ClearPageHistory;
5077var
5078 i: longint;
5079 NavPoint: TNavigatePoint;
5080begin
5081 for i := 0 to PageHistory.Count - 1 do
5082 begin
5083 NavPoint := PageHistory.Objects[ i ] as TNavigatePoint;
5084 NavPoint.Destroy;
5085 end;
5086 PageHistory.Clear;
5087 CurrentHistoryIndex := -1;
5088 CreateNavigateToMenuItems;
5089 EnableControls;
5090end;
5091
5092Procedure TMainForm.SaveWindows( SourceList: TList;
5093 DestList: TList;
5094 Parent: TSavedHelpWindow );
5095
5096var
5097 WindowIndex: longint;
5098 Window: THelpWindow;
5099 WindowCopy: TSavedHelpWindow;
5100begin
5101 // limit storage to only what's need since list will be static.
5102 DestList.Capacity := SourceList.Count;
5103 for WindowIndex := 0 to SourceList.Count - 1 do
5104 begin
5105 Window := SourceList[ WindowIndex ];
5106 WindowCopy := TSavedHelpWindow.Create;
5107 WindowCopy.Parent := Parent;
5108 WindowCopy.Rect.Assign( Window.Rect );
5109 WindowCopy.Topic := Window.Topic;
5110 WindowCopy.Group := Window.Group;
5111 WindowCopy.TopCharIndex := Window.View.TopCharIndex;
5112 SaveWindows( Window.ChildWindows, WindowCopy.ChildWindows, WindowCopy );
5113 DestList.Add( WindowCopy );
5114 end;
5115end;
5116
5117Procedure TMainForm.DisplayWindows( WindowList: TList;
5118 Parent: THelpWindow );
5119var
5120 WindowIndex: longint;
5121 WindowCopy: TSavedHelpWindow;
5122 NewWindow: THelpWindow;
5123begin
5124 for WindowIndex := 0 to WindowList.Count - 1 do
5125 begin
5126 WindowCopy := WindowList[ WindowIndex ];
5127 NewWindow := OpenWindow( WindowCopy.Topic,
5128 WindowCopy.Group,
5129 Parent,
5130 WindowCopy.Rect,
5131 false ); // don't follow links
5132 NewWindow.View.TopCharIndex := WindowCopy.TopCharIndex;
5133 DisplayWindows( WindowCopy.ChildWindows, NewWindow );
5134 end;
5135end;
5136
5137Procedure TMainForm.CreateNavigateToMenuItems;
5138var
5139 MenuItem: TMenuItem;
5140 i: integer;
5141begin
5142 // clear existing items
5143 DestroyListObjects( NavigateToMenuItems );
5144 NavigateToMenuItems.Clear;
5145
5146 if CurrentHistoryIndex > 0 then
5147 begin
5148 // We are going to add some items, so
5149 // add a seperator from the rest of the menu first
5150 MenuItem := TMenuItem.Create( self );
5151 MenuItem.Caption:= '-';
5152 NavigateMenu.Add( MenuItem );
5153 NavigateToMenuItems.Add( MenuItem );
5154 end;
5155
5156 i := CurrentHistoryIndex - 1; // don't include the current history item
5157 while ( ( i >= 0 )
5158 and ( i > CurrentHistoryIndex - 10 ) ) do
5159 begin
5160 MenuItem := TMenuItem.Create( self );
5161 MenuItem.Caption := PageHistory[ i ];
5162 MenuItem.Hint := GoBackHint
5163 + StrDoubleQuote( PageHistory[ i ] );
5164 MenuItem.OnClick := OnNavigateToMenuItemClick;
5165 MenuItem.Tag := i;
5166
5167 NavigateMenu.Add( MenuItem );
5168 NavigateToMenuItems.Add( MenuItem );
5169 dec( i );
5170 end;
5171end;
5172
5173Procedure TMainForm.NavigateToPoint( NavPoint: TNavigatePoint );
5174begin
5175 Navigating := true;
5176
5177 // close current windows
5178 CloseWindows;
5179
5180 // Display windows for the navigate point
5181 DisplayWindows( NavPoint.Windows, nil );
5182
5183 // Select the contents topic
5184 ContentsOutline.SetSelectedObject( NavPoint.ContentsTopic );
5185
5186 // Update the navigate menu (since a different set of
5187 // back-points are now available)
5188 CreateNavigateToMenuItems;
5189
5190 // Make the topic windows visible
5191 ShowWindows;
5192
5193 // Update back buttons etc...
5194 EnableControls;
5195
5196 Navigating := false;
5197end;
5198
5199Procedure TMainForm.NavigateToHistoryIndex( Index: longint );
5200var
5201 NavPoint: TNavigatePoint;
5202begin
5203 UpdateCurrentNavigatePoint;
5204 CurrentHistoryIndex := Index;
5205 NavPoint := PageHistory.Objects[ CurrentHistoryIndex ] as TNavigatePoint;
5206 NavigateToPoint( NavPoint );
5207end;
5208
5209Procedure TMainForm.NavigateForward;
5210Begin
5211 if CurrentHistoryIndex < PageHistory.Count - 1 then
5212 begin
5213 NavigateToHistoryIndex( CurrentHistoryIndex + 1 );
5214 end;
5215End;
5216
5217Procedure TMainForm.NavigateBack;
5218Begin
5219 if CurrentHistoryIndex > 0 then
5220 begin
5221 NavigateToHistoryIndex( CurrentHistoryIndex - 1 );
5222 end;
5223End;
5224
5225Procedure TMainForm.NavigatePreviousInContents;
5226begin
5227 ContentsOutline.GotoNextNodeUp;
5228 DisplaySelectedContentsTopic;
5229end;
5230
5231Procedure TMainForm.NavigateNextInContents;
5232begin
5233 ContentsOutline.GotoNextNodeDown;
5234 DisplaySelectedContentsTopic;
5235end;
5236
5237Procedure TMainForm.CorrectNotesPositions( Topic: TTopic;
5238 Text: pchar );
5239var
5240 NoteIndex: longint;
5241 Note: THelpNote;
5242 p: pchar;
5243 NextP: pchar;
5244 Element: TTextElement;
5245 TextIndex: longint;
5246begin
5247 NoteIndex := 0;
5248 for NoteIndex := 0 to Notes.Count - 1 do
5249 begin
5250 Note := Notes[ NoteIndex ];
5251 if Note.Topic = Topic then
5252 begin
5253 // this note belongs the the specified topic.
5254 p := Text;
5255
5256 while true do
5257 begin
5258 Element := ExtractNextTextElement( p, NextP );
5259 if Element.ElementType = teTextEnd then
5260 break;
5261 TextIndex := PCharDiff( p, Text );
5262 if TextIndex >= Note.InsertPoint then
5263 begin
5264 // found a safe point to insert
5265 if TextIndex <> Note.InsertPoint then
5266 begin
5267 // correct it.
5268 Note.InsertPoint := TextIndex;
5269 end;
5270 break;
5271 end;
5272
5273 p := NextP;
5274 end;
5275 end;
5276 end;
5277end;
5278
5279Procedure TMainForm.InsertNotesIntoTopicText( Topic: TTopic;
5280 Text: TAString );
5281var
5282 NoteIndex: longint;
5283 Note: THelpNote;
5284 ActualInsertPoint: longword;
5285begin
5286 CorrectNotesPositions( Topic, Text.AsPChar );
5287
5288 for NoteIndex := 0 to Notes.Count - 1 do
5289 begin
5290 Note := Notes[ NoteIndex ];
5291 if Note.Topic = Topic then
5292 begin
5293 // Adjust insert point for any notes we have already inserted.
5294 ActualInsertPoint := FindActualNoteCharIndex( Note.InsertPoint,
5295 NoteIndex,
5296 Topic );
5297 RefreshNoteInsertInfo( NoteIndex );
5298 Text.Insert( ActualInsertPoint, Note.InsertText );
5299 end;
5300 end;
5301end;
5302
5303Procedure TMainForm.NavigatePreviousMIOnClick (Sender: TObject);
5304Begin
5305 NavigatePreviousInContents;
5306End;
5307
5308Procedure TMainForm.NavigateNextMIOnClick (Sender: TObject);
5309Begin
5310 NavigateNextInContents;
5311End;
5312
5313Function TMainForm.GetActiveWindow: THelpWindow;
5314var
5315 View: TRichTextView;
5316 FirstWindow: THelpWindow;
5317begin
5318 Result := nil;
5319 if Screen.ActiveControl is TRichTextView then
5320 begin
5321 View := Screen.ActiveControl as TRichTextView;
5322 Result := FindWindowFromView( View, Windows );
5323 end
5324 else if Windows.Count = 1 then
5325 begin
5326 FirstWindow := Windows[ 0 ];
5327 if FirstWindow.ChildWindows.Count = 0 then
5328 Result := FirstWindow;
5329 end;
5330end;
5331
5332Procedure TMainForm.CopyMIOnClick (Sender: TObject);
5333var
5334 Window: THelpWindow;
5335begin
5336 if ActiveControl = nil then
5337 exit;
5338
5339 if ActiveControl is TEdit then
5340 begin
5341 // this is for the edit controls in the left panel
5342 TEdit( ActiveControl ).CopyToClipboard;
5343 exit;
5344 end;
5345
5346 // else copy from rtv in active help window
5347
5348 Window := GetActiveWindow;
5349 if Window = nil then
5350 exit;
5351
5352 Window.View.CopySelectionToClipboard;
5353End;
5354
5355Procedure TMainForm.SelectAllMIOnClick (Sender: TObject);
5356var
5357 Window: THelpWindow;
5358begin
5359 Window:= GetActiveWindow;
5360 if Window = nil then
5361 begin
5362 DoErrorDlg( SelectAllTitle,
5363 SelectAllWindowError );
5364 exit;
5365 end;
5366 Window.View.SelectAll;
5367End;
5368
5369Procedure TMainForm.DebugShowCodesMIOnClick (Sender: TObject);
5370Begin
5371 DebugShowCodesMI.Checked:= not DebugShowCodesMI.Checked;
5372 RefreshWindows( Windows );
5373End;
5374
5375Procedure TMainForm.HelpProductInformationMIOnClick (Sender: TObject);
5376Begin
5377 EnsureProductInformationFormLoaded;
5378 ProductInformationForm.ShowModal;
5379End;
5380
5381Procedure TMainForm.OnOverLink ( Sender: TRichTextView; LinkString: String);
5382var
5383 Link: THelpLink;
5384 LinkIndex: longint;
5385 Window: THelpWindow;
5386 LinkedTopic: TTopic;
5387 Filename: string;
5388 SourceFile: THelpFile;
5389 LinkedProgram: string;
5390 URL: string;
5391 LinkDetails: string;
5392Begin
5393 if StrLeft( LinkString, 4 ) = 'note' then
5394 begin
5395 SetStatus( EditNoteMsg )
5396 end
5397 else if StrLeft( LinkString, 7 ) = 'program' then
5398 begin
5399 LinkedProgram := StrRightFrom( LinkString, 9 );
5400 SetStatus( LinkMsg
5401 + LinkedProgram );
5402 end
5403 else if StrLeft( LinkString, 3 ) = 'url' then
5404 begin
5405 URL := StrRightFrom( LinkString, 5 );
5406 SetStatus( LinkMsg
5407 + URL );
5408 end
5409 else if StrLeft( LinkString, 8 ) = 'external' then
5410 begin
5411 LinkDetails := StrRightFrom( LinkString, 10 );
5412 LinkIndex := StrToInt( ExtractNextValue( LinkDetails, ' ' ) );
5413 Window := FindWindowFromView( Sender, Windows );
5414 SourceFile := Window.Topic.HelpFile as THelpFile;
5415 Filename := SourceFile.ReferencedFiles[ LinkIndex ];
5416 SetStatus( LinkMsg
5417 + StrDoubleQuote( Filename ) );
5418 end
5419 else
5420 begin
5421 Window := FindWindowFromView( Sender, Windows );
5422 LinkIndex := StrToInt( LinkString );
5423 Link := Window.Topic.Links[ LinkIndex ];
5424
5425 if Link is TFootnoteHelpLink then
5426 begin
5427 SetStatus( FootnoteMsg );
5428 end
5429 else
5430 begin
5431 LinkedTopic := FindTopicForLink( Link );
5432
5433 if LinkedTopic <> nil then
5434 begin
5435 SetStatus( LinkMsg
5436 + StrDoubleQuote( Trim( LinkedTopic.Title ) ) );
5437 end
5438 else
5439 begin
5440 SetStatus( UnknownLinkMsg );
5441 end;
5442 end;
5443 end;
5444End;
5445
5446Procedure TMainForm.OnNotOverLink ( Sender: TRichTextView; LinkString: String);
5447Begin
5448 SetStatus( '' );
5449end;
5450
5451Procedure TMainForm.OnClickLink ( Sender: TRichTextView; LinkString: String);
5452var
5453 Link: THelpLink;
5454 LinkIndex: longint;
5455 SourceWindow: THelpWindow;
5456 NoteIndex: longint;
5457 Window: THelpWindow;
5458 SourceFile: THelpFile;
5459 ProgramLink: string;
5460 ProgramPath: string;
5461 URL: string;
5462 LinkDetails: string;
5463 ProgramInfo : TSerializableStringList;
5464Begin
5465 if StrLeft( LinkString, 4 ) = 'note' then
5466 begin
5467 NoteIndex := StrToInt( StrRightFrom( LinkString, 5 ) );
5468 NotesListBox.ItemIndex := NoteIndex;
5469 EditNote( NoteIndex );
5470 end
5471 else if StrLeft( LinkString, 7 ) = 'program' then
5472 begin
5473 ProgramInfo := TSerializableStringList.create;
5474 ProgramInfo.readValuesFromSerializedString(StrRightFrom( LinkString, 9 ));
5475 ProgramPath := ProgramInfo.get(0);
5476 ProgramLink := ProgramInfo.get(1);
5477 TSerializableStringList.destroy;
5478 // call LaunchProgram here to inherit the environment
5479 LaunchProgram(ProgramPath, ProgramLink, '');
5480 SetStatus( 'Launched ' + ProgramPath );
5481 end
5482 else if StrLeft( LinkString, 3 ) = 'url' then
5483 begin
5484 URL := StrRightFrom( LinkString, 5 );
5485 LaunchURL( URL );
5486 SetStatus( 'Opened '
5487 + URL );
5488 end
5489 else if StrLeft( LinkString, 8 ) = 'external' then
5490 begin
5491 LinkDetails := StrRightFrom( LinkString, 10 );
5492 LinkIndex := StrToInt( ExtractNextValue( LinkDetails, ' ' ) );
5493 Window := FindWindowFromView( Sender, Windows );
5494 SourceFile := Window.Topic.HelpFile as THelpFile;
5495
5496 g_ExternalLinkFileName := SourceFile.ReferencedFiles[ LinkIndex ];
5497 g_ExternalLinkTopic := LinkDetails;
5498 g_ExternalLinkSourceFilename := SourceFile.Filename;
5499 g_ExternalLinkKeepCurrent := true; // hm... what would be nice?
5500
5501 PostMsg( Self.Handle,
5502 WM_FOLLOWEXTERNALLINK,
5503 0,
5504 0 );
5505 end
5506 else
5507 begin
5508 SourceWindow := FindWindowFromView( Sender, Windows );
5509 LinkIndex := StrToInt( LinkString );
5510 Link := SourceWindow.Topic.Links[ LinkIndex ];
5511
5512 PostMsg( Self.Handle,
5513 WM_FOLLOWLINK,
5514 longint( Link ),
5515 longint( SourceWindow ) );
5516
5517 end;
5518End;
5519
5520Procedure TMainForm.OnWindowAboutToClose( Window: THelpWindow;
5521 var CanClose: boolean );
5522begin
5523 if Navigating then
5524 exit;
5525
5526 UpdateCurrentNavigatePoint; // Save it before close...
5527
5528 CanClose := true;
5529end;
5530
5531Procedure TMainForm.RemoveHelpWindowFromParent( Window: THelpWindow );
5532var
5533 ParentWindow: THelpWindow;
5534 WindowIndex: longint;
5535Begin
5536 if Navigating then
5537 exit;
5538
5539 if Window.ParentHelpWindow = nil then
5540 begin
5541 WindowIndex := Windows.IndexOf( Window );
5542 Windows.Delete( WindowIndex );
5543 end
5544 else
5545 begin
5546 ParentWindow := Window.ParentHelpWindow;
5547 WindowIndex := ParentWindow.ChildWindows.IndexOf( Window );
5548 ParentWindow.ChildWindows.Delete( WindowIndex );
5549 end;
5550end;
5551
5552Procedure TMainForm.OnWindowClose( Window: THelpWindow );
5553Begin
5554 if Navigating then
5555 exit;
5556
5557 RemoveHelpWindowFromParent( Window );
5558
5559 SaveNavigatePoint;
5560 EnableControls;
5561End;
5562
5563Procedure TMainForm.BackButtonOnClick (Sender: TObject);
5564Begin
5565 NavigateBack;
5566End;
5567
5568Procedure TMainForm.RTViewOnSetupShow (Sender: TObject);
5569Begin
5570End;
5571
5572Procedure TMainForm.ExitMIOnClick (Sender: TObject);
5573Begin
5574 Close;
5575End;
5576
5577Procedure TMainForm.CreateMRUMenuItems;
5578var
5579 MenuItem: TMenuItem;
5580 i: integer;
5581 FileName: string;
5582 FileNameIndex: longint;
5583 MRUText: string;
5584 MRUItem: TMRUItem;
5585begin
5586 DestroyListObjects( MRUMenuItems );
5587 MRUMenuItems.Clear;
5588
5589 // if there are Most Recently Used files
5590 if Settings.MRUList.Count > 0 then
5591 begin
5592 // create a seperator after Exit
5593 MenuItem:= TMenuItem.Create( self );
5594 MenuItem.Name := 'MRUSeparatorMI';
5595 MenuItem.Caption:= '-';
5596 FileMenu.Add( MenuItem );
5597 MRUMenuItems.Add( MenuItem );
5598 end;
5599
5600 // Add items for the MRU files
5601 for i:= 0 to Settings.MRUList.Count -1 do
5602 begin
5603 MRUItem := Settings.MRUList[ i ];
5604
5605 MenuItem := TMenuItem.Create( self );
5606
5607 MenuItem.Name := 'MRUItem' + IntToStr( i ) + 'MI';
5608 MRUText := MRUItem.Title;
5609 if Trim( MRUText ) = '' then
5610 begin
5611 // Take the filenames, less path, as caption...
5612 MRUText := '';
5613 for FileNameIndex := 0 to MRUItem.Filenames.Count - 1 do
5614 begin
5615 FileName := MRUItem.Filenames[ FileNameIndex ];
5616 FileName := ExtractFileName( FileName );
5617 FileName := ChangeFileExt( FileName, '' );// remove extension
5618 AddToListString( MRUText,
5619 FileName,
5620 '+' );
5621
5622 // stop after 50 chars
5623 if Length( MRUText ) > 50 then
5624 begin
5625 MRUText := MRUText + '+ ...';
5626 break;
5627 end;
5628 end;
5629 end;
5630
5631 MenuItem.Caption:= '~'
5632 + IntToStr( i + 1 )
5633 + '. '
5634 + MRUText;
5635 if MRUItem.Filenames.Count = 1 then
5636 MenuItem.Hint := MRUItem.Filenames[ 0 ]
5637 else
5638 MenuItem.Hint := MRUItem.Title
5639 + ' ('
5640 + IntToStr( MRUItem.Filenames.Count )
5641 + ' '
5642 + MRUMultipleFilesHint
5643 + ')';
5644
5645 MenuItem.OnClick:= OnMRUMenuItemClick;
5646 MenuItem.Tag:= i;
5647 FileMenu.Add( MenuItem );
5648 MRUMenuItems.Add( MenuItem );
5649 end;
5650end;
5651
5652procedure TMainForm.OnMRUMenuItemClick( Sender: TObject );
5653var
5654 Tag: longint;
5655 MenuItem: TMenuItem;
5656 MRUItem: TMRUItem;
5657begin
5658 MenuItem:= Sender as TMenuItem;
5659 Tag:= MenuItem.Tag;
5660 MRUItem := Settings.MRUList[ Tag ];
5661 if OpenFiles( MRUItem.FileNames, '', true ) then
5662 begin
5663 ClearHelpManager;
5664 end;
5665end;
5666
5667Procedure TMainForm.OnNavigateToMenuItemClick( Sender: TObject );
5668var
5669 MenuItem: TMenuItem;
5670 Tag: longint;
5671begin
5672 MenuItem:= Sender as TMenuItem;
5673 Tag:= MenuItem.Tag;
5674 NavigateToHistoryIndex( Tag );
5675end;
5676
5677Procedure TMainForm.AddChildNodes( HelpFile: THelpFile;
5678 ParentNode: TNode;
5679 Level: longint;
5680 Var TopicIndex: longint );
5681var
5682 Topic: TTopic;
5683 Node: TNode;
5684begin
5685 assert( ParentNode <> nil );
5686 Node := nil;
5687 while TopicIndex < HelpFile.TopicCount do
5688 begin
5689 Topic:= HelpFile.Topics[ TopicIndex ];
5690
5691 if Topic.ShowInContents then
5692 begin
5693 if Topic.ContentsLevel < Level then
5694 break;
5695
5696 if Topic.ContentsLevel = Level then
5697 begin
5698 Node:= ParentNode.AddChild( Topic.Title,
5699 Topic );
5700 inc( TopicIndex );
5701 end
5702 else
5703 begin
5704 assert( Node <> nil );
5705 AddChildNodes( HelpFile,
5706 Node,
5707 Topic.ContentsLevel,
5708 TopicIndex );
5709 Node := nil;
5710 end
5711 end
5712 else
5713 begin
5714 inc( TopicIndex );
5715 end;
5716 end;
5717
5718end;
5719
5720Procedure TMainForm.LoadContents( Files: TList;
5721 Var FirstNode: TNode );
5722var
5723 TopicIndex: longint;
5724 Topic: TTopic;
5725 Node: TNode;
5726 FileIndex: longint;
5727 HelpFile: THelpFile;
5728begin
5729 ContentsOutline.BeginUpdate;
5730 LogEvent(LogStartup, 'Load contents outline');
5731
5732 // we don't clear it first, to allow adding additional files
5733 // into the contents tree
5734
5735 LogEvent(LogStartup, 'Loop files');
5736
5737 FirstNode := nil;
5738
5739 Node := nil;
5740
5741 for FileIndex:= 0 to Files.Count - 1 do
5742 begin
5743 HelpFile := Files[ FileIndex ];
5744 LogEvent(LogStartup, 'File ' + IntToStr( FileIndex ) );
5745 TopicIndex := 0;
5746 while TopicIndex < HelpFile.TopicCount do
5747 begin
5748 Topic := HelpFile.Topics[ TopicIndex ];
5749 assert( Topic.ContentsLevel >= 0,
5750 'Topic contents level is ' + IntToStr( Topic.ContentsLevel ) );
5751 if Topic.ShowInContents then
5752 begin
5753 if Topic.ContentsLevel = 1 then
5754 begin
5755 Node := ContentsOutline.AddChild( Topic.Title,
5756 Topic );
5757 if FirstNode = nil then
5758 FirstNode := node;
5759
5760 inc( TopicIndex );
5761 end
5762 else
5763 begin
5764 // subnodes
5765 assert( Node <> nil, 'No level 1 topic for subnodes!' );
5766 AddChildNodes( HelpFile,
5767 Node,
5768 Topic.ContentsLevel,
5769 TopicIndex );
5770 Node := nil;
5771 end;
5772 end
5773 else
5774 begin
5775 inc( TopicIndex );
5776 end;
5777 end;
5778 end;
5779 LogEvent(LogStartup, ' EndUpdate' );
5780 ContentsOutline.EndUpdate;
5781
5782 if Settings.OpenWithExpandedContents then
5783 begin
5784 LogEvent(LogStartup, ' Expand all contents' );
5785 ContentsOutline.ExpandAll
5786 end
5787 else if ContentsOutline.ChildCount = 1 then
5788 begin
5789 LogEvent(LogStartup, ' Expand first node' );
5790 // Contents has only one top level node... expand it
5791 FirstNode.Expand;
5792 end;
5793
5794 ContentsLoaded := true;
5795 LogEvent(LogStartup, ' Contents loaded' );
5796
5797end;
5798
5799Procedure TMainForm.SaveNotesForFile( HelpFile: THelpFile );
5800var
5801 NotesFileName: string;
5802 TopicIndex: longword;
5803 Note: THelpNote;
5804 NoteIndex: longint;
5805
5806 NotesFile: HFile;
5807 OpenAction: ULong;
5808 rc: APIRET;
5809 CName: Cstring;
5810 FileNoteCount: integer;
5811
5812begin
5813 LogEvent(LogStartup, 'Save notes for ' + HelpFile.Filename );
5814
5815 if not HelpFile.NotesLoaded then
5816 // we never loaded the notes/displayed a topic from this file
5817 // so don't do anything.
5818 exit;
5819
5820 LogEvent(LogStartup, 'Really saving' );
5821
5822 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5823
5824 FileNoteCount := 0;
5825 for NoteIndex := 0 to Notes.Count - 1 do
5826 begin
5827 Note := Notes[ NoteIndex ];
5828
5829 if Note.Topic.HelpFile = HelpFile then
5830 inc( FileNoteCount );
5831 end;
5832
5833 if FileNoteCount = 0 then
5834 begin
5835 // no notes. delete notes file if it already exists.
5836 if FileExists( NotesFileName ) then
5837 DeleteFile( NotesFileName );
5838 exit;
5839 end;
5840
5841 CName:= NotesFileName;
5842 rc:= DosOpen( CName,
5843 NotesFile,
5844 OpenAction,
5845 0, // file size
5846 0, // attrs
5847 OPEN_ACTION_CREATE_IF_NEW + OPEN_ACTION_REPLACE_IF_EXISTS,
5848 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_WRITEONLY,
5849 nil ); // no eas
5850 if rc <> 0 then
5851 begin
5852 DoErrorDlg( SaveNotesTitle,
5853 SaveNotesError
5854 + EndLine
5855 + NotesFileName
5856 + EndLine
5857 + SysErrorMessage( rc ) );
5858 exit;
5859 end;
5860
5861 for NoteIndex:= 0 to Notes.Count - 1 do
5862 begin
5863 Note:= Notes[ NoteIndex ];
5864
5865 if Note.Topic.HelpFile <> HelpFile then
5866 continue;
5867
5868 TopicIndex:= HelpFile.IndexOfTopic( Note.Topic );
5869
5870 MyWriteLn( NotesFile,
5871 IntToStr( TopicIndex ));
5872 MyWriteLn( NotesFile,
5873 IntToStr( Note.InsertPoint ) );
5874
5875 MyWrite( NotesFile,
5876 Note.Text.AsPChar,
5877 Note.Text.Length );
5878
5879 MyWriteLn( NotesFile,
5880 '' );
5881 MyWriteLn( NotesFile,
5882 '#ENDNOTE#' );
5883
5884 end;
5885
5886 DosClose( NotesFile );
5887end;
5888
5889Procedure TMainForm.LoadNotes( HelpFile: THelpFile );
5890var
5891 NotesFileName: string;
5892 TopicIndex: longint;
5893 InsertPoint: longint;
5894 Note: THelpNote;
5895
5896 NotesFile: HFile;
5897 OpenAction: ULong;
5898 rc: APIRET;
5899 CName: Cstring;
5900
5901 Paragraph: TAString;
5902 NotEOF: boolean;
5903 NoteText: TAString;
5904
5905begin
5906 LogEvent(LogStartup, 'Load notes for ' + HelpFile.Filename );
5907
5908 if HelpFile.NotesLoaded then
5909 exit;
5910
5911 HelpFile.NotesLoaded := true;
5912 NotesFileName := ChangeFileExt( HelpFile.FileName, '.nte' );
5913
5914 if not FileExists( NotesFileName ) then
5915 // no notes
5916 exit;
5917
5918 CName := NotesFileName;
5919 rc := DosOpen( CName,
5920 NotesFile,
5921 OpenAction,
5922 0, // file size - irrelevant, not creating,
5923 0, // attrs - ''
5924 OPEN_ACTION_OPEN_IF_EXISTS,
5925 OPEN_SHARE_DENYREADWRITE + OPEN_ACCESS_READONLY,
5926 nil ); // no eas
5927 if rc <> 0 then
5928 begin
5929 DoErrorDlg( LoadNotesTitle,
5930 LoadNotesError
5931 + EndLine
5932 + NotesFileName
5933 + EndLine
5934 + SysErrorMessage( rc ) );
5935 exit;
5936 end;
5937
5938 Paragraph := TAString.Create;
5939 NoteText := TAString.Create;
5940
5941 NotEOF := true;
5942
5943 while NotEOF do
5944 begin
5945 // Read contents index
5946 NotEOF := Paragraph.ReadParagraph( NotesFile );
5947 if not NotEOF then
5948 continue;
5949 try
5950 TopicIndex := StrToInt( Paragraph.AsString );
5951 except
5952 TopicIndex := -1;
5953 end;
5954
5955 // Read insert point
5956 NotEOF := Paragraph.ReadParagraph( NotesFile );
5957 if not NotEOF then
5958 continue;
5959 try
5960 InsertPoint := StrToInt( Paragraph.AsString );
5961 except
5962 InsertPoint := -1;
5963 end;
5964
5965 NoteText.Clear;
5966
5967 while NotEOF do
5968 begin
5969 NotEOF := Paragraph.ReadParagraph( NotesFile );
5970 if Paragraph.SameAs( '#ENDNOTE#' ) then
5971 begin
5972 // found end of note
5973 if ( TopicIndex >= 0 )
5974 and ( InsertPoint >= 0 ) then
5975 begin
5976 Note := THelpNote.Create;
5977 Note.Topic := HelpFile.Topics[ TopicIndex ];
5978 Note.InsertPoint := InsertPoint;
5979
5980 // Remove the last end line
5981 Note.Text.Assign( NoteText );
5982 if Note.Text.Length > 2 then
5983 Note.Text.Delete( Note.Text.Length - 2, 2 );
5984
5985 Notes.Add( Note );
5986 end;
5987 break;
5988 end;
5989 NoteText.Add( Paragraph );
5990 NoteText.AddString( #13 + #10 );
5991 end;
5992
5993 end;
5994 DosClose( NotesFile );
5995
5996 Paragraph.Destroy;
5997 NoteText.Destroy;
5998
5999end;
6000
6001Procedure TMainForm.UpdateNotesDisplay;
6002var
6003 NoteIndex: longint;
6004 Note: THelpNote;
6005 NoteTitle: string;
6006begin
6007 NotesListBox.Clear;
6008 for NoteIndex := 0 to Notes.Count - 1 do
6009 begin
6010 Note := Notes[ NoteIndex ];
6011
6012 if Note.Topic > nil then
6013 NoteTitle := Note.Topic.Title
6014 else
6015 NoteTitle := StrLeft( Note.Text.AsString, 100 );
6016 NotesListBox.Items.AddObject( NoteTitle,
6017 Note );
6018 end;
6019 EnableNotesControls;
6020end;
6021
6022Procedure TMainForm.EnableNotesControls;
6023var
6024 NoteSelected: boolean;
6025begin
6026 NoteSelected:= NotesListBox.ItemIndex <> -1;
6027 EditNoteButton.Enabled:= NoteSelected;
6028 GotoNoteButton.Enabled:= NoteSelected;
6029 DeleteNoteButton.Enabled:= NoteSelected;
6030 AddNoteButton.Enabled := CurrentOpenFiles.Count > 0;
6031end;
6032
6033Function TMainForm.OKToCloseFile: boolean;
6034begin
6035 Result := true;
6036
6037 if PrintThread = nil then
6038 // haven't used print thread yet
6039 exit;
6040
6041 if not PrintThread.IsRunning then
6042 // not currently running
6043 exit;
6044
6045 Result := DoConfirmDlg( CheckStopPrintTitle,
6046 CheckStopPrintMsg );
6047
6048end;
6049
6050Procedure TMainForm.StopPrinting;
6051begin
6052 if PrintThread <> nil then
6053 begin
6054 if PrintThread.IsRunning then
6055 begin
6056 SetStatus( StoppingPrintMsg );
6057 PrintThread.ForceStop( 5 ); // wait up to 5 seconds then terminate
6058 SetStatus( PrintStoppedMsg );
6059 ResetProgress;
6060 end;
6061 end;
6062end;
6063
6064Procedure TMainForm.CloseFile;
6065var
6066 FileIndex: longint;
6067 HelpFile: THelpFile;
6068 M1: longint;
6069begin
6070 StopPrinting;
6071
6072 LogEvent(LogShutdown, 'Set Caption' );
6073 MainTitle := '';
6074 SetMainCaption;
6075
6076 LogEvent(LogShutdown, 'Close Windows' );
6077 CloseWindows;
6078
6079 LogEvent(LogShutdown, 'Set selected node to nil' );
6080 ContentsOutline.SelectedNode:= Nil;
6081
6082 M1:= MemAvail;
6083
6084 LogEvent(LogShutdown, 'Clear contents outline' );
6085 ContentsOutline.Clear;
6086
6087 LogEvent(LogShutdown, 'Free contents: ' + IntToStr( MemAvail - M1 ) );
6088 M1:= MemAvail;
6089
6090 DisplayedIndex.Clear;
6091 IndexListBox.Clear;
6092 LogEvent(LogShutdown, 'Clear index ' + IntToStr( MemAvail - M1 ) );
6093 M1:= MemAvail;
6094
6095 NotesListBox.Clear;
6096 SearchResultsListBox.Clear;
6097
6098 LogEvent(LogShutdown, 'Notes, search etc ' + IntToStr( MemAvail - M1 ) );
6099 M1:= MemAvail;
6100
6101 // First save notes and bookmarks.
6102 // It's important we do this first
6103 // since we scan all notes each time to find the ones
6104 // belonging to this file.
6105 SaveBookmarks;
6106
6107 SaveNotes;
6108
6109 ClearAllWordSequences;
6110
6111 LogEvent(LogShutdown, 'Destroy helpfile objects' );
6112
6113 // Now destroy help files
6114 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6115 begin
6116 HelpFile := CurrentOpenFiles[ FileIndex ];
6117 GlobalFilelist.RemoveFile( Frame.Handle,
6118 HelpFile.Filename );
6119 HelpFile.Free;
6120 end;
6121
6122 CurrentOpenFiles.Clear;
6123
6124 LogEvent(LogShutdown, 'Destroy helpfiles ' + IntToStr( MemAvail - M1 ) );
6125 M1 := MemAvail;
6126
6127 LogEvent(LogShutdown, 'Clear notes' );
6128 ClearNotes;
6129
6130 LogEvent(LogShutdown, 'Clear bookmarks' );
6131 ClearBookmarks;
6132
6133 ClearPageHistory;
6134
6135 LogEvent(LogShutdown, 'Enable controls' );
6136 EnableControls;
6137
6138 LogEvent(LogShutdown, 'CloseFile done' );
6139
6140end;
6141
6142Function TMainForm.FindOpenHelpFile( FileName: string ): THelpFile;
6143var
6144 FileIndex: longint;
6145begin
6146 for FileIndex:= 0 to CurrentOpenFiles.Count - 1 do
6147 begin
6148 Result:= CurrentOpenFiles[ FileIndex ];
6149 if StringsSame( Result.Filename, FileName ) then
6150 // found
6151 exit;
6152 end;
6153 Result:= nil;
6154end;
6155
6156// This rather horrendous looking bit of code simply:
6157
6158// Gets the contents from each file
6159// Sorts it alphabetically.
6160// Merges all the sorted contents and indexes together,
6161// alphabetically.
6162type
6163 TListType = ( ltContents, ltIndex );
6164
6165procedure TMainForm.LoadIndex;
6166var
6167 HelpFile: THelpFile;
6168 TextCompareResult: integer;
6169
6170 FileIndex: longint;
6171
6172 Contents: TList;
6173 ContentsLists: TList; // of tlist
6174 IndexLists: TList; // of tstringlist
6175 ContentsNextIndex: array[ 0..255 ] of longint;
6176 IndexNextIndex: array[ 0..255 ] of longint;
6177 Topic: TTopic;
6178
6179 ListIndex: longint;
6180
6181 pListEntry: pstring;
6182 pLowestEntry: pstring;
6183 pLastEntry: pstring;
6184
6185 LowestEntryListIndex: longint;
6186 LowestEntryListType: TListType;
6187 LowestEntryTopic: TTopic;
6188
6189 Index: TStringList;
6190
6191 i : longint;
6192begin
6193 LogEvent(LogStartup, 'Create index' );
6194
6195 SetWaitCursor;
6196
6197 LogEvent(LogStartup, ' Get/sort lists' );
6198
6199 ProgressBar.Position := 70;
6200 SetStatus( 'Building index... ' );
6201
6202 ContentsLists := TList.Create;
6203 IndexLists := TList.Create;
6204
6205 // collect the contents and index lists from the files
6206 for FileIndex := 0 to CurrentOpenFiles.Count - 1 do
6207 begin
6208 HelpFile := CurrentOpenFiles[ FileIndex ];
6209 ProgressBar.Position := 70 + 10 * FileIndex div CurrentOpenFiles.Count;
6210
6211 if Settings.IndexStyle in [ isAlphabetical, isFull ] then
6212 begin
6213 Contents := TList.Create;
6214 Contents.Capacity := HelpFile.TopicCount;
6215
6216 // copy [contents] topic list
6217 for i := 0 to HelpFile.TopicCount - 1 do
6218 begin
6219 Topic := HelpFile.Topics[ i ];
6220 if Topic.ShowInContents then
6221 Contents.Add( Topic );
6222 end;
6223
6224 // sort by title
6225 Contents.Sort( TopicTitleCompare );
6226
6227 ContentsLists.Add( Contents );
6228
6229 // initialise list index
6230 ContentsNextIndex[ ContentsLists.Count - 1 ] := 0;
6231 end;
6232
6233 if Settings.IndexStyle in [ isFileOnly, isFull ] then
6234 begin
6235 IndexLists.Add( HelpFile.Index );
6236 IndexNextIndex[ IndexLists.Count - 1 ] := 0;
6237 end;
6238 end;
6239
6240 // Unlike contents, we do clear the index
6241 // (even if we are adding more files) because we need
6242 // to re-merge the whole thing
6243 DisplayedIndex.Clear;
6244 ProgressBar.Position := 80;
6245
6246 LogEvent(LogStartup, ' Merge lists' );
6247
6248 pLastEntry := NullStr;
6249 while true do
6250 begin
6251 pLowestEntry := NullStr;
6252 LowestEntryListIndex := -1;
6253
6254 // Find alphabetically lowest (remaining) topic
6255
6256 // first, look in contents lists
6257 for ListIndex := 0 to ContentsLists.Count - 1 do
6258 begin
6259 Contents := ContentsLists[ ListIndex ];
6260 if ContentsNextIndex[ ListIndex ] < Contents.Count then
6261 begin
6262 // list is not yet finished, get next entry
6263 Topic := Contents[ ContentsNextIndex[ ListIndex ] ];
6264 pListEntry := Topic.TitlePtr;
6265
6266 if pLowestEntry^ <> '' then
6267 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6268 else
6269 TextCompareResult := -1;
6270
6271 if TextCompareResult < 0 then
6272 begin
6273 // this index entry comes before the lowest one so far
6274 pLowestEntry := pListEntry;
6275 LowestEntryListIndex := ListIndex;
6276 LowestEntryListType := ltContents;
6277 LowestEntryTopic := Topic;
6278 end;
6279 end;
6280 end;
6281
6282 // look in indices
6283 for ListIndex := 0 to IndexLists.Count - 1 do
6284 begin
6285 Index := IndexLists[ ListIndex ];
6286 if IndexNextIndex[ ListIndex ] < Index.Count then
6287 begin
6288 // list is not yet finished, get next entry
6289 pListEntry := Index.ValuePtrs[ IndexNextIndex[ ListIndex ] ];
6290
6291 if pLowestEntry^ <> '' then
6292 TextCompareResult := CompareText( pListEntry^, pLowestEntry^ )
6293 else
6294 TextCompareResult := -1;
6295
6296 if TextCompareResult < 0 then
6297 begin
6298 // this index entry comes before the lowest one so far
6299 pLowestEntry := pListEntry;
6300 LowestEntryListIndex := ListIndex;
6301 LowestEntryListType := ltIndex;
6302 LowestEntryTopic := TTopic( Index.Objects[ IndexNextIndex[ ListIndex ] ] );
6303 end;
6304 end;
6305 end;
6306
6307 if LowestEntryListIndex = -1 then
6308 // we're out
6309 break;
6310
6311 if ( pLowestEntry^ ) <> ( pLastEntry^ ) then
6312 // add, if different from last
6313 DisplayedIndex.AddObject( pLowestEntry^,
6314 LowestEntryTopic );
6315 pLastEntry := pLowestEntry;
6316
6317 if LowestEntryListType = ltContents then
6318 begin
6319 inc( ContentsNextIndex[ LowestEntryListIndex ] );
6320 end
6321 else
6322 begin
6323 // found in one of indices.
6324 // Check for subsequent indented strings
6325 Index := IndexLists[ LowestEntryListIndex ];
6326
6327 i := IndexNextIndex[ LowestEntryListIndex ] + 1;
6328 while i < Index.Count do
6329 begin
6330 pListEntry := Index.ValuePtrs[ i ];
6331 if pListEntry^ = '' then
6332 break;
6333
6334 if pListEntry^[ 1 ] <> ' ' then
6335 // not indented, stop looking
6336 break;
6337
6338 // found one,
6339 Topic := Index.Objects[ i ] as TTopic;
6340 DisplayedIndex.AddObject( pListEntry^,
6341 Topic );
6342 inc( i );
6343 end;
6344 IndexNextIndex[ LowestEntryListIndex ] := i;
6345 end;
6346 end;
6347
6348 ProgressBar.Position := 95;
6349 LogEvent(LogStartup, ' Display index (count = '
6350 + IntToStr( DisplayedIndex.Count )
6351 + ')' );
6352
6353 // Now display the final index list
6354 IndexListBox.Items.Assign( DisplayedIndex );
6355
6356 LogEvent(LogStartup, ' Tidy up' );
6357
6358 IndexLists.Destroy;
6359
6360 DestroyListAndObjects( ContentsLists );
6361
6362 IndexLoaded := true;
6363
6364 ClearWaitCursor;
6365
6366 SetStatus( 'Index loaded' );
6367 LogEvent(LogStartup, ' Done' );
6368end;
6369
6370Procedure TMainForm.OnHelpFileLoadProgress( n, outof: integer;
6371 message: string );
6372var
6373 ProgressOnFiles: longint;
6374 Filename: string;
6375 ProgressOnThisFile: longint;
6376
6377begin
6378 Filename := LoadingFilenameList[ LoadingFileIndex ];
6379
6380 ProgressOnFiles := round( 100 * LoadingFileIndex / LoadingFilenameList.Count );
6381 ProgressOnThisFile := round( 100 * n / outof / LoadingFilenameList.Count );
6382
6383 SetProgress( ( ProgressOnFiles + ProgressOnThisFile ) div 2,
6384 100,
6385 LoadingFileMsg
6386 + ExtractFileName( Filename )
6387 + ': '
6388 + message );
6389end;
6390
6391Procedure TMainForm.SetProgress( n, outof: integer;
6392 message: string );
6393begin
6394 ProgressBar.Position := n * 100 div outof;
6395 SetStatus( message );
6396 ProgressBar.Show;
6397end;
6398
6399// Load a single file.
6400Function TMainForm.OpenFile( const FileName: string;
6401 const WindowTitle: string;
6402 const SelectFirstContentsNode: boolean ): boolean;
6403var
6404 FileNames: TStringList;
6405begin
6406 FileNames := TStringList.Create;
6407 FileNames.Add( FileName );
6408 Result := OpenFiles( FileNames,
6409 WindowTitle,
6410 DisplayFirstTopic );
6411 FileNames.Destroy;
6412end;
6413
6414Function TMainForm.OpenAdditionalFile( const FileName: string;
6415 const DisplayFirstTopic: boolean ): boolean;
6416var
6417 FileNames: TStringList;
6418begin
6419 FileNames := TStringList.Create;
6420 FileNames.Add( FileName );
6421 Result := OpenAdditionalFiles( FileNames,
6422 DisplayFirstTopic );
6423 FileNames.Destroy;
6424end;
6425
6426Function TMainForm.OpenWindowsHelp( const Filename: string ): boolean;
6427var
6428 WinHelpDetails: PROGDETAILS;
6429 szFilename: cstring;
6430begin
6431
6432 result := true;
6433 if Settings.ConfirmWinHelp then
6434 result := DoYesNoDlg( WindowsHelpTitle,
6435 WindowsHelpPrompt
6436 + EndLine
6437 + FileName );
6438 if not result then
6439 exit;
6440
6441 szFilename := FileName;
6442 with WinHelpDetails do
6443 begin
6444 Length := sizeof( WinHelpDetails );
6445 progt.progc := PROG_31_ENHSEAMLESSCOMMON ;
6446 progt.fbVisible := SHE_VISIBLE;
6447 pszTitle := ''; // not used?
6448 pszExecutable := 'winhelp.exe';
6449 pszParameters := Addr( szFilename );
6450 pszStartupDir := nil;
6451 pszIcon := nil;
6452 pszEnvironment := nil;
6453 swpInitial.fl := SWP_ACTIVATE or SWP_SHOW;
6454 end;
6455
6456 result := WinStartApp( NULLHANDLE,
6457 WinHelpDetails,
6458 '',
6459 nil,
6460 SAF_INSTALLEDCMDLINE ) <> 0;
6461
6462 // Doesn't work for Dos/Win programs
6463 // RunProgram( 'winhelp.exe', FileName );
6464end;
6465
6466// Load the specified set of help files
6467Function TMainForm.LoadFiles( const FileNames: TStrings;
6468 HelpFiles: TList ): boolean;
6469var
6470 HelpFile: THelpFile;
6471 FileIndex: longint;
6472 FileName: string;
6473 FullFilePath: string;
6474
6475 FileHandlesAdjustNum: LONG;
6476 CurrentMaxFileHandles: ULONG;
6477 RequiredFileHandles: LONG;
6478begin
6479 LogEvent(LogStartup, 'LoadFiles' );
6480
6481 LoadingFilenameList := TStringList.Create;
6482
6483 TranslateIPFEnvironmentVars( FileNames, LoadingFilenameList );
6484
6485 LogEvent(LogStartup, 'Finding files' );
6486
6487 ProgressBar.Show;
6488
6489 // now find full file paths,
6490 // and also the total file size for progress display
6491 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6492 begin
6493 FileName := LoadingFilenameList[ FileIndex ];
6494 LogEvent(LogStartup, ' File: ' + FileName );
6495
6496 // Find the help file, if possible
6497 FullFilePath := FindHelpFile( Filename );
6498 if FullFilePath <> '' then
6499 begin
6500 LogEvent(LogStartup, ' Full path: ' + FullFilePath );
6501 end
6502 else
6503 begin
6504 LogEvent(LogStartup, ' File not found' );
6505 FullFilePath := FileName; // we'll complain later.
6506 end;
6507 LoadingFilenameList[ FileIndex ] := FullFilePath;
6508 end;
6509
6510 // Make sure we have enough file handles
6511
6512 FileHandlesAdjustNum := 0;
6513 DosSetRelMaxFH( FileHandlesAdjustNum, // 0 queries current
6514 CurrentMaxFileHandles );
6515
6516 RequiredFileHandles := CurrentOpenFiles.Count // already opened
6517 + LoadingFilenameList.Count // new ones
6518 + 40; // some spares.
6519 if CurrentMaxFileHandles < RequiredFileHandles then
6520 begin
6521 // need some more
6522 FileHandlesAdjustNum := RequiredFileHandles - CurrentMaxFileHandles;
6523 DosSetRelMaxFH( FileHandlesAdjustNum,
6524 CurrentMaxFileHandles );
6525 end;
6526
6527 // Now actually load the files
6528 for FileIndex := 0 to LoadingFilenameList.Count - 1 do
6529 begin
6530 Filename := LoadingFilenameList[ FileIndex ];
6531 LogEvent(LogStartup, ' Loading: ' + Filename );
6532 try
6533 LoadingFileIndex := FileIndex;
6534
6535 // load the file
6536 HelpFile := THelpFile.Create( FileName );
6537 if Settings.FixedFontSubstitution then
6538 HelpFile.SetupFontSubstitutes( Settings.FixedFontSubstitutes );
6539
6540 HelpFiles.Add( HelpFile );
6541
6542 except
6543 on E: Exception do
6544 begin
6545
6546 if E is EWindowsHelpFormatException then
6547 begin
6548 OpenWindowsHelp( Filename );
6549 end
6550 else
6551 begin
6552 DoErrorDlg( FileOpenTitle,
6553 HelpFileError
6554 + FileName
6555 + ': '
6556 + E.Message );
6557 end;
6558
6559 // back out of the load process
6560 Result := false;
6561
6562 DestroyListObjects( HelpFiles );
6563
6564 LoadingFilenameList.Destroy;
6565 ResetProgress;
6566 exit;
6567 end
6568 end;
6569 end;
6570
6571 LoadingFilenameList.Destroy;
6572
6573 Result := true;
6574
6575end;
6576
6577// Add the current list of open files as
6578// a Most Recently Used entry
6579Procedure TMainForm.AddCurrentToMRUFiles;
6580var
6581 Filenames: TStringList;
6582 i: longint;
6583 HelpFile: THelpFile;
6584begin
6585 Filenames := TStringList.Create;
6586
6587 for i := 0 to CurrentOpenFiles.Count - 1 do
6588 begin
6589 HelpFile := CurrentOpenFiles[ i ];
6590 Filenames.Add( HelpFile.Filename );
6591 end;
6592
6593 // update most-recently-used file list
6594 HelpFile := CurrentOpenFiles[ 0 ];
6595 AddToMRUList( HelpFile.Title,
6596 Filenames );
6597
6598 // recreate menu
6599 CreateMRUMenuItems;
6600
6601 Filenames.Destroy;
6602end;
6603
6604// Display the specified set of files
6605Procedure TMainForm.DisplayFiles( NewFiles: TList;
6606 Var FirstContentsNode: TNode );
6607var
6608 HelpFile: THelpFile;
6609 FileIndex: longint;
6610begin
6611 LogEvent(LogStartup, 'DisplayFiles' );
6612 // Now load the various parts of the file(s)
6613 // into the user interface
6614 ProgressBar.Position := 50;
6615 SetStatus( LoadingStatusDisplaying );
6616
6617 // Add our open files in the global filelist
6618 for FileIndex := 0 to NewFiles.Count - 1 do
6619 begin
6620 HelpFile := NewFiles[ FileIndex ];
6621 GlobalFilelist.AddFile( HelpFile.Filename, Frame.Handle );
6622 // LoadNotes( HelpFile );
6623 LoadBookmarks( HelpFile );
6624 end;
6625
6626 UpdateNotesDisplay;
6627
6628 BuildBookmarksMenu;
6629 UpdateBookmarksForm;
6630
6631 ProgressBar.Position := 55;
6632
6633 ContentsLoaded := false;
6634 IndexLoaded := false;
6635
6636 LoadContents( NewFiles, FirstContentsNode );
6637
6638 ProgressBar.Position := 75;
6639
6640 // LoadIndex;
6641
6642 ProgressBar.Position := 100;
6643 SetStatus( LoadingStatusDone );
6644
6645 LogEvent(LogStartup, 'DisplayFiles Done' );
6646
6647end;
6648
6649Function TMainForm.OpenFiles( const FileNames: TStrings;
6650 const WindowTitle: string;
6651 const DisplayFirstTopic: boolean ): boolean;
6652var
6653 HelpFiles: TList;
6654 FirstContentsNode: TNode;
6655begin
6656 LogEvent(LogStartup, 'OpenFiles' );
6657
6658 if not OKToCloseFile then
6659 exit;
6660
6661 SetWaitCursor;
6662
6663 HelpFiles := TList.Create;
6664
6665 if not LoadFiles( FileNames,
6666 HelpFiles ) then
6667 begin
6668 ClearWaitCursor;
6669 HelpFiles.Destroy;
6670 exit;
6671 end;
6672
6673 Result := true;
6674
6675 SearchResultsListBox.Clear;
6676 PageHistory.Clear;
6677 CurrentHistoryIndex := -1;
6678
6679 // Now that we have successfully loaded the new help file(s)
6680 // close the existing one.
6681 CloseFile;
6682
6683 AssignList( HelpFiles, CurrentOpenFiles );
6684
6685 ProgressBar.Position := 50;
6686 SetStatus( LoadingStatusDisplaying );
6687
6688 AddCurrentToMRUFiles;
6689
6690 if WindowTitle = '' then
6691 MainTitle := THelpFile( CurrentOpenFiles[ 0 ] ).Title
6692 else
6693 MainTitle := WindowTitle;
6694
6695 SetMainCaption;
6696
6697 // Now load the various parts of the file(s)
6698 // into the user interface
6699
6700 ContentsOutline.Clear;
6701
6702 DisplayFiles( HelpFiles,
6703 FirstContentsNode );
6704
6705 if CmdLineParameters.getHelpManagerFlag then
6706 ShowLeftPanel := Settings.ShowLeftPanel_Help
6707 else
6708 ShowLeftPanel := Settings.ShowLeftPanel_Standalone;
6709
6710 // Select first contents node if there is one
6711 if FirstContentsNode <> nil then
6712 begin
6713 LogEvent(LogStartup, ' Select first node' );
6714 ContentsOutline.SelectedNode := FirstContentsNode;
6715 end;
6716
6717 ClearWaitCursor;
6718
6719 ResetProgress;
6720
6721 NotebookOnPageChanged( self ); // ensure e.g. index loaded
6722
6723 EnableControls;
6724
6725 if DisplayFirstTopic then
6726 begin
6727 LogEvent(LogStartup, 'Display first topic' );
6728 DisplaySelectedContentsTopic;
6729 end;
6730
6731 LogEvent(LogStartup, 'OpenFiles complete' );
6732end;
6733
6734Function TMainForm.OpenAdditionalFiles( const FileNames: TStrings;
6735 const DisplayFirstTopic: boolean ): boolean;
6736var
6737 HelpFiles: TList;
6738 FirstNewContentsNode: TNode;
6739begin
6740 LogEvent(LogStartup, 'OpenAdditionalFiles' );
6741
6742 if not OKToCloseFile then
6743 exit;
6744
6745 SetWaitCursor;
6746
6747 HelpFiles := TList.Create;
6748
6749 if not LoadFiles( FileNames,
6750 HelpFiles ) then
6751 begin
6752 ClearWaitCursor;
6753 HelpFiles.Destroy;
6754 exit;
6755 end;
6756
6757 Result := true;
6758
6759 AddList( HelpFiles, CurrentOpenFiles );
6760
6761 AddCurrentToMRUFiles;
6762
6763 DisplayFiles( HelpFiles,
6764 FirstNewContentsNode );
6765
6766 // Select first contents node of new file
6767 if FirstNewContentsNode <> nil then
6768 ContentsOutline.SelectedNode := FirstNewContentsNode;
6769
6770 HelpFiles.Destroy;
6771
6772 ClearWaitCursor;
6773
6774 ResetProgress;
6775
6776 EnableControls;
6777
6778 if DisplayFirstTopic then
6779 DisplaySelectedContentsTopic;
6780
6781 LogEvent(LogStartup, 'OpenAdditionalFiles complete' );
6782end;
6783
6784Procedure TMainForm.OpenMIOnClick (Sender: TObject);
6785Begin
6786 FileOpen;
6787end;
6788
6789procedure TMainForm.FileOpen;
6790var
6791 Filenames: TStringList;
6792 KeepCurrentFiles: boolean;
6793 OpenedOK: boolean;
6794begin
6795 if not OKToCloseFile then
6796 exit;
6797
6798 if Settings.UseOriginalDialogs then
6799 begin
6800 SystemOpenDialog.Filename := AddSlash( Settings.LastOpenDirectory ) + '*.hlp;*.inf';
6801 if not SystemOpenDialog.Execute then
6802 exit;
6803
6804 Settings.LastOpenDirectory := ExtractFilePath( SystemOpenDialog.Filename );
6805 // note - sibyl's encapsulation doesn't allow multi-select
6806 OpenedOK := OpenFile( SystemOpenDialog.FileName, '', true );
6807 end
6808 else
6809 begin
6810 Filenames := TStringList.Create;
6811 KeepCurrentFiles := false;
6812 if not DoOpenMultiFileDialog( FileOpenTitle,
6813 HelpFilesDesc
6814 + '|*.inf;*.hlp|'
6815 + AllFilesDesc
6816 + '|*.*',
6817 '*.hlp;*.inf',
6818 Settings.LastOpenDirectory,
6819 KeepCurrentFiles,
6820 Filenames ) then
6821 exit;
6822
6823 if KeepCurrentFiles then
6824 OpenedOK := OpenAdditionalFiles( FileNames, true )
6825 else
6826 OpenedOK := OpenFiles( FileNames, '', true );
6827 Filenames.Destroy;
6828 end;
6829
6830 if OpenedOK then
6831 ClearHelpManager;
6832End;
6833
6834Procedure TMainForm.CloseWindows;
6835Begin
6836 DestroyListObjects( Windows );
6837 Windows.Clear;
6838end;
6839
6840// Help manager mode
6841
6842// if window is minimised then restore it
6843// (ideally should go back to maximized - don't know how)
6844Procedure TMainForm.RestoreWindow;
6845Begin
6846 If WindowState = wsMinimized then
6847 WindowState := wsNormal;
6848end;
6849
6850Procedure TMainForm.NHMDisplayIndex( Var Msg: TMessage );
6851begin
6852 RestoreWindow;
6853 DisplayIndex;
6854 // if nothing is being display already...
6855 if Windows.Count = 0 then
6856 // display first topic
6857 DisplaySelectedContentsTopic;
6858end;
6859
6860Procedure TMainForm.NHMDisplayContents( Var Msg: TMessage );
6861begin
6862 RestoreWindow;
6863 DisplayContents;
6864 // if nothing is being display already...
6865 if Windows.Count = 0 then
6866 // display first topic
6867 DisplaySelectedContentsTopic;
6868end;
6869
6870Procedure TMainForm.NHMTopicByResourceID( Var Msg: TMessage );
6871begin
6872 RestoreWindow;
6873 DisplayTopicByResourceID( Msg.Param1 );
6874end;
6875
6876Procedure TMainForm.NHMTopicByPanelName( Var Msg: TMessage );
6877var
6878 pMessageMem: pchar;
6879 PanelName: string;
6880 Topic: TTopic;
6881begin
6882 RestoreWindow;
6883
6884 pMessageMem := pchar( Msg.Param1 );
6885 PanelName := StrPas( pMessageMem );
6886 SharedMemory.Free( pMessageMem );
6887
6888 Topic := FindTopicByName( PanelName );
6889 if Topic = nil then
6890 Topic := FindTopicByGlobalName( PanelName );
6891
6892 if Topic <> nil then
6893 DisplayTopic( Topic )
6894 else
6895 SearchFor( PanelName );
6896end;
6897
6898// Sent from other instances starting up (and exiting immediately)
6899
6900Procedure TMainForm.NHMSearch( Var Msg: TMessage );
6901var
6902 pSearchText: pchar;
6903begin
6904 RestoreWindow;
6905
6906 pSearchText := pstring( Msg.Param1 );
6907 SearchFor( StrPas( pSearchText ) );
6908 SharedMemory.Free( pSearchText );
6909end;
6910
6911Procedure TMainForm.NHMGlobalSearch( Var Msg: TMessage );
6912var
6913 pSearchText: pchar;
6914begin
6915 RestoreWindow;
6916
6917 pSearchText := pstring( Msg.Param1 );
6918 DoGlobalSearch( StrPas( pSearchText ) );
6919 SharedMemory.Free( pSearchText );
6920end;
6921
6922Procedure TMainForm.NHMShowUsage( Var Msg: TMessage );
6923begin
6924 RestoreWindow;
6925 ShowUsage;
6926end;
6927
6928Procedure TMainForm.NHMSetFiles( Var Msg: TMessage );
6929var
6930 pFileNames: pchar;
6931begin
6932 // NOT restoring window here because this is not something the user should see...
6933 pFileNames := pstring( Msg.Param1 );
6934 OpenFilesFromTextList( StrPas( pFileNames ), false );
6935 SharedMemory.Free( pFileNames );
6936end;
6937
6938Procedure TMainForm.NHMSetTitle( Var Msg: TMessage );
6939var
6940 pTitle: pchar;
6941begin
6942 pTitle := pstring( Msg.Param1 );
6943 MainTitle := StrPas( pTitle );
6944 SharedMemory.Free( pTitle );
6945
6946 SetMainCaption;
6947end;
6948
6949Procedure TMainForm.NHMTest( Var Msg: TMessage );
6950var
6951 ps: pstring;
6952begin
6953 ps := PString( Msg.Param1 );
6954 ShowMessage( 'Got test message: ' + ps^ );
6955 SharedMemory.Free( ps );
6956end;
6957
6958Initialization
6959 RegisterClasses ([TMainForm, TSplitBar,
6960 TNoteBook,
6961 TEdit, TListBox,
6962 TRichTextView, TCoolBar2, TMainMenu, TMenuItem,
6963 TImageList, TPanel, TButton,
6964 TSystemOpenDialog, TOutline2, TCustomListBox, TPopupMenu, TSpeedButton
6965 , TProgressBar, TTabSet2]);
6966End.
Note: See TracBrowser for help on using the repository browser.