home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w055 / 4.ddi / SOURCES.LIF / BUFFERS.PEL < prev    next >
Encoding:
Text File  |  1990-09-27  |  19.9 KB  |  794 lines

  1. # $Header:   P:/source/ppee/macros/buffers.pev   1.123   21 Aug 1990 14:51:50   ericj  $
  2.  
  3. ##############################################################################
  4. #
  5. #           Sage Software - POLYTRON Division
  6. #             1700 NW 167th Place
  7. #               Beaverton, OR 97006
  8. #
  9. #   Copyright 1990, Sage Software, Inc.
  10. #
  11. #   Permission is hereby granted for licensed users of Sage Professional
  12. #   Editor and PolyAwk to copy and modify this source code for their own
  13. #   personal use.  These derivative works may be distributed only to other
  14. #   licensed Sage Professional Editor and PolyAwk users.  All other usage
  15. #   is prohibited without express written permission from Sage Software.
  16. #
  17. ##############################################################################
  18.  
  19. #### $Workfile:   buffers.pel  $: Support for Buffers
  20.  
  21.  
  22. #
  23. # buffer flags:
  24. #
  25. global    BUFFER_SYSTEM            = 0x0001
  26. global    BUFFER_IN_VIRTUAL_SPACE        = 0x0002
  27. global    BUFFER_POSITION_IS_VIRTUAL    = 0x0002 # This is the documented one
  28. global    BUFFER_CONTROL_Z_IS_EOF        = 0x0004
  29. #reserved                = 0x0008
  30. global    BUFFER_READ_ONLY        = 0x0010
  31. global    BUFFER_AUTOSAVE_MODIFIED    = 0x0020
  32. global    BUFFER_MODIFIED            = 0x0040
  33. global    BUFFER_OVERTYPE_MODE        = 0x0080
  34. global    BUFFER_EXPAND_TABS        = 0x0100
  35. global    BUFFER_WP_ENABLED        = 0x0200
  36. global    BUFFER_REAL_SPACE_ONLY        = 0x0400
  37. global    BUFFER_SNAP_TO_EOL        = 0x0800
  38. global    BUFFER_NO_UNDO            = 0x1000
  39. global    BUFFER_TABS_TO_SPACES        = 0x2000
  40. global    BUFFER_WHOLE_LINES        = 0x4000
  41.  
  42. #user defined buffer flags
  43. global    DOS_BUFFER_FLAG =         0x00020000;
  44.  
  45. global print_device = "prn"
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53. ##
  54. ## functions to interrogate/set bits in the buffer_flags word
  55. ##
  56.  
  57. global function buffer_is_modified(){
  58.     return ( and(buffer_flags, BUFFER_MODIFIED) != 0 )
  59. }
  60.  
  61. global function set_buffer_flag( mask, value ) {
  62.     if ( value )
  63.         buffer_flags = or( buffer_flags, mask )
  64.     else
  65.         buffer_flags = and( buffer_flags, not(mask) )
  66.  
  67.     return value
  68. }
  69.  
  70. global function set_default_buffer_flag( mask, value ) {
  71.     if ( value )
  72.         default_buffer_flags = or( default_buffer_flags, mask )
  73.     else
  74.         default_buffer_flags = and( default_buffer_flags, not(mask) )
  75.  
  76.     return value
  77. }
  78.  
  79.  
  80. ##
  81. ## buffer_list() - pop up a menu with a list of active buffers
  82. ##
  83.  
  84. global function buffer_list( systemFlag )
  85. {
  86.     local    bufferListArray        # array containing the buffer list
  87.     local    sequenceArray
  88.     local    bl_buffer
  89.  
  90.     local    nBuffers
  91.     local    thisBuffer
  92.     local    headBuffer
  93.     local    priorWindow = current_window
  94.     local    fn
  95.     local    entry
  96.     local    scanCode, asciiCode
  97.     local    fmode, bmode, newMode, sameMode
  98.     local    resp
  99.     local    key
  100.     local    i
  101.  
  102.     thisBuffer = headBuffer = current_buffer
  103.  
  104.      # ensure that headBuffer is not a system buffer
  105.      if ( and( buffer_flags, BUFFER_SYSTEM ) && !systemFlag ) {
  106.          headBuffer = next_buffer()
  107.      }
  108.  
  109.     # build the buffer list
  110.  
  111.     nBuffers = 0
  112.     do {
  113.         # start with the full file name
  114.         fn = buffer_filename
  115.         if ( fn == "" )
  116.             fn = "[" buffer_name "]"
  117.  
  118.         # append selected attribute flags
  119.         if ( and( buffer_flags, BUFFER_MODIFIED ))
  120.             fn = fn "*"
  121.  
  122.         if ( and( buffer_flags, BUFFER_READ_ONLY ))
  123.             fn = fn " (RO)"
  124.  
  125.         if ( and( buffer_flags, BUFFER_SYSTEM ))
  126.             fn = buffer_name " (System Buffer)"
  127.  
  128.         # update the buffer list arrays
  129.         sequenceArray[ nBuffers++ ] = fn
  130.         bufferListArray[ fn ] = current_buffer
  131.  
  132.         # advance to next buffer in ring
  133.         next_buffer( "", systemFlag )
  134.  
  135.     } while ( current_buffer != headBuffer )
  136.  
  137.     # create a system buffer for the buffer list
  138.  
  139.     current_window = create_factory_window( 20, 2, 55, 20,    \
  140.             WINDOW_MENU + WINDOW_SB_RIGHT )
  141.     current_buffer = bl_buffer = create_buffer(        \
  142.             "Buffer List",                \
  143.             "",                    \
  144.             BUFFER_SYSTEM + BUFFER_NO_UNDO )
  145.     attach_window_buffer( current_window, current_buffer )
  146.     window_name = "Buffer List"
  147.  
  148.     for ( i=0; i<nBuffers; i++ ) {
  149.         insert_string( sequenceArray[i] )
  150.         insert_newline()
  151.     }
  152.     backspace()
  153.     delete sequenceArray
  154.     goto_buffer_top()
  155.  
  156.     # put up an instructions
  157.     message( " or  : <Enter> to select" \
  158.             ", D(elete), W(rite), R(ead-only), <Esc> to exit" )
  159.  
  160.     # buffer list command loop
  161.     do {
  162.         # find the current buffer id
  163.         fn = read_buffer()
  164.         if ( fn in bufferListArray ) {
  165.             entry = bufferListArray[ fn ]
  166.         } else {
  167.             warning( "Internal error in buffer_list" \
  168.                     " - cannot continue" )
  169.             break
  170.         }
  171.  
  172.         # get the buffer list command
  173.         drop_anchor( LINE_SELECTION )
  174.         display_update()
  175.         key = getkey()
  176.         flush_keyboard()
  177.  
  178.         scanCode    = asciiCode = key
  179.         scanCode    = shiftr( scanCode, 8 )
  180.         asciiCode    = toupper( chr( and( asciiCode, 0xff )))
  181.         raise_anchor()
  182.  
  183.         if ( asciiCode == "\r" ) {    # Enter key
  184.             # make selected buffer current
  185.             thisBuffer = entry
  186.             break
  187.  
  188.         } else if ( asciiCode == "D" ) {
  189.             # delete the buffer and the entry
  190.             if ( delete_buffer_key( entry ) ) {
  191.                 delete_line()
  192.                 if (current_line_length == 0 ) {
  193.                     backspace()
  194.                     current_column = 0
  195.                 }
  196.             }
  197.  
  198.         } else if ( asciiCode == "W" ) {
  199.             # write the buffer
  200.             current_buffer = entry
  201.             write_buffer()
  202.             current_buffer = bl_buffer
  203.  
  204.             # remove the '*' from the entry in the buffer list
  205.             if ( (match( fn, /\*/ )) ) {
  206.                 current_column = RSTART
  207.                 delete_chars(1)
  208.                 goto_bol()
  209.                 bufferListArray[ read_buffer() ] = entry
  210.             }
  211.  
  212.         } else if ( asciiCode == "R" ) {
  213.             # toggle the read-only bit
  214.             current_buffer = entry
  215.             buffer_flags = xor( buffer_flags, BUFFER_READ_ONLY )
  216.             fn = buffer_filename
  217.             fmode = filemode( fn )
  218.             bmode = (and( buffer_flags, BUFFER_READ_ONLY ) != 0)
  219.             current_buffer = bl_buffer
  220.  
  221.             # update the "(RO)" tag in the buffer list
  222.             if ( (match( read_buffer(), / \(RO\)/ )) ) {
  223.                 current_column = RSTART
  224.                 delete_chars(RLENGTH)
  225.             } else {
  226.                 current_column = current_line_length + 1
  227.                 insert_string( " (RO)" )
  228.             }
  229.             goto_bol()
  230.             bufferListArray[ read_buffer() ] = entry
  231.  
  232.             # ask if we should change the disk file's
  233.             # read-only attribute bit
  234.  
  235.             if ( fmode >= 0 ) {
  236.  
  237.                 # get the new file attributes
  238.                 fmode = xor( fmode, _READ_ONLY )
  239.                 newMode = bmode ? "read-only" : "writable"
  240.  
  241.                 # does the disk read-only mode match the buffer's?
  242.                 sameMode = ( (and( fmode, _READ_ONLY ) != 0) \
  243.                         == bmode)
  244.  
  245.                 # make the change after getting confirmation
  246.                 if ( sameMode ) {
  247.                     resp = toupper( confirm( \
  248.                             "make file " fn " " newMode    \
  249.                             " also? [yn]", "yYnN" ))
  250.                     if ( resp == "Y" ) {
  251.                         filemode( fn, fmode )
  252.                     } else if ( resp == "" ) {
  253.                         # replace misleading "canceled" message
  254.                         message( "" )
  255.                     }
  256.                 }
  257.             }
  258.  
  259.         } else if ( scanCode == SCANCODE_HOME ) {
  260.             current_line = 1
  261.         } else if ( scanCode == SCANCODE_END ) {
  262.             current_line = buffer_last_line
  263.         } else if ( scanCode == SCANCODE_UP ) {
  264.             # preceeding entry, wrap at top
  265.             if (current_line == 1 ) {
  266.                 current_line = buffer_last_line
  267.             } else {
  268.                 current_line--
  269.             }
  270.         } else if ( scanCode == SCANCODE_DOWN ) {
  271.             # succeeding entry, wrap at bottom
  272.             if (current_line == buffer_last_line ) {
  273.                 current_line = 1
  274.             } else {
  275.                 current_line++
  276.             }
  277.         } else if ( scanCode == SCANCODE_LEFT_PRESS ||
  278.                 scanCode == SCANCODE_LEFT_CLICK ) {
  279.             menu_mouse_key()
  280.         }
  281.  
  282.     } while ( scanCode != SCANCODE_ESC )    # Escape key
  283.  
  284.     # remove the buffer and window
  285.     delete_buffer( bl_buffer )
  286.     delete_window()
  287.     if ( priorWindow ) {
  288.         current_window = priorWindow
  289.     }
  290.     bl_buffer = 0
  291.  
  292.     # remove the buffer list array
  293.     delete bufferListArray
  294.  
  295.     # select the new current buffer
  296.     if ( thisBuffer ) {
  297.         current_buffer = thisBuffer
  298.         display_filename()
  299.     } else {
  300.         message( "" )
  301.     }
  302. }
  303.  
  304.  
  305.  
  306. global function delete_buffer_without_asking( bufferToDelete )
  307. {
  308.     local    priorBuffer = current_buffer
  309.  
  310.     current_buffer = bufferToDelete
  311.     if ( current_buffer == bufferToDelete ) {
  312.         #
  313.         # if the buffer exists, clear the buffer modified bit first
  314.         # in order to avoid the "buffer had been modified" prompt
  315.         #
  316.         buffer_flags = and( buffer_flags, not( BUFFER_MODIFIED ) )
  317.         delete_buffer()
  318.         current_buffer = priorBuffer
  319.     }
  320. }
  321.  
  322. global function display_filename( useNotify )
  323. {
  324.     local    fn = buffer_filename
  325.  
  326.     # get the status of the modified bit in the current buffer
  327.     if ( and( buffer_flags, BUFFER_MODIFIED )) {
  328.         fn = fn "*"
  329.     }
  330.  
  331.     if ( useNotify )
  332.         notify( "File: " fn )
  333.     else
  334.         message( "File: " fn )
  335. }
  336.  
  337. global function change_output_name()
  338. {
  339.     local    newOutputName
  340.  
  341.     newOutputName = prompt("Enter new output file name: ", "")
  342.     if (newOutputName) {
  343.         buffer_filename = newOutputName
  344.         buffer_name = path_fname(buffer_filename) \
  345.             path_ext(buffer_filename)
  346.         buffer_flags = or( buffer_flags, BUFFER_MODIFIED );
  347.     }
  348.  
  349.     display_update()
  350. }
  351.  
  352.  
  353. #
  354. # paste()
  355. #
  356. # a synonym for insert_scrap()
  357. #
  358. global function paste()                        #PUBLIC #INT
  359. {
  360.     return insert_scrap()
  361. }
  362.  
  363. # cut()
  364. #
  365. # a synonym for delete_to_scrap()
  366. #
  367. global function cut(){                        #PUBLIC #INT
  368.     return delete_to_scrap()
  369. }
  370.  
  371.  
  372. global function print_buffer()                    #PUBLIC    #VOID
  373. {
  374.     local expand_tabs = and( buffer_flags, BUFFER_EXPAND_TABS );
  375.  
  376.     message( "Printing..." );
  377.  
  378.     buffer_flags = or( buffer_flags, BUFFER_EXPAND_TABS );
  379.  
  380.      if (region_type() != 0)
  381.         write_marked_block( print_device )
  382.     else
  383.         write_buffer( print_device )
  384.  
  385.  
  386.  
  387.     if (!expand_tabs)
  388.         buffer_flags = and( buffer_flags, not(BUFFER_EXPAND_TABS) );
  389.  
  390.     message( "Printing complete." )
  391. }
  392.  
  393.  
  394.  
  395.  
  396. #
  397. #  Backups will be made in the appropriate directory according to the 
  398. #  following rules:
  399. #
  400. #
  401. #
  402. #    Using c:\foo\test.c  as the same test file
  403. #
  404. #
  405. #                       \    backup_file_ext ==
  406. #                        \
  407. #                         \                          │
  408. #                          \         ".bak"          │     "" | "*"
  409. #  backup_directory      == ┌────────────────────────┼─────────────────────┐
  410. #                           │                        │                     │
  411. #                        "" │ \spe\backup\test.bak   │ \spe\backup\test.c  │
  412. #                           │                        │                     │
  413. #                        ───┼────────────────────────┼─────────────────────┤
  414. #                           │                        │                     │
  415. #                       "*" │ c:\foo\test.bak        │ c:\foo\test.bak     │
  416. #                           │                        │                     │
  417. #                        ───┼────────────────────────┼─────────────────────┤
  418. #                           │                        │                     │
  419. #         (any dir)  "~~~\" │ ~~~\test.bak           │ ~~~\test.c          │
  420. #                           │                        │                     │
  421. #                           └────────────────────────┴─────────────────────┘
  422. #
  423. #    Values for backup_directory:
  424. #      "*"      - means the directory where the file was originally loaded from
  425. #      "~~~\"   - any valid drive and path name.
  426. #      ""       - use the directory \spe\backup on the current drive
  427. #
  428. #    Values for backup_file_ext:
  429. #      ".bak"   - and valid extension to be used as the new backup file extension
  430. #                 ( if !("*" or "") always uses ".bak" for now
  431. #      ""       - use the current file's extension as the backup file extension
  432. #      "*"      - use the current file's extension as the backup file extension
  433. #
  434.  
  435. global backup_directory
  436. global backup_file_ext
  437.  
  438.  
  439. global function backup_file( fname )
  440. {
  441.     local   pos, bakFilename
  442.     local    pname
  443.     local   new_ext  = ".bak";
  444.     local   new_path;
  445.     local   dest_drive;
  446.     local   fmode;
  447.  
  448.     fname = buildpath( fname );
  449.     
  450.     if (!backup_files_enabled || (filemode( fname ) == -1))
  451.         return TRUE;
  452.     else{
  453.  
  454.         if (backup_file_ext == "*" || !backup_file_ext)
  455.             new_ext = path_ext( fname );
  456.         else 
  457.             new_ext = backup_file_ext;
  458.  
  459.  
  460.         if (substr( new_ext, 1, 1) != ".")
  461.             new_ext = "." new_ext;
  462.  
  463.         new_ext = substr( new_ext, 1, 4);
  464.  
  465.         if (backup_directory && (backup_directory != "*")) {
  466.             backup_directory = buildpath( backup_directory );
  467.             new_path = trim( backup_directory, "\\" );
  468.             if (filemode( new_path ) != _SUBDIR ) {
  469.                 warning( "Invalid backup directory path: " backup_directory "." );
  470.                 backup_directory = "";
  471.             }
  472.  
  473.         }
  474.  
  475.         if (!backup_directory) {
  476.             new_path = buildpath( "\\spe\\backup" );
  477.  
  478.             if (filemode("\\spe" ) != _SUBDIR){
  479.                 if (!mkdir( "\\spe" )) {
  480.                     warning( "Cannot create backup directory `\\spe'." );
  481.                     backup_directory = "*";
  482.                 }
  483.             }
  484.             if (filemode("\\spe\\backup" ) != _SUBDIR)
  485.                 if (!mkdir( "\\spe\\backup" )) {
  486.                     warning( "Cannot create backup directory `\\spe\\backup'." );
  487.                     backup_directory = "*";
  488.                 }
  489.         }
  490.  
  491.         if (backup_directory == "*") {
  492.             new_path = path_path( fname )
  493.         }
  494.  
  495.         pname = "\\" path_fname( fname );
  496.         new_path = trim( new_path, "\\" );
  497.  
  498.         bakFilename =  new_path pname new_ext;
  499.         if (bakFilename == fname )
  500.             bakFilename = new_path pname ".bak"
  501.  
  502.         message( "Writing backup file '" bakFilename "'." );
  503.  
  504.         dest_drive = substr( bakFilename, 1, 1 );
  505.         if (bakFilename != fname ){
  506.             fmode = filemode( bakFilename );
  507.             if ( (fmode != -1) && and( fmode, _READ_ONLY )){
  508.                 if (tolower(confirm( "`" bakFilename "' is read-only, overwrite?", "yYnN")) != "y")
  509.                     return FALSE;
  510.                 filemode( bakFilename, _NORMAL );
  511.             }
  512.  
  513.             if ( dest_drive == substr( fname, 1, 1 ) ){
  514.                 # backing up on same disk, just rename it.
  515.                 #
  516.                 if (buffer_size * 2 >= disk_free( dest_drive )) {
  517.                     warning( "Not enough disk space on drive " dest_drive ": no backup created!");
  518.                     return FALSE;
  519.                 }
  520.  
  521.                 unlink( bakFilename );
  522.                 return rename( fname, bakFilename )
  523.             }
  524.             else
  525.                 return filecopy( fname, bakFilename )
  526.         }
  527.     }
  528.     return FALSE
  529. }
  530.  
  531.  
  532. ## write_all_buffers()
  533. #
  534. # write all of the modified buffers to their output file but first
  535. # check the read/write permission of the output file.  Two passes are
  536. # made at writing the files: first, save all of the r/w files, second,
  537. # try to save the read-only files which will generate an error.
  538. #
  539. global function write_all_buffers()                #PUBLIC #INT
  540. {
  541.     local    priorWindow = current_window
  542.     local    old_curnt_buffer = current_buffer
  543.     local    fmask = BUFFER_MODIFIED + BUFFER_READ_ONLY
  544.     local    buf = current_buffer;
  545.     local   exitBuffers = 0;
  546.  
  547.     #
  548.     # create a temporary window so that the original window does
  549.     # not change when messages are written
  550.     current_window = create_window( 1,1,1,1, WINDOW_SYSTEM )
  551.     hide_window()
  552.  
  553.     if  ( and(buffer_flags,BUFFER_SYSTEM) )
  554.         old_curnt_buffer = next_buffer();
  555.  
  556.     #
  557.     # loop through the list of buffers and write all of the
  558.     # read/write files first
  559.     #
  560.     do {
  561.         #
  562.         # see if the buffer has changed
  563.         #
  564.         if ( and( buffer_flags, fmask ) == BUFFER_MODIFIED) {
  565.             #
  566.             # don't save read-only files this pass
  567.             #
  568.             message( buffer_filename )
  569.             if (!backup_file( buffer_filename )){
  570.                 notify( "Unable to create backup file for `" buffer_filename "'" );
  571.                 exitBuffers = 1;
  572.                 break;
  573.             }
  574.             if (write_buffer() < 0 ){
  575.                 exitBuffers = 1;
  576.                 break;
  577.             }
  578.         }
  579.         next_buffer()
  580.     } while (old_curnt_buffer != current_buffer)
  581.  
  582.  
  583.     #
  584.     # now loop through again and try to write the read-only files
  585.     # which will generate an error, but at least the r/w files
  586.     # have been saved.
  587.     #
  588.     if (!exitBuffers){
  589.         do {
  590.             #
  591.             # see if the buffer has changed
  592.             #
  593.             if ( and( buffer_flags, fmask ) == fmask ) {
  594.                 #
  595.                 # save the read-only files this pass
  596.                 #
  597.                 message( buffer_filename )
  598.                 if (!backup_file( buffer_filename )){
  599.                     notify( "Unable to create backup file for `" buffer_filename "'" );
  600.                     exitBuffers = 1;
  601.                     break;
  602.                 }
  603.                 if (write_buffer() < 0 )
  604.                     exitBuffers = 1;
  605.                     break;
  606.             }
  607.             next_buffer()
  608.         } while (old_curnt_buffer != current_buffer)
  609.     }
  610.  
  611.     current_buffer = buf;
  612.  
  613.     # restore the original window
  614.     delete_window()
  615.     if ( window_valid( priorWindow ))
  616.         current_window = priorWindow
  617.  
  618.     message( "" )
  619.     return !exitBuffers;
  620. }
  621.  
  622.  
  623.  
  624.  
  625. ## alter current_buffer's tab settings
  626. #
  627. global function tabs( stops1, stops2 ){            #PUBLIC #VOID
  628.     if( !stops1 )
  629.         stops1 = prompt( "Enter tab stop settings: ", buffer_tabs )
  630.     else if (argcount() > 1)
  631.         stops1 = stops1 " " stops2;
  632.  
  633.     if( stops1 ){
  634.         buffer_tabs = stops1
  635.         message( "" )
  636.     }
  637. }
  638.  
  639.  
  640. ## delete_buffer_key()
  641. #
  642. # A replacement for the delete_buffer() function to be bound to keys.
  643. # It protects the user from accidently having a system buffer (such as the
  644. # DOS buffer or help buffer) become current.
  645. #
  646. # The bufid argument is an optional buffer id of the buffer to delete.
  647. # If not specified, the current buffer will be deleted.
  648. #
  649. # The nextFlag argument is a flag which should be set to 1 (TRUE) to have the
  650. # deleted buffer be replaced with next_buffer() rather than prev_buffer().
  651. # The default is prev_buffer().
  652. #
  653. # The return value is FALSE if the specified buffer is the only buffer or if
  654. # they answer no to the "really delete?" prompt.
  655. #
  656. global function delete_buffer_key( bufid, nextFlag ) {
  657.  
  658.     local    priorWindow = current_window
  659.     local    priorBuffer = current_buffer
  660.     local    replacementBuffer
  661.     local    sentinel
  662.     local    resp
  663.     local    eid
  664.  
  665.     # make the specified buffer current
  666.     if ( bufid ) {
  667.         current_buffer = bufid
  668.     } else {
  669.         bufid = current_buffer
  670.     }
  671.  
  672.     # find the buffer to use to replace the deleted buffer.  Stop
  673.     # now if the buffer to delete is the last regular buffer.
  674.  
  675.     if ( nextFlag ) {
  676.         next_buffer()
  677.     } else {
  678.         prev_buffer()
  679.     }
  680.     if ( current_buffer == bufid ) {
  681.         current_buffer = priorBuffer
  682.         warning( "Cannot delete last buffer" )
  683.         return FALSE
  684.     } else {
  685.         replacementBuffer = current_buffer
  686.         current_buffer = bufid
  687.     }
  688.  
  689.     # ask for confirmation if the buffer has been modified
  690.     if ( and( buffer_flags, BUFFER_MODIFIED )) {
  691.         current_buffer = priorBuffer
  692.         resp = toupper( confirm(
  693.                 "Buffer has been modified. Delete [ynw]? ",
  694.                 "YyNnWw" ))
  695.         if ( resp == "Y" ) {
  696.             # yes, turn off the modified bit and proceed
  697.             current_buffer = bufid
  698.             buffer_flags = xor( buffer_flags, BUFFER_MODIFIED )
  699.         } else if ( resp == "W" ) {
  700.             # write first, clearing the modified bit as we do
  701.             current_buffer = bufid
  702.             write_buffer()
  703.         } else {
  704.             return FALSE
  705.         }
  706.     }
  707.  
  708.     # fix all non_system windows attached to this buffer
  709.  
  710.     if ( and( window_flags, WINDOW_SYSTEM ) ) {
  711.         sentinel = next_window()
  712.     } else {
  713.         sentinel = current_window
  714.     }
  715.  
  716.     do {
  717.         if ( bufid == current_buffer ) {
  718.             attach_window_buffer( current_window, replacementBuffer )
  719.         }
  720.         next_window()
  721.     } while ( current_window != sentinel )
  722.  
  723.     # restore the original window
  724.     if ( priorWindow ) {
  725.         current_window = priorWindow
  726.     }
  727.  
  728.     # delete the buffer, now that no windows (other than the current
  729.     # one) are attached
  730.  
  731.     current_buffer = bufid
  732.     eid = "unlock_file"        # avoids compiler warning
  733.     if (function_id( eid ))
  734.         execute_function( "unlock_file " buffer_filename );
  735.     delete_buffer()
  736.     if (bufid == current_buffer) {
  737.         # failed to delete buffer
  738.         current_buffer = priorBuffer
  739.         return FALSE
  740.     }
  741.  
  742.     # restore the original buffer if it was not the one deleted
  743.     if ( priorBuffer != bufid ) {
  744.         current_buffer = priorBuffer
  745.     } else {
  746.         # otherwise make the new current buffer the appropriate
  747.         # non-system buffer; and display the new filename
  748.         current_buffer = replacementBuffer
  749.         if ( dialog_window )
  750.             display_filename()
  751.     }
  752.     return TRUE
  753. }
  754.  
  755.  
  756. global function toggle_real_space( on ){
  757.  
  758.     if( argcount() < 1 )
  759.         on = !and( buffer_flags, BUFFER_REAL_SPACE_ONLY );
  760.     else
  761.         on = 0+on
  762.  
  763.     #
  764.     # toggle the setting
  765.     #
  766.     if (on)
  767.         buffer_flags = or( buffer_flags, BUFFER_REAL_SPACE_ONLY )
  768.     else
  769.         buffer_flags = and( buffer_flags, not(BUFFER_REAL_SPACE_ONLY) )
  770.  
  771.  
  772.     message( and( buffer_flags, BUFFER_REAL_SPACE_ONLY )     \
  773.         ? "Real space only."        \
  774.         : "Virtual space allowed." )
  775.     return on;
  776. }
  777.  
  778. global function write_buffer_key(){
  779.     if (and(buffer_flags, BUFFER_MODIFIED))
  780.         write_buffer();
  781. }
  782.  
  783. global function next_buffer_key(){
  784.     next_buffer();
  785.     if (dialog_window)
  786.         display_filename();
  787. }
  788.  
  789. global function prev_buffer_key(){
  790.     prev_buffer();
  791.     if (dialog_window)
  792.         display_filename();
  793. }
  794.