home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / editors / epm / e_macros / stdprocs.e < prev    next >
Encoding:
Text File  |  1993-09-29  |  58.9 KB  |  1,780 lines

  1. compile if EVERSION >= 4 & EVERSION < '5.51'  -- 5.51 & above define this internally.
  2. defproc address(var varname) =
  3.    return selector(varname) || offset(varname)
  4. compile endif
  5.  
  6. ; A useful subroutine:  asks "Are you sure (Y/N)?" (same as DOS's prompt
  7. ; after "erase *.*") and returns uppercase keystroke.
  8. ; If called with a string parameter, displays it at start of prompt, e.g.
  9. ;   usersays = askyesno("About to erase.")
  10. ;   ==>   "About to erase. Are you sure (Y/N)? "
  11. ; EPM 5.12B:  Now enabled for EPM, using entrybox().  Optional second argument
  12. ; is a flag to prevent the "Are you sure" from being appended.
  13. ; EPM 5.15:  Now uses WinMessageBox to get Yes, No buttons.  [\toolktxx\c\include\pmwin.h]
  14. defproc askyesno
  15.    prompt=arg(1)
  16. compile if EVERSION < 5
  17.    if not arg(2) then
  18.       prompt=prompt || ARE_YOU_SURE_YN__MSG
  19.    endif
  20.    return upcase(mgetkey(prompt))     /* Accept key from macro. */
  21. compile else
  22.    if not arg(2) then
  23.       prompt=prompt\13 || ARE_YOU_SURE__MSG
  24.    endif
  25.    return substr(YES_CHAR || NO_CHAR, winmessagebox('', prompt, 16388) - 5, 1)  -- YESNO + MOVEABLE
  26. compile endif
  27.  
  28.  
  29. compile if EVERSION >= 4
  30. ; Does an atol of its argument, then a word reversal and returns the result.
  31. defproc atol_swap(num)
  32.    hwnd=atol(num)
  33.  compile if EVERSION >= '5.17'
  34.    return rightstr(hwnd,2) || leftstr(hwnd,2)
  35.  compile else
  36.    return substr(hwnd,3,2) || substr(hwnd,1,2)
  37.  compile endif
  38. compile endif
  39.  
  40.  
  41. defproc checkmark()        /* Common routine, save space.  from Jim Hurley.*/
  42.   if marktype()='' then
  43. compile if EPM
  44.     sayerror NO_MARK_HERE__MSG
  45. compile else
  46.     sayerror NO_MARK__MSG
  47. compile endif
  48.     stop
  49.   endif
  50.  
  51. ; Routine to tell if a mark is visible on the screen.  (Actually, only on the
  52. ; current window; if the window is less than full size, a mark could be visible
  53. ; in an inactive window without our being able to tell.)  Also, if a character
  54. ; mark begins above the top of the window and ends below the bottom, and the
  55. ; window contains only blank lines, then this routine will return 1 (since the
  56. ; mark spans the window) even though no sign of the mark will be visible.
  57. defproc check_mark_on_screen =
  58.    if marktype() = '' then return 0; endif  -- If no mark, then not on screen.
  59.    getmark first_mark_line, last_mark_line, first_mark_col, last_mark_col
  60.    first_screen_line = .line - .cursory + 1
  61.    last_screen_line = .line - .cursory + .windowheight
  62.    if last_mark_line < first_screen_line then return 0; endif
  63.    if first_mark_line > last_screen_line then return 0; endif
  64.    no_char_overlap = marktype()<>'CHAR' or first_mark_line=last_mark_line
  65.    if last_mark_col < .col - .cursorx + 1 and
  66.       (no_char_overlap or last_mark_line=first_screen_line)
  67.    then return 0; endif
  68.    if first_mark_col > .col - .cursorx + .windowwidth and
  69.       (no_char_overlap or first_mark_line=last_screen_line)
  70.    then return 0; endif
  71.    return 1
  72.  
  73. ; Tests whether the "filename" is actually a printer
  74. ; device, so we'll know whether to test printer readiness first.
  75. ; Called by savefile() in SAVELOAD.E.  Returns 0 if not, else printer number.
  76. defproc check_for_printer(name)
  77.    if not name then return 0; endif
  78. compile if EVERSION >= '5.50'
  79.    if leftstr(name,1)='"' & rightstr(name,1)='"' then
  80.       name=substr(name,2,length(name)-2)
  81.    endif
  82. compile endif
  83. compile if EVERSION >= '5.17'
  84.    if rightstr(name,1) = ':' then  -- a device
  85.       name = leftstr(name,length(name)-1)
  86. compile else
  87.    if substr(name,length(name),1) = ':' then  -- a device
  88.       name = substr(name,1,length(name)-1)
  89. compile endif
  90.    else       -- Might be a full pathspec, C:\EDIT\PRN, and still go to a device!
  91.       indx = lastpos('\',name)
  92.       if not indx then indx = lastpos(':',name) endif
  93.       if indx then name=substr(name,indx+1) endif
  94.       indx = pos('.',name)
  95.       if indx then name=substr(name,1,indx-1) endif
  96.    endif
  97.    if upcase(name)='PRN' then return 1; endif
  98. compile if EVERSION >= 4  -- Check_for_printer always returns true, so we don't need to distinguish COMn.
  99.    return (4+pos('.'upcase(name)'.','.LPT1.LPT2.LPT3.LPT4.LPT5.LPT6.LPT7.LPT8.LPT9.COM1.COM2.COM3.COM4.')) % 5
  100. compile else
  101.    return (4+pos('.'upcase(name)'.','.LPT1.LPT2.LPT3.')) % 5
  102. compile endif
  103.  
  104. compile if WANT_WINDOWS
  105. ; This proc is called only by DEFC EDIT in messy-desk mode.
  106. defproc create_window_for_each_file(emptyfileid)
  107.    fileidlist=''
  108.    activatefile emptyfileid /* Start list at beginning so we get 'em all.    */
  109.    nextfile                 /* Except first one, can leave one in each ring. */
  110.    loop
  111.       nextfile
  112.       .box=1
  113.       getfileid fileid
  114.       if fileid=emptyfileid then
  115.          leave
  116.       endif
  117.       fileidlist=fileidlist fileid
  118.    endloop
  119.    rest=fileidlist
  120.    loop
  121.       parse value rest with fileid rest
  122.       if fileid='' then
  123.          leave
  124.       endif
  125.       rc=0
  126.       newwindow fileid
  127.       if rc then leave endif
  128.       getfileid cur_fileid
  129.       activatefile fileid
  130.       quitview
  131.       activatefile cur_fileid
  132.    endloop
  133. compile endif
  134.  
  135.  
  136. COMPILE IF EVERSION >= 4
  137. defproc dec_to_string(string)    -- for dynalink usage
  138.    line = ''
  139.    for i = 1 to length(string)
  140.      line= line || asc(substr(string,i,1)) || ' '
  141.    endfor
  142.    return line
  143. COMPILE ENDIF
  144.  
  145. define
  146. compile if EVERSION >= '5.20'  -- 5.20 adds a HINI to the *Profile calls.
  147.    HINI_PARM = 'HINI_PROFILE,'
  148. compile else
  149.    HINI_PARM = ' '
  150. compile endif
  151.  
  152. defproc default_printer
  153. compile if defined(my_printer)
  154.    return MY_PRINTER
  155. compile elseif EPM
  156.    parse value queryprofile($HINI_PARM 'PM_SPOOLER', 'PRINTER') with printername ';'
  157.    if printername<>'' then
  158.       parse value queryprofile($HINI_PARM 'PM_SPOOLER_PRINTER', printername) with dev ';'
  159.       if dev<>'' then return dev; endif
  160.    endif
  161. compile endif
  162.    return 'LPT1'
  163.  
  164. ;  Returns DOS version number, multiplied by 100 so we can treat
  165. ;  it as an integer string.  That is, DOS 3.2 is reported as "320".
  166. ;  Needed by DEFPROC SUBDIR.
  167.  
  168. defproc dos_version()
  169. compile if E3
  170.    parse value int86x(DOS_INT,DOS_GET_VERSION,'') with ax .
  171.    major = ax // 256                  /* AL = major version number */
  172. ;  minor = (ax - major) % 256
  173.    return 100*major + (ax - major) % 256
  174. compile elseif EPM32
  175.       verbuf = copies(\0,8)
  176.       res= dynalink32('DOSCALLS',          /* dynamic link library name */
  177.                      '#348',              /* ordinal for DOS32QuerySysInfo */
  178.                      atol(11)         ||  -- Start index (Major version number)
  179.                      atol(12)         ||  -- End index (Minor version number)
  180.                      address(verbuf)  ||  -- buffer
  181.                      atol(8),2)           -- Buffer length
  182. ;     major = ltoa(leftstr(verbuf,4),10)
  183. ;     minor = ltoa(rightstr(verbuf,4),10)
  184.       return 100*ltoa(leftstr(verbuf,4),10) + ltoa(rightstr(verbuf,4),10)
  185. compile else
  186.       verbuf = 'nn'
  187.       res= dynalink('DOSCALLS',          /* dynamic link library name */
  188.                     '#92',               /* ordinal for DOSGETVERSION */
  189.                     address(verbuf))
  190. ;     major = asc(substr(verbuf,2,1))
  191. ;     minor = asc(substr(verbuf,1,1))
  192.       return 100*asc(substr(verbuf,2,1)) + asc(substr(verbuf,1,1))
  193. compile endif
  194.  
  195.  
  196. compile if WANT_ET_COMMAND     -- Let user omit ET command.
  197. defproc ec_position_on_error(tempfile)   /* load file containing error */
  198.    'xcom e 'tempfile
  199.    if rc then    -- Unexpected error.
  200.       sayerror ERROR_LOADING__MSG tempfile
  201.       if rc=-282 then 'xcom q'; endif  -- sayerror('New file')
  202.       return
  203.    endif
  204.    if .last<=4 then
  205.       getline msg,.last
  206.       'xcom q'
  207.    else
  208.       getline msg,2
  209. compile if EPM
  210.       if leftstr(msg,3)='(C)' then  -- 5.20 changed output
  211.          getline msg,4
  212.       endif
  213. compile endif
  214.       getline temp,.last
  215.       parse value temp with 'col= ' col
  216.       getline temp,.last-1
  217.       parse value temp with 'line= ' line
  218.       getline temp,.last-2
  219.       parse value temp with 'filename=' filename
  220.       'xcom q'
  221.       'e 'filename               -- not xcom here, respect user's window style
  222.       if line<>'' and col<>'' then
  223. compile if EPM
  224.          .cursory=min(.windowheight%2,.last)
  225. compile else
  226.          .cursory=15
  227. compile endif
  228.          if col>0 then
  229.             .col=col
  230.             line
  231.          else
  232.             .line=line-1   /* sometimes the compiler is off by 1 */
  233.             getline s
  234.             .col=length(s) /* position cursor at end of previous line */
  235.          endif
  236.       endif
  237.    endif
  238.    sayerror msg
  239. compile endif
  240.  
  241. defproc einsert_line
  242.    insert
  243.    up
  244.    getline line
  245.    parse value pmargins() with leftcol . paracol .
  246.    if line='' or not .line then
  247.       .col=paracol
  248.    else
  249.       call pfirst_nonblank()
  250.       if .col=paracol then .col=leftcol; endif
  251.    endif
  252.    down
  253.  
  254. compile if ENHANCED_ENTER_KEYS
  255. defproc enter_common(action)
  256.  compile if WANT_STREAM_MODE = 'SWITCH'
  257.    universal stream_mode
  258.    if stream_mode then
  259.  compile endif
  260.  compile if WANT_STREAM_MODE
  261.       if .line then
  262.          split
  263.          .col=1
  264.          down
  265.       else
  266.          insert
  267.          .col=1
  268.       endif
  269.       return
  270.  compile endif
  271.  compile if WANT_STREAM_MODE = 'SWITCH'
  272.    endif
  273.  compile endif
  274.  compile if WANT_STREAM_MODE <> 1
  275.    if .line = .last  & (action=3 | action=5) then  -- 'ADDATEND' | 'DEPENDS+'
  276.       call einsert_line()
  277.       down                       -- This keeps the === Bottom === line visible.
  278.       return
  279.    endif
  280. ;     'NEXTLINE' 'ADDATEND'                        'DEPENDS'  'DEPENDS+'
  281.    if action=2 | action=3 | (not insert_state() & (action=4 | action=5)) then
  282.       down                          -- go to next line
  283.       begin_line
  284.       return
  285.    endif
  286.    if action=6 then
  287.       call splitlines()
  288.       call pfirst_nonblank()
  289.       down
  290. ;;    refresh
  291.       return
  292.    endif
  293.    call einsert_line()           -- insert a line
  294.  compile endif  -- WANT_STREAM_MODE <> 1
  295. compile endif
  296.  
  297. ;  Erasetemp erases a file quietly (no "File not found" message) on both DOS
  298. ;  and OS/2.  Thanks to Larry Margolis.  Returns 0 if successful erase, or
  299. ;  the error code (if on DOS) which will usually be 2 for 'file not found'.
  300. defproc erasetemp(filename)
  301.    asciiz = filename\0
  302. compile if E3
  303.    call free()    -- Keep variables from moving around before int86x.
  304.    parse value int86x(DOS_INT,DOS_UNLINK 0 0 ofs(asciiz), seg(asciiz)) with ax . . . . . cf ',' .
  305.    -- Most callers will ignore error code, don't care file doesn't exist.
  306.    -- if cf then sayerror 'DOS error code' ax endif
  307.    if cf then return ax; endif
  308. compile elseif EPM32
  309.    return dynalink32('DOSCALLS',          /* dynamic link library name */
  310.                     '#259',               /* ordinal value for DOSDELETE */
  311.                     address(asciiz) )
  312. compile else
  313.    return dynalink('DOSCALLS',          /* dynamic link library name */
  314.                    '#60',               /* ordinal value for DOSDELETE */
  315.                    address(asciiz) ||
  316.                    atoi(0)         ||   /* reserved                  */
  317.                    atoi(0))             /* reserved                  */
  318. compile endif
  319.  
  320. compile if EPM
  321. defproc find_token(var startcol, var endcol)  -- find a token around the cursor.
  322.    if arg(3)='' then
  323.       token_separators = ' ~`!%^&*()-+=][{}|\:;?/><,'''\t
  324.    else
  325.       token_separators = arg(3)
  326.    endif
  327.    if arg(4)='' then
  328.       diads = '-> ++ -- << >> <= >= && || += -= *= /= %= ¬= &= |= ::'
  329.    else
  330.       diads = arg(4)
  331.    endif
  332.    getline line
  333.    len = length(line)
  334.    if .col>len | pos(substr(line, .col, 1), ' '\t) then
  335.       return  -- Past end of line, or over whitespace
  336.    endif
  337.    endcol = verify(line, token_separators, 'M', .col)
  338.    if endcol = .col then  -- On an operator.
  339.       startcol = endcol
  340.       if wordpos(substr(line, startcol, 2), diads) then
  341.          endcol = endcol + 1  -- On first character
  342.       elseif .col > 1 then
  343.          if wordpos(substr(line, endcol-1, 2), diads) then
  344.             startcol = startcol - 1  -- -- On last character
  345.          endif
  346.       endif
  347.       return 2
  348.    endif
  349.    if endcol then
  350.       endcol = endcol - 1
  351.    else
  352.       endcol = len
  353.    endif
  354.    startcol = verify(reverse(line), token_separators, 'M', len - .col + 1)
  355.    if startcol then
  356.       startcol = len - startcol + 2
  357.    else
  358.       startcol = 1
  359.    endif
  360.    return 1
  361. compile endif
  362.  
  363. ; Note on a speed trick:  The following routine is used to both verify that
  364. ; an external program exists, and to get its path.  After that first search,
  365. ; the exact path location of the routine is known; it can be remembered so that
  366. ; all future calls can supply the exact location to avoid the path search.
  367. ; See SUBDIR for an example of its use.
  368.  
  369. defproc find_routine(utility)  -- Split from SUBDIR
  370.    parse arg util opts         -- take first word, so can pass options too.
  371.    findfile fully_qualified,util,'PATH','P'
  372.    if rc then return -1 endif
  373. compile if E3
  374.    if dos_version() < 300 then
  375.       return utility             --DOS 2 can't handle the path
  376.    endif                         --in front of the command.
  377. compile endif
  378.    return fully_qualified opts
  379.  
  380. compile if EVERSION >='5.50'    -- For GPI version, we must manage the cursor ourself
  381. defproc fixup_cursor()
  382.  compile if UNDERLINE_CURSOR
  383.    cursorh = 3 - 67*insert_state()         -- 0 -> 3; 1 -> -64
  384.    cursorw = '-128'
  385.  compile else
  386.    cursorw = 2 - 130*(not insert_state())  -- 0 -> -128; 1 -> 2
  387.    cursorh = '-128'
  388.  compile endif
  389.    cursor_dimensions cursorw, cursorh
  390. compile endif
  391.  
  392. compile if EVERSION < 5
  393. defproc init_operation_on_commandline
  394.    universal comsfileid,oldline
  395.    if command_state() then
  396.       activatefile comsfileid
  397.       oldline=.line
  398.       getcommand line,col,scrollpos
  399.       insertline line,.last+1
  400.       .cursorx=col-scrollpos+1
  401.       .col=col
  402.       bottom
  403.    endif
  404. compile endif
  405.  
  406. ; Returns true if parameter given is a number.
  407. ; Leading and trailing spaces are ignored.
  408. defproc isnum
  409.    zzi=pos('-',arg(1))           -- Optional minus sign?
  410.    if zzi then                   -- If there is one,
  411.       parse arg zz1 '-' zz zz2   --   zz1 <- before it, zz <- number, zz2 <- after
  412.    else
  413.       parse arg zz zz1 zz2       --   zz <- number; zz1, zz2 <- after it
  414.    endif
  415.    zz=strip(zz)                  -- Delete leading & trailing spaces.
  416.    if zz1||zz2 <> '' or          -- If there were more tokens on the line
  417.       zz==''                     -- or if the result is null
  418.    then return 0 endif           -- then not a number.
  419. compile if EVERSION >= 4         -- OS/2 version - real numbers
  420.    if pos(DECIMAL,zz) <> lastpos(DECIMAL,zz) then return 0 endif
  421.                                  -- Max. of one decimal point.
  422.    return not verify(zz,'0123456789'DECIMAL)
  423. compile else                        -- DOS version - integers only
  424.    return not verify(zz,'0123456789')
  425. compile endif
  426.  
  427. defproc isoption(var cmdline,optionletter)
  428.    i=pos(argsep||upcase(optionletter),upcase(cmdline))
  429.    if i then
  430. compile if EPM
  431.       cmdline=delstr(cmdline,i,2)
  432. compile else
  433.       cmdline=substr(cmdline,1,i-1)||substr(cmdline,i+2)
  434. compile endif
  435.       return 1
  436.    endif
  437.  
  438. defproc joinlines()
  439.    if .line<.last and .line then
  440. compile if EPM           -- Can't use REPLACELINE because it wipes out attributes.
  441.       oldcol = .col
  442.       down                   -- ensure one space at start of second line
  443.       call pfirst_nonblank()
  444.       col2 = .col
  445.       .col = 1
  446.       getsearch savesearch
  447.       if col2 > 2 then       -- Shift line left
  448.          'xcom c/'copies(' ',col2-2)'//'  -- Change first n-1 blanks to null
  449.       elseif col2=1 then     -- Shift line right
  450. ;        'xcom c/^/ /g'         -- insert a space at beginning of line
  451.          i=insert_state()
  452.          if not i then insert_toggle endif
  453.          keyin ' '
  454.          if not i then insert_toggle endif
  455.       endif
  456.       setsearch savesearch
  457.       up                     -- ensure no spaces at end of first line
  458.       .col = length(strip(textline(.line),'T')) + 1
  459.       erase_end_line
  460.       .col = oldcol
  461. compile else           -- E3 and EOS2 can still use the old, simple way.
  462.       /* remove all but one trailing space of current line */
  463.       getline line
  464.       replaceline strip(line,'T')' '
  465.       /* remove all leading spaces of next line */
  466.       getline line,.line+1
  467.       replaceline strip(line),.line+1
  468. compile endif
  469.       join
  470.    endif
  471.  
  472. compile if EVERSION < 5
  473. defproc leave_last_command
  474.    if (not arg() or arg(2)) and arg(1) then
  475.       cursor_command
  476.       up
  477.       for i = 1 to arg(1)-1
  478.          right
  479.       endfor
  480.    endif
  481. compile endif
  482.  
  483. compile if WANT_LAN_SUPPORT
  484. defproc lock
  485.    file=.filename\0
  486.  compile if EPM32
  487.    newhandle='????'
  488.    actiontaken=atol(1)   -- File exists
  489.    result = dynalink32('DOSCALLS',
  490.                       '#273',                     /* dos32open          */
  491.                       address(file)         ||
  492.                       address(newhandle)    ||
  493.                       address(actiontaken)  ||
  494.                       atol(0)    ||       -- file size
  495.                       atol(0)    ||       -- file attribute
  496.                       atol(17)   ||       -- open flag; open if exists, else create
  497.                       atol(146)  ||       -- openmode; deny Read/Write
  498.                       atol(0),2)
  499.  compile else
  500.    newhandle='??'
  501.    actiontaken=atoi(1)   -- File exists
  502.    result = dynalink('DOSCALLS',
  503.                      '#70',                     /* dosopen          */
  504.                      address(file)        ||
  505.                      address(newhandle)   ||
  506.                      address(actiontaken) ||
  507.                      atol(0)              || -- file size
  508.                      atoi(0)              || -- file attribute
  509.                      atoi(17)             || -- open flag; open if exists, else create
  510.                      atoi(146)            || -- openmode; deny Read/Write
  511.                      atol(0))
  512.  compile endif
  513.    if result then
  514. ;     'quit'  /* quit since the file could not be locked */
  515.       messageNwait('DOSOPEN' ERROR__MSG result NOT_LOCKED__MSG)
  516.       return result
  517.    endif
  518.  compile if EPM32
  519.    if newhandle = \0\0\0\0 then  -- Handle of 0 - bad news
  520.       newhandle2=\255\255\255\255
  521.       result = dynalink32('DOSCALLS',
  522.                          '#260',                     /* Dos32DupHandle     */
  523.                          newhandle ||
  524.                          address( newhandle2 ), 2)
  525.       call dynalink32('DOSCALLS',    -- Free the original handle
  526.                      '#257',                    -- dos32close
  527.                      newhandle, 2)
  528.       if result then
  529.          messageNwait('DosDupHandle' ERROR__MSG result NOT_LOCKED__MSG)
  530.          return result
  531.       endif
  532.       newhandle = newhandle2
  533.    endif
  534.    .lockhandle=ltoa(newhandle,10)
  535.  compile else
  536.    if newhandle = \0\0 then  -- Handle of 0 - bad news
  537.       newhandle2=atoi(65535)
  538.       result = dynalink('DOSCALLS',
  539.                         '#61',                     /* DosDupHandle     */
  540.                         newhandle ||
  541.                         address( newhandle2 ))
  542.       call dynalink('DOSCALLS',    -- Free the original handle
  543.                     '#59',                    -- dosclose
  544.                     newhandle)
  545.       if result then
  546.          messageNwait('DosDupHandle' ERROR__MSG result NOT_LOCKED__MSG)
  547.          return result
  548.       endif
  549.       newhandle = newhandle2
  550.    endif
  551.    .lockhandle=itoa(newhandle,10)
  552.  compile endif
  553. compile endif
  554.  
  555. defproc max(a,b)  -- Support as many arguments as E3 will allow.
  556.    maximum=a
  557.    do i=2 to arg()
  558.       if maximum<arg(i) then maximum=arg(i); endif
  559.    end
  560.    return maximum
  561.  
  562. compile if E3
  563. definit  /* Keep this definit close to the proc it serves. */
  564.    universal lines_entered
  565.    lines_entered=0
  566.  
  567. defproc maybe_autosave    -- For E3 users, this routine increments the autosave
  568.    universal autosave,lines_entered  -- counter, and does an autosave if necessary.
  569.    if autosave then
  570.       lines_entered = lines_entered +1
  571.       if lines_entered >= autosave then
  572.          'xcom save' MakeTempName()  -- Don't worry about HPFS files in E3.
  573.          if rc=-2  then  -- sayerror('File not found') -> Invalid filename
  574.             'xcom save' MakeTempName('BAD-NAME')
  575.          endif
  576.          .modify=1                  /* Reraise the modify flag. */
  577.          lines_entered =0
  578.       endif
  579.    endif
  580. compile endif
  581.  
  582.  
  583. compile if BACKUP_PATH <> ''
  584. ;  Procedure to pick a filename for backup purposes, like STDPROCS.E$.
  585. defproc MakeBakName
  586.    name = arg(1)
  587.    if name = '' then   /* if no arg given, default to current filename */
  588.       name = .filename
  589.    endif
  590.    -- Change name as little as possible, but enough to identify it as
  591.    -- a noncritical file.  Replace the last character with '$'.
  592.    ext = filetype(name)
  593.    if length(ext)=3 then
  594.       ext = substr(ext,1,2)'$'
  595.    else
  596.       ext = ext'$'
  597.    endif
  598.    -- We still use MakeTempName() for its handling of host names.
  599.    bakname = MakeTempName(name)
  600.    i=lastpos('\',bakname)       -- but with a different directory
  601.    if i then
  602.       bakname = substr(bakname,i+1)
  603.    endif
  604.    parse value bakname with fname'.'.
  605.  compile if BACKUP_PATH = '='
  606.    bakname = fname'.'ext
  607.    i=lastpos('\',name)       -- Use original file's directory
  608.    if i then
  609.       bakname = substr(name,1,i) || bakname
  610.    endif
  611.  compile else
  612.    bakname = BACKUP_PATH || fname'.'ext
  613.  compile endif
  614.    return bakname
  615. compile endif
  616.  
  617.  
  618. ;  Procedure to pick a temporary filename like ORIGNAME.$$1.
  619. ;  First argument is the filename, 2nd is the fileid.  Both are optional,
  620. ;  default to the current filename and fileid if absent.
  621. ;  Revised by BTTUCKER to catch all cases and work with E3EMUL.
  622. defproc MakeTempName
  623.    universal vAUTOSAVE_PATH
  624.    TempName  = arg(1)
  625.    extension = arg(2)
  626.    if TempName = '' then   /* if no arg given, default to current filename */
  627.       TempName = .filename
  628.    endif
  629.    if TempName = '' then
  630.       TempName = '$'       /* new file? o.k. then $  */
  631.    else /* We want only PC file name, VM filename, or MVS firstname          */
  632.         /* These next statements will strip everything else off...           */
  633.      p = lastpos('\',TempName)                      /* PC filename with path */
  634.      if p then TempName=substr(TempName,p+1) endif
  635.      p = pos('.',TempName)                          /* PC or MVS filename    */
  636.      if p then TempName=substr(TempName,1,p-1) endif
  637.      p = pos(' ',TempName)                          /* VM filename (or HPFS) */
  638.      if p then TempName=substr(TempName,1,p-1) endif
  639.      p = pos(':',TempName)                          /* VM or MVS filename    */
  640.      if p then TempName=substr(TempName,p+1) endif
  641.      p = pos("'",TempName)                          /* MVS filename          */
  642.      if p then TempName=substr(TempName,p+1) endif
  643.      if length(tempname)>8 then tempname=substr(tempname,1,8); endif  /* HPFS names */
  644.    endif
  645.  
  646.    -- TempName might still be blank, as for '.Unnamed file'.
  647.    if TempName='' then TempName='$'; endif
  648.  
  649.    TempName = vAUTOSAVE_PATH || TempName
  650.    if extension='' then            /* default is current fileid              */
  651.       getfileid extension
  652.    endif
  653. compile if EVERSION < 5
  654.    extension = '$$' || extension
  655. compile else
  656.    /* In EPM we can have the same filename in multiple edit windows without
  657.     * knowing it, because different edit windows are actually separate
  658.     * instances of the editor.  So try to make the tempname unique by
  659.     * combining the window handle with the fileid.  Combine two middle
  660.     * digits of the window handle with the last digit of the fileid.
  661.     */
  662.    extension = substr(getpminfo(EPMINFO_EDITCLIENT),2,2) || extension
  663. compile endif
  664.    if length(extension)>3 then     /* could be >one digit, or something else */
  665.       extension=substr(extension,2,3)
  666.    endif
  667.    return TempName'.'extension
  668.  
  669. defproc message
  670.    getfileid fileid
  671.    sayerror arg(1)
  672.    activatefile fileid
  673.  
  674. ; Print message and wait for a key press.
  675. ; Preserve active file and activate ring.
  676. ; Note:  There is no need to use "call" to invoke this procedure,  since it
  677. ; returns the null string.  Execution of a null string does nothing
  678. defproc messageNwait
  679.    getfileid zzfileid
  680. compile if EPM
  681.    display -4                    -- Force a messagebox popup from the SAYERROR
  682.  compile if EVERSION >= '5.60b'
  683.    display 32                    -- Force a messagebox popup from the SAYERROR
  684.  compile endif
  685. compile endif
  686.    sayerror arg(1)
  687. compile if EVERSION < 5
  688.    call getkey()
  689. compile else
  690.  compile if EVERSION >= '5.60b'
  691.    display -32
  692.  compile endif
  693.    display 4
  694. compile endif
  695.    activatefile zzfileid
  696.  
  697. compile if EVERSION < 5
  698. ; Mgetkey() acts the same as a call to getkey(), but first checks
  699. ; whether we're in mid-execution of a key-string (Ctrl-R/Ctrl-T).
  700. ; If so it gets the next key from the string.  Call this in place of
  701. ; getkey() if you want the user to be able to record the response.
  702. ; Don't call this for unusual inputs, such as messageNwait after errors.
  703.  
  704. ; Optional argument is prompt string, will be displayed on status line.
  705.  
  706. defproc mgetkey()
  707.    universal Kstring,inKstring          /* See c_r in STDKEYS.E. */
  708.    prompt=arg(1)
  709.    if prompt<>'' and inKstring<=0 then
  710.       sayerror prompt
  711.    endif
  712.    if inKstring=0 then     /* If not recording or replaying, normal input. */
  713.       k=getkey()
  714.    elseif inKstring=-1 then /* If recording, stash key in string.          */
  715.       k=getkey()
  716.       Kstring=Kstring||k   /* Trust that it doesn't get longer than 255.   */
  717.    else           /* inKstring>0 ==> replaying; get next key from Kstring. */
  718.       k=substr(Kstring,inKstring,1)
  719.       ksize=1
  720.       if k==substr(esc,1,1) then       /* extended key ? */
  721.          k=substr(Kstring,inKstring,2) /* Yes, 2 bytes for extended key.   */
  722.          ksize=2
  723.       endif
  724.       inKstring=inKstring+ksize        /* bump index AFTER execution */
  725.    endif
  726.    if prompt<>'' and inKstring<=0 then
  727.       sayerror 0
  728.    endif
  729.    return k
  730. compile endif
  731.  
  732. defproc min(a,b)  -- Support as many arguments as E3 will allow.
  733.    minimum=a
  734.    do i=2 to arg()
  735.       if minimum>arg(i) then minimum=arg(i); endif
  736.    end
  737.    return minimum
  738.  
  739. compile if EVERSION < 5
  740. defproc move_results_to_commandline
  741.    universal oldline
  742.    if command_state() then
  743.       getline line
  744.       deleteline
  745.       setcommand line,.col,.col-.cursorx+1
  746.       oldline
  747.    endif
  748. compile endif
  749.  
  750. ; The following two routines (from Larry Margolis) let the
  751. ; user decide what action should be taken when the Enter and Ctrl-Enter
  752. ; keys are pressed.  The possible values for the action constants are
  753. ; defined in STDCNF.
  754.  
  755. compile if C_ENTER_ACTION & not ENHANCED_ENTER_KEYS  -- If null, don't define - user will supply.
  756. defproc my_c_enter
  757.    compile if C_ENTER_ACTION = 'ADDATEND' | C_ENTER_ACTION = 'DEPENDS+'
  758.    if .line = .last then         -- If we're on the last line, then add a line.
  759. compile if EVERSION < '4.12'
  760.       call maybe_autosave()
  761. compile endif
  762.       call einsert_line()
  763.       down                       -- This keeps the === Bottom === line visible.
  764.    else
  765.    compile endif
  766.  
  767.    compile if C_ENTER_ACTION = 'DEPENDS' | C_ENTER_ACTION = 'DEPENDS+'
  768.    if insert_state() then        -- DEPENDS means if insertstate() then ...
  769.    compile endif
  770.  
  771.    compile if C_ENTER_ACTION = 'NEXTLINE' | C_ENTER_ACTION = 'DEPENDS' |
  772.               C_ENTER_ACTION = 'ADDATEND' | C_ENTER_ACTION = 'DEPENDS+'
  773.    down                          -- go to next line
  774.    begin_line
  775.    compile endif
  776.  
  777.    compile if C_ENTER_ACTION = 'DEPENDS' | C_ENTER_ACTION = 'DEPENDS+'
  778.    else                          -- otherwise ...
  779.    compile endif
  780.  
  781.    compile if C_ENTER_ACTION = 'ADDLINE' | C_ENTER_ACTION = 'DEPENDS' | C_ENTER_ACTION = 'DEPENDS+'
  782. compile if EVERSION < '4.12'
  783.    call maybe_autosave()
  784. compile endif
  785.    call einsert_line()           -- insert a line
  786.    compile endif
  787.  
  788.    compile if C_ENTER_ACTION = 'DEPENDS' | C_ENTER_ACTION='ADDATEND' | C_ENTER_ACTION = 'DEPENDS+'
  789.    endif
  790.    compile endif
  791.  
  792.    compile if C_ENTER_ACTION = 'DEPENDS+'
  793.    endif
  794.    compile endif
  795.  
  796.    compile if C_ENTER_ACTION = 'STREAM'
  797.    call splitlines()
  798.    call pfirst_nonblank()
  799.    down
  800.     compile if EPM
  801.    refresh
  802.     compile endif
  803.    compile endif
  804. compile endif
  805.  
  806. compile if not ENHANCED_ENTER_KEYS & ENTER_ACTION   -- If null, don't define - user will supply.
  807. defproc my_enter
  808.  compile if WANT_STREAM_MODE = 'SWITCH'
  809.    universal stream_mode
  810.  compile endif
  811.  compile if EVERSION < 5
  812.    if command_state() then
  813.       execute
  814.  compile else
  815.    if 0 then   -- EPM has no command_state()
  816.  compile endif
  817.  compile if WANT_STREAM_MODE = 'SWITCH'
  818.    elseif stream_mode then
  819.  compile endif
  820.  compile if WANT_STREAM_MODE
  821.       if .line then
  822.          split
  823.          .col=1
  824.          down
  825.       else
  826.          insert
  827.          .col=1
  828.       endif
  829.       return
  830.  compile endif
  831.  compile if WANT_STREAM_MODE <> 1
  832.  compile if ENTER_ACTION = 'ADDATEND' | ENTER_ACTION = 'DEPENDS+'
  833.    elseif .line = .last then     -- If we're on the last line, then add a line.
  834. compile if EVERSION <= '4.12'
  835.       call maybe_autosave()
  836. compile endif
  837.       call einsert_line()
  838.       down                       -- This keeps the === Bottom === line visible.
  839.  compile endif
  840.    else
  841.       compile if ENTER_ACTION = 'DEPENDS' | ENTER_ACTION = 'DEPENDS+'
  842.       if insert_state() then     -- DEPENDS means if insertstate() then ...
  843.       compile endif
  844.  
  845.       compile if ENTER_ACTION = 'ADDLINE' | ENTER_ACTION = 'DEPENDS' | ENTER_ACTION = 'DEPENDS+'
  846. compile if EVERSION < '4.12'
  847.       call maybe_autosave()
  848. compile endif
  849.       call einsert_line()        -- insert a line
  850.       compile endif
  851.  
  852.       compile if ENTER_ACTION = 'DEPENDS' | ENTER_ACTION = 'DEPENDS+'
  853.       else                       -- otherwise ...
  854.       compile endif
  855.  
  856.       compile if ENTER_ACTION = 'NEXTLINE' | ENTER_ACTION = 'DEPENDS' |
  857.                  ENTER_ACTION = 'ADDATEND' | ENTER_ACTION = 'DEPENDS+'
  858.       down                       -- go to next line
  859.       begin_line
  860.       compile endif
  861.  
  862.       compile if ENTER_ACTION = 'DEPENDS' | ENTER_ACTION = 'DEPENDS+'
  863.       endif
  864.       compile endif
  865.  
  866.       compile if ENTER_ACTION = 'STREAM'
  867.       if .line then
  868.          if .col<=length(textline(.line)) then
  869.             split
  870.             .col=1
  871.          else
  872.             split
  873.             call pfirst_nonblank()
  874.          endif
  875.          down
  876.       else
  877.          insert
  878.          .col=1
  879.       endif
  880.        compile if EPM
  881.       refresh
  882.        compile endif
  883.       compile endif
  884.  compile endif  -- WANT_STREAM_MODE <> 1
  885.    endif
  886. compile endif
  887.  
  888.  
  889. ;  A common routine to parse an argument string containing a mix of
  890. ;  options and DOS file specs.  The DOS file specs can contain an "=" for the
  891. ;  path or the fileid, which will be replaced by the corresponding part of the
  892. ;  previous file (initially, the current filename).
  893. defproc parse_file_n_opts(argstr)
  894.    prev_filename = .filename
  895.    output = ''
  896.    do while argstr<>''
  897. compile if EVERSION >= '5.50'
  898.       parse value argstr with filename rest
  899.       if leftstr(filename,1)='"' then
  900.          parse value argstr with '"' filename '"' argstr
  901.          filename = '"'filename'"'
  902.       else
  903.          argstr = rest
  904.       endif
  905. compile else
  906.       parse value argstr with filename argstr
  907. compile endif
  908.       if substr(filename,1,1)<>'/' then
  909.          call parse_filename(filename,prev_filename)
  910.          prev_filename = filename
  911.       endif
  912.       output = output filename
  913.    end
  914.    return substr(output,2)
  915.  
  916. ;  A common routine to parse a DOS file name.  Optional second argument
  917. ;  gives source for = when used for path or fileid.  RC is 0 if successful, or
  918. ;  position of "=" in first arg if no second arg given but was needed.
  919. defproc parse_filename(var filename)
  920. compile if EVERSION >= '5.50'
  921.    if leftstr(filename,1)='"' & rightstr(filename,1)='"' then
  922.       return 0
  923.    endif
  924. compile endif
  925.    sourcefile = strip(arg(2))
  926.    if sourcefile='' then return pos('=',filename) endif
  927.  
  928.    if filename='=' then filename=sourcefile; return 0; endif
  929.  
  930.    lastsep = lastpos('\',sourcefile)
  931.    if not lastsep & substr(sourcefile,2,1) = ':' then lastsep=2; endif
  932.  
  933.    /* E doesn't handle the = prefix if it's on the first file given on      */
  934.    /* the E command line.  This replaces = with path of current file.  LAM  */
  935.    if substr(filename,1,1) = '=' & lastsep then
  936.       if substr(filename,2,1) = '.' then filename='='filename endif
  937.       filename=substr(sourcefile,1,lastsep) || substr(filename,2)
  938.    endif
  939.  
  940.    /* Also accept '=' after the pathspec, like 'c:\bat\=', */
  941.    /* or c:\bat\=.bat or c:\doc\new.=                      */
  942.    p = pos('=',filename)
  943.    if p > 1 then
  944.       sourcefileid=substr(sourcefile,max(lastsep+1,1))
  945.       parse value sourcefileid with sourcefilename '.' sourcefileext
  946.       lastsep2 = lastpos('\',filename)
  947.       if not lastsep2 & substr(filename,2,1) = ':' then lastsep2=2; endif
  948.       dot1=pos('.',filename,max(lastsep2,1))
  949.       firstpart=substr(filename,1,p-1)
  950.       if dot1 then
  951.          if dot1<p then  -- filename.=
  952.             filename= firstpart || sourcefileext
  953.          else            -- =.ext
  954.             filename= firstpart || sourcefilename || substr(filename,dot1)
  955.          endif
  956.       else            -- d:\path\         ||        filename.ext
  957.          filename= firstpart || sourcefileid
  958.       endif -- dot1
  959.    endif -- p > 1
  960.    return 0
  961.  
  962. ;  This proc is called by DEFC EDIT.
  963. ;  Does *not* assume all options are specified before filenames.
  964. defproc parse_leading_options(var rest,var options)
  965.    options=''
  966.    loop
  967.       parse value rest with wrd more
  968.       if substr(wrd,1,1)='/' then
  969.          options = options wrd
  970.          rest = more
  971.       else
  972.          leave
  973.       endif
  974.    endloop
  975.  
  976.  
  977. ; PBEGIN_MARK: this procedure moves the cursor to the first character of the
  978. ; mark area.  If the mark area is not in the active file, the marked file is
  979. ; activated.
  980. defproc pbegin_mark
  981.    call checkmark()
  982.    getmark  firstline,lastline,firstcol,lastcol,fileid
  983.    activatefile fileid
  984. compile if EVERSION < 5
  985.    cursor_data
  986. compile endif
  987.    firstline
  988.    if marktype()<>'LINE' then
  989.       .col=firstcol
  990.    endif
  991.  
  992.  
  993. ; PBEGIN_WORD: moves the cursor to the beginning of the word if the cursor is on
  994. ; this word.  If it's not on a word, it's moved to the beginning of the first
  995. ; word on the left.  If there is no word on the left it's moved to the beginning
  996. ; of the word on the right.  If the line is empty the cursor doesn't move.
  997. defproc pbegin_word
  998.    getline line,.line
  999.    if  substr(line,.col,1)=' ' then
  1000.       p=verify(line,' ')       /* 1st case: the cursor on a space */
  1001.       if p>=.col then
  1002.          .col=p
  1003.       else
  1004.          if p then
  1005.             q=p
  1006.             loop
  1007.                p=verify(line,' ','M',p)
  1008.                if not p or p>.col then leave endif
  1009.                p=verify(line,' ','',p)
  1010.                if not p or p>.col then leave endif
  1011.                q=p
  1012.             endloop
  1013.             .col=q
  1014.          endif
  1015.       endif
  1016.    else
  1017.       if .col<>1 then          /* 2nd case: not on a space */
  1018.          .col=lastpos(' ',line,.col)+1
  1019.       endif
  1020.    endif
  1021.  
  1022.  
  1023. ; PBLOCK_REFLOW: reflow the text in the marked area.  Then the destination block
  1024. ; area must be selected and a second call to this procedure reflow the source
  1025. ; block in the destination block.  The source block is fill with spaces.
  1026. ;   option=0 saves the marked block in temp file
  1027. ;   option=1 reflow temp file text and copies it to marked area
  1028. defproc pblock_reflow(option,var spc,var tempofid)
  1029.    call checkmark()
  1030.    if not option then
  1031.       usedmk=marktype()
  1032.       getmark  firstline1,lastline1,firstcol1,lastcol1,fileid1
  1033.       /* move the source mark to a temporary file */
  1034. compile if EPM
  1035.       'xcom e /c .tempo'
  1036.       if rc<>sayerror('New file') then
  1037.          sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  1038.          return rc
  1039.       endif
  1040.       .visible = 0                                  -- Make hidden
  1041. compile else
  1042.       'xcom e 'argsep'q 'argsep'n 'argsep'h .tempo'
  1043.       if rc & rc<>sayerror('New file') then
  1044.          sayerror ERROR__MSG rc BAD_TMP_FILE__MSG
  1045.          return rc
  1046.       endif
  1047.       sayerror 1
  1048. compile endif
  1049.       getfileid tempofid
  1050.       activatefile tempofid
  1051.       call pcopy_mark()
  1052.       activatefile fileid1
  1053. compile if EVERSION < 5
  1054.       cursor_data
  1055. compile endif
  1056.       call pset_mark(firstline1,lastline1,firstcol1,lastcol1,usedmk,fileid1)
  1057.       if usedmk='LINE' then
  1058.          begin_line
  1059.       endif
  1060.       spc=usedmk firstline1 lastline1 firstcol1 lastcol1 fileid1
  1061.       return 0
  1062.    else
  1063.       getfileid startfid
  1064.       if marktype() <> 'BLOCK' then
  1065.          sayerror NEED_BLOCK_MARK__MSG
  1066.          /* release tempo */
  1067.          rc=0
  1068.          activatefile tempofid
  1069.          if rc then return rc; endif
  1070.          .modify=0
  1071.          'xcom q'
  1072.          activatefile startfid
  1073.          return 1
  1074.       endif
  1075. compile if EPM  -- Make sure temp file is good before deleting current file's text.
  1076.       rc=0
  1077.       activatefile tempofid
  1078.       if rc then return rc; endif
  1079.       activatefile startfid
  1080. compile endif
  1081.       parse value spc with usedmk firstline1 lastline1 firstcol1 lastcol1 fileid1
  1082.       getmark  firstline2,lastline2,firstcol2,lastcol2,fileid2
  1083.       /* fill source with space */
  1084.       if usedmk='LINE' then
  1085.          for i = firstline1 to lastline1
  1086.             replaceline '',i,fileid2
  1087.          endfor
  1088.       else
  1089.          call pset_mark(firstline1,lastline1,firstcol1,lastcol1,usedmk,fileid1)
  1090.          call pfill_mark(' ')
  1091.       endif
  1092.       call pset_mark(firstline2,lastline2,firstcol2,lastcol2,'BLOCK',fileid2)
  1093.       delete_mark
  1094.       /* let's reflow in the hidden file */
  1095.       activatefile tempofid
  1096.       width = lastcol2+1-firstcol2
  1097.       height = lastline2+1-firstline2
  1098. compile if EVERSION < '4.12'
  1099.       savemargins= pmargins()
  1100. compile endif
  1101.       'xcom ma 1 'width
  1102.       unmark; mark_line; bottom; mark_line
  1103.       reflow
  1104. compile if EVERSION < '4.12'
  1105.       'xcom ma 'savemargins
  1106. compile endif
  1107.       nbl = .last
  1108.       /* go back to the destination */
  1109.       activatefile fileid2
  1110.       if nbl > height then
  1111.          fix = nbl-height
  1112.          getline line,lastline2
  1113.          for i = 1 to fix
  1114.             insertline line,lastline2+1
  1115.          endfor
  1116.       elseif nbl < height then
  1117.          fix=0
  1118.          for i = nbl+1 to height
  1119.             insertline '',tempofid.last+1,tempofid
  1120.          endfor
  1121.          nbl=height
  1122.       else
  1123.          fix=0
  1124.       endif
  1125.       call pset_mark(1,nbl,1,width,'BLOCK',tempofid)
  1126.       firstline2; .col=firstcol2; copy_mark; unmark
  1127.       call pset_mark(firstline2,lastline2+fix,firstcol2,lastcol2,'BLOCK',fileid2)
  1128.       /* release tempo */
  1129.       activatefile tempofid
  1130.       .modify=0
  1131.       'xcom q'
  1132.       activatefile fileid2
  1133.       sayerror 1
  1134.     endif
  1135.  
  1136.  
  1137. ; PCENTER_MARK: center the strings between the block marks
  1138. defproc pcenter_mark
  1139.    if  marktype() = 'BLOCK' then
  1140.       getmark  firstline,lastline,firstcol,lastcol,fileid
  1141.    elseif marktype() = 'LINE' then
  1142.       getmark  firstline,lastline,firstcol,lastcol,fileid
  1143.       parse value pmargins() with  firstcol lastcol .
  1144.    elseif marktype() = '' then
  1145.       getfileid fileid
  1146.       parse value pmargins() with  firstcol lastcol .
  1147.       firstline=.line;lastline=.line
  1148.    else
  1149.       sayerror CHAR_INVALID__MSG
  1150.       stop
  1151.    endif
  1152.    sz = lastcol+1-firstcol
  1153.    for i=firstline to lastline
  1154.       getline line,i,fileid
  1155.       inblock=strip(substr(line,firstcol,sz))
  1156.       if inblock='' then iterate endif
  1157. compile if EPM
  1158.       replaceline strip(overlay(center(inblock, sz), line, firstcol),'T'), i, fileid
  1159. compile else
  1160.       replaceline substr(line,1,firstcol-1) ||
  1161.          substr(substr('',1,(sz-length(inblock))%2)||inblock,1,sz) ||
  1162.          substr(line,lastcol+1) ,i,fileid
  1163. compile endif
  1164.    endfor
  1165.  
  1166.  
  1167. compile if EVERSION < 5
  1168. ;  A built-in function command_state() is now provided for better
  1169. ;  efficiency.  This defproc is kept only for compatibility with older macros.
  1170. ;  Please use command_state() instead.
  1171. defproc pcommand_state
  1172.    return command_state()
  1173.  
  1174.  
  1175. ; PCOMMON_TAB_MARGIN: subroutine common to ptabs and pmargins
  1176.  
  1177. defproc pcommon_tab_margin(TabOrMargins)
  1178. ;    the tricky stuff:  execute ma (or tabs) and get the result from coms.e file
  1179.    getcommand oldcmd,oldcol,oldscroll    -- Save old cmdline status
  1180.    TabOrMargins                          -- Execute the command
  1181.    getcommand setting                    -- Get current setting from cmdline
  1182.    setcommand oldcmd,oldcol,oldscroll    -- Restore old cmdline status
  1183.    parse value setting with . val        -- Get the stuff we want
  1184.    return val
  1185. compile endif
  1186.  
  1187. compile if 0    -- The following two routines are unused; why waste space??  LAM
  1188. ; PDISPLAY_MARGINS: put the margins mark on the current line
  1189.  
  1190. defproc pdisplay_margins()
  1191.    i=insert_state()
  1192.    if i then insert_toggle endif
  1193.    call psave_pos(save_pos)
  1194.    insert
  1195.    parse value pmargins() with lm rm pm .
  1196.    .col=lm;keyin'L';.col=pm;keyin'P';.col=rm;keyin'R'
  1197.    begin_line
  1198.    call prestore_pos(save_pos)
  1199.    if i then insert_toggle endif
  1200.    return 0
  1201.  
  1202.  
  1203. ; PDISPLAY_TABS: put the tab stops on the current line
  1204.  
  1205. defproc pdisplay_tabs()
  1206.    i=insert_state()
  1207.    if i then insert_toggle endif
  1208.    call psave_pos(save_pos)
  1209.    insert
  1210.    tabstops = ptabs()
  1211.    do forever
  1212.       parse value tabstops with tabx tabstops
  1213.       if tabx = '' then leave endif
  1214.       .col=tabx
  1215.       keyin'T'
  1216.    end
  1217.    begin_line
  1218.    call prestore_pos(save_pos)
  1219.    if i then insert_toggle endif
  1220.    return 0
  1221. compile endif
  1222.  
  1223. ; PEND_MARK: moves the cursor to the end of the marked area
  1224. defproc pend_mark
  1225.    call checkmark()
  1226.    getmark  firstline,lastline,firstcol,lastcol,fileid
  1227.    activatefile fileid
  1228. compile if EVERSION < 5
  1229.    cursor_data
  1230. compile endif
  1231.    if marktype()<>'LINE' then
  1232.       .col=lastcol
  1233.    endif
  1234.    lastline
  1235.  
  1236. ; PEND_WORD: moves the cursor to the end of the word if the cursor is on this
  1237. ; word.  If it's not on a word, it's moved to the end of the first word on the
  1238. ; right.  If there is no word on the right it's moved to the end of the word on
  1239. ; the left.  If the line is empty the cursor doesn't move.
  1240. defproc pend_word
  1241.    getline line,.line
  1242.    if  substr(line,.col,1)=' '  then
  1243.       if substr(line,.col)=' ' then
  1244.          if  line<> ' ' then
  1245.             for i=.col to 2 by -1
  1246.                if substr(line,i-1,1)<>' ' then leave endif
  1247.             endfor
  1248.            .col=i-1
  1249.          endif
  1250.       else
  1251.          p=verify(line,' ','',.col)
  1252.          p=verify(line' ',' ','M',p)
  1253.          .col=p-1
  1254.       endif
  1255.    else
  1256.       if .col<>MAXCOL then
  1257.          i=pos(' ',line,.col)
  1258.          if i then
  1259.             .col=i-1
  1260.          else
  1261.             .col=length(line)
  1262.          endif
  1263.       endif
  1264.    endif
  1265.  
  1266.  
  1267. defproc pfile_exists /* Check if file already exists in ring */
  1268.    if substr(arg(1),2,1)=':'  then
  1269.       /* parse off drive specifier and try again */
  1270.       getfileid zzfileid,substr(arg(1),3)
  1271.    else
  1272.       getfileid zzfileid,arg(1)
  1273.    endif
  1274.    return zzfileid<>''
  1275.  
  1276. defproc pfind_blank_line
  1277.    -- Find first blank line after the current one.  Make that the new current
  1278.    -- line.  If no such line is found before the end of file, don't change the
  1279.    -- current line.
  1280.    for i = .line+1 to .last
  1281.       getline line,i
  1282.       -- Ver 3.11:  Modified to respect GML tags:  stop at first blank line
  1283.       -- or first line with a period or a colon (".:") in column 1.
  1284.       if line='' or not verify(substr(line,1,1), ".:" ) then
  1285.          i
  1286.          leave
  1287.       endif
  1288.    endfor
  1289.  
  1290. defproc pfirst_nonblank
  1291.    /* different from PE */
  1292.    if not .line then .col=1
  1293.    else
  1294.       getline line
  1295.       .col=max(1,verify(line,' '))
  1296.    endif
  1297.  
  1298.  
  1299. ; PLOWERCASE: force to lowercase the marked area
  1300.  
  1301. defproc plowercase
  1302.    call checkmark()
  1303.    /* invoke pinit_extract, pextract_string, pput_string_back to do the job */
  1304.    call psave_pos(save_pos)
  1305.    call pinit_extract()
  1306.    do forever
  1307.       code = pextract_string(string)
  1308.       if code = 1 then leave; endif
  1309.       if code = 0 then
  1310.          string = lowcase(string)
  1311.          call pput_string_back(string)
  1312.       endif
  1313.    end
  1314.    call prestore_pos(save_pos)
  1315.  
  1316.  
  1317. ; PMARGINS: return the current margins setting. (Uses pcommon_tab_margin)
  1318.  
  1319. defproc pmargins
  1320. compile if EVERSION < 5
  1321.    return pcommon_tab_margin('ma')
  1322. compile else
  1323.    return .margins
  1324. compile endif
  1325.  
  1326.  
  1327. ; PMARK: mark at the cursor position (mark type received as argument).  Used by
  1328. ; pset_mark
  1329. defproc pmark(mt)
  1330.    if mt= 'LINE' then
  1331.       mark_line
  1332.    elseif mt = 'CHAR' then
  1333.       mark_char
  1334.    else
  1335.       mark_block
  1336.    endif
  1337.  
  1338.  
  1339. ; PMARK_WORD: mark the word pointed at by the cursor.  If the cursor is on a
  1340. ; space, the word at the right is marked.  If there is no word on the right, the
  1341. ; word on the left is marked.
  1342. defproc pmark_word
  1343.    if marktype()<>'' then
  1344.       sayerror -279  -- 'Text already marked'
  1345.       stop
  1346.    endif
  1347.    call pend_word()
  1348. compile if WANT_CHAR_OPS
  1349.    mark_char
  1350. compile else
  1351.    mark_block
  1352. compile endif
  1353.    call pbegin_word()
  1354. compile if WANT_CHAR_OPS
  1355.    mark_char
  1356. compile else
  1357.    mark_block
  1358. compile endif
  1359. compile if EVERSION > 5
  1360.   'Copy2SharBuff'       /* Copy mark to shared text buffer */
  1361. compile endif
  1362.  
  1363.  
  1364. ; PRESTORE_MARK: restore the current marks (cannot be used as a stack) See also
  1365. ; psave_mark
  1366. defproc prestore_mark(savemark)
  1367.    unmark
  1368.    parse value savemark with savefirstline savelastline savefirstcol savelastcol savemkfileid savemt
  1369.    if savemt<>'' then
  1370.       call pset_mark(savefirstline,savelastline,savefirstcol,savelastcol,savemt,savemkfileid)
  1371.    endif
  1372.  
  1373.  
  1374. ; PRESTORE_POS: restore the cursor position (cannot be used as a stack) See
  1375. ; also psave_pos()
  1376. defproc prestore_pos(save_pos)
  1377.    parse value save_pos with svline svcol svcx svcy
  1378.    .cursory = svcy                          -- set .cursory
  1379.    min(svline, .last)                       -- set .line
  1380.    .col = MAXCOL; .col = svcol - svcx + 1   -- set left edge of window
  1381.    .col = svcol                             -- set .col
  1382.  
  1383.  
  1384. ;  Printer_ready( printer_number ) tests whether printer is ready.
  1385. ;
  1386. ;  Enter with printer_number = 1 for the first printer (LPT1), 2 for LPT2.
  1387. ;  No argument at all defaults to LPT1.
  1388. ;
  1389. ;  Returns 1 (true)  for printer attached and ready.
  1390. ;  Returns 0 (false) for printer not attached or not ready.
  1391. ;
  1392. ;  Note:  Assumes the standard BIOS responses for an IBM PC.
  1393. ;  The BIOS responds with AH=90 hex for printer ready.
  1394. ;  Might not work on clones and other strange machines.
  1395. ;
  1396. ;  If we're on OS/2 we don't check because the spooler protects us from
  1397. ;  a hang if the printer's off-line.  We always return "ready" on OS/2.
  1398. ;
  1399. defproc printer_ready
  1400. compile if EVERSION >= 4
  1401.    return 1
  1402. compile else
  1403.    if arg(1)='' then
  1404.       printer_number=1
  1405.    elseif not isnum(arg(1)) then
  1406.       sayerror 'Printer_ready:  'INVALID_NUMBER__MSG
  1407.       return 0
  1408.    else
  1409.       printer_number = arg(1)
  1410.    endif
  1411.    /* Call BIOS interrupt 17 hex with AH=2, printer status query. */
  1412.    parse value int86x(23,512 0 0 printer_number-1,'') with printer_status .
  1413. ;    IBM PC family returns '90' for printer ready (not busy + selected).
  1414. ;    Some clones return 'D0' (not busy + acknowledge + selected).
  1415. ;    Here, we'll accept either value.
  1416. ;                    hex2dec('9000'):              hex2dec('D000'):
  1417.    return (printer_status == -28672) or (printer_status == -12288)
  1418. compile endif
  1419.  
  1420.  
  1421. ; PSAVE_MARK: save the current marks (cannot be used as a stack) See also
  1422. ; prestore_pos()
  1423. defproc psave_mark(var savemark)
  1424.    savemt=marktype()
  1425.    if savemt then
  1426.       getmark  savefirstline,savelastline,savefirstcol,savelastcol,savemkfileid
  1427.       unmark
  1428.       savemark=savefirstline savelastline savefirstcol savelastcol savemkfileid savemt
  1429.    else
  1430.       savemark=''
  1431.    endif
  1432.  
  1433.  
  1434. ; PSAVE_POS: save the cursor position (cannot be used as a stack) See also
  1435. ; prestore_pos()
  1436. defproc psave_pos(var save_pos)
  1437.    save_pos=.line .col .cursorx .cursory
  1438.  
  1439.  
  1440. defproc pset_mark(firstline,lastline,firstcol,lastcol,mt,fileid)
  1441. compile if EVERSION >= '5.50'
  1442.    setmark firstline,lastline,firstcol,lastcol,wordpos(mt,'LINE CHAR BLOCK CHARG BLOCKG')-1,fileid
  1443. compile else
  1444.    getfileid actfileid    /* preserve current active fileid */
  1445.    rc = 0
  1446.    activatefile fileid
  1447.  compile if not E3
  1448.    if rc=sayerror('Invalid fileid') then stop; endif
  1449.  compile endif
  1450.    call psave_pos(save_pos)
  1451.    unmark
  1452.    if lastcol then
  1453.       .col=lastcol; lastline
  1454.    else
  1455.       lastline-1; .col=MAXCOL
  1456.    endif
  1457.    call  pmark(mt)
  1458.    .col=firstcol; firstline
  1459.    call pmark(mt)
  1460.    call prestore_pos(save_pos)
  1461.    activatefile actfileid         /* restore the initial active file */
  1462. compile endif
  1463.  
  1464. ; PTABS: return the current tabs setting. (Uses pcommon_tab_margin)
  1465.  
  1466. defproc ptabs
  1467. compile if EVERSION < 5
  1468.    return pcommon_tab_margin('tabs')
  1469. compile else
  1470.    return .tabs
  1471. compile endif
  1472.  
  1473.  
  1474. ; PUPPERCASE: force to uppercase the marked area
  1475.  
  1476. defproc puppercase
  1477.    call checkmark()
  1478.    /* invoke pinit_extract, pextract_string, pput_string_back to do the job */
  1479.    call psave_pos(save_pos)
  1480.    call pinit_extract()
  1481.    do forever
  1482.       code = pextract_string(string)
  1483.       if code = 1 then leave endif
  1484.       if code = 0 then
  1485.          string = upcase(string)
  1486.          call pput_string_back(string)
  1487.       endif
  1488.    end
  1489.    call prestore_pos(save_pos)
  1490.  
  1491. ;defproc remove_trailing_spaces
  1492. ;   /* This is no longer used by any file in standard E.  Use strip()  */
  1493. ;   /* instead.  But left here for compatibility with older procs.     */
  1494. ;   return strip(arg(1),'T')
  1495.  
  1496. compile if EPM
  1497. ; In E3 and EOS2, we can use a_X to enter the value of any key.  In EPM,
  1498. ; we can't, so the following routine is used by KEY and LOOPKEY to convert
  1499. ; from an ASCII key name to the internal value.  It handles shift or alt +
  1500. ; any letter, or a function key (optionally, with any shift prefix).  LAM
  1501. defproc resolve_key(k)
  1502.    kl=lowcase(k)
  1503.    suffix=\2                           -- For unshifted function keys
  1504.    if length(k)>=3 & pos(substr(k,2,1),'_-+') then
  1505.       if length(k)>3 & substr(kl,3,1)='f' then     -- Shifted function key
  1506.          suffix=substr(\10\34\18,pos(leftstr(kl,1),'sac'),1)  -- Set suffix,
  1507.          kl=substr(kl,3)             -- strip shift prefix, and more later...
  1508.       else                        -- alt+letter or ctrl+letter
  1509.          k=substr(kl,3,1) || substr(' ',pos(leftstr(kl,1),'ac'),1)
  1510.       endif
  1511.    endif
  1512.    if leftstr(kl,1)='f' & isnum(substr(kl,2)) then
  1513.       k=chr(substr(kl,2)+31) || suffix
  1514.    endif
  1515.    return k
  1516. compile endif
  1517.  
  1518. compile if EVERSION < 5
  1519. defproc restore_command_state(cstate)
  1520.    if command_state()<>cstate then
  1521.       command_toggle
  1522.    endif
  1523.  
  1524. defproc save_command_state(var cstate)
  1525.    cstate=command_state()
  1526.    cursor_data
  1527.    refresh            /* Force E to update the cursor position */
  1528. compile endif
  1529.  
  1530.  
  1531. -- 4.10:  Saving with tab compression is built in now.  No need for
  1532. -- the make-do proc savefilewithtabs().  DOS version still needs it for
  1533. -- people editing MAKE files, but we make it optional via WANT_TABS.
  1534.  
  1535. compile if E3 & WANT_TABS
  1536. ; Note:  This does not tabify the entire file; it just replaces 8 blanks
  1537. ; in the first column with a tab character.
  1538. defproc savefilewithtabs(filename)
  1539.    options=arg(2)
  1540.    call psave_pos(save_pos)
  1541.    getfileid fileid
  1542.    unmark;bottom;markline;top;markline
  1543.    call prestore_pos(save_pos)
  1544.    'xcom e 'argsep'n .';deleteline
  1545.    if rc and rc<>-282 then  -- sayerror("new file")
  1546.       return rc
  1547.    endif
  1548.    rc=0
  1549.    copymark
  1550.    if rc then return rc endif
  1551.    unmark
  1552.    top;.col=1;markblock;bottom;.col=8;markblock
  1553.    .col=1;top
  1554.    'c/        /'\t'/m*'     /* replace first column 8 spaces with tab */
  1555.    sayerror 1  /* Turn off pending messages */
  1556.    unmark
  1557.    savestatus=savefile(filename,options)
  1558.    .modify=0
  1559.    'xcom q'
  1560.    if savestatus then return savestatus endif
  1561.    activatefile fileid
  1562.    if filename=.filename then
  1563.       .modify=0
  1564.    endif
  1565.    return 0
  1566. compile endif
  1567.  
  1568. define
  1569. compile if EVERSION < '5.21'
  1570.    MSGC = '.messagecolor'
  1571. compile elseif EVERSION < '5.50'
  1572.    MSGC = 'vMESSAGECOLOR'
  1573. compile else            -- GPI version
  1574.    MSGC = 'color'
  1575. compile endif
  1576.  
  1577. ; Paste up a message in a box, using SAYAT's.  Useful for "Processing..." msgs.
  1578. defproc sayatbox
  1579. compile if EVERSION >= '5.21'
  1580.    universal vMESSAGECOLOR
  1581. compile endif
  1582. compile if WANT_DBCS_SUPPORT
  1583.    universal ondbcs
  1584. compile endif
  1585.  
  1586. compile if EVERSION >= '5.50'  -- GPI version; doesn't use background color in SAYATs.
  1587.    color = sayat_color()
  1588. compile endif
  1589. compile if WANT_DBCS_SUPPORT
  1590.    if ondbcs then
  1591.       middle = substr('',1,length(arg(1)),\x06)
  1592.       sayat '  '\x01\x06||middle||\x06\x02'  ',1,2, $MSGC
  1593.       sayat '  '\x05' 'arg(1)' '\x05'  ',2,2, $MSGC
  1594.       sayat '  '\x03\x06||middle\x06\x04'  ',3,2, $MSGC
  1595.    else
  1596. compile endif
  1597.       middle = substr('',1,length(arg(1)),'═')
  1598.       sayat '  ╔═'middle'═╗  ',1,2, $MSGC
  1599.       sayat '  ║ 'arg(1)' ║  ',2,2, $MSGC
  1600.       sayat '  ╚═'middle'═╝  ',3,2, $MSGC
  1601. compile if WANT_DBCS_SUPPORT
  1602.    endif
  1603. compile endif
  1604.  
  1605. compile if EVERSION >= '5.50'
  1606. defproc sayat_color =          -- Pick a color for SAYAT that doesn't conflict w/ foreground or background color.
  1607.    universal vMESSAGECOLOR
  1608.    if vMESSAGECOLOR // 16 <> .textcolor // 16 & vMESSAGECOLOR // 16 <> .textcolor % 16 then
  1609.       return vMESSAGECOLOR       -- Preference is the message color.
  1610.    endif
  1611.    if vMESSAGECOLOR // 16 <> LIGHT_RED then
  1612.       return LIGHT_RED           -- Second choice is light red.
  1613.    endif
  1614.    if .textcolor // 16 <> LIGHT_BLUE & .textcolor % 16 <> LIGHT_BLUE then
  1615.       return LIGHT_BLUE          -- If that's used, then how about light blue
  1616.    endif
  1617.    return GREEN                  -- Final fallback is green.
  1618. compile endif
  1619.  
  1620. defproc splitlines()
  1621.    if .line then
  1622.       split
  1623.       oldcol=.col
  1624.       call pfirst_nonblank()
  1625. compile if EPM           -- Can't use REPLACELINE because it wipes out attributes.
  1626.       col1 = .col
  1627.       down
  1628.       if textline(.line)<>'' then
  1629.          call pfirst_nonblank()
  1630.          col2 = .col
  1631.          getsearch savesearch
  1632.          .col = 1
  1633.          if col1 < col2 then       -- Shift new line left
  1634.             'xcom c/'copies(' ',col2-col1)'//'  -- Change first n blanks to null
  1635.          elseif col1 > col2 then   -- Shift new line right
  1636. ;;            c = substr(textline(.line),1,1)  -- LAM: simpler to use GREP
  1637. ;;            if c='/' then d='?'; else d='/'; endif  -- Choose delimiter
  1638. ;;            'xcom c 'd||c||d||substr('',1,col1-col2)||c||d  -- Add blanks before 1st char.
  1639.             'xcom c /^/'copies(' ',col1-col2)'/g'  -- Add blanks before 1st char.
  1640.          endif
  1641.          setsearch savesearch
  1642.       endif
  1643.       up
  1644. compile else           -- E3 and EOS2 can still use the old, simple way.
  1645.       getline line,.line+1
  1646.       replaceline substr('',1,.col-1) ||    -- indent like previous line
  1647.          strip(line,'L'),                   -- (remove leading spaces)
  1648.          .line+1
  1649. compile endif
  1650.       .col=oldcol
  1651.    endif
  1652.  
  1653.  
  1654. ; Note on a speed trick:  subdir_present is initialized to null at start-up.
  1655. ; This causes defproc subdir(), the first time it's called, to execute a
  1656. ; FINDFILE (by way of find_routine) to search the path for the subdir program.
  1657. ; (See DEFC HELP for another example of findfile.)
  1658. ; After that first search the exact path location of subdir is known; it's
  1659. ; remembered in the universal variable subdir_present.  All future calls supply
  1660. ; the exact location (as in "C:\UTIL\SUBDIR.COM") to avoid the path search.
  1661.  
  1662. definit  /* Keep this definit close to the proc it serves. */
  1663.    universal subdir_present
  1664.    subdir_present=''
  1665.  
  1666. defproc subdir
  1667.    universal subdir_present
  1668.    if subdir_present='' then  -- First time; look for the program
  1669.  compile if E3
  1670.       subdir_present=find_routine('SUBDIR /Q')
  1671.       if subdir_present == -1 then      -- Not found
  1672.          if Dos_Version() >= 500 then   -- If DOS version is 5, can use DIR
  1673.             subdir_present='dir /b /s'  -- (SUBDIR preferable for leading wildcards)
  1674.          endif
  1675.       endif
  1676.  compile else
  1677.       if Dos_Version() >= 2000 then   -- If OS/2 2.0 or above, use DIR
  1678.          subdir_present='dir /b /s'   -- (OS/2 DIR supports leading wildcards)
  1679.       else
  1680.          subdir_present=find_routine('FILEFIND')
  1681.       endif
  1682.  compile endif
  1683.       if subdir_present == -1 then     -- Not found, try ATTRIB
  1684.          subdir_present=find_routine('ATTRIB /S')
  1685.       endif
  1686.    endif
  1687.    if subdir_present == -1 then
  1688.       sayerror CANT_FIND_PROG__MSG 'ATTRIB'
  1689.       stop
  1690.    endif
  1691.    quietshell subdir_present arg(1)
  1692.  
  1693. compile if EVERSION >= 4
  1694. defproc swapwords(num)
  1695.    return substr(num,3,2) || substr(num,1,2)
  1696. compile endif
  1697.  
  1698.  
  1699. compile if E3 or (EPM & not (EVERSION >= '5.17'))
  1700. ;  EOS2 & EPM have a TEXTLINE() function built in.  This is added here so that
  1701. ;  E3 macro programmers can use TEXTLINE also, if they like.
  1702. defproc textline(linenum)
  1703.    getline line,linenum; return line
  1704. compile endif
  1705.  
  1706. -- Standard text reflow, moved from Alt+P definition in STDKEYS.E.
  1707. -- Only called from Alt+P if no mark exists; users wishing to call
  1708. -- this from their own code must save & restore the mark themselves
  1709. -- if that's desired.
  1710. defproc text_reflow
  1711.    if .line then
  1712.       getline line
  1713.       if line<>'' then  -- If currently on a blank line, don't reflow.
  1714.          oldcursory=.cursory;oldcursorx=.cursorx; oldline=.line;oldcol=.col;
  1715.          unmark;mark_line
  1716.          call pfind_blank_line()
  1717.          -- Ver 3.11:  slightly revised test works better with GML sensitivity.
  1718.          if .line<>oldline then
  1719.             up
  1720.          else
  1721.             bottom
  1722.          endif
  1723.          mark_line
  1724.          reflow
  1725.  
  1726. compile if REFLOW_LIKE_PE   /* position on next paragraph (like PE) */
  1727.          down                       /* Thanks to Doug Short. */
  1728.          for i=.line+1 to .last
  1729.             getline line,i
  1730.             if line<>'' then i; leave; endif
  1731.          endfor
  1732. compile else
  1733.          /* or like old E */
  1734.          getmark firstline,lastline
  1735.          firstline
  1736.          .cursory=oldcursory;.cursorx=oldcursorx; oldline;.col=oldcol
  1737. compile endif
  1738.          unmark
  1739.       endif
  1740.    endif
  1741.  
  1742. ;  A truncate function to maintain compatibility of macros between this
  1743. ;  version and the OS/2 version which will have floating point.  Two
  1744. ;  functions in DOSUTIL.E need this.
  1745. ;
  1746. ;  If we're passed a floating point number with a decimal point in it,
  1747. ;  like "4.0", drop the decimal part.
  1748. ;  If we're passed an exponential-format number like "6E3", fatal error.
  1749. defproc trunc(num)
  1750.    if not verify('E',upcase(num)) then
  1751.       sayerror NO_FLOAT__MSG num
  1752.       stop
  1753.    endif
  1754.    parse value num with whole'.'.
  1755.    return whole
  1756.  
  1757. compile if WANT_LAN_SUPPORT
  1758. defproc unlock(fileid)
  1759.    if fileid.lockhandle = 0 then
  1760.       sayerror fileid.filename NOT_LOCKED__MSG
  1761.       return 1
  1762.    endif
  1763.  compile if EPM32
  1764.    result = dynalink32('DOSCALLS',    -- Free the original handle
  1765.                        '#257',                    -- dos32close
  1766.                        atol(fileid.lockhandle), 2)
  1767.  compile else
  1768.    result = dynalink('DOSCALLS',
  1769.                      '#59',                    /* dosclose */
  1770.                      atoi(fileid.lockhandle))
  1771.  compile endif
  1772.    if result then
  1773.       sayerror 'DOSCLOSE' ERROR_NUMBER__MSG result
  1774.    else
  1775.       fileid.lockhandle = 0
  1776.    endif
  1777.    return result
  1778. compile endif
  1779.  
  1780.