14 static Point prevmouse;
15 static Window *mousew;
18 cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
25 * Always guaranteed that n bytes may be interpreted
26 * without worrying about partial runes. This may mean
27 * reading up to UTFmax-1 more bytes than n; the caller
28 * knows this. If n is a firm limit, the caller should
38 w = chartorune(s, (char*)q);
53 fprint(2, "acme: %s: %r\n", s);
54 remove(acmeerrorfile);
59 errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
65 r = runemalloc(ndir+8);
66 if(n = ndir){ /* assign = */
67 runemove(r, dir, ndir);
70 runemove(r+n, L"+Errors", 7);
75 if(rowadd(&row, nil, -1) == nil)
76 error("can't create column to make error window");
77 w = coladd(row.col[row.ncol-1], nil, nil, -1);
82 for(i=nincl; --i>=0; ){
83 n = runestrlen(incl[i]);
85 runemove(r, incl[i], n);
88 for(i=0; i<NINDENT; i++)
89 w->indent[i] = globalindent[i];
93 /* make new window, if necessary; return with it locked */
95 errorwin(Mntdir *md, int owner)
101 w = errorwin1(nil, 0, nil, 0);
103 w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
107 /* window was deleted too fast */
114 * Incoming window should be locked.
115 * It will be unlocked and returned window
116 * will be locked in its place.
119 errorwinforwin(Window *w)
121 int i, n, nincl, owner;
127 dir = dirname(t, nil, 0);
128 if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
136 incl = emalloc(nincl*sizeof(Rune*));
137 for(i=0; i<nincl; i++){
138 n = runestrlen(w->incl[i]);
139 incl[i] = runemalloc(n+1);
140 runemove(incl[i], w->incl[i], n);
146 w = errorwin1(dir.r, dir.nr, incl, nincl);
150 /* window deleted too fast */
156 typedef struct Warning Warning;
164 static Warning *warnings;
168 addwarningtext(Mntdir *md, Rune *r, int nr)
172 for(warn = warnings; warn; warn=warn->next){
174 bufinsert(&warn->buf, warn->buf.nc, r, nr);
178 warn = emalloc(sizeof(Warning));
179 warn->next = warnings;
184 bufinsert(&warn->buf, 0, r, nr);
188 /* called while row is locked */
192 Warning *warn, *next;
195 int owner, nr, q0, n;
198 for(warn=warnings; warn; warn=next) {
199 w = errorwin(warn->md, 'E');
206 * Most commands don't generate much output. For instance,
207 * Edit ,>cat goes through /dev/cons and is already in blocks
208 * because of the i/o system, but a few can. Edit ,p will
209 * put the entire result into a single hunk. So it's worth doing
210 * this in blocks (and putting the text in a buffer in the first
211 * place), to avoid a big memory footprint.
215 for(n = 0; n < warn->buf.nc; n += nr){
216 nr = warn->buf.nc - n;
219 bufread(&warn->buf, n, r, nr);
220 textbsinsert(t, t->file->nc, r, nr, TRUE, &nr);
222 textshow(t, q0, t->file->nc, 1);
229 bufclose(&warn->buf);
239 warning(Mntdir *md, char *s, ...)
245 r = runevsmprint(s, arg);
248 error("runevsmprint failed");
249 addwarningtext(md, r, runestrlen(r));
254 runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
258 return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
278 runetobyte(Rune *r, int n)
284 s = emalloc(n*UTFmax+1);
285 setmalloctag(s, getcallerpc(&r));
286 snprint(s, n*UTFmax+1, "%.*S", n, r);
291 bytetorune(char *s, int *ip)
297 r = runemalloc(nb+1);
298 cvttorunes(s, nb, r, &nb, &nr, nil);
308 * Hard to get absolutely right. Use what we know about ASCII
309 * and assume anything above the Latin control characters is
310 * potentially an alphanumeric.
312 * Treat 0xA0 (non-breaking space) as a special alphanumeric
317 if(0x7F<=c && c<0xA0)
319 if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
325 rgetc(void *v, uint n)
327 return ((Rune*)v)[n];
331 tgetc(void *a, uint n)
338 return textreadc(t, n);
342 skipbl(Rune *r, int n, int *np)
344 while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
353 findbl(Rune *r, int n, int *np)
355 while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
366 prevmouse = mouse->xy;
371 restoremouse(Window *w)
373 if(mousew!=nil && mousew==w)
374 moveto(mousectl, prevmouse);
391 error("strdup failed");
392 setmalloctag(t, getcallerpc(&s));
403 error("malloc failed");
404 setmalloctag(p, getcallerpc(&n));
410 erealloc(void *p, uint n)
414 error("realloc failed");
415 setmalloctag(p, getcallerpc(&n));
423 makenewwindow(Text *t)
426 Window *w, *bigw, *emptyw;
432 else if(seltext && seltext->col)
437 if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
438 error("can't make column");
439 c = row.col[row.ncol-1];
442 if(t==nil || t->w==nil || c->nw==0)
443 return coladd(c, nil, nil, -1);
445 /* find biggest window and biggest blank spot */
448 for(i=1; i<c->nw; i++){
450 /* use >= to choose one near bottom of screen */
451 if(w->body.maxlines >= bigw->body.maxlines)
453 if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines)
456 emptyb = &emptyw->body;
457 el = emptyb->maxlines-emptyb->nlines;
458 /* if empty space is big, use it */
459 if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2))
460 y = emptyb->r.min.y+emptyb->nlines*font->height;
462 /* if this window is in column and isn't much smaller, split it */
463 if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
465 y = (bigw->r.min.y + bigw->r.max.y)/2;
467 w = coladd(c, nil, nil, y);
468 if(w->body.maxlines < 2)
469 colgrow(w->col, w, 1);