home *** CD-ROM | disk | FTP | other *** search
- /* buffers.c -- Buffer handling
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #include <string.h>
- #include <stdlib.h>
-
- _PR void buffer_sweep(void);
- _PR void buffer_prin(VALUE, VALUE);
- _PR TX *first_buffer(void);
- _PR void swap_buffers(VW *, TX *);
- _PR TX *swap_buffers_tmp(VW *, TX *);
- _PR POS *get_tx_cursor(TX *);
- _PR int auto_save_buffers(void);
- _PR void make_marks_resident(TX *);
- _PR void make_marks_non_resident(TX *);
- _PR void mark_sweep(void);
- _PR int mark_cmp(VALUE, VALUE);
- _PR void mark_prin(VALUE, VALUE);
- _PR void buffers_init(void);
- _PR void buffers_kill(void);
-
- /*
- * Chain of all allocated TXs.
- */
- _PR TX *buffer_chain;
- TX *buffer_chain;
-
- VALUE sym_auto_save_function, sym_leading, sym_all;
-
- _PR VALUE cmd_make_buffer_name(VALUE);
- DEFUN("make-buffer-name", cmd_make_buffer_name, subr_make_buffer_name, (VALUE rawName), V_Subr1, DOC_make_buffer_name) /*
- ::doc:make_buffer_name::
- make-buffer-name NAME
-
- Construct a unique buffer-name from NAME.
- ::end:: */
- {
- int suffix = 1;
- DECLARE1(rawName, STRINGP);
- while(TRUE)
- {
- u_char buf[256];
- u_char *thistry;
- TX *tx = buffer_chain;
- if(suffix != 1)
- {
- sprintf(buf, "%s<%d>", VSTR(rawName), suffix);
- thistry = buf;
- }
- else
- thistry = VSTR(rawName);
- while(tx)
- {
- if(tx->tx_BufferName && !strcmp(thistry, VSTR(tx->tx_BufferName)))
- break;
- tx = tx->tx_Next;
- }
- if(!tx)
- {
- if(suffix == 1)
- return(rawName);
- return(string_dup(buf));
- }
- suffix++;
- }
- }
-
- _PR VALUE cmd_make_buffer(VALUE, VALUE, VALUE);
- DEFUN("make-buffer", cmd_make_buffer, subr_make_buffer, (VALUE name, VALUE oldTx, VALUE litName), V_Subr3, DOC_make_buffer) /*
- ::doc:make_buffer::
- make-buffer NAME
-
- Return a new buffer, it's name is the result of (make-buffer-name NAME).
- ::end:: */
- {
- TX *tx;
- DECLARE1(name, STRINGP);
- if(!BUFFERP(oldTx))
- {
- if(curr_vw)
- oldTx = VAL(curr_vw->vw_Tx);
- else
- oldTx = NULL;
- }
- if((tx = mycalloc(sizeof(TX))) && clear_line_list(tx))
- {
- tx->tx_Type = V_Buffer;
- tx->tx_Next = buffer_chain;
- buffer_chain = tx;
- data_after_gc += sizeof(TX);
- tx->tx_BufferName = NILP(litName) ? cmd_make_buffer_name(name) : name;
- if(tx->tx_BufferName)
- {
- tx->tx_FileName = null_string;
- tx->tx_MinorModeNameList = sym_nil;
- tx->tx_MinorModeNameString = null_string;
- tx->tx_SavedBlockStatus = -1;
- tx->tx_TabSize = 8;
- tx->tx_LocalVariables = sym_nil;
- tx->tx_GlyphTable = oldTx ? VTX(oldTx)->tx_GlyphTable
- : cmd_default_glyph_table();
- tx->tx_LastSaveTime = sys_time();
- tx->tx_UndoList = sym_nil;
- tx->tx_ToUndoList = NULL;
- tx->tx_UndoneList = sym_nil;
- return(VAL(tx));
- }
- }
- return(NULL);
- }
-
- _PR VALUE cmd_destroy_buffer(VALUE);
- DEFUN("destroy-buffer", cmd_destroy_buffer, subr_destroy_buffer, (VALUE tx), V_Subr1, DOC_destroy_buffer) /*
- ::doc:destroy_buffer::
- destory-buffer BUFFER
-
- Throw away everything associated with buffer. All resident marks are made
- non-resident.
- ::end:: */
- {
- DECLARE1(tx, BUFFERP);
- make_marks_non_resident(VTX(tx));
- clear_line_list(VTX(tx));
- VTX(tx)->tx_FileName = null_string;
- VTX(tx)->tx_BufferName = null_string;
- VTX(tx)->tx_ModeName = NULL;
- VTX(tx)->tx_MinorModeNameList = sym_nil;
- VTX(tx)->tx_MinorModeNameString = null_string;
- VTX(tx)->tx_Changes = 0;
- VTX(tx)->tx_LocalVariables = sym_nil;
- VTX(tx)->tx_GlyphTable = cmd_default_glyph_table();
- VTX(tx)->tx_Flags |= TXFF_RDONLY | TXFF_REFRESH_ALL | TXFF_NO_UNDO;
- VTX(tx)->tx_UndoList = sym_nil;
- VTX(tx)->tx_ToUndoList = NULL;
- VTX(tx)->tx_UndoneList = sym_nil;
- #if 0
- sm_flush(&main_strmem);
- #endif
- return(sym_t);
- }
-
- void
- buffer_sweep(void)
- {
- TX *tx = buffer_chain;
- buffer_chain = NULL;
- while(tx)
- {
- TX *nxt = tx->tx_Next;
- if(!GC_MARKEDP(VAL(tx)))
- {
- make_marks_non_resident(tx);
- kill_line_list(tx);
- myfree(tx);
- }
- else
- {
- GC_CLR(VAL(tx));
- tx->tx_Next = buffer_chain;
- buffer_chain = tx;
- }
- tx = nxt;
- }
- }
- void
- buffer_prin(VALUE strm, VALUE obj)
- {
- stream_puts(strm, "#<buffer ", -1, FALSE);
- stream_puts(strm, VSTR(VTX(obj)->tx_BufferName), -1, TRUE);
- stream_putc(strm, '>');
- }
-
- TX *
- first_buffer(void)
- {
- TX *tx;
- if(!curr_vw)
- {
- curr_vw = VWIN(cmd_make_window(sym_nil, sym_nil, sym_nil, sym_nil));
- if(!curr_vw)
- return(NULL);
- }
- tx = VTX(cmd_make_buffer(MKSTR("*jade*"), sym_nil, sym_t));
- if(tx)
- {
- swap_buffers(curr_vw, tx);
- #ifndef NOSCRLBAR
- sys_update_scroller(curr_vw);
- #endif
- return(tx);
- }
- return(NULL);
- }
-
- /*
- * Makes `new' the file being shown in window `vw'
- */
- void
- swap_buffers(VW *vw, TX *new)
- {
- TX *old = vw->vw_Tx;
- if(old != new)
- {
- if(old)
- {
- old->tx_SavedCPos = vw->vw_CursorPos;
- old->tx_SavedWPos = vw->vw_DisplayOrigin;
- old->tx_SavedBlockPos[0] = vw->vw_BlockS;
- old->tx_SavedBlockPos[1] = vw->vw_BlockE;
- old->tx_SavedBlockStatus = vw->vw_BlockStatus;
- }
- vw->vw_Tx = new;
- vw->vw_CursorPos = new->tx_SavedCPos;
- vw->vw_DisplayOrigin = new->tx_SavedWPos;
- vw->vw_BlockS = new->tx_SavedBlockPos[0];
- vw->vw_BlockE = new->tx_SavedBlockPos[1];
- vw->vw_BlockStatus = new->tx_SavedBlockStatus;
- vw->vw_LastRefTx = NULL;
- }
- }
- /*
- * "nd" means non-destructive. refcount's of buffers are not changed and
- * previous buffer shown is returned.
- * This is intended to allow *temporary* switching of buffers before
- * reinstalling the original.
- * ** this is kind of obsolete but never mind **
- */
- TX *
- swap_buffers_tmp(VW *vw, TX *new)
- {
- TX *old = vw->vw_Tx;
- if(old != new)
- {
- if(old)
- {
- old->tx_SavedCPos = vw->vw_CursorPos;
- old->tx_SavedWPos = vw->vw_DisplayOrigin;
- old->tx_SavedBlockPos[0] = vw->vw_BlockS;
- old->tx_SavedBlockPos[1] = vw->vw_BlockE;
- old->tx_SavedBlockStatus = vw->vw_BlockStatus;
- }
- vw->vw_Tx = new;
- vw->vw_CursorPos = new->tx_SavedCPos;
- vw->vw_DisplayOrigin = new->tx_SavedWPos;
- vw->vw_BlockS = new->tx_SavedBlockPos[0];
- vw->vw_BlockE = new->tx_SavedBlockPos[1];
- vw->vw_BlockStatus = new->tx_SavedBlockStatus;
- }
- return(old);
- }
-
- _PR VALUE cmd_get_file_buffer(VALUE);
- DEFUN("get-file-buffer", cmd_get_file_buffer, subr_get_file_buffer, (VALUE name), V_Subr1, DOC_get_file_buffer) /*
- ::doc:get_file_buffer::
- get-file-buffer NAME
-
- Scan all buffers for one containing the file NAME.
- ::end:: */
- {
- TX *tx = buffer_chain;
- DECLARE1(name, STRINGP);
- while(tx)
- {
- if(same_files(VSTR(name), VSTR(tx->tx_FileName)))
- return(VAL(tx));
- tx = tx->tx_Next;
- }
- return(sym_nil);
- }
-
- _PR VALUE cmd_get_buffer(VALUE);
- DEFUN("get-buffer", cmd_get_buffer, subr_get_buffer, (VALUE name), V_Subr1, DOC_get_buffer) /*
- ::doc:get_buffer::
- get-buffer NAME
-
- Scan all buffers for one whose name is NAME.
- ::end:: */
- {
- TX *tx = buffer_chain;
- if(BUFFERP(name))
- return(name);
- DECLARE1(name, STRINGP);
- while(tx)
- {
- if(!strcmp(VSTR(name), VSTR(tx->tx_BufferName)))
- return(VAL(tx));
- tx = tx->tx_Next;
- }
- return(sym_nil);
- }
-
- POS *
- get_tx_cursor(TX *tx)
- {
- VW *vw = view_chain;
- /* Check active window first */
- if(curr_vw->vw_Tx == tx)
- return(&curr_vw->vw_CursorPos);
- while(vw)
- {
- if(vw->vw_Window && (vw->vw_Tx == tx))
- return(&vw->vw_CursorPos);
- vw = vw->vw_Next;
- }
- return(&tx->tx_SavedCPos);
- }
-
- /*
- * returns the number of buffers saved.
- * (maybe should only save one buffer at a time, then wait to be called
- * again to save next in line? This could be less intrusive: yes.)
- */
- int
- auto_save_buffers(void)
- {
- /*
- * Stops me entering here more than once at the same time. This
- * can happen when tracing the `auto-save-function'
- */
- static bool Exclusion;
- if(!Exclusion)
- {
- VALUE tx = VAL(buffer_chain);
- u_long time = sys_time();
- Exclusion = TRUE;
- while(tx)
- {
- if(VTX(tx)->tx_Changes
- && VTX(tx)->tx_AutoSaveInterval
- && (VTX(tx)->tx_LastSaveChanges != VTX(tx)->tx_Changes)
- && (time > (VTX(tx)->tx_LastSaveTime + VTX(tx)->tx_AutoSaveInterval)))
- {
- GCVAL gcv_tx;
- PUSHGC(gcv_tx, tx);
- call_lisp1(sym_auto_save_function, tx);
- POPGC;
- VTX(tx)->tx_LastSaveTime = time;
- VTX(tx)->tx_LastSaveChanges = VTX(tx)->tx_Changes;
- Exclusion = FALSE;
- return(1);
- }
- tx = VAL(VTX(tx)->tx_Next);
- }
- Exclusion = FALSE;
- }
- return(0);
- }
-
- _PR VALUE cmd_current_buffer(VALUE);
- DEFUN("current-buffer", cmd_current_buffer, subr_current_buffer, (VALUE vw), V_Subr1, DOC_current_buffer) /*
- ::doc:current_buffer::
- current-buffer [WINDOW]
-
- Return the buffer that WINDOW (or the current window) is displaying.
- ::end:: */
- {
- if(!WINDOWP(vw))
- vw = VAL(curr_vw);
- return(VAL(VWIN(vw)->vw_Tx));
- }
-
- _PR VALUE cmd_set_current_buffer(VALUE, VALUE);
- DEFUN("set-current-buffer", cmd_set_current_buffer, subr_set_current_buffer, (VALUE tx, VALUE vw), V_Subr2, DOC_set_current_buffer) /*
- ::doc:set_current_buffer::
- set-current-buffer BUFFER [WINDOW]
-
- Set the buffer that WINDOW (or the current window) is displaying. Returns
- the buffer which was being displayed before.
- ::end:: */
- {
- VALUE old;
- DECLARE1(tx, BUFFERP);
- if(!WINDOWP(vw))
- vw = VAL(curr_vw);
- old = VAL(VWIN(vw)->vw_Tx);
- swap_buffers(VWIN(vw), VTX(tx));
- return(old);
- }
-
- _PR VALUE cmd_buffer_file_name(VALUE);
- DEFUN("buffer-file-name", cmd_buffer_file_name, subr_buffer_file_name, (VALUE tx), V_Subr1, DOC_buffer_file_name) /*
- ::doc:buffer_file_name::
- buffer-file-name [BUFFER]
-
- Return the name of the file being edited in BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- return(VTX(tx)->tx_FileName);
- }
-
- _PR VALUE cmd_set_buffer_file_name(VALUE, VALUE);
- DEFUN("set-buffer-file-name", cmd_set_buffer_file_name, subr_set_buffer_file_name, (VALUE tx, VALUE name), V_Subr2, DOC_set_buffer_file_name) /*
- ::doc:set_buffer_file_name::
- set-buffer-file-name BUFFER NAME
-
- Set the name of the file being edited in BUFFER to NAME.
- ::end:: */
- {
- DECLARE1(name, STRINGP);
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- make_marks_non_resident(VTX(tx));
- VTX(tx)->tx_FileName = name;
- make_marks_resident(VTX(tx));
- return(name);
- }
-
- _PR VALUE cmd_buffer_name(VALUE);
- DEFUN("buffer-name", cmd_buffer_name, subr_buffer_name, (VALUE tx), V_Subr1, DOC_buffer_name) /*
- ::doc:buffer_name::
- buffer-name [BUFFER]
-
- Return the name of BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- return(VTX(tx)->tx_BufferName);
- }
-
- _PR VALUE cmd_set_buffer_name(VALUE, VALUE);
- DEFUN("set-buffer-name", cmd_set_buffer_name, subr_set_buffer_name, (VALUE tx, VALUE name), V_Subr2, DOC_set_buffer_name) /*
- ::doc:set_buffer_name::
- set-buffer-name BUFFER NAME
-
- Set the name of BUFFER to NAME.
- ::end:: */
- {
- DECLARE1(name, STRINGP);
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- VTX(tx)->tx_BufferName = name;
- sys_reset_sleep_titles(VTX(tx));
- return(name);
- }
-
- _PR VALUE cmd_buffer_changes(VALUE);
- DEFUN("buffer-changes", cmd_buffer_changes, subr_buffer_changes, (VALUE tx), V_Subr1, DOC_buffer_changes) /*
- ::doc:buffer_changes::
- buffer-changes [BUFFER]
-
- Return the number of modifications to BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- return(make_number(VTX(tx)->tx_Changes));
- }
-
- _PR VALUE cmd_buffer_modified_p(VALUE);
- DEFUN("buffer-modified-p", cmd_buffer_modified_p, subr_buffer_modified_p, (VALUE tx), V_Subr1, DOC_buffer_modified_p) /*
- ::doc:buffer_modified_p::
- buffer-modified-p [BUFFER]
-
- Returns t if the buffer has changed since it was last saved.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- /* TXFF_SPECIAL means this buffer's modifications aren't important. */
- if(VTX(tx)->tx_Flags & TXFF_SPECIAL)
- return(sym_nil);
- if(VTX(tx)->tx_Changes != VTX(tx)->tx_ProperSaveChanges)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_set_buffer_modified(VALUE, VALUE);
- DEFUN("set-buffer-modified", cmd_set_buffer_modified, subr_set_buffer_modified, (VALUE tx, VALUE stat), V_Subr2, DOC_set_buffer_modified) /*
- ::doc:set_buffer_modified::
- set-buffer-modified BUFFER STATUS
-
- If STATUS is nil make it look as though buffer hasn't changed, else make
- it look as though it has.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- if(NILP(stat))
- {
- VTX(tx)->tx_ProperSaveChanges = VTX(tx)->tx_Changes;
- VTX(tx)->tx_LastSaveChanges = VTX(tx)->tx_Changes;
- }
- else
- {
- VTX(tx)->tx_ProperSaveChanges = VTX(tx)->tx_Changes - 1;
- VTX(tx)->tx_LastSaveChanges = VTX(tx)->tx_Changes - 1;
- }
- return(tx);
- }
-
- _PR VALUE cmd_set_buffer_special(VALUE tx, VALUE specialp);
- DEFUN("set-buffer-special", cmd_set_buffer_special, subr_set_buffer_special, (VALUE tx, VALUE specialp), V_Subr2, DOC_set_buffer_special) /*
- ::doc:set_buffer_special::
- set-buffer-special BUFFER SPECIALP
-
- When a buffer is `special' it means that it is controlled by some Lisp code,
- not by the user typing into it (although this can still happen as well). This
- is used for things like the `*jade*' or `*Info*' buffers (in fact most of
- the buffers whose names are surrounded by asterisks are special).
-
- What the `special' attribute actually does is make sure that the buffer is
- never truely killed (`kill-buffer' removes it from each window's `buffer-list'
- but doesn't detroy the actual contents) and modifications don't cause the
- `+' marker to appear in the status line.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- if(NILP(specialp))
- VTX(tx)->tx_Flags &= ~TXFF_SPECIAL;
- else
- VTX(tx)->tx_Flags |= TXFF_SPECIAL;
- return(tx);
- }
-
- _PR VALUE cmd_buffer_special_p(VALUE tx);
- DEFUN("buffer-special-p", cmd_buffer_special_p, subr_buffer_special_p, (VALUE tx), V_Subr1, DOC_buffer_special_p) /*
- ::doc:buffer_special_p::
- buffer-special-p [BUFFER]
-
- Returns t if BUFFER is ``special''. See `set-buffer-special' for the meaning of
- the ``special'' attribute.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- if(VTX(tx)->tx_Flags & TXFF_SPECIAL)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_set_buffer_read_only(VALUE tx, VALUE stat);
- DEFUN("set-buffer-read-only", cmd_set_buffer_read_only, subr_set_buffer_read_only, (VALUE tx, VALUE stat), V_Subr2, DOC_set_buffer_read_only) /*
- ::doc:set_buffer_read_only::
- set-buffer-read-only BUFFER READ-ONLY-P
-
- If a buffer is read-only no modification of its contents is allowed.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- if(NILP(stat))
- VTX(tx)->tx_Flags &= ~TXFF_RDONLY;
- else
- VTX(tx)->tx_Flags |= TXFF_RDONLY;
- return(tx);
- }
-
- _PR VALUE cmd_buffer_read_only_p(VALUE tx);
- DEFUN("buffer-read-only-p", cmd_buffer_read_only_p, subr_buffer_read_only_p, (VALUE tx), V_Subr1, DOC_buffer_read_only_p) /*
- ::doc:buffer_read_only_p::
- buffer-read-only-p [BUFFER]
-
- Returns t if BUFFER is read-only. See `set-buffer-read-only'.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- if(VTX(tx)->tx_Flags & TXFF_RDONLY)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_buffer_length(VALUE);
- DEFUN("buffer-length", cmd_buffer_length, subr_buffer_length, (VALUE tx), V_Subr1, DOC_buffer_length) /*
- ::doc:buffer_length::
- buffer-length [BUFFER]
-
- Returns the number of lines in BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- return(make_number(VTX(tx)->tx_NumLines));
- }
-
- _PR VALUE cmd_line_length(VALUE, VALUE);
- DEFUN("line-length", cmd_line_length, subr_line_length, (VALUE pos, VALUE tx), V_Subr2, DOC_line_length) /*
- ::doc:line_length::
- line-length [LINE-POS] [BUFFER]
-
- Returns the length (not including newline) of the specified line, or
- using current cursor position if specifiers are not provided.
- ::end:: */
- {
- POS p;
- if(POSP(pos))
- {
- if(!BUFFERP(tx))
- tx = VAL(curr_vw->vw_Tx);
- p = VPOS(pos);
- }
- else
- {
- p = curr_vw->vw_CursorPos;
- tx = VAL(curr_vw->vw_Tx);
- }
- return(make_number(VTX(tx)->tx_Lines[p.pos_Line].ln_Strlen - 1));
- }
-
- _PR VALUE cmd_with_buffer(VALUE);
- DEFUN("with-buffer", cmd_with_buffer, subr_with_buffer, (VALUE args), V_SF, DOC_with_buffer) /*
- ::doc:with_buffer::
- with-buffer BUFFER FORMS...
-
- Temporarily switches to buffer, then executes the FORMS in it before
- returning to the original buffer.
- ::end:: */
- {
- if(CONSP(args))
- {
- GCVAL gcv_args;
- VALUE res;
- PUSHGC(gcv_args, args);
- if((res = cmd_eval(VCAR(args))) && BUFFERP(res))
- {
- VALUE oldtx = VAL(swap_buffers_tmp(curr_vw, VTX(res)));
- if(oldtx)
- {
- GCVAL gcv_oldtx;
- PUSHGC(gcv_oldtx, oldtx);
- res = cmd_progn(VCDR(args));
- POPGC;
- swap_buffers_tmp(curr_vw, VTX(oldtx));
- }
- }
- POPGC;
- return(res);
- }
- return(NULL);
- }
-
- _PR VALUE cmd_bufferp(VALUE);
- DEFUN("bufferp", cmd_bufferp, subr_bufferp, (VALUE arg), V_Subr1, DOC_bufferp) /*
- ::doc:bufferp::
- bufferp ARG
-
- Returns t if ARG is a buffer.
- ::end:: */
- {
- if(BUFFERP(arg))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE var_auto_save_interval(VALUE);
- DEFUN("auto-save-interval", var_auto_save_interval, subr_auto_save_interval, (VALUE val), V_Var, DOC_auto_save_interval) /*
- ::doc:auto_save_interval::
- The number of modifications which must be made to a buffer before it
- is considered for auto-saving. A value of zero means that this buffer
- is not to be auto-saved.
- ::end:: */
- {
- return(handle_var_int(val, &curr_vw->vw_Tx->tx_AutoSaveInterval));
- }
-
- _PR VALUE var_last_save_changes(VALUE);
- DEFUN("last-save-changes", var_last_save_changes, subr_last_save_changes, (VALUE val), V_Var, DOC_last_save_changes) /*
- ::doc:last_save_changes::
- Number of changes the last time this buffer was saved (could be auto-save).
- ::end:: */
- {
- return(handle_var_int(val, &curr_vw->vw_Tx->tx_LastSaveChanges));
- }
-
- _PR VALUE var_last_user_save_changes(VALUE);
- DEFUN("last-user-save-changes", var_last_user_save_changes, subr_last_user_save_changes, (VALUE val), V_Var, DOC_last_user_save_changes) /*
- ::doc:last_user_save_changes::
- Number of changes the last time this buffer was saved (not from auto-save).
- ::end:: */
- {
- return(handle_var_int(val, &curr_vw->vw_Tx->tx_ProperSaveChanges));
- }
-
- _PR VALUE var_last_save_time(VALUE);
- DEFUN("last-save-time", var_last_save_time, subr_last_save_time, (VALUE val), V_Var, DOC_last_save_time) /*
- ::doc:last_save_time::
- System time at last save of this buffer (could be from an auto-save).
- ::end:: */
- {
- return(handle_var_int(val, &curr_vw->vw_Tx->tx_LastSaveTime));
- }
-
- _PR VALUE var_tab_size(VALUE);
- DEFUN("tab-size", var_tab_size, subr_tab_size, (VALUE val), V_Var, DOC_tab_size) /*
- ::doc:tab_size::
- Sets the size of tab-stops.
- ::end:: */
- {
- return(handle_var_int(val, &curr_vw->vw_Tx->tx_TabSize));
- }
-
- _PR VALUE var_mode_name(VALUE);
- DEFUN("mode-name", var_mode_name, subr_mode_name, (VALUE val), V_Var, DOC_mode_name) /*
- ::doc:mode_name::
- This is used to display the name of the edit-mode being used in the status
- line.
- ::end:: */
- {
- TX *tx = curr_vw->vw_Tx;
- if(val)
- {
- if(STRINGP(val))
- tx->tx_ModeName = val;
- else
- tx->tx_ModeName = NULL;
- return(val);
- }
- else if(tx->tx_ModeName)
- return(tx->tx_ModeName);
- return(sym_nil);
- }
-
- _PR VALUE var_minor_mode_names(VALUE);
- DEFUN("minor-mode-names", var_minor_mode_names, subr_minor_mode_names, (VALUE val), V_Var, DOC_minor_mode_names) /*
- ::doc:minor_mode_names::
- List of strings naming all minor-modes enabled in this buffer.
- ::end:: */
- {
- TX *tx = curr_vw->vw_Tx;
- if(!val)
- return(tx->tx_MinorModeNameList);
- if(!CONSP(val))
- val = sym_nil;
- tx->tx_MinorModeNameList = val;
- if(NILP(val))
- tx->tx_MinorModeNameString = null_string;
- else
- {
- int len;
- u_char *str;
- VALUE tmp = val;
- for(len = 0; CONSP(tmp) && STRINGP(VCAR(tmp)); tmp = VCDR(tmp))
- len += STRING_LEN(VCAR(tmp)) + 1;
- tx->tx_MinorModeNameString = make_string(len + 1);
- str = VSTR(tx->tx_MinorModeNameString);
- tmp = val;
- while(CONSP(tmp) && STRINGP(VCAR(tmp)))
- {
- *str++ = ' ';
- str = stpcpy(str, VSTR(VCAR(tmp)));
- tmp = VCDR(tmp);
- }
- }
- return(val);
- }
-
- /* chain of all non-resident marks, linked via `mk_Next' */
- static Mark *non_resident_mark_chain;
- /* chain of all marks, linked via `mk_NextAlloc' */
- static Mark *mark_chain;
-
- /*
- * For all non-resident marks, see if any point to NEWTX, if so link them
- * onto NEWTX's `tx_Marks' chain.
- */
- void
- make_marks_resident(TX *newtx)
- {
- Mark *nxt, *mk = non_resident_mark_chain;
- non_resident_mark_chain = NULL;
- while(mk)
- {
- nxt = mk->mk_Next;
- if(same_files(VSTR(newtx->tx_FileName), VSTR(mk->mk_File.name)))
- {
- mk->mk_File.tx = newtx;
- mk->mk_Resident = TRUE;
- mk->mk_Next = newtx->tx_MarkChain;
- newtx->tx_MarkChain = mk;
- }
- else
- {
- mk->mk_Next = non_resident_mark_chain;
- non_resident_mark_chain = mk;
- }
- mk = nxt;
- }
- }
-
- void
- make_marks_non_resident(TX *oldtx)
- {
- Mark *nxt, *mk = oldtx->tx_MarkChain;
- oldtx->tx_MarkChain = NULL;
- while(mk)
- {
- nxt = mk->mk_Next;
- mk->mk_File.name = oldtx->tx_FileName;
- mk->mk_Resident = FALSE;
- mk->mk_Next = non_resident_mark_chain;
- non_resident_mark_chain = mk;
- mk = nxt;
- }
- }
-
- /*
- * Takes MK off the buffer mark chain that it's on (or the non_resident_mark_chain).
- */
- static void
- unchain_mark(Mark *mk)
- {
- Mark **headp, *this;
- if(!mk->mk_Resident)
- headp = &non_resident_mark_chain;
- else
- headp = &(mk->mk_File.tx->tx_MarkChain);
- this = *headp;
- *headp = NULL;
- while(this)
- {
- Mark *tmp = this->mk_Next;
- if(this != mk)
- {
- this->mk_Next = *headp;
- *headp = this;
- }
- this = tmp;
- }
- }
-
- void
- mark_sweep(void)
- {
- Mark *mk = mark_chain;
- mark_chain = NULL;
- while(mk)
- {
- Mark *nxt = mk->mk_NextAlloc;
- if(!GC_MARKEDP(VAL(mk)))
- {
- unchain_mark(mk);
- str_free(mk);
- }
- else
- {
- GC_CLR(VAL(mk));
- mk->mk_NextAlloc = mark_chain;
- mark_chain = mk;
- }
- mk = nxt;
- }
- }
-
- int
- mark_cmp(VALUE v1, VALUE v2)
- {
- int rc = 1;
- if(VTYPE(v1) == VTYPE(v2))
- {
- u_char *name1, *name2;
- if(VMARK(v1)->mk_Resident)
- name1 = VSTR(VMARK(v1)->mk_File.tx->tx_FileName);
- else
- name1 = VSTR(VMARK(v1)->mk_File.name);
- if(VMARK(v2)->mk_Resident)
- name2 = VSTR(VMARK(v2)->mk_File.tx->tx_FileName);
- else
- name2 = VSTR(VMARK(v2)->mk_File.name);
- if(same_files(name1, name2))
- {
- if(!(rc = VPOS(VMARK(v1)->mk_Pos).pos_Line - VPOS(VMARK(v2)->mk_Pos).pos_Line))
- rc = VPOS(VMARK(v1)->mk_Pos).pos_Col - VPOS(VMARK(v2)->mk_Pos).pos_Col;
- }
- }
- return(rc);
- }
-
- void
- mark_prin(VALUE strm, VALUE obj)
- {
- u_char tbuf[40];
- stream_puts(strm, "#<mark ", -1, FALSE);
- if(VMARK(obj)->mk_Resident)
- buffer_prin(strm, VAL(VMARK(obj)->mk_File.tx));
- else
- {
- stream_putc(strm, '"');
- stream_puts(strm, VSTR(VMARK(obj)->mk_File.name), -1, TRUE);
- stream_putc(strm, '"');
- }
- sprintf(tbuf, " #<pos %ld %ld>>",
- VPOS(VMARK(obj)->mk_Pos).pos_Col,
- VPOS(VMARK(obj)->mk_Pos).pos_Line);
- stream_puts(strm, tbuf, -1, FALSE);
- }
-
- _PR VALUE cmd_make_mark(VALUE, VALUE);
- DEFUN("make-mark", cmd_make_mark, subr_make_mark, (VALUE pos, VALUE buffer), V_Subr2, DOC_make_mark) /*
- ::doc:make_mark::
- make-mark [POS] [BUFFER | FILE-NAME]
-
- Creates a new mark pointing to position POS either in the current file
- or in FILE-NAME, or BUFFER.
-
- Note that FILE-NAME doesn't have to be a file that has been loaded, it's
- stored as a string, the file it points to is only opened when needed.
-
- Unlike position objects, the position in a file that a mark points to is
- updated as the file changes -- it will always point to the same character
- (for as long as that character exists, anyway).
- ::end:: */
- {
- Mark *mk = NULL;
- if((mk = str_alloc(sizeof(Mark))) && (mk->mk_Pos = make_lpos(NULL)))
- {
- mk->mk_Type = V_Mark;
- mk->mk_NextAlloc = mark_chain;
- mark_chain = mk;
- data_after_gc += sizeof(Mark);
- if(POSP(pos))
- VPOS(mk->mk_Pos) = VPOS(pos);
- else
- VPOS(mk->mk_Pos) = curr_vw->vw_CursorPos;
- if(STRINGP(buffer))
- {
- VALUE tx;
- if((tx = cmd_get_file_buffer(buffer)) && BUFFERP(tx))
- {
- mk->mk_Resident = TRUE;
- mk->mk_File.tx = VTX(tx);
- mk->mk_Next = VTX(tx)->tx_MarkChain;
- VTX(tx)->tx_MarkChain = mk;
- }
- else
- {
- mk->mk_Resident = FALSE;
- mk->mk_File.name = buffer;
- mk->mk_Next = non_resident_mark_chain;
- non_resident_mark_chain = mk;
- }
- }
- else
- {
- if(!BUFFERP(buffer))
- buffer = VAL(curr_vw->vw_Tx);
- mk->mk_Resident = TRUE;
- mk->mk_File.tx = VTX(buffer);
- mk->mk_Next = VTX(buffer)->tx_MarkChain;
- VTX(buffer)->tx_MarkChain = mk;
- }
- return(VAL(mk));
- }
- if(mk)
- str_free(mk);
- return(NULL);
- }
-
- _PR VALUE cmd_set_mark(VALUE, VALUE, VALUE);
- DEFUN("set-mark", cmd_set_mark, subr_set_mark, (VALUE mark, VALUE pos, VALUE buffer), V_Subr3, DOC_set_mark) /*
- ::doc:set_mark::
- set-mark MARK [POS] [FILE-NAME | BUFFER]
-
- Sets the position which MARK points to POS in FILE-NAME or BUFFER.
- ::end:: */
- {
- DECLARE1(mark, MARKP);
- if(POSP(pos))
- VPOS(VMARK(mark)->mk_Pos) = VPOS(pos);
- if(BUFFERP(buffer) || STRINGP(buffer))
- {
- Mark *mk, **chain;
- if(VMARK(mark)->mk_Resident)
- chain = &(VMARK(mark)->mk_File.tx->tx_MarkChain);
- else
- chain = &non_resident_mark_chain;
- mk = *chain;
- *chain = NULL;
- while(mk)
- {
- Mark *nxt = mk->mk_Next;
- if(mk != VMARK(mark))
- {
- mk->mk_Next = *chain;
- *chain = mk;
- }
- else
- mk->mk_Next = NULL;
- mk = nxt;
- }
- VMARK(mark)->mk_File.name = buffer;
- switch(VTYPE(buffer))
- {
- VALUE tmp;
- case V_StaticString:
- case V_DynamicString:
- tmp = cmd_get_file_buffer(buffer);
- if((tmp == NULL) || NILP(tmp))
- {
- VMARK(mark)->mk_Resident = FALSE;
- VMARK(mark)->mk_Next = non_resident_mark_chain;
- non_resident_mark_chain = VMARK(mark);
- break;
- }
- VMARK(mark)->mk_File.name = tmp;
- /* FALL THROUGH */
- case V_TX:
- VMARK(mark)->mk_Resident = TRUE;
- VMARK(mark)->mk_Next = VMARK(mark)->mk_File.tx->tx_MarkChain;
- VMARK(mark)->mk_File.tx->tx_MarkChain = VMARK(mark);
- break;
- }
- }
- return(mark);
- }
-
- _PR VALUE cmd_mark_pos(VALUE);
- DEFUN("mark-pos", cmd_mark_pos, subr_mark_pos, (VALUE mark), V_Subr1, DOC_mark_pos) /*
- ::doc:mark_pos::
- mark-pos MARK
-
- Returns the position that MARK points to. (note that this is the *same*
- object that the mark stores internally -- so don't modify it unless you're
- really sure you know what you're doing)
- ::end:: */
- {
- DECLARE1(mark, MARKP);
- return(VMARK(mark)->mk_Pos);
- }
-
- _PR VALUE cmd_mark_file(VALUE);
- DEFUN("mark-file", cmd_mark_file, subr_mark_file, (VALUE mark), V_Subr1, DOC_mark_file) /*
- ::doc:mark_file::
- mark-file MARK
-
- Returns the file-name or buffer that MARK points to.
- ::end:: */
- {
- DECLARE1(mark, MARKP);
- return(VMARK(mark)->mk_File.name);
- }
-
- _PR VALUE cmd_mark_resident_p(VALUE);
- DEFUN("mark-resident-p", cmd_mark_resident_p, subr_mark_resident_p, (VALUE mark), V_Subr1, DOC_mark_resident_p) /*
- ::doc:mark_resident_p::
- mark-resident-p MARK
-
- Returns t if the file that MARK points to is in a buffer.
- ::end:: */
- {
- DECLARE1(mark, MARKP);
- if(VMARK(mark)->mk_Resident)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_markp(VALUE);
- DEFUN("markp", cmd_markp, subr_markp, (VALUE mark), V_Subr1, DOC_markp) /*
- ::doc:markp::
- markp ARG
-
- Return t if ARG is a mark.
- ::end:: */
- {
- if(MARKP(mark))
- return(sym_t);
- return(sym_nil);
- }
-
- void
- buffers_init(void)
- {
- mark_static((VALUE *)&non_resident_mark_chain);
- INTERN(sym_auto_save_function, "auto-save-function");
- INTERN(sym_leading, "leading");
- INTERN(sym_all, "all");
- ADD_SUBR(subr_make_buffer_name);
- ADD_SUBR(subr_make_buffer);
- ADD_SUBR(subr_destroy_buffer);
- ADD_SUBR(subr_get_file_buffer);
- ADD_SUBR(subr_get_buffer);
- ADD_SUBR(subr_current_buffer);
- ADD_SUBR(subr_set_current_buffer);
- ADD_SUBR(subr_buffer_file_name);
- ADD_SUBR(subr_set_buffer_file_name);
- ADD_SUBR(subr_buffer_name);
- ADD_SUBR(subr_set_buffer_name);
- ADD_SUBR(subr_buffer_changes);
- ADD_SUBR(subr_buffer_modified_p);
- ADD_SUBR(subr_set_buffer_modified);
- ADD_SUBR(subr_set_buffer_special);
- ADD_SUBR(subr_buffer_special_p);
- ADD_SUBR(subr_set_buffer_read_only);
- ADD_SUBR(subr_buffer_read_only_p);
- ADD_SUBR(subr_buffer_length);
- ADD_SUBR(subr_line_length);
- ADD_SUBR(subr_with_buffer);
- ADD_SUBR(subr_bufferp);
- ADD_SUBR(subr_auto_save_interval);
- ADD_SUBR(subr_last_save_changes);
- ADD_SUBR(subr_last_user_save_changes);
- ADD_SUBR(subr_last_save_time);
- ADD_SUBR(subr_tab_size);
- ADD_SUBR(subr_mode_name);
- ADD_SUBR(subr_minor_mode_names);
- ADD_SUBR(subr_make_mark);
- ADD_SUBR(subr_set_mark);
- ADD_SUBR(subr_mark_pos);
- ADD_SUBR(subr_mark_file);
- ADD_SUBR(subr_mark_resident_p);
- ADD_SUBR(subr_markp);
- }
-
- void
- buffers_kill(void)
- {
- TX *tx = buffer_chain;
- Mark *mk = mark_chain;
- while(tx)
- {
- TX *nxttx = tx->tx_Next;
- kill_line_list(tx);
- myfree(tx);
- tx = nxttx;
- }
- buffer_chain = NULL;
- while(mk)
- {
- Mark *nxtmk = mk->mk_NextAlloc;
- str_free(mk);
- mk = nxtmk;
- }
- mark_chain = NULL;
- }
-