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>
-
- _PR void buffer_sweep(void);
- _PR void buffer_prin(VALUE, VALUE);
- _PR TX *firstbuffer(void);
- _PR void swapvwfiles(VW *, TX *);
- _PR TX *swapvwfilesnd(VW *, TX *);
- _PR int execfilecode(TX *, long *);
- _PR POS *gettxcurspos(TX *);
- _PR int autosavebuffers(void);
- _PR void makemarksres(TX *);
- _PR void makemarksnonres(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 *BufferChain;
- TX *BufferChain;
-
- VALUE sym_auto_save_function, sym_no_file_code_p, 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 = BufferChain;
- 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(valstrdup(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(CurrVW)
- oldTx = CurrVW->vw_Tx;
- else
- oldTx = NULL;
- }
- if((tx = mycalloc(sizeof(TX))) && clearlinelist(tx))
- {
- tx->tx_Type = V_Buffer;
- tx->tx_Next = BufferChain;
- BufferChain = tx;
- DataAfterGC += sizeof(TX);
- tx->tx_BufferName = NILP(litName) ? cmd_make_buffer_name(name) : name;
- if(tx->tx_BufferName)
- {
- tx->tx_FileName = NullString;
- tx->tx_SavedBlockStatus = -1;
- copyfileprefs(tx, oldTx);
- tx->tx_LocalVariables = sym_nil;
- tx->tx_LastSaveTime = getsystime();
- return(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);
- makemarksnonres(VTX(tx));
- clearlinelist(VTX(tx));
- VTX(tx)->tx_FileName = NullString;
- VTX(tx)->tx_BufferName = NullString;
- VTX(tx)->tx_ModeName = NULL;
- VTX(tx)->tx_Changes = 0;
- VTX(tx)->tx_LocalVariables = sym_nil;
- VTX(tx)->tx_Flags |= TXFF_RDONLY | TXFF_REFRESH_ALL;
- sm_flush(&MainStrMem);
- return(sym_t);
- }
-
- void
- buffer_sweep(void)
- {
- TX *tx = BufferChain;
- BufferChain = NULL;
- while(tx)
- {
- TX *nxt = tx->tx_Next;
- if(!GC_MARKEDP(tx))
- {
- makemarksnonres(tx);
- killlinelist(tx);
- myfree(tx);
- }
- else
- {
- GC_CLR(tx);
- tx->tx_Next = BufferChain;
- BufferChain = tx;
- }
- tx = nxt;
- }
- }
- void
- buffer_prin(VALUE strm, VALUE obj)
- {
- streamputs(strm, "#<buffer ", FALSE);
- streamputs(strm, VSTR(VTX(obj)->tx_BufferName), TRUE);
- streamputc(strm, '>');
- }
-
- TX *
- firstbuffer(void)
- {
- TX *tx;
- if(!CurrVW)
- {
- if(!(CurrVW = cmd_make_window(sym_nil, sym_nil, sym_nil, sym_nil)))
- return(NULL);
- }
- tx = cmd_make_buffer(MKSTR("*jade*"), sym_nil, sym_t);
- if(tx)
- {
- #ifndef NOSCRLBAR
- updatescroller(CurrVW);
- #endif
- swapvwfiles(CurrVW, tx);
- return(tx);
- }
- return(NULL);
- }
-
- /*
- * Makes `new' the file being shown in window `vw'
- */
- void
- swapvwfiles(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 *
- swapvwfilesnd(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 = BufferChain;
- DECLARE1(name, STRINGP);
- while(tx)
- {
- if(samefiles(VSTR(name), VSTR(tx->tx_FileName)))
- return(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 = BufferChain;
- if(BUFFERP(name))
- return(name);
- DECLARE1(name, STRINGP);
- while(tx)
- {
- if(!strcmp(VSTR(name), VSTR(tx->tx_BufferName)))
- return(tx);
- tx = tx->tx_Next;
- }
- return(sym_nil);
- }
-
- int
- execfilecode(TX *tx, long *codePos)
- {
- bool rc = FALSE;
- String *buf;
- long buflen;
- VALUE nfc;
- if((nfc = cmd_symbol_value(sym_no_file_code_p)) && !NILP(nfc))
- return(rc);
- buflen = (codePos[2] - codePos[1]) * 100;
- buf = mystralloc(buflen + 1);
- if(buf)
- {
- if(colcopysect(tx, codePos, VSTR(buf), buflen))
- {
- TX *old;
- buf->str_Type = V_String;
- old = swapvwfilesnd(CurrVW, tx);
- if(old)
- {
- VALUE res;
- if((res = evalstring(VSTR(buf), TRUE)) && !NILP(res))
- rc = TRUE;
- swapvwfilesnd(CurrVW, old);
- }
- }
- mystrfree(buf);
- }
- return(rc);
- }
-
- POS *
- gettxcurspos(TX *tx)
- {
- VW *vw = ViewChain;
- /* Check active window first */
- if(CurrVW->vw_Tx == tx)
- return(&CurrVW->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
- autosavebuffers(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 = BufferChain;
- u_long time = getsystime();
- 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);
- calllisp1(sym_auto_save_function, tx);
- POPGC;
- VTX(tx)->tx_LastSaveTime = time;
- VTX(tx)->tx_LastSaveChanges = VTX(tx)->tx_Changes;
- Exclusion = FALSE;
- return(1);
- }
- tx = 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 = CurrVW;
- return(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 = CurrVW;
- old = VWIN(vw)->vw_Tx;
- swapvwfiles(VWIN(vw), VTX(tx));
- return(old);
- }
-
- _PR VALUE cmd_file_name(VALUE);
- DEFUN("file-name", cmd_file_name, subr_file_name, (VALUE tx), V_Subr1, DOC_file_name) /*
- ::doc:file_name::
- (file-name [BUFFER])
- Return the name of the file being edited in BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = CurrVW->vw_Tx;
- return(VTX(tx)->tx_FileName);
- }
-
- _PR VALUE cmd_set_file_name(VALUE, VALUE);
- DEFUN("set-file-name", cmd_set_file_name, subr_set_file_name, (VALUE tx, VALUE name), V_Subr2, DOC_set_file_name) /*
- ::doc:set_file_name::
- (set-file-name BUFFER NAME)
- Set the name of the file being edited in BUFFER to NAME.
- ::end:: */
- {
- DECLARE1(name, STRINGP);
- if(!BUFFERP(tx))
- tx = CurrVW->vw_Tx;
- makemarksnonres(VTX(tx));
- VTX(tx)->tx_FileName = name;
- makemarksres(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 = CurrVW->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 = CurrVW->vw_Tx;
- VTX(tx)->tx_BufferName = name;
- resetslptxtitles(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 = CurrVW->vw_Tx;
- return(newnumber(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 = CurrVW->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 = CurrVW->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 = CurrVW->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 = CurrVW->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 = CurrVW->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 = CurrVW->vw_Tx;
- if(VTX(tx)->tx_Flags & TXFF_RDONLY)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_file_length(VALUE);
- DEFUN("file-length", cmd_file_length, subr_file_length, (VALUE tx), V_Subr1, DOC_file_length) /*
- ::doc:file_length::
- (file-length [BUFFER])
- Returns the number of lines in BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = CurrVW->vw_Tx;
- return(newnumber(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 = CurrVW->vw_Tx;
- p = VPOS(pos);
- }
- else
- {
- p = CurrVW->vw_CursorPos;
- tx = CurrVW->vw_Tx;
- }
- return(newnumber(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...) <SPECIAL-FORM>
- 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 = swapvwfilesnd(CurrVW, VTX(res));
- if(oldtx)
- {
- GCVAL gcv_oldtx;
- PUSHGC(gcv_oldtx, oldtx);
- res = cmd_progn(VCDR(args));
- POPGC;
- swapvwfilesnd(CurrVW, 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(handlevarint(val, &CurrVW->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(handlevarint(val, &CurrVW->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(handlevarint(val, &CurrVW->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(handlevarint(val, &CurrVW->vw_Tx->tx_LastSaveTime));
- }
-
- _PR VALUE var_screen_tab(VALUE);
- DEFUN("screen-tab", var_screen_tab, subr_screen_tab, (VALUE val), V_Var, DOC_screen_tab) /*
- ::doc:screen_tab::
- Sets the size of tab-stops for the `left-tab' and `right-tab' commands.
- ::end:: */
- {
- return(handlevarint(val, &CurrVW->vw_Tx->tx_TabSize));
- }
-
- _PR VALUE var_disk_tab(VALUE);
- DEFUN("disk-tab", var_disk_tab, subr_disk_tab, (VALUE val), V_Var, DOC_disk_tab) /*
- ::doc:disk_tab::
- Sets the size of the tab-stops used when loading and saving files in this
- buffer.
- ::end:: */
- {
- return(handlevarint(val, &CurrVW->vw_Tx->tx_DiskTab));
- }
-
- _PR VALUE var_save_tabs(VALUE);
- DEFUN("save-tabs", var_save_tabs, subr_save_tabs, (VALUE val), V_Var, DOC_save_tabs) /*
- ::doc:save_tabs::
- Defines whether or not tab characters (ASCII 9) are used when saving files,
- STATUS can be one of,
- nil NO tabs are used, all spaces are left intact.
- leading All *leading* spaces in each line will be optimised into
- tabs.
- all All groups of spaces (except after any quotes) are changed
- to tabs wherever possible.
- ::end:: */
- {
- if(val)
- {
- int st;
- if(SYMBOLP(val))
- {
- switch(VSTR(VSYM(val)->sym_Name)[0])
- {
- case 'n': /* nil */
- st = 0;
- break;
- case 'l': /* leading */
- st = 1;
- break;
- case 'a': /* all */
- st = 2;
- break;
- default:
- return(NULL);
- }
- }
- else if(NUMBERP(val))
- st = VNUM(val);
- else
- return(NULL);
- CurrVW->vw_Tx->tx_SaveTabs = st;
- return(val);
- }
- switch(CurrVW->vw_Tx->tx_SaveTabs)
- {
- case 0:
- return(sym_nil);
- case 1:
- return(sym_leading);
- case 2:
- return(sym_all);
- }
- return(NULL);
- }
-
- _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 = CurrVW->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);
- }
-
- /* chain of all non-resident marks, linked via `mk_Next' */
- Mark *NRMarkChain;
- /* chain of all marks, linked via `mk_NextAlloc' */
- Mark *MarkChain;
-
- /*
- * For all non-resident marks, see if any point to NEWTX, if so link them
- * onto NEWTX's `tx_Marks' chain.
- */
- void
- makemarksres(TX *newtx)
- {
- Mark *nxt, *mk = NRMarkChain;
- NRMarkChain = NULL;
- while(mk)
- {
- nxt = mk->mk_Next;
- if(samefiles(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 = NRMarkChain;
- NRMarkChain = mk;
- }
- mk = nxt;
- }
- }
-
- void
- makemarksnonres(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 = NRMarkChain;
- NRMarkChain = mk;
- mk = nxt;
- }
- }
-
- /*
- * Takes MK off the buffer mark chain that it's on (or the NRMarkChain).
- */
- static void
- unchainmark(Mark *mk)
- {
- Mark **headp, *this;
- if(!mk->mk_Resident)
- headp = &NRMarkChain;
- 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 = MarkChain;
- MarkChain = NULL;
- while(mk)
- {
- Mark *nxt = mk->mk_NextAlloc;
- if(!GC_MARKEDP(mk))
- {
- unchainmark(mk);
- mystrfree(mk);
- }
- else
- {
- GC_CLR(mk);
- mk->mk_NextAlloc = MarkChain;
- MarkChain = 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(samefiles(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];
- streamputs(strm, "#<mark ", FALSE);
- if(VMARK(obj)->mk_Resident)
- {
- if(VMARK(obj)->mk_File.tx->tx_FileName)
- {
- streamputc(strm, '"');
- streamputs(strm, VSTR(VMARK(obj)->mk_File.tx->tx_FileName), TRUE);
- streamputc(strm, '"');
- }
- else
- streamputs(strm, VSTR(VMARK(obj)->mk_File.tx->tx_BufferName), TRUE);
- }
- else
- {
- streamputc(strm, '"');
- streamputs(strm, VSTR(VMARK(obj)->mk_File.name), TRUE);
- streamputc(strm, '"');
- }
- sprintf(tbuf, " #<pos %ld %ld>>",
- VPOS(VMARK(obj)->mk_Pos).pos_Col + 1,
- VPOS(VMARK(obj)->mk_Pos).pos_Line + 1);
- streamputs(strm, tbuf, 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 = mystralloc(sizeof(Mark))) && (mk->mk_Pos = newlpos(NULL)))
- {
- mk->mk_Type = V_Mark;
- mk->mk_NextAlloc = MarkChain;
- MarkChain = mk;
- DataAfterGC += sizeof(Mark);
- if(POSP(pos))
- VPOS(mk->mk_Pos) = VPOS(pos);
- else
- VPOS(mk->mk_Pos) = CurrVW->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 = NRMarkChain;
- NRMarkChain = mk;
- }
- }
- else
- {
- if(!BUFFERP(buffer))
- buffer = CurrVW->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(mk);
- }
- if(mk)
- mystrfree(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, *nxt, **chain;
- if(VMARK(mark)->mk_Resident)
- chain = &(VMARK(mark)->mk_File.tx->tx_MarkChain);
- else
- chain = &NRMarkChain;
- mk = *chain;
- *chain = NULL;
- while(mk)
- {
- nxt = mk->mk_Next;
- if(mk != mark)
- {
- mk->mk_Next = *chain;
- *chain = mk;
- }
- else
- mk->mk_Next = NULL;
- mk = nxt;
- }
- switch(VTYPE(buffer))
- {
- case V_StaticString:
- case V_String:
- if(!(VMARK(mark)->mk_File.tx = cmd_get_file_buffer(buffer)))
- {
- VMARK(mark)->mk_File.name = buffer;
- VMARK(mark)->mk_Resident = FALSE;
- VMARK(mark)->mk_Next = NRMarkChain;
- NRMarkChain = mark;
- break;
- }
- goto dotx;
- case V_TX:
- VMARK(mark)->mk_File.tx = buffer;
- dotx:
- VMARK(mark)->mk_Resident = TRUE;
- VMARK(mark)->mk_Next = VMARK(mark)->mk_File.tx->tx_MarkChain;
- VMARK(mark)->mk_File.tx->tx_MarkChain = 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)
- {
- markstatic((VALUE *)&NRMarkChain);
- INTERN(sym_auto_save_function, "auto-save-function");
- INTERN(sym_no_file_code_p, "no-file-code-p");
- 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_file_name);
- ADD_SUBR(subr_set_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_file_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_screen_tab);
- ADD_SUBR(subr_disk_tab);
- ADD_SUBR(subr_save_tabs);
- ADD_SUBR(subr_mode_name);
- 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 = BufferChain;
- Mark *mk = MarkChain;
- while(tx)
- {
- TX *nxttx = tx->tx_Next;
- killlinelist(tx);
- myfree(tx);
- tx = nxttx;
- }
- while(mk)
- {
- Mark *nxtmk = mk->mk_NextAlloc;
- mystrfree(mk);
- mk = nxtmk;
- }
- }
-