Esempio n. 1
0
void
textshow(Text *t, uint q0, uint q1, int doselect)
{
	int qe;
	int nl;
	uint q;

	if(t->what != Body){
		if(doselect)
			textsetselect(t, q0, q1);
		return;
	}
	if(t->w!=nil && t->maxlines==0)
		colgrow(t->col, t->w, 1);
	if(doselect)
		textsetselect(t, q0, q1);
	qe = t->org+t->nchars;
	if(t->org<=q0 && (q0<qe || (q0==qe && qe==t->file->nc+t->ncache)))
		textscrdraw(t);
	else{
		if(t->w->nopen[QWevent] > 0)
			nl = 3*t->maxlines/4;
		else
			nl = t->maxlines/4;
		q = textbacknl(t, q0, nl);
		/* avoid going backwards if trying to go forwards - long lines! */
		if(!(q0>t->org && q<t->org))
			textsetorigin(t, q, TRUE);
		while(q0 > t->org+t->nchars)
			textsetorigin(t, t->org+1, FALSE);
	}
}
Esempio n. 2
0
/*
 * Heuristic city.
 */
Window*
makenewwindow(Text *t)
{
	Column *c;
	Window *w, *bigw, *emptyw;
	Text *emptyb;
	int i, y, el;

	if(activecol)
		c = activecol;
	else if(seltext && seltext->col)
		c = seltext->col;
	else if(t && t->col)
		c = t->col;
	else{
		if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
			error("can't make column");
		c = row.col[row.ncol-1];
	}
	activecol = c;
	if(t==nil || t->w==nil || c->nw==0)
		return coladd(c, nil, nil, -1);

	/* find biggest window and biggest blank spot */
	emptyw = c->w[0];
	bigw = emptyw;
	for(i=1; i<c->nw; i++){
		w = c->w[i];
		/* use >= to choose one near bottom of screen */
		if(w->body.maxlines >= bigw->body.maxlines)
			bigw = w;
		if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines)
			emptyw = w;
	}
	emptyb = &emptyw->body;
	el = emptyb->maxlines-emptyb->nlines;
	/* if empty space is big, use it */
	if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2))
		y = emptyb->r.min.y+emptyb->nlines*font->height;
	else{
		/* if this window is in column and isn't much smaller, split it */
		if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)
			bigw = t->w;
		y = (bigw->r.min.y + bigw->r.max.y)/2;
	}
	w = coladd(c, nil, nil, y);
	if(w->body.maxlines < 2)
		colgrow(w->col, w, 1);
	return w;
}
Esempio n. 3
0
void
colclose(Column *c, Window *w, int dofree)
{
	Rectangle r;
	int i, didmouse, up;

	/* w is locked */
	if(!c->safe)
		colgrow(c, w, 1);
	for(i=0; i<c->nw; i++)
		if(c->w[i] == w)
			goto Found;
	error("can't find window");
  Found:
	r = w->r;
	w->tag.col = nil;
	w->body.col = nil;
	w->col = nil;
	didmouse = restoremouse(w);
	if(dofree){
		windelete(w);
		winclose(w);
	}
	c->nw--;
	memmove(c->w+i, c->w+i+1, (c->nw-i)*sizeof(Window*));
	c->w = realloc(c->w, c->nw*sizeof(Window*));
	if(c->nw == 0){
		draw(screen, r, display->white, nil, ZP);
		return;
	}
	up = 0;
	if(i == c->nw){		/* extend last window down */
		w = c->w[i-1];
		r.min.y = w->r.min.y;
		r.max.y = c->r.max.y;
	}else{			/* extend next window up */
		up = 1;
		w = c->w[i];
		r.max.y = w->r.max.y;
	}
	draw(screen, r, textcols[BACK], nil, ZP);
	if(c->safe) {
		if(!didmouse && up)
			w->showdel = TRUE;
		winresize(w, r, FALSE, TRUE);
		if(!didmouse && up)
			movetodel(w);
	}
}
Esempio n. 4
0
/*
 * Heuristic city.
 */
