home *** CD-ROM | disk | FTP | other *** search
- # $Header: P:/source/ppee/macros/buffers.pev 1.123 21 Aug 1990 14:51:50 ericj $
-
- ##############################################################################
- #
- # Sage Software - POLYTRON Division
- # 1700 NW 167th Place
- # Beaverton, OR 97006
- #
- # Copyright 1990, Sage Software, Inc.
- #
- # Permission is hereby granted for licensed users of Sage Professional
- # Editor and PolyAwk to copy and modify this source code for their own
- # personal use. These derivative works may be distributed only to other
- # licensed Sage Professional Editor and PolyAwk users. All other usage
- # is prohibited without express written permission from Sage Software.
- #
- ##############################################################################
-
- #### $Workfile: buffers.pel $: Support for Buffers
-
-
- #
- # buffer flags:
- #
- global BUFFER_SYSTEM = 0x0001
- global BUFFER_IN_VIRTUAL_SPACE = 0x0002
- global BUFFER_POSITION_IS_VIRTUAL = 0x0002 # This is the documented one
- global BUFFER_CONTROL_Z_IS_EOF = 0x0004
- #reserved = 0x0008
- global BUFFER_READ_ONLY = 0x0010
- global BUFFER_AUTOSAVE_MODIFIED = 0x0020
- global BUFFER_MODIFIED = 0x0040
- global BUFFER_OVERTYPE_MODE = 0x0080
- global BUFFER_EXPAND_TABS = 0x0100
- global BUFFER_WP_ENABLED = 0x0200
- global BUFFER_REAL_SPACE_ONLY = 0x0400
- global BUFFER_SNAP_TO_EOL = 0x0800
- global BUFFER_NO_UNDO = 0x1000
- global BUFFER_TABS_TO_SPACES = 0x2000
- global BUFFER_WHOLE_LINES = 0x4000
-
- #user defined buffer flags
- global DOS_BUFFER_FLAG = 0x00020000;
-
- global print_device = "prn"
-
-
-
-
-
-
-
- ##
- ## functions to interrogate/set bits in the buffer_flags word
- ##
-
- global function buffer_is_modified(){
- return ( and(buffer_flags, BUFFER_MODIFIED) != 0 )
- }
-
- global function set_buffer_flag( mask, value ) {
- if ( value )
- buffer_flags = or( buffer_flags, mask )
- else
- buffer_flags = and( buffer_flags, not(mask) )
-
- return value
- }
-
- global function set_default_buffer_flag( mask, value ) {
- if ( value )
- default_buffer_flags = or( default_buffer_flags, mask )
- else
- default_buffer_flags = and( default_buffer_flags, not(mask) )
-
- return value
- }
-
-
- ##
- ## buffer_list() - pop up a menu with a list of active buffers
- ##
-
- global function buffer_list( systemFlag )
- {
- local bufferListArray # array containing the buffer list
- local sequenceArray
- local bl_buffer
-
- local nBuffers
- local thisBuffer
- local headBuffer
- local priorWindow = current_window
- local fn
- local entry
- local scanCode, asciiCode
- local fmode, bmode, newMode, sameMode
- local resp
- local key
- local i
-
- thisBuffer = headBuffer = current_buffer
-
- # ensure that headBuffer is not a system buffer
- if ( and( buffer_flags, BUFFER_SYSTEM ) && !systemFlag ) {
- headBuffer = next_buffer()
- }
-
- # build the buffer list
-
- nBuffers = 0
- do {
- # start with the full file name
- fn = buffer_filename
- if ( fn == "" )
- fn = "[" buffer_name "]"
-
- # append selected attribute flags
- if ( and( buffer_flags, BUFFER_MODIFIED ))
- fn = fn "*"
-
- if ( and( buffer_flags, BUFFER_READ_ONLY ))
- fn = fn " (RO)"
-
- if ( and( buffer_flags, BUFFER_SYSTEM ))
- fn = buffer_name " (System Buffer)"
-
- # update the buffer list arrays
- sequenceArray[ nBuffers++ ] = fn
- bufferListArray[ fn ] = current_buffer
-
- # advance to next buffer in ring
- next_buffer( "", systemFlag )
-
- } while ( current_buffer != headBuffer )
-
- # create a system buffer for the buffer list
-
- current_window = create_factory_window( 20, 2, 55, 20, \
- WINDOW_MENU + WINDOW_SB_RIGHT )
- current_buffer = bl_buffer = create_buffer( \
- "Buffer List", \
- "", \
- BUFFER_SYSTEM + BUFFER_NO_UNDO )
- attach_window_buffer( current_window, current_buffer )
- window_name = "Buffer List"
-
- for ( i=0; i<nBuffers; i++ ) {
- insert_string( sequenceArray[i] )
- insert_newline()
- }
- backspace()
- delete sequenceArray
- goto_buffer_top()
-
- # put up an instructions
- message( " or : <Enter> to select" \
- ", D(elete), W(rite), R(ead-only), <Esc> to exit" )
-
- # buffer list command loop
- do {
- # find the current buffer id
- fn = read_buffer()
- if ( fn in bufferListArray ) {
- entry = bufferListArray[ fn ]
- } else {
- warning( "Internal error in buffer_list" \
- " - cannot continue" )
- break
- }
-
- # get the buffer list command
- drop_anchor( LINE_SELECTION )
- display_update()
- key = getkey()
- flush_keyboard()
-
- scanCode = asciiCode = key
- scanCode = shiftr( scanCode, 8 )
- asciiCode = toupper( chr( and( asciiCode, 0xff )))
- raise_anchor()
-
- if ( asciiCode == "\r" ) { # Enter key
- # make selected buffer current
- thisBuffer = entry
- break
-
- } else if ( asciiCode == "D" ) {
- # delete the buffer and the entry
- if ( delete_buffer_key( entry ) ) {
- delete_line()
- if (current_line_length == 0 ) {
- backspace()
- current_column = 0
- }
- }
-
- } else if ( asciiCode == "W" ) {
- # write the buffer
- current_buffer = entry
- write_buffer()
- current_buffer = bl_buffer
-
- # remove the '*' from the entry in the buffer list
- if ( (match( fn, /\*/ )) ) {
- current_column = RSTART
- delete_chars(1)
- goto_bol()
- bufferListArray[ read_buffer() ] = entry
- }
-
- } else if ( asciiCode == "R" ) {
- # toggle the read-only bit
- current_buffer = entry
- buffer_flags = xor( buffer_flags, BUFFER_READ_ONLY )
- fn = buffer_filename
- fmode = filemode( fn )
- bmode = (and( buffer_flags, BUFFER_READ_ONLY ) != 0)
- current_buffer = bl_buffer
-
- # update the "(RO)" tag in the buffer list
- if ( (match( read_buffer(), / \(RO\)/ )) ) {
- current_column = RSTART
- delete_chars(RLENGTH)
- } else {
- current_column = current_line_length + 1
- insert_string( " (RO)" )
- }
- goto_bol()
- bufferListArray[ read_buffer() ] = entry
-
- # ask if we should change the disk file's
- # read-only attribute bit
-
- if ( fmode >= 0 ) {
-
- # get the new file attributes
- fmode = xor( fmode, _READ_ONLY )
- newMode = bmode ? "read-only" : "writable"
-
- # does the disk read-only mode match the buffer's?
- sameMode = ( (and( fmode, _READ_ONLY ) != 0) \
- == bmode)
-
- # make the change after getting confirmation
- if ( sameMode ) {
- resp = toupper( confirm( \
- "make file " fn " " newMode \
- " also? [yn]", "yYnN" ))
- if ( resp == "Y" ) {
- filemode( fn, fmode )
- } else if ( resp == "" ) {
- # replace misleading "canceled" message
- message( "" )
- }
- }
- }
-
- } else if ( scanCode == SCANCODE_HOME ) {
- current_line = 1
- } else if ( scanCode == SCANCODE_END ) {
- current_line = buffer_last_line
- } else if ( scanCode == SCANCODE_UP ) {
- # preceeding entry, wrap at top
- if (current_line == 1 ) {
- current_line = buffer_last_line
- } else {
- current_line--
- }
- } else if ( scanCode == SCANCODE_DOWN ) {
- # succeeding entry, wrap at bottom
- if (current_line == buffer_last_line ) {
- current_line = 1
- } else {
- current_line++
- }
- } else if ( scanCode == SCANCODE_LEFT_PRESS ||
- scanCode == SCANCODE_LEFT_CLICK ) {
- menu_mouse_key()
- }
-
- } while ( scanCode != SCANCODE_ESC ) # Escape key
-
- # remove the buffer and window
- delete_buffer( bl_buffer )
- delete_window()
- if ( priorWindow ) {
- current_window = priorWindow
- }
- bl_buffer = 0
-
- # remove the buffer list array
- delete bufferListArray
-
- # select the new current buffer
- if ( thisBuffer ) {
- current_buffer = thisBuffer
- display_filename()
- } else {
- message( "" )
- }
- }
-
-
-
- global function delete_buffer_without_asking( bufferToDelete )
- {
- local priorBuffer = current_buffer
-
- current_buffer = bufferToDelete
- if ( current_buffer == bufferToDelete ) {
- #
- # if the buffer exists, clear the buffer modified bit first
- # in order to avoid the "buffer had been modified" prompt
- #
- buffer_flags = and( buffer_flags, not( BUFFER_MODIFIED ) )
- delete_buffer()
- current_buffer = priorBuffer
- }
- }
-
- global function display_filename( useNotify )
- {
- local fn = buffer_filename
-
- # get the status of the modified bit in the current buffer
- if ( and( buffer_flags, BUFFER_MODIFIED )) {
- fn = fn "*"
- }
-
- if ( useNotify )
- notify( "File: " fn )
- else
- message( "File: " fn )
- }
-
- global function change_output_name()
- {
- local newOutputName
-
- newOutputName = prompt("Enter new output file name: ", "")
- if (newOutputName) {
- buffer_filename = newOutputName
- buffer_name = path_fname(buffer_filename) \
- path_ext(buffer_filename)
- buffer_flags = or( buffer_flags, BUFFER_MODIFIED );
- }
-
- display_update()
- }
-
-
- #
- # paste()
- #
- # a synonym for insert_scrap()
- #
- global function paste() #PUBLIC #INT
- {
- return insert_scrap()
- }
-
- # cut()
- #
- # a synonym for delete_to_scrap()
- #
- global function cut(){ #PUBLIC #INT
- return delete_to_scrap()
- }
-
-
- global function print_buffer() #PUBLIC #VOID
- {
- local expand_tabs = and( buffer_flags, BUFFER_EXPAND_TABS );
-
- message( "Printing..." );
-
- buffer_flags = or( buffer_flags, BUFFER_EXPAND_TABS );
-
- if (region_type() != 0)
- write_marked_block( print_device )
- else
- write_buffer( print_device )
-
-
-
- if (!expand_tabs)
- buffer_flags = and( buffer_flags, not(BUFFER_EXPAND_TABS) );
-
- message( "Printing complete." )
- }
-
-
-
-
- #
- # Backups will be made in the appropriate directory according to the
- # following rules:
- #
- #
- #
- # Using c:\foo\test.c as the same test file
- #
- #
- # \ backup_file_ext ==
- # \
- # \ │
- # \ ".bak" │ "" | "*"
- # backup_directory == ┌────────────────────────┼─────────────────────┐
- # │ │ │
- # "" │ \spe\backup\test.bak │ \spe\backup\test.c │
- # │ │ │
- # ───┼────────────────────────┼─────────────────────┤
- # │ │ │
- # "*" │ c:\foo\test.bak │ c:\foo\test.bak │
- # │ │ │
- # ───┼────────────────────────┼─────────────────────┤
- # │ │ │
- # (any dir) "~~~\" │ ~~~\test.bak │ ~~~\test.c │
- # │ │ │
- # └────────────────────────┴─────────────────────┘
- #
- # Values for backup_directory:
- # "*" - means the directory where the file was originally loaded from
- # "~~~\" - any valid drive and path name.
- # "" - use the directory \spe\backup on the current drive
- #
- # Values for backup_file_ext:
- # ".bak" - and valid extension to be used as the new backup file extension
- # ( if !("*" or "") always uses ".bak" for now
- # "" - use the current file's extension as the backup file extension
- # "*" - use the current file's extension as the backup file extension
- #
-
- global backup_directory
- global backup_file_ext
-
-
- global function backup_file( fname )
- {
- local pos, bakFilename
- local pname
- local new_ext = ".bak";
- local new_path;
- local dest_drive;
- local fmode;
-
- fname = buildpath( fname );
-
- if (!backup_files_enabled || (filemode( fname ) == -1))
- return TRUE;
- else{
-
- if (backup_file_ext == "*" || !backup_file_ext)
- new_ext = path_ext( fname );
- else
- new_ext = backup_file_ext;
-
-
- if (substr( new_ext, 1, 1) != ".")
- new_ext = "." new_ext;
-
- new_ext = substr( new_ext, 1, 4);
-
- if (backup_directory && (backup_directory != "*")) {
- backup_directory = buildpath( backup_directory );
- new_path = trim( backup_directory, "\\" );
- if (filemode( new_path ) != _SUBDIR ) {
- warning( "Invalid backup directory path: " backup_directory "." );
- backup_directory = "";
- }
-
- }
-
- if (!backup_directory) {
- new_path = buildpath( "\\spe\\backup" );
-
- if (filemode("\\spe" ) != _SUBDIR){
- if (!mkdir( "\\spe" )) {
- warning( "Cannot create backup directory `\\spe'." );
- backup_directory = "*";
- }
- }
- if (filemode("\\spe\\backup" ) != _SUBDIR)
- if (!mkdir( "\\spe\\backup" )) {
- warning( "Cannot create backup directory `\\spe\\backup'." );
- backup_directory = "*";
- }
- }
-
- if (backup_directory == "*") {
- new_path = path_path( fname )
- }
-
- pname = "\\" path_fname( fname );
- new_path = trim( new_path, "\\" );
-
- bakFilename = new_path pname new_ext;
- if (bakFilename == fname )
- bakFilename = new_path pname ".bak"
-
- message( "Writing backup file '" bakFilename "'." );
-
- dest_drive = substr( bakFilename, 1, 1 );
- if (bakFilename != fname ){
- fmode = filemode( bakFilename );
- if ( (fmode != -1) && and( fmode, _READ_ONLY )){
- if (tolower(confirm( "`" bakFilename "' is read-only, overwrite?", "yYnN")) != "y")
- return FALSE;
- filemode( bakFilename, _NORMAL );
- }
-
- if ( dest_drive == substr( fname, 1, 1 ) ){
- # backing up on same disk, just rename it.
- #
- if (buffer_size * 2 >= disk_free( dest_drive )) {
- warning( "Not enough disk space on drive " dest_drive ": no backup created!");
- return FALSE;
- }
-
- unlink( bakFilename );
- return rename( fname, bakFilename )
- }
- else
- return filecopy( fname, bakFilename )
- }
- }
- return FALSE
- }
-
-
- ## write_all_buffers()
- #
- # write all of the modified buffers to their output file but first
- # check the read/write permission of the output file. Two passes are
- # made at writing the files: first, save all of the r/w files, second,
- # try to save the read-only files which will generate an error.
- #
- global function write_all_buffers() #PUBLIC #INT
- {
- local priorWindow = current_window
- local old_curnt_buffer = current_buffer
- local fmask = BUFFER_MODIFIED + BUFFER_READ_ONLY
- local buf = current_buffer;
- local exitBuffers = 0;
-
- #
- # create a temporary window so that the original window does
- # not change when messages are written
- current_window = create_window( 1,1,1,1, WINDOW_SYSTEM )
- hide_window()
-
- if ( and(buffer_flags,BUFFER_SYSTEM) )
- old_curnt_buffer = next_buffer();
-
- #
- # loop through the list of buffers and write all of the
- # read/write files first
- #
- do {
- #
- # see if the buffer has changed
- #
- if ( and( buffer_flags, fmask ) == BUFFER_MODIFIED) {
- #
- # don't save read-only files this pass
- #
- message( buffer_filename )
- if (!backup_file( buffer_filename )){
- notify( "Unable to create backup file for `" buffer_filename "'" );
- exitBuffers = 1;
- break;
- }
- if (write_buffer() < 0 ){
- exitBuffers = 1;
- break;
- }
- }
- next_buffer()
- } while (old_curnt_buffer != current_buffer)
-
-
- #
- # now loop through again and try to write the read-only files
- # which will generate an error, but at least the r/w files
- # have been saved.
- #
- if (!exitBuffers){
- do {
- #
- # see if the buffer has changed
- #
- if ( and( buffer_flags, fmask ) == fmask ) {
- #
- # save the read-only files this pass
- #
- message( buffer_filename )
- if (!backup_file( buffer_filename )){
- notify( "Unable to create backup file for `" buffer_filename "'" );
- exitBuffers = 1;
- break;
- }
- if (write_buffer() < 0 )
- exitBuffers = 1;
- break;
- }
- next_buffer()
- } while (old_curnt_buffer != current_buffer)
- }
-
- current_buffer = buf;
-
- # restore the original window
- delete_window()
- if ( window_valid( priorWindow ))
- current_window = priorWindow
-
- message( "" )
- return !exitBuffers;
- }
-
-
-
-
- ## alter current_buffer's tab settings
- #
- global function tabs( stops1, stops2 ){ #PUBLIC #VOID
- if( !stops1 )
- stops1 = prompt( "Enter tab stop settings: ", buffer_tabs )
- else if (argcount() > 1)
- stops1 = stops1 " " stops2;
-
- if( stops1 ){
- buffer_tabs = stops1
- message( "" )
- }
- }
-
-
- ## delete_buffer_key()
- #
- # A replacement for the delete_buffer() function to be bound to keys.
- # It protects the user from accidently having a system buffer (such as the
- # DOS buffer or help buffer) become current.
- #
- # The bufid argument is an optional buffer id of the buffer to delete.
- # If not specified, the current buffer will be deleted.
- #
- # The nextFlag argument is a flag which should be set to 1 (TRUE) to have the
- # deleted buffer be replaced with next_buffer() rather than prev_buffer().
- # The default is prev_buffer().
- #
- # The return value is FALSE if the specified buffer is the only buffer or if
- # they answer no to the "really delete?" prompt.
- #
- global function delete_buffer_key( bufid, nextFlag ) {
-
- local priorWindow = current_window
- local priorBuffer = current_buffer
- local replacementBuffer
- local sentinel
- local resp
- local eid
-
- # make the specified buffer current
- if ( bufid ) {
- current_buffer = bufid
- } else {
- bufid = current_buffer
- }
-
- # find the buffer to use to replace the deleted buffer. Stop
- # now if the buffer to delete is the last regular buffer.
-
- if ( nextFlag ) {
- next_buffer()
- } else {
- prev_buffer()
- }
- if ( current_buffer == bufid ) {
- current_buffer = priorBuffer
- warning( "Cannot delete last buffer" )
- return FALSE
- } else {
- replacementBuffer = current_buffer
- current_buffer = bufid
- }
-
- # ask for confirmation if the buffer has been modified
- if ( and( buffer_flags, BUFFER_MODIFIED )) {
- current_buffer = priorBuffer
- resp = toupper( confirm(
- "Buffer has been modified. Delete [ynw]? ",
- "YyNnWw" ))
- if ( resp == "Y" ) {
- # yes, turn off the modified bit and proceed
- current_buffer = bufid
- buffer_flags = xor( buffer_flags, BUFFER_MODIFIED )
- } else if ( resp == "W" ) {
- # write first, clearing the modified bit as we do
- current_buffer = bufid
- write_buffer()
- } else {
- return FALSE
- }
- }
-
- # fix all non_system windows attached to this buffer
-
- if ( and( window_flags, WINDOW_SYSTEM ) ) {
- sentinel = next_window()
- } else {
- sentinel = current_window
- }
-
- do {
- if ( bufid == current_buffer ) {
- attach_window_buffer( current_window, replacementBuffer )
- }
- next_window()
- } while ( current_window != sentinel )
-
- # restore the original window
- if ( priorWindow ) {
- current_window = priorWindow
- }
-
- # delete the buffer, now that no windows (other than the current
- # one) are attached
-
- current_buffer = bufid
- eid = "unlock_file" # avoids compiler warning
- if (function_id( eid ))
- execute_function( "unlock_file " buffer_filename );
- delete_buffer()
- if (bufid == current_buffer) {
- # failed to delete buffer
- current_buffer = priorBuffer
- return FALSE
- }
-
- # restore the original buffer if it was not the one deleted
- if ( priorBuffer != bufid ) {
- current_buffer = priorBuffer
- } else {
- # otherwise make the new current buffer the appropriate
- # non-system buffer; and display the new filename
- current_buffer = replacementBuffer
- if ( dialog_window )
- display_filename()
- }
- return TRUE
- }
-
-
- global function toggle_real_space( on ){
-
- if( argcount() < 1 )
- on = !and( buffer_flags, BUFFER_REAL_SPACE_ONLY );
- else
- on = 0+on
-
- #
- # toggle the setting
- #
- if (on)
- buffer_flags = or( buffer_flags, BUFFER_REAL_SPACE_ONLY )
- else
- buffer_flags = and( buffer_flags, not(BUFFER_REAL_SPACE_ONLY) )
-
-
- message( and( buffer_flags, BUFFER_REAL_SPACE_ONLY ) \
- ? "Real space only." \
- : "Virtual space allowed." )
- return on;
- }
-
- global function write_buffer_key(){
- if (and(buffer_flags, BUFFER_MODIFIED))
- write_buffer();
- }
-
- global function next_buffer_key(){
- next_buffer();
- if (dialog_window)
- display_filename();
- }
-
- global function prev_buffer_key(){
- prev_buffer();
- if (dialog_window)
- display_filename();
- }
-