home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / wxwin140 / utils / wxhelp / src / wxhelp.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  34.2 KB  |  1,327 lines

  1. /*
  2.  * File:     wxhelp.cc
  3.  * Purpose:  wxWindows help system
  4.  *
  5.  *                       wxWindows 1.40
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                        Date: 18-4-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <windows.h> // Included only for using MS C/C++ precompiled headers
  30. #include <ctype.h>
  31. #include <stdlib.h>
  32. #include "wx.h"
  33. #include "wx_help.h"
  34. #include "wx_hash.h"
  35. #include "hytext.h"
  36. #include "wxhelp.h"
  37. #include "wxhlpblk.h"
  38.  
  39. float helpVersion = 1.3;
  40.  
  41. #define HELP_SERVER_ID -1
  42.  
  43. #ifdef wx_x
  44. #define DEFAULT_EDITOR "emacs"
  45. #endif
  46. #ifdef wx_msw
  47. #define DEFAULT_EDITOR "notepad"
  48. #endif
  49.  
  50. #ifdef wx_x
  51. short icon_bits[] = {
  52. #include "hlp_icn"
  53. };
  54. #endif
  55.  
  56. MyFrame   *MainFrame = NULL;
  57. SearchBox *TheSearchBox = NULL;
  58. wxHyperTextMapping *mapping = NULL;
  59. wxFont *swiss_font_12 = NULL;
  60. char *hyFilename = NULL;
  61. Bool hyEditMode = FALSE;
  62.  
  63. int SearchWindowX = 10;
  64. int SearchWindowY = 10;
  65.  
  66. wxList hyHistory;
  67. HypertextItem *hySelection = NULL;
  68. wxNode *hyHistoryPointer = NULL;
  69.  
  70. // Communication
  71. HelpConnection *TheHelpConnection = NULL;
  72. HelpServer *TheHelpServer = NULL;
  73.  
  74. #ifdef wx_msw // Only one instance in Windows 3 so make it a server ALWAYS
  75. int TheHelpServerId = 4000;
  76. #endif
  77. #ifdef wx_x
  78. int TheHelpServerId = -1;
  79. #endif
  80.  
  81. // wxHelp also has help!!
  82. wxHelpInstance *HelpInstance = NULL;
  83. wxPathList HelpPathList;
  84.  
  85. #ifdef wx_xview
  86. #define HELP_PANEL_HEIGHT 30
  87. #endif
  88. #ifdef wx_motif
  89. #define HELP_PANEL_HEIGHT 40
  90. #endif
  91. #ifdef wx_msw
  92. #define HELP_PANEL_HEIGHT 40
  93. #endif
  94.  
  95. // This statement initialises the whole application
  96. MyApp     myApp;
  97.  
  98. void hyHelpPrevious(wxButton& but, wxEvent& ev)
  99. {
  100.   MainFrame->window->DisplayPreviousSection();
  101.   MainFrame->window->DisplaySection();
  102.   long block_id = MainFrame->window->FindBlockForSection(MainFrame->window->current_section);
  103.   MainFrame->window->StoreHypertextItem(block_id);
  104. }
  105.  
  106. void hyHelpNext(wxButton& but, wxEvent& ev)
  107. {
  108.   MainFrame->window->DisplayNextSection();
  109.   MainFrame->window->DisplaySection();
  110.   long block_id = MainFrame->window->FindBlockForSection(MainFrame->window->current_section);
  111.   MainFrame->window->StoreHypertextItem(block_id);
  112. }
  113.  
  114. void hyHelpBack(wxButton& but, wxEvent& ev)
  115. {
  116.   MainFrame->window->HistoryBack();
  117. }
  118.  
  119. void hyHelpHistory(wxButton& but, wxEvent& ev)
  120. {
  121. }
  122.  
  123. void hyHelpContents(wxButton& but, wxEvent& ev)
  124. {
  125.   MainFrame->window->DisplayFileAtTop();
  126.   long block_id = MainFrame->window->FindBlockForSection(MainFrame->window->current_section);
  127.   MainFrame->window->StoreHypertextItem(block_id);
  128. }
  129.  
  130. void hyHelpSearch(wxButton& but, wxEvent& ev)
  131. {
  132.   HelpSearch();
  133. }
  134.  
  135. // The `main program' equivalent, creating the windows and returning the
  136. // main frame
  137. wxFrame *MyApp::OnInit(void)
  138. {
  139.   int i = 1;
  140.   while (i < argc)
  141.   {
  142.     if (strcmp(argv[i], "-f") == 0)
  143.     {
  144.       i ++;
  145.       if (i == argc)
  146.         hyErrorMsg("-f must take a filename!");
  147.       else
  148.       {
  149.         hyFilename = copystring(argv[i]);
  150.         i ++;
  151.       }
  152.     }
  153.     else if (strcmp(argv[i], "-edit") == 0)
  154.     {
  155.       i ++;
  156.       hyEditMode = TRUE;
  157.     }
  158.     else if (strcmp(argv[i], "-server") == 0)
  159.     {
  160.       i ++;
  161.       TheHelpServerId = atoi(argv[i]);
  162.       i ++;
  163.     }
  164.     else i++;
  165.   }
  166.  
  167.   HelpPathList.AddEnvList("WXHELPFILES");
  168.   HelpPathList.AddEnvList("PATH");
  169.  
  170.   // Create the main frame window
  171.   MainFrame = new MyFrame(NULL, "wxHelp", 0, 0, 500, 400);
  172.  
  173.   if (hyEditMode)
  174.     MainFrame->CreateStatusLine();
  175.  
  176.   // Give it an icon
  177. #ifdef wx_msw
  178.   wxIcon *icon = new wxIcon("hlp_icn");
  179. #endif
  180. #ifdef wx_x
  181.   wxIcon *icon = new wxIcon(icon_bits, 64, 64);
  182. #endif
  183.  
  184.   MainFrame->SetIcon(icon);
  185.  
  186.   // Make a menubar
  187.   wxMenu *file_menu = new wxMenu;
  188.  
  189.   file_menu->Append(HELP_OPEN, "&Open File");
  190.   if (hyEditMode)
  191.     file_menu->Append(HELP_SAVE, "&Save File");
  192.  
  193.   file_menu->AppendSeparator();
  194.   file_menu->Append(HELP_EXIT, "&Exit");
  195.  
  196.   wxMenu *edit_menu = NULL;
  197.   wxMenu *block_menu = NULL;
  198.   if (hyEditMode)
  199.   {
  200.     block_menu = new wxMenu;
  201.     edit_menu = new wxMenu;
  202.     edit_menu->Append(HELP_RUN_EDITOR, "Run &Editor");
  203.     edit_menu->Append(HELP_CLEAR_SELECTION, "&Clear selection");
  204.     edit_menu->Append(HELP_CLEAR_BLOCK, "Clear &block");
  205.     edit_menu->AppendSeparator();
  206.     edit_menu->Append(HELP_SET_TITLE, "&Set title");
  207.  
  208.     block_menu->Append(HELP_MARK_LARGE_HEADING, "Mark &large heading");
  209.     block_menu->Append(HELP_MARK_SMALL_HEADING, "Mark &small heading");
  210.     block_menu->Append(HELP_MARK_LARGE_VISIBLE_SECTION, "Mark large &visible section");
  211.     block_menu->Append(HELP_MARK_SMALL_VISIBLE_SECTION, "Mark small visible §ion");
  212.     block_menu->Append(HELP_MARK_INVISIBLE_SECTION, "Mark &invisible section");
  213.     block_menu->AppendSeparator();
  214.  
  215.     block_menu->Append(HELP_MARK_RED, "Mark &red");
  216.     block_menu->Append(HELP_MARK_BLUE, "Mark &blue");
  217.     block_menu->Append(HELP_MARK_GREEN, "Mark &green");
  218.     block_menu->AppendSeparator();
  219.     block_menu->Append(HELP_MARK_BOLD, "Mark &bold");
  220.     block_menu->Append(HELP_MARK_ITALIC, "Mark &italics");
  221.     block_menu->Append(HELP_MARK_RED_ITALIC, "Mark red i&talics");
  222.     block_menu->Append(HELP_MARK_SMALL_TEXT, "Mark small te&xt");
  223.   }
  224.  
  225.   wxMenu *help_menu = new wxMenu;
  226.   help_menu->Append(HELP_HELP_CONTENTS, "&Help on wxHelp");
  227.   help_menu->AppendSeparator();
  228.   help_menu->Append(HELP_ABOUT, "&About wxHelp");
  229.  
  230.   wxMenuBar *menu_bar = new wxMenuBar;
  231.  
  232.   menu_bar->Append(file_menu, "&File");
  233.  
  234.   if (hyEditMode)
  235.   {
  236.     menu_bar->Append(edit_menu, "&Edit");
  237.     menu_bar->Append(block_menu, "&Blocks");
  238.   }
  239.  
  240.   menu_bar->Append(help_menu, "&Help");
  241.  
  242.   // Associate the menu bar with the frame
  243.   MainFrame->SetMenuBar(menu_bar);
  244.  
  245.   // Make a button bar, a la Windows Help
  246.   MainFrame->panel = new wxPanel(MainFrame, 0, 0, 400, HELP_PANEL_HEIGHT);
  247.  
  248.   (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpContents, "Contents");
  249.   (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpSearch, "Search");
  250. //  (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpHistory, "History");
  251.   (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpBack, "Back");
  252.   (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpPrevious, "<<");
  253.   (void)new wxButton(MainFrame->panel, (wxFunction)hyHelpNext, ">>");
  254.  
  255.   // Make a hypertext window
  256.   MainFrame->window = new HelpWindow(MainFrame, 0, 0, 400, 400, 0);
  257.   MainFrame->window->SetEditMode(hyEditMode);
  258.   MainFrame->window->SetIndexWriting(TRUE);
  259.  
  260.   mapping = new wxHyperTextMapping;
  261.   // This recognized by library as the default text
  262.   mapping->AddMapping(500, 12, wxSWISS, wxNORMAL, wxNORMAL, "BLACK", "Default");
  263.  
  264.   mapping->AddMapping(hyBLOCK_NORMAL, -1, -1, -1, -1, NULL, "Normal text");
  265.   mapping->AddMapping(hyBLOCK_RED, -1, -1, -1, -1, "RED", "Red");
  266.   mapping->AddMapping(hyBLOCK_BLUE, -1, -1, -1, -1, "BLUE", "Blue");
  267.   mapping->AddMapping(hyBLOCK_GREEN, -1, -1, -1, -1, "FOREST GREEN", "Green");
  268.   mapping->AddMapping(hyBLOCK_LARGE_HEADING, 20, wxSWISS, wxNORMAL, wxBOLD, "BLACK", "Large heading");
  269.   mapping->AddMapping(hyBLOCK_SMALL_HEADING, 14, wxSWISS, wxNORMAL, wxBOLD, "BLACK", "Small heading");
  270.   mapping->AddMapping(hyBLOCK_ITALIC, -1, -1, wxITALIC, -1, NULL, "Italic");
  271.   mapping->AddMapping(hyBLOCK_BOLD, -1, -1, -1, wxBOLD, NULL, "Bold");
  272.   mapping->AddMapping(hyBLOCK_ITALIC, -1, -1, wxITALIC, -1, NULL, "Italic");
  273.   mapping->AddMapping(hyBLOCK_RED_ITALIC, -1, -1, wxITALIC, -1, "RED", "Red italic");
  274.   mapping->AddMapping(hyBLOCK_INVISIBLE_SECTION, -1, -1, -1, wxITALIC, "RED", "Invisible Section Marker", wxHYPER_SECTION, FALSE);
  275.   mapping->AddMapping(hyBLOCK_LARGE_VISIBLE_SECTION, 20, -1, -1, wxBOLD, "BLACK", "Large visible section", wxHYPER_SECTION, TRUE);
  276.   mapping->AddMapping(hyBLOCK_SMALL_VISIBLE_SECTION, 14, -1, -1, wxBOLD, "BLACK", "Small visible section", wxHYPER_SECTION, TRUE);
  277.   mapping->AddMapping(hyBLOCK_SMALL_TEXT, 10, -1, -1, -1, NULL, "Small text");
  278.   mapping->AddMapping(hyBLOCK_TELETYPE, -1, wxMODERN, -1, -1, NULL, "Teletype");
  279.  
  280.   MainFrame->window->SetMapping(mapping);
  281.  
  282.   if (hyFilename)
  283.   {
  284.     char *s = HelpPathList.FindValidPath(hyFilename);
  285.     if (!s)
  286.     {
  287.       MainFrame->SetTitle("wxHelp (no title)");
  288.       char buf[500];
  289.       sprintf(buf, "Cannot find file %s.\nTrying editing the WXHELPFILES environment variable.", hyFilename);
  290. #ifdef wx_x
  291.       cerr << buf << "\n";
  292. #endif
  293. #ifdef wx_msw
  294.       wxMessageBox(buf);
  295. #endif
  296.     }
  297.     else
  298.     {
  299.       MainFrame->window->LoadFile(s);
  300.       if (MainFrame->window->GetTitle())
  301.         MainFrame->SetTitle(MainFrame->window->GetTitle());
  302.       else
  303.         MainFrame->SetTitle("wxHelp (no title)");
  304.  
  305.       MainFrame->window->DisplayFileAtTop();
  306.       MainFrame->window->StoreHypertextItem(-1);
  307.       MainFrame->window->DisplaySection();
  308.     }
  309.   }
  310.  
  311.   if (TheHelpServerId > 0)
  312.   {
  313.     wxIPCInitialize();
  314.  
  315.     TheHelpServer = new HelpServer;
  316.     char buf[50];
  317.     sprintf(buf, "%d", TheHelpServerId);
  318.     TheHelpServer->Create(buf);
  319.   }
  320.  
  321.   HelpInstance = new wxHelpInstance;
  322.   HelpInstance->Initialize("help.xlp", HELP_SERVER_ID);
  323.  
  324.   MainFrame->Centre();
  325.   MainFrame->Show(TRUE);
  326.  
  327.   return MainFrame;
  328. }
  329.  
  330. // Define my frame constructor
  331. MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
  332.   wxFrame(frame, title, x, y, w, h)
  333. {
  334.   window = NULL;
  335.   panel = NULL;
  336. }
  337.  
  338. // Intercept menu commands
  339. void MyFrame::OnMenuCommand(int id)
  340. {
  341.   switch (id)
  342.   {
  343.     case HELP_SET_TITLE:
  344.     {
  345.       char *def = "";
  346.       if (window->GetTitle())
  347.         def = window->GetTitle();
  348.       char *title = wxGetTextFromUser("Enter help file title", "Text input",
  349.                     def);
  350.       if (title)
  351.       {
  352.         window->SetTitle(title);
  353.         SetTitle(title);
  354.         window->modified = TRUE;
  355.       }
  356.       break;
  357.     }
  358.     case HELP_OPEN:
  359.     {
  360.       // First save any edits in the current text window
  361.       if (window->Modified())
  362.       {
  363.         int choice = wxMessageBox("Save edits (Yes), Discard edits (No)?",
  364.                      "Message", wxYES_NO, this);
  365.         if (choice == wxYES)
  366.         {
  367.           char *file = wxFileSelector("Select a help file to save to", PathOnly(hyFilename),  FileNameFromPath(hyFilename), "xlp", "*.xlp");
  368.           if (file)
  369.       {
  370.             hyFilename = copystring(file);
  371.             window->SaveFile(hyFilename);
  372.       }
  373.         }
  374.       }
  375.       char *s = wxFileSelector("Load hypertext file", NULL, NULL, NULL, "*.xlp");
  376.       if (s)
  377.       {
  378.         hyFilename = copystring(s);
  379.         window->LoadFile(HelpPathList.FindValidPath(s));
  380.         if (window->GetTitle())
  381.           SetTitle(window->GetTitle());
  382.         else
  383.           SetTitle("wxHelp (no title)");
  384.         window->DisplayFileAtTop();
  385.         window->StoreHypertextItem(-1);
  386.         window->DisplaySection();
  387.       }
  388.       break;
  389.     }
  390.     case HELP_SAVE:
  391.     {
  392.       char *s = wxFileSelector("Save hypertext file", PathOnly(hyFilename), FileNameFromPath(hyFilename), "txt", "*.xlp");
  393.       if (s)
  394.         window->SaveFile(s);
  395.       break;
  396.     }
  397.  
  398.     case HELP_RUN_EDITOR:
  399.     {
  400.       // First save any edits in the current text window
  401.       if (window->Modified())
  402.       {
  403.         int choice = wxMessageBox("Save edits (Yes), Discard edits (No)?",
  404.                      "Message", wxYES_NO, this);
  405.         if (choice == wxYES)
  406.         {
  407.           char *file = wxFileSelector("Select a help file to save to", PathOnly(hyFilename),  FileNameFromPath(hyFilename), "xlp", "*.xlp");
  408.           if (file)
  409.       {
  410.             hyFilename = copystring(file);
  411.             window->SaveFile(hyFilename);
  412.       }
  413.         }
  414.       }
  415.  
  416.       char *editor = getenv("EDITOR");
  417.       if (!editor)
  418.         editor = DEFAULT_EDITOR;
  419.  
  420.       char buf[300];
  421.       if (!hyFilename)
  422.         hyFilename = wxFileSelector("Select a help file to edit", NULL, NULL, "xlp", "*.xlp");
  423.       if (hyFilename)
  424.       {
  425.         window->SaveSection();
  426.         strcpy(buf, editor);
  427.         strcat(buf, " ");
  428.         strcat(buf, hyFilename);
  429.         wxExecute(buf);
  430.  
  431.         // In Windows, it returns immediately so we can't automatically
  432.         // redisplay the file
  433. #ifdef wx_x
  434.         window->LoadFile(HelpPathList.FindValidPath(hyFilename));
  435.         if (window->GetTitle())
  436.           SetTitle(window->GetTitle());
  437.         else
  438.           SetTitle("wxHelp (no title)");
  439.         window->RestoreSection();
  440.         window->DisplaySection();
  441. #endif
  442.       }
  443.       break;
  444.     }
  445.  
  446.     case HELP_EXIT:
  447.     {
  448.       OnClose();
  449.       delete this;
  450.       break;
  451.     }
  452.  
  453.     case HELP_MARK_RED:
  454.     {
  455.       long id = window->GetFirstSelection();
  456.       while (id != -1)
  457.       {
  458.         window->SetBlockType(id, hyBLOCK_RED);
  459.         window->SelectBlock(id, FALSE);
  460.         id = window->GetNextSelection();
  461.       }
  462.       window->SaveSection();
  463.       window->Compile();
  464.       window->RestoreSection();
  465.       window->DisplaySection();
  466.       break;
  467.     }
  468.     case HELP_MARK_BLUE:
  469.     {
  470.       long id = window->GetFirstSelection();
  471.       while (id != -1)
  472.       {
  473.         window->SetBlockType(id, hyBLOCK_BLUE);
  474.         window->SelectBlock(id, FALSE);
  475.         id = window->GetNextSelection();
  476.       }
  477.       window->SaveSection();
  478.       window->Compile();
  479.       window->RestoreSection();
  480.       window->DisplaySection();
  481.       break;
  482.     }
  483.  
  484.     case HELP_MARK_ITALIC:
  485.     {
  486.       long id = window->GetFirstSelection();
  487.       while (id != -1)
  488.       {
  489.         window->SetBlockType(id, hyBLOCK_ITALIC);
  490.         window->SelectBlock(id, FALSE);
  491.         id = window->GetNextSelection();
  492.       }
  493.       window->SaveSection();
  494.       window->Compile();
  495.       window->RestoreSection();
  496.       window->DisplaySection();
  497.       break;
  498.     }
  499.  
  500.     case HELP_MARK_RED_ITALIC:
  501.     {
  502.       long id = window->GetFirstSelection();
  503.       while (id != -1)
  504.       {
  505.         window->SetBlockType(id, hyBLOCK_RED_ITALIC);
  506.         window->SelectBlock(id, FALSE);
  507.         id = window->GetNextSelection();
  508.       }
  509.       window->SaveSection();
  510.       window->Compile();
  511.       window->RestoreSection();
  512.       window->DisplaySection();
  513.       break;
  514.     }
  515.  
  516.     case HELP_MARK_BOLD:
  517.     {
  518.       long id = window->GetFirstSelection();
  519.       while (id != -1)
  520.       {
  521.         window->SetBlockType(id, hyBLOCK_BOLD);
  522.         window->SelectBlock(id, FALSE);
  523.         id = window->GetNextSelection();
  524.       }
  525.       window->SaveSection();
  526.       window->Compile();
  527.       window->RestoreSection();
  528.       window->DisplaySection();
  529.       break;
  530.     }
  531.     case HELP_MARK_SMALL_TEXT:
  532.     {
  533.       long id = window->GetFirstSelection();
  534.       while (id != -1)
  535.       {
  536.         window->SetBlockType(id, hyBLOCK_SMALL_TEXT);
  537.         window->SelectBlock(id, FALSE);
  538.         id = window->GetNextSelection();
  539.       }
  540.       window->SaveSection();
  541.       window->Compile();
  542.       window->RestoreSection();
  543.       window->DisplaySection();
  544.       break;
  545.     }
  546.  
  547.     case HELP_MARK_LARGE_HEADING:
  548.     {
  549.       long id = window->GetFirstSelection();
  550.       while (id != -1)
  551.       {
  552.         window->SetBlockType(id, hyBLOCK_LARGE_HEADING);
  553.         window->SelectBlock(id, FALSE);
  554.         id = window->GetNextSelection();
  555.       }
  556.       window->SaveSection();
  557.       window->Compile();
  558.       window->RestoreSection();
  559.       window->DisplaySection();
  560.       break;
  561.     }
  562.     case HELP_MARK_SMALL_HEADING:
  563.     {
  564.       long id = window->GetFirstSelection();
  565.       while (id != -1)
  566.       {
  567.         window->SetBlockType(id, hyBLOCK_SMALL_HEADING);
  568.         window->SelectBlock(id, FALSE);
  569.         id = window->GetNextSelection();
  570.       }
  571.       window->SaveSection();
  572.       window->Compile();
  573.       window->RestoreSection();
  574.       window->DisplaySection();
  575.       break;
  576.     }
  577.     case HELP_MARK_INVISIBLE_SECTION:
  578.     {
  579.       window->SaveSection();
  580.       long id = window->GetFirstSelection();
  581.       while (id != -1)
  582.       {
  583.         window->SetBlockType(id, hyBLOCK_INVISIBLE_SECTION);
  584.         window->SelectBlock(id, FALSE);
  585.         id = window->GetNextSelection();
  586.       }
  587.       window->SaveSection();
  588.       window->Compile();
  589.       window->RestoreSection();
  590.       window->DisplaySection();
  591.       break;
  592.     }
  593.     case HELP_MARK_LARGE_VISIBLE_SECTION:
  594.     {
  595.       window->SaveSection();
  596.       long id = window->GetFirstSelection();
  597.       while (id != -1)
  598.       {
  599.         window->SetBlockType(id, hyBLOCK_LARGE_VISIBLE_SECTION);
  600.         window->SelectBlock(id, FALSE);
  601.         id = window->GetNextSelection();
  602.       }
  603.       window->SaveSection();
  604.       window->Compile();
  605.       window->RestoreSection();
  606.       window->DisplaySection();
  607.       break;
  608.     }
  609.     case HELP_MARK_SMALL_VISIBLE_SECTION:
  610.     {
  611.       window->SaveSection();
  612.       long id = window->GetFirstSelection();
  613.       while (id != -1)
  614.       {
  615.         window->SetBlockType(id, hyBLOCK_SMALL_VISIBLE_SECTION);
  616.         window->SelectBlock(id, FALSE);
  617.         id = window->GetNextSelection();
  618.       }
  619.       window->SaveSection();
  620.       window->Compile();
  621.       window->RestoreSection();
  622.       window->DisplaySection();
  623.       break;
  624.     }
  625.     case HELP_CLEAR_SELECTION:
  626.     {
  627.       long id = window->GetFirstSelection();
  628.       while (id != -1)
  629.       {
  630.         window->SelectBlock(id, FALSE);
  631.         id = window->GetNextSelection();
  632.       }
  633.       window->SaveSection();
  634.       window->Compile();
  635.       window->RestoreSection();
  636.       window->DisplaySection();
  637.       break;
  638.     }
  639.  
  640.     case HELP_CLEAR_BLOCK:
  641.     {
  642.       window->SaveSection();
  643.       long id = window->GetFirstSelection();
  644.       while (id != -1)
  645.       {
  646.         window->SelectBlock(id, FALSE);
  647.  
  648.         window->ClearBlock(id);
  649.         id = window->GetNextSelection();
  650.       }
  651.       window->SaveSection();
  652.       window->Compile();
  653.       window->RestoreSection();
  654.       window->DisplaySection();
  655.       break;
  656.     }
  657.  
  658. /*
  659.     case HELP_TEST:
  660.     {
  661.       wxDC *dc = MainFrame->window->GetDC();
  662.       dc->SetFont(swiss_font_12);
  663.  
  664.       char **choices = new char*[wxTheColourDatabase->Number()];
  665.       wxNode *node = wxTheColourDatabase->First();
  666.       int i = 0;
  667.       while (node)
  668.       {
  669.         choices[i] = node->key.string;
  670.         node = node->Next();
  671.         i ++;
  672.       }
  673.       char *col = wxGetSingleChoice("Choose a colour", "Choice",
  674.           wxTheColourDatabase->Number(), choices);
  675.       if (col)
  676.       {
  677.         dc->SetTextBackground(wxWHITE);
  678.         dc->SetTextForeground(wxTheColourDatabase->FindColour(col));
  679.         dc->DrawText("Hello, some test text", 30, 30);
  680.       }
  681.       break;
  682.     }
  683. */
  684.     case HELP_HELP_CONTENTS:
  685.     {
  686.       HelpInstance->LoadFile();
  687.       HelpInstance->DisplayContents();
  688.       break;
  689.     }
  690.  
  691.     case HELP_ABOUT:
  692.     {
  693.       char buf[400];
  694.       sprintf(buf, "wxHelp version %.2f\n", helpVersion);
  695.       strcat(buf, "by Julian Smart, AIAI (c) April 1993\n");
  696.       strcat(buf, "J.Smart@ed.ac.uk");
  697.       wxMessageBox(buf, "About wxHelp");
  698.       break;
  699.     }
  700.   }
  701. }
  702.  
  703. // Define the behaviour for the frame closing
  704. // - must delete all frames except for the main one.
  705. Bool MyFrame::OnClose(void)
  706. {
  707.   // First save any edits in the current text window
  708.   if (window->Modified())
  709.   {
  710.     int choice = wxMessageBox("Save edits (Yes), Discard edits (No)?",
  711.                  "Message", wxYES_NO | wxCANCEL, this);
  712.     if (choice == wxYES)
  713.     {
  714.       char *file = wxFileSelector("Select a help file to save to", PathOnly(hyFilename),  FileNameFromPath(hyFilename), "xlp", "*.xlp");
  715.       if (file)
  716.       {
  717.         hyFilename = copystring(file);
  718.         window->SaveFile(hyFilename);
  719.       } else return FALSE;
  720.     } else if (choice == wxCANCEL) return FALSE;
  721.   }
  722.   if (TheSearchBox)
  723.     delete TheSearchBox;
  724.  
  725.   if (TheHelpConnection)
  726.     TheHelpConnection->Disconnect();
  727.  
  728.   HelpInstance->Quit();
  729.  
  730.   return TRUE;
  731. }
  732.  
  733. void MyFrame::OnSize(int w, int h)
  734. {
  735.   if (panel && window)
  736.   {
  737.     int width, height;
  738.     GetClientSize(&width, &height);
  739.     panel->SetSize(0, 0, width, HELP_PANEL_HEIGHT);
  740.     window->SetSize(0, HELP_PANEL_HEIGHT, width, height - HELP_PANEL_HEIGHT);
  741.   }
  742. }
  743.  
  744. HelpWindow::HelpWindow(wxFrame *frame, int x, int y, int w, int h, int style):
  745.   wxHyperTextWindow(frame, x, y, w, h, style)
  746. {
  747. }
  748.  
  749. HelpWindow::~HelpWindow(void)
  750. {
  751. }
  752.  
  753. void HelpWindow::OnSelectBlock(long block_id, Bool select)
  754. {
  755.   if (select)
  756.   {
  757.     if (hySelection)
  758.       delete hySelection;
  759.     hySelection = new HypertextItem(hyFilename, block_id);
  760.   }
  761.   else
  762.   {
  763.     if (hySelection && (hySelection->block_id == block_id))
  764.     {
  765.       delete hySelection;
  766.       hySelection = NULL;
  767.     }
  768.   }
  769. }
  770.  
  771. void HelpWindow::ClearBlock(long block_id)
  772. {
  773.   wxHyperTextWindow::ClearBlock(block_id);
  774.   HypertextItem *item = (HypertextItem *)GetLinkTable()->Get(block_id);
  775.   if (item)
  776.   {
  777.     long other_block = item->block_id;
  778.     if (other_block != 0)
  779.     {
  780.       (void)GetLinkTable()->Delete(block_id);
  781.       delete item;
  782.     }
  783.   }
  784. }
  785.  
  786. // Select/deselect block if SHIFT held down (default behaviour),
  787. // or traverse a link otherwise.
  788. void HelpWindow::OnLeftClick(float x, float y, int char_pos, int line, long block_id, int keys)
  789. {
  790.   if (keys & KEY_SHIFT)
  791.   {
  792.     wxHyperTextWindow::OnLeftClick(x, y, char_pos, line, block_id, keys);
  793.     return;
  794.   }
  795.   else if ((keys & KEY_CTRL) && block_id > -1 && hyEditMode)
  796.   {
  797.     // Display some useful info
  798.     int type = GetBlockType(block_id);
  799.  
  800.     wxNode *node = mapping->Find(type);
  801.     wxHTMappingStructure *struc = (wxHTMappingStructure *)node->Data();
  802.  
  803.     char *linked = " (not linked)";
  804.     if (GetLinkTable()->Get(block_id))
  805.       linked = " (linked)";
  806.     char buf[300];
  807.  
  808.     sprintf(buf, "%s %s", struc->name, linked);
  809.     MainFrame->SetStatusText(buf);
  810.   }
  811.   else if (block_id > -1)
  812.   {
  813.     HypertextItem *item = (HypertextItem *)GetLinkTable()->Get(block_id);
  814.     if (!item)
  815.       return;
  816.  
  817.     long other_block = item->block_id;
  818.     if (other_block > 0)
  819.     {
  820.       if (item->filename)
  821.       {
  822.         char *s = HelpPathList.FindValidPath(item->filename);
  823.         if (s)
  824.         {
  825.           if (!hyFilename || (strcmp(hyFilename, s) != 0))
  826.           {
  827.             if (hyFilename)
  828.               delete hyFilename;
  829.             hyFilename = copystring(s);
  830.             LoadFile(hyFilename);
  831.             if (GetTitle())
  832.               MainFrame->SetTitle(GetTitle());
  833.             else
  834.               MainFrame->SetTitle("wxHelp (no title)");
  835.           }
  836.         }
  837.         else
  838.         {
  839.           char buf[500];
  840.           sprintf(buf, "Could not find file %s.\nTry editing the WXHELPFILES environment variable", item->filename);
  841.           (void)wxMessageBox(buf, "wxHelp Error");
  842.           return;
  843.         }
  844.       }
  845.       DisplayFileAt(other_block);
  846.       StoreHypertextItem(other_block);
  847.       DisplaySection();
  848.     }
  849.   }
  850. }
  851.  
  852. // Popup a menu for deleting block, linking with other items,
  853. // etc.
  854. void HelpWindow::OnRightClick(float x, float y, int char_pos, int line, long block_id, int keys)
  855. {
  856.   int block_type = GetBlockType(block_id);
  857.   if (block_type == BLOCK_TYPE_SELECTION)
  858.     return;
  859.  
  860.   int x1, y1, x2, y2;
  861.   MainFrame->GetPosition(&x2, &y2);
  862.  
  863.   ViewStart(&x1, &y1);
  864.   int mouse_x = (int)(GetDC()->LogicalToDeviceX(x - x1) + x2);
  865.   int mouse_y = (int)(GetDC()->LogicalToDeviceY(y - y1) + y2);
  866.  
  867.   char **choices = new char *[10];
  868.   int no_choices = 0;
  869.  
  870.   choices[no_choices] = "Link block to selection";
  871.   no_choices ++;
  872.   choices[no_choices] = "Unlink block";
  873.   no_choices ++;
  874.   choices[no_choices] = "Clear block";
  875.   no_choices ++;
  876.  
  877.   char *choice = wxGetSingleChoice("Pick a block action", "Menu",
  878.                                    no_choices, choices, MainFrame, mouse_x, mouse_y);
  879.   if (!choice)
  880.   {
  881.     delete choices;
  882.     return;
  883.   }
  884.  
  885.   if (strcmp(choice, "Link block to selection") == 0)
  886.   {
  887.     if (hySelection)
  888.     {
  889.       if (GetLinkTable()->Get(block_id))
  890.         MainFrame->SetStatusText("This block already linked!");
  891.       else if (hySelection->block_id > -1)
  892.       {
  893.         GetLinkTable()->Put(block_id,
  894.           new HypertextItem(hySelection->filename, hySelection->block_id));
  895.         modified = TRUE;
  896.         SelectBlock(hySelection->block_id, FALSE);
  897.         Compile();
  898.         DisplayFile();
  899.       }
  900.     }
  901.   }
  902.   else if (strcmp(choice, "Unlink block") == 0)
  903.   {
  904.     HypertextItem *item = (HypertextItem *)GetLinkTable()->Get(block_id);
  905.     if (!item)
  906.       MainFrame->SetStatusText("Nothing to unlink.");
  907.     else
  908.     {
  909.       (void)GetLinkTable()->Delete(block_id);
  910.       delete item;
  911.       modified = TRUE;
  912.       MainFrame->SetStatusText("Unlinked block.");
  913.     }
  914.   }
  915.   else if (strcmp(choice, "Clear block") == 0)
  916.   {
  917.     SaveSection();
  918.     HypertextItem *item = (HypertextItem *)GetLinkTable()->Get(block_id);
  919.     if (item)
  920.     {
  921.       (void)GetLinkTable()->Delete(block_id);
  922.       delete item;
  923.     }
  924.  
  925.     SelectBlock(block_id, FALSE);
  926.     ClearBlock(block_id);
  927.     modified = TRUE;
  928.     Compile();
  929.     RestoreSection();
  930.   }
  931.  
  932.   delete choices;
  933. }
  934.  
  935. void HelpWindow::DisplaySection(void)
  936. {
  937.   if (hyEditMode)
  938.   {
  939.     char buf[300];
  940.     int sect = GetCurrentSectionNumber();
  941.     sprintf(buf, "Section %d", sect);
  942.     MainFrame->SetStatusText(buf);
  943.   }
  944. }
  945.  
  946. void HelpWindow::StoreHypertextItem(long block_id)
  947. {
  948.   wxNode *last = hyHistory.Last();
  949.   // Don't store if the same as last time!
  950.   if (last)
  951.   {
  952.     HypertextItem *ep = (HypertextItem *)last->Data();
  953.     if (ep->filename && hyFilename &&
  954.         ((strcmp(ep->filename, hyFilename) == 0) && ep->block_id == block_id))
  955.       return;
  956.   }
  957.   hyHistory.Append(new HypertextItem(hyFilename, block_id));
  958.   hyHistoryPointer = hyHistory.Last();
  959. }
  960.  
  961. void HelpWindow::HistoryBack(void)
  962. {
  963.   if (!hyHistoryPointer)
  964.     hyHistoryPointer = hyHistory.First();
  965.  
  966.   hyHistoryPointer = hyHistoryPointer->Previous();
  967.   if (!hyHistoryPointer)
  968.     hyHistoryPointer = hyHistory.First();
  969.  
  970.   HypertextItem *ep = (HypertextItem *)hyHistoryPointer->Data();
  971.   char *s = ep->filename;
  972.   if (s && strcmp(s, hyFilename) != 0)
  973.   {
  974.     LoadFile(HelpPathList.FindValidPath(s));
  975.     if (GetTitle())
  976.       MainFrame->SetTitle(GetTitle());
  977.     else
  978.       MainFrame->SetTitle("wxHelp (no title)");
  979.     hyFilename = copystring(s);
  980.   }
  981.   DisplayFileAt(ep->block_id);
  982. }
  983.  
  984. void HelpWindow::DisplayHistory(void)
  985. {
  986. }
  987.  
  988.  
  989. void hyErrorMsg(char *msg)
  990. {
  991. #ifdef wx_x
  992.   if (myApp.Initialized())
  993.     (void)wxMessageBox(msg, "Error", wxOK);
  994.   else
  995.     cerr << "Error: " << msg << "\n";
  996. #endif
  997. #ifdef wx_msw
  998.     (void)wxMessageBox(msg, "Error", wxOK);
  999. #endif
  1000. }
  1001.  
  1002. /* Searching
  1003.  */
  1004.  
  1005. class StringData: public wxObject
  1006. {
  1007.  public:
  1008.   char *s;
  1009.   wxObject *data;
  1010.   StringData(char *s, wxObject *data);
  1011. };
  1012.  
  1013. StringData::StringData(char *the_s, wxObject *the_data)
  1014. {
  1015.   s = the_s;
  1016.   data = the_data;
  1017. }
  1018.  
  1019. int wxCompareStringData(const void *arg1, const void *arg2)
  1020. {
  1021.   StringData **one = (StringData **)arg1;
  1022.   StringData **two = (StringData **)arg2;
  1023.  
  1024.   return strcmp((*one)->s, (*two)->s);
  1025. }
  1026.  
  1027. void SortStringDataList(wxList *list)
  1028. {
  1029.   int n = list->Number();
  1030.   StringData **array = new StringData *[list->Number()];
  1031.   int i = 0;
  1032.   wxNode *node = list->First();
  1033.   while (node)
  1034.   {
  1035.     array[i] = (StringData *)node->Data();
  1036.     i ++;
  1037.     node = node->Next();
  1038.   }
  1039.   qsort(array, n, sizeof(StringData *), wxCompareStringData);
  1040.   list->Clear();
  1041.  
  1042.   for (i = 0; i < n; i++)
  1043.     list->Append((StringData *)(array[i]));
  1044.  
  1045.   delete array;
  1046. }
  1047.  
  1048.  
  1049. void hyDoSearch(wxButton& button, wxEvent& event)
  1050. {
  1051.   SearchBox *box = (SearchBox *)button.GetParent();
  1052.   box->DoSearch();
  1053. }
  1054.  
  1055. void hySearchQuit(wxButton& button, wxEvent& event)
  1056. {
  1057.   SearchBox *box = (SearchBox *)button.GetParent();
  1058. //  box->GetPosition(&SearchWindowX, &SearchWindowY);
  1059.   TheSearchBox = NULL;
  1060.   delete box;
  1061. }
  1062.  
  1063. void hySearchSelection(wxListBox& listbox, wxEvent& event)
  1064. {
  1065.   int sel = listbox.GetSelection();
  1066.   long block_id = (long)listbox.GetClientData(sel);
  1067.   MainFrame->window->DisplayFileAt(block_id);
  1068.   MainFrame->window->StoreHypertextItem(block_id);
  1069.   MainFrame->window->DisplaySection();
  1070.   MainFrame->Iconize(FALSE);
  1071.   MainFrame->Show(TRUE);
  1072. }
  1073.  
  1074. // Search window
  1075. SearchBox::SearchBox(wxFrame *parent):
  1076.   wxDialogBox(parent, "Search", FALSE, SearchWindowX, SearchWindowY, 500, 300)
  1077. {
  1078.   SetClientSize(500, 300);
  1079.  
  1080.   (void)new wxButton(this, (wxFunction)&hySearchQuit, "Quit");
  1081.  
  1082.   search_item = new wxText(this, (wxFunction)NULL, "Search string", "*", -1, -1, 400, -1);
  1083.   NewLine();
  1084.  
  1085.   (void)new wxButton(this, (wxFunction)&hyDoSearch, "Do Search");
  1086.   NewLine();
  1087.  
  1088.   titles_item = new wxListBox(this, (wxFunction)&hySearchSelection,
  1089.                              "Items", wxSINGLE, -1, -1, 400, 200);
  1090.  
  1091.   Fit();
  1092. }
  1093.  
  1094. wxList *FindMatchingStrings(char *search_string1)
  1095. {
  1096.   wxCursor *old_cursor = MainFrame->window->SetCursor(wxHOURGLASS_CURSOR);
  1097.   ::wxSetCursor(wxHOURGLASS_CURSOR);
  1098.  
  1099.   char buffer[300];
  1100.   char *search_string = copystring(search_string1);
  1101.  
  1102.   int i;
  1103.   for (i = 0; i < strlen(search_string); i ++)
  1104.     search_string[i] = toupper(search_string[i]);
  1105.  
  1106.   wxList *string_list = new wxList;
  1107.  
  1108.   wxNode *node = MainFrame->window->text_chunks.First();
  1109.   while (node)
  1110.   {
  1111.     wxTextChunk *chunk = (wxTextChunk *)node->Data();
  1112.     if ((chunk->special_attribute == wxHYPER_SECTION) && chunk->visibility)
  1113.     {
  1114.       MainFrame->window->GetBlockText(buffer, 300, node, chunk->block_id);
  1115.       char *text = copystring(buffer);
  1116.  
  1117.       for (i = 0; i < strlen(buffer); i ++)
  1118.         buffer[i] = toupper(buffer[i]);
  1119.  
  1120.       if (search_string && (search_string[0] == '*' || StringMatch(search_string, buffer)))
  1121.         string_list->Append(new StringData(text, (wxObject *)chunk->block_id));
  1122.     }
  1123.     node = node->Next();
  1124.   }
  1125.  
  1126.   SortStringDataList(string_list);
  1127.   delete search_string;
  1128.  
  1129.   MainFrame->window->SetCursor(old_cursor);
  1130.   ::wxSetCursor(wxSTANDARD_CURSOR);
  1131.  
  1132.   return string_list;
  1133. }
  1134.  
  1135. void DeleteMatchingStrings(wxList *string_list)
  1136. {
  1137.   wxNode *node = string_list->First();
  1138.   while (node)
  1139.   {
  1140.     StringData *sd = (StringData *)node->Data();
  1141.  
  1142.     delete sd;
  1143.     delete node;
  1144.     node = string_list->First();
  1145.   }
  1146.   delete string_list;
  1147. }
  1148.  
  1149. void SearchBox::DoSearch(wxList *string_list)
  1150. {
  1151.   char *search_string = copystring(search_item->GetValue());
  1152.   if (!search_string)
  1153.     return;
  1154.  
  1155.   wxCursor *old_cursor = MainFrame->window->SetCursor(wxHOURGLASS_CURSOR);
  1156.   ::wxSetCursor(wxHOURGLASS_CURSOR);
  1157.  
  1158.   titles_item->Show(FALSE);
  1159.   titles_item->Clear();
  1160.  
  1161.   if (!string_list)
  1162.     string_list = FindMatchingStrings(search_string);
  1163.  
  1164.   wxNode *node = string_list->First();
  1165.   while (node)
  1166.   {
  1167.     StringData *sd = (StringData *)node->Data();
  1168.     titles_item->Append(sd->s, (char *)sd->data);
  1169.  
  1170.     node = node->Next();
  1171.   }
  1172.   DeleteMatchingStrings(string_list);
  1173.  
  1174.   titles_item->Show(TRUE);
  1175.   delete search_string;
  1176.  
  1177.   MainFrame->window->SetCursor(old_cursor);
  1178.   ::wxSetCursor(wxSTANDARD_CURSOR);
  1179. }
  1180.  
  1181. void HelpSearch(void)
  1182. {
  1183.   if (TheSearchBox)
  1184.   {
  1185.     TheSearchBox->Show(TRUE);
  1186.     return;
  1187.   }
  1188.   TheSearchBox = new SearchBox(NULL);
  1189.   TheSearchBox->DoSearch();
  1190.  
  1191.   TheSearchBox->Show(TRUE);
  1192. }
  1193.  
  1194. /*
  1195.  * Communication with applications
  1196.  *
  1197.  */
  1198.  
  1199. Bool HelpConnection::OnExecute(char *topic, char *data, int size, int format)
  1200. {
  1201.   if (strcmp(topic, "WXHELP") == 0)
  1202.   {
  1203.     switch (data[0])
  1204.     {
  1205.       case 's': // Display at section (-1 for top)
  1206.       {
  1207.         int section_no = atoi(data + 2);
  1208.         if (section_no == -1)
  1209.         {
  1210.           MainFrame->window->DisplayFileAtTop();
  1211.           MainFrame->window->StoreHypertextItem(-1);
  1212.           MainFrame->Iconize(FALSE);
  1213.           MainFrame->Show(TRUE);
  1214.           return TRUE;
  1215.         }
  1216.         else
  1217.         {
  1218.           // Find section for block
  1219.           wxNode *sectionNode = MainFrame->window->sections.Nth(section_no - 1);
  1220.           if (sectionNode)
  1221.       {
  1222.             wxTextChunk *chunk = (wxTextChunk *)sectionNode->Data();
  1223.             MainFrame->window->DisplayFileAt(chunk->block_id);
  1224.             MainFrame->window->StoreHypertextItem(chunk->block_id);
  1225.             MainFrame->Iconize(FALSE);
  1226.             MainFrame->Show(TRUE);
  1227.             return TRUE;
  1228.       }
  1229.           else return TRUE;
  1230.         }
  1231.         break;
  1232.       }
  1233.       case 'b': // Display at block
  1234.       {
  1235.         long block_no = atol(data + 2);
  1236.         MainFrame->window->DisplayFileAt(block_no);
  1237.         MainFrame->window->StoreHypertextItem(block_no);
  1238.         MainFrame->Iconize(FALSE);
  1239.         MainFrame->Show(TRUE);
  1240.         return TRUE;
  1241.         break;
  1242.       }
  1243.       case 'f': // Load file
  1244.       {
  1245.         char *s = HelpPathList.FindValidPath(data + 2);
  1246.         if (!s)
  1247.         {
  1248.           MainFrame->SetTitle("wxHelp (no title)");
  1249.           char buf[500];
  1250.           sprintf(buf, "Cannot find file %s.\nTrying editing the WXHELPFILES environment variable.", hyFilename);
  1251.           wxMessageBox(buf);
  1252.           return FALSE;
  1253.         }
  1254.  
  1255.         if (!hyFilename || (strcmp(s, hyFilename) != 0))
  1256.     {
  1257.           if (hyFilename) delete hyFilename;
  1258.           hyFilename = copystring(s);
  1259.           Bool succ = MainFrame->window->LoadFile(hyFilename);
  1260.           MainFrame->window->StoreHypertextItem(-1);
  1261.           MainFrame->Iconize(FALSE);
  1262.           MainFrame->Show(TRUE);
  1263.           return succ;
  1264.     }
  1265.         else
  1266.         {
  1267.           MainFrame->Iconize(FALSE);
  1268.           MainFrame->Show(TRUE);
  1269.           return TRUE;
  1270.     }
  1271.         break;
  1272.       }
  1273.       case 'k': // Search for string
  1274.       {
  1275.         char *str = data + 2;
  1276.         MainFrame->Iconize(FALSE);
  1277.         MainFrame->Show(TRUE);
  1278.  
  1279.         wxList *string_list = FindMatchingStrings(str);
  1280.         int n = string_list->Number();
  1281.         if (n == 0)
  1282.     {
  1283.           delete string_list;
  1284.           return FALSE;
  1285.     }
  1286.         else if (n == 1)
  1287.     {
  1288.           StringData *sd = (StringData *)string_list->First()->Data();
  1289.           long block_id = (long)sd->data;
  1290.           DeleteMatchingStrings(string_list);
  1291.  
  1292.           MainFrame->window->DisplayFileAt(block_id);
  1293.           MainFrame->window->StoreHypertextItem(block_id);
  1294.           MainFrame->window->DisplaySection();
  1295.           return TRUE;
  1296.     }
  1297.         else
  1298.     {
  1299.           MainFrame->Iconize(FALSE);
  1300.           MainFrame->Show(TRUE);
  1301.           if (TheSearchBox)
  1302.             TheSearchBox->Show(TRUE);
  1303.           else
  1304.             TheSearchBox = new SearchBox(NULL);
  1305.           TheSearchBox->search_item->SetValue(str);
  1306.           TheSearchBox->DoSearch(string_list);
  1307.  
  1308.           TheSearchBox->Show(TRUE);
  1309.           return TRUE;
  1310.     }
  1311.         break;
  1312.       }
  1313.       default:
  1314.         return FALSE;
  1315.     }
  1316.   } else return FALSE;
  1317. }
  1318.  
  1319. Bool HelpConnection::OnDisconnect(void)
  1320. {
  1321.   TheHelpConnection = NULL;
  1322.   MainFrame->OnClose();
  1323.   delete MainFrame;
  1324.   delete this;
  1325.   return TRUE;
  1326. }
  1327.