source: trunk/NewView/MainForm.pas@ 32

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

% more source cleanup (uses)

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