home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / HISTORY.PEL < prev    next >
Text File  |  1995-03-31  |  28KB  |  1,005 lines

  1. # $Header:   P:\source\wmacros\history.pev   1.63.1.0   31 Mar 1995 16:23:52   WALKER  $
  2. ## $Tabs:4 7$
  3.  
  4. ##############################################################################
  5. #
  6. #       Compuware Corporation
  7. #         31440 Northwestern Highway
  8. #           Farmington Hills, Michigan 48334-2564
  9. #
  10. #   This source code listing contains information that is
  11. #   proprietary to Compuware Corporation and may not be copied
  12. #   duplicated, translated, transmitted, stored, retrieved
  13. #   or in any manner or by any method conveyed or disclosed
  14. #   to a third party or parties without express written
  15. #   permission from Compuware Corporation.
  16. #
  17. #  
  18. ##############################################################################
  19.  
  20. #### $Workfile:   history.pel  $: Response history support
  21.  
  22. local   historyArray
  23. local   historyName
  24. local   historyElement
  25. local   historyPromptString  # current prompt string displayed by prompt_history
  26.  
  27. local writeConfigArray[]
  28.  
  29. global  edit_file_dir = 1  # set to 1 to display dir list from edit_file_key()
  30. global  MAX_HISTORY   = 10
  31. global  history_font  = -1 # Font to use for History List,
  32.                            # Default is FONT_MODERN8
  33.  
  34. # This function will return an array containing the history of a
  35. # specified type of history given an index into the history array, 
  36. function history_config( index )
  37. {
  38.    local i           = 0
  39.    local end         = (index 0 in historyArray) ? historyArray[index 0] : 0
  40.  
  41.    local data_index  = 1
  42.    local data[]
  43.  
  44.    local word = "";
  45.    
  46.    if (writeConfigArray[index] != 1)
  47.       return;
  48.  
  49.    #
  50.    # check to make sure something is in array
  51.    #
  52.    if (!(index i in historyArray))
  53.       historyArray[ index i ] = i;
  54.    
  55.    # 
  56.    # Write list to file
  57.    #
  58.    if ( end > MAX_HISTORY )
  59.       i = end - MAX_HISTORY 
  60.    
  61.    while ( (i=i+1) <= end )
  62.    {
  63. #     gsub("\"", "'", historyArray[index i] )
  64.       word = historyArray[index i];
  65.  
  66.       #  Although this line appears to be pointless, it fixes the problem
  67.       #  of actual new lines being written to the config file.
  68.       gsub("\\n", "\\n", word);
  69.  
  70.       data[ data_index++ ] = sprintf(  "add_prompt_history %s \"%s\"\n", 
  71.                                        index, 
  72.                                        quote_quote(quote_regex( word )) )
  73.    }
  74.    data[ data_index++ ] = sprintf( "\n" )
  75.    return data   
  76. }
  77.  
  78. global function get_history_list(history_name)
  79. {
  80.    local end
  81.    local i = 0
  82.    local data[]
  83.    local retval = ""
  84.  
  85.    setup_prompt_history( history_name )
  86.    end = (history_name 0 in historyArray) ? historyArray[history_name 0] : 0
  87.  
  88.    if (history_name i in historyArray)
  89.    {
  90.       data = history_config( history_name )
  91.    
  92.       for ( i = 1; i < end; i++ ) 
  93.       { 
  94.          retval = retval historyArray[history_name i] "^"
  95.       }
  96.    }
  97.  
  98.    return retval
  99. }
  100.  
  101. local IDM_ADD_EDITFILE = 0x300
  102. global function add_editfile_to_menu()
  103. {
  104.    local main_menu = menu_info(0, MI_MENUHANDLE)
  105.    local menu = menu_info( main_menu, MI_MENUHANDLE, IDM_FILE )
  106.    local menu_id = IDM_ADD_EDITFILE
  107.    local MAX_ITEMS = 5
  108.    local history_name = "EDITFILE"
  109.    local end
  110.    local i = 0
  111.    local count = 1
  112.    local data[]
  113.  
  114.    delete_event(EVENT.NEW_EDIT_FILE, "add_editfile_to_menu")
  115.    attach_event_handler(EVENT.NEW_EDIT_FILE, "add_editfile_to_menu")
  116.  
  117.    setup_prompt_history( history_name )
  118.    end = (history_name 0 in historyArray) ? historyArray[history_name 0] : 0
  119.  
  120.    if (!(history_name i in historyArray))
  121.       return
  122.  
  123.    data = history_config( history_name )
  124.  
  125.    for ( i = menu_id; i <= menu_id + MAX_ITEMS; i++ )
  126.       delete_menuitem(main_menu, i)
  127.  
  128.    for ( i = end; i > 0 && i > end - MAX_ITEMS; i-- ) 
  129.    { 
  130.       insert_menuitem(menu, menu_id, IDM_EXIT, MI_MENUITEM, "~" count++ " " historyArray[history_name i] )
  131.       menu_functions[menu_id] = "create_buf_and_win " historyArray[history_name i]
  132.       menu_id++
  133.    }
  134.  
  135.    insert_menuitem(menu, menu_id++, IDM_EXIT, MI_SEPARATOR )
  136. }
  137.  
  138. #------------------------------------------------------------------#
  139. ##      prompt_history()
  140. #
  141. # Prompt the user for a string and process all illegally typed characters
  142. # through the _bad_prompt_key() function.  The parameters passed are as
  143. # follows:
  144. #
  145. #       index     - a string identifying which history stack to use
  146. #       promptstr - first parameter to prompt()
  147. #       defaultstr- second parameter to prompt()
  148. #       usehistory- if defaultstr == "" and usehistory == 1, use the
  149. #                   last history item
  150. #
  151. # Example:
  152. #       prompt_history( "SEARCH", "Search for: ", "noname" )
  153. #
  154. #       Each time this is called an a valid input string is entered
  155. #       and returned by prompt(), it is added to the history stack
  156. #       and subsequent calls can access this stack.
  157. #
  158. global function setup_prompt_history(index, element)
  159. {
  160.    local   patt
  161.    local   i     = 0;
  162.    local   id    = function_id( "_bad_prompt_key" );
  163.  
  164.    # don't setup a history twice
  165.    #
  166.    if ( index == historyName)
  167.       return
  168.  
  169.    #
  170.    #  initialize historyArray in need to
  171.    #
  172.    if (!(index i in historyArray))
  173.    {
  174.       historyArray[ index i ] = i;
  175.  
  176.       writeConfigArray[index] = 1
  177.       read_config_section("$" index "_HISTORY$")
  178.    }
  179.    #
  180.    # let the command history functions know where to find
  181.    # the command history for this specified call.
  182.    #
  183.    historyName = index;
  184.    historyElement = element ? -1 : 0;
  185.  
  186.    # install an event handler to make history
  187.    # available to the prompt function.
  188.    # only needs to be installed once
  189.    #
  190.    delete_event( EVENT.INVALID_PCHAR, id )
  191.    attach_event_handler( EVENT.INVALID_PCHAR, id )
  192.  
  193. }
  194.  
  195. global function prompt_history( index, promptstr, defaultstr, usehistory, highlight, helpid ) 
  196. {
  197.    local patt
  198.  
  199.    if ( argcount() < 5 )
  200.       highlight = TRUE
  201.  
  202.    setup_prompt_history( index )
  203.  
  204.    historyElement = defaultstr ? -1 : 0;
  205.    #
  206.    # prompt for the search pattern and provide command history
  207.    #
  208.    if ((historyElement == 0) && (usehistory))
  209.    {
  210.       defaultstr = current_history_item( index );
  211.       historyElement = -1;
  212.    }
  213.  
  214.    if (!helpid)
  215.       helpid = "default_prompt"
  216.    patt = prompt( historyPromptString = promptstr, defaultstr, helpid, highlight )
  217.  
  218.    cleanup_prompt_history();
  219.  
  220.    return patt;
  221. }
  222.  
  223. global function cleanup_prompt_history()
  224. {
  225.    delete_event( EVENT.INVALID_PCHAR, function_id( "_bad_prompt_key" ) )
  226.  
  227.    if ( historyName == "SEARCH" )
  228.       optional_function("delete_regex_table")
  229.  
  230.    historyName = ""
  231. }
  232.  
  233. # This function is useful for those edit controls in dialogs that may
  234. # cause a DM_INVALID_PCHAR message because they want to use history
  235. # features
  236. #
  237. function dialog_history( dlgHand, dlgId, histName )
  238. {
  239.    local old_prompt_response
  240.  
  241.    prompt_response = query_dialog_item(dlgHand, dlgId, DAC_EDIT_TEXT)
  242.       
  243.    # save prompt_response before the we execute the event
  244.    #
  245.    old_prompt_response = prompt_response
  246.  
  247.    setup_prompt_history( histName, prompt_response )
  248.  
  249.    execute_event_handler( EVENT.INVALID_PCHAR )
  250.  
  251.    # only update edit box if any event handlers for EVENT.INVALID_PCHAR
  252.    # have changed the prompt_response variable.  Every time an edit box
  253.    # is updated the cursor is positioned at the end of the line.
  254.    if ( prompt_response != old_prompt_response )
  255.    {
  256.       set_dialog_item(dlgHand, dlgId, DAC_EDIT_TEXT, prompt_response "", 1)
  257.    }
  258.  
  259. }
  260.  
  261. ##      _bad_prompt_key()
  262. #
  263. # This is the event handler used to handle bad keys entered from the prompt
  264. # primitive.
  265. #
  266. # A few notes:
  267. #
  268. #    o  This function will receive any key which is not a simple upper
  269. #       or lower case letter, including <Enter>, <Spacebar>, <Ctrl-A> etc.
  270. #
  271. #    o  The "prompt_response" variable contains the current input string
  272. #       at the prompt.  This string can be modified in any manner and will
  273. #       be reflected at the prompt line.
  274. #
  275. #    o  The value of "current_key" will be processed when this function
  276. #       returns as if this function was never called.  If you wish that
  277. #       the key not be processed, set "current_key = 0"; or if you wish to
  278. #       replace it with a different key, set "current_key = <your_keycode>".
  279. #       For example, setting current_key to "KEYCODE_HOME" will cause the
  280. #       cursor to move to the beginning of the prompt response.
  281. #
  282. #    o  Setting current_key to the magic value -1 resets prompt() to its
  283. #       initial state, i.e. it highlights the current prompt_response value
  284. #       and places the cursor at the end of the response.  If the
  285. #       prompt_response variable is changed without setting current_key
  286. #       to -1, the cursor position will be left unchanged.
  287. #
  288. global function _bad_prompt_key()
  289. {
  290.    local   min = 0;
  291.    local   max, i
  292.    local   buffer;
  293.    local   tempArray[]
  294.    local   width = 20
  295.    local   response
  296.    local   help_word, start, end, parent
  297.    
  298.    if ( current_key == KEYCODE_TAB )
  299.    {
  300.       #
  301.       # if we are performing an invoke_function (F10) and a TAB
  302.       # was pressed, then display function listing
  303.       #
  304.       if (historyName == "XMACRO" || historyName == "ISPF")
  305.       {
  306.          displayFunctionList(historyName)
  307.          current_key = 0
  308.          return
  309.       }
  310.       # if we are performing an edit_file 
  311.       else if (historyName == "EDITFILE" || historyName == "SRCHFILES")
  312.       {
  313.          # save the prompt_display_handle since the following loop could
  314.          # bring up several dialogs and change the prompt_display_handle
  315.          parent = prompt_display_handle
  316.  
  317.          # continue displaying directory information as long as a directory
  318.          # is selected
  319.          while ( displayDirContents() && prompt_response ~ /\\$/ ) 
  320.          {}
  321.  
  322.          current_key = 0
  323.          return
  324.       }
  325.       else if(historyName == "BOOKMARKS")
  326.       {
  327.          displayMatchingBookmark();
  328.          current_key = 0;
  329.          return;
  330.       }
  331.    }
  332.    else if (current_key == KEYCODE_PAGEUP     || current_key == KEYCODE_PAGEDOWN ||
  333.             current_key == KEYCODE_NUM_PAGEUP || current_key == KEYCODE_NUM_PAGEDOWN )
  334.    {
  335.       # display history list
  336.       tempArray = get_history( historyName )
  337.  
  338.       for ( i in tempArray )
  339.          width = max(width, length(tempArray[i]))
  340.  
  341.       # i will be set to the last element and our list box is 0 based
  342.       select_index = i - 1
  343.  
  344.       response = prompt_selection( historyName " History List", width, tempArray )
  345.  
  346.       # reset select_index back to 0
  347.       select_index = 0
  348.       
  349.       if ( !response )
  350.          prompt_response = old_response
  351.       else 
  352.          prompt_response = response
  353.  
  354.       delete( tempArray )
  355.       current_key = -1  # highlight the string
  356.       return
  357.    }
  358. #   else if ( current_key == help_key )
  359.    else if ( current_key == 0x9020 )  # CTRL-F1
  360.    {
  361.       if ( historyName == "XMACRO" )
  362.       {
  363.          # initialize start to beginning of word
  364.          start = 1
  365.  
  366.          # if "?" is found, then start after it
  367.          if ( match(prompt_response, "\\?") == 1 )
  368.             start = 2
  369.  
  370.          # end the word at either a space or EOL
  371.          end       = match(prompt_response, " |$") - 1
  372.          help_word = trim(substr(prompt_response, start, end))
  373.  
  374.          display_help_item( help_word )
  375.       }
  376.       else if ( historyName == "SEARCH" )
  377.          display_help_item( "regexpr" )
  378.  
  379.       current_key = 0;
  380.       return;
  381.    }
  382.    else if (current_key == KEYCODE_ESC)
  383.    {
  384.       if ( status_bar_flags )
  385.          message("Command cancelled.")
  386.       return;
  387.    }
  388.    else if (current_key == KEYCODE_CTRL_R && historyName == "SEARCH" )
  389.       optional_function("display_regex_table")
  390.  
  391.    #
  392.    # is there something in the list?
  393.    #
  394.    max = historyArray[ historyName min ];
  395.    if (current_key == KEYCODE_DOWN || current_key == KEYCODE_NUM_DOWN)
  396.    {
  397.       # get previous command
  398.       if (max)
  399.          historyElement = (historyElement + 1) % max
  400.    }
  401.    else if (current_key == KEYCODE_UP || current_key == KEYCODE_NUM_UP)
  402.    {
  403.       # get next command
  404.       if (max)
  405.       {
  406.          if (historyElement <= 0)                # skip first entry if < 0
  407.             historyElement = max + historyElement;
  408.          if (historyElement)
  409.             historyElement--;
  410.       }
  411.    }
  412.    else if (int_to_key(current_key) == "<Alt-L>" || int_to_key(current_key) == "<Ctrl-L>" )
  413.    {
  414.       current_key = -1  # highlight the string
  415.       return
  416.    }
  417.    else if (int_to_key(current_key) == "<Alt-D>" || int_to_key(current_key) == "<Ctrl-D>" )
  418.    {
  419.       # remove the current item from the history list
  420.       #
  421.       delete_history_item( historyName, prompt_response )
  422.  
  423.       # then just fall through and allow the prompt_response to change
  424.    }
  425.    else if (int_to_key(current_key) == "<Enter>" )
  426.    {
  427.       if ( prompt_response )
  428.          add_prompt_history( historyName, prompt_response )
  429.  
  430.       return
  431.    }
  432.    else
  433.    {
  434.       #             
  435.       # Didn't find any keys that we want to handle so
  436.       # just return.
  437.       #
  438.       return;
  439.    }
  440.  
  441.    #
  442.    # read the response out of the buffer
  443.    #
  444.    # index was 0..n-1, it should be 1..n
  445.    current_key = 0;
  446.    if (max <= 0)
  447.       return;
  448.    else
  449.    {
  450.       prompt_response = historyArray[ historyName (historyElement + 1) ];
  451.       current_key = -1        # highlight the new prompt response
  452.    }
  453. }
  454.  
  455. # these function are here so historyElement doesn't need to be global
  456. #
  457. function get_history_element()
  458. {
  459.    return historyElement
  460. }
  461.  
  462. ## find an item in the command history array
  463. #
  464. global function current_history_item( index, i )
  465. {
  466.    i += 0
  467.    if (index i in historyArray)
  468.    {
  469.       i = historyArray[ index i ];
  470.       if (i)
  471.          return historyArray[ index i ];
  472.    }
  473.    return "";
  474. }
  475.  
  476. ## add an item to the command history array
  477. #
  478. global function add_prompt_history( index, patt )
  479. {
  480.    local i = 0;
  481.    local j = 0;
  482.    local promptCount = 0;
  483.    local found = 0;
  484.  
  485.    setup_prompt_history( index )
  486.  
  487.    # remove the item from list and just add it to the bottom
  488.    delete_history_item( index, patt )
  489.  
  490.    promptCount = historyArray[ index i ];
  491.  
  492.    historyArray[ index 0 ] = ++promptCount;
  493.  
  494.    # add patten to end of list
  495.    historyArray[ index promptCount ] = patt;
  496.  
  497.    cleanup_prompt_history()
  498.  
  499.    return patt
  500. }
  501.  
  502. # removes the specified pattern from the history list
  503.  
  504. function delete_history_item( histName, pattern )
  505. {
  506.    local j, i = 1
  507.    local promptCount = 0;
  508.    local found = 0;
  509.  
  510.    if (histName 0 in historyArray)
  511.       promptCount = historyArray[ histName 0 ] + 0
  512.  
  513.    # search the history list for the pattern
  514.    #
  515.    while (histName i in historyArray && i <= promptCount)
  516.    {  
  517.       if (historyArray[ histName i ]  == pattern)
  518.       {
  519.          found = i;
  520.          break
  521.       }
  522.       i = i + 1;
  523.    }
  524.    
  525.    # if the pattern was found, move the item after it up one place
  526.    #
  527.    if ( found )
  528.    {
  529.       i = found
  530.       while (i < promptCount)
  531.       {
  532.          j = 1 + i
  533.          historyArray[histName i] = historyArray[histName j]
  534.          i = i + 1
  535.       }
  536.  
  537.       delete historyArray[ histName promptCount ]
  538.       historyArray[ histName 0 ] = --promptCount
  539.    }
  540.  
  541.    return found
  542. }
  543.  
  544.  
  545. function get_history( index )
  546. {
  547.    local temp
  548.    local i = 0
  549.    
  550.    while ( ++i <= historyArray[index 0] )
  551.    {
  552.       temp[i] = historyArray[index i]
  553.    }
  554.  
  555.    return temp
  556. }
  557.  
  558. #--------- display list of functions and allow movement within it --------#
  559.  
  560.  
  561. ## displayFunctionList()
  562. #
  563. # Display all of the functions available which start with
  564. # the pattern specified of at least two characters (zero or one might
  565. # take too long)
  566. #
  567. global  symbol_list
  568.  
  569. local function displayFunctionList(historyName)
  570. {
  571.    local   i
  572.    local   fid
  573.    local   prefix
  574.    local   result
  575.    local   searchFor
  576.    local   numOfEntries
  577.    local   sorted_symbol_list
  578.    local   symbolMatchFlag = PRIMITIVE_ALL + GLOBAL_ALL
  579.    local   width = 20
  580.    local   listdlg
  581.    current_key = 0
  582.    
  583.    # extract question mark
  584.    if ( substr( prompt_response, 1, 1 ) == "?" )
  585.    {
  586.       prefix = "?"
  587.       searchFor = substr( prompt_response, 2 )
  588.    }
  589.    else
  590.    {
  591.       searchFor = prompt_response
  592.       # uncomment the following line to omit variables from
  593.       # <F10> command completion (if no "?" is present)
  594.       # symbolMatchFlag = PRIMITIVE_FUN + GLOBAL_FUN
  595.    }
  596.  
  597.    # in case symbol_match takes a long time
  598.    if ( status_bar_flags )
  599.       message( "Working..." )
  600.    # read a list of all symbols beginning with the specified pattern
  601.    if ( length( searchFor ) < 2 )
  602.    {
  603.       if ( status_bar_flags )
  604.          message( "Must type at least two characters." )
  605.       beep()
  606.       return
  607.    }
  608.    else if (!(symbol_list = symbol_match( searchFor, symbolMatchFlag )) )
  609.    {
  610.       if ( status_bar_flags )
  611.          message( "no matching symbols found." )
  612.       beep()
  613.       return
  614.    }
  615.  
  616.    if ( status_bar_flags )
  617.       message( "" )
  618.  
  619.    # Add emulation-specific commands.
  620.    optional_function( tolower(historyName) "_commands", searchFor )
  621.  
  622.    # how many did we get?
  623.    for (i in symbol_list)
  624.    {
  625.       sorted_symbol_list[ symbol_list[i] ] = numOfEntries++
  626.       width = max(width, length(symbol_list[i]))
  627.    }
  628.  
  629.    if ( numOfEntries == 0 )              # no match
  630.       beep()
  631.  
  632.    else if ( numOfEntries == 1 )         # only one match
  633.    {
  634.       new_response = prefix symbol_list[i]
  635.       current_key = KEYCODE_END
  636.    } 
  637.    else
  638.    {
  639.       # create a dialog box for the list
  640.       listdlg = create_selection_dialog( "Command List", width )
  641.       
  642.       # fill the list box 
  643.       for (i in sorted_symbol_list)
  644.       {
  645.          #add items to list box
  646.          set_dialog_item( listdlg, IDL_LIST, DAC_ADD_ITEM, prefix i )
  647.       }
  648.       begin_dialog(listdlg)
  649.       delete_dialog(listdlg)
  650.    }
  651.  
  652.    if ( !new_response )
  653.       prompt_response = old_response
  654.    else 
  655.       prompt_response = new_response
  656.  
  657.    delete( symbol_list )           # deallocate the arrays
  658.    delete( sorted_symbol_list )
  659. }
  660.  
  661. #--------- display directory specified and allow movement within it --------#
  662.  
  663.  
  664. ## displayDirContents()
  665. #
  666. # Display all of the files in the current directory which start with
  667. # the pattern specified of *.* if none.
  668. #
  669. # Maybe add changing directories and other items later.
  670. #
  671.  
  672. local function displayDirContents( parent )
  673. {
  674.    local   fname
  675.    local   numOfEntries = 0        # number of files in current directory
  676.    local   lastname
  677.    local   prompt_start
  678.    local   l,r,c,i
  679.    local   srchname, tmp
  680.    local   insert_prev_dir = FALSE
  681.    local   find_flags, dir_list, file_list
  682.    local   dirInfo = ""
  683.    local   maxWidth = 20
  684.    local   ft, status
  685.    local   listdlg
  686.  
  687.    prompt_start = prompt_response
  688.    l = rindex( prompt_start, "\\" )
  689.    r = rindex( prompt_start, "/" )
  690.    c = rindex( prompt_start, ":" )
  691.    l = l > r ? l : r
  692.    l = l > c ? l : c
  693.    prompt_start = prefix( prompt_start, l )
  694.  
  695.    #
  696.    # read in all of normal file names from the current directory
  697.    # and insert them into the current_buffer
  698.    #
  699.    srchname = prompt_response
  700.    if ( (!srchname) || (rindex(srchname, "?") != length( srchname )))
  701.    {
  702.       tmp = path_ext( srchname )
  703.       if ( !tmp )
  704.       {
  705.          if ( length(path_fname(srchname)) >= 8 )
  706.             srchname = srchname ".*"
  707.          else
  708.             srchname = srchname "*.*"
  709.       }
  710.       else
  711.       {
  712.          if ( length(tmp) < 4 )
  713.             srchname = srchname "*"
  714.       }
  715.    }
  716.  
  717.    find_flags = ONLY_SUBDIR            # include only directories
  718.  
  719.    # in case directory search takes a long time
  720.    if (status_bar_flags)
  721.       message( "Working..." )
  722.  
  723.    for (i=0; i < 2; i++)
  724.    {
  725.       fname = findfirst( srchname, find_flags )
  726.       fname = path_fname( fname ) path_ext( fname )
  727.  
  728.       while (fname)
  729.       {
  730.          if (i == 0)
  731.          {
  732.             lastname = fname "\\"
  733.             if ( edit_file_dir )
  734.             {
  735.                ft = filetime()
  736.                dirInfo = sprintf( "  <DIR>  %8s  %8s  %s", dos_date(ft), dos_time(ft), lastname)
  737.             }
  738.             else
  739.                dirInfo = lastname
  740.  
  741.             dir_list[ toupper(lastname) ] = dirInfo
  742.             maxWidth = max(length(dirInfo), maxWidth)
  743.          }
  744.          else
  745.          {
  746.             lastname = tolower(fname)
  747.             if ( edit_file_dir )
  748.             {
  749.                if ( filesize() >= 0 )
  750.                {
  751.                   ft = filetime()
  752.                   dirInfo = sprintf( "%7d  %8s  %8s  %s", filesize(), dos_date(ft), dos_time(ft), lastname)
  753.                }
  754.             }
  755.             else 
  756.                dirInfo = lastname
  757.  
  758.             file_list[ lastname ] = dirInfo 
  759.             maxWidth = max(length(file_list[lastname]), maxWidth)
  760.          }
  761.          numOfEntries++
  762.          fname = findnext()
  763.       }
  764.       find_flags = _NORMAL           # include normal files
  765.    }
  766.  
  767.    if (".\\" in dir_list){
  768.       numOfEntries--;
  769.       delete( dir_list[ ".\\" ] )
  770.    }
  771.  
  772.    if ( numOfEntries == 0 )
  773.    {
  774.       # no files match the file pattern
  775.       if ( status_bar_flags )
  776.          message( "No match found." )
  777.       current_key = 0;
  778.       beep();
  779.       return;
  780.    }
  781.    else if ((numOfEntries == 1) && (!insert_prev_dir))
  782.    {
  783.       if ( status_bar_flags )
  784.          message( "" )
  785.       #
  786.       # only one file that matched, just set the prompt response
  787.       # and return
  788.       #
  789.       prompt_response = prompt_start lastname;
  790.       current_key = KEYCODE_END
  791.       return;
  792.    }
  793.  
  794.    if ( status_bar_flags )
  795.       message( "" )
  796.  
  797.    if (status_bar_flags)
  798.       message( "File: " prompt_response )
  799.  
  800.    # create a dialog box with the dir list
  801.    listdlg = create_selection_dialog( "File List", maxWidth, dir_list, parent )
  802.    
  803. #   for (i in dir_list)
  804. #   {
  805. #      # fill the list box 
  806. #      set_dialog_item( listdlg, IDL_LIST, DAC_ADD_ITEM, dir_list[i] )
  807. #   }
  808.  
  809.    # now add the file_list
  810.    for (i in file_list)
  811.    {
  812.       # fill the list box 
  813.       set_dialog_item( listdlg, IDL_LIST, DAC_ADD_ITEM, file_list[i])
  814.    }
  815.  
  816.    begin_dialog(listdlg)
  817.    delete_dialog(listdlg)
  818.  
  819.    # new_response won't have a value if we cancelled from 
  820.    # the above dialog.  We will save this value and return it
  821.    status = !!new_response
  822.  
  823.    if ( edit_file_dir )
  824.    {
  825.       if(!status)
  826.          prompt_response = old_response
  827.       else
  828.          prompt_response = prompt_start substr(new_response, 30)
  829.    }
  830.    else
  831.       prompt_response = prompt_start new_response
  832.  
  833.    delete dir_list
  834.    delete file_list
  835.    
  836.    return status
  837. }
  838.  
  839. function displayMatchingBookmark()
  840. {
  841.    local count = 0, i, name, pos;
  842.    local length = length(prompt_response);
  843.    local dhMark, mark_list;
  844.  
  845.    mark_list = build_bookmark_list()
  846.    for(name in mark_list)
  847.    {
  848.       if(substr(name, 1, length) == prompt_response)
  849.       {
  850.          count++;
  851.       }
  852.       else
  853.          delete mark_list[name]
  854.    }
  855.    if(count == 1)
  856.    {
  857.       current_key = KEYCODE_END;
  858.       new_response = mark_list[name];
  859.    }
  860.    else if(count > 1)
  861.    {
  862.       dhMark = create_selection_dialog("Bookmarks", 0, mark_list);
  863.       begin_dialog(dhMark);
  864.       delete_dialog(dhMark);
  865.    }
  866.    else
  867.       beep();
  868.  
  869.    if ( !new_response ) 
  870.       prompt_response = old_response
  871.    else
  872.    {
  873.       pos = match(new_response, ":");
  874.       prompt_response = substr(new_response, 1, pos-1);
  875.    }
  876. }
  877.  
  878. function prompt_selection(title, width, list, parent, sort)
  879. {
  880.    local dlgid = create_selection_dialog(title, width, list, parent, sort)
  881.    begin_dialog( dlgid )
  882.    delete_dialog( dlgid )
  883.    return new_response
  884. }                
  885.  
  886. # The following variables are used as storing results from the 
  887. # history list selection dialog.  These values are later used
  888. # to set prompt_response depending on how the dialog box was
  889. # ended.
  890. local  old_response      # response before dialog was invoked
  891. global new_response      # response selected from dialog box
  892.  
  893. function create_selection_dialog(title, width, list, parent, sort)
  894. {
  895.    local cursize, i
  896.    local dhFile
  897.  
  898.    # if no parent is specified, default to the the prompt_display_handle
  899.    if ( !parent ) 
  900.       parent = prompt_display_handle
  901.  
  902.    new_response = ""
  903.  
  904.    old_response = prompt_response
  905.  
  906.    # create a dialog box for the list
  907.    #
  908.    dhFile = create_dialog( function_id("selection_list_callback"), 
  909.                            parent, IDD_LIST, resource_dll, title )
  910.    
  911.    #add the list box
  912.    add_dialog_item( dhFile, IDL_LIST,  DCTRL_LIST_BOX )
  913.    if (sort == 2)
  914.       set_dialog_item( dhFile, IDL_LIST, DAC_SORT_DESCENDING )
  915.    else if (sort)
  916.       set_dialog_item( dhFile, IDL_LIST, DAC_SORT_ASCENDING )
  917.    add_dialog_item( dhFile, DI_OK,     DCTRL_DEFAULT_PUSH_BUTTON )
  918.    add_dialog_item( dhFile, DI_CANCEL, DCTRL_PUSH_BUTTON )
  919.    save_button_positions(dhFile)
  920.  
  921.    if (history_font)
  922.       set_dialog_item( dhFile, IDL_LIST, DAC_FONT, history_font+0, FONT_NORMAL)
  923.  
  924.    set_dialog_window( dhFile, DWC_SIZEBORDER )
  925.  
  926.    if ( width )
  927.    {
  928.       width = min(500, width * 12)
  929.       cursize = query_dialog_window(dhFile, DWC_SIZE)
  930.       set_dialog_window(dhFile, DWC_SIZE, width, cursize % 65536 )
  931.    }
  932.  
  933.  
  934.    # fill the list box 
  935.    if ( list )
  936.       for (i in list)
  937.          set_dialog_item( dhFile, IDL_LIST, DAC_ADD_ITEM, list[i])
  938.  
  939.    return dhFile
  940. }
  941.  
  942. local select_index = 0
  943. function selection_list_callback()
  944. {
  945.    local new_width, new_height
  946.  
  947.    if ( callback_msg == DM_INIT )
  948.    {
  949.       set_dialog_item(callback_dialog_handle, IDL_LIST, DAC_SETFOCUS)
  950.       set_dialog_item(callback_dialog_handle, IDL_LIST, DAC_SELECT_INDEX, select_index)
  951.    }
  952.    else if ( callback_msg == DM_OK || callback_msg == DM_DOUBLE_CLICK )
  953.    {
  954.       # get the response from the list box and store in temporary spot
  955.       # so we can clean it up if we have to
  956.       new_response = query_dialog_item(callback_dialog_handle, IDL_LIST, DAC_SELECT_ITEM )
  957.       
  958.       return DRC_EXIT
  959.    }
  960.    else if ( ( callback_msg == DM_CLICK && callback_index == DI_CANCEL ) \
  961.             || callback_msg == DM_CANCEL)
  962.    {
  963.       new_response = ""
  964.       return DRC_EXIT
  965.    }
  966.    else if ( callback_msg == DM_RESIZE )
  967.    {
  968.       # new size is stored in a long as (short width)(short height)
  969.       new_width  = callback_data / 65536
  970.       new_height = callback_data % 65536
  971.       
  972.       if ( new_width && new_height )
  973.       {
  974.          # resize list box to match new dialog size
  975.          set_dialog_item(callback_dialog_handle, IDL_LIST, DAC_SIZE,
  976.                          new_width - 40, new_height - 120 )
  977.  
  978.          # Move the buttons for Windows.
  979.          if (isWindows())
  980.          {
  981.             set_dialog_item(callback_dialog_handle, DI_OK, DAC_POSITION,
  982.                             button_pos[DI_OK] / 65536,
  983.                             button_pos[DI_OK] % 65536)
  984.    
  985.             set_dialog_item(callback_dialog_handle, DI_CANCEL, DAC_POSITION,
  986.                             button_pos[DI_CANCEL] / 65536,
  987.                             button_pos[DI_CANCEL] % 65536)
  988.          }
  989.       }
  990.       return DRC_MSG_PROCESSED
  991.    }
  992.    return DRC_CONTINUE
  993. }              
  994.  
  995. local button_pos[]
  996. local function save_button_positions(handle)
  997. {
  998.    if (isWindows())
  999.    {
  1000.       button_pos[DI_OK]     = query_dialog_item( handle, DI_OK,     DAC_POSITION)
  1001.       button_pos[DI_CANCEL] = query_dialog_item( handle, DI_CANCEL, DAC_POSITION)
  1002.    }
  1003. }
  1004.  
  1005.