|
|
researchv9-SUN3(old)
#include <jerq.h>
#include <layer.h>
#include <font.h>
#include <queue.h>
#include <jerqproc.h>
#include <setup.h>
#include "frame/frame.h"
#include "../msgs.h"
#define ECHO (tp->flags0&TECHO)
#define RAW (tp->flags0&TRAW)
#define CBREAK (tp->flags0&TCBREAK)
#define CRMOD (tp->flags0&TCRMOD)
/*
* Keyboard-dependent things
*/
#ifdef BLITKBD
#define BREAKKEY 0xE0
#define SCROLLKEY 0xB0 /* Why not NO SCRL? */
#undef ringbell
#define ringbell() DUART->b_data=0x02
#else
#define BREAKKEY 0x80
#define SCROLLKEY 0xB2 /* Why not NUM LOCK? */
#endif
#define CTRLW 0x17
#define NSCRL 2
int HIWATER; /* #chars max to save off top of screen */
int LOWATER;
int doubleclickOK;
typedef struct Type{
Frame *frame; /* Frame being typed at */
short start; /* start pos. of text to be sent to host */
short nchars; /* number of chars typed */
String old; /* old text scrolled off top */
char scroll;
}Type;
String buf;
short scrltimeout;
#define M 3 /* margin around frame */
windowproc(){
register Frame *f;
register got;
String rcvstr;
static String zerostr;
Type current;
if((current.frame=f=fralloc(P->layer->rect, M))==0){
mesg("can't allocate frame");
for(;;)
sleep(1000);
}
frinit(f);
setborder(P); /* frames always draw them black */
muxmesg((int)(P-proctab), C_POPLD);
current.start=0;
current.nchars=0;
current.scroll=0;
current.old=zerostr;
insure(¤t.old, 128, P);
rcvstr=zerostr;
insure(&rcvstr, 128, P);
Urequest(RCV|KBD|MOUSE);
Ucursswitch((Texture *)0);
setscroll(¤t);
for(;;){
linecurse(f); /* cursor is off, so turn it on */
do{
if(P->state&RESHAPED){
frsetrects(f, P->layer->rect);
drawframe(f); /* sets complete */
setborder(P);
if(!complete && current.scroll)
advance(¤t);
P->state&=~(RESHAPED|MOVED|BLOCKED);
linecurse(f); /* put it back */
}
}while((got=Uwait((P->state&BLOCKED)?
KBD|MOUSE|ALARM : KBD|MOUSE|RCV|ALARM))==MOUSE
&& button123()==0);
linecurse(f); /* turn it off */
if(got&ALARM){
setscroll(¤t);
P->state&=~ALARMREQD;
}
if(got&MOUSE && button123())
wbuttons(¤t);
else if(got&KBD)
kbd(¤t, Ukbdchar());
else if(got&RCV)
rcv(¤t, &rcvstr);
}
}
bufinit(){
strzero(&buf);
if(VALMAXADDR)
HIWATER=10000, LOWATER=8000;
else
HIWATER=2500, LOWATER=1500;
}
getmuxbuf(s)
register String *s;
{
insure(s, buf.n, P);
movstring(buf.n, buf.s, s->s);
s->n=buf.n;
}
setmuxbuf(s)
String *s;
{
snarf(s, 0, s->n);
}
rcv(t, rcvstr)
Type *t;
register String *rcvstr;
{
register char *p;
register Frame *f=t->frame;
register i, posn, c;
int compl;
struct ttychars *tp=&P->ttychars;
/* Read the string */
c=Urcvchar();
loop:
while(c=='\b'){
if(t->start > 0)
deltype(t, t->start-1, t->start);
c=Urcvchar();
}
p=rcvstr->s;
for(i=0; c!=-1; c=Urcvchar()){ /*aplterm1*/
c&=0x7F;
if(c == '\b') break;
if(c=='\7')
ringbell(); /* smashes keyclick? */
if(c && c!='\r' && c<P->defaultfont->n){
*p++=c;
if(++i==rcvstr->size)
break;
}
}
rcvstr->n=i;
posn=t->start;
if(f->s1<posn && posn<f->s2){
t->start=posn=f->s1; /* before selected text; avoids problems */
t->nchars=0;
}
/* Undraw selection if necessary */
if(posn<f->s2 && f->s2>f->s1)
selectf(f, F_XOR);
/* Find where it goes */
instext(f, rcvstr, posn);
compl=inscomplete;
/* Adjust the selection and typing location */
if(posn<f->s2 || (f->s1==f->s2 && posn==f->s2)){
f->s1+=i;
f->s2+=i;
}
t->start+=i;
if(posn+i<f->s2 && f->s2>f->s1)
selectf(f, F_XOR);
if(!compl){
if(t->scroll)
advance(t);
else
P->state|=BLOCKED; /* so cat hugefile is safe */
}
if(c=='\b')
goto loop;
alarm(scrltimeout);
}
linecurse(t)
register Frame *t;
{
Point p;
if(t && t->str.s && t->s1==t->s2){
p=ptofchar(t, t->s1);
Rectf(Rpt(p, Pt(p.x+1, p.y+newlnsz)), F_XOR);
}
}
mesg(s)
char *s;
{
string(&defont, s, P->layer, add(P->rect.origin, Pt(2, 2)), F_STORE);
}
kbd(t, ac)
register Type *t;
char ac;
{
static int raw, echo, cbreak, crmod; /* can be static; we don't sleep here */
register Frame *f=t->frame;
register struct ttychars *tp=&P->ttychars;
int tounix;
unsigned char c;
c=ac;
if(c==SCROLLKEY){
scrlf(t, charofpt(f,
Pt(f->rect.origin.x, f->rect.origin.y+newlnsz*f->nlines/2)));
return;
}
if(f->s2>f->s1)
cut(t, 1);
if(f->s2>=t->start){
tounix=TRUE;
raw=RAW;
cbreak=CBREAK;
crmod=CRMOD;
echo=ECHO;
}else{
tounix=FALSE;
raw=FALSE;
cbreak=FALSE;
crmod=TRUE;
echo=TRUE;
}
if(raw && c!=BREAKKEY){ /* break goes, even in raw mode */
/* flush input */
t->start+=t->nchars;
t->nchars=0;
Noecho:
Usendchar(c);
return; /* no echo in raw mode */
}
if(c==BREAKKEY)
c=tp->intrc;
if(c==tp->intrc || c==tp->quitc){ /* always kill */
/* flush input */
t->start=f->str.n;
t->nchars=0;
muxkill(c==tp->intrc? 2 : 3, P);
return;
}
/* never raw mode */
if(!echo && t->nchars>0){ /* send off what's already there */
sendsubstr(f->str.s, t->start, t->nchars-t->start);
t->nchars=0;
t->start=f->str.n;
}
c&=0x7F; /* strip off sign bit from keypad */ /*aplterm2*/
if(c==tp->eofc && !cbreak){
if(tounix)
goto Send; /* throw away eofc */
return;
}
if(c=='\r' && crmod)
c='\n';
if(!echo)
goto Noecho;
if(f->s2>0 && f->str.s[f->s2-1]=='\\' &&
(c==tp->erase || (c==tp->kill&&tounix) || c==CTRLW ||
c==tp->stopc || c==tp->startc)){
deltype(t, f->s2-1, f->s2); /* throw away \ */
goto Ordinary;
}
if(c==tp->erase || c==CTRLW){
if(f->s1 > (tounix? t->start : 0))
deltype(t, f->s1-nback(f, c, tounix? t->start : 0), f->s1);
return;
}
if(c==tp->kill && tounix){
f->s2=f->str.n;
inschar(t, '@');
inschar(t, '\n');
t->start=f->s2;
t->nchars=0;
return;
}
if(c==tp->stopc){
P->state|=BLOCKED;
return;
}
if(c==tp->startc){
P->state&=~BLOCKED;
return;
}
Ordinary:
inschar(t, c);
if(tounix && (P->state&BLOCKED))
P->state&=~BLOCKED;
if(tounix && f->s2>t->start && (c=='\n' || (cbreak && c=='\r'))){
Send:
sendsubstr(f->str.s, t->start, f->s2);
t->nchars-=f->s2-t->start;
t->start+=f->s2-t->start;
}
}
nback(f, c, lim)
Frame *f;
{
register n=0, s1=f->s1;
register char *s=f->str.s+s1;
static char alphanl[]=
"\n0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define alphanum alphanl+1
if(s1 <= 0)
return 0;
if(c!=CTRLW || *--s=='\n')
return 1;
/* else it's ^W. first, get to an alphanumeric (or newline) */
while(n<s1-lim && notin(*s, alphanl))
--s, ++n;
/* *s is alphanumeric or space; now back up to non-alphanumeric */
while(n<s1 && !notin(*s, alphanum))
--s, ++n;
return n;
}
notin(c, s)
register c;
register char *s;
{
c&=0xFF;
while(*s)
if(c == *s++)
return FALSE;
return TRUE;
}
inschar(t, ac)
register Type *t;
{
static char c;
static String kbdstr={
&c,
1,
1
};
register Frame *f=t->frame;
c=ac;
instype(t, &kbdstr, f->s2);
if(!inscomplete)
scrlf(t, getto(f, f->s2));
setsel(f, f->s2+1);
}
getto(f, end)
register Frame *f;
{
register nl, nc, i;
nl=max(NSCRL, f->nlines/5);
nc=charofpt(f, f->rect.corner);
while(nc<end)
if(f->str.s[nc++]=='\n')
nl++;
/* nl is now #lines; find how many chars from start of frame */
for(i=nc=0; i<end; )
if(f->str.s[i++]=='\n'){
nc=i;
if(--nl<=0)
return nc;
}
return end;
}
advance(t)
Type *t;
{
/* should work first time unless lines are folded */
do; while(!scrlf(t, getto(t->frame, t->frame->str.n)));
}
insertstring(p, i, s, n) /* warning: must call insure() before this! */
String *p;
char *s;
{
String str;
str.s=s, str.n=n;
insstring(p, i, &str);
}
inserttype(t, s, n) /* warning: must call insure() before this! */
Type *t;
char *s;
{
register Frame *f=t->frame;
String str;
str.s=s, str.n=n;
selectf(f, F_XOR);
instext(f, &str, 0);
f->s1+=n;
f->s2+=n;
t->start+=n;
selectf(f, F_XOR);
}
scrlf(t, n)
register Type *t;
register n;
{
register Frame *f=t->frame;
if(n>0){
if(n>f->str.n)
n=f->str.n;
sendoldtext(t, n);
/* quick hack; don't worry about order of allocation */
insure(&t->old, t->old.n+n, P);
insertstring(&t->old, t->old.n, f->str.s, n);
if(t->old.n>HIWATER)
delstring(&t->old, 0, t->old.n-LOWATER);
if(n=deltype(t, 0, n)) /* all text in frame now visible */
P->state&=~BLOCKED;
}
setscroll(t);
return n;
}
scrlb(t, n)
register Type *t;
register n;
{
register Frame *f=t->frame;
register i;
if(n>0){
if(n>t->old.n)
n=t->old.n;
i=t->old.n-n;
while(i>0 && t->old.s[i-1]!='\n')
i--, n++;
insure(&t->old, t->old.n+n, P);
inserttype(t, t->old.s+i, n);
delstring(&t->old, i, t->old.n);
}
setscroll(t);
}
deltype(t, s1, s2)
register Type *t;
register s1, s2;
{
register Frame *f=t->frame;
int compl;
if(s2<=t->start)
t->start-=s2-s1;
else if(s1>=t->start)
t->nchars-=s2-s1;
else if(s2>t->start){ /* deletion overlaps start */
t->nchars-=s2-t->start;
t->start=s1;
}
selectf(f, F_XOR);
deltext(f, s1, s2);
compl=complete;
f->s1-=max(0, min(f->s1, s2)-s1);
f->s2-=max(0, min(f->s2, s2)-s1);
selectf(f, F_XOR);
return compl;
}
instype(t, s, s1)
register Type *t;
String *s;
register s1;
{
if(s->n>0){
if(s1<t->start)
t->start+=s->n;
else if(s1>=t->start)
t->nchars+=s->n;
instext(t->frame, s, s1);
}
}
#define CUT 0
#define PASTE 1
#define SNARF 2
#define SENDIT 3
#define SCROLL 4
#define UP 0
#define DOWN 1
static char *editstrs[]={
"cut",
"paste",
"snarf",
"send",
0,
0,
};
static Menu editmenu={editstrs};
wbuttons(t)
register Type *t;
{
register Frame *f=t->frame;
static char *scrollstrs[]={ "scroll", "noscroll" };
if(!ptinrect(mouse.xy, f->totalrect)){ /* not for us anyway */
doubleclickOK=0;
return;
}
if(ptinrect(mouse.xy, f->scrollrect))
scroll(t, mouse.buttons);
else if(button1()){
if(ptinrect(mouse.xy, f->rect))
frselect(f, mouse.xy);
}else if(button2()){
doubleclickOK=0;
editstrs[SCROLL]=scrollstrs[t->scroll];
switch(menuhit(&editmenu, 2)){
case CUT:
cut(t, 1);
break;
case PASTE:
paste(t, &buf);
break;
case SNARF:
if(f->s2>f->s1)
snarf(&f->str, f->s1, f->s2);
break;
case SENDIT:
send(t);
break;
case SCROLL:
if((t->scroll^=1) &&
(frameop(f, opnull, f->rect.origin,
f->str.s, f->str.n), !complete))
advance(t);
break;
}
}else{
doubleclickOK=0;
Urequest(RCV|KBD);
sleep(2);
Urequest(RCV|KBD|MOUSE);
}
}
snarf(p, i, j)
register String *p;
register short i, j;
{
register n = j-i;
insure(&buf, n, (struct Proc *)0);
movstring(n, p->s+i, buf.s);
buf.n = n;
}
cut(t, save)
register Type *t;
{
register n;
register Frame *f=t->frame;
if((n=f->s1) != f->s2){
if(save)
snarf(&f->str, n, f->s2);
deltype(t, f->s1, f->s2);
f->s1=f->s2;
setsel(f, n);
P->state&=~BLOCKED; /* in case we are suspended */
}
}
paste(t, s)
register Type *t;
String *s;
{
register Frame *f=t->frame;
if(s->n==0)
return;
cut(t, 0);
instype(t, s, f->s1);
f->s2=f->s1+s->n;
selectf(f, F_XOR);
}
send(t)
register Type *t;
{
register Frame *f=t->frame;
if(f->s1!=f->s2)
snarf(&f->str, f->s1, f->s2);
if(buf.n==0)
return;
if(t->nchars)
deltype(t, t->start, t->start+t->nchars);
if(P->ttychars.flags0&TECHO){
instext(f, &buf, f->str.n);
if(!inscomplete)
advance(t);
}
selectf(f, F_XOR);
f->s1=f->s2=f->str.n;
sendsubstr(buf.s, 0, buf.n);
if(buf.s[buf.n-1]!='\n'){
sendnchars(1, "\n");
if((P->ttychars.flags0&(TRAW|TCBREAK|TECHO))==TECHO)
inschar(t, '\n');
delim();
}
/* else the delim's already been sent */
t->start=f->s2;
t->nchars=0;
}
sendsubstr(s, beg, end)
register char *s;
{
register m, n;
if(beg==end){
delim();
return;
}
for(m=beg; m<end; m=n+1){
/* invariant: n is the last character we are going to send */
for(n=m; n<end && s[n]!='\n'; n++)
if(n==end-1)
break;
sendnchars(n-m+1, s+m);
if(n<end && s[n]=='\n')
delim();
}
}
sendoldtext(t, n)
register Type *t;
{
if(t->start<n && t->nchars>0){
if(n>t->start+t->nchars)
n=t->start+t->nchars;
sendsubstr(t->frame->str.s, t->start, n);
}
}
Texture grey = {
0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA,
0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA,
};
Point
scrollclip(p)
Point p;
{
if(p.x<0){
p.y-=p.x;
p.x=0;
}
if(p.y>SCROLLRANGE)
p.y=SCROLLRANGE;
return p;
}
Rectangle
scrollmark(f, p)
register Frame *f;
Point p;
{
Rectangle r;
p=scrollclip(p);
r=f->scrollrect;
r.origin.y=clixtopix(f, p.x);
r.corner.y=clixtopix(f, p.y);
return r;
}
clixtopix(f, y)
register Frame *f;
{
return f->scrollrect.origin.y+muldiv(f->nlines*newlnsz, y, SCROLLRANGE);
}
pixtoclix(f, y)
register Frame *f;
{
return muldiv(y-f->rect.origin.y, SCROLLRANGE, f->nlines*newlnsz);
}
drawscrollbar(f)
register Frame *f;
{
Rectangle r;
register Bitmap *b; /* offscreen to avoid flicker */
r=inset(f->scrollrect, -1);
b=balloc(r);
if(b==0)
b=(Bitmap *)D;
Urectf(b, r, F_OR);
lrectf(b, scrollmark(f, f->scroll), F_XOR);
Ubitblt(b, r, D, r.origin, F_STORE);
if(b!=(Bitmap *)D)
bfree(b);
}
setscroll(t)
register Type *t;
{
register Frame *f=t->frame;
Point new;
register x, y;
x=f->rect.origin.y+1; /* a little margin at the top */
y=f->rect.corner.y-1; /* and bottom */
if(t->old.n+f->str.n>0)
x+=muldiv(f->nlines*newlnsz, t->old.n, t->old.n+f->str.n);
if(f->cpl[f->nlines-1]>0){
int n;
n=charofpt(f, Pt(XMAX, YMAX));
y-=muldiv(f->nlines*newlnsz, f->str.n-n, t->old.n+f->str.n);
}
if(x>y-(f->rect.corner.y-f->rect.origin.y)/30)
x=y-(f->rect.corner.y-f->rect.origin.y)/30;
if(y<x+(f->rect.corner.y-f->rect.origin.y)/30)
y=x+(f->rect.corner.y-f->rect.origin.y)/30;
new.x=pixtoclix(f, x);
new.y=pixtoclix(f, y);
if(abs(f->scroll.x-new.x)>20 || abs(f->scroll.y-new.y)>20){
f->scroll=new;
drawscrollbar(f);
}
}
Point
checkmouse(f, mousep, p)
Frame *f;
Point mousep, p;
{
if(!ptinrect(mousep, f->scrollrect)){
extern Rectangle Null;
return Null.origin;
}
return p;
}
Point
but1func(f, p)
register Frame *f;
Point p;
{
register delta=muldiv(p.y-f->rect.origin.y, f->scroll.y-f->scroll.x, f->nlines*newlnsz);
return checkmouse(f, p, sub(f->scroll, Pt(delta, delta)));
}
Point
but2func(f, p)
register Frame *f;
Point p;
{
Point scroll;
register size=(f->scroll.y-f->scroll.x)/2;
scroll.x=pixtoclix(f, p.y)-size;
scroll.y=pixtoclix(f, p.y)+size;
return checkmouse(f, p, scroll);
}
Point
but3func(f, p)
register Frame *f;
Point p;
{
register delta=muldiv(p.y-f->rect.origin.y, f->scroll.y-f->scroll.x, f->nlines*newlnsz);
return checkmouse(f, p, add(f->scroll, Pt(delta, delta)));
}
typedef Point (*ptrfpoint)();
ptrfpoint butfunc[]={
0,
but1func,
but2func,
but3func,
};
Point
guide(m, p)
Point m, p;
{
if(abs(m.x-p.x)<3)
m.x=p.x;
return m;
}
scrollbar(f, but)
register Frame *f;
{
ptrfpoint fp;
Point pt;
fp=butfunc[but];
pt=mouse.xy;
while(button(but)){
ltexture(D, scrollmark(f, (*fp)(f, pt)), &grey, F_XOR);
do nap(3); while(eqpt(mouse.xy, pt) && button(but));
ltexture(D, scrollmark(f, (*fp)(f, pt)), &grey, F_XOR);
cursset(pt=guide(mouse.xy, pt));
}
if(ptinrect(pt, f->scrollrect)){
f->scroll=(*fp)(f, pt);
if(f->scroll.x<0){
f->scroll.y-=f->scroll.x;
f->scroll.x=0;
}
if(f->scroll.x>SCROLLRANGE){
f->scroll.y-=f->scroll.x-SCROLLRANGE;
f->scroll.x=SCROLLRANGE;
}
return 1;
}
return 0;
}
scroll(t, but)
register Type *t;
{
register Frame *f=t->frame;
Point old, new;
register y, b;
old=f->scroll;
if(scrollbar(f, b=whichbutton())){
new=f->scroll;
f->scroll=old; /* ugh */
y=mouse.xy.y;
if(b==2){
y=muldiv(f->str.n+t->old.n, new.x, SCROLLRANGE);
if(y>=t->old.n){
y-=t->old.n;
do; while(y<f->str.n && f->str.s[y++]!='\n');
scrlf(t, y);
}else
scrlb(t, t->old.n-y);
}else if(new.x>=old.x)
scrlf(t, charofpt(f, Pt(f->rect.origin.x, y)));
else
scrlb(t, oldlinepos(t, (y-f->scrollrect.origin.y)/newlnsz));
}
}
oldlinepos(t, n)
register Type *t;
register n;
{
register i=t->old.n;
while(n>0 && i>0)
if(t->old.s[--i]=='\n')
--n;
return t->old.n-i;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.