source: trunk/NewView/MainForm.pas@ 44

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

% command line
% debug output

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