home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
src
/
buffers.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-03
|
30KB
|
1,147 lines
/* 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 c