source: trunk/NewView/MainForm.pas@ 38

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

fixes for beta3

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