14 static Point prevmouse;
15 static Window *mousew;
28 runestr(Rune *r, uint n)
38 cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
45 * Always guaranteed that n bytes may be interpreted
46 * without worrying about partial runes. This may mean
47 * reading up to UTFmax-1 more bytes than n; the caller
48 * knows this. If n is a firm limit, the caller should
58 w = chartorune(s, (char*)q);
73 fprint(2, "acme: %s: %r\n", s);
78 errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
83 static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
85 r = runemalloc(ndir+8);
87 runemove(r, dir, ndir);
90 runemove(r+n, Lpluserrors, 7);
95 if(rowadd(&row, nil, -1) == nil)
96 error("can't create column to make error window");
97 w = coladd(row.col[row.ncol-1], nil, nil, -1);
102 for(i=nincl; --i>=0; ){
103 n = runestrlen(incl[i]);
105 runemove(r, incl[i], n);
108 w->autoindent = globalautoindent;
112 /* make new window, if necessary; return with it locked */
114 errorwin(Mntdir *md, int owner)
120 w = errorwin1(nil, 0, nil, 0);
122 w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
126 /* window was deleted too fast */
133 * Incoming window should be locked.
134 * It will be unlocked and returned window
135 * will be locked in its place.
138 errorwinforwin(Window *w)
140 int i, n, nincl, owner;
146 dir = dirname(t, nil, 0);
147 if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
155 incl = emalloc(nincl*sizeof(Rune*));
156 for(i=0; i<nincl; i++){
157 n = runestrlen(w->incl[i]);
158 incl[i] = runemalloc(n+1);
159 runemove(incl[i], w->incl[i], n);
165 w = errorwin1(dir.r, dir.nr, incl, nincl);
169 /* window deleted too fast */
175 typedef struct Warning Warning;
183 static Warning *warnings;
187 addwarningtext(Mntdir *md, Rune *r, int nr)
191 for(warn = warnings; warn; warn=warn->next){
193 bufinsert(&warn->buf, warn->buf.nc, r, nr);
197 warn = emalloc(sizeof(Warning));
198 warn->next = warnings;
203 bufinsert(&warn->buf, 0, r, nr);
207 /* called while row is locked */
211 Warning *warn, *next;
214 int owner, nr, q0, n;
217 for(warn=warnings; warn; warn=next) {
218 w = errorwin(warn->md, 'E');
225 * Most commands don't generate much output. For instance,
226 * Edit ,>cat goes through /dev/cons and is already in blocks
227 * because of the i/o system, but a few can. Edit ,p will
228 * put the entire result into a single hunk. So it's worth doing
229 * this in blocks (and putting the text in a buffer in the first
230 * place), to avoid a big memory footprint.
234 for(n = 0; n < warn->buf.nc; n += nr){
235 nr = warn->buf.nc - n;
238 bufread(&warn->buf, n, r, nr);
239 textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
241 textshow(t, q0, t->file->b.nc, 1);
248 bufclose(&warn->buf);
258 warning(Mntdir *md, char *s, ...)
264 r = runevsmprint(s, arg);
267 error("runevsmprint failed");
268 addwarningtext(md, r, runestrlen(r));
273 runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
277 return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
297 runetobyte(Rune *r, int n)
303 s = emalloc(n*UTFmax+1);
304 setmalloctag(s, getcallerpc(&r));
305 snprint(s, n*UTFmax+1, "%.*S", n, r);
310 bytetorune(char *s, int *ip)
316 r = runemalloc(nb+1);
317 cvttorunes(s, nb, r, &nb, &nr, nil);
327 * Hard to get absolutely right. Use what we know about ASCII
328 * and assume anything above the Latin control characters is
329 * potentially an alphanumeric.
333 if(0x7F<=c && c<=0xA0)
335 if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
341 rgetc(void *v, uint n)
343 return ((Rune*)v)[n];
347 tgetc(void *a, uint n)
352 if(n >= t->file->b.nc)
354 return textreadc(t, n);
358 skipbl(Rune *r, int n, int *np)
360 while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
369 findbl(Rune *r, int n, int *np)
371 while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
382 prevmouse = mouse->xy;
387 restoremouse(Window *w)
389 if(mousew!=nil && mousew==w)
390 moveto(mousectl, prevmouse);
407 error("strdup failed");
408 setmalloctag(t, getcallerpc(&s));
419 fprint(2, "allocating %d from %lux: %r\n", n, getcallerpc(&n));
421 error("malloc failed");
423 setmalloctag(p, getcallerpc(&n));
429 erealloc(void *p, uint n)
433 fprint(2, "reallocating %d: %r\n", n);
434 error("realloc failed");
436 setmalloctag(p, getcallerpc(&n));
444 makenewwindow(Text *t)
447 Window *w, *bigw, *emptyw;
453 else if(seltext && seltext->col)
458 if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
459 error("can't make column");
460 c = row.col[row.ncol-1];
463 if(t==nil || t->w==nil || c->nw==0)
464 return coladd(c, nil, nil, -1);
466 /* find biggest window and biggest blank spot */
469 for(i=1; i<c->nw; i++){
471 /* use >= to choose one near bottom of screen */
472 if(w->body.fr.maxlines >= bigw->body.fr.maxlines)
474 if(w->body.fr.maxlines-w->body.fr.nlines >= emptyw->body.fr.maxlines-emptyw->body.fr.nlines)
477 emptyb = &emptyw->body;
478 el = emptyb->fr.maxlines-emptyb->fr.nlines;
479 /* if empty space is big, use it */
480 if(el>15 || (el>3 && el>(bigw->body.fr.maxlines-1)/2))
481 y = emptyb->fr.r.min.y+emptyb->fr.nlines*font->height;
483 /* if this window is in column and isn't much smaller, split it */
484 if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
486 y = (bigw->r.min.y + bigw->r.max.y)/2;
488 w = coladd(c, nil, nil, y);
489 if(w->body.fr.maxlines < 2)
490 colgrow(w->col, w, 1);