home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / kwhelp.zip / KWHELP.E < prev    next >
Text File  |  1993-05-20  |  12KB  |  392 lines

  1. /************************************************************************/
  2. -- KWHELP.E
  3. -- Mat Kramer, MekTek, 75746.2404@compuserve.com
  4. -- 20 May 93: Initial revision
  5. --
  6. -- Please send comments, suggestions, bug reports to the above address.
  7. --
  8. -- This is a replacement for EPM's standard KWHELP.E.  It adds:
  9. --    * generic "h" command to allow looking up a topic in a book
  10. --    * list of available books generated from BOOKSHELF environment
  11. --    * filetype-sensitivity in the index search -- the "EXTENSIONS:"
  12. --      tags are not ignored.
  13. --    * index search will search for case-insensitive match if no exact
  14. --      match is found.
  15. --
  16. -- Entry points are typically the "kwhelp" command (which searches the help
  17. -- index for the token under the text cursor), and the "h" command,
  18. -- described below.  "kwhelp" is assigned to Ctrl+H and Ctrl+DblClick
  19. -- by default.
  20. --
  21. -- Ideas for enhancements:
  22. --    - Sort the book list
  23. --    - Use DESCRIPTION tags or INF files to get titles of books
  24. --    - Check environment for concatenated books (e.g., PMREF)
  25. --
  26. -- NOTE: This is not meant to work with earlier incarnations of E (pre-EPM)
  27. /************************************************************************/
  28. include 'stdconst.e'
  29.  
  30. const
  31. compile if not defined(EPM_POINTER)
  32.    EPM_POINTER = TEXT_POINTER
  33. compile endif
  34.  
  35.  
  36. /************************************************************************/
  37. -- kwhelp
  38. -- pHelp_C_identifier()
  39. --
  40. -- These are the entry defined by the standard KWHELP.E
  41. /************************************************************************/
  42. defc kwhelp=  call pHelp_C_identifier()
  43.  
  44. defproc pHelp_C_identifier
  45.    if not find_token(startcol, endcol) then
  46.       return
  47.    endif
  48.    identifier = substr(textline(.line), startcol, (endcol-startcol)+1)
  49.    'h' identifier '*'
  50.  
  51.  
  52. /************************************************************************/
  53. -- h [topic [book]]
  54. --
  55. -- This command gets help on a specified topic from a specified book.
  56. -- if book='*', then the HELPNDX is search for a matching book.  If
  57. -- book is not specified, the user is prompted to pick a book from all
  58. -- of the available books in the BOOKSHELF directories.  If topic is
  59. -- not specified, the user is prompted to enter a topic string.
  60. /************************************************************************/
  61. defc h
  62.  
  63.    parse arg topic book
  64.  
  65.    /* get topic */
  66.    if topic = '' then
  67.       topic = entrybox('Enter Topic')
  68.    endif
  69.    if topic = '' then
  70.       return
  71.    endif
  72.  
  73.    /* get book to view */
  74.    if book = '' then
  75.       book = SelectBook()
  76.    endif
  77.    if book = '' then
  78.       return
  79.    endif
  80.  
  81.    /* get the required command */
  82.    if book = '*' then
  83.       cmd = FindIndexCmd(topic)
  84.       if cmd = '' then
  85.          sayerror 'Topic not in help index:' topic
  86.          book = SelectBook()
  87.          if book = '' then
  88.             return
  89.          endif
  90.       endif
  91.    else
  92.       cmd = 'view' book topic
  93.    endif
  94.  
  95.    /* execute the command */
  96.    'dos' cmd
  97.    return
  98.  
  99.  
  100. /************************************************************************/
  101. -- SelectBook()
  102. --
  103. -- Procedure prompts user to select an INF book from the BOOKSHELF.
  104. -- Returns an empty string if no books were found or if the user
  105. -- selected Cancel.
  106. /************************************************************************/
  107. defproc SelectBook
  108.  
  109.    universal vTEMP_FILENAME, booklist
  110.  
  111.    /* create a book list if not already done */
  112.    if not booklist then
  113.  
  114.       mouse_setpointer WAIT_POINTER
  115.  
  116.       /* get a list of all books */
  117.       call erasetemp(vTEMP_FILENAME)
  118.       booklist = get_env('BOOKSHELF')
  119.       sayerror 'Building book list:' booklist
  120.       do while booklist <> ''
  121.          parse value booklist with bookdir ';' booklist
  122.          call subdir(bookdir'\*.INF >>'vTEMP_FILENAME)
  123.       enddo
  124.       'edit /d /q' vTEMP_FILENAME
  125.       call erasetemp(vTEMP_FILENAME)
  126.    
  127.       /* build a delimited book list for listbox() */
  128.       booklist = '/'  -- initial delimiter
  129.       top
  130.       do while .line < .last
  131.          book = textline(.line)
  132.          if pos('SYS', book) <> 1 then
  133.             /* not an error line (SYSnnnn:), add to list */
  134.             book = substr(book, lastpos('\', book)+1)  -- get filename
  135.             book = leftstr(book, length(book)-4)  -- strip .INF extension
  136.             booklist = booklist||book||'/'
  137.          endif
  138.          down
  139.       enddo
  140.       'quit'  -- don't need the file anymore
  141.  
  142.       mouse_setpointer EPM_POINTER
  143.  
  144.    endif
  145.  
  146.    /* present the listbox */
  147.    if verify(booklist, '/') > 0 then
  148.       return listbox('Select Book', booklist)
  149.    else
  150.       return ''
  151.    endif
  152.  
  153.  
  154. /************************************************************************/
  155. -- FindIndexCmd(topic)
  156. --
  157. -- Searches the help index (NDX files) for a matching topic.  If one
  158. -- is found, the command required to view the information is returned.
  159. -- Otherwise, an empty string is returned.
  160. --
  161. -- format of index file:
  162. --     (Win*, view pmwin.inf ~)
  163. --     (printf, view dde4help.inf printf)
  164. /************************************************************************/
  165. defproc FindIndexCmd(topic)
  166.  
  167.    universal helpindex_id
  168.  
  169.    ftype = filetype()  -- save file type
  170.  
  171.    /* switch to the help index */
  172.    getfileid CurrentFile             /* save the ID of the current file */
  173.    if helpindex_id then
  174.       rc = 0
  175.       activatefile helpindex_id
  176.       if rc then  -- File's gone?
  177.          helpindex_id = 0
  178.       endif
  179.    endif
  180.    if not helpindex_id then
  181.       'LoadHelpIndex'
  182.    endif
  183.  
  184.    /* search for a match */
  185.    sayerror 'Searching help index for:' topic
  186.    mouse_setpointer WAIT_POINTER
  187.    display -2  -- disable messages
  188.    call psave_mark(savemark)
  189.    getsearch savesearch
  190.    found = SearchSections(topic, ftype, line, col)
  191.    if not found then
  192.       found = SearchSections(topic, '*', line, col)
  193.    endif
  194.    if not found then
  195.       found = SearchSections(topic, '', line, col)  -- search ALL sections
  196.    endif
  197.    setsearch savesearch
  198.    call prestore_mark(savemark)
  199.    display 2  -- enable messages
  200.    mouse_setpointer EPM_POINTER
  201.  
  202.    /* substitute occurences of '~' with original topic */
  203.    if not found then
  204.       cmd = ''
  205.    else
  206.       parse value substr(textline(line), col) with ',' cmd ')'
  207.       loop
  208.          i = pos('~', cmd)
  209.          if not i then
  210.             leave
  211.          endif
  212.          cmd = leftstr(cmd, i-1)||topic||substr(cmd, i+1)
  213.       endloop
  214.    endif
  215.  
  216.    activatefile CurrentFile
  217.    return cmd
  218.  
  219.  
  220. /************************************************************************/
  221. -- LoadHelpIndex
  222. --
  223. -- Loads all files specified in the HELPNDX environment variable into
  224. -- the hidden buffer with fileid "helpindex_id".  The specified files
  225. -- are searched for first in the default locations (findfile 'D' option),
  226. -- then in the PATH.
  227. /************************************************************************/
  228. defc LoadHelpIndex
  229.  
  230.    universal helpindex_id
  231.  
  232.    helplist = Get_Env('HELPNDX')
  233.    if helplist='' then
  234. compile if defined(KEYWORD_HELP_INDEX_FILE)
  235.        helplist = KEYWORD_HELP_INDEX_FILE
  236. compile else
  237.        helplist = 'epmkwhlp.ndx'
  238. compile endif
  239.    endif
  240.    sayerror 'Loading help index:' helplist
  241.    do while helplist<>''
  242.       parse value helplist with helpindex '+' helplist
  243.  
  244.       /* look for the help index file in current dir, EPMPATH, DPATH, and EPM.EXE's dir: */
  245.       findfile destfilename, helpindex, '','D'
  246.  
  247.       if rc then
  248.          /* If that fails, try the standard path. */
  249.          findfile destfilename, helpindex, 'PATH'
  250.          if rc then
  251.             sayerror  'Help index 'helpindex' not found'
  252.             iterate
  253.          endif
  254.       endif
  255. compile if EVERSION >='5.50'
  256.       if pos(' ',destfilename) then
  257.          destfilename = '"'destfilename'"'  -- HPFS support
  258.       endif
  259. compile endif
  260.       if helpindex_id then
  261.          /* append to help index */
  262.          bottom
  263.          last = .last
  264.          'get' destfilename
  265.       else
  266.          /* load first help index */
  267.          'xcom e /d' destfilename
  268.          getfileid helpindex_id
  269.          .visible = 0
  270.       endif
  271.    enddo
  272.    return
  273.  
  274.  
  275. /************************************************************************/
  276. -- SearchSections(string, filetype, line, col)
  277. --
  278. -- The NDX file(s) are sectioned with the "EXTENSIONS" tags, which
  279. -- specify which file types the section applies to.  This procedure will
  280. -- search all sections matching the specified file type.  If ftype=''
  281. -- then all sections are searched.  (* as an extension means the section
  282. -- applies to all file types).
  283. --
  284. -- returns 1 if a match was found (loaction is in line & col)
  285. -- returns 0 if no match was found
  286. /************************************************************************/
  287. defproc SearchSections(string, ftype, var line, var col)
  288.  
  289.    search = 'xcom L ~EXTENSIONS:~e+'
  290.  
  291.    /* find first section */
  292.    top; .col = 1
  293.    getfileid fileid
  294.    search
  295.    if rc then
  296.       return 0  -- no sections?!
  297.    endif
  298.    startline = .line
  299.    startcol = .col
  300.    /* get list of extensions, padded on both sides with space */
  301.    ext = upcase(' '||substr(textline(.line), .col+11)||' ')
  302.  
  303.    more = 1
  304.    do while more
  305.  
  306.       /* move to next match or bottom */
  307.       down  -- move past this match
  308.       search
  309.       if rc then
  310.          bottom  -- last section
  311.          more = 0
  312.       endif
  313.       nextline = .line
  314.       nextcol = .col
  315.  
  316.       /* search this section if it applies */
  317.       if (ftype='') or (pos(' '||upcase(ftype)||' ', ext)>0) then
  318.  
  319.          call pset_mark(startline, nextline, 1, 1, 'LINE', fileid)
  320.          .line = startline  -- move to start of mark
  321.          .col = startcol
  322.          if LocateIndexEntry(string, line, col) then
  323.             return 1  -- found a match in this section
  324.          endif
  325.       endif
  326.  
  327.       /* move to next match */
  328.       if more then
  329.          .line = nextline
  330.          .col = nextcol
  331.          startline = nextline
  332.          startcol = nextcol
  333.          ext = upcase(' '||substr(textline(.line), .col+11)||' ')
  334.       endif
  335.  
  336.    enddo
  337.    return 0  -- not found
  338.  
  339.  
  340. /************************************************************************/
  341. -- LocateIndexEntry(topic, line, col)
  342. --
  343. -- Searches the marked area of an NDX file for a matching entries.  After
  344. -- looking for an exact (case-insensitive) match, it tries all possible
  345. -- prefixes.
  346. --
  347. -- Returns 1 for index entry match (at line, col)
  348. /************************************************************************/
  349. defproc LocateIndexEntry(topic, var line, var col)
  350.  
  351.    if LocateBestCase('('topic',', line, col) then
  352.       return 1  -- found match
  353.    endif
  354.    do i = length(topic) to 0 by -1
  355.       if LocateBestCase('('leftstr(topic, i)'*,', line, col) then
  356.          return 1  -- found prefix match
  357.       endif
  358.    enddo
  359.    return 0  -- sorry, no match
  360.  
  361.  
  362. /************************************************************************/
  363. -- LocateBestCase(string, line, col)
  364. --
  365. -- Search the marked area for the specified string.  Return location of
  366. -- a case sensitive match in 'line' and 'col', otherwise case insensitive.
  367. -- The return value is 1 if a string was found, 0 otherwise.
  368. -- Assumes that starting location is at the start of the marked area
  369. /************************************************************************/
  370. defproc LocateBestCase(string, var line, var col)
  371.  
  372.    top; .col = 1
  373.    line = ''  -- flag none found yet
  374.    rc = 0
  375.    do while not rc
  376.       'xcom L ~'string'~cm+'  -- find next match in this section
  377.       if not rc then
  378.          line = .line  -- save match location
  379.          col = .col
  380.          if string = substr(textline(.line), .col, length(string)) then
  381.             return 1  -- found an exact (same case) match
  382.          endif
  383.       endif
  384.       right -- move beyond this match
  385.    enddo
  386.    if line = '' then
  387.       return 0  -- no matches found
  388.    else
  389.       return 1  -- use last match (case insensitive)
  390.    endif
  391.  
  392.