Window*
makenewwindow(Page *p)
{
    Column *c;
    Window *w, *bigw, *emptyw;
    Page *emptyp;
    int i, y, el;

    if(activecol)
        c = activecol;
    else if(selpage && selpage->col)
        c = selpage->col;
    else if(p && p->col)
        c = p->col;
    else {
        if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
            error("can't make column");
        c = row.col[row.ncol-1];
    }
    activecol = c;
    if(p==nil || p->w==nil || c->nw==0)
        return coladd(c, nil, nil, -1);

    /* find biggest window and biggest blank spot */
    emptyw = c->w[0];
    bigw = emptyw;
    for(i=1; i<c->nw; i++) {
        w = c->w[i];
        /* use >= to choose one near bottom of screen */
        if(Dy(w->page.all) >= Dy(bigw->page.all))
            bigw = w;
        if(w->page.lay==nil && Dy(w->page.all) >= Dy(emptyw->page.all))
            emptyw = w;
    }
    emptyp = &emptyw->page;
    el = Dy(emptyp->all);
    /* if empty space is big, use it */
    if(el>15 || (el>3 && el>(Dy(bigw->page.all)-1)/2))
        y = emptyp->all.max.y;
    else {
        /* if this window is in column and isn't much smaller, split it */
        if(p->col==c && Dy(p->w->r)>2*Dy(bigw->r)/3)
            bigw = p->w;
        y = (bigw->r.min.y + bigw->r.max.y)/2;
    }
    w = coladd(c, nil, nil, y);
    colgrow(w->col, w, 1);
    return w;
}
Esempio n. 5
0
void
textshow(Text *t, uint q0, uint q1, int doselect)
{
	int qe;
	int nl;
	int tsd;
	int nc;
	uint q;

	if(t->what != Body){
		if(doselect)
			textsetselect(t, q0, q1);
		return;
	}
	if(t->w!=nil && t->fr.maxlines==0)
		colgrow(t->col, t->w, 1);
	if(doselect)
		textsetselect(t, q0, q1);
	qe = t->org+t->fr.nchars;
	tsd = FALSE;	/* do we call textscrdraw? */
	nc = t->file->b.nc+t->ncache;
	if(t->org <= q0){
		if(nc==0 || q0<qe)
			tsd = TRUE;
		else if(q0==qe && qe==nc){
			if(textreadc(t, nc-1) == '\n'){
				if(t->fr.nlines<t->fr.maxlines)
					tsd = TRUE;
			}else
				tsd = TRUE;
		}
	}
	if(tsd)
		textscrdraw(t);
	else{
		if(t->w->nopen[QWevent] > 0)
			nl = 3*t->fr.maxlines/4;
		else
			nl = t->fr.maxlines/4;
		q = textbacknl(t, q0, nl);
		/* avoid going backwards if trying to go forwards - long lines! */
		if(!(q0>t->org && q<t->org))
			textsetorigin(t, q, TRUE);
		while(q0 > t->org+t->fr.nchars)
			textsetorigin(t, t->org+1, FALSE);
	}
}
Esempio n. 6
0
Window*
coladd(Column *c, Window *w, Window *clone, int y)
{
	Rectangle r, r1;
	Window *v;
	int i, t;

	v = nil;
	r = c->r;
	r.min.y = c->tag.r.max.y+Border;
	if(y<r.min.y && c->nw>0){	/* steal half of last window by default */
		v = c->w[c->nw-1];
		y = v->body.r.min.y+Dy(v->body.r)/2;
	}
	/* look for window we'll land on */
	for(i=0; i<c->nw; i++){
		v = c->w[i];
		if(y < v->r.max.y)
			break;
	}
	if(c->nw > 0){
		if(i < c->nw)
			i++;	/* new window will go after v */
		/*
		 * if v's too small, grow it first.
		 */
		if(!c->safe || v->body.maxlines<=3){
			colgrow(c, v, 1);
			y = v->body.r.min.y+Dy(v->body.r)/2;
		}
		r = v->r;
		if(i == c->nw)
			t = c->r.max.y;
		else
			t = c->w[i]->r.min.y-Border;
		r.max.y = t;
		draw(screen, r, textcols[BACK], nil, ZP);
		r1 = r;
		y = min(y, t-(v->tag.font->height+v->body.font->height+Border+1));
		r1.max.y = min(y, v->body.r.min.y+v->body.nlines*v->body.font->height);
		r1.min.y = winresize(v, r1, FALSE);
		r1.max.y = r1.min.y+Border;
		draw(screen, r1, display->black, nil, ZP);
		r.min.y = r1.max.y;
	}
	if(w == nil){
		w = emalloc(sizeof(Window));
		w->col = c;
		draw(screen, r, textcols[BACK], nil, ZP);
		wininit(w, clone, r);
	}else{
		w->col = c;
		winresize(w, r, FALSE);
	}
	w->tag.col = c;
	w->tag.row = c->row;
	w->body.col = c;
	w->body.row = c->row;
	c->w = realloc(c->w, (c->nw+1)*sizeof(Window*));
	memmove(c->w+i+1, c->w+i, (c->nw-i)*sizeof(Window*));
	c->nw++;
	c->w[i] = w;
	savemouse(w);
	/* near but not on the button */
	moveto(mousectl, addpt(w->tag.scrollr.max, Pt(3, 3)));
	barttext = &w->body;
	c->safe = TRUE;
	return w;
}
Esempio n. 7
0
void
coldragwin(Column *c, Window *w, int but)
{
	Rectangle r;
	int i, b;
	Point p, op;
	Window *v;
	Column *nc;

	clearmouse();
	setcursor(mousectl, &boxcursor);
	b = mouse->buttons;
	op = mouse->xy;
	while(mouse->buttons == b)
		readmouse(mousectl);
	setcursor(mousectl, nil);
	if(mouse->buttons){
		while(mouse->buttons)
			readmouse(mousectl);
		return;
	}

	for(i=0; i<c->nw; i++)
		if(c->w[i] == w)
			goto Found;
	error("can't find window");

  Found:
	p = mouse->xy;
	if(abs(p.x-op.x)<5 && abs(p.y-op.y)<5){
		colgrow(c, w, but);
		winmousebut(w);
		return;
	}
	/* is it a flick to the right? */
	if(abs(p.y-op.y)<10 && p.x>op.x+30 && rowwhichcol(c->row, p)==c)
		p.x = op.x+Dx(w->r);	/* yes: toss to next column */
	nc = rowwhichcol(c->row, p);
	if(nc!=nil && nc!=c){
		colclose(c, w, FALSE);
		coladd(nc, w, nil, p.y);
		winmousebut(w);
		return;
	}
	if(i==0 && c->nw==1)
		return;			/* can't do it */
	if((i>0 && p.y<c->w[i-1]->r.min.y) || (i<c->nw-1 && p.y>w->r.max.y)
	|| (i==0 && p.y>w->r.max.y)){
		/* shuffle */
		colclose(c, w, FALSE);
		coladd(c, w, nil, p.y);
		winmousebut(w);
		return;
	}
	if(i == 0)
		return;
	v = c->w[i-1];
	if(p.y < v->tag.all.max.y)
		p.y = v->tag.all.max.y;
	if(p.y > w->r.max.y-Dy(w->tag.all)-Border)
		p.y = w->r.max.y-Dy(w->tag.all)-Border;
	r = v->r;
	r.max.y = p.y;
	if(r.max.y > v->body.r.min.y){
		r.max.y -= (r.max.y-v->body.r.min.y)%v->body.font->height;
		if(v->body.r.min.y == v->body.r.max.y)
			r.max.y++;
	}
	if(!eqrect(v->r, r)){
		draw(screen, r, textcols[BACK], nil, ZP);
		winresize(v, r, c->safe);
	}
	r.min.y = v->r.max.y;
	r.max.y = r.min.y+Border;
	draw(screen, r, display->black, nil, ZP);
	r.min.y = r.max.y;
	if(i == c->nw-1)
		r.max.y = c->r.max.y;
	else
		r.max.y = c->w[i+1]->r.min.y-Border;
	if(!eqrect(w->r, r)){
		draw(screen, r, textcols[BACK], nil, ZP);
		winresize(w, r, c->safe);
	}
	c->safe = TRUE;
    	winmousebut(w);
}
Esempio n. 8
0
Window*
coladd(Column *c, Window *w, Window *clone, int y)
{
	Rectangle r, r1;
	Window *v;
	int i, j, minht, ymax, buggered;

	v = nil;
	r = c->r;
	r.min.y = c->tag.fr.r.max.y+Border;
	if(y<r.min.y && c->nw>0){	/* steal half of last window by default */
		v = c->w[c->nw-1];
		y = v->body.fr.r.min.y+Dy(v->body.fr.r)/2;
	}
	/* look for window we'll land on */
	for(i=0; i<c->nw; i++){
		v = c->w[i];
		if(y < v->r.max.y)
			break;
	}
	buggered = 0;
	if(c->nw > 0){
		if(i < c->nw)
			i++;	/* new window will go after v */
		/*
		 * if landing window (v) is too small, grow it first.
		 */
		minht = v->tag.fr.font->height+Border+1;
		j = 0;
		while(!c->safe || v->body.fr.maxlines<=3 || Dy(v->body.all) <= minht){
			if(++j > 10){
				buggered = 1;	/* too many windows in column */
				break;
			}
			colgrow(c, v, 1);
		}

		/*
		 * figure out where to split v to make room for w
		 */
		
		/* new window stops where next window begins */
		if(i < c->nw)
			ymax = c->w[i]->r.min.y-Border;
		else
			ymax = c->r.max.y;
		
		/* new window must start after v's tag ends */
		y = max(y, v->tagtop.max.y+Border);
		
		/* new window must start early enough to end before ymax */
		y = min(y, ymax - minht);
		
		/* if y is too small, too many windows in column */
		if(y < v->tagtop.max.y+Border)
			buggered = 1;

		/*
		 * resize & redraw v
		 */
		r = v->r;
		r.max.y = ymax;
		draw(screen, r, textcols[BACK], nil, ZP);
		r1 = r;
		y = min(y, ymax-(v->tag.fr.font->height*v->taglines+v->body.fr.font->height+Border+1));
		r1.max.y = min(y, v->body.fr.r.min.y+v->body.fr.nlines*v->body.fr.font->height);
		r1.min.y = winresize(v, r1, FALSE, FALSE);
		r1.max.y = r1.min.y+Border;
		draw(screen, r1, display->black, nil, ZP);
		
		/*
		 * leave r with w's coordinates
		 */
		r.min.y = r1.max.y;
	}
	if(w == nil){
		w = emalloc(sizeof(Window));
		w->col = c;
		draw(screen, r, textcols[BACK], nil, ZP);
		wininit(w, clone, r);
	}else{
		w->col = c;
		winresize(w, r, FALSE, TRUE);
	}
	w->tag.col = c;
	w->tag.row = c->row;
	w->body.col = c;
	w->body.row = c->row;
	c->w = realloc(c->w, (c->nw+1)*sizeof(Window*));
	memmove(c->w+i+1, c->w+i, (c->nw-i)*sizeof(Window*));
	c->nw++;
	c->w[i] = w;
	c->safe = TRUE;
	
	/* if there were too many windows, redraw the whole column */
	if(buggered)
		colresize(c, c->r);

	savemouse(w);
	/* near the button, but in the body */
	moveto(mousectl, addpt(w->tag.scrollr.max, Pt(3, 3)));
	barttext = &w->body;
	return w;
}
Esempio n. 9
0
Window*
openfile(Text *t, Expand *e)
{
	Range r;
	Window *w, *ow;
	int eval, i, n;
	Rune *rp;
	Runestr rs;
	uint dummy;

	r.q0 = 0;
	r.q1 = 0;
	if(e->nname == 0){
		w = t->w;
		if(w == nil)
			return nil;
	}else{
		w = lookfile(e->name, e->nname);
		if(w == nil && e->name[0] != '/'){
			/*
			 * Unrooted path in new window.
			 * This can happen if we type a pwd-relative path
			 * in the topmost tag or the column tags.  
			 * Most of the time plumber takes care of these,
			 * but plumber might not be running or might not
			 * be configured to accept plumbed directories.
			 * Make the name a full path, just like we would if
			 * opening via the plumber.
			 */
			n = utflen(wdir)+1+e->nname+1;
			rp = runemalloc(n);
			runesnprint(rp, n, "%s/%.*S", wdir, e->nname, e->name);
			rs = cleanrname(runestr(rp, n-1));
			free(e->name);
			e->name = rs.r;
			e->nname = rs.nr;
			w = lookfile(e->name, e->nname);
		}
	}
	if(w){
		t = &w->body;
		if(!t->col->safe && t->fr.maxlines==0) /* window is obscured by full-column window */
			colgrow(t->col, t->col->w[0], 1);
	}else{
		ow = nil;
		if(t)
			ow = t->w;
		w = makenewwindow(t);
		t = &w->body;
		winsetname(w, e->name, e->nname);
		if(textload(t, 0, e->bname, 1) >= 0)
			t->file->unread = FALSE;
		t->file->mod = FALSE;
		t->w->dirty = FALSE;
		winsettag(t->w);
		textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc);
		if(ow != nil){
			for(i=ow->nincl; --i>=0; ){
				n = runestrlen(ow->incl[i]);
				rp = runemalloc(n);
				runemove(rp, ow->incl[i], n);
				winaddincl(w, rp, n);
			}
			w->autoindent = ow->autoindent;
		}else
			w->autoindent = globalautoindent;
		xfidlog(w, "new");
	}
	if(e->a1 == e->a0)
		eval = FALSE;
	else{
		eval = TRUE;
		r = address(TRUE, t, range(-1,-1), range(t->q0, t->q1), e->u.at, e->a0, e->a1, e->agetc, &eval, &dummy);
		if(r.q0 > r.q1) {
			eval = FALSE;
			warning(nil, "addresses out of order\n");
		}
		if(eval == FALSE)
			e->jump = FALSE;	/* don't jump if invalid address */
	}
	if(eval == FALSE){
		r.q0 = t->q0;
		r.q1 = t->q1;
	}
	textshow(t, r.q0, r.q1, 1);
	winsettag(t->w);
	seltext = t;
	if(e->jump)
		moveto(mousectl, addpt(frptofchar(&t->fr, t->fr.p0), Pt(4, font->height-4)));
	return w;
}