home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / NUCLEUS.PEL < prev    next >
Text File  |  1995-03-22  |  58KB  |  2,275 lines

  1. # $Header:   P:\source\wmacros\nucleus.pev   1.158   22 Mar 1995 13:45:32   pfhmlw0  $
  2.  
  3. ##############################################################################
  4. #
  5. #       Compuware Corporation
  6. #         31440 Northwestern Highway
  7. #           Farmington Hills, Michigan 48334-2564
  8. #
  9. #   This source code listing contains information that is
  10. #   proprietary to Compuware Corporation and may not be copied
  11. #   duplicated, translated, transmitted, stored, retrieved
  12. #   or in any manner or by any method conveyed or disclosed
  13. #   to a third party or parties without express written
  14. #   permission from Compuware Corporation.
  15. #
  16. #  
  17. ##############################################################################
  18.  
  19. #### $Workfile:   nucleus.pel  $: manifest constants and core utilities
  20.  
  21. # reserved global variables
  22.  
  23. global TRUE     = 1
  24. global FALSE    = 0
  25. global UNINITIALIZED = "uninitialized"
  26.  
  27. global backup_files_enabled;
  28.  
  29. global testmode              = 0; # Editor was started in test mode.
  30.  
  31.         ## DOS file attributes:
  32. global FILEMODE_NORMAL          = 0x00000021
  33. global _READ_ONLY               = 0x00000001
  34. global _HIDDEN                  = 0x00000002
  35. global _SYSTEM                  = 0x00000004
  36. global _VOL_ID                  = 0x00000008 # Not valid for OS/2
  37. global _SUBDIR                  = 0x00000010
  38. global _ARCHIVE                 = 0x00000020
  39. global _NORMAL                  = 0x00000021
  40.  
  41. global ONLY_READ_ONLY           = 0x00000101
  42. global ONLY_HIDDEN              = 0x00000202
  43. global ONLY_SYSTEM              = 0x00000404
  44. global ONLY_VOL_ID              = 0x00000808 # Not valid for OS/2
  45. global ONLY_SUBDIR              = 0x00001010
  46. global ONLY_ARCHIVE             = 0x00002020
  47.  
  48.         ## Event numbers:
  49. global EVENT        
  50. local  EVENT_setup = setup_events()
  51.  
  52. global function setup_events()
  53. {
  54.    EVENT.EMULATION_CHANGED      = 9
  55.    EVENT.IDLE_TIME              = 10
  56.    EVENT.CTRL_BREAK             = 11
  57.    EVENT.INVALID_PCHAR          = 12
  58.    EVENT.UNASSGN_KEY            = 13
  59.    EVENT.NEW_EDIT_FILE          = 14
  60.    EVENT.NEW_CURNT_BUFFER       = 15
  61.    EVENT.NEW_CURNT_WINDOW       = 16
  62.    EVENT.HELP_INVOKED           = 17
  63.    EVENT.IDLE_THRESHOLD         = 18
  64.    EVENT.EXIT_EDITOR            = 19
  65.    EVENT.TEMP_SPACE_OVFLW       = 20
  66.    EVENT.EDIT_FILE_SAVE         = 21
  67.    EVENT.KEYPRESS               = 22
  68.    EVENT.READ_ONLY_MOD          = 23
  69.    EVENT.NEW_SCREEN_SIZE        = 24
  70.    EVENT.NEW_CURNT_SCREEN       = 25   #  (Reserved)
  71.    EVENT.DISPLAY_UPDATE         = 26
  72.    EVENT.PROCESS_COMPLETE       = 27
  73.    EVENT.MOUSE_LEFT_DOWN        = 28
  74.    EVENT.MOUSE_RIGHT_DOWN       = 29
  75.    EVENT.MOUSE_MID_DOWN         = 30
  76.    EVENT.MOUSE_LEFT_UP          = 31
  77.    EVENT.MOUSE_RIGHT_UP         = 32
  78.    EVENT.MOUSE_MID_UP           = 33
  79.    EVENT.MOUSE_LEFT_CLICK1      = 34
  80.    EVENT.MOUSE_RIGHT_CLICK1     = 35
  81.    EVENT.MOUSE_MID_CLICK1       = 36
  82.    EVENT.MOUSE_LEFT_CLICK2      = 37
  83.    EVENT.MOUSE_RIGHT_CLICK2     = 38
  84.    EVENT.MOUSE_MID_CLICK2       = 39
  85.    EVENT.INSERT_KEY             = 40
  86.    EVENT.INSERT_STRING          = 41
  87.    EVENT.DELETE_CHARS           = 42
  88.    EVENT.INSERT_NEWLINE         = 43
  89.    EVENT.SHELL_EXIT             = 44
  90.    EVENT.FUNCTION_CHANGED       = 45
  91.    EVENT.DELETING_BUFFER        = 46
  92.    EVENT.DELETING_WINDOW        = 47
  93.    EVENT.SYSTEM_MENU_KEY        = 48
  94.    EVENT.WINDOW_MODE_CHANGE     = 49
  95.    EVENT.BUFFER_CREATED         = 50
  96.    EVENT.CPM                    = 51
  97.    EVENT.ERROR                  = 52   #  (Reserved)
  98.                                 
  99.    EVENT.LMOUSE_DRAG            = 53
  100.    EVENT.MMOUSE_DRAG            = 54
  101.    EVENT.RMOUSE_DRAG            = 55
  102.                                 
  103.    EVENT.RESIZE_EDITWIN         = 56
  104.                                  
  105.    EVENT.SCROLL_HORZ            = 57
  106.    EVENT.SCROLL_VERT            = 58
  107.                                 
  108.    EVENT.NEW_EMPTY_BUFFER       = 59
  109.    EVENT.KEYPRESS_AFTER         = 60
  110.    EVENT.EDITOR_RUNNING         = 61
  111.                                 
  112.    EVENT.MENU_COMMAND           = 62
  113.    EVENT.TOOLBAR_COMMAND        = 63
  114.                                 
  115.    EVENT.PIPE_DATA              = 64
  116.    EVENT.FIRST_MOD              = 65
  117.    EVENT.CLOSING_REMOTE_WINDOW  = 66
  118.    EVENT.FILE_DROPPED           = 67
  119.    EVENT.UNMOD                  = 68
  120.    EVENT.UNABLE_TO_OPEN_FILE    = 69
  121.    EVENT.NEW_CURNT_EDITWIN      = 70
  122.    EVENT.ACTIVATE               = 71
  123.    EVENT.DEACTIVATE             = 72
  124.    EVENT.WINDOW_CREATED         = 73
  125.    EVENT.TRACKING_DONE          = 74
  126.  
  127.    EVENT_setup = 1; # prevent warning that EVENT_setup is not used!
  128.    return 1         # return someting
  129. }
  130.  
  131.  
  132. ## System file numbers:         (see locate_cpe_file)
  133. global CPE_FILE_CONFIG     = 1     # cpe.cfg
  134. global CPE_FILE_AE         = 2     # cpe.ae
  135. global CPE_FILE_BINDINGS   = 3     # bindings.txt
  136. global CPE_FILE_KEYMAP     = 4     # keymap.txt
  137. global CPE_FILE_LANGUAGE   = 5     # language.pel
  138. global CPE_FILE_INI        = 6     # cpe.ini
  139. global CPE_FILE_HELP       = 7     # cpe.hlp
  140.  
  141. ## System flags (for the system() primitive)
  142. global SYS_NONE      = 0x0000
  143. global SYS_SHELL     = 0x0002
  144. global SYS_ASYNC     = 0x0004
  145. global SYS_DETACHED  = 0x0008      # in Windows this is the same as SYS_ASYNC.
  146. global SYS_NOEXPOSE  = 0x0010
  147.  
  148. ## System flags (for the system() primitive) for OS/2 Only.
  149. global SYS_SESSION   = 0x0001
  150. global SYS_NOSESSION = 0x0020
  151. global SYS_QUIET     = 0x0100
  152. global SYS_DOSSHELL  = 0x0200
  153.  
  154. ## System flags (for the system() primitive) for Windows Only.
  155. global SYS_HIDE      = 0x0020
  156. global SYS_MAXIMIZE  = 0x0040
  157. global SYS_MINIMIZE  = 0x0080
  158.  
  159. # Pleae note that SYS_NOSESSION and SYS_HIDE both have similar effects,
  160. # the window is hidden in windows, a seperate session is NOT started and
  161. # therefore not viewable in OS/2.  (However, a PM or Full-Screen program
  162. # is started with SYS_NOSESSION set will still be visible, it will only
  163. # hide Windowed (Character-Mode) programs)
  164. #
  165. # If a DOS box is started by the system command in Windows, the SYS_HIDE,
  166. # SYS_MAXIMIZE, and SYS_MINIMIZE will only take affect if the _default.pif
  167. # file specifies minimized.  If it specifies full-screen the DOS box will
  168. # be full-screen and nothing can be done to alter that.
  169. #
  170. # If a Windows (or DOS) program is started using SYS_HIDE and SYS_ASYNC
  171. # is NOT set, Preditor may be locked forever as it waits for the program
  172. # to exit unless it exits by itself (since it will be hidden, it can NOT
  173. # be closed and it won't even show up in the Task-List!)
  174.  
  175. ## Operating system constants for use with the isWindows() function
  176. global OS2     = 0
  177. global WINDOWS = 1
  178. global WIN_OS2 = 2
  179.  
  180. ## count_command_line_files()
  181. #
  182. # count command line filenames
  183. #
  184. local  files_on_command_line = 0; # Counts # of files on command line.
  185. local  files_counted         = 0; # TRUE if the files have been counted.
  186. global start_editor_minimized = 0;
  187.  
  188. global function count_command_line_files()
  189. {
  190.    local arg, iarg, option
  191.  
  192.    if (!files_counted)
  193.    {
  194.       files_counted         = TRUE
  195.       files_on_command_line = 0
  196.  
  197.       for ( iarg=1; iarg<ARGC; iarg++ )
  198.       {
  199.          arg    = ARGV[iarg]
  200.          option = prefix(arg,1)
  201.          if ( option == "-" || option == "/")
  202.          {
  203.             arg = substr(arg,2)
  204.             option = prefix(arg,1)
  205.  
  206.             if ( option == "m" || option == "M" )
  207.                start_editor_minimized = 1
  208.  
  209.             while ( arg )
  210.             {
  211.                # Check options that accept arguments
  212.                if (cindex("fFlLPRgGaAcCiI", prefix(arg,1)))
  213.                {
  214.                   arg = substr(arg,2)
  215.                   if ( arg == "" )
  216.                      iarg++
  217.                   else
  218.                      arg = ""
  219.                }
  220.                else
  221.                   arg = substr(arg,2)
  222.             }
  223.          }
  224.          else
  225.             files_on_command_line++
  226.       }
  227.    }
  228.  
  229.    return files_on_command_line
  230. }
  231.  
  232. ## process_command_line()
  233. #
  234. # handle command line options and invoke edit_file on filenames
  235. #
  236. global function process_command_line()
  237. {
  238.    local   cmd_line_error
  239.    local   arg, iarg, i, option
  240.    local   recordKeysFile
  241.    local   playbackKeysFile
  242.    local   files_specified       = FALSE
  243.  
  244.    # process command line arguments one at a time
  245.  
  246.    for ( iarg=1; iarg<ARGC; iarg++ )
  247.    {
  248.       arg    = ARGV[iarg]
  249.       option = prefix(arg,1)
  250.  
  251.       if ( option == "-" || option == "/")
  252.       {
  253.          arg = substr(arg,2)
  254.  
  255.          while ( arg )
  256.          {
  257.             option = prefix(arg,1)
  258.             arg    = substr(arg,2)
  259.  
  260.             #
  261.             # invoke startup Function
  262.             #
  263.             if ( option == "f" || option == "F" )
  264.             {
  265.                if ( arg == "" )
  266.                     arg = ARGV[ ++iarg ]
  267.  
  268.                arg = trim( ltrim( arg ));
  269.                arg = trim( ltrim( arg, "\"" ), "\"" );
  270.  
  271.                execute_function( arg )
  272.                arg = ""
  273.             }
  274.             #
  275.             # Readonly option
  276.             #
  277.             else if ( option == "r" )
  278.             {
  279.                set_default_buffer_flag( BUFFER_READ_ONLY, TRUE )
  280.                toggle_buffer_flags( BUFFER_READ_ONLY, TRUE )
  281.             }
  282.             #
  283.             # Load PVCS group file
  284.             #
  285.             else if ( option == "l" || option == "L" )
  286.             {
  287.                if ( arg == "" )
  288.                     arg = ARGV[ ++iarg ]
  289.  
  290.                pvcs_get_group( arg );
  291.                arg = ""
  292.             }
  293.             #
  294.             # control-Z is eof option
  295.             #
  296.             else if ( option == "z" || option == "Z" )
  297.             {
  298.                default_buffer_eof_string = buffer_eof_string = chr( 26 )
  299.             }
  300.             #
  301.             # playback keys stored in key file
  302.             #
  303.             else if ( option == "P" )
  304.             {
  305.                playbackKeys = TRUE
  306.                if ( arg == "" )
  307.                     arg = ARGV[ ++iarg ]
  308.  
  309.                playbackKeysFile = arg
  310.                arg = ""
  311.             }
  312.             #
  313.             # save all keys to playback file
  314.             #
  315.             else if ( option == "R" )
  316.             {
  317.                recordKeys = TRUE
  318.                if ( arg == "" )
  319.                     arg = ARGV[ ++iarg ]
  320.  
  321.                recordKeysFile = arg
  322.                arg = ""
  323.             }
  324.             #
  325.             # start editor for WorkFrame communications
  326.             #
  327.             else if (option == "w" || option == "W" )
  328.             {
  329.                optional_function("initialize_wf_dde")
  330.             }
  331.             #
  332.             # start editor for DDE communications
  333.             #
  334.             else if (option == "d" || option == "D" )
  335.             {
  336.                optional_function("initialize_dde")
  337.             }
  338.             #
  339.             # Goto Line-number option.
  340.             #
  341.             else if ( option == "g" || option == "G" )
  342.             {
  343.                if ( arg == "" )
  344.                     arg = ARGV[ ++iarg ]
  345.  
  346.                goto_line( atoi(arg) );
  347.                arg = ""
  348.             }
  349.             #
  350.             # start editor in test mode
  351.             #
  352.             else if (option == "t" || option == "T" )
  353.             {
  354.                testmode = TRUE
  355.             }
  356.             #
  357.             # start editor minimized
  358.             #
  359.             else if (option == "m" || option == "M" )
  360.             {
  361.                start_editor_minimized = 1
  362.             }
  363.             else if (option == "n" || option == "N" )
  364.             {
  365.                # this parameter handled in the editor
  366.             }
  367.             #
  368.             # invoke awk function Library
  369.             # or Load Config file.
  370.             # or Load Ini file.
  371.             #
  372.             # specified filename is processed
  373.             # in C code so skip to the next argument
  374.             #
  375.             else if (option == "a" || option == "A" || \
  376.                      option == "c" || option == "C" || \
  377.                      option == "i" || option == "I" )
  378.             {
  379.                if ( arg == "" )
  380.                    iarg++
  381.  
  382.                arg = ""
  383.             }
  384.             #
  385.             # unrecognized switch character
  386.             #
  387.             else if (optional_function("xpp_command_line", option))
  388.             {
  389.             }
  390.             else if (optional_function("user_command_line", option))
  391.             {
  392.             }
  393.             else
  394.             {
  395.                cmd_line_error = "option " option " not recognized"
  396.                arg = ""
  397.             }
  398.          }
  399.       }
  400.       else
  401.       {
  402.          # treat arguments not beginning with "-" or "/" as filenames
  403.          create_buf_and_win(arg)
  404.          files_specified = TRUE
  405.          if (!files_counted)
  406.             files_on_command_line++
  407.       }
  408.    }
  409.  
  410.    files_counted = TRUE
  411.  
  412.    # make the first buffer in the list the current buffer
  413.    # if there were command-line files specified
  414.    if ( files_specified && mdi_mode != 2 )
  415.       next_buffer()
  416.  
  417.    # record/playback session support
  418.    if ( playbackKeys )
  419.       playbackKeysInitialize( playbackKeysFile )
  420.  
  421.    else if ( recordKeys )
  422.       recordKeysInitialize( recordKeysFile )
  423.  
  424.    display_update()        # so following messages show up
  425.  
  426.    if (cmd_line_error)
  427.       warning( cmd_line_error )
  428. }
  429.  
  430. ## display copyright notice and version label
  431. #
  432. global function print_version()
  433. {
  434.    optional_function( "enable_status_bar_messages" )
  435.    notify( version_label() )
  436.    optional_function( "restore_status_bar" )
  437. }
  438.  
  439. local function version_label()
  440. {
  441.    return  editor_title "\n" \
  442.            version "- Copyright (c) 1994, 1995\n" \
  443.            "Compuware Corporation\n" \
  444.            "All Rights Reserved."
  445. }
  446.  
  447. ## prompt the user for a command, and run it
  448. #
  449. global function system_key(com)
  450. {
  451.    local err = 0
  452.  
  453.    if (!com)
  454.       com = ltrim( prompt_history( "SYSTEM", "System Command: ", "", 1, 1, "command" ))
  455.  
  456.    if(com)
  457.    {
  458.       add_prompt_history( "SYSTEM", com )
  459.       err = system_pause(com)
  460.    }
  461.    
  462. #  else
  463. #     err = system()
  464.  
  465.    if (err)
  466.    {
  467.       if (!com || match(com, "^.*[@&].* "))
  468.          message("process id = %d", err)
  469.       else
  470.          warning("%s exited with %d", com ? com : "System Command", err)
  471.    }
  472.    else
  473.       message( "" )
  474. }
  475.  
  476. ## Utility function to set an environment variable from the command line.
  477. #
  478. global function setenv(var, value)
  479. {
  480.    ENV[var] = value
  481. }
  482.  
  483. ## Define cd as an alias for chdir
  484. #
  485. global function cd(path)
  486. {
  487.    if (argcount())
  488.       chdir(path)
  489.  
  490.    message(getcwd())
  491. }
  492.  
  493. ## Define pwd to diaplay the current directory.
  494. #
  495. global function pwd()
  496. {
  497.    message(getcwd())
  498. }
  499.  
  500. ## utilities
  501. #
  502. global function min(a,b)
  503. {
  504.    return (a<b) ? a : b;
  505. }
  506.  
  507. global function max(a,b)
  508. {
  509.    return (a>b) ? a : b;
  510. }
  511.  
  512. global function abs(n)
  513. {
  514.    return (n+0<0) ? -n : n;
  515. }
  516.  
  517. # quote all regex characters in a string
  518.  
  519. function quote_regex( s )                                       #PUBLIC #STR
  520. {
  521.    local r = s
  522.    gsub( "[\\\\.*+?<>{}()^$|\\[\\]]", "\\\\&", r )
  523.    return r
  524. }
  525.  
  526. # quote all escape characters in a string,
  527.  
  528. function quote_string( s )                                      #PUBLIC #STR
  529. {
  530.    local r = s
  531.    gsub( "[\"\\\\]", "\\\\&", r )
  532.    return r
  533. }
  534.  
  535. function quote_quote( s )                                      #PUBLIC #STR
  536. {
  537.    local r = s
  538.    gsub( "\"", "\\\"", r )
  539.    return r
  540. }
  541.  
  542. # unquote all escape characters {backslashes(\) & quotes(")} in a string,
  543.  
  544. function unquote_string( s )                                    #PUBLIC #STR
  545. {
  546.    gsub(/\\\\/, "\\", s)
  547.    gsub(/\\\"/, "\"", s)
  548.    return s
  549. }
  550.  
  551. ## string manipulation utilities
  552. #
  553. global function strrepeat( s, n )                               #PUBLIC #STR
  554. {
  555.    local   t = ""
  556.  
  557.    while (n-- > 0)
  558.    {
  559.       t = s t
  560.    }
  561.    return t
  562. }
  563.  
  564. global function compress( s, t )                                #PUBLIC #STR
  565. {
  566.    local   repl
  567.    if (s)
  568.    {
  569.       repl = length(t) ? substr(t,1,1) : " "
  570.       gsub( build_cc(t) "+", repl, s )
  571.    }
  572.    return s
  573. }
  574.  
  575. global function ltrim( s, t )                                   #PUBLIC #STR
  576. {
  577.    if (s)
  578.       sub( "^" build_cc(t) "+", "", s )
  579.  
  580.    return s
  581. }
  582.  
  583. global function trim( s, t )                                    #PUBLIC #STR
  584. {
  585.    if (s)
  586.       sub( build_cc(t) "+$", "", s )
  587.  
  588.    return s
  589. }
  590.  
  591. local function build_cc( t )
  592. {
  593. #
  594. # Build a regular expression "character class" containing the specified
  595. # list of characters.  If no characters are specified, return the character
  596. # class "[ \t]" (the default pattern used by trim, ltrim and compress)
  597. # which matches either the space or tab characters.
  598. #
  599.    if (t)
  600.    {
  601.       # quote the "\" and "]" characters; also quote "^" only
  602.       # if it is the first character in the list
  603.       gsub( /\\/, "\\\\", t )
  604.       gsub( /\]/, "\\]", t )
  605.       sub( /^\^/, "\\^", t )
  606.       return "[" t "]"
  607.    }
  608.    else
  609.       return "[ \t]"
  610. }
  611.  
  612. global function trans( s, tr, repl )                            #PUBLIC #STR
  613. {
  614.    local   len
  615.    local   i
  616.    local   result = ""
  617.    local   ch
  618.  
  619.    if (!tr)
  620.       return ""
  621.  
  622.    if (!repl)
  623.       repl = ""
  624.  
  625.    while (s != "")
  626.    {
  627.       ch = substr( s,1,1 )
  628.       s = substr( s,2 )
  629.  
  630.       len = length( tr )
  631.       i = 1
  632.       while (len--)
  633.       {
  634.          if (gsub( quote_regex(substr( tr, i, 1 )), substr( repl, i, 1 ), ch ))
  635.             break
  636.          else
  637.             i++
  638.       }
  639.       result = result ch
  640.    }
  641.    return result
  642. }
  643.  
  644. ## push_keymap and pop_keymap
  645. #
  646. # push the specified keymap id onto the keymap stack. If no keymap
  647. # id is specified, push the current keymap
  648. #
  649. # pop of the top element on the keymap stack and make it the current
  650. # keymap
  651. #
  652. local  keymapStack
  653. local  keymapIndex
  654.  
  655. global function push_keymap( kid )                              #PUBLIC #INT
  656. {
  657.    local   oldkmp = current_keymap
  658.  
  659.    keymapStack[ keymapIndex++ ] = current_keymap
  660.  
  661.    if ( argcount() )       #  set to new keymap if one was specified
  662.    {
  663.       if (kid != current_keymap)
  664.       {
  665.          current_keymap = kid
  666.          if (current_keymap == oldkmp)
  667.          {
  668.             keymapIndex--
  669.             return FALSE            # didn't set it
  670.          }
  671.       }
  672.    }
  673.  
  674.    return TRUE
  675. }
  676.  
  677. global function pop_keymap()                                    #PUBLIC #INT
  678. {
  679.    if( keymapIndex > 0 )
  680.    {
  681.       current_keymap = keymapStack[ --keymapIndex ]
  682.       return TRUE
  683.    }
  684.    else
  685.       return FALSE
  686. }
  687.  
  688.  
  689. local function read_temp_file( sel_type, second_temp_file )
  690. {
  691.    local longest_line
  692.    local old_cb = current_buffer
  693.    local i
  694.  
  695.    if ( sel_type != COLUMN_SELECTION )
  696.       read_file( second_temp_file )
  697.    else
  698.    {
  699.       current_buffer = create_buffer( "", second_temp_file, BUFFER_SYSTEM )
  700.  
  701.       for ( i = 1; i <= buffer_last_line; i++ )
  702.       {
  703.          current_line = i
  704.          longest_line = max( longest_line, current_line_width )
  705.       }
  706.  
  707.       goto_buffer_top()
  708.       begin_selection( COLUMN_SELECTION )
  709.       goto_buffer_bottom()
  710.       current_column = longest_line
  711.  
  712.       copy_to_scrap()
  713.       delete_buffer()
  714.       current_buffer = old_cb
  715.  
  716.       insert_scrap()
  717.    }
  718. }
  719.  
  720. ## invoke a filter and replace the selected region with the result
  721. #
  722. global function filter( command )                               #PUBLIC #VOID
  723. {
  724.    local   first_temp_file
  725.    local   second_temp_file
  726.    local   block_marked
  727.    local   status
  728.  
  729.    first_temp_file  = create_temp_name()
  730.    second_temp_file = create_temp_name()
  731.  
  732.    save_position()
  733.  
  734.    #
  735.    # Write the marked block out to the first temp file.
  736.    #
  737.    block_marked = selection_type()
  738.    if ( block_marked )
  739.    {
  740.       end_selection()
  741.       goto_mark( selection_mark_top() )
  742.  
  743.       if ( block_marked == LINE_SELECTION )
  744.          goto_bol()
  745.  
  746.       else if ( and(buffer_flags, BUFFER_IN_VIRTUAL_SPACE) )
  747.          prev_char()
  748.    }
  749.    else
  750.    {
  751.       # no selection - select the entire buffer
  752.       goto_buffer_bottom()
  753.       begin_selection( LINE_SELECTION )
  754.       goto_buffer_top()
  755.       end_selection()
  756.    }
  757.  
  758.    write_marked_block( first_temp_file )
  759.  
  760.    #
  761.    # Filter the first_temp_file through the "command" to generate
  762.    # the second_temp_file.
  763.    #
  764.    if ( system(command, first_temp_file, second_temp_file, second_temp_file) >= 0 )
  765.    {
  766.       #
  767.       # Delete the selection, then replace it with the contents
  768.       # of the second_temp_file.
  769.       #
  770.       delete_chars()                  # delete the selection
  771. #      read_file( second_temp_file )
  772.       read_temp_file( block_marked, second_temp_file )
  773.       restore_position( 0 )
  774.       status = FALSE
  775.    }
  776.    else
  777.    {
  778.       # system command failed
  779.       if ( !block_marked )
  780.          remove_selection()
  781.  
  782.       restore_position( 1 )
  783.       status = TRUE
  784.    }
  785.  
  786.    unlink( second_temp_file )
  787.    unlink( first_temp_file )
  788.  
  789.    return status
  790. }
  791.  
  792.  
  793. #-------------- code to record and playback an edit session ---------------#
  794.  
  795. local   recordFileName
  796. local   recordKeys
  797. local   playbackFile
  798. local   playbackKeys
  799. local   playbackMacroId
  800. local   recordMacroId
  801.  
  802. global function recordKeysInitialize( keyfname )
  803. {
  804.    recordFileName = keyfname
  805.  
  806.    recordMacroId = function_id( "record_macro_exit" )
  807.    attach_event_handler( EVENT.EXIT_EDITOR,  recordMacroId )
  808.    record_macro()
  809.    return TRUE
  810. }
  811.  
  812. global function playbackKeysInitialize( keyfname )
  813. {
  814.    if ( filemode(keyfname) >= 0 )
  815.    {
  816.       playbackFile = keyfname
  817.  
  818.       playbackMacroId = function_id( "playbackkeys" )
  819.       playbackkeys()
  820.       return TRUE
  821.    }
  822.    else
  823.    {
  824.       warning( "File '%s' doesn't exist", keyfname )
  825.       return FALSE
  826.    }
  827. }
  828.  
  829. global function playbackkeys()
  830. {
  831.    load_key_file(0, playbackFile)
  832.    playback_macro()
  833. }
  834.  
  835. global function record_macro_exit()
  836. {
  837.    delete_event( EVENT.EXIT_EDITOR, recordMacroId )
  838.    # end record
  839.    record_macro()
  840.    write_key_file(recordFileName)
  841. }
  842.  
  843.  
  844. # -------------------------------------------------------------------------- #
  845.  
  846. ## attach_cleanup_handler()
  847. #
  848. # If the pvcsedit.ae file is changed while the editor is running (typically
  849. # by recompiling a .pel file), the error "Currently executing function has
  850. # been changed" may result.  In this case, an event is triggered upon 
  851. # return from the system command.  Here, we use that event to finish up
  852. # whatever function was running at the time.  The "cleanup_handler" function
  853. # must reside in a different file than that from which it was called to be
  854. # effective.  (See also the comments within the system_window_command()
  855. # function in system.pel).
  856.  
  857. local   function_to_call
  858.  
  859. global function attach_cleanup_handler( handler_name )
  860. {
  861.    if (( function_to_call = function_id( handler_name )))
  862.    {
  863.       attach_event_handler( EVENT.FUNCTION_CHANGED, "cleanup_handler" )
  864.    }
  865. }
  866.  
  867. global function cleanup_handler()
  868. {
  869.    delete_event( EVENT.FUNCTION_CHANGED, "cleanup_handler" )
  870.    execute_function( function_to_call )
  871. }
  872.  
  873. # -------------------------------------------------------------------------- #
  874.  
  875. ## insert whole lines
  876. #
  877. global function paste_lines()
  878. {
  879.    goto_bol()
  880.    insert_scrap()
  881. }
  882.  
  883. ## delete whole lines
  884. #
  885. global function cut_lines()
  886. {
  887.    if( selection_type() != LINE_SELECTION )
  888.       begin_selection( LINE_SELECTION )
  889.  
  890.    delete_to_scrap()
  891. }
  892.  
  893. ## toggle pause on error flag
  894. #
  895. global function toggle_pause( on )                              #PUBLIC #VOID
  896. {
  897.    if (argcount())
  898.       pe( on )
  899.    else
  900.       pe()
  901. }
  902.  
  903. global function pe( on )                                        #PUBLIC #VOID
  904. {
  905.    if( argcount() < 1 )
  906.       pause_on_error = !pause_on_error
  907.    else
  908.       pause_on_error = !!(0+on) != 0
  909.  
  910.    if( pause_on_error )
  911.       message( "pause_on_error Enabled" )
  912.    else
  913.       message( "pause_on_error Disabled" )
  914. }
  915.  
  916. ## arrays containing the names of the editor system files
  917. #
  918. global  cpe_filename
  919. local   existing_cpe_file
  920. local   primary_cpe_dir
  921.  
  922. ## setup the cpe_filename array
  923. #
  924. global function init_cpe_filename()
  925. {
  926.    # initialize filename array if necessary
  927.    if ( !cpe_filename )
  928.    {
  929.         cpe_filename[CPE_FILE_CONFIG]   = editor_config
  930.         cpe_filename[CPE_FILE_AE]       = editor_ae
  931.         cpe_filename[CPE_FILE_BINDINGS] = "bindings.txt"
  932.         cpe_filename[CPE_FILE_KEYMAP]   = "keymap.txt"
  933.         cpe_filename[CPE_FILE_LANGUAGE] = "language.pel"
  934.         cpe_filename[CPE_FILE_INI]      = editor_inifile
  935.         cpe_filename[CPE_FILE_HELP]     = editor_helpfile
  936.    }
  937. }
  938.  
  939. ## return the name of an existing file using the CPE path
  940. #
  941. # valid argument values are:
  942. #       CPE_FILE_AE        # cpe.ae
  943. #       CPE_FILE_CONFIG    # cpe.cfg
  944. #       CPE_FILE_KEYMAP    # keymap.txt
  945. #       CPE_FILE_BINDINGS  # bindings.txt
  946. #       CPE_FILE_LANGUAGE  # language.pel
  947. #       CPE_FILE_INI       # cpe.ini
  948. #       CPE_FILE_HELP      # cpe.hlp
  949. #
  950. global function locate_cpe_file( cpe_id )
  951. {
  952.    local   fn
  953.    local   element
  954.    local   path
  955.    local   result
  956.  
  957.    init_cpe_filename()
  958.  
  959.    # has the file already been located?
  960.    if ( cpe_id in existing_cpe_file )
  961.       return existing_cpe_file[cpe_id]
  962.    else if ( cpe_id in cpe_filename )
  963.    {
  964.       fn = cpe_filename[cpe_id]
  965.       do
  966.       {
  967.          # look first in the current or specified directory
  968.          if ( filemode( fn ) >= 0 )
  969.          {
  970.             existing_cpe_file[cpe_id] = fn = buildpath( fn )
  971.             return fn
  972.          }
  973.          else
  974.          {
  975.             # strip out the filename and look in the current directory
  976.             fn = path_fname(fn) path_ext(fn)
  977.             if (fn != cpe_filename[cpe_id])
  978.             {
  979.                if ( filemode( fn ) >= 0 )
  980.                {
  981.                   existing_cpe_file[cpe_id] = fn = buildpath( fn )
  982.                   return fn
  983.                }
  984.             }
  985.  
  986.             # search the editor_path_var path
  987.             #
  988.             path = ENV[ editor_path_var ]
  989.  
  990.             while ( path )
  991.             {
  992.                # extract a directory from the semicolon separated list
  993.                if ( match( path, /;/ ))
  994.                {
  995.                   element = trim( substr( path, 1, RSTART-1 ))
  996.                   path = ltrim( substr( path, RSTART+1 ))
  997.                }
  998.                else
  999.                {
  1000.                   element = path
  1001.                   path = 0
  1002.                }
  1003.  
  1004.                # treat path elements consisting only of a
  1005.                # drive letter as the cwd on that drive
  1006.                if ( match( element, /:$/ ))
  1007.                   element = element "."
  1008.  
  1009.                # assemble filename (multiple backslashes are ok)
  1010.                result = buildpath( element "\\" fn )
  1011.  
  1012.                # check existence
  1013.                if ( filemode( result ) >= 0 )
  1014.                {
  1015.                   existing_cpe_file[cpe_id] = result
  1016.                   return result
  1017.                }
  1018.             }
  1019.    
  1020.             # try ARGV[0]
  1021.             if ( match( ARGV[0], /.*\\/ ))
  1022.             {
  1023.                result = buildpath( substr( ARGV[0], RSTART, RLENGTH ) fn )
  1024.                if ( filemode( result ) >= 0 )
  1025.                {
  1026.                   existing_cpe_file[cpe_id] = result
  1027.                   return result
  1028.                }
  1029.             }
  1030.  
  1031.             # if all of that failed, try again after removing
  1032.             # the "help\" part of the name, before giving up
  1033.             if ( substr(fn,1,5) == "help\\" )
  1034.                fn = substr( fn, 6 )
  1035.             else
  1036.                break
  1037.          }
  1038.       } while ( fn )
  1039.    }
  1040.    # return null
  1041. }
  1042.  
  1043. ## return the first directory given in the CPE path
  1044. #
  1045. global function editor_path( cpe_id )
  1046. {
  1047.    # cpe_id is an optional argument containing the id of
  1048.    # one of the editor support files (e.g. CPE_FILE_CONFIG).
  1049.    # If specified, the name of the file will be appended
  1050.  
  1051.    local   fn
  1052.    local   path
  1053.    local   fmode
  1054.  
  1055.    if ( primary_cpe_dir )
  1056.    {
  1057.       # cpe path has already been processed
  1058.       path = primary_cpe_dir
  1059.    }
  1060.    else if (( path = ENV[ editor_path_var ] ))
  1061.    {
  1062.       # handle a semicolon separated list of directories
  1063.       if ( match( path, /;/ ))
  1064.          path = substr( path, 1, RSTART-1 )
  1065.  
  1066.       # treat path elements consisting only of a
  1067.       # drive letter as the cwd on that drive
  1068.       if ( match( path, /:$/ ))
  1069.          path = path "."
  1070.  
  1071.       path = buildpath( path "\\" )
  1072.  
  1073.       # handle root as a special case since filemode of
  1074.       # root is unreliable on certain networks
  1075.       if ( path !~ /:[\\/]$/ )
  1076.       {
  1077.          # if the directory doesn't exist, use the cwd
  1078.          fmode = substr( path, length( path )) == "\\"            \
  1079.                  ? filemode( substr( path, 1, length( path )-1 )) \
  1080.                  : -1
  1081.  
  1082.          if ( (fmode <= 0) || !and( fmode, _SUBDIR ))
  1083.             path = buildpath( "." )
  1084.       }
  1085.       primary_cpe_dir = path
  1086.    }
  1087.  
  1088.    init_cpe_filename()
  1089.  
  1090.    # if an optional file argument was specified, append the name of the
  1091.    # appropriate file
  1092.  
  1093.    if ( cpe_id in cpe_filename )
  1094.    {
  1095.       fn = cpe_filename[cpe_id]
  1096.       if (fn == path_fname(fn) path_ext(fn))
  1097.          return path fn
  1098.       else
  1099.          return fn
  1100.    }
  1101.    else
  1102.       return path
  1103. }
  1104.  
  1105. ## path_path
  1106. #
  1107. # return the drive:path of a filespec, trailing slash/backslash
  1108. # is included.
  1109. #
  1110. global function path_path(fspec)
  1111. {
  1112.    local last_fs
  1113.    local last_bs
  1114.  
  1115.    if (length(fspec) == 0)
  1116.       return "";
  1117.    else
  1118.    {
  1119.       last_fs = rindex( fspec, "/" )
  1120.       last_bs = rindex( fspec, "\\" )
  1121.  
  1122.       return prefix( fspec, (last_fs > last_bs) ? last_fs : last_bs );
  1123.    }
  1124. }
  1125.  
  1126.  
  1127. ## bld_fnam
  1128. #
  1129. # build a filename out of its components
  1130. #
  1131. global function bld_fnam(path, name, suffix)
  1132. {
  1133.    local name1, name2, name3, name4;
  1134.  
  1135.    name1 = path_path(path);
  1136.    name2 = path_fname(name);
  1137.    name3 = path_ext(suffix);
  1138.    if (length(name3) == 0)
  1139.       name3 = "." suffix;
  1140.  
  1141.    name4 = name1 name2 name3
  1142.    gsub("\"", "", name4)
  1143.    return name4
  1144. }
  1145.  
  1146. ## mkpath
  1147. #
  1148. # create a directoy including all intermediate directories.
  1149. #
  1150. global function mkpath(path)
  1151. {
  1152.    local dirs, i
  1153.    local subdir = ""
  1154.  
  1155.    path = buildpath(path)
  1156.    split(path, dirs, "\\")
  1157.    for (i in dirs)
  1158.    {
  1159.       if (i == 1)
  1160.          subdir = dirs[i]
  1161.       else
  1162.       {
  1163.          subdir = subdir "\\" dirs[i]
  1164.          if (filemode(subdir) != _SUBDIR)
  1165.          {
  1166.             if (!mkdir(subdir))
  1167.                return FALSE
  1168.          }
  1169.       }
  1170.    }
  1171.    return TRUE
  1172. }
  1173.  
  1174. ## quit from editor
  1175. #
  1176. # don't want to do exit_editor if in_exit is TRUE
  1177. local in_exit = FALSE
  1178.  
  1179. global function exit_editor()
  1180. {
  1181.    local   buf
  1182.    local   priorMessageLevel
  1183.    local   i = buffers_modified
  1184.    local   oldBuffer = current_buffer
  1185.  
  1186.    really_close = TRUE
  1187.  
  1188. ############################################
  1189. # new way of saving changes before quiting #
  1190. ############################################
  1191.    optional_function( "exit_vdiff", 0 )   # if vdiff is active, close it down
  1192.  
  1193.    save_changes_list = TRUE
  1194.  
  1195.    if ( in_exit )
  1196.       {
  1197.       save_changes_list = FALSE
  1198.       return
  1199.       }
  1200.    else if ( buffer_list(0, 1) )
  1201.       {
  1202.       really_close = TRUE
  1203.       in_exit = TRUE
  1204.       return
  1205. #      quit( 1, 0 )
  1206.       }
  1207.    else
  1208.       {
  1209.       really_close = FALSE
  1210.       save_changes_list = FALSE
  1211.       in_exit = FALSE
  1212.       return
  1213.       }
  1214. ############################################
  1215. ############################################
  1216.  
  1217.  
  1218.    if ( i && in_exit == FALSE ) 
  1219.    {
  1220.       buf = sprintf( "%d %s been modified, Exit[ynw]? ", \
  1221.                      i, i > 1 ? "buffers have" : "buffer has")
  1222.  
  1223.       i = tolower( confirm(buf, "yYnNwW") )
  1224.  
  1225.       if (i == "w") 
  1226.       {
  1227.          priorMessageLevel = message_level
  1228.          message_level = 0
  1229.  
  1230.          if ( !write_all_buffers() ) 
  1231.          {
  1232.  
  1233.             message_level = priorMessageLevel
  1234.             current_buffer = oldBuffer
  1235.             really_close = FALSE
  1236.             return
  1237.  
  1238.          }
  1239.          else
  1240.             really_close = TRUE
  1241.       }
  1242.       else if ( i == "y" )
  1243.          really_close = TRUE;
  1244.  
  1245.       else if ( i == "n" )
  1246.          really_close = FALSE;
  1247.  
  1248.       else
  1249.          really_close = FALSE;
  1250.          
  1251.    }
  1252. }
  1253.  
  1254. global function done2()
  1255. {
  1256.    # if we are in detached mode just close the current 
  1257.    # window
  1258.    if ( mdi_mode == 2 )
  1259.    {
  1260.       delete_window()
  1261.       return
  1262.    }
  1263.    else
  1264.    {
  1265.       done()
  1266.    }
  1267. }
  1268.  
  1269. global function done(exit_editor)
  1270. {
  1271.    local   buf
  1272.    local   priorMessageLevel
  1273.    local   i = buffers_modified
  1274.  
  1275.    #CFV added if-statement so that we can just do a quit without getting
  1276.    # the save-buffer-list if there are modifications
  1277.    if (exit_editor)
  1278.    {
  1279.       delete_event(EVENT.EXIT_EDITOR, "exit_editor")
  1280.       quit(1, 0);
  1281.       return;
  1282.    }
  1283.    
  1284.    # don't quit by default
  1285.    really_close = FALSE
  1286.  
  1287.    ############################################
  1288.    # new way of saving changes before quiting #
  1289.    ############################################
  1290.    save_changes_list = TRUE
  1291.    if ( buffer_list(0, 1) )
  1292.    {
  1293.       in_exit      = TRUE
  1294.       really_close = TRUE
  1295.       quit( 1, 0 )
  1296.    }
  1297.    else
  1298.    {
  1299.       in_exit           = FALSE
  1300.       really_close      = FALSE
  1301.       save_changes_list = FALSE
  1302.       return
  1303.    }
  1304.    ############################################
  1305.    ############################################
  1306.  
  1307.    if ( i )
  1308.    {
  1309.       buf = sprintf( "%d %s been modified, Exit[ynw]? ", \
  1310.                       i, i > 1 ? "buffers have" : "buffer has")
  1311.  
  1312.       i = tolower( confirm(buf, "yYnNwW") )
  1313.       if ( i != "n" )
  1314.          in_exit = TRUE
  1315.  
  1316.       if (i == "w")
  1317.       {
  1318.          priorMessageLevel = message_level
  1319.          message_level = 0
  1320.          if ( !write_all_buffers() )
  1321.          {
  1322.             message_level = priorMessageLevel
  1323.             return
  1324.          }
  1325.       }
  1326.       else if (i != "y") 
  1327.          return
  1328.    }
  1329.    really_close = TRUE
  1330.    quit( 0, 0 )
  1331. }
  1332.  
  1333. ## write all buffers and exit
  1334. #
  1335. global function write_and_exit()
  1336. {
  1337.    if (write_all_buffers())
  1338.       quit(0,0)
  1339. }
  1340.  
  1341. ## set_flag_bits() - set the value of one or more bits in a flag
  1342. #
  1343. #
  1344. # arguments:
  1345. #
  1346. #    srcFlag - the value of the input flag
  1347. #
  1348. #    mask    - which bits in the input flag are to be changed
  1349. #
  1350. #    newBits - what the new flag should be (only those bits specified
  1351. #               in the mask will be affected)
  1352. #
  1353. # function result: new flag
  1354. #
  1355. #
  1356. # example:
  1357. #    This example sets the WINDOW_HEX(0x4000) bit contained in the 
  1358. #    WINDOW_CHARS(0x6000) group of flags:
  1359. #     window_flags = set_flag_bits( window_flags, WINDOW_CHARS, WINDOW_HEX )
  1360. #
  1361. #    To turn on a bit specify the same mask and newBits paramters, for example:
  1362. #     flags = set_flag_bits( flags, 0x0101, 0x0001 )
  1363. #    will turn on bit 1 of the flags variable.
  1364. #
  1365. #    To turn off a bit specify opposite mask and newBits paramters, for example:
  1366. #     flags = set_flag_bits( flags, 0x0101, 0x0100 )
  1367. #    will turn off bit 1 of the flags variable.
  1368. #
  1369. global function set_flag_bits( srcFlag, mask, newBits )         #PUBLIC #INT
  1370. {
  1371.    # first turn off all bits in mask
  1372.    srcFlag = and( srcFlag, not(mask) )
  1373.  
  1374.    # newBits should be a part of the mask
  1375. #     if ( and( mask, newBits ) )
  1376.    srcFlag = or( srcFlag, and( newBits, mask) )
  1377.    
  1378. #  This section caused problems when run into accidentally;
  1379.    # if newBits not part of mask, but it equals 1, turn on bits of mask
  1380. #     else if ( newBits == 1 )
  1381. #        srcFlag = or( srcFlag, mask)
  1382.  
  1383.    return srcFlag
  1384. }
  1385.                  
  1386. ## toggle_file_backup()
  1387. #
  1388. global function toggle_file_backup( on )
  1389. {
  1390.    if ( argcount() < 1 )           # no argument specified
  1391.       backup_files_enabled = !backup_files_enabled;
  1392.  
  1393.    else
  1394.       backup_files_enabled = 0+on   # use the argument specified
  1395.  
  1396.    message( backup_files_enabled ? "Backup files will be created." \
  1397.                                  : "Backup files will not be created.")
  1398. }
  1399.  
  1400. ### push_dir()
  1401. # Push the name of the current working directory on a stack and change to
  1402. # the specified directory.
  1403. #
  1404. ### pop_dir()
  1405. # Change back to a previously pushed directory and pop the element off the
  1406. # stack.  Returns TRUE if successful, FALSE if there is no directory element
  1407. # on the stack.
  1408. #
  1409.  
  1410. local   cwd_stack
  1411. local   cwd_stack_size
  1412.  
  1413. global function push_dir( new_dir )
  1414. {
  1415.    cwd_stack[ ++cwd_stack_size ] = getcwd()
  1416.    if ( new_dir )
  1417.       chdir( new_dir )
  1418. }
  1419.  
  1420. global function pop_dir()
  1421. {
  1422.    if ( cwd_stack_size in cwd_stack )
  1423.    {
  1424.       chdir( cwd_stack[ cwd_stack_size ] )
  1425.       delete cwd_stack[ cwd_stack_size-- ]
  1426.       return TRUE
  1427.    }
  1428.    else
  1429.       return FALSE
  1430. }
  1431.  
  1432. ## support for functions in optional .PEL files
  1433. #
  1434. function optional_function( fn_name, arg1 ,arg2, arg3, arg4, arg5 )
  1435. {
  1436.    local   fid, count = argcount();
  1437.  
  1438.    if((count < 1) || !fn_name)
  1439.       fid = 0
  1440.    else if (count == 1 )
  1441.       fid = function_id( fn_name );
  1442.    else if (count == 2)
  1443.       fid = function_id( fn_name, arg1 );
  1444.    else if (count == 3)
  1445.       fid = function_id( fn_name, arg1, arg2 );
  1446.    else if (count == 4)
  1447.       fid = function_id( fn_name, arg1, arg2, arg3 );
  1448.    else if (count == 5)
  1449.       fid = function_id( fn_name, arg1, arg2, arg3, arg4 );
  1450.    else
  1451.       fid = function_id( fn_name, arg1, arg2, arg3, arg4, arg5 );
  1452.  
  1453.    if (fid)
  1454.       return execute_function( fid )
  1455.    else
  1456.       return FALSE
  1457. }
  1458.  
  1459. ## create_semaphore_fname()
  1460. #
  1461. #  Create a new extension for the file name specified.  The extension needs
  1462. #  to be unique or else conflicts may occur and files will be reported as 
  1463. #  locked when they actually aren't.
  1464. #
  1465. #  All extensions will appear in the form xxx.__! or xxx.x_! or xxx.xx!
  1466. #
  1467. global function create_semaphore_fname( fname, lastchar )
  1468. {
  1469.    local bname;
  1470.    local ext;
  1471.    local ppath;
  1472.    local count;
  1473.  
  1474.    fname = buildpath( fname );
  1475.    bname = path_fname( fname );
  1476.    ext   = path_ext( fname );
  1477.    ppath = substr( fname, 1, length( fname ) - length( bname ) - length( ext ));
  1478.    if (ext == "")
  1479.        ext = ".";
  1480.  
  1481.    ext = substr(substr( ext "___", 1, 3) lastchar, 1, 4);
  1482.  
  1483.    return ppath bname ext;
  1484. }
  1485.  
  1486. global function system_pause( cmd, sys_flags )
  1487. {
  1488.    local flags
  1489.    local fileid
  1490.    local cmdFileName
  1491.    local semfile
  1492.    local semid
  1493.  
  1494.    if (match(cmd, "^[@&*+?=]"))
  1495.    {
  1496.       flags = substr(cmd, RSTART,  RLENGTH)
  1497.       cmd   = substr(cmd, RSTART + RLENGTH)
  1498.    }
  1499.  
  1500.    if (isWindows())
  1501.       cmdFileName = create_temp_name(0, "bat")
  1502.    else
  1503.       cmdFileName = create_temp_name(0, "cmd")
  1504.  
  1505.    fileid = fopen(cmdFileName, 2)
  1506.  
  1507.    # Win-OS/2 get complicated since OS/2 never informs Windows when a DOS
  1508.    # program started by him exits, forcing all system commands to run ASYNC.
  1509.  
  1510.    if (isWindows() == WIN_OS2)
  1511.    {
  1512.       # Create a Semaphore-File for the Batch file to delete.
  1513.       semfile = create_temp_name(0, "sem")
  1514.       semid   = fopen(semfile, 2)
  1515.       fprintf( semid, "%s\n", cmd);
  1516.       fclose(semid)
  1517.  
  1518.       # Create the batch file and execute it.
  1519.       fprintf( fileid, "%s\n@pause\n@del %s\n", cmd, semfile);
  1520.       fclose(fileid)
  1521.       system( flags cmdFileName, 0, 0, 0,
  1522.               or(or(sys_flags, SYS_SESSION), SYS_ASYNC))
  1523.  
  1524.       # Wait for the batch file to delete the semaphore file.
  1525.       while (filemode(semfile) != -1)
  1526.          idle(TRUE)
  1527.    }
  1528.    else
  1529.    {
  1530.       fprintf( fileid, "%s\n@pause\n", cmd, cmdFileName );
  1531.       fclose(fileid)
  1532.       system( flags cmdFileName, 0, 0, 0, or(sys_flags, SYS_SESSION) )
  1533.    }
  1534.    unlink( cmdFileName )
  1535. }
  1536.  
  1537. global function resize_editwin()
  1538. {
  1539.    # maintain zoomed state
  1540.    if ( current_window && and(window_flags, WINDOW_ZOOM) == WINDOW_EXPANDED && mdi_mode < 2 )
  1541.       expand_window()
  1542. }
  1543.  
  1544.  
  1545. # DWM 5/18/94
  1546. # deletes all events in the range and returns an array
  1547. # containing all of the gids removed
  1548. global function save_and_remove_events( event_start, event_end )
  1549. {
  1550.    local event
  1551.    local macro
  1552.    local event_list[]
  1553.  
  1554.    if ( argcount() >= 2 && event_start <= event_end )
  1555.       {
  1556.       for ( event = event_start; event <= event_end; event++ )
  1557.          {
  1558.          event_list[ event ] = query_event( event )
  1559.    
  1560.          for ( macro in event_list[ event ] )
  1561.             delete_event( event, event_list[event][macro] )
  1562.          }
  1563.       }
  1564.    else
  1565.       warning( "save_and_remove_events:  invalid parameters" )
  1566.  
  1567.    return event_list
  1568. }
  1569.  
  1570. # DWM 5/28/94
  1571. # restores events removed by save_and_remove_events
  1572. global function restore_events( event_list[] )
  1573. {
  1574.    local event
  1575.    local macro
  1576.  
  1577.    for ( event in event_list )
  1578.       {
  1579.       for ( macro in event_list[ event ] )
  1580.          attach_event_handler( event, event_list[event][macro] )
  1581.       }
  1582. }
  1583.  
  1584. #
  1585. # Searches for string in the array and returns the index.  If not found,
  1586. # it just returns.  Keep in mind that the type of the return value will
  1587. # be "uninitialized" and that is how you can tell if the item was found
  1588. #
  1589. function find_in_array( theArray[], theString )
  1590. {
  1591.    local i
  1592.  
  1593.    for ( i in theArray )
  1594.       if ( theArray[i] == theString )
  1595.          return i
  1596.  
  1597.    return 
  1598. }
  1599.  
  1600. # DWM 5/28/94
  1601. # return an array containing all of the elements of both arrays.
  1602. # If there is a collision, favor the second array
  1603. global function merge_arrays( array1[], array2[] )
  1604. {
  1605.    local item
  1606.    local array[]
  1607.  
  1608.    for ( item in array1 )
  1609.       array[ item ] = array1[ item ]
  1610.  
  1611.    for ( item in array2 )
  1612.       array[ item ] = array2[ item ]
  1613.  
  1614.    return array
  1615. }
  1616.  
  1617. # Event handler called when a file is dropped 
  1618. # onto a running editor. The dropped_file variable
  1619. # contains the name of the file dropped onto 
  1620. # the editor
  1621. global function file_dropped()
  1622. {
  1623.    if ( dropped_file )
  1624.    {
  1625. #      set_editwin_property( EWC_TO_TOP )
  1626.       create_buf_and_win_key( dropped_file )
  1627.       update_current_view()
  1628.    }
  1629. }
  1630.  
  1631. ## SYMBOL_REGEX
  1632. #
  1633. # A search argument which defines an "identifier", such as a function or
  1634. # variable name.  The default is to use "C++" rules.
  1635. #
  1636. global   SYMBOL_REGEX = "[a-zA-Z0-9_:~]+"
  1637. global   SYMBOL_REGEX2 = "[/\\#\\(\\)\\{\\}\\[\\]\\*\\&a-zA-Z0-9_:~]+"
  1638.  
  1639. ## symbol_under_cursor()
  1640. #
  1641. # This function returns the name of the identifier presently under the
  1642. # cursor.  The default identifier is defined as any consecutive string of upper
  1643. # or lower case letters, numbers, underscores, and dots.  If the cursor is
  1644. # not on one of those characters, or is in "virtual space", this function
  1645. # returns the NULL value.
  1646. #
  1647. global function symbol_under_cursor( symbol_regex )
  1648. {
  1649.    local   symbol
  1650.    local   prevCol
  1651.    local   cursorPos
  1652.    local   last
  1653.  
  1654.    if ( !symbol_regex )
  1655.         symbol_regex = SYMBOL_REGEX
  1656.  
  1657.    # is the cursor on a character?
  1658.    if ( and( buffer_flags, BUFFER_IN_VIRTUAL_SPACE ))
  1659.       return ""
  1660.  
  1661.    # read the entire current line into a string, then restore
  1662.    # the cursor position
  1663.    #
  1664.    prevCol = current_column
  1665.    cursorPos = buffer_offset
  1666.    current_column = 1
  1667.    cursorPos = cursorPos + 1 - buffer_offset
  1668.    symbol = read_buffer()
  1669.    current_column = prevCol
  1670.  
  1671.    # ensure that the cursor is on a valid symbol
  1672.    if ( !match( substr( symbol, cursorPos ), "^" symbol_regex ))
  1673.       return ""
  1674.  
  1675.    last = cursorPos + RLENGTH
  1676.  
  1677.    # find the first character in the symbol
  1678.    if ( !match( substr( symbol, 1, cursorPos), symbol_regex "$" ))
  1679.    {
  1680.       # should never happen
  1681.       return ""
  1682.    }
  1683.  
  1684.    # read symbol from buffer
  1685.    return substr( symbol, RSTART, last - RSTART )
  1686. }
  1687.  
  1688. ## left_symbol_under_cursor
  1689. #
  1690. # just like symbol_under_cursor above, but if it doesn't find a symbol, it
  1691. # moves left once and tries again
  1692. #
  1693. function left_symbol_under_cursor( symbol_regex )
  1694. {
  1695.    local key = symbol_under_cursor( symbol_regex )
  1696.  
  1697.    if ( !key )
  1698.    {
  1699.       save_position();
  1700.       left();
  1701.       key = symbol_under_cursor( symbol_regex )
  1702.       restore_position(1);
  1703.    }
  1704.  
  1705.    return key
  1706. }
  1707.  
  1708. #
  1709. # strtok function: Similar to the C function of the same name,
  1710. #                  breaks up a string using the supplied delimiters
  1711. #                  (which are specified in a regular expression)
  1712. #
  1713. local tokstring
  1714. local tokdelim
  1715.  
  1716. global function strtok( str, delimeter )
  1717. {
  1718.    local temp
  1719.    local match_ret
  1720.    local ret_str = FALSE
  1721.  
  1722.    # if there is a string, make it and the delimeter current
  1723.    if ( (argcount() > 0) && str )
  1724.       tokstring = str
  1725.       
  1726.    if ( (argcount() == 2) && delimeter )
  1727.       tokdelim = delimeter
  1728.       
  1729.    if ( tokstring )
  1730.    {
  1731.       # replace '\' char with "\\" for regex matching
  1732.       gsub( "\\", "\\\\", tokstring )
  1733.       
  1734.       match_ret = match( tokstring, tokdelim )
  1735.       
  1736.       if ( match_ret && (RSTART == 1) )
  1737.          tokstring = substr( tokstring, RLENGTH + 1, length(tokstring) )
  1738.          
  1739.       if ( !match_ret )
  1740.       {
  1741.          ret_str = tokstring
  1742.          tokstring = ""
  1743.       }
  1744.       else
  1745.       {
  1746.          ret_str = substr( tokstring, 1, RSTART - 1 )
  1747.          tokstring = substr( tokstring, RSTART + RLENGTH, length(tokstring) )
  1748.       }
  1749.    }
  1750.    return ret_str
  1751. }
  1752.  
  1753. global function get_tokstring()
  1754. {
  1755.    return tokstring
  1756. }
  1757.  
  1758. #
  1759. # Function to set an environment variable.
  1760. #
  1761. global function set_environment( env_string, value_string )
  1762. {
  1763.    if ( env_string )
  1764.       ENV[ env_string ] = value_string
  1765.    else
  1766.       warning("bad arguments sent to set_environment(%s, %s)", env_string, value_string )
  1767. }
  1768.  
  1769. #  
  1770. #  Function to check if you are in the Windows environment
  1771. #  Return values - 0: not in (windows or win/os2)
  1772. #                  1: Windows
  1773. #                  2: Win-OS2
  1774. #  
  1775. global function isWindows()
  1776. {
  1777.    local result = 0;
  1778.  
  1779.    if(tolower(substr(os_name, 1, 1)) == "w")
  1780.    {
  1781.       result++;
  1782.       if(tolower(substr(os_name, 4, 1)) == "-")
  1783.          result++
  1784.    }
  1785.  
  1786.    return result;
  1787. }
  1788.  
  1789. ##############
  1790. # File Access
  1791. ##############
  1792.  
  1793. global copy_lan_files_on_action     = ""
  1794. global copy_floppy_files_on_action  = ""
  1795. global copy_local_files_on_action   = ""
  1796.  
  1797. global function copy_lan_files_on( action )
  1798. {
  1799.    local act = tolower( action )
  1800.  
  1801.    if ( act && (act != "mod" && act != "open") )
  1802.       warning( "copy_lan_files_on: invalid copy action--" action )
  1803.  
  1804.    copy_lan_files_on_action = act
  1805. }
  1806.  
  1807. global function copy_floppy_files_on( action )
  1808. {
  1809.    local act = tolower( action )
  1810.  
  1811.    if ( act && (act != "mod" && act != "open") )
  1812.       warning( "copy_floppy_files_on: invalid copy action--" action )
  1813.  
  1814.    copy_floppy_files_on_action = act
  1815. }
  1816.  
  1817. global function copy_local_files_on( action )
  1818. {
  1819.    local act = tolower( action )
  1820.  
  1821.    if ( act && (act != "mod" && act != "open") )
  1822.       warning( "copy_lan_files_on: invalid copy action--" action )
  1823.  
  1824.    copy_local_files_on_action = act
  1825. }
  1826.  
  1827. global lock_lan_files_on_mod     = FALSE
  1828. global lock_floppy_files_on_mod  = FALSE
  1829. global lock_local_files_on_mod   = FALSE
  1830.  
  1831. global function set_file_access( p1, p2, p3, p4, p5, p6 )
  1832. {
  1833.    # add + 0 to ensure values are numeric
  1834.    lock_lan_files_on_mod = p1 + 0
  1835.    copy_lan_files_on_action = p2
  1836.    
  1837.    lock_local_files_on_mod = p3 + 0
  1838.    copy_local_files_on_action = p4
  1839.    
  1840.    lock_floppy_files_on_mod = p5 + 0
  1841.    copy_floppy_files_on_action = p6
  1842. }
  1843.  
  1844. global function toggle_lock_lan_files_on_mod( onOff )
  1845. {
  1846.    if ( !argcount() )
  1847.       onOff = !lock_lan_files_on_mod
  1848.  
  1849.    lock_lan_files_on_mod = !!onOff
  1850. }
  1851.  
  1852. global function toggle_lock_floppy_files_on_mod( onOff )
  1853. {
  1854.    if ( !argcount() )
  1855.       onOff = !lock_floppy_files_on_mod
  1856.  
  1857.    lock_floppy_files_on_mod = !!onOff
  1858. }
  1859.  
  1860. global function toggle_lock_local_files_on_mod( onOff )
  1861. {
  1862.    if ( !argcount() )
  1863.       onOff = !lock_local_files_on_mod
  1864.  
  1865.    lock_local_files_on_mod = !!onOff
  1866. }
  1867.  
  1868. global lock_on_mod = FALSE
  1869. global function toggle_lock_on_mod( bool )
  1870. {
  1871.    if ( !argcount() )
  1872.       bool = !lock_on_mod
  1873.       
  1874.    if ( bool )
  1875.    {
  1876.       # only turn it on if it's off
  1877.       if ( !lock_on_mod )
  1878.       {
  1879.         attach_event_handler( EVENT.FIRST_MOD, "lock_buffer" )
  1880.         attach_event_handler( EVENT.UNMOD, "unlock_buffer" )
  1881.         lock_on_mod = TRUE
  1882.       }
  1883.    }  
  1884.    # only turn it off if it's on
  1885.    else if ( lock_on_mod )
  1886.    {
  1887.       delete_event( EVENT.FIRST_MOD, "lock_buffer" )
  1888.       delete_event( EVENT.UNMOD, "unlock_buffer" )
  1889.       lock_on_mod = FALSE
  1890.    }  
  1891. }  
  1892.  
  1893. global copy_on_mod = FALSE
  1894. global function toggle_copy_on_mod( bool )
  1895. {
  1896.    if ( !argcount() )
  1897.       bool = !copy_on_mod
  1898.       
  1899.    if ( bool )
  1900.    {
  1901.       # only turn it on if it's off
  1902.       if ( !copy_on_mod )
  1903.       {
  1904.         attach_event_handler( EVENT.FIRST_MOD, "copy_buffer_internally" )
  1905.         copy_on_mod = TRUE
  1906.       }
  1907.    }
  1908.    # only turn it off if it's on
  1909.    else if ( copy_on_mod )
  1910.    {
  1911.       delete_event( EVENT.FIRST_MOD, "copy_buffer_internally" )
  1912.       copy_on_mod = FALSE
  1913.    }
  1914. }
  1915.  
  1916. global function is_lan_drive( path )
  1917. {
  1918.    local is = FALSE
  1919.    local drive_letter
  1920.  
  1921.    if ( argcount() < 1 )
  1922.       path = buffer_filename
  1923.  
  1924.    if ( disk_is_removeable(path) )
  1925.    {
  1926.       drive_letter = tolower( prefix(path, 1) )
  1927.       if ( drive_letter != "a" && drive_letter != "b" )
  1928.          is = TRUE
  1929.    }
  1930.  
  1931.    return is
  1932. }
  1933.  
  1934. global function is_floppy_drive( path )
  1935. {
  1936.    local is = FALSE
  1937.    local drive_letter
  1938.  
  1939.    if ( argcount() < 1 )
  1940.       path = buffer_filename
  1941.  
  1942.    if ( disk_is_removeable(path) )
  1943.    {
  1944.       drive_letter = tolower( prefix(path, 1) )
  1945.       if ( drive_letter == "a" || drive_letter == "b" )
  1946.          is = TRUE
  1947.    }
  1948.  
  1949.    return is
  1950. }
  1951.  
  1952. global function is_local_drive( path )
  1953. {
  1954.    local is = FALSE
  1955.  
  1956.    if ( argcount() < 1 )
  1957.       path = buffer_filename
  1958.  
  1959.    if ( !disk_is_removeable(path) )
  1960.       is = TRUE
  1961.  
  1962.    return is
  1963. }
  1964.  
  1965. global file_access_list[]
  1966. global function file_access_first_mod_handler()
  1967. {
  1968.    if ( filemode(buffer_filename) != -1 )
  1969.    {
  1970.       if ( is_lan_drive(buffer_filename) )
  1971.       {
  1972.          if ( lock_lan_files_on_mod )
  1973.          {
  1974.             if ( lock_buffer() )
  1975.                file_access_list[ buffer_filename ] = BUFFER_LOCKED
  1976.             else
  1977.                warning( "unable to lock file " buffer_filename )
  1978.          }
  1979.       
  1980.          if ( copy_lan_files_on_action == "mod" )
  1981.          {
  1982.             if ( !copy_buffer_internally() )
  1983.                warning( "unable to copy file " buffer_filename " internally" )
  1984.          }
  1985.       }
  1986.       else if ( is_floppy_drive(buffer_filename) )
  1987.       {
  1988.          if ( lock_floppy_files_on_mod )
  1989.          {
  1990.             if ( !lock_buffer() )
  1991.                warning( "unable to lock file " buffer_filename )
  1992.          }
  1993.       
  1994.          if ( copy_floppy_files_on_action == "mod" )
  1995.          {
  1996.             if ( !copy_buffer_internally() )
  1997.                warning( "unable to copy file " buffer_filename " internally" )
  1998.          }
  1999.       }
  2000.       else
  2001.       {
  2002.          if ( lock_local_files_on_mod )
  2003.          {
  2004.             if ( lock_buffer() )
  2005.                file_access_list[ buffer_filename ] = BUFFER_LOCKED
  2006.             else
  2007.                warning( "unable to lock file " buffer_filename )
  2008.          }
  2009.       
  2010.          if ( copy_local_files_on_action == "mod" )
  2011.          {
  2012.             if ( !copy_buffer_internally() )
  2013.                warning( "unable to copy file " buffer_filename " internally" )
  2014.          }
  2015.       }
  2016.    }
  2017. }
  2018.  
  2019. global function file_access_unmod_handler()
  2020. {
  2021.    if ( buffer_filename in file_access_list )
  2022.    {
  2023.      if ( file_access_list[buffer_filename] == BUFFER_LOCKED )
  2024.         unlock_buffer()
  2025.    }
  2026. }
  2027.  
  2028. global function file_access_file_open_handler()
  2029. {
  2030.    if ( filemode(buffer_filename) != -1 )
  2031.    {
  2032.       if ( is_lan_drive(buffer_filename) )
  2033.       {
  2034.          if ( copy_lan_files_on_action == "open" )
  2035.          {
  2036.             if ( !copy_buffer_internally() )
  2037.                warning( "unable to copy file " buffer_filename " internally" )
  2038.          }
  2039.       }
  2040.       else if ( is_floppy_drive(buffer_filename) )
  2041.       {
  2042.          if ( copy_floppy_files_on_action == "open" )
  2043.          {
  2044.             if ( !copy_buffer_internally() )
  2045.                warning( "unable to copy file " buffer_filename " internally" )
  2046.          }
  2047.       }
  2048.       else
  2049.       {
  2050.          if ( copy_local_files_on_action == "open" )
  2051.          {
  2052.             if ( !copy_buffer_internally() )
  2053.                warning( "unable to copy file " buffer_filename " internally" )
  2054.          }
  2055.       }
  2056.    }
  2057. }
  2058.  
  2059.  
  2060. local file_error_status = 0
  2061. global function file_error_callback()
  2062. {
  2063.    local ret_val = DRC_CONTINUE
  2064.    
  2065.    if ( callback_msg == DM_CLICK )
  2066.    {
  2067.       if ( callback_index == IDB_FILE_ERROR_RETRY )
  2068.          refresh_buffer()
  2069.          
  2070.       else if ( callback_index == IDB_FILE_ERROR_FAIL )
  2071.          file_error_status = -1
  2072.    }                                    
  2073.    
  2074.    return ret_val
  2075. }
  2076.  
  2077. local in_file_error[]
  2078. local failed[]
  2079. local dhErrorDlg[]
  2080. global function file_error_prompt()
  2081. {
  2082.    if ( !(current_buffer in failed) )
  2083.    {
  2084.       if ( !in_file_error[buffer_filename] )
  2085.       {
  2086.          dhErrorDlg[buffer_filename] = create_dialog( function_id( "file_error_callback" ),
  2087.                                                       0, IDD_FILE_ERROR, resource_dll );
  2088.    
  2089.          set_dialog_window(   dhErrorDlg[buffer_filename], DWC_TITLE, 
  2090.                               "File Error--" buffer_filename )
  2091.    
  2092.          set_dialog_item(  dhErrorDlg[buffer_filename], IDB_FILE_ERROR_DISCARD,
  2093.                            DAC_DISABLE )
  2094.       }
  2095.    
  2096.       in_file_error[buffer_filename]++
  2097.    
  2098.       beep()
  2099.       begin_dialog( dhErrorDlg[buffer_filename] )
  2100.  
  2101.       if ( file_error_status < 0 )  
  2102.          failed[ current_buffer ] = TRUE
  2103.    
  2104.       display_redraw()
  2105.    
  2106.       in_file_error[buffer_filename]--
  2107.    
  2108.       # delete the dialog when our nesting level is zero
  2109.       if ( !in_file_error[buffer_filename] )
  2110.       {
  2111.          file_error_status = 0
  2112.          delete_dialog( dhErrorDlg[buffer_filename] )
  2113.       }
  2114.    }
  2115. }
  2116.  
  2117. global function catch_file_open_error()
  2118. {
  2119.    file_error_prompt()
  2120. }     
  2121.  
  2122. local find_paths[]
  2123. local find_num = 1
  2124. global function findfirst_path( path_list )
  2125. {
  2126.    local first
  2127.    local path
  2128.    local mask
  2129.    local traversed
  2130.    local count = split( path_list, find_paths, ";" )
  2131.  
  2132.    while ( !first && count > traversed )
  2133.    {
  2134.       traversed++
  2135.  
  2136.       mask = path_fname( find_paths[traversed] ) path_ext( find_paths[traversed] )
  2137.       path = path_path( find_paths[traversed] )
  2138.    
  2139.       first = findfirst( path mask )
  2140.    }
  2141.  
  2142.    if ( !first )
  2143.    {
  2144.       delete find_paths
  2145.       find_num = 1
  2146.    }
  2147.    else
  2148.       find_num = traversed
  2149.  
  2150.    return first
  2151. }
  2152.  
  2153. global function findnext_path()
  2154. {
  2155.    local path
  2156.    local mask
  2157.    local more_paths = TRUE
  2158.    local next_file = findnext()
  2159.  
  2160.    while ( !next_file && more_paths )
  2161.    {
  2162.       if ( (find_num + 1) in find_paths )
  2163.       {
  2164.          find_num++
  2165.  
  2166.          mask = path_fname( find_paths[find_num] ) path_ext( find_paths[find_num] )
  2167.          path = path_path( find_paths[find_num] )
  2168.  
  2169.          next_file = findfirst( path mask )
  2170.       }
  2171.       else
  2172.          more_paths = FALSE
  2173.    }
  2174.    
  2175.    if ( !next_file )
  2176.    {
  2177.       delete find_paths
  2178.       find_num = 1
  2179.    }
  2180.  
  2181.    return next_file
  2182. }
  2183.  
  2184. global function current_find_path()
  2185. {
  2186.    local fpath
  2187.  
  2188.    if ( find_num in find_paths )
  2189.       fpath = path_path( find_paths[find_num] )
  2190.  
  2191.    return fpath
  2192. }
  2193.  
  2194. # this function is attached to the EVENT.TRACKING_DONE event handler.
  2195. # it simply creates a new window of the same size as the tracking 
  2196. # rectangle.  It accounts for one buffer per window.
  2197. global function create_track_window()
  2198. {
  2199.    local w1;
  2200.    local newBuffer;
  2201.  
  2202.    if ( (abs(tracking_width) >= 20) && (abs(tracking_height) >= 20) )
  2203.    {
  2204.       if(create_new_bufwin)
  2205.       {
  2206.          newBuffer = new_buffer_name();
  2207.       
  2208.          if(newBuffer)
  2209.          {
  2210.             create_buf_and_win(newBuffer, 0, tracking_left, tracking_bottom, tracking_width, tracking_height );
  2211.             buffer_flags = or(buffer_flags, BUFFER_SCRATCH);
  2212.          }
  2213.       }
  2214.       else
  2215.       {
  2216.          w1 = create_window( tracking_left, tracking_bottom, tracking_width, tracking_height )
  2217.          attach_window_buffer( w1, current_buffer )
  2218.          current_window = w1
  2219.       }
  2220.    }
  2221. }     
  2222.  
  2223. global function new_buffer_name()
  2224. {
  2225.    local BufNum         = 1;
  2226.    local newBuffer      = "Scratch.001"
  2227.    local buf_orig_name  = ""
  2228.    local scratch_list[]
  2229.    local start_buf
  2230.    local wf
  2231.  
  2232.    # loop through all buffers
  2233.    start_buf = current_buffer
  2234.    do
  2235.    {
  2236.       buf_orig_name = path_fname(buffer_original_filename) path_ext(buffer_original_filename)
  2237.       # if the buffer's name or its original name was Scratch.xxx, try
  2238.       # the next scratch num
  2239.       if ( tolower(buffer_name) ~ /scratch.[0-9][0-9][0-9]/ )
  2240.          scratch_list[ atoi(substr(buffer_name, 9)) ] = TRUE
  2241.       else if ( tolower(buf_orig_name) ~ /scratch.[0-9][0-9][0-9]/   )
  2242.          scratch_list[ atoi(substr(buf_orig_name, 9)) ] = TRUE
  2243.    }
  2244.    while ( start_buf != next_buffer("", 1, 1) )
  2245.  
  2246.    BufNum = 1
  2247.    while ( scratch_list[ BufNum ] )
  2248.       BufNum++
  2249.  
  2250.    while ( BufNum < 1000 )
  2251.    {
  2252.       newBuffer = sprintf("Scratch.%03d", BufNum)
  2253.  
  2254.       # if the file already exists skip it.
  2255.       if ( filemode( newBuffer ) == -1 )
  2256.       {
  2257.          break;
  2258.       }
  2259.  
  2260.       BufNum++
  2261.  
  2262.       while ( scratch_list[ BufNum ] && BufNum < 1000 )
  2263.          BufNum++
  2264.    }
  2265.  
  2266.    if ( BufNum >= 1000 )
  2267.    {
  2268.       warning("No more scratch buffers allowed!")
  2269.       newBuffer = "";
  2270.    }
  2271.  
  2272.    return newBuffer;
  2273. }
  2274.  
  2275.