This is scrn.c in view mode; [Download] [Up]
/* Device independant TTY interface for JOE 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 <stdio.h> #include <signal.h> #include "blocks.h" #include "vs.h" #include "termcap.h" #include "tty.h" #include "zstr.h" #include "scrn.h" int skiptop=0; int lines=0; int columns=0; extern int mid; /* How to display characters */ unsigned xlata[256]= { UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE+UNDERLINE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE, INVERSE+UNDERLINE, }; unsigned char xlatc[256]= { 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,63 }; /* Set attributes */ int attr(t,c) SCRN *t; int c; { int e; c&=~255; e=(t->attrib&~c); if(e) /* If any attribute go off, switch them all off: fixes bug on PCs */ { if(t->me) texec(t->cap,t->me,1); else { if(t->ue) texec(t->cap,t->ue,1); if(t->se) texec(t->cap,t->se,1); } t->attrib=0; } e=(c&~t->attrib); if(e&INVERSE) if(t->mr) texec(t->cap,t->mr,1); else if(t->so) texec(t->cap,t->so,1); if(e&UNDERLINE) if(t->us) texec(t->cap,t->us,1); if(e&BLINK) if(t->mb) texec(t->cap,t->mb,1); if(e&BOLD) if(t->md) texec(t->cap,t->md,1); if(e&DIM) if(t->mh) texec(t->cap,t->mh,1); t->attrib=c; return 0; } /* Set scrolling region */ void setregn(t,top,bot) SCRN *t; int top,bot; { if(!t->cs) { t->top=top; t->bot=bot; return; } if(t->top!=top || t->bot!=bot) { t->top=top; t->bot=bot; texec(t->cap,t->cs,1,top,bot-1); t->x= -1; t->y= -1; } } /* Enter insert mode */ void setins(t,x) SCRN *t; { if(t->ins!=1 && t->im) { t->ins=1; texec(t->cap,t->im,1,x); } } /* Exit insert mode */ int clrins(t) SCRN *t; { if(t->ins!=0) { texec(t->cap,t->ei,1); t->ins=0; } return 0; } /* Erase from given screen coordinate to end of line */ int eraeol(t,x,y) SCRN *t; { int *s, *ss; int w=t->co-x-1; /* Don't worry about last column */ if(w<=0) return 0; s=t->scrn+y*t->co+x; ss=s+w; do if(*--ss!=' ') { ++ss; break; } while(ss!=s); if((ss-s>3 || s[w]!=' ') && t->ce) { cpos(t,x,y); attr(t,0); texec(t->cap,t->ce,1); msetI(s,' ',w); } else if(s!=ss) { if(t->ins) clrins(t); if(t->x!=x || t->y!=y) cpos(t,x,y); if(t->attrib) attr(t,0); while(s!=ss) { *s=' '; ttputc(' '); ++t->x; ++s; } } return 0; } /* As above but useable in insert mode */ /* The cursor position must already be correct */ void outatri(t,x,y,c) SCRN *t; { unsigned char ch; if(c== -1) c=' '; ch=c; c-=ch; if(c!=t->attrib) attr(t,c); if(t->haz && ch=='~') ch='\\'; ttputc(ch); ++t->x; } void out(t,c) char *t; char c; { ttputc(c); } SCRN *nopen(cap) CAP *cap; { SCRN *t=(SCRN *)malloc(sizeof(SCRN)); int x,y; ttopen(); t->cap=cap; setcap(cap,baud,out,NULL); t->li=getnum(t->cap,"li"); if(t->li<1) t->li=24; t->co=getnum(t->cap,"co"); if(t->co<2) t->co=80; x=y=0; ttgtsz(&x,&y); if(x>7 && y>3) t->li=y, t->co=x; t->haz=getflag(t->cap,"hz"); t->os=getflag(t->cap,"os"); t->eo=getflag(t->cap,"eo"); if(getflag(t->cap,"hc")) t->os=1; if(t->os || getflag(t->cap,"ul")) t->ul=1; else t->ul=0; t->xn=getflag(t->cap,"xn"); t->am=getflag(t->cap,"am"); t->ti=jgetstr(t->cap,"ti"); t->cl=jgetstr(t->cap,"cl"); t->cd=jgetstr(t->cap,"cd"); t->te=jgetstr(t->cap,"te"); t->mb=0; t->md=0; t->mh=0; t->mr=0; t->avattr=0; if(!(t->me=jgetstr(t->cap,"me"))) goto oops; if((t->mb=jgetstr(t->cap,"mb"))) t->avattr|=BLINK; if((t->md=jgetstr(t->cap,"md"))) t->avattr|=BOLD; if((t->mh=jgetstr(t->cap,"mh"))) t->avattr|=DIM; if((t->mr=jgetstr(t->cap,"mr"))) t->avattr|=INVERSE; oops: t->so=0; t->se=0; if(getnum(t->cap,"sg")<=0 && !t->mr && jgetstr(t->cap,"se")) { if(t->so=jgetstr(t->cap,"so")) t->avattr|=INVERSE; t->se=jgetstr(t->cap,"se"); } if(getflag(t->cap,"xs") || getflag(t->cap,"xt")) t->so=0; t->us=0; t->ue=0; if(getnum(t->cap,"ug")<=0 && jgetstr(t->cap,"ue")) { if(t->us=jgetstr(t->cap,"us")) t->avattr|=UNDERLINE; t->ue=jgetstr(t->cap,"ue"); } if(!(t->uc=jgetstr(t->cap,"uc"))) if(t->ul) t->uc="_"; if(t->uc) t->avattr|=UNDERLINE; t->ms=getflag(t->cap,"ms"); t->da=getflag(t->cap,"da"); t->db=getflag(t->cap,"db"); t->cs=jgetstr(t->cap,"cs"); t->rr=getflag(t->cap,"rr"); t->sf=jgetstr(t->cap,"sf"); t->sr=jgetstr(t->cap,"sr"); t->SF=jgetstr(t->cap,"SF"); t->SR=jgetstr(t->cap,"SR"); t->al=jgetstr(t->cap,"al"); t->dl=jgetstr(t->cap,"dl"); t->AL=jgetstr(t->cap,"AL"); t->DL=jgetstr(t->cap,"DL"); if(!getflag(t->cap,"ns") && !t->sf) t->sf="\12"; if(!getflag(t->cap,"in") && baud<38400 ) { t->dc=jgetstr(t->cap,"dc"); t->DC=jgetstr(t->cap,"DC"); t->dm=jgetstr(t->cap,"dm"); t->ed=jgetstr(t->cap,"ed"); t->im=jgetstr(t->cap,"im"); t->ei=jgetstr(t->cap,"ei"); t->ic=jgetstr(t->cap,"ic"); t->IC=jgetstr(t->cap,"IC"); t->ip=jgetstr(t->cap,"ip"); t->mi=getflag(t->cap,"mi"); } else { t->dm=0; t->dc=0; t->DC=0; t->ed=0; t->im=0; t->ic=0; t->IC=0; t->ip=0; t->ei=0; t->mi=1; } t->bs=0; if(jgetstr(t->cap,"bc")) t->bs=jgetstr(t->cap,"bc"); else if(jgetstr(t->cap,"le")) t->bs=jgetstr(t->cap,"le"); if(getflag(t->cap,"bs")) t->bs="\10"; t->cbs=tcost(t->cap,t->bs,1,2,2); t->lf="\12"; if(jgetstr(t->cap,"do")) t->lf=jgetstr(t->cap,"do"); t->clf=tcost(t->cap,t->lf,1,2,2); t->up=jgetstr(t->cap,"up"); t->cup=tcost(t->cap,t->up,1,2,2); t->nd=jgetstr(t->cap,"nd"); t->tw=8; if(getnum(t->cap,"it")>0) t->tw=getnum(t->cap,"it"); else if(getnum(t->cap,"tw")>0) t->tw=getnum(t->cap,"tw"); if(!(t->ta=jgetstr(t->cap,"ta"))) if(getflag(t->cap,"pt")) t->ta="\11"; t->bt=jgetstr(t->cap,"bt"); if(getflag(t->cap,"xt")) t->ta=0, t->bt=0; t->cta=tcost(t->cap,t->ta,1,2,2); t->cbt=tcost(t->cap,t->bt,1,2,2); t->ho=jgetstr(t->cap,"ho"); t->cho=tcost(t->cap,t->ho,1,2,2); t->ll=jgetstr(t->cap,"ll"); t->cll=tcost(t->cap,t->ll,1,2,2); t->cr="\15"; if(jgetstr(t->cap,"cr")) t->cr=jgetstr(t->cap,"cr"); if(getflag(t->cap,"nc") || getflag(t->cap,"xr")) t->cr=0; t->ccr=tcost(t->cap,t->cr,1,2,2); t->cRI=tcost(t->cap,t->RI=jgetstr(t->cap,"RI"),1,2,2); t->cLE=tcost(t->cap,t->LE=jgetstr(t->cap,"LE"),1,2,2); t->cUP=tcost(t->cap,t->UP=jgetstr(t->cap,"UP"),1,2,2); t->cDO=tcost(t->cap,t->DO=jgetstr(t->cap,"DO"),1,2,2); t->cch=tcost(t->cap,t->ch=jgetstr(t->cap,"ch"),1,2,2); t->ccv=tcost(t->cap,t->cv=jgetstr(t->cap,"cv"),1,2,2); t->ccV=tcost(t->cap,t->cV=jgetstr(t->cap,"cV"),1,2,2); t->ccm=tcost(t->cap,t->cm=jgetstr(t->cap,"cm"),1,2,2); t->cce=tcost(t->cap,t->ce=jgetstr(t->cap,"ce"),1,2,2); /* Make sure terminal can do absolute positioning */ if(t->cm) goto ok; if(t->ch && t->cv) goto ok; if(t->ho && (t->lf || t->DO || t->cv)) goto ok; if(t->ll && (t->up || t->UP || t->cv)) goto ok; if(t->cr && t->cv) goto ok; leave=1; ttclose(); signrm(); fprintf(stderr,"Sorry, your terminal can't do absolute cursor positioning.\nIt's broken\n"); return 0; ok: /* Determine if we can scroll */ if((t->sr || t->SR) && (t->sf || t->SF) && t->cs || (t->al || t->AL) && (t->dl || t->DL)) t->scroll=1; else { t->scroll=0; if(baud<38400) mid=1; } /* Determine if we can ins/del within lines */ if((t->im || t->ic || t->IC) && (t->dc || t->DC)) t->insdel=1; else t->insdel=0; /* Adjust for high baud rates */ if(baud>=38400) t->scroll=0, t->insdel=0; /* Initialize variable screen size dependant vars */ t->scrn=0; t->sary=0; t->updtab=0; t->compose=0; t->ofst=0; t->ary=0; t->htab=(struct hentry *)malloc(256*sizeof(struct hentry)); nresize(t,t->co,t->li); /* Send out terminal initialization string */ if(t->ti) texec(t->cap,t->ti,1); return t; } /* Change size of screen */ void nresize(t,w,h) SCRN *t; { if(h<4) h=4; if(w<8) w=8; t->li=h; t->co=w; if(t->sary) free(t->sary); if(t->updtab) free(t->updtab); if(t->scrn) free(t->scrn); if(t->compose) free(t->compose); if(t->ofst) free(t->ofst); if(t->ary) free(t->ary); t->scrn=(int *)malloc(t->li*t->co*sizeof(int)); t->sary=(int *)calloc(t->li,sizeof(int)); t->updtab=(int *)malloc(t->li*sizeof(int)); t->compose=(int *)malloc(t->co*sizeof(int)); t->ofst=(int *)malloc(t->co*sizeof(int)); t->ary=(struct hentry *)malloc(t->co*sizeof(struct hentry)); nredraw(t); } /* Calculate cost of positioning the cursor using only relative cursor * positioning functions: t->(lf, DO, up, UP, bs, LE, RI, ta, bt) and rewriting * characters (to move right) * * This doesn't use the am and bw capabilities although it probably could. */ static int relcost(t,x,y,ox,oy) register SCRN *t; register int x,y,ox,oy; { int cost=0; /* If we don't know the cursor position, force use of absolute positioning */ if(oy== -1 || ox== -1) return 10000; /* First adjust row */ if(y>oy) { int dist=y-oy; /* Have to go down */ if(t->lf) { int mult=dist*t->clf; if(dist<10 && t->cDO<mult) cost+=t->cDO; else if(dist>=10 && t->cDO+1<mult) cost+=t->cDO+1; else cost+=mult; } else if(t->DO) if(dist<10) cost+=t->cDO; else cost+=t->cDO+1; else return 10000; } else if(y<oy) { int dist=oy-y; /* Have to go up */ if(t->up) { int mult=dist*t->cup; if(dist<10 && t->cUP<mult) cost+=t->cUP; else if(dist>=10 && t->cUP<mult) cost+=t->cUP+1; else cost+=mult; } else if(t->UP) if(dist<10) cost+=t->cUP; else cost+=t->cUP+1; else return 10000; } /* Now adjust column */ /* Use tabs */ if(x>ox && t->ta) { int dist=x-ox; int ntabs=(dist+ox%t->tw)/t->tw; int cstunder=x%t->tw+t->cta*ntabs, cstover; if(x+t->tw<t->co && t->bs) cstover=t->cbs*(t->tw-x%t->tw)+t->cta*(ntabs+1); else cstover=10000; if(dist<10 && cstunder<t->cRI && cstunder<x-ox && cstover>cstunder) return cost+cstunder; else if(cstunder<t->cRI+1 && cstunder<x-ox && cstover>cstunder) return cost+cstunder; else if(dist<10 && cstover<t->cRI && cstover<x-ox) return cost+cstover; else if(cstover<t->cRI+1 && cstover<x-ox) return cost+cstover; } else if(x<ox && t->bt) { int dist=ox-x; int ntabs=(dist+t->tw-ox%t->tw)/t->tw; int cstunder,cstover; if(t->bs) cstunder=t->cbt*ntabs+t->cbs*(t->tw-x%t->tw); else cstunder=10000; if(x-t->tw>=0) cstover=t->cbt*(ntabs+1)+x%t->tw; else cstover=10000; if(dist<10 && cstunder<t->cLE && (t->bs?cstunder<(ox-x)*t->cbs:1) && cstover>cstunder) return cost+cstunder; if(cstunder<t->cLE+1 && (t->bs?cstunder<(ox-x)*t->cbs:1) && cstover>cstunder) return cost+cstunder; else if(dist<10 && cstover<t->cRI && (t->bs?cstover<(ox-x)*t->cbs:1)) return cost+cstover; else if(cstover<t->cRI+1 && (t->bs?cstover<(ox-x)*t->cbs:1)) return cost+cstover; } /* Use simple motions */ if(x<ox) { int dist=ox-x; /* Have to go left */ if(t->bs) { int mult=dist*t->cbs; if(t->cLE<mult && dist<10) cost+=t->cLE; else if(t->cLE+1<mult) cost+=t->cLE+1; else cost+=mult; } else if(t->LE) cost+=t->cLE; else return 10000; } else if(x>ox) { int dist=x-ox; /* Have to go right */ /* Hmm.. this should take into account possible attribute changes */ if(t->cRI<dist && dist<10) cost+=t->cRI; else if(t->cRI+1<dist) cost+=t->cRI+1; else cost+=dist; } return cost; } /* Find optimal set of cursor positioning commands to move from the current * cursor row and column (either or both of which might be unknown) to the * given new row and column and execute them. */ static void cposs(t,x,y) register SCRN *t; register int x,y; { register int bestcost,cost; int bestway; int hy; int hl; /* Home y position is usually 0, but it is 'top' if we have scrolling region * relative addressing */ if(t->rr) hy=t->top, hl=t->bot-1; else hy=0, hl=t->li-1; /* Assume best way is with only using relative cursor positioning */ bestcost=relcost(t,x,y,t->x,t->y); bestway=0; /* Now check if combinations of absolute cursor positioning functions are * better (or necessary in case one or both cursor positions are unknown) */ if(t->ccm<bestcost) { cost=tcost(t->cap,t->cm,1,y,x); if(cost<bestcost) bestcost=cost, bestway=6; } if(t->ccr<bestcost) { cost=relcost(t,x,y,0,t->y)+t->ccr; if(cost<bestcost) bestcost=cost, bestway=1; } if(t->cho<bestcost) { cost=relcost(t,x,y,0,hy)+t->cho; if(cost<bestcost) bestcost=cost, bestway=2; } if(t->cll<bestcost) { cost=relcost(t,x,y,0,hl)+t->cll; if(cost<bestcost) bestcost=cost, bestway=3; } if(t->cch<bestcost && x!=t->x) { cost=relcost(t,x,y,x,t->y)+tcost(t->cap,t->ch,1,x); if(cost<bestcost) bestcost=cost, bestway=4; } if(t->ccv<bestcost && y!=t->y) { cost=relcost(t,x,y,t->x,y)+tcost(t->cap,t->cv,1,y); if(cost<bestcost) bestcost=cost, bestway=5; } if(t->ccV<bestcost) { cost=relcost(t,x,y,0,y)+tcost(t->cap,t->cV,1,y); if(cost<bestcost) bestcost=cost, bestway=13; } if(t->cch+t->ccv<bestcost && x!=t->x && y!=t->y) { cost=tcost(t->cap,t->cv,1,y-hy)+tcost(t->cap,t->ch,1,x); if(cost<bestcost) bestcost=cost, bestway=7; } if(t->ccv+t->ccr<bestcost && y!=t->y) { cost=tcost(t->cap,t->cv,1,y)+tcost(t->cap,t->cr,1)+ relcost(t,x,y,0,y); if(cost<bestcost) bestcost=cost, bestway=8; } if(t->cll+t->cch<bestcost) { cost=tcost(t->cap,t->ll,1)+tcost(t->cap,t->ch,1,x)+ relcost(t,x,y,x,hl); if(cost<bestcost) bestcost=cost, bestway=9; } if(t->cll+t->ccv<bestcost) { cost=tcost(t->cap,t->ll,1)+tcost(t->cap,t->cv,1,y)+ relcost(t,x,y,0,y); if(cost<bestcost) bestcost=cost, bestway=10; } if(t->cho+t->cch<bestcost) { cost=tcost(t->cap,t->ho,1)+tcost(t->cap,t->ch,1,x)+ relcost(t,x,y,x,hy); if(cost<bestcost) bestcost=cost, bestway=11; } if(t->cho+t->ccv<bestcost) { cost=tcost(t->cap,t->ho,1)+tcost(t->cap,t->cv,1,y)+ relcost(t,x,y,0,y); if(cost<bestcost) bestcost=cost, bestway=12; } /* Do absolute cursor positioning if we don't know the cursor position or * if it is faster than doing only relative cursor positioning */ switch(bestway) { case 1: texec(t->cap,t->cr,1); t->x=0; break; case 2: texec(t->cap,t->ho,1); t->x=0; t->y=hy; break; case 3: texec(t->cap,t->ll,1); t->x=0; t->y=hl; break; case 9: texec(t->cap,t->ll,1); t->x=0; t->y=hl; goto doch; case 11: texec(t->cap,t->ho,1); t->x=0; t->y=hy; doch: case 4: texec(t->cap,t->ch,1,x); t->x=x; break; case 10: texec(t->cap,t->ll,1); t->x=0; t->y=hl; goto docv; case 12: texec(t->cap,t->ho,1); t->x=0; t->y=hy; goto docv; case 8: texec(t->cap,t->cr,1); t->x=0; docv: case 5: texec(t->cap,t->cv,1,y); t->y=y; break; case 6: texec(t->cap,t->cm,1,y,x); t->y=y, t->x=x; break; case 7: texec(t->cap,t->cv,1,y); t->y=y; texec(t->cap,t->ch,1,x); t->x=x; break; case 13: texec(t->cap,t->cV,1,y); t->y=y; t->x=0; break; } /* Use relative cursor position functions if we're not there yet */ /* First adjust row */ if(y>t->y) /* Have to go down */ if(!t->lf || t->cDO<(y-t->y)*t->clf) texec(t->cap,t->DO,1,y-t->y), t->y=y; else while(y>t->y) texec(t->cap,t->lf,1), ++t->y; else if(y<t->y) /* Have to go up */ if(!t->up || t->cUP<(t->y-y)*t->cup) texec(t->cap,t->UP,1,t->y-y), t->y=y; else while(y<t->y) texec(t->cap,t->up,1), --t->y; /* Use tabs */ if(x>t->x && t->ta) { int ntabs=(x-t->x+t->x%t->tw)/t->tw; int cstunder=x%t->tw+t->cta*ntabs, cstover; if(x+t->tw<t->co && t->bs) cstover=t->cbs*(t->tw-x%t->tw)+t->cta*(ntabs+1); else cstover=10000; if(cstunder<t->cRI && cstunder<x-t->x && cstover>cstunder) { if(ntabs) { t->x=x-x%t->tw; do texec(t->cap,t->ta,1); while(--ntabs); } } else if(cstover<t->cRI && cstover<x-t->x) { t->x=t->tw+x-x%t->tw; ++ntabs; do texec(t->cap,t->ta,1); while(--ntabs); } } else if(x<t->x && t->bt) { int ntabs=((t->x+t->tw-1)-(t->x+t->tw-1)%t->tw- ((x+t->tw-1)-(x+t->tw-1)%t->tw))/t->tw; int cstunder,cstover; if(t->bs) cstunder=t->cbt*ntabs+t->cbs*(t->tw-x%t->tw); else cstunder=10000; if(x-t->tw>=0) cstover=t->cbt*(ntabs+1)+x%t->tw; else cstover=10000; if(cstunder<t->cLE && (t->bs?cstunder<(t->x-x)*t->cbs:1) && cstover>cstunder) { if(ntabs) { do texec(t->cap,t->bt,1); while(--ntabs); t->x=x+t->tw-x%t->tw; } } else if(cstover<t->cRI && (t->bs?cstover<(t->x-x)*t->cbs:1)) { t->x=x-x%t->tw; ++ntabs; do texec(t->cap,t->bt,1); while(--ntabs); } } /* Now adjust column */ if(x<t->x) /* Have to go left */ if(!t->bs || t->cLE<(t->x-x)*t->cbs) texec(t->cap,t->LE,1,t->x-x), t->x=x; else while(x<t->x) texec(t->cap,t->bs,1), --t->x; else if(x>t->x) /* Have to go right */ /* Hmm.. this should take into account possible attribute changes */ if(t->cRI<x-t->x) texec(t->cap,t->RI,1,x-t->x), t->x=x; else { int *s=t->scrn+t->x+t->y*t->co; if(t->ins) clrins(t); while(x>t->x) { int c= (0xFF&*s); int a= (0xFF00&*s); if(a!=t->attrib) attr(t,a); ttputc(c); ++s; ++t->x; } } } int cpos(t,x,y) register SCRN *t; register int x,y; { if(y==t->y) { if(x==t->x) return 0; if(x>t->x && x-t->x<4 && !t->ins) { int *cs=t->scrn+t->x+t->co*t->y; if(t->ins) clrins(t); do { int c= (0xFF& *cs); int a= (0xFF00& *cs); if(a!=t->attrib) attr(t,a); ttputc(c); ++cs; ++t->x; } while(x!=t->x); return 0; } } if(!t->ms && t->attrib&(INVERSE|UNDERLINE)) attr(t,t->attrib&~(INVERSE|UNDERLINE)); if(y<t->top || y>=t->bot) setregn(t,0,t->li); cposs(t,x,y); return 0; } static void doinschr(t,x,y,s,n) SCRN *t; int x,y,*s,n; { int a; if(x<0) s-=x, x=0; if(x>=t->co-1 || n<=0) return; if(t->im || t->ic || t->IC) { cpos(t,x,y); if(n==1 && t->ic || !t->IC) { if(!t->ic) setins(t,x); for(a=0;a!=n;++a) { texec(t->cap,t->ic,1,x); outatri(t,x+a,y,s[a]); texec(t->cap,t->ip,1,x); } if(!t->mi) clrins(t); } else { texec(t->cap,t->IC,1,n); for(a=0;a!=n;++a) outatri(t,x+a,y,s[a]); } } mmove(t->scrn+x+t->co*y+n,t->scrn+x+t->co*y,(t->co-(x+n))*sizeof(int)); mcpy(t->scrn+x+t->co*y,s,n*sizeof(int)); } static void dodelchr(t,x,y,n) SCRN *t; int x,y,n; { int a; if(x<0) x=0; if(!n || x>=t->co-1) return; if(t->dc || t->DC) { cpos(t,x,y); texec(t->cap,t->dm,1,x); /* Enter delete mode */ if(n==1 && t->dc || !t->DC) for(a=n;a;--a) texec(t->cap,t->dc,1,x); else texec(t->cap,t->DC,1,n); texec(t->cap,t->ed,1,x); /* Exit delete mode */ } mmove(t->scrn+t->co*y+x,t->scrn+t->co*y+x+n,(t->co-(x+n))*sizeof(int)); msetI(t->scrn+t->co*y+t->co-n,' ',n); } /* Insert/Delete within line */ void magic(t,y,cs,s,placex) SCRN *t; int y,*cs,*s; { struct hentry *htab=t->htab; int *ofst=t->ofst; int aryx=1; int x; if(!(t->im || t->ic || t->IC) || !(t->dc || t->DC)) return; mset(htab,0,256*sizeof(struct hentry)); msetI(ofst,0,t->co); /* Build hash table */ for(x=0;x!=t->co-1;++x) t->ary[aryx].next=htab[cs[x]&255].next, t->ary[aryx].loc=x, ++htab[cs[x]&255].loc, htab[cs[x]&255].next=aryx++; /* Build offset table */ for(x=0;x<t->co-1;) if(htab[s[x]&255].loc>=15) ofst[x++]= t->co-1; else { int aryy; int maxaryy; int maxlen=0; int best=0; int bestback=0; int z; for(aryy=htab[s[x]&255].next;aryy;aryy=t->ary[aryy].next) { int amnt,back; int tsfo=t->ary[aryy].loc-x; int cst= -Iabs(tsfo); int pre=32; for(amnt=0;x+amnt<t->co-1 && x+tsfo+amnt<t->co-1;++amnt) { if(cs[x+tsfo+amnt]!=s[x+amnt]) break; else if(s[x+amnt]&255!=32 || pre!=32) ++cst; pre=s[x+amnt]&255; } pre=32; for(back=0;back+x>0 && back+tsfo+x>0;--back) { if(cs[x+tsfo+back-1]!=s[x+back-1]) break; else if(s[x+back-1]&255!=32 || pre!=32) ++cst; pre=s[x+back-1]&255; } if(cst>best) maxaryy=aryy, maxlen=amnt, best=cst, bestback=back; } if(!maxlen) ofst[x]=t->co-1, maxlen=1; else if(best<2) for(z=0;z!=maxlen;++z) ofst[x+z]=t->co-1; else for(z=0;z!=maxlen-bestback;++z) ofst[x+z+bestback]=t->ary[maxaryy].loc-x; x+=maxlen; } /* Apply scrolling commands */ for(x=0;x!=t->co-1;++x) { int q=ofst[x]; if(q && q!=t->co-1) if(q>0) { int z,fu; for(z=x;z!=t->co-1 && ofst[z]==q;++z); while(s[x]==cs[x] && x<placex) ++x; dodelchr(t,x,y,q); for(fu=x;fu!=t->co-1;++fu) if(ofst[fu]!=t->co-1) ofst[fu]-=q; x=z-1; } else { int z,fu; for(z=x;z!=t->co-1 && ofst[z]==q;++z); while(s[x+q]==cs[x+q] && x-q<placex) ++x; doinschr(t,x+q,y,s+x+q,-q); for(fu=x;fu!=t->co-1;++fu) if(ofst[fu]!=t->co-1) ofst[fu]-=q; x=z-1; } } } static void doupscrl(t,top,bot,amnt) SCRN *t; int top,bot,amnt; { int a=amnt; if(!amnt) return; attr(t,0); if(top==0 && bot==t->li && (t->sf || t->SF)) { setregn(t,0,t->li); cpos(t,0,t->li-1); if(amnt==1 && t->sf || !t->SF) while(a--) texec(t->cap,t->sf,1,t->li-1); else texec(t->cap,t->SF,a,a); goto done; } if(bot==t->li && (t->dl || t->DL)) { setregn(t,0,t->li); cpos(t,0,top); if(amnt==1 && t->dl || !t->DL) while(a--) texec(t->cap,t->dl,1,top); else texec(t->cap,t->DL,a,a); goto done; } if(t->cs && ( t->sf || t->SF )) { setregn(t,top,bot); cpos(t,0,bot-1); if(amnt==1 && t->sf || !t->SF) while(a--) texec(t->cap,t->sf,1,bot-1); else texec(t->cap,t->SF,a,a); goto done; } if((t->dl || t->DL) && (t->al || t->AL)) { cpos(t,0,top); if(amnt==1 && t->dl || !t->DL) while(a--) texec(t->cap,t->dl,1,top); else texec(t->cap,t->DL,a,a); a=amnt; cpos(t,0,bot-amnt); if(amnt==1 && t->al || !t->AL) while(a--) texec(t->cap,t->al,1,bot-amnt); else texec(t->cap,t->AL,a,a); goto done; } msetI(t->updtab+top,1,bot-top); return; done: mfwrd(t->scrn+top*t->co,t->scrn+(top+amnt)*t->co, (bot-top-amnt)*t->co*sizeof(int)); if(bot==t->li && t->db) { msetI(t->scrn+(t->li-amnt)*t->co,-1,amnt*t->co); msetI(t->updtab+t->li-amnt,1,amnt); } else msetI(t->scrn+(bot-amnt)*t->co,' ',amnt*t->co); } static void dodnscrl(t,top,bot,amnt) SCRN *t; int top,bot,amnt; { int a=amnt; if(!amnt) return; attr(t,0); if(top==0 && bot==t->li && (t->sr || t->SR)) { setregn(t,0,t->li); cpos(t,0,0); if(amnt==1 && t->sr || !t->SR) while(a--) texec(t->cap,t->sr,1,0); else texec(t->cap,t->SR,a,a); goto done; } if(bot==t->li && (t->al || t->AL)) { setregn(t,0,t->li); cpos(t,0,top); if(amnt==1 && t->al || !t->AL) while(a--) texec(t->cap,t->al,1,top); else texec(t->cap,t->AL,a,a); goto done; } if(t->cs && (t->sr || t->SR)) { setregn(t,top,bot); cpos(t,0,top); if(amnt==1 && t->sr || !t->SR) while(a--) texec(t->cap,t->sr,1,top); else texec(t->cap,t->SR,a,a); goto done; } if((t->dl || t->DL) && (t->al || t->AL)) { cpos(t,0,bot-amnt); if(amnt==1 && t->dl || !t->DL) while(a--) texec(t->cap,t->dl,1,bot-amnt); else texec(t->cap,t->DL,a,a); a=amnt; cpos(t,0,top); if(amnt==1 && t->al || !t->AL) while(a--) texec(t->cap,t->al,1,top); else texec(t->cap,t->AL,a,a); goto done; } msetI(t->updtab+top,1,bot-top); return; done: mbkwd(t->scrn+(top+amnt)*t->co,t->scrn+top*t->co, (bot-top-amnt)*t->co*sizeof(int)); if(!top && t->da) { msetI(t->scrn,-1,amnt*t->co); msetI(t->updtab,1,amnt); } else msetI(t->scrn+t->co*top,' ',amnt*t->co); } void nscroll(t) SCRN *t; { int y,z,q,r,p; for(y=0;y!=t->li;++y) { q=t->sary[y]; if(have) return; if(q && q!=t->li) if(q>0) { for(z=y;z!=t->li && t->sary[z]==q;++z) t->sary[z]=0; doupscrl(t,y,z+q,q), y=z-1; } else { for(r=y;r!=t->li && (t->sary[r]<0 || t->sary[r]==t->li);++r); p=r-1; do { q=t->sary[p]; if(q && q!=t->li) { for(z=p;t->sary[z]=0, (z && t->sary[z-1]==q);--z); dodnscrl(t,z+q,p+1,-q); p=z+1; } } while(p--!=y); y=r-1; } } msetI(t->sary,0,t->li); } void npartial(t) SCRN *t; { attr(t,0); clrins(t); setregn(t,0,t->li); } void nescape(t) SCRN *t; { npartial(t); cpos(t,0,t->li-1); eraeol(t,0,t->li-1); if(t->te) texec(t->cap,t->te,1); } void nreturn(t) SCRN *t; { if(t->ti) texec(t->cap,t->ti,1); nredraw(t); } void nclose(t) SCRN *t; { int x; leave=1; attr(t,0); clrins(t); setregn(t,0,t->li); cpos(t,0,t->li-1); if(t->te) texec(t->cap,t->te,1); ttclose(); rmcap(t->cap); free(t->scrn); free(t->sary); free(t->ofst); free(t->htab); free(t->ary); free(t); } void nscrldn(t,top,bot,amnt) SCRN *t; int top,bot,amnt; { int x; if(!amnt || top>=bot || bot>t->li) return; if(amnt<bot-top && bot-top-amnt<amnt/2 || !t->scroll) amnt=bot-top; if(amnt<bot-top) { for(x=bot;x!=top+amnt;--x) t->sary[x-1]=(t->sary[x-amnt-1]==t->li?t->li:t->sary[x-amnt-1]-amnt), t->updtab[x-1]=t->updtab[x-amnt-1]; for(x=top;x!=top+amnt;++x) t->updtab[x]=1; } if(amnt>bot-top) amnt=bot-top; msetI(t->sary+top,t->li,amnt); if(amnt==bot-top) msetI(t->updtab+top,1,amnt); } void nscrlup(t,top,bot,amnt) SCRN *t; int top,bot,amnt; { int x; if(!amnt || top>=bot || bot>t->li) return; if(amnt<bot-top && bot-top-amnt<amnt/2 || !t->scroll) amnt=bot-top; if(amnt<bot-top) { for(x=top+amnt;x!=bot;++x) t->sary[x-amnt]=(t->sary[x]==t->li?t->li:t->sary[x]+amnt), t->updtab[x-amnt]=t->updtab[x]; for(x=bot-amnt;x!=bot;++x) t->updtab[x]=1; } if(amnt>bot-top) amnt=bot-top; msetI(t->sary+bot-amnt,t->li,amnt); if(amnt==bot-top) msetI(t->updtab+bot-amnt,1,amnt); } extern int dostaupd; void nredraw(t) SCRN *t; { dostaupd=1; msetI(t->scrn,' ',t->co*skiptop); msetI(t->scrn+skiptop*t->co,-1,(t->li-skiptop)*t->co); msetI(t->sary,0,t->li); msetI(t->updtab+skiptop,-1,t->li-skiptop); t->x= -1; t->y= -1; t->top=t->li; t->bot=0; t->attrib= -1; t->ins= -1; attr(t,0); clrins(t); setregn(t,0,t->li); if(!skiptop) if(t->cl) { texec(t->cap,t->cl,1,0); t->x=0; t->y=0; msetI(t->scrn,' ',t->li*t->co); } else if(t->cd) { cpos(t,0,0); texec(t->cap,t->cd,1,0); msetI(t->scrn,' ',t->li*t->co); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.