source: trunk/NewView/MainForm.pas@ 25

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

refactoring for cmd line parameters handling finished

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