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 w->autoindent = globalautoindent;
92 /* make new window, if necessary; return with it locked */
94 errorwin(Mntdir *md, int owner)
100 w = errorwin1(nil, 0, nil, 0);
102 w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
106 /* window was deleted too fast */
113 * Incoming window should be locked.
114 * It will be unlocked and returned window
115 * will be locked in its place.
118 errorwinforwin(Window *w)
120 int i, n, nincl, owner;
126 dir = dirname(t, nil, 0);
127 if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
135 incl = emalloc(nincl*sizeof(Rune*));
136 for(i=0; i<nincl; i++){
137 n = runestrlen(w->incl[i]);
138 incl[i] = runemalloc(n+1);
139 runemove(incl[i], w->incl[i], n);
145 w = errorwin1(dir.r, dir.nr, incl, nincl);
149 /* window deleted too fast */
155 typedef struct Warning Warning;
163 static Warning *warnings;
167 addwarningtext(Mntdir *md, Rune *r, int nr)
171 for(warn = warnings; warn; warn=warn->next){
173 bufinsert(&warn->buf, warn->buf.nc, r, nr);
177 warn = emalloc(sizeof(Warning));
178 warn->next = warnings;
183 bufinsert(&warn->buf, 0, r, nr);
187 /* called while row is locked */
191 Warning *warn, *next;
194 int owner, nr, q0, n;
197 for(warn=warnings; warn; warn=next) {
198 w = errorwin(warn->md, 'E');
205 * Most commands don't generate much output. For instance,
206 * Edit ,>cat goes through /dev/cons and is already in blocks
207 * because of the i/o system, but a few can. Edit ,p will
208 * put the entire result into a single hunk. So it's worth doing
209 * this in blocks (and putting the text in a buffer in the first
210 * place), to avoid a big memory footprint.
214 for(n = 0; n < warn->buf.nc; n += nr){
215 nr = warn->buf.nc - n;
218 bufread(&warn->buf, n, r, nr);
219 textbsinsert(t, t->file->nc, r, nr, TRUE, &nr);
221 textshow(t, q0, t->file->nc, 1);
228 bufclose(&warn->buf);
238 warning(Mntdir *md, char *s, ...)
244 r = runevsmprint(s, arg);
247 error("runevsmprint failed");
248 addwarningtext(md, r, runestrlen(r));
253 runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
257 return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
277 runetobyte(Rune *r, int n)
283 s = emalloc(n*UTFmax+1);
284 setmalloctag(s, getcallerpc(&r));
285 snprint(s, n*UTFmax+1, "%.*S", n, r);
290 bytetorune(char *s, int *ip)
296 r = runemalloc(nb+1);
297 cvttorunes(s, nb, r, &nb, &nr, nil);
307 * Hard to get absolutely right. Use what we know about ASCII
308 * and assume anything above the Latin control characters is
309 * potentially an alphanumeric.
311 * Treat 0xA0 (non-breaking space) as a special alphanumeric
316 if(0x7F<=c && c<0xA0)
318 if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
324 rgetc(void *v, uint n)
326 return ((Rune*)v)[n];
330 tgetc(void *a, uint n)
337 return textreadc(t, n);
341 skipbl(Rune *r, int n, int *np)
343 while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
352 findbl(Rune *r, int n, int *np)
354 while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
365 prevmouse = mouse->xy;
370 restoremouse(Window *w)
372 if(mousew!=nil && mousew==w)
373 moveto(mousectl, prevmouse);
390 error("strdup failed");
391 setmalloctag(t, getcallerpc(&s));
402 error("malloc failed");
403 setmalloctag(p, getcallerpc(&n));
409 erealloc(void *p, uint n)
413 error("realloc failed");
414 setmalloctag(p, getcallerpc(&n));
422 makenewwindow(Text *t)
425 Window *w, *bigw, *emptyw;
431 else if(seltext && seltext->col)
436 if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
437 error("can't make column");
438 c = row.col[row.ncol-1];
441 if(t==nil || t->w==nil || c->nw==0)
442 return coladd(c, nil, nil, -1);
444 /* find biggest window and biggest blank spot */
447 for(i=1; i<c->nw; i++){
449 /* use >= to choose one near bottom of screen */
450 if(w->body.maxlines >= bigw->body.maxlines)
452 if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines)
455 emptyb = &emptyw->body;
456 el = emptyb->maxlines-emptyb->nlines;
457 /* if empty space is big, use it */
458 if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2))
459 y = emptyb->r.min.y+emptyb->nlines*font->height;
461 /* if this window is in column and isn't much smaller, split it */
462 if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
464 y = (bigw->r.min.y + bigw->r.max.y)/2;
466 w = coladd(c, nil, nil, y);
467 if(w->body.maxlines < 2)
468 colgrow(w->col, w, 1);