This is bw.c in view mode; [Download] [Up]
/* Edit buffer window generation
Copyright (C) 1992 Joseph H. Allen
This file is part of JOE (Joe's Own Editor)
JOE 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 1, or (at your option) any later version.
JOE 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
JOE; see the file COPYING. If not, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "tty.h"
#include "vfile.h"
#include "termcap.h"
#include "kbd.h"
#include "b.h"
#include "scrn.h"
#include "w.h"
#include "ublock.h"
#include "zstr.h"
#include "blocks.h"
#include "bw.h"
/* Display modes */
int dspasis=0;
int marking=0;
extern int square;
extern int staen;
P *getto(p,cur,top,line)
P *p,*cur,*top;
long line;
{
long dist=MAXLONG;
long d;
P *best;
if(!p)
{
if(d=(line-cur->line>=0?line-cur->line:cur->line-line), d<dist)
dist=d, best=cur;
if(d=(line-top->line>=0?line-top->line:top->line-line), d<dist)
dist=d, best=top;
p=pdup(best);
pbol(p);
}
while(line>p->line) if(!pnextl(p)) break;
if(line<p->line)
{
while(line<p->line) pprevl(p);
pbol(p);
}
return p;
}
/* Scroll window to follow cursor */
int mid=0;
void bwfllw(w)
BW *w;
{
P *newtop;
if(w->cursor->line<w->top->line)
{
newtop=pdup(w->cursor);
pbol(newtop);
if(mid)
if(newtop->line>=w->h/2) pline(newtop,newtop->line-w->h/2);
else pset(newtop,newtop->b->bof);
if(w->top->line-newtop->line<w->h)
nscrldn(w->t->t,w->y,w->y+w->h,(int)(w->top->line-newtop->line));
else msetI(w->t->t->updtab+w->y,1,w->h);
pset(w->top,newtop);
prm(newtop);
}
else if(w->cursor->line>=w->top->line+w->h)
{
newtop=pdup(w->top);
if(mid) newtop=getto(NULL,w->cursor,w->top,w->cursor->line-w->h/2);
else newtop=getto(NULL,w->cursor,w->top,w->cursor->line-(w->h-1));
if(newtop->line-w->top->line<w->h)
nscrlup(w->t->t,
w->y,
w->y+w->h,
(int)(newtop->line-w->top->line));
else msetI(w->t->t->updtab+w->y,1,w->h);
pset(w->top,newtop);
prm(newtop);
}
/* Adjust column */
if(w->cursor->xcol<w->offset)
{
w->offset=w->cursor->xcol;
msetI(w->t->t->updtab+w->y,1,w->h);
}
else if(w->cursor->xcol>=w->offset+w->w)
{
w->offset=w->cursor->xcol-(w->w-1);
msetI(w->t->t->updtab+w->y,1,w->h);
}
}
/* Scroll a buffer window after an insert occured. 'flg' is set to 1 if
* the first line was split
*/
void bwins(w,l,n,flg)
BW *w;
long l,n;
int flg;
{
if(l+flg+n<w->top->line+w->h && l+flg>=w->top->line && l+flg<=w->b->eof->line)
{
if(flg) w->t->t->sary[w->y+l-w->top->line]=w->t->t->li;
nscrldn(w->t->t,(int)(w->y+l+flg-w->top->line),w->y+w->h,(int)n);
}
if(l<w->top->line+w->h && l>=w->top->line)
if(n>=w->h-(l-w->top->line))
msetI(w->t->t->updtab+w->y+l-w->top->line,1,w->h-(int)(l-w->top->line));
else
msetI(w->t->t->updtab+w->y+l-w->top->line,1,(int)n+1);
}
/* Scroll current windows after a delete */
void bwdel(w,l,n,flg)
BW *w;
long l,n;
int flg;
{
/* Update the line where the delete began */
if(l<w->top->line+w->h && l>=w->top->line)
w->t->t->updtab[w->y+l-w->top->line]=1;
/* Update the line where the delete ended */
if(l+n<w->top->line+w->h && l+n>=w->top->line)
w->t->t->updtab[w->y+l+n-w->top->line]=1;
if(l<w->top->line+w->h &&
(l+n>=w->top->line+w->h ||
l+n==w->b->eof->line && w->b->eof->line>=w->top->line+w->h))
if(l>=w->top->line)
/* Update window from l to end */
msetI(w->t->t->updtab+w->y+l-w->top->line,1,w->h-(int)(l-w->top->line));
else
/* Update entire window */
msetI(w->t->t->updtab+w->y,1,w->h);
else if(l<w->top->line+w->h && l+n==w->b->eof->line &&
w->b->eof->line<w->top->line+w->h)
if(l>=w->top->line)
/* Update window from l to end of file */
msetI(w->t->t->updtab+w->y+l-w->top->line,1,(int)n);
else
/* Update from beginning of window to end of file */
msetI(w->t->t->updtab+w->y,1,(int)(w->b->eof->line-w->top->line));
else if(l+n<w->top->line+w->h &&
l+n>w->top->line &&
l+n<w->b->eof->line)
if(l+flg>=w->top->line)
nscrlup(w->t->t,(int)(w->y+l+flg-w->top->line),w->y+w->h,(int)n);
else
nscrlup(w->t->t,w->y,w->y+w->h,(int)(l+n-w->top->line));
}
/* Update a single line */
static int lgen(t,y,screen,x,w,p,scr,from,to)
SCRN *t;
int y;
int *screen; /* Screen line address */
int w; /* Window */
P *p; /* Buffer pointer */
long scr; /* Starting column to display */
long from,to; /* Range for marked block */
{
int ox=x;
int done=1;
long col=0;
long byte=p->byte;
char *bp; /* Buffer pointer, 0 if not set */
int amnt; /* Amount left in this segment of the buffer */
int c, ta, c1;
unsigned char bc;
/* Initialize bp and amnt from p */
if(p->ofst>=p->hdr->hole)
{
bp=p->ptr+p->hdr->ehole+p->ofst-p->hdr->hole;
amnt=SEGSIZ-p->hdr->ehole-(p->ofst-p->hdr->hole);
}
else
{
bp=p->ptr+p->ofst;
amnt=p->hdr->hole-p->ofst;
}
if(col==scr) goto loop;
lp: /* Display next character */
if(amnt) do
{
bc= *bp++;
#ifdef __MSDOS__
if(bc=='\r')
{
++byte;
if(!--amnt)
{
pppl:
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
}
else goto nnnl;
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
if(!amnt) goto pppl;
}
}
if(*bp=='\n')
{
++bp;
++byte;
++amnt;
goto eobl;
}
nnnl: --byte; ++amnt;
}
#endif
if(square)
if(bc=='\t')
{
long tcol=col+p->b->o.tab-col%p->b->o.tab;
if(tcol>from && tcol<=to) c1=INVERSE;
else c1=0;
}
else
if(col>=from && col<to) c1=INVERSE;
else c1=0;
else
if(byte>=from && byte<to) c1=INVERSE;
else c1=0;
++byte;
if(bc=='\t')
{
ta=p->b->o.tab-col%p->b->o.tab;
if(ta+col>scr)
{
ta-=scr-col;
goto dota;
}
if((col+=ta)==scr) { --amnt; goto loop; }
}
else if(bc=='\n') goto eobl;
else if(++col==scr) { --amnt; goto loop; }
}
while(--amnt);
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
goto lp;
}
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
goto lp;
}
goto eof;
loop: /* Display next character */
if(amnt) do
{
bc= *bp++;
#ifdef __MSDOS__
if(bc=='\r')
{
++byte;
if(!--amnt)
{
ppl:
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
}
else goto nnl;
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
if(!amnt) goto ppl;
}
}
if(*bp=='\n')
{
++bp;
++byte;
++amnt;
goto eobl;
}
nnl: --byte; ++amnt;
}
#endif
if(square)
if(bc=='\t')
{
long tcol=scr+x-ox+p->b->o.tab-(scr+x-ox)%p->b->o.tab;
if(tcol>from && tcol<=to) c1=INVERSE;
else c1=0;
}
else
if(scr+x-ox>=from && scr+x-ox<to) c1=INVERSE;
else c1=0;
else
if(byte>=from && byte<to) c1=INVERSE;
else c1=0;
++byte;
if(bc=='\t')
{
ta=p->b->o.tab-((x-ox+scr)%p->b->o.tab);
dota:
do
{
outatr(t,screen+x,x,y,' ',c1);
if(ifhave) goto bye;
if(++x==w) goto eosl;
}
while(--ta);
}
else if(bc=='\n') goto eobl;
else
{
xlat(c,bc);
c^=c1;
outatr(t,screen+x,x,y,bc,c);
if(ifhave) goto bye;
if(++x==w) goto eosl;
}
}
while(--amnt);
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
goto loop;
}
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
goto loop;
}
goto eof;
eobl: /* End of buffer line found. Erase to end of screen line */
++p->line;
eof:
if(x!=w) done=eraeol(t,x,y);
else done=0;
/* Set p to bp/amnt */
bye:
if(bp-p->ptr<=p->hdr->hole) p->ofst=bp-p->ptr;
else p->ofst=bp-p->ptr-(p->hdr->ehole-p->hdr->hole);
p->byte=byte;
return done;
eosl:
if(bp-p->ptr<=p->hdr->hole) p->ofst=bp-p->ptr;
else p->ofst=bp-p->ptr-(p->hdr->ehole-p->hdr->hole);
p->byte=byte;
pnextl(p);
return 0;
}
/* Generate line into an array */
static int lgena(t,y,screen,x,w,p,scr,from,to)
SCRN *t;
int y;
int *screen; /* Screen line address */
int w; /* Window */
P *p; /* Buffer pointer */
long scr; /* Starting column to display */
long from,to; /* Range for marked block */
{
int ox=x;
int done=1;
long col=0;
long byte=p->byte;
char *bp; /* Buffer pointer, 0 if not set */
int amnt; /* Amount left in this segment of the buffer */
int c, ta, c1;
unsigned char bc;
/* Initialize bp and amnt from p */
if(p->ofst>=p->hdr->hole)
{
bp=p->ptr+p->hdr->ehole+p->ofst-p->hdr->hole;
amnt=SEGSIZ-p->hdr->ehole-(p->ofst-p->hdr->hole);
}
else
{
bp=p->ptr+p->ofst;
amnt=p->hdr->hole-p->ofst;
}
if(col==scr) goto loop;
lp: /* Display next character */
if(amnt) do
{
bc= *bp++;
if(square)
if(bc=='\t')
{
long tcol=col+p->b->o.tab-col%p->b->o.tab;
if(tcol>from && tcol<=to) c1=INVERSE;
else c1=0;
}
else
if(col>=from && col<to) c1=INVERSE;
else c1=0;
else
if(byte>=from && byte<to) c1=INVERSE;
else c1=0;
++byte;
if(bc=='\t')
{
ta=p->b->o.tab-col%p->b->o.tab;
if(ta+col>scr)
{
ta-=scr-col;
goto dota;
}
if((col+=ta)==scr) { --amnt; goto loop; }
}
else if(bc=='\n') goto eobl;
else if(++col==scr) { --amnt; goto loop; }
}
while(--amnt);
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
goto lp;
}
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
goto lp;
}
goto eobl;
loop: /* Display next character */
if(amnt) do
{
bc= *bp++;
if(square)
if(bc=='\t')
{
long tcol=scr+x-ox+p->b->o.tab-(scr+x-ox)%p->b->o.tab;
if(tcol>from && tcol<=to) c1=INVERSE;
else c1=0;
}
else
if(scr+x-ox>=from && scr+x-ox<to) c1=INVERSE;
else c1=0;
else
if(byte>=from && byte<to) c1=INVERSE;
else c1=0;
++byte;
if(bc=='\t')
{
ta=p->b->o.tab-((x-ox+scr)%p->b->o.tab);
dota:
do
{
screen[x]=' '+c1;
if(++x==w) goto eosl;
}
while(--ta);
}
else if(bc=='\n') goto eobl;
else
{
xlat(c,bc);
c^=c1;
screen[x]=c+bc;
if(++x==w) goto eosl;
}
}
while(--amnt);
if(bp==p->ptr+SEGSIZ)
{
if(pnext(p))
{
bp=p->ptr;
amnt=p->hdr->hole;
goto loop;
}
}
else
{
bp=p->ptr+p->hdr->ehole;
amnt=SEGSIZ-p->hdr->ehole;
goto loop;
}
goto eof;
eobl: /* End of buffer line found. Erase to end of screen line */
++p->line;
eof:
while(x!=w) screen[x++]=' ';
done=0;
/* Set p to bp/amnt */
bye:
if(bp-p->ptr<=p->hdr->hole) p->ofst=bp-p->ptr;
else p->ofst=bp-p->ptr-(p->hdr->ehole-p->hdr->hole);
p->byte=byte;
return done;
eosl:
if(bp-p->ptr<=p->hdr->hole) p->ofst=bp-p->ptr;
else p->ofst=bp-p->ptr-(p->hdr->ehole-p->hdr->hole);
p->byte=byte;
pnextl(p);
return 0;
}
void gennum(w,screen,t,y,comp)
BW *w;
int *screen;
SCRN *t;
int *comp;
{
char buf[12];
int z;
int lin=w->top->line+y-w->y;
if(lin<=w->b->eof->line) sprintf(buf,"%5ld ",w->top->line+y-w->y+1);
else zcpy(buf," ");
for(z=0;buf[z];++z)
{
outatr(t,screen+z,z,y,buf[z],0);
if(ifhave) return;
comp[z]=buf[z];
}
}
void bwgen(w,linums)
BW *w;
{
int *screen;
P *p=0;
P *q=pdup(w->cursor);
int bot=w->h+w->y;
int y;
int dosquare=0;
long from,to;
long fromline,toline;
SCRN *t=w->t->t;
fromline=toline=from=to=0;
if(markv(0) && markk->b==w->b)
if(square)
{
from=markb->xcol, to=markk->xcol, dosquare=1;
fromline=markb->line;
toline=markk->line;
}
else from=markb->byte, to=markk->byte;
else if(marking && markb && markb->b==w->b &&
w->cursor->byte!= markb->byte && !from)
if(square)
{
from=Lmin(w->cursor->xcol,markb->xcol),
to=Lmax(w->cursor->xcol,markb->xcol);
fromline=Lmin(w->cursor->line,markb->line);
toline=Lmax(w->cursor->line,markb->line);
dosquare=1;
}
else from=Lmin(w->cursor->byte,markb->byte),
to=Lmax(w->cursor->byte,markb->byte);
if(marking) msetI(t->updtab+w->y,1,w->h);
y=w->cursor->line-w->top->line+w->y;
for(screen=t->scrn+y*w->t->w;y!=bot; ++y, screen+=w->t->w)
{
if(ifhave && !linums) break;
if(linums) gennum(w,screen,t,y,t->compose);
if(t->updtab[y])
{
p=getto(p,w->cursor,w->top,w->top->line+y-w->y);
if(t->insdel && !w->x)
{
pset(q,p);
if(dosquare)
if(w->top->line+y-w->y>=fromline &&
w->top->line+y-w->y<=toline)
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,from,to);
else
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,0L,0L);
else
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,from,to);
magic(t,y,screen,t->compose,
(int)(w->cursor->xcol-w->offset+w->x));
}
if(dosquare)
if(w->top->line+y-w->y>=fromline &&
w->top->line+y-w->y<=toline)
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
from,to);
else
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
0L,0L);
else
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
from,to);
}
}
y=w->y;
for(screen=t->scrn+w->y*w->t->w; y!=w->y+w->cursor->line-w->top->line;
++y, screen+=w->t->w)
{
if(ifhave && !linums) break;
if(linums) gennum(w,screen,t,y,t->compose);
if(t->updtab[y])
{
p=getto(p,w->cursor,w->top,w->top->line+y-w->y);
if(t->insdel && !w->x)
{
pset(q,p);
if(dosquare)
if(w->top->line+y-w->y>=fromline &&
w->top->line+y-w->y<=toline)
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,from,to);
else
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,0L,0L);
else
lgena(t,y,t->compose,w->x,w->x+w->w,q,w->offset,from,to);
magic(t,y,screen,t->compose,
(int)(w->cursor->xcol-w->offset+w->x));
}
if(dosquare)
if(w->top->line+y-w->y>=fromline &&
w->top->line+y-w->y<=toline)
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
from,to);
else
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
0L,0L);
else
t->updtab[y]=lgen(t,y,screen,w->x,w->x+w->w,p,w->offset,
from,to);
}
}
prm(q);
if(p) prm(p);
}
void bwmove(w,x,y)
BW *w;
int x,y;
{
w->x=x;
w->y=y;
}
void bwresz(w,wi,he)
BW *w;
int wi, he;
{
if(he>w->h && w->y!= -1) msetI(w->t->t->updtab+w->y+w->h,1,he-w->h);
w->w=wi;
w->h=he;
}
BW *bwmk(window,b,prompt)
W *window;
B *b;
int prompt;
{
BW *w=(BW *)malloc(sizeof(BW));
w->parent=window;
w->pid=0;
w->out= -1;
w->b=b;
if(prompt || !window->y && staen)
w->y=window->y, w->h=window->h;
else
w->y=window->y+1, w->h=window->h-1;
if(b->oldcur)
{
w->top=b->oldtop, b->oldtop=0, w->top->owner=0;
w->cursor=b->oldcur, b->oldcur=0, w->cursor->owner=0;
}
else
{
w->top=pdup(b->bof);
w->cursor=pdup(b->bof);
}
w->t=window->t;
w->object=NULL;
w->offset=0;
w->o=w->b->o;
if(w->o.linums) w->x=window->x+LINCOLS, w->w=window->w-LINCOLS;
else w->x=window->x, w->w=window->w;
if(window==window->main)
{
rmkbd(window->kbd);
window->kbd=mkkbd(getcontext(w->o.context));
}
w->top->xcol=0; w->cursor->xcol=0;
return w;
}
void bwrm(w)
BW *w;
{
prm(w->top);
prm(w->cursor);
brm(w->b);
free(w);
}
int ustat(bw)
BW *bw;
{
static char buf[80];
unsigned c=brc(bw->cursor);
if(c==MAXINT)
sprintf(buf,"** Line %ld Col %ld Offset %ld/0x%lX **",
bw->cursor->line+1,piscol(bw->cursor)+1,bw->cursor->byte,
bw->cursor->byte);
else
sprintf(buf,"** Line %ld Col %ld Offset %ld/0x%lX Char %d/0%o/0x%X **",
bw->cursor->line+1,piscol(bw->cursor)+1,bw->cursor->byte,
bw->cursor->byte,c,c,c);
msgnw(bw,buf);
return 0;
}
int ucrawlr(bw)
BW *bw;
{
int amnt=bw->w/2;
pcol(bw->cursor,bw->cursor->xcol+amnt);
bw->cursor->xcol+=amnt;
bw->offset+=amnt;
updall();
return 0;
}
int ucrawll(bw)
BW *bw;
{
int amnt=bw->w/2;
int curamnt=bw->w/2;
if(amnt>bw->offset) amnt=bw->offset, curamnt=bw->offset;
if(!bw->offset) curamnt=bw->cursor->xcol;
if(!curamnt) return -1;
pcol(bw->cursor,bw->cursor->xcol-curamnt);
bw->cursor->xcol-=curamnt;
bw->offset-=amnt;
updall();
return 0;
}
void orphit(bw)
BW *bw;
{
++bw->b->count;
bw->b->orphan=1;
pdupown(bw->cursor,&bw->b->oldcur);
pdupown(bw->top,&bw->b->oldtop);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.