ref: a369f1f2450401b373cc4f10e7448e1af9579135
parent: fb7cc13fe8c7e198e6130f973448b13ac8614470
author: aap <aap@papnet.eu>
date: Mon Sep 30 15:48:40 EDT 2024
tracking front branch.
--- a/fs.c
+++ b/fs.c
@@ -443,6 +443,7 @@
rd = fid->omode==ORDWR || fid->omode==OREAD;
wr = fid->omode==ORDWR || fid->omode==OWRITE;
+ if(fid->omode != -1)
switch(QFILE(fid->qid.path)){
/* replace snarf buffer when /dev/snarf is closed */
case Qsnarf:
@@ -555,39 +556,46 @@
}
static char*
-readblocking(Req *r, Channel *readchan)
+waitblocking(Req *r, Channel *waitchan, Channel **replychan)
{
Window *w;
- Channel *chan;
- Stringpair pair;
enum { Adata, Agone, Aflush, NALT };
Alt alts[NALT+1];
w = XF(r->fid)->w;
- alts[Adata] = ALT(readchan, &chan, CHANRCV);
- if(w)
- alts[Agone] = ALT(w->gone, nil, CHANRCV);
- else
- alts[Agone] = ALT(nil, nil, CHANNOP);
+ *replychan = nil;
+ alts[Adata] = ALT(waitchan, replychan, CHANRCV);
+ alts[Agone] = w ? ALT(w->gone, nil, CHANRCV)
+ : ALT(nil, nil, CHANNOP);
alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
alts[NALT].op = CHANEND;
switch(alt(alts)){
- case Adata:
- pair.s = r->ofcall.data;
- pair.ns = r->ifcall.count;
- send(chan, &pair);
- recv(chan, &pair);
- r->ofcall.count = min(r->ifcall.count, pair.ns);
- return nil;
- case Agone:
- return Edeleted;
- case Aflush:
- return Eflush;
+ case Adata: return nil;
+ case Agone: return Edeleted;
+ case Aflush: return Eflush;
}
- return nil; /* can't happen */
+ assert(0); /* can't happen */
+ return nil;
}
+static char*
+readblocking(Req *r, Channel *readchan)
+{
+ Channel *chan;
+ Stringpair pair;
+ char *err;
+
+ if(err = waitblocking(r, readchan, &chan))
+ return err;
+ pair.s = r->ofcall.data;
+ pair.ns = r->ifcall.count;
+ send(chan, &pair);
+ recv(chan, &pair);
+ r->ofcall.count = min(r->ifcall.count, pair.ns);
+ return nil;
+}
+
static void
xread(Req *r)
{
@@ -679,12 +687,10 @@
Text *x;
vlong offset;
u32int count;
- char *data, *p, *e;
+ char *data, *p, *e, *err;
Point pt;
- Channel *kbd;
+ Channel *chan;
Stringpair pair;
- enum { Adata, Agone, Aflush, NALT };
- Alt alts[NALT+1];
xf = XF(r->fid);
w = xf->w;
@@ -705,25 +711,15 @@
switch(f){
case Qtext:
case Qcons:
- alts[Adata] = ALT(w->conswrite, &kbd, CHANRCV);
- alts[Agone] = ALT(w->gone, nil, CHANRCV);
- alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
- alts[NALT].op = CHANEND;
- switch(alt(alts)){
- case Adata:
- cnvsize(&xf->cnv, count);
- memmove(xf->cnv.buf+xf->cnv.n, data, count);
- xf->cnv.n += count;
- pair = b2r(&xf->cnv);
- send(kbd, &pair);
- break;
- case Agone:
- respond(r, Edeleted);
+ if(err = waitblocking(r, w->conswrite, &chan)){
+ respond(r, err);
return;
- case Aflush:
- respond(r, Eflush);
- return;
}
+ cnvsize(&xf->cnv, count);
+ memmove(xf->cnv.buf+xf->cnv.n, data, count);
+ xf->cnv.n += count;
+ pair = b2r(&xf->cnv);
+ send(chan, &pair);
break;
case Qconsctl:
@@ -991,8 +987,15 @@
return 0;
}
+static void
+srvthread(void*)
+{
+ threadsetname("fs");
+ srv(&fsys);
+}
+
void
-fs(void)
+startfs(void)
{
io9p = ioproc();
@@ -1003,7 +1006,7 @@
snprint(srvpipe, sizeof(srvpipe), "lola.%s.%lud", user, (ulong)getpid());
post(srvpipe, fsysfd);
// chatty9p++;
- srv(&fsys);
+ threadcreate(srvthread, nil, mainstacksize);
}
int
--- a/inc.h
+++ b/inc.h
@@ -64,7 +64,7 @@
int posx;
};
-void xinit(Text *x, Rectangle textr, Rectangle scrollr, Font *ft, Image *b, Image **cols);
+void xinit(Text *x, Rectangle textr, Rectangle scrollr, int tabwidth, Font *ft, Image *b, Image **cols);
void xsetrects(Text *x, Rectangle textr, Rectangle scrollr);
void xclear(Text *x);
void xredraw(Text *x);
@@ -77,7 +77,6 @@
void xscrdraw(Text *x);
void xscroll(Text *x, Mousectl *mc, int but);
void xscrolln(Text *x, int n);
-void xtickupdn(Text *x, int d);
void xshow(Text *x, uint q0);
void xplacetick(Text *x, uint q);
void xtype(Text *x, Rune r);
@@ -89,7 +88,6 @@
void xpaste(Text *x);
void xsend(Text *x);
int xplumb(Text *w, char *src, char *dir, int maxsize);
-void freescrtemps(void);
enum
{
@@ -118,6 +116,7 @@
extern Screen *wscreen;
extern Mousectl *mctl;
+extern int tabwidth;
extern int scrolling;
extern char *startdir;
extern int shiftdown;
@@ -298,7 +297,7 @@
extern Srv fsys;
-void fs(void);
+void startfs(void);
int fsmount(int id);
#define runemalloc(n) malloc((n)*sizeof(Rune))
--- a/main.c
+++ b/main.c
@@ -2,7 +2,8 @@
RKeyboardctl *kbctl;
Mousectl *mctl;
-int scrolling = 1;
+int tabwidth;
+int scrolling;
char *startdir;
int shiftdown;
int gotscreen;
@@ -20,6 +21,29 @@
write(windows[i]->notefd, "hangup", 6);
}
+static char *oknotes[] ={
+ "delete",
+ "hangup",
+ "kill",
+ "exit",
+ nil, // for debugging
+ nil
+};
+
+int
+notehandler(void*, char *msg)
+{
+ int i;
+
+ killprocs();
+ for(i = 0; oknotes[i]; i++)
+ if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)
+ threadexitsall(msg);
+ fprint(2, "lola %d: abort: %s\n", getpid(), msg);
+ abort();
+ return 0;
+}
+
/*
* /dev/snarf updates when the file is closed, so we must open our own
* fd here rather than use snarffd
@@ -420,57 +444,37 @@
}
-enum {
- Cut,
- Paste,
- Snarf,
- Plumb,
- Look,
- Send,
- Scroll
-};
-char *menu2str[] = {
- "cut",
- "paste",
- "snarf",
- "plumb",
- "look",
- "send",
- "scroll",
- nil
-};
-Menu menu2 = { menu2str };
-
-enum {
- New,
- Reshape,
- Move,
- Delete,
- Hide,
- Exit
-};
-int Hidden = Exit+1;
-char *menu3str[7 + MAXWINDOWS] = {
- "New",
- "Resize",
- "Move",
- "Delete",
- "Hide",
- "Exit",
- nil
-};
-Menu menu3 = { menu3str };
-
void
btn2menu(Window *w)
{
+ enum {
+ Cut,
+ Paste,
+ Snarf,
+ Plumb,
+ Look,
+ Send,
+ Scroll
+ };
+ static char *str[] = {
+ "cut",
+ "paste",
+ "snarf",
+ "plumb",
+ "look",
+ "send",
+ "scroll",
+ nil
+ };
+ static Menu menu = { str };
+
int sel;
Text *x;
Cursor *c;
x = &w->text;
- menu2str[Scroll] = w->scrolling ? "noscroll" : "scroll";
- sel = menuhit(2, mctl, &menu2, wscreen);
+ str[Scroll] = w->scrolling ? "noscroll" : "scroll";
+ sel = menuhit(2, mctl, &menu, wscreen);
switch(sel){
case Cut:
xsnarf(x);
@@ -508,6 +512,26 @@
void
btn3menu(void)
{
+ enum {
+ New,
+ Reshape,
+ Move,
+ Delete,
+ Hide,
+ Exit
+ };
+ int Hidden = Exit+1;
+ static char *str[7 + MAXWINDOWS] = {
+ "New",
+ "Resize",
+ "Move",
+ "Delete",
+ "Hide",
+ "Exit",
+ nil
+ };
+ static Menu menu = { str };
+
static Window *hidden[MAXWINDOWS];
int nhidden;
Window *w, *t;
@@ -518,13 +542,13 @@
t = windows[i];
if(t->hidden || obscured(t, t->img->r, t->higher)){
hidden[nhidden] = windows[i];
- menu3str[nhidden+Hidden] = windows[i]->label;
+ str[nhidden+Hidden] = windows[i]->label;
nhidden++;
}
}
- menu3str[nhidden+Hidden] = nil;
+ str[nhidden+Hidden] = nil;
- sel = menuhit(3, mctl, &menu3, wscreen);
+ sel = menuhit(3, mctl, &menu, wscreen);
switch(sel){
case New:
sweep(nil);
@@ -572,6 +596,7 @@
cursorwin = w;
again:
if(w == nil){
+ /* background */
setcursornormal(nil);
if(mctl->buttons & 4)
btn3menu();
@@ -587,9 +612,10 @@
bandresize(w);
}
}else if(w != focused){
+ /* inactive window */
wsetcursor(w);
if(mctl->buttons & 7 ||
- mctl->buttons & (8|16) && focused->mouseopen){
+ mctl->buttons & (8|16) && focused && focused->mouseopen){
wraise(w);
wfocus(w);
if(mctl->buttons & 1)
@@ -598,6 +624,7 @@
goto again;
}
}else if(!w->mouseopen){
+ /* active text window */
wsetcursor(w);
if(mctl->buttons && topwin != w)
wraise(w);
@@ -611,6 +638,7 @@
if(mctl->buttons & 4)
btn3menu();
}else{
+ /* active graphics window */
wsetcursor(w);
drainmouse(mctl, w);
}
@@ -632,7 +660,6 @@
sysfatal("resize failed: %r");
nr = screen->clipr;
- freescrtemps();
freescreen(wscreen);
wscreen = allocscreen(screen, background, 0);
draw(screen, screen->r, background, nil, ZP);
@@ -761,16 +788,71 @@
}
void
-threadmain(int, char *[])
+initcmd(void *arg)
{
+ char *cmd;
+ char *wsys;
+ int fd;
+
+ cmd = arg;
+ rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);
+ wsys = getenv("wsys");
+ fd = open(wsys, ORDWR);
+ if(fd < 0)
+ fprint(2, "lola: failed to open wsys: %r\n");
+ if(mount(fd, -1, "/mnt/wsys", MREPL, "none") < 0)
+ fprint(2, "lola: failed to mount wsys: %r\n");
+ if(bind("/mnt/wsys", "/dev/", MBEFORE) < 0)
+ fprint(2, "lola: failed to bind wsys: %r\n");
+ free(wsys);
+ close(fd);
+ procexecl(nil, "/bin/rc", "rc", "-c", cmd, nil);
+ fprint(2, "lola: exec failed: %r\n");
+ exits("exec");
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: lola [-i initcmd] [-s]\n");
+ exits("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ char *initstr, *s;
char buf[256];
-//rfork(RFENVG);
-//newwindow("-dx 1280 -dy 800");
+if(strcmp(argv[0]+1, ".out") == 0){
+rfork(RFENVG);
+newwindow("-dx 1280 -dy 800");
+scrolling = TRUE;
+oknotes[nelem(oknotes)-2] = "interrupt";
+}
+ initstr = nil;
+ ARGBEGIN{
+ case 'i':
+ initstr = EARGF(usage());
+ break;
+ case 's':
+ scrolling = TRUE;
+ break;
+ default:
+ usage();
+ }ARGEND
+
if(getwd(buf, sizeof(buf)) == nil)
startdir = estrdup(".");
else
startdir = estrdup(buf);
+ s = getenv("tabstop");
+ if(s)
+ tabwidth = strtol(s, nil, 0);
+ if(tabwidth == 0)
+ tabwidth = 4;
+ free(s);
+
if(initdraw(nil, nil, "lola") < 0)
sysfatal("initdraw: %r");
kbctl = initkbd(nil, nil);
@@ -800,6 +882,10 @@
flushimage(display, 1);
- fs();
- // not reached
+ startfs();
+
+ if(initstr)
+ proccreate(initcmd, initstr, mainstacksize);
+
+ threadnotify(notehandler, 1);
}
--- a/text.c
+++ b/text.c
@@ -8,9 +8,11 @@
};
void
-xinit(Text *x, Rectangle textr, Rectangle scrollr, Font *ft, Image *b, Image **cols)
+xinit(Text *x, Rectangle textr, Rectangle scrollr, int tabwidth, Font *ft, Image *b, Image **cols)
{
+ frclear(x, FALSE);
frinit(x, textr, ft, b, cols);
+ x->maxtab = x->maxtab/8*tabwidth;
x->i = b;
x->scrollr = scrollr;
x->lastsr = ZR;
@@ -111,6 +113,7 @@
w->org += n;
else if(q0 <= w->org+w->nchars)
frinsert(w, r, r+n, q0-w->org);
+ xscrdraw(w);
return q0;
}
@@ -271,29 +274,6 @@
* Scrolling
*/
-static Image *scrtmp;
-
-static Image*
-scrtemps(void)
-{
- int h;
-
- if(scrtmp == nil){
- h = BIG*Dy(screen->r);
- scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DNofill);
- }
- return scrtmp;
-}
-
-void
-freescrtemps(void)
-{
- if(scrtmp){
- freeimage(scrtmp);
- scrtmp = nil;
- }
-}
-
static Rectangle
scrpos(Rectangle r, uint p0, uint p1, uint tot)
{
@@ -325,27 +305,17 @@
void
xscrdraw(Text *w)
{
- Rectangle r, r1, r2;
- Image *b;
+ Rectangle r1, r2;
- b = scrtemps();
- if(b == nil || w->i == nil)
+ if(w->i == nil)
return;
- r = w->scrollr;
- r1 = r;
- r1.min.x = 0;
- r1.max.x = Dx(r);
+
+ r1 = w->scrollr;
r2 = scrpos(r1, w->org, w->org+w->nchars, w->nr);
if(!eqrect(r2, w->lastsr)){
w->lastsr = r2;
- /* move r1, r2 to (0,0) to avoid clipping */
- r2 = rectsubpt(r2, r1.min);
- r1 = rectsubpt(r1, r1.min);
- draw(b, r1, w->cols[BORD], nil, ZP);
- draw(b, r2, w->cols[BACK], nil, ZP);
- r2.min.x = r2.max.x-1;
- draw(b, r2, w->cols[BORD], nil, ZP);
- draw(w->i, r, b, nil, Pt(0, r1.min.y));
+ draw(w->i, r1, w->cols[BORD], nil, ZP);
+ draw(w->i, insetrect(r2,1), w->cols[BACK], nil, ZP);
}
}
@@ -468,30 +438,6 @@
xsetorigin(x, q0, TRUE);
}
-/* move tick up or down while staying at the same x position */
-void
-xtickupdn(Text *x, int d)
-{
- Point p;
- int py;
- uint q0;
-
- xshow(x, x->q0);
- p = frptofchar(x, x->q0-x->org);
- if(x->posx >= 0)
- p.x = x->posx;
- py = p.y;
- p.y += d*x->font->height;
- if(p.y < x->Frame.r.min.y ||
- p.y > x->Frame.r.max.y-x->font->height){
- xscrolln(x, d);
- p.y = py;
- }
- q0 = x->org+frcharofpt(x, p);
- xsetselect(x, q0, q0);
- x->posx = p.x;
-}
-
static Text *selecttext;
static Mousectl *selectmc;
static uint selectq;
@@ -531,7 +477,7 @@
int
iswordrune(Rune r)
{
- return isalpharune(r) || isdigitrune(r);
+ return r == '_' || isalpharune(r) || isdigitrune(r);
}
static int
--- a/wctl.c
+++ b/wctl.c
@@ -87,10 +87,10 @@
while(*s!='\0' && !isspacerune(*s))
s++;
for(i=0; tab[i]!=nil; i++)
- if(strncmp(tab[i], t, strlen(tab[i])) == 0){
+ if(s-t > 0 && strncmp(tab[i], t, s-t) == 0){
*sp = s;
return i;
- }
+ }
return -1;
}
--- a/wind.c
+++ b/wind.c
@@ -76,11 +76,20 @@
w->text.cols[TEXT] = colors[c];
}
+/* get rid of the window visually */
static void
+wremove(Window *w)
+{
+ if(w->img)
+ originwindow(w->img, w->img->r.min, screen->r.max);
+}
+
+static void
wsetsize(Window *w, Rectangle r)
{
Rectangle hr;
+ wremove(w);
if(w->img)
freeimage(w->img);
if(w->hidden){
@@ -89,9 +98,10 @@
originwindow(w->img, r.min, hr.min);
}else
w->img = allocwindow(wscreen, r, Refbackup, DNofill);
+ w->mc.image = w->img;
wcalcrects(w);
draw(w->img, w->img->r, colors[BACK], nil, ZP);
- xinit(&w->text, w->textr, w->scrollr, font, w->img, colors);
+ xinit(&w->text, w->textr, w->scrollr, tabwidth, font, w->img, colors);
}
static int id = 1;
@@ -117,7 +127,6 @@
windows[nwindows++] = w;
w->mc.c = chancreate(sizeof(Mouse), 16);
-
w->gone = chancreate(sizeof(int), 0);
w->kbd = chancreate(sizeof(char*), 16);
w->ctl = chancreate(sizeof(int), 0);
@@ -175,12 +184,10 @@
memmove(&windows[i], &windows[i+1], (nwindows-i)*sizeof(Window*));
break;
}
- if(w->img){
- /* rio does this, not sure if useful */
- originwindow(w->img, w->img->r.min, screen->r.max);
+ if(w->img)
freeimage(w->img);
- }
w->img = nil;
+ w->mc.image = nil;
flushimage(display, 1);
}
@@ -198,11 +205,12 @@
/* increment ref count temporarily
* so win thread doesn't exit too early */
incref(w);
+ wremove(w);
wunfocus(w);
wclose(w);
+ decref(w);
if(!inwinthread(w))
wsendmsg(w, Wakeup);
- decref(w);
}else
assert(w->ref > 0);
}
@@ -294,6 +302,7 @@
void
wdelete(Window *w)
{
+ wremove(w);
wunfocus(w);
wsendmsg(w, Deleted);
}
@@ -416,10 +425,10 @@
if(w->hidden)
return -1;
incref(w);
+ wremove(w);
wunfocus(w);
w->hidden = TRUE;
w->wctlready = TRUE;
- originwindow(w->img, w->img->r.min, screen->r.max);
wsendmsg(w, Wakeup);
wrelease(w);
return 1;
@@ -959,7 +968,7 @@
break;
case AComplete:
- if(w->img!=nil){
+ if(w->img){
if(!comp->advance)
showcandidates(w, comp);
if(comp->advance){