Пример #1
0
int
vtfilesetsize(VtFile *r, u64int size)
{
	int depth, edepth;
	VtEntry e;
	VtBlock *b;

	assert(ISLOCKED(r));
	if(size == 0)
		return vtfiletruncate(r);

	if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize){
		werrstr(ETooBig);
		return -1;
	}

	b = fileload(r, &e);
	if(b == nil)
		return -1;

	/* quick out */
	if(e.size == size){
		vtblockput(b);
		return 0;
	}

	depth = sizetodepth(size, e.psize, e.dsize);
	edepth = DEPTH(e.type);
	if(depth < edepth){
		if(shrinkdepth(r, b, &e, depth) < 0){
			vtblockput(b);
			return -1;
		}
	}else if(depth > edepth){
		if(growdepth(r, b, &e, depth) < 0){
			vtblockput(b);
			return -1;
		}
	}

	if(size < e.size)
		shrinksize(r, &e, size);

	e.size = size;
	vtentrypack(&e, b->data, r->offset % r->epb);
	vtblockput(b);

	return 0;
}
Пример #2
0
/* of the final tree.                                           */
void CORD_balance_insert(CORD x, size_t len, ForestElement * forest)
{
    int depth;

    if (CORD_IS_STRING(x)) {
        CORD_add_forest(forest, x, len);
    } else if (IS_CONCATENATION(x)
               && ((depth = DEPTH(x)) >= MAX_DEPTH
                   || len < min_len[depth])) {
        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
        size_t left_len = LEFT_LEN(conc);

        CORD_balance_insert(conc -> left, left_len, forest);
        CORD_balance_insert(conc -> right, len - left_len, forest);
    } else /* function or balanced */ {
        CORD_add_forest(forest, x, len);
    }
}
Пример #3
0
/*
 * We need cnt more positions on this line.
 * Open up new space on the screen (this may in fact be a
 * screen rollup).
 *
 * On a dumb terminal we may infact redisplay the rest of the
 * screen here brute force to keep it pretty.
 */
void
vneedpos(int npcnt)
{
	register int d = DEPTH(vcline);
	register int rmdr = d * WCOLS - linend;

	/*
	 * Delete the showmode string on wraparound to last line. Cannot use
	 * vclrech() since the mode string is printed on the echo area, but
	 * not actually a part of it.
	 */
	if (value(SHOWMODE) && (value(REDRAW) || (IM && EI)) &&
			npcnt == rmdr - IN && LINE(vcline) + d == WECHO) {
		int sdc, sdl;
		char *ocurs;

		endim();
		sdc = destcol, sdl = destline, ocurs = cursor;
		splitw++;
		vgoto(WECHO, 0);
		if (CD) {
			vputp(CD, 1);
		} else if (CE) {
			vputp(CE, 1);
		} else {
			int i;

			for (i = 1; i < WCOLS; i++)
				vputchar(' ');
		}
		destcol = sdc, destline = sdl; cursor = ocurs;
		splitw = 0;
	}
	if (npcnt <= rmdr - IN)
		return;
	endim();
	vnpins(1);
}
Пример #4
0
/*
 * Workhorse for rearranging line descriptors on changes.
 * The idea here is that, starting with line l, cnt lines
 * have been replaced with newcnt lines.  All of these may
 * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
 * since we may be called from an undo after the screen has
 * moved a lot.  Thus we have to be careful.
 *
 * Many boundary conditions here.
 */
void 
vreplace(int l, int cnt, int newcnt)
{
	register int from, to, i;
	bool savenote = 0;

#ifdef ADEBUG
	if (trace) {
		tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
		tvliny();
	}
#endif
	if (l >= vcnt)
		return;
	if (l < 0) {
		if (l + cnt < 0) {
			/*
			 * Nothing on the screen is relevant.
			 * Settle for redrawing from scratch (later).
			 */
			vcnt = 0;
			return;
		}
		/*
		 * Normalize l to top of screen; the add is
		 * really a subtract from cnt since l is negative.
		 */
		cnt += l;
		l = 0;

		/*
		 * Unseen lines were affect so notify (later).
		 */
		savenote++;
	}

	/*
	 * These shouldn't happen
	 * but would cause great havoc.
	 */
	if (cnt < 0)
		cnt = 0;
	if (newcnt < 0)
		newcnt = 0;

	/*
	 * Surely worthy of note if more than report
	 * lines were changed.
	 */
	if (cnt > value(REPORT) || newcnt > value(REPORT))
		savenote++;

	/*
	 * Same number of lines affeted as on screen, and we
	 * can insert and delete lines.  Thus we just type
	 * over them, since otherwise we will push them
	 * slowly off the screen, a clear lose.
	 */
	if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
		if (cnt > 1 && l + cnt > vcnt)
			savenote++;
		vdirty(l, newcnt);
	} else {
		/*
		 * Lines are going away, squish them out.
		 */
		if (cnt > 0) {
			/*
			 * If non-displayed lines went away,
			 * always notify.
			 */
			if (cnt > 1 && l + cnt > vcnt)
				savenote++;
			if (l + cnt >= vcnt)
				cnt = vcnt - l;
			else
				for (from = l + cnt, to = l; from <= vcnt; to++, from++)
					vlcopy(vlinfo[to], vlinfo[from]);
			vcnt -= cnt;
		}
		/*
		 * Open up space for new lines appearing.
		 * All new lines are piled in the same place,
		 * and will be unpiled by vredraw/vsync, which
		 * inserts lines in front as it unpiles.
		 */
		if (newcnt > 0) {
			/*
			 * Newlines are appearing which may not show,
			 * so notify (this is only approximately correct
			 * when long lines are present).
			 */
			if (newcnt > 1 && l + newcnt > vcnt + 1)
				savenote++;

			/*
			 * If there will be more lines than fit, then
			 * just throw way the rest of the stuff on the screen.
			 */
			if (l + newcnt > WBOT && AL && DL) {
				vcnt = l;
				goto skip;
			}
			from = vcnt, to = vcnt + newcnt;
			i = TUBELINES - to;
			if (i < 0)
				from += i, to += i;
			vcnt = to;
			for (; from >= l; from--, to--)
				vlcopy(vlinfo[to], vlinfo[from]);
			for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
				LINE(to) = LINE(from);
				DEPTH(to) = 0;
				FLAGS(to) = VDIRT;
			}
		}
	}
skip:
	if (Pline == numbline && cnt != newcnt)
		/*
		 * When lines positions are shifted, the numbers
		 * will be wrong.
		 */
		vdirty(l, WECHO);
	if (!savenote)
		notecnt = 0;
#ifdef ADEBUG
	if (trace)
		tvliny();
#endif
}
Пример #5
0
/*
 * Fully cleanup the screen, leaving no @ lines except at end when
 * line after last won't completely fit.  The routine vsync is
 * more conservative and much less work on dumb terminals.
 */
void 
vredraw(register int p)
{
	register int l;
	register line *tp;
	char temp[LBSIZE];
	bool anydl = 0;
	short oldhold = hold;

#ifdef ADEBUG
	if (trace)
		tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
#endif
	if (holdupd) {
		holdupd = 3;
		return;
	}
	if (state == HARDOPEN || splitw)
		return;
	if (p < 0 /* || p > WECHO */)
		error(catgets(catd, 1, 221, "Internal error: vredraw"));

	/*
	 * Trim the ragged edges (lines which are off the screen but
	 * not yet logically discarded), save the current line, and
	 * search for first logical line affected by the redraw.
	 */
	vscrap();
	CP(temp, linebuf);
	l = 0;
	tp = dot - vcline;
	if (vcnt == 0)
		LINE(0) = WTOP;
	while (l < vcnt && LINE(l) < p)
		l++, tp++;

	/*
	 * We hold off echo area clearing during the redraw in deference
	 * to a final clear of the echo area at the end if appropriate.
	 */
	heldech = 0;
	hold |= HOLDECH;
	for (; l < vcnt && Peekkey != ATTN; l++) {
		if (l == vcline)
			strcLIN(temp);
		else
			getline(*tp);

		/*
		 * Delete junk between displayed lines.
		 */
		if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
			if (anydl == 0 && DB && CD) {
				hold = oldhold;
				vclrech(0);
				anydl = 1;
				hold |= HOLDECH;
				heldech = 0;
			}
			vdellin(p, LINE(l) - p, l);
		}

		/*
		 * If line image is not know to be up to date, then
		 * redisplay it;  else just skip onward.
		 */
		LINE(l) = p;
		if (FLAGS(l) & VDIRT) {
			DEPTH(l) = vdepth();
			if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
				vscrap();
				break;
			}
			FLAGS(l) &= ~VDIRT;
			vreopen(p, lineno(tp), l);
			p = LINE(l) + DEPTH(l);
		} else
			p += DEPTH(l);
		tp++;
	}

	/*
	 * That takes care of lines which were already partially displayed.
	 * Now try to fill the rest of the screen with text.
	 */
	if (state == VISUAL && p <= WBOT) {
		int ovcline = vcline;

		vcline = l;
		for (; tp <= dol && Peekkey != ATTN; tp++) {
			getline(*tp);
			if (p + vdepth() - 1 > WBOT)
				break;
			vopen(tp, p);
			p += DEPTH(vcline);
			vcline++;
		}
		vcline = ovcline;
	}

	/*
	 * Thats all the text we can get on.
	 * Now rest of lines (if any) get either a ~ if they
	 * are past end of file, or an @ if the next line won't fit.
	 */
	for (; p <= WBOT && Peekkey != ATTN; p++)			
		vclrlin(p, tp);
	strcLIN(temp);
	hold = oldhold;
	if (heldech)
		vclrech(0);
#ifdef ADEBUG
	if (trace)
		tvliny();
#endif
}
Пример #6
0
/*
 * Open new lines.
 *
 * Tricky thing here is slowopen.  This causes display updating
 * to be held off so that 300 baud dumb terminals don't lose badly.
 * This also suppressed counts, which otherwise say how many blank
 * space to open up.  Counts are also suppressed on intelligent terminals.
 * Actually counts are obsoleted, since if your terminal is slow
 * you are better off with slowopen.
 */
void 
voOpen (
    int c,	/* mjm: char --> int */
    register int cnt
)
{
	register int ind = 0, i;
	short oldhold = hold;
#ifdef	SIGWINCH
	sigset_t set, oset;
#endif

	if (value(SLOWOPEN) || value(REDRAW) && AL && DL)
		cnt = 1;
#ifdef	SIGWINCH
	sigemptyset(&set);
	sigaddset(&set, SIGWINCH);
	sigprocmask(SIG_BLOCK, &set, &oset);
#endif
	vsave();
	setLAST();
	if (value(AUTOINDENT))
		ind = whitecnt(linebuf);
	if (c == 'O') {
		vcline--;
		dot--;
		if (dot > zero)
			getDOT();
	}
	if (value(AUTOINDENT)) {
#ifdef LISPCODE
		if (value(LISP))
			ind = lindent(dot + 1);
#endif
	}
	killU();
	prepapp();
	if (FIXUNDO)
		vundkind = VMANY;
	if (state != VISUAL)
		c = WBOT + 1;
	else {
		c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
		if (c < ZERO)
			c = ZERO;
		i = LINE(vcline + 1) - c;
		if (i < cnt && c <= WBOT && (!AL || !DL))
			vinslin(c, cnt - i, vcline);
	}
	*genindent(ind) = 0;
	vdoappend(genbuf);
	vcline++;
	oldhold = hold;
	hold |= HOLDROL;
	vopen(dot, c);
	hold = oldhold;
	if (value(SLOWOPEN))
		/*
		 * Oh, so lazy!
		 */
		vscrap();
	else
		vsync1(LINE(vcline));
	cursor = linebuf;
	linebuf[0] = 0;
	vappend('o', 1, ind);
#ifdef	SIGWINCH
	sigprocmask(SIG_SETMASK, &oset, NULL);
#endif
}
Пример #7
0
/*
 * Now do the insert of the characters (finally).
 */
void
viin(int c)
/*	int c;		/\* mjm: char --> int */
{
	register cell *tp, *up;
	register int i, j;
	register bool noim = 0;
	int remdoom;
	short oldhold = hold;

	hold |= HOLDPUPD;
	if (tabsize && (IM && EI) && inssiz - doomed > tabslack)
		/*
		 * There is a tab out there which will be affected
		 * by the insertion since there aren't enough doomed
		 * characters to take up all the insertion and we do
		 * have insert mode capability.
		 */
		if (inscol + insmc0 + doomed == tabstart) {
			/*
			 * The end of the doomed characters sits right at the
			 * start of the tabs, then we don't need to use insert
			 * mode; unless the tab has already been expanded
			 * in which case we MUST use insert mode.
			 */
			slakused = 0;
			noim = !shft;
		} else {
			/*
			 * The last really special case to handle is case
			 * where the tab is just sitting there and doesn't
			 * have enough slack to let the insertion take
			 * place without shifting the rest of the line
			 * over.  In this case we have to go out and
			 * delete some characters of the tab before we start
			 * or the answer will be wrong, as the rest of the
			 * line will have been shifted.  This code means
			 * that terminals with only insert chracter (no
			 * delete character) won't work correctly.
			 */
			i = inssiz - doomed - tabslack - slakused;
			i %= value(TABSTOP);
			if (i > 0) {
				vgotoCL(tabstart);
				godm();
				for (i = inssiz - doomed - tabslack; i > 0; i--)
					vputp(DC, DEPTH(vcline));
				enddm();
			}
		}

	/* 
	 * Now put out the characters of the actual insertion.
	 */
	vigotoCL(inscol);
	remdoom = doomed;
	for (i = inssiz; i > 0; i--) {
		if (remdoom > insmc1) {
			remdoom--;
			endim();
		} else if (noim || insmc1 && remdoom == insmc1)
			endim();
		else if (IM && EI) {
			vcsync();
			goim();
		}
		vputchar(c);
	}

	if (!IM || !EI || remdoom && remdoom == insmc1) {
		/*
		 * We are a dumb terminal; brute force update
		 * the rest of the line; this is very much an n^^2 process,
		 * and totally unreasonable at low speed.
		 *
		 * You asked for it, you get it.
		 */
		tp = vtube0 + inscol + doomed;
		for (i = inscol + doomed; i < tabstart; i++)
			vputchar(*tp++);
		hold = oldhold;
		vigotoCL(tabstart + inssiz + insmc0 - doomed);
		for (i = tabsize - (inssiz - insmc0 - doomed) + shft;
				i > 0; i--)
			vputchar(' ' | QUOTE);
	} else {
		if (!IN) {
			/*
			 * On terminals without multi-line
			 * insert in the hardware, we must go fix the segments
			 * between the inserted text and the following
			 * tabs, if they are on different lines.
			 *
			 * Aaargh.
			 */
			tp = vtube0;
			for (j = (inscol + insmc0 + inssiz - 1) / WCOLS + 1;
			    j <= (tabstart + inssiz - doomed - 1) / WCOLS; j++) {
				vgotoCL(j * WCOLS);
				i = inssiz - doomed + insmc1;
				up = tp + j * WCOLS - i;
				goim();
				do
					vputchar(*up++);
				while (--i && *up);
			}
		} else {
			/*
			 * On terminals with multi line inserts,
			 * life is simpler, just reflect eating of
			 * the slack.
			 */
			tp = vtube0 + tabend;
			for (i = tabsize - (inssiz + insmc1 - doomed); i >= 0; i--) {
				if ((*--tp & (QUOTE|TRIM)) == QUOTE) {
					--tabslack;
					if (tabslack >= slakused)
						continue;
				}
				*tp = ' ' | QUOTE;
			}
		}
		/*
		 * Blank out the shifted positions to be tab positions.
		 */
		if (shft) {
			tp = vtube0 + tabend + shft;
			for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
				if ((*--tp & QUOTE) == 0)
					*tp = ' ' | QUOTE;
		}
	}

	/*
	 * Finally, complete the screen image update
	 * to reflect the insertion.
	 */
	hold = oldhold;
	tp = vtube0 + tabstart;
	up = tp + insmc1 + inssiz - doomed;
	for (i = tabstart; i > inscol + doomed; i--)
		*--up = *--tp;
#ifdef	MB
	for (i = insmc1; i > 0; i--)
		*--up = MULTICOL;
#endif
	for (i = inssiz; i > 0; i--)
		*--up = c | (insmc1 ? MULTICOL : 0);
	doomed = 0;
}
Пример #8
0
void
vappend(int ch, int cnt, int indent)
{
	register int i;
	register char *gcursor;
	bool escape;
	int repcnt;
	short oldhold = hold;

	/*
	 * Before a move in hardopen when the line is dirty
	 * or we are in the middle of the printed representation,
	 * we retype the line to the left of the cursor so the
	 * insert looks clean.
	 */
	if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
		rubble = 1;
		wcursor = cursor;
		vmove();
	}
	vaifirst = indent == 0;

	/*
	 * Handle replace character by (eventually)
	 * limiting the number of input characters allowed
	 * in the vgetline routine.
	 */
	if (ch == 'r')
		repcnt = 2;
	else
		repcnt = 0;

	/*
	 * If an autoindent is specified, then
	 * generate a mixture of blanks to tabs to implement
	 * it and place the cursor after the indent.
	 * Text read by the vgetline routine will be placed in genbuf,
	 * so the indent is generated there.
	 */
	if (value(AUTOINDENT) && indent != 0) {
		gcursor = genindent(indent);
		*gcursor = 0;
		vgotoCL(qcolumn(cursor - 1, genbuf));
	} else {
		gcursor = genbuf;
		*gcursor = 0;
		if (ch == 'o')
			vfixcurs();
	}

	/*
	 * Prepare for undo.  Pointers delimit inserted portion of line.
	 */
	vUA1 = vUA2 = cursor;

	/*
	 * If we are not in a repeated command and a ^@ comes in
	 * then this means the previous inserted text.
	 * If there is none or it was too long to be saved,
	 * then beep() and also arrange to undo any damage done
	 * so far (e.g. if we are a change.)
	 */
	if ((vglobp && *vglobp == 0) || peekbr()) {
		if ((INS[0] & (OVERBUF|TRIM)) == OVERBUF) {
			beep();
			if (!splitw)
				ungetkey('u');
			doomed = 0;
			hold = oldhold;
			return;
		}
		/*
		 * Unread input from INS.
		 * An escape will be generated at end of string.
		 * Hold off n^^2 type update on dumb terminals.
		 */
		vglobp = INS;
		hold |= HOLDQIK;
	} else if (vglobp == 0)
		/*
		 * Not a repeated command, get
		 * a new inserted text for repeat.
		 */
		INS[0] = 0;

	/*
	 * For wrapmargin to hack away second space after a '.'
	 * when the first space caused a line break we keep
	 * track that this happened in gobblebl, which says
	 * to gobble up a blank silently.
	 */
	gobblebl = 0;

	/*
	 * Text gathering loop.
	 * New text goes into genbuf starting at gcursor.
	 * cursor preserves place in linebuf where text will eventually go.
	 */
	if (*cursor == 0 || state == CRTOPEN)
		hold |= HOLDROL;
	for (;;) {
		if (ch == 'r' && repcnt == 0)
			escape = 0;
		else {
			gcursor = vgetline(repcnt, gcursor, &escape);

			/*
			 * After an append, stick information
			 * about the ^D's and ^^D's and 0^D's in
			 * the repeated text buffer so repeated
			 * inserts of stuff indented with ^D as backtab's
			 * can work.
			 */
			if (HADUP)
				addtext("^");
			else if (HADZERO)
				addtext("0");
			while (CDCNT > 0)
				addtext("\204"), CDCNT--;
			if (gobbled)
				addtext(" ");
			addtext(ogcursor);
		}
		repcnt = 0;

		/*
		 * Smash the generated and preexisting indents together
		 * and generate one cleanly made out of tabs and spaces
		 * if we are using autoindent.
		 */
		if (!vaifirst && value(AUTOINDENT)) {
			i = fixindent(indent);
			if (!HADUP)
				indent = i;
			gcursor = strend(genbuf);
		}

		/*
		 * Limit the repetition count based on maximum
		 * possible line length; do output implied
		 * by further count (> 1) and cons up the new line
		 * in linebuf.
		 */
		cnt = vmaxrep(ch, cnt);
		CP(gcursor + 1, cursor);
		do {
			CP(cursor, genbuf);
			if (cnt > 1) {
				int oldhold = hold;

				Outchar = vinschar;
				hold |= HOLDQIK;
				ex_printf("%s", genbuf);
				hold = oldhold;
				Outchar = vputchar;
			}
			cursor += gcursor - genbuf;
		} while (--cnt > 0);
		endim();
		vUA2 = cursor;
		if (escape != '\n')
			CP(cursor, gcursor + 1);

		/*
		 * If doomed characters remain, clobber them,
		 * and reopen the line to get the display exact.
		 */
		if (state != HARDOPEN) {
			DEPTH(vcline) = 0;
			if (doomed > 0) {
				register int cind = cindent();

				physdc(cind, cind + doomed);
				doomed = 0;
			}
			i = vreopen(LINE(vcline), lineDOT(), vcline);
		}

		/*
		 * All done unless we are continuing on to another line.
		 */
		if (escape != '\n')
			break;

		/*
		 * Set up for the new line.
		 * First save the current line, then construct a new
		 * first image for the continuation line consisting
		 * of any new autoindent plus the pushed ahead text.
		 */
		killU();
		addtext(gobblebl ? " " : "\n");
		vsave();
		cnt = 1;
		if (value(AUTOINDENT)) {
#ifdef LISP
			if (value(LISP))
				indent = lindent(dot + 1);
			else
#endif
			     if (!HADUP && vaifirst)
				indent = whitecnt(linebuf);
			vaifirst = 0;
			strcLIN(vpastwh(gcursor + 1));
			gcursor = genindent(indent);
			*gcursor = 0;
			if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
				gcursor = genbuf;
			CP(gcursor, linebuf);
		} else {
			CP(genbuf, gcursor + 1);
			gcursor = genbuf;
		}

		/*
		 * If we started out as a single line operation and are now
		 * turning into a multi-line change, then we had better yank
		 * out dot before it changes so that undo will work
		 * correctly later.
		 */
		if (vundkind == VCHNG) {
			vremote(1, (void (*)(int))yank, 0);
			undap1--;
		}

		/*
		 * Now do the append of the new line in the buffer,
		 * and update the display.  If slowopen
		 * we don't do very much.
		 */
		vdoappend(genbuf);
		vundkind = VMANYINS;
		vcline++;
		if (state != VISUAL)
			vshow(dot, NOLINE);
		else {
			i += LINE(vcline - 1);
			vopen(dot, i);
			if (value(SLOWOPEN))
				vscrap();
			else
				vsync1(LINE(vcline));
		}
		strcLIN(gcursor);
		*gcursor = 0;
		cursor = linebuf;
		vgotoCL(qcolumn(cursor - 1, genbuf));
	}

	/*
	 * All done with insertion, position the cursor
	 * and sync the screen.
	 */
	hold = oldhold;
	if (cursor > linebuf)
		cursor--;
	if (state != HARDOPEN)
		vsyncCL();
	else if (cursor > linebuf)
		back1();
	doomed = 0;
	wcursor = cursor;
	vmove();
}
Пример #9
0
CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
{
    size_t result_len;
    size_t lenx;
    int depth;

    if (x == CORD_EMPTY) return(y);
    if (leny == 0) return(x);
    if (CORD_IS_STRING(x)) {
        lenx = strlen(x);
        result_len = lenx + leny;
        if (result_len <= SHORT_LIMIT) {
            char * result = (char *)GC_MALLOC_ATOMIC(result_len + 1);

            if (result == 0) OUT_OF_MEMORY;
#           ifdef LINT2
                memcpy(result, x, lenx + 1);
#           else
                memcpy(result, x, lenx);
                                /* No need to copy the terminating zero */
                                /* as result[lenx] is written below.    */
#           endif
            memcpy(result + lenx, y, leny);
            result[result_len] = '\0';
            return((CORD) result);
        } else {
            depth = 1;
        }
    } else {
        CORD right;
        CORD left;
        char * new_right;

        lenx = LEN(x);

        if (leny <= SHORT_LIMIT/2
            && IS_CONCATENATION(x)
            && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) {
            size_t right_len;

            /* Merge y into right part of x. */
            if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) {
                right_len = lenx - LEN(left);
            } else if (((CordRep *)x) -> concatenation.left_len != 0) {
                right_len = lenx - ((CordRep *)x) -> concatenation.left_len;
            } else {
                right_len = strlen(right);
            }
            result_len = right_len + leny;  /* length of new_right */
            if (result_len <= SHORT_LIMIT) {
                new_right = (char *)GC_MALLOC_ATOMIC(result_len + 1);
                if (new_right == 0) OUT_OF_MEMORY;
                memcpy(new_right, right, right_len);
                memcpy(new_right + right_len, y, leny);
                new_right[result_len] = '\0';
                y = new_right;
                leny = result_len;
                x = left;
                lenx -= right_len;
                /* Now fall through to concatenate the two pieces: */
            }
            if (CORD_IS_STRING(x)) {
                depth = 1;
            } else {
                depth = DEPTH(x) + 1;
            }
        } else {
            depth = DEPTH(x) + 1;
        }
        result_len = lenx + leny;
    }
    {
      /* The general case; lenx, result_len is known: */
        struct Concatenation * result = GC_NEW(struct Concatenation);

        if (NULL == result) OUT_OF_MEMORY;
        result->header = CONCAT_HDR;
        result->depth = (char)depth;
        if (lenx <= MAX_LEFT_LEN)
            result->left_len = (unsigned char)lenx;
        result->len = (word)result_len;
        result->left = x;
        GC_PTR_STORE_AND_DIRTY((void *)&result->right, y);
        GC_reachable_here(x);
        if (depth >= MAX_DEPTH) {
            return(CORD_balance((CORD)result));
        } else {
            return((CORD) result);
        }
    }
}
Пример #10
0
/*
 * Delete display positions stcol through endcol.
 * Amount of use of special terminal features here is limited.
 */
void
physdc(int stcol, int endcol)
{
	register cell *tp, *up;
	cell *tpe = NULL;
	register int i;
	register int nc = endcol - stcol;

#ifdef IDEBUG
	if (trace)
		tfixnl(), fprintf(trace, "physdc(%d, %d)\n", stcol, endcol);
#endif
	if (!DC || nc <= 0)
		return;
	if (IN) {
		/*
		 * CONCEPT-100 like terminal.
		 * If there are any ``spaces'' in the material to be
		 * deleted, then this is too hard, just retype.
		 */
		vprepins();
		up = vtube0 + stcol;
		i = nc;
		do {
			if ((*up++ & (QUOTE|TRIM)) == QUOTE)
				return;
		} while (--i);
		i = 2 * nc;
		do {
			if (*up == 0 || (*up++ & QUOTE) == QUOTE)
				return;
		} while (--i);
		vgotoCL(stcol);
	} else {
		/*
		 * HP like delete mode.
		 * Compute how much text we are moving over by deleting.
		 * If it appears to be faster to just retype
		 * the line, do nothing and that will be done later.
		 * We are assuming 2 output characters per deleted
		 * characters and that clear to end of line is available.
		 */
		i = stcol / WCOLS;
		if (i != endcol / WCOLS)
			return;
		i += LINE(vcline);
		stcol %= WCOLS;
		endcol %= WCOLS;
		up = vtube[i]; tp = up + endcol; tpe = up + WCOLS;
		while (tp < tpe && *tp)
			tp++;
		if (tp - (up + stcol) < 2 * nc)
			return;
		vgoto(i, stcol);
	}

	/*
	 * Go into delete mode and do the actual delete.
	 * Padding is on DC itself.
	 */
	godm();
	for (i = nc; i > 0; i--)
		vputp(DC, DEPTH(vcline));
	vputp(ED, 0);

	/*
	 * Straighten up.
	 * With CONCEPT like terminals, characters are pulled left
	 * from first following null.  HP like terminals shift rest of
	 * this (single physical) line rigidly.
	 */
	if (IN) {
		up = vtube0 + stcol;
		tp = vtube0 + endcol;
		while (i = *tp++) {
			if ((i & (QUOTE|TRIM)) == QUOTE)
				break;
			*up++ = i;
		}
		do
			*up++ = i;
		while (--nc);
	} else {
		copy(up + stcol, up + endcol,
				(WCOLS - endcol) * sizeof *up);
		vclrcell(tpe - nc, nc);
	}
}
Пример #11
0
CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
{
    register size_t result_len;
    register size_t lenx;
    register int depth;

    if (x == CORD_EMPTY) return(y);
    if (leny == 0) return(x);
    if (CORD_IS_STRING(x)) {
        lenx = strlen(x);
        result_len = lenx + leny;
        if (result_len <= SHORT_LIMIT) {
            register char * result = MK_GC_MALLOC_ATOMIC(result_len+1);

            if (result == 0) OUT_OF_MEMORY;
            memcpy(result, x, lenx);
            memcpy(result + lenx, y, leny);
            result[result_len] = '\0';
            return((CORD) result);
        } else {
            depth = 1;
        }
    } else {
        register CORD right;
        register CORD left;
        register char * new_right;
        register size_t right_len;

        lenx = LEN(x);

        if (leny <= SHORT_LIMIT/2
            && IS_CONCATENATION(x)
            && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) {
            /* Merge y into right part of x. */
            if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) {
                right_len = lenx - LEN(left);
            } else if (((CordRep *)x) -> concatenation.left_len != 0) {
                right_len = lenx - ((CordRep *)x) -> concatenation.left_len;
            } else {
                right_len = strlen(right);
            }
            result_len = right_len + leny;  /* length of new_right */
            if (result_len <= SHORT_LIMIT) {
                new_right = MK_GC_MALLOC_ATOMIC(result_len + 1);
                if (new_right == 0) OUT_OF_MEMORY;
                memcpy(new_right, right, right_len);
                memcpy(new_right + right_len, y, leny);
                new_right[result_len] = '\0';
                y = new_right;
                leny = result_len;
                x = left;
                lenx -= right_len;
                /* Now fall through to concatenate the two pieces: */
            }
            if (CORD_IS_STRING(x)) {
                depth = 1;
            } else {
                depth = DEPTH(x) + 1;
            }
        } else {
            depth = DEPTH(x) + 1;
        }
        result_len = lenx + leny;
    }
    {
      /* The general case; lenx, result_len is known: */
        register struct Concatenation * result;

        result = MK_GC_NEW(struct Concatenation);
        if (result == 0) OUT_OF_MEMORY;
        result->header = CONCAT_HDR;
        result->depth = depth;
        if (lenx <= MAX_LEFT_LEN) result->left_len = lenx;
        result->len = result_len;
        result->left = x;
        result->right = y;
        if (depth >= MAX_DEPTH) {
            return(CORD_balance((CORD)result));
        } else {
            return((CORD) result);
        }
    }
}
Пример #12
0
static int
shrinksize(VtFile *r, VtEntry *e, uvlong size)
{
	int i, depth, type, isdir, ppb;
	uvlong ptrsz;
	uchar score[VtScoreSize];
	VtBlock *b;

	b = vtcacheglobal(r->c, e->score, e->type);
	if(b == nil)
		return -1;

	ptrsz = e->dsize;
	ppb = e->psize/VtScoreSize;
	type = e->type;
	depth = DEPTH(type);
	for(i=0; i+1<depth; i++)
		ptrsz *= ppb;

	isdir = r->dir;
	while(depth > 0){
		if(b->addr == NilBlock){
			/* not worth copying the block just so we can zero some of it */
			vtblockput(b);
			return -1;
		}

		/*
		 * invariant: each pointer in the tree rooted at b accounts for ptrsz bytes
		 */

		/* zero the pointers to unnecessary blocks */
		i = (size+ptrsz-1)/ptrsz;
		for(; i<ppb; i++)
			memmove(b->data+i*VtScoreSize, vtzeroscore, VtScoreSize);

		/* recurse (go around again) on the partially necessary block */
		i = size/ptrsz;
		size = size%ptrsz;
		if(size == 0){
			vtblockput(b);
			return 0;
		}
		ptrsz /= ppb;
		type--;
		memmove(score, b->data+i*VtScoreSize, VtScoreSize);
		vtblockput(b);
		b = vtcacheglobal(r->c, score, type);
		if(b == nil)
			return -1;
	}

	if(b->addr == NilBlock){
		vtblockput(b);
		return -1;
	}

	/*
	 * No one ever truncates BtDir blocks.
	 */
	if(depth==0 && !isdir && e->dsize > size)
		memset(b->data+size, 0, e->dsize-size);
	vtblockput(b);
	return 0;
}
Пример #13
0
int
vtfileflushbefore(VtFile *r, u64int offset)
{
	VtBlock *b, *bb;
	VtEntry e;
	int i, base, depth, ppb, epb, doflush;
	int index[VtPointerDepth+1], j, ret;
	VtBlock *bi[VtPointerDepth+2];
	uchar *score;

	assert(ISLOCKED(r));
	if(offset == 0)
		return 0;

	b = fileload(r, &e);
	if(b == nil)
		return -1;

	/*
	 * compute path through tree for the last written byte and the next one.
	 */
	ret = -1;
	memset(bi, 0, sizeof bi);
	depth = DEPTH(e.type);
	bi[depth+1] = b;
	i = mkindices(&e, (offset-1)/e.dsize, index);
	if(i < 0)
		goto Err;
	if(i > depth)
		goto Err;
	ppb = e.psize / VtScoreSize;
	epb = e.dsize / VtEntrySize;

	/*
	 * load the blocks along the last written byte
	 */
	index[depth] = r->offset % r->epb;
	for(i=depth; i>=0; i--){
		bb = blockwalk(b, index[i], r->c, VtORDWR, &e);
		if(bb == nil)
			goto Err;
		bi[i] = bb;
		b = bb;
	}
	ret = 0;

	/*
	 * walk up the path from leaf to root, flushing anything that
	 * has been finished.
	 */
	base = e.type&~VtTypeDepthMask;
	for(i=0; i<=depth; i++){
		doflush = 0;
		if(i == 0){
			/* leaf: data or dir block */
			if(offset%e.dsize == 0)
				doflush = 1;
		}else{
			/*
			 * interior node: pointer blocks.
			 * specifically, b = bi[i] is a block whose index[i-1]'th entry 
			 * points at bi[i-1].  
			 */
			b = bi[i];

			/*
			 * the index entries up to but not including index[i-1] point at 
			 * finished blocks, so flush them for sure.
			 */
			for(j=0; j<index[i-1]; j++)
				if(flushblock(r->c, nil, b->data+j*VtScoreSize, ppb, epb, base+i-1) < 0)
					goto Err;

			/*
			 * if index[i-1] is the last entry in the block and is global
			 * (i.e. the kid is flushed), then we can flush this block.
			 */
			if(j==ppb-1 && vtglobaltolocal(b->data+j*VtScoreSize)==NilBlock)
				doflush = 1;
		}
		if(doflush){
			if(i == depth)
				score = e.score;
			else
				score = bi[i+1]->data+index[i]*VtScoreSize;
			if(flushblock(r->c, bi[i], score, ppb, epb, base+i) < 0)
				goto Err;
		}
	}

Err:
	/* top: entry.  do this always so that the score is up-to-date */
	vtentrypack(&e, bi[depth+1]->data, index[depth]);
	for(i=0; i<nelem(bi); i++)
		if(bi[i])
			vtblockput(bi[i]);
	return ret;
}
Пример #14
0
OP_ERROR
SOP_Ocean::cookMySop(OP_Context &context)
{
    float now = context.getTime();

    //std::cout << "cook ocean, t = " << now << std::endl;

    // lock inputs
    if (lockInputs(context) >= UT_ERROR_ABORT )
    {
        return error();
    }


    GEO_Point		*ppt;
    UT_Interrupt	*boss;

    // Check to see that there hasn't been a critical error in cooking the SOP.
    if (error() < UT_ERROR_ABORT)
    {
        boss = UTgetInterrupt();

        // Start the interrupt server
        boss->opStart("Updating Ocean");

        duplicatePointSource(0,context);

        int   gridres  = 1 << int(GRID_RES(now));
        float stepsize = GRID_SIZE(now) / (float)gridres;

        bool do_chop     = CHOP(now);
        bool do_jacobian = JACOBIAN(now);
        bool do_normals  = NORMALS(now) && !do_chop;

        if (!_ocean || _ocean_needs_rebuild)
        {
            if (_ocean)
            {
                delete _ocean;
            }

            if (_ocean_context)
            {
                delete _ocean_context;
            }

            _ocean = new drw::Ocean(gridres,gridres,stepsize,stepsize,
                                    V(0),L(0),1.0,W(0),1-DAMP(0),ALIGN(0),
                                    DEPTH(0),SEED(0));
            _ocean_scale   = _ocean->get_height_normalize_factor();

            _ocean_context = _ocean->new_context(true,do_chop,do_normals,do_jacobian);

            _ocean_needs_rebuild = false;
//             std::cout << "######### SOP, rebuilt ocean, norm_factor = " << _ocean_scale 
//                       << " chop = " << do_chop 
//                       << " norm = " << do_normals
//                       << " jacobian = " << do_jacobian
//                       << std::endl;
        }

        float chop_amount = CHOPAMOUNT(now);

        // sum up the waves at this timestep
        _ocean->update(TIME(now),*_ocean_context,true,do_chop,do_normals,do_jacobian,
                       _ocean_scale * SCALE(now),chop_amount);

        bool linterp = ! INTERP(now);


        // get our attribute indices
        GA_RWAttributeRef normal_index;
        GA_RWAttributeRef jminus_index;
        GA_RWAttributeRef eminus_index;

        if (do_normals)
        {
            normal_index = gdp->addNormalAttribute(GEO_POINT_DICT);
        }
        if (do_jacobian)
        {
            // jminus_index = gdp->addPointAttrib("mineigval",sizeof(float),GB_ATTRIB_FLOAT,0);
            // eminus_index = gdp->addPointAttrib("mineigvec",sizeof(UT_Vector3),GB_ATTRIB_VECTOR,0);
            jminus_index = gdp->addTuple(GA_STORE_REAL32,GA_ATTRIB_POINT,"mineigval",1,GA_Defaults(0));
            eminus_index = gdp->addFloatTuple(GA_ATTRIB_POINT,"mineigvec",1,GA_Defaults(0));
        }

        // this is not that fast, can it be done quicker ???
        GA_FOR_ALL_GPOINTS(gdp, ppt)
            {
                UT_Vector4 p = ppt->getPos();

                
                if (linterp)
                {
                    _ocean_context->eval_xz(p(0),p(2));
                }
                else
                {
                    _ocean_context->eval2_xz(p(0),p(2));
                }

                if (do_chop) 
                {
                    p.assign( p(0) + _ocean_context->disp[0],
                              p(1) + _ocean_context->disp[1],
                              p(2) + _ocean_context->disp[2] );
                }
                else
                {
                    // ppt->getPos()(1) += _ocean_context->disp[1];
                	UT_Vector4 tmp_p = ppt->getPos();
                	tmp_p(1) += _ocean_context->disp[1];
                	ppt->setPos(tmp_p);
                }

                if (do_normals)
                {
                	/*
					  UT_Vector3* normal = (UT_Vector3*) ppt->castAttribData<UT_Vector3>(normal_index);
					  normal->assign(_ocean_context->normal[0],
					                 _ocean_context->normal[1],
					                 _ocean_context->normal[2]);
					  normal->normalize();
                    */
                	ppt->getValue<UT_Vector3>(normal_index).assign(_ocean_context->normal[0],
																   _ocean_context->normal[1],
																   _ocean_context->normal[2]);
                	ppt->getValue<UT_Vector3>(normal_index).normalize();
                }

                if (do_jacobian)
                {/*
                    float *js = (float*)ppt->castAttribData<float>(jminus_index);
                    *js = _ocean_context->Jminus;
                    UT_Vector3* eminus = (UT_Vector3*)ppt->castAttribData<UT_Vector3>(eminus_index);
                    eminus->assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]);
                    */
                    ppt->setValue<float>(jminus_index,_ocean_context->Jminus);
                    ppt->getValue<UT_Vector3>(eminus_index).assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]);
                }
				ppt->setPos(p);
            }
Пример #15
0
/*
 * Do the shift of the next tabstop implied by
 * insertion so it expands.
 */
void
vishft(void)
{
	int tshft = 0;
	int j;
	register int i;
	register cell *tp = vtube0;
	register cell *up;
	short oldhold = hold;

	shft = value(TABSTOP);
	hold |= HOLDPUPD;
	if (!IM && !EI) {
		/*
		 * Dumb terminals are easy, we just have
		 * to retype the text.
		 */
		vigotoCL(tabend + shft);
		up = tp + tabend;
		for (i = tabend; i < linend; i++)
			vputchar(*up++);
	} else if (IN) {
		/*
		 * CONCEPT-like terminals do most of the work for us,
		 * we don't have to muck with simulation of multi-line
		 * insert mode.  Some of the shifting may come for free
		 * also if the tabs don't have enough slack to take up
		 * all the inserted characters.
		 */
		i = shft;
		slakused = inssiz - doomed;
		if (slakused > tabslack) {
			i -= slakused - tabslack;
			slakused -= tabslack;
		}
		if (i > 0 && tabend != linend) {
			tshft = i;
			vgotoCL(tabend);
			goim();
			do
				vputchar(' ' | QUOTE);
			while (--i);
		}
	} else {
		/*
		 * HP and Datamedia type terminals have to have multi-line
		 * insert faked.  Hack each segment after where we are
		 * (going backwards to where we are.)  We then can
		 * hack the segment where the end of the first following
		 * tab group is.
		 */
		for (j = DEPTH(vcline) - 1; j > (tabend + shft) / WCOLS; j--) {
			vgotoCL(j * WCOLS);
			goim();
			up = tp + j * WCOLS - shft;
			i = shft;
			do {
				if (*up)
					vputchar(*up++);
				else
					break;
			} while (--i);
		}
		vigotoCL(tabstart);
		i = shft - (inssiz - doomed);
		if (i > 0) {
			tabslack = inssiz - doomed;
			vcsync();
			goim();
			do
				vputchar(' ');
			while (--i);
		}
	}
	/*
	 * Now do the data moving in the internal screen
	 * image which is common to all three cases.
	 */
	tp += linend;
	up = tp + shft;
	i = linend - tabend;
	if (i > 0)
		do
			*--up = *--tp;
		while (--i);
	if (IN && tshft) {
		i = tshft;
		do
			*--up = ' ' | QUOTE;
		while (--i);
	}
	hold = oldhold;
}
Пример #16
0
/*
 * Insert character c at current cursor position.
 * Multi-character inserts occur only as a result
 * of expansion of tabs (i.e. inssize == 1 except
 * for tabs) and code assumes this in several place
 * to make life simpler.
 */
int
vinschar(int c)
/*	int c;		/\* mjm: char --> int */
{
	register int i;
	register cell *tp;
	char	*OIM;
	bool	OXN;
	int	noim, filler = 0;

	insmc1 = colsc(c) - 1;
	if ((!IM || !EI) && ((hold & HOLDQIK) || !value(REDRAW) || value(SLOWOPEN))) {
		/*
		 * Don't want to try to use terminal
		 * insert mode, or to try to fake it.
		 * Just put the character out; the screen
		 * will probably be wrong but we will fix it later.
		 */
		if (c == '\t') {
			vgotab();
			return c;
		}
		vputchar(c);
#ifdef	MB
		if (insmc1 == 0 && (vtube0[destcol]&(TRIM|MULTICOL))==MULTICOL)
			vtube0[destcol] = INVBIT;
#endif	/* MB */
		if (DEPTH(vcline) * WCOLS + !value(REDRAW) >
		    (destline - LINE(vcline)) * WCOLS + destcol)
			return c;
		/*
		 * The next line is about to be clobbered
		 * make space for another segment of this line
		 * (on an intelligent terminal) or just remember
		 * that next line was clobbered (on a dumb one
		 * if we don't care to redraw the tail.
		 */
		if (AL) {
			vnpins(0);
		} else {
			c = LINE(vcline) + DEPTH(vcline);
			if (c < LINE(vcline + 1) || c > WBOT)
				return c;
			i = destcol;
			vinslin(c, 1, vcline);
			DEPTH(vcline)++;
			vigoto(c, i);
			vprepins();
		}
		return c;
	}
	/*
	 * Compute the number of positions in the line image of the
	 * current line.  This is done from the physical image
	 * since that is faster.  Note that we have no memory
	 * from insertion to insertion so that routines which use
	 * us don't have to worry about moving the cursor around.
	 */
	if (*vtube0 == 0)
		linend = 0;
	else {
		/*
		 * Search backwards for a non-null character
		 * from the end of the displayed line.
		 */
		i = WCOLS * DEPTH(vcline);
		if (i == 0)
			i = WCOLS;
		tp = vtube0 + i;
		while (*--tp == 0)
			if (--i == 0)
				break;
		linend = i + insmc1;
	}

	/*
	 * We insert at a position based on the physical location
	 * of the output cursor.
	 */
	inscol = destcol + (destline - LINE(vcline)) * WCOLS;
	insmc0 = 0;
#ifdef	MB
	i = 0;
	while (inscol+i < LBSIZE && vtube0[inscol+i]&MULTICOL &&
			(vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) != MULTICOL)
		i++;
	while (inscol+insmc0+i < LBSIZE &&
			(vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) == MULTICOL)
		insmc0++;
#endif	/* MB */
	if (c == '\t') {
		/*
		 * Characters inserted from a tab must be
		 * remembered as being part of a tab, but we can't
		 * use QUOTE here since we really need to print blanks.
		 * QUOTE|' ' is the representation of this.
		 */
		inssiz = tabcol(inscol+insmc0, value(TABSTOP)) - inscol - insmc0;
		c = ' ' | QUOTE;
	} else
		inssiz = 1;

	/*
	 * If the text to be inserted is less than the number
	 * of doomed positions, then we don't need insert mode,
	 * rather we can just typeover.
	 */
	if (inssiz + insmc1 <= doomed) {
		endim();
		if (inscol + insmc0 != linend)
			doomed -= inssiz + insmc1;
#ifdef	MB
		if (insmc1 == 0 && c != '\t' &&
				vtube0[inscol+insmc0] & MULTICOL)
			vtube0[inscol+insmc0] = INVBIT;
#endif	/* MB */
		do
			vputchar(c);
		while (--inssiz);
		return c;
	}

	/*
	 * Have to really do some insertion, thus
	 * stake out the bounds of the first following
	 * group of tabs, computing starting position,
	 * ending position, and the number of ``spaces'' therein
	 * so we can tell how much it will squish.
	 */
	tp = vtube0 + inscol + insmc0;
	for (i = inscol + insmc0; i < linend; i++) {
		if (*tp++ & QUOTE) {
			--tp;
			break;
		}
	}
	tabstart = tabend = i;
	tabslack = 0;
	while (tabend < linend) {
		i = *tp++;
		if ((i & QUOTE) == 0)
			break;
		if ((i & (TRIM|MULTICOL)) == 0)
			tabslack++;
		tabsize++;
		tabend++;
	}
	tabsize = tabend - tabstart;

	/*
	 * For HP's and DM's, e.g. tabslack has no meaning.
	 */
	if (!IN)
		tabslack = 0;
#ifdef IDEBUG
	if (trace) {
		fprintf(trace, "inscol %d, inssiz %d, tabstart %d, ",
			inscol, inssiz, tabstart);
		fprintf(trace, "tabend %d, tabslack %d, linend %d\n",
			tabend, tabslack, linend);
	}
#endif
	OIM = IM;
	OXN = XN;
	noim = 0;
#ifdef	MB
	if (mb_cur_max > 1) {
		if (destcol + 1 + insmc1 == WCOLS + 1) {
			noim = 1;
			if (insmc1 == 1 && insmc0 == 0)
				filler = 1;
		}
		for (i = inscol; vtube0[i]; i++)
			if (i + 1 >= WCOLS && vtube0[i] & MULTICOL) {
				noim = 1;
				break;
			}
	}
#endif	/* MB */
	if (noim) {
		endim();
		IM = 0;
		XN = 0;
	}

	/*
	 * The real work begins.
	 */
	slakused = 0;
	shft = 0;
	if (tabsize) {
		/*
		 * There are tabs on this line.
		 * If they need to expand, then the rest of the line
		 * will have to be shifted over.  In this case,
		 * we will need to make sure there are no ``spaces''
		 * in the rest of the line (on e.g. CONCEPT-100)
		 * and then grab another segment on the screen if this
		 * line is now deeper.  We then do the shift
		 * implied by the insertion.
		 */
		if (inssiz >= doomed + tabcol(tabstart, value(TABSTOP)) - tabstart) {
			if (IN)
				vrigid();
			vneedpos(value(TABSTOP));
			vishft();
		}
	} else if (inssiz + insmc1 > doomed)
		/*
		 * No tabs, but line may still get deeper.
		 */
		vneedpos(inssiz + insmc1 - doomed);
	/*
	 * Now put in the inserted characters.
	 */
	viin(c);

	/*
	 * Now put the cursor in its final resting place.
	 */
	destline = LINE(vcline);
	destcol = inscol + inssiz + insmc1 + filler;
	vcsync();
	if (IM != OIM) {
		IM = OIM;
		XN = OXN;
	}
	return c;
}
Пример #17
0
void studrenDrawTriangle(S_Renderer *pRenderer,
                         S_Coords *v1, S_Coords *v2, S_Coords *v3,
                         S_Coords *n1, S_Coords *n2, S_Coords *n3,
                         int x1, int y1,
                         int x2, int y2,
                         int x3, int y3
                         )
{

	S_StudentRenderer   * renderer;

	/* ukazatel na studentsky renderer */
	renderer = (S_StudentRenderer *)pRenderer;

	int         minx, miny, maxx, maxy;
	int         a1, a2, a3, b1, b2, b3, c1, c2, c3;
	int         /*s1,*/ s2, s3;
	int         x, y, e1, e2, e3;
	double      alpha, beta, w1, w2, w3, z;
	S_RGBA      col1, col2, col3, color;

	IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3);

	/* vypocet barev ve vrcholech */
	col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
	col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
	col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

	/* obalka trojuhleniku */
	minx = MIN(x1, MIN(x2, x3));
	maxx = MAX(x1, MAX(x2, x3));
	miny = MIN(y1, MIN(y2, y3));
	maxy = MAX(y1, MAX(y2, y3));

	/* oriznuti podle rozmeru okna */
	miny = MAX(miny, 0);
	maxy = MIN(maxy, pRenderer->frame_h - 1);
	minx = MAX(minx, 0);
	maxx = MIN(maxx, pRenderer->frame_w - 1);

	/* vektory urcene vrcholy 1-2 a 1-3 */
	a1 = x2 - x1;
	a3 = x3 - x1;
	b1 = y2 - y1;
	b3 = y3 - y1;

	/* overeni counterclockwise orientace troj. pomoci vektoroveho soucinu */
	if ((a1 * b3 - b1 * a3) < 0)
	{
		/* spatna orientace -> prohodime vrcholy 2 a 3 */
		SWAP(x2, x3);
		SWAP(y2, y3);

		/* a take barvy vrcholu */
		SWAP(col2.red, col3.red);
		SWAP(col2.green, col3.green);
		SWAP(col2.blue, col3.blue);
		SWAP(col2.alpha, col3.alpha);
	}

	/* Pineduv alg. rasterizace troj.
	hranova fce je obecna rovnice primky Ax + By + C = 0
	primku prochazejici body (x1, y1) a (x2, y2) urcime jako
	(y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */

	/* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */
	a1 = y1 - y2;
	a2 = y2 - y3;
	a3 = y3 - y1;
	b1 = x2 - x1;
	b2 = x3 - x2;
	b3 = x1 - x3;

	/* koeficient C */
	c1 = x1 * y2 - x2 * y1;
	c2 = x2 * y3 - x3 * y2;
	c3 = x3 * y1 - x1 * y3;

	/* vypocet hranove fce (vzdalenost od primky) pro protejsi body */
	/*s1 = a1 * x3 + b1 * y3 + c1;*/
	s2 = a2 * x1 + b2 * y1 + c2;
	s3 = a3 * x2 + b3 * y2 + c3;

	/* uprava koeficientu C pro korektni vyplnovani, viz "OpenGL top-left rule" */
	/* https://books.google.cz/books?id=3ljRBQAAQBAJ&pg=PA73 */
	if ((y1 == y2 && x2 > x1) || y2 < y1)
	{
		c1 -= 1;
	}
	if ((y2 == y3 && x3 > x2) || y3 < y2)
	{
		c2 -= 1;
	}
	if ((y3 == y1 && x1 > x3) || y1 < y3)
	{
		c3 -= 1;
	}

	// moje deklarace
	int * index;
	S_Frag tmp_frag;

	/* koeficienty pro barycentricke souradnice */
	alpha = 1.0 / (ABS(s2) + 1);
	beta = 1.0 / (ABS(s3) + 1);

	/* vyplnovani... */
	for (y = miny; y <= maxy; ++y)
	{
		/* inicilizace hranove fce v bode (minx, y) */
		e1 = a1 * minx + b1 * y + c1;
		e2 = a2 * minx + b2 * y + c2;
		e3 = a3 * minx + b3 * y + c3;

		for (x = minx; x <= maxx; ++x)
		{
			if (e1 >= 0 && e2 >= 0 && e3 >= 0)
			{
				/* interpolace pomoci barycentrickych souradnic
				e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */
				w1 = alpha * e2;
				w2 = beta * e3;
				w3 = 1.0 - w1 - w2;

				/* interpolace z-souradnice */
				z = w1 * v1->z + w2 * v2->z + w3 * v3->z;

				/* interpolace barvy */
				color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red);
				color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green);
				color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue);
				color.alpha = ROUND2BYTE(w1 * col1.alpha + w2 * col2.alpha + w3 * col3.alpha);


				/* vykresleni bodu */
				if (z < DEPTH(pRenderer, x, y))
				{
					/*PIXEL(pRenderer, x, y) = color;
					DEPTH(pRenderer, x, y) = z;*/

					index = (int *)vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x);

					//tmp_index = *index;

					tmp_frag = makeFrag(color, z, *index);
					*index = fragvecPushBack(renderer->vecNodeBuff, tmp_frag);

					//printf("%d\n", fragvecGetPtr(renderer->vecNodeBuff, 0)->next);
				}
			}

			/* hranova fce o pixel vedle */
			e1 += a1;
			e2 += a2;
			e3 += a3;
		}
	}

	/* Razeni a pocitani vyslednych barev */
	// deklarace pro sorting
	int sortStart, sortIndex;
	int myDepth;

	// michani barev
	S_RGBA mixColor;
	double col_R, col_G, col_B, col_A;
	double aSrc;

	// pomocne fragmenty
	S_Frag * pattern;
	S_Frag myFragTMP;
	S_Frag * myFragment;

	// pruchod pro razeni
	for (y = miny; y <= maxy; ++y)
	{
		for (x = minx; x <= maxx; ++x)
		{
			// index byl deklarovan uz vyse
			index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x));

			if (*index != -1)
			{
				sortStart = *index;
				
				/* K razeni je pouzit radici algoritmus Select Sort */
				while ((myFragment = fragvecGetPtr(renderer->vecNodeBuff, sortStart))->next != -1)
				{
					sortStart = myFragment->next;
					sortIndex = myFragment->next;

					// dokud se neprojde "pole" na sebe navazujicich(indexujicich) prvku
					while (sortIndex != -1)
					{
						pattern = fragvecGetPtr(renderer->vecNodeBuff, sortIndex);

						// dojde k prohozeni hodnot, najde-li se mensi hloubka
						if (pattern->depth < myFragment->depth)
						{
							myFragTMP.depth = myFragment->depth;
							myFragTMP.color = myFragment->color;
							myFragment->depth = pattern->depth;
							myFragment->color = pattern->color;
							pattern->depth = myFragTMP.depth;
							pattern->color = myFragTMP.color;
						}

						sortIndex = pattern->next;
					}
				}
			}
		}
	}

	// pruchod pro michani barev
	for (y = miny; y <= maxy; ++y)
	{
		for (x = minx; x <= maxx; ++x)
		{
			// index byl deklarovan uz vyse
			index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x));

			if (*index != -1)
			{
				sortStart = *index;

				// michani barvy
				myDepth = 0;
				col_R = 0.0;
				col_G = 0.0;
				col_B = 0.0;
				col_A = 1.0;

				while (sortStart != -1)
				{
					pattern = fragvecGetPtr(renderer->vecNodeBuff, sortStart);

					aSrc = pattern->color.alpha / 255.0;

					col_R = col_A * pattern->color.red + col_R;
					col_G = col_A * pattern->color.green + col_G;
					col_B = col_A * pattern->color.blue + col_B;

					col_A = (1.0 - aSrc) * col_A;

					sortStart = pattern->next;
				}

				mixColor.alpha = 255;
				mixColor.red = ROUND2BYTE(col_R);
				mixColor.green = ROUND2BYTE(col_G);
				mixColor.blue = ROUND2BYTE(col_B);

				PIXEL(pRenderer, x, y) = mixColor;
				DEPTH(pRenderer, x, y) = myDepth;
			}
		}
	}
}
// . remove this node from the tree
// . used to remove the last node and replace it with a higher scorer
void TopTree::deleteNode ( int32_t i , uint8_t domHash ) {
	// sanity check
	if ( PARENT(i) == -2 ) { char *xx=NULL;*xx=0; }
	// get node
	//TopNode *t = &m_nodes[i];
	// debug
	//if ( ! checkTree ( false ) ) { char *xx = NULL; *xx = 0; }
	//if ( i == 262 )
	//	log("HEY");

	// if it was the low node, update it
	if ( i == m_lowNode ) {
		m_lowNode = getNext ( i );
		if ( m_lowNode == -1 ) { 
			log("toptree: toptree delete error node #%"INT32" "
			    "domHash=%"INT32" because next node is -1 numnodes=%"INT32"",
			    i,(int32_t)domHash,m_numUsedNodes);
		//char *xx=NULL;*xx=0; }
			//return;
		}
	}
	
	// update the vcount
	if      ( m_domCount[domHash] <  m_cap ) m_vcount -= 1.0;
	else if ( m_domCount[domHash] == m_cap ) m_vcount -= m_partial;
	// update the dom count
	m_domCount[domHash]--;
	// debug
	//if ( domHash == 0x35 )
	//	log("top: domCount down for 0x%"XINT32" now %"INT32"",domHash,m_domCount[domHash]);

	// parent of i
	int32_t iparent ;
	int32_t jparent ;
	// j will be the node that replace node #i
	int32_t j = i;
	// . now find a node to replace node #i
	// . get a node whose key is just to the right or left of i's key
	// . get i's right kid
	// . then get that kid's LEFT MOST leaf-node descendant
	// . this little routine is stolen from getNextNode(i)
	// . try to pick a kid from the right the same % of time as from left
	if ( ( m_pickRight     && RIGHT(j) >= 0 ) || 
	     ( LEFT(j)   < 0 && RIGHT(j) >= 0 )  ) {
		// try to pick a left kid next time
		m_pickRight = 0;
		// go to the right kid
		j = RIGHT ( j );
		// now go left as much as we can
		while ( LEFT ( j ) >= 0 ) j = LEFT ( j );
		// use node j (it's a leaf or has a right kid)
		goto gotReplacement;
	}
	// . now get the previous node if i has no right kid
	// . this little routine is stolen from getPrevNode(i)
	if ( LEFT(j) >= 0 ) {
		// try to pick a right kid next time
		m_pickRight = 1;
		// go to the left kid
		j = LEFT ( j );
		// now go right as much as we can
		while ( RIGHT ( j ) >= 0 ) j = RIGHT ( j );
		// use node j (it's a leaf or has a left kid)
		goto gotReplacement;
	}
	// . come here if i did not have any kids (i's a leaf node)
	// . get i's parent
	iparent = PARENT(i);
	// make i's parent, if any, disown him
	if ( iparent >= 0 ) {
		if   ( LEFT(iparent) == i ) LEFT (iparent) = -1;
		else                        RIGHT(iparent) = -1;
	}
	// empty him
	PARENT(i) = -2;
	// . reset the depths starting at iparent and going up until unchanged
	// . will balance at pivot nodes that need it
	//if ( m_doBalancing ) 
	setDepths ( iparent );

	// debug
	//if ( ! checkTree ( false ) ) { char *xx = NULL; *xx = 0; }

	goto done;

	// . now replace node #i with node #j
	// . i should not equal j at this point
 gotReplacement:

	// . j's parent should take j's one kid
	// . that child should likewise point to j's parent
	// . j should only have <= 1 kid now because of our algorithm above
	// . if j's parent is i then j keeps his kid
	jparent = PARENT(j);
	if ( jparent != i ) {
		// parent:    if j is my left  kid, then i take j's right kid
		// otherwise, if j is my right kid, then i take j's left kid
		if ( LEFT ( jparent ) == j ) {
			LEFT  ( jparent ) = RIGHT ( j );
			if (RIGHT(j)>=0) PARENT ( RIGHT(j) ) = jparent;
		}
		else {
			RIGHT ( jparent ) = LEFT   ( j );
			if (LEFT (j)>=0) PARENT ( LEFT(j) ) = jparent;
		}
	}

	// . j inherits i's children (providing i's child is not j)
	// . those children's parent should likewise point to j
	if ( LEFT (i) != j ) {
		LEFT (j) = LEFT (i);
		if ( LEFT(j) >= 0 ) PARENT(LEFT (j)) = j;
	}
	if ( RIGHT(i) != j ) {
		RIGHT(j) = RIGHT(i);
		if ( RIGHT(j) >= 0 ) PARENT(RIGHT(j)) = j;
	}
	// j becomes the kid of i's parent, if any
	iparent = PARENT(i);
	if ( iparent >= 0 ) {
		if   ( LEFT(iparent) == i ) LEFT (iparent) = j;
		else                        RIGHT(iparent) = j;
	}
	// iparent may be -1
	PARENT(j) = iparent;

	// if i was the head node now j becomes the head node
	if ( m_headNode == i ) m_headNode = j;

	// kill i
	PARENT(i) = -2;

	// return if we don't have to balance
	//if ( ! m_doBalancing ) return;
	// our depth becomes that of the node we replaced, unless moving j
	// up to i decreases the total depth, in which case setDepths() fixes
	DEPTH ( j ) = DEPTH ( i );
	// debug msg
	//fprintf(stderr,"... replaced %"INT32" it with %"INT32" (-1 means none)\n",i,j);
	// . recalculate depths starting at old parent of j
	// . stops at the first node to have the correct depth
	// . will balance at pivot nodes that need it
	if ( jparent != i ) setDepths ( jparent );
	else                setDepths ( j );

 done:

	// the guy we are deleting is now the first "empty node" and
	// he must link to the old empty node
	m_nodes[i].m_right = m_emptyNode;
	m_emptyNode = i;

	//m_lastKickedOutDocId = m_nodes[i].m_docId;

	// count it
	m_numUsedNodes--;
	// flag it
	m_kickedOutDocIds = true;

	// debug
	//if ( ! checkTree ( true ) ) { char *xx = NULL; *xx = 0; }
}
Пример #19
0
/* Graph reduction function. Destructively modifies the graph passed in.
 */
enum graphReductionResult
reduce_graph(struct node *root)
{
	enum graphReductionResult r = UNKNOWN;

	struct spine_stack *stack = NULL;

	unsigned long reduction_counter = 0;
	int max_redex_count = 0;

	/* Used to decide what to do next:
	 * at an application (interior node of graph)
	 * you can take the left branch into subtree,
	 * take the right branch, or pop the node and
	 * go "up" the tree. */
	enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP };
	enum Direction dir = DIR_LEFT;

	stack = new_spine_stack(64);

	/* root constitutes the "dummy" root node */
	root->updateable = root->left_addr;
	pushnode(stack, root, 1);

	D print_graph(root, 0, TOPNODE(stack)->sn);

	while (STACK_NOT_EMPTY(stack))
	{
		int pop_stack_cnt = 1;
		int performed_reduction = 0;
		struct node *topnode = TOPNODE(stack);
		const char *atom_name = NULL;

		switch (topnode->typ)
		{
		case APPLICATION:
			switch (dir)
			{
			case DIR_LEFT:
				topnode->updateable = topnode->left_addr;
				pushnode(stack, topnode->left, 0);
				D printf("push left branch on stack, depth now %d\n", DEPTH(stack));
				pop_stack_cnt = 0;
				break;

			case DIR_RIGHT:
				topnode->updateable = topnode->right_addr;
				pushnode(stack, topnode->right, 2);
				D printf("push right branch on stack, depth now %d\n", DEPTH(stack));
				pop_stack_cnt = 0;
				break;

			case DIR_UP:
				break;
			}
			break;

		case ATOM:
			/* node->typ indicates a combinator, which can comprise a built-in,
			 * or it can comprise a mere variable. Let node->rule decide. */
			if (topnode->rule && DEPTH(stack) >= (topnode->rule->required_depth + 2))
			{
				D {
					atom_name = topnode->name;
					printf("%s reduction (sn %d), stack depth %d, before: ",
						topnode->name,
						topnode->sn,
					 	DEPTH(stack)
					);
					print_graph(root->left, topnode->sn, topnode->sn);
				}

				pop_stack_cnt = topnode->rule->required_depth + 1;

				perform_reduction(stack);

				performed_reduction = 1;

			} else D {
				printf("%s atom, stack depth %d, required depth %d.\n",
					topnode->name,
				 	DEPTH(stack),
					topnode->rule? topnode->rule->required_depth + 2: -1
				);
			}
			if (performed_reduction) SS;
			break;
		}
Пример #20
0
/*
 * Put the character c on the screen at the current cursor position.
 * This routine handles wraparound and scrolling and understands not
 * to roll when splitw is set, i.e. we are working in the echo area.
 * There is a bunch of hacking here dealing with the difference between
 * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
 * code to deal with terminals which overstrike, including CRT's where
 * you can erase overstrikes with some work.  CRT's which do underlining
 * implicitly which has to be erased (like CONCEPTS) are also handled.
 */
int
vputchar(register int c)
{
	register cell *tp;
	register int d, m, n;

#ifndef	BIT8
	c &= (QUOTE|TRIM);
#endif
#ifdef TRACE
	if (trace)
		tracec(c);
#endif
	/* Fix problem of >79 chars on echo line. */
	if (destcol >= WCOLS-1 && splitw && destline == WECHO)
		pofix();
#ifdef	MB
	if (mb_cur_max > 1) {
		if (c == MULTICOL)
			return c;
		/*
		 * If a multicolumn character extends beyond the screen
		 * width, it must be put on the next line. A tilde is
		 * printed as an indicator but must disappear when the
		 * text is moved at a later time.
		 */
		if (c == ('~'|INVBIT|QUOTE))
			c = '~'|INVBIT;
		else if (c == ('~'|INVBIT))
			return c;
		else if (destcol < WCOLS && destcol +
				colsc(c==QUOTE ? ' ' : c&TRIM&~MULTICOL) - 1
				>= WCOLS)
			vputchar('~'|INVBIT|QUOTE);
	}
#endif	/* MB */
	if (destcol >= WCOLS) {
		destline += destcol / WCOLS;
		destcol %= WCOLS;
	}
	if (destline > WBOT && (!splitw || destline > WECHO))
		vrollup(destline);
	tp = vtube[destline] + destcol;
	if (c == QUOTE) {
		if (insmode) {
			/*
			 * When in insert mode, tabs have to expand
			 * to real, printed blanks.
			 */
			c = ' ' | QUOTE;
			goto def;
		}
		if (*tp == 0) {
			/*
			 * A ``space''.
			 */
			if ((hold & HOLDPUPD) == 0)
				*tp = QUOTE;
			destcol++;
			return c;
		}
		/*
		 * A ``space'' ontop of a part of a tab.
		 */
		if (*tp & QUOTE) {
			destcol++;
			return c;
		}
		c = ' ' | QUOTE;
		goto def;
	}

#ifdef	notdef
#ifdef	BIT8
	if (c == ' ' | QUOTE) {
		c = ' ';
		goto def;
	}
#endif
#endif
	switch (c) {

	case '\t':
		vgotab();
		return c;

	case ' ':
		/*
		 * We can get away without printing a space in a number
		 * of cases, but not always.  We get away with doing nothing
		 * if we are not in insert mode, and not on a CONCEPT-100
		 * like terminal, and either not in hardcopy open or in hardcopy
		 * open on a terminal with no overstriking, provided,
		 * in all cases, that nothing has ever been displayed
		 * at this position.  Ugh.
		 */
		if (!insmode && !IN && (state != HARDOPEN || OS)
		&& (*tp&QUOTE)) {
			*tp = ' ';
			destcol++;
			return c;
		}
		goto def;

def:
	default:
		d = *tp & TRIM;
		/*
		 * Now get away with doing nothing if the characters
		 * are the same, provided we are not in insert mode
		 * and if we are in hardopen, that the terminal has overstrike.
		 */
		if ((d & ~MULTICOL) == (c & TRIM & ~MULTICOL) && !insmode &&
				(state != HARDOPEN || OS) && c != MULTICOL) {
			n = colsc(d);
			for (m = 1; m < n; m++)
				if ((tp[m] & (MULTICOL|TRIM)) != MULTICOL)
					break;
			if (m == n) {
				if ((hold & HOLDPUPD) == 0)
					*tp = c | (n > 1 ? MULTICOL : 0);
				destcol += n;
				return c;
			}
		}
		/*
		 * Backwards looking optimization.
		 * The low level cursor motion routines will use
		 * a cursor motion right sequence to step 1 character
		 * right.  On, e.g., a DM3025A this is 2 characters
		 * and printing is noticeably slower at 300 baud.
		 * Since the low level routines are not allowed to use
		 * spaces for positioning, we discover the common
		 * case of a single space here and force a space
		 * to be printed.
		 */
		if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) {
			vputc(' ');
			outcol++;
		}

		/*
		 * This is an inline expansion a call to vcsync() dictated
		 * by high frequency in a profile.
		 */
		if (outcol != destcol || outline != destline)
			vgoto(destline, destcol);

		/*
		 * Deal with terminals which have overstrike.
		 * We handle erasing general overstrikes, erasing
		 * underlines on terminals (such as CONCEPTS) which
		 * do underlining correctly automatically (e.g. on nroff
		 * output), and remembering, in hardcopy mode,
		 * that we have overstruct something.
		 */
		if (!insmode && d && d != ' ' && d != (c & TRIM)) {
			if (EO && (OS || UL && (c == '_' || d == '_'))) {
				vputc(' ');
				outcol++, destcol++;
				back1();
			} else
				rubble = 1;
		}

		/*
		 * Unless we are just bashing characters around for
		 * inner working of insert mode, update the display.
		 */
		if ((hold & HOLDPUPD) == 0)
			*tp = c;

		/*
		 * In insert mode, put out the IC sequence, padded
		 * based on the depth of the current line.
		 * A terminal which had no real insert mode, rather
		 * opening a character position at a time could do this.
		 * Actually should use depth to end of current line
		 * but this rarely matters.
		 */
#ifdef	notdef
		if (insmode)
#else
		/*
		 * It seems today's termcap writers consider this
		 * an either-or situation; if both im and ic
		 * are used vi puts out additional spaces.
		 *
		 * SVR4 ex does not include this change. If it hits
		 * your terminal, change back to the old way and
		 * mail me a description.
		 *
		 * GR July 2000
		 */
		if (insmode && (!IM || !*IM))
#endif	/* !notdef */
		{
			n = colsc(c&TRIM);
			for (m = 0; m < n; m++)
				vputp(IC, DEPTH(vcline));
		}
		vputc(c & TRIM);

		/*
		 * In insert mode, IP is a post insert pad.
		 */
		if (insmode)
			vputp(IP, DEPTH(vcline));
		destcol++, outcol++;

		/*
		 * CONCEPT braindamage in early models:  after a wraparound
		 * the next newline is eaten.  It's hungry so we just
		 * feed it now rather than worrying about it.
		 * Fixed to use	return linefeed to work right
		 * on vt100/tab132 as well as concept.
		 */
		if (XN && outcol % WCOLS == 0) {
			vputc('\r');
			vputc('\n');
		}
	}
#ifdef	MB
	if (mb_cur_max > 1 && (d = colsc(c&TRIM&~MULTICOL)) > 1) {
		if ((hold & HOLDPUPD) == 0)
			*tp |= MULTICOL;
		while (--d) {
			if ((hold & HOLDPUPD) == 0)
				*++tp = MULTICOL;
			destcol++;
			outcol++;
		}
	}
#endif	/* MB */
	return c;
}
// returns false if tree had problem, true otherwise
bool TopTree::checkTree ( bool printMsgs ) {
	// now check parent kid correlations
	for ( int32_t i = 0 ; i < m_numUsedNodes ; i++ ) {
		// skip node if parents is -2 (unoccupied)
		if ( PARENT(i) == -2 ) continue;
		// if no left/right kid it MUST be -1
		if ( LEFT(i) < -1 )
			return log("query: toptree: checktree: left "
				   "kid %"INT32" < -1",i);
		if ( RIGHT(i) < -1 )
			return log("query: toptree: checktree: right "
				   "kid %"INT32" < -1",i);
		// check left kid
		if ( LEFT(i) >= 0 && PARENT(LEFT(i)) != i ) 
			return log("query: toptree: checktree: tree has "
				   "error %"INT32"",i);
		// then right kid
		if ( RIGHT(i) >= 0 && PARENT(RIGHT(i)) != i )
                       return log("query: toptree: checktree: tree has "
				  "error2 %"INT32"",i);
	}
	// now return if we aren't doing active balancing
	//if ( ! DEPTH ) return true;
	// debug -- just always return now
	if ( printMsgs ) log("***m_headNode=%"INT32", m_numUsedNodes=%"INT32"",
			      m_headNode,m_numUsedNodes);
	// verify that parent links correspond to kids
	for ( int32_t i = 0 ; i < m_numUsedNodes ; i++ ) {
		int32_t P = PARENT (i);
		if ( P == -2 ) continue; // deleted node
		if ( P == -1 && i != m_headNode ) 
			return log("query: toptree: checktree: node %"INT32" has "
				   "no parent",i);
		// check kids
		if ( P>=0 && LEFT(P) != i && RIGHT(P) != i ) 
			return log("query: toptree: checktree: node %"INT32"'s "
				    "parent disowned",i);
		// ensure i goes back to head node
		int32_t j = i;
		while ( j >= 0 ) { 
			if ( j == m_headNode ) break;
			j = PARENT(j);
		}
		if ( j != m_headNode ) 
			return log("query: toptree: checktree: node %"INT32"'s no "
				   "head node above",i);
		if ( printMsgs ) 
			fprintf(stderr,"***node=%"INT32" left=%"INT32" rght=%"INT32" "
				"prnt=%"INT32", depth=%"INT32"\n",
				i,LEFT(i),RIGHT(i),PARENT(i),
				(int32_t)DEPTH(i));
		//ensure depth
		int32_t newDepth = computeDepth ( i );
		if ( DEPTH(i) != newDepth ) 
			return log("query: toptree: checktree: node %"INT32"'s "
				   "depth should be %"INT32"",i,newDepth);
	}
	if ( printMsgs ) log("query: ---------------");
	// no problems found
	return true;
}
Пример #22
0
static VtFile *
vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int offset, int mode)
{
	int epb;
	u32int size;
	VtEntry e;
	VtFile *r;

	assert(p==nil || ISLOCKED(p));

	if(p == nil){
		assert(offset == 0);
		epb = 1;
	}else
		epb = p->dsize / VtEntrySize;

	if(b->type != VtDirType){
		werrstr("bad block type %#uo", b->type);
		return nil;
	}

	/*
	 * a non-active entry is the only thing that
	 * can legitimately happen here. all the others
	 * get prints.
	 */
	if(vtentryunpack(&e, b->data, offset % epb) < 0){
		fprint(2, "vtentryunpack failed: %r (%.*H)\n", VtEntrySize, b->data+VtEntrySize*(offset%epb));
		return nil;
	}
	if(!(e.flags & VtEntryActive)){
		werrstr("entry not active");
		return nil;
	}

	if(DEPTH(e.type) < sizetodepth(e.size, e.psize, e.dsize)){
		fprint(2, "depth %ud size %llud psize %ud dsize %ud\n",
			DEPTH(e.type), e.size, e.psize, e.dsize);
		werrstr("bad depth");
		return nil;
	}

	size = vtcacheblocksize(c);
	if(e.dsize > size || e.psize > size){
		werrstr("block sizes %ud, %ud bigger than cache block size %ud",
			e.psize, e.dsize, size);
		return nil;
	}

	r = vtmallocz(sizeof(VtFile));
	r->c = c;
	r->mode = mode;
	r->dsize = e.dsize;
	r->psize = e.psize;
	r->gen = e.gen;
	r->dir = (e.type & VtTypeBaseMask) == VtDirType;
	r->ref = 1;
	r->parent = p;
	if(p){
		qlock(&p->lk);
		assert(mode == VtOREAD || p->mode == VtORDWR);
		p->ref++;
		qunlock(&p->lk);
	}else{
		assert(b->addr != NilBlock);
		r->local = 1;
	}
	memmove(r->score, b->score, VtScoreSize);
	r->offset = offset;
	r->epb = epb;

	return r;
}
// this is the same as above but LEFT and RIGHT are swapped
int32_t TopTree::rotateLeft ( int32_t i ) {
	// i's left kid's LEFT kid takes his place
	int32_t A = i;
	int32_t N = RIGHT  ( A );
	int32_t W = RIGHT  ( N );
	int32_t X = LEFT ( N );
	int32_t Q = -1;
	int32_t T = -1;
	if ( X >= 0 ) {
		Q = RIGHT  ( X );
		T = LEFT ( X );
	}
	// let AP be A's parent
	int32_t AP = PARENT ( A );
	// whose the bigger subtree, W or X? (depth includes W or X itself)
	int32_t Wdepth = 0;
	int32_t Xdepth = 0;
	if ( W >= 0 ) Wdepth = DEPTH(W);
	if ( X >= 0 ) Xdepth = DEPTH(X);
	// debug msg
	//fprintf(stderr,"A=%"INT32" AP=%"INT32" N=%"INT32" W=%"INT32" X=%"INT32" Q=%"INT32" T=%"INT32" "
	//"Wdepth=%"INT32" Xdepth=%"INT32"\n",A,AP,N,W,X,Q,T,Wdepth,Xdepth);
	// goto Xdeeper if X is deeper
	if ( Wdepth < Xdepth ) goto Xdeeper;
	// N's parent becomes A's parent
	PARENT ( N ) = AP;
	// A's parent becomes N
	PARENT ( A ) = N;
	// X's parent becomes A
	if ( X >= 0 ) PARENT ( X ) = A;
	// A's parents kid becomes N
	if ( AP >= 0 ) {
		if ( RIGHT ( AP ) == A ) RIGHT  ( AP ) = N;
		else                    LEFT ( AP ) = N;
	}
	// if A had no parent, it was the headNode
	else {
		//fprintf(stderr,"changing head node from %"INT32" to %"INT32"\n",
		//m_headNode,N);
		m_headNode = N;
	}
	// N's LEFT kid becomes A
	LEFT ( N ) = A;
	// A's RIGHT  kid becomes X		
	RIGHT  ( A ) = X;
	// . compute A's depth from it's X and B kids
	// . it should be one less if Xdepth smaller than Wdepth
	// . might set DEPTH(A) to computeDepth(A) if we have problems
	if ( Xdepth < Wdepth ) DEPTH ( A ) -= 2;
	else                   DEPTH ( A ) -= 1;
	// N gains a depth iff W and X were of equal depth
	if ( Wdepth == Xdepth ) DEPTH ( N ) += 1;
	// now we're done, return the new pivot that replaced A
	return N;
	// come here if X is deeper
 Xdeeper:
	// X's parent becomes A's parent
	PARENT ( X ) = AP;
	// A's parent becomes X
	PARENT ( A ) = X;
	// N's parent becomes X
	PARENT ( N ) = X;
	// Q's parent becomes N
	if ( Q >= 0 ) PARENT ( Q ) = N;
	// T's parent becomes A
	if ( T >= 0 ) PARENT ( T ) = A;
	// A's parent's kid becomes X
	if ( AP >= 0 ) {
		if ( RIGHT ( AP ) == A ) RIGHT  ( AP ) = X;
		else	                LEFT ( AP ) = X;
	}
	// if A had no parent, it was the headNode
	else {
		//fprintf(stderr,"changing head node2 from %"INT32" to %"INT32"\n",
		//m_headNode,X);
		m_headNode = X;
	}
	// A's RIGHT     kid becomes T
	RIGHT  ( A ) = T;
	// N's LEFT    kid becomes Q
	LEFT ( N ) = Q;
	// X's RIGHT     kid becomes N
	RIGHT  ( X ) = N;
	// X's LEFT    kid becomes A
	LEFT ( X ) = A;
	// X's depth increases by 1 since it gained 1 level of 2 new kids
	DEPTH ( X ) += 1;
	// N's depth decreases by 1
	DEPTH ( N ) -= 1;
	// A's depth decreases by 2
	DEPTH ( A ) -= 2; 
	// now we're done, return the new pivot that replaced A
	return X;
}
Пример #24
0
static int
shrinkdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth)
{
	VtBlock *b, *nb, *ob, *rb;
	VtEntry oe;

	assert(ISLOCKED(r));
	assert(depth <= VtPointerDepth);

	rb = vtcacheglobal(r->c, e->score, e->type);
	if(rb == nil)
		return -1;

	/*
	 * Walk down to the new root block.
	 * We may stop early, but something is better than nothing.
	 */
	oe = *e;

	ob = nil;
	b = rb;
	for(; DEPTH(e->type) > depth; e->type--){
		nb = vtcacheglobal(r->c, b->data, e->type-1);
		if(nb == nil)
			break;
		if(ob!=nil && ob!=rb)
			vtblockput(ob);
		ob = b;
		b = nb;
	}

	if(b == rb){
		vtblockput(rb);
		return 0;
	}

	/*
	 * Right now, e points at the root block rb, b is the new root block,
	 * and ob points at b.  To update:
	 *
	 *	(i) change e to point at b
	 *	(ii) zero the pointer ob -> b
	 *	(iii) free the root block
	 *
	 * p (the block containing e) must be written before
	 * anything else.
 	 */

	/* (i) */
	memmove(e->score, b->score, VtScoreSize);
	vtentrypack(e, p->data, r->offset % r->epb);

	/* (ii) */
	memmove(ob->data, vtzeroscore, VtScoreSize);

	/* (iii) */
	vtblockput(rb);
	if(ob!=nil && ob!=rb)
		vtblockput(ob);
	vtblockput(b);

	if(DEPTH(e->type) == depth)
		return 0;
	return -1;
}
Пример #25
0
void
vappend(int ch, int cnt, int indent)
{
	int i;
	unsigned char *gcursor;
	bool escape;
	int repcnt, savedoomed;
	short oldhold = hold;
	int savecnt = cnt;
	line *startsrcline;
	int startsrccol, endsrccol;
	int gotNL = 0;
	int imultlinecnt = 0;
	int omultlinecnt = 0;

	if ((savecnt > 1) && (ch == 'o' || ch == 'O')) {
		omultlinecnt = 1;
	}
#ifdef XPG6
	if ((savecnt > 1) && (ch == 'a' || ch == 'A' || ch == 'i' || ch == 'I'))
		imultlinecnt = 1;
#endif /* XPG6 */

	/*
	 * Before a move in hardopen when the line is dirty
	 * or we are in the middle of the printed representation,
	 * we retype the line to the left of the cursor so the
	 * insert looks clean.
	 */

	if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
		rubble = 1;
		gcursor = cursor;
		i = *gcursor;
		*gcursor = ' ';
		wcursor = gcursor;
		(void) vmove();
		*gcursor = i;
	}
	/*
	 * If vrep() passed indent = 0, this is the 'r' command,
	 * so don't autoindent until the last char.
	 */
	vaifirst = indent == 0;

	/*
	 * Handle replace character by (eventually)
	 * limiting the number of input characters allowed
	 * in the vgetline routine.
	 */
	if (ch == 'r')
		repcnt = 2;
	else
		repcnt = 0;

	/*
	 * If an autoindent is specified, then
	 * generate a mixture of blanks to tabs to implement
	 * it and place the cursor after the indent.
	 * Text read by the vgetline routine will be placed in genbuf,
	 * so the indent is generated there.
	 */
	if (value(vi_AUTOINDENT) && indent != 0) {
		unsigned char x;
		gcursor = genindent(indent);
		*gcursor = 0;
		vgotoCL(nqcolumn(lastchr(linebuf, cursor), genbuf)); 
	} else {
		gcursor = genbuf;
		*gcursor = 0;
		if (ch == 'o')
			vfixcurs();
	}

	/*
	 * Prepare for undo.  Pointers delimit inserted portion of line.
	 */
	vUA1 = vUA2 = cursor;

	/*
	 * If we are not in a repeated command and a ^@ comes in
	 * then this means the previous inserted text.
	 * If there is none or it was too long to be saved,
	 * then beep() and also arrange to undo any damage done
	 * so far (e.g. if we are a change.)
	 */
	switch (ch) {
	case 'r':
		break;
	case 'a':
		/*
		 * TRANSLATION_NOTE
		 *	"A" is a terse mode message corresponding to
		 *	"APPEND MODE".
		 *	Translated message of "A" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("A"));
		} else {
			vshowmode(gettext("APPEND MODE"));
		}
		break;
	case 's':
		/*
		 * TRANSLATION_NOTE
		 *	"S" is a terse mode message corresponding to
		 *	"SUBSTITUTE MODE".
		 *	Translated message of "S" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("S"));
		} else {
			vshowmode(gettext("SUBSTITUTE MODE"));
		}
		break;
	case 'c':
		/*
		 * TRANSLATION_NOTE
		 *	"C" is a terse mode message corresponding to
		 *	"CHANGE MODE".
		 *	Translated message of "C" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("C"));
		} else {
			vshowmode(gettext("CHANGE MODE"));
		}
		break;
	case 'R':
		/*
		 * TRANSLATION_NOTE
		 *	"R" is a terse mode message corresponding to
		 *	"REPLACE MODE".
		 *	Translated message of "R" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("R"));
		} else {
			vshowmode(gettext("REPLACE MODE"));
		}
		break;
	case 'o':
		/*
		 * TRANSLATION_NOTE
		 *	"O" is a terse mode message corresponding to
		 *	"OPEN MODE".
		 *	Translated message of "O" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("O"));
		} else {
			vshowmode(gettext("OPEN MODE"));
		}
		break;
	case 'i':
		/*
		 * TRANSLATION_NOTE
		 *	"I" is a terse mode message corresponding to
		 *	"INSERT MODE" and the following "INPUT MODE".
		 *	Translated message of "I" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("I"));
		} else {
			vshowmode(gettext("INSERT MODE"));
		}
		break;
	default:
		/*
		 * TRANSLATION_NOTE
		 *	"I" is a terse mode message corresponding to
		 *	"INPUT MODE" and the previous "INSERT MODE".
		 *	Translated message of "I" must be 1 character (not byte).
		 *	Or, just leave it.
		 */
		if (value(vi_TERSE)) {
			vshowmode(gettext("I"));
		} else {
			vshowmode(gettext("INPUT MODE"));
		}
	}
	ixlatctl(1);
	if ((vglobp && *vglobp == 0) || peekbr()) {
		if (INS[128] == 0200) {
			(void) beep();
			if (!splitw)
				ungetkey('u');
			doomed = 0;
			hold = oldhold;
			return;
		}
		/*
		 * Unread input from INS.
		 * An escape will be generated at end of string.
		 * Hold off n^^2 type update on dumb terminals.
		 */
		vglobp = INS;
		inscdcnt = INSCDCNT;
		hold |= HOLDQIK;
	} else if (vglobp == 0) {
		/*
		 * Not a repeated command, get
		 * a new inserted text for repeat.
		 */
		INS[0] = 0;
		INS[128] = 0;
		INSCDCNT = 0;
	}

	/*
	 * For wrapmargin to hack away second space after a '.'
	 * when the first space caused a line break we keep
	 * track that this happened in gobblebl, which says
	 * to gobble up a blank silently.
	 */
	gobblebl = 0;

	startsrcline = dot;
	startsrccol = cursor - linebuf;

	/*
	 * Text gathering loop.
	 * New text goes into genbuf starting at gcursor.
	 * cursor preserves place in linebuf where text will eventually go.
	 */
	if (*cursor == 0 || state == CRTOPEN)
		hold |= HOLDROL;
	for (;;) {
		if (ch == 'r' && repcnt == 0)
			escape = 0;
		else {
			ixlatctl(1);
			/*
			 * When vgetline() returns, gcursor is
			 * pointing to '\0' and vgetline() has
			 * read an ESCAPE or NL.
			 */
			gcursor = vgetline(repcnt, gcursor, &escape, ch);
			if (escape == '\n') {
				gotNL = 1;
#ifdef XPG6
				if (ch == 'r') {
					/*
					 * XPG6 assertion 313 [count]r\n :
					 * Arrange to set cursor correctly.
					 */
					endsrccol = gcursor - genbuf - 1;
				}
#endif /* XPG6 */
			} else {
				/*
				 * Upon escape, gcursor is pointing to '\0'
				 * terminating the string in genbuf.
				 */
				endsrccol = gcursor - genbuf - 1;
			}
			ixlatctl(0);

			/*
			 * After an append, stick information
			 * about the ^D's and ^^D's and 0^D's in
			 * the repeated text buffer so repeated
			 * inserts of stuff indented with ^D as backtab's
			 * can work.
			 */
			if (HADUP)
				addtext("^");
			else if (HADZERO)
				addtext("0");
			if(!vglobp)
				INSCDCNT = CDCNT;
			while (CDCNT > 0) {
				addtext("\004");
				CDCNT--;
			}
			if (gobbled)
				addtext(" ");
			addtext(ogcursor);
		}
		repcnt = 0;

		/*
		 * Smash the generated and preexisting indents together
		 * and generate one cleanly made out of tabs and spaces
		 * if we are using autoindent and this isn't 'r' command.
		 */
		if (!vaifirst && value(vi_AUTOINDENT)) {
			i = fixindent(indent);
			if (!HADUP)
				indent = i;
			gcursor = strend(genbuf);
		}

		/*
		 * Set cnt to 1 to avoid repeating the text on the same line.
		 * Do this for commands 'i', 'I', 'a', and 'A', if we're
		 * inserting anything with a newline for XPG6.  Always do this
		 * for commands 'o' and 'O'.
		 */
		if ((imultlinecnt && gotNL) || omultlinecnt) {
			cnt = 1;
		}

		/*
		 * Limit the repetition count based on maximum
		 * possible line length; do output implied
		 * by further count (> 1) and cons up the new line
		 * in linebuf.
		 */
		cnt = vmaxrep(ch, cnt);
		/*
		 * cursor points to linebuf
		 * Copy remaining old text (cursor) in original
		 * line to after new text (gcursor + 1) in genbuf.
		 */
		CP(gcursor + 1, cursor);
		/*
		 * For [count] r \n command, when replacing [count] chars
		 * with '\n', this loop replaces [count] chars with "".
		 */
		do {
			/* cp new text (genbuf) into linebuf (cursor) */
			CP(cursor, genbuf);
			if (cnt > 1) {
				int oldhold = hold;

				Outchar = vinschar;
				hold |= HOLDQIK;
				viprintf("%s", genbuf);
				hold = oldhold;
				Outchar = vputchar;
			}
			/* point cursor after new text in linebuf */
			cursor += gcursor - genbuf;
		} while (--cnt > 0);
		endim();
		vUA2 = cursor;
		/* add the remaining old text after the cursor */
		if (escape != '\n')
			CP(cursor, gcursor + 1);

		/*
		 * If doomed characters remain, clobber them,
		 * and reopen the line to get the display exact.
		 * eg. c$ to change to end of line
		 */
		if (state != HARDOPEN) {
			DEPTH(vcline) = 0;
			savedoomed = doomed;
			if (doomed > 0) {
				int cind = cindent();

				physdc(cind, cind + doomed);
				doomed = 0;
			}
			if(MB_CUR_MAX > 1)
				rewrite = _ON;
			i = vreopen(LINE(vcline), lineDOT(), vcline);
			if(MB_CUR_MAX > 1)
				rewrite = _OFF;
#ifdef TRACE
			if (trace)
				fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
#endif
			if (ch == 'R')
				doomed = savedoomed;
		}

		/*
		 * Unless we are continuing on to another line
		 * (got a NL), break out of the for loop (got
		 * an ESCAPE).
		 */
		if (escape != '\n') {
			vshowmode("");
			break;
		}

		/*
		 * Set up for the new line.
		 * First save the current line, then construct a new
		 * first image for the continuation line consisting
		 * of any new autoindent plus the pushed ahead text.
		 */
		killU();
		addtext(gobblebl ? " " : "\n");
		/* save vutmp (for undo state) into temp file */
		vsave();
		cnt = 1;
		if (value(vi_AUTOINDENT)) {
			if (value(vi_LISP))
				indent = lindent(dot + 1);
			else
			     if (!HADUP && vaifirst)
				indent = whitecnt(linebuf);
			vaifirst = 0;
			strcLIN(vpastwh(gcursor + 1));
			gcursor = genindent(indent);
			*gcursor = 0;
			if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
				gcursor = genbuf;
			CP(gcursor, linebuf);
		} else {
			/*
			 * Put gcursor at start of genbuf to wipe
			 * out previous line in preparation for
			 * the next vgetline() loop.
			 */
			CP(genbuf, gcursor + 1);
			gcursor = genbuf;
		}

		/*
		 * If we started out as a single line operation and are now
		 * turning into a multi-line change, then we had better yank
		 * out dot before it changes so that undo will work
		 * correctly later.
		 */
		if (FIXUNDO && vundkind == VCHNG) {
			vremote(1, yank, 0);
			undap1--;
		}

		/*
		 * Now do the append of the new line in the buffer,
		 * and update the display, ie: append genbuf to
		 * the file after dot.  If slowopen
		 * we don't do very much.
		 */
		vdoappend(genbuf);
		vundkind = VMANYINS;
		vcline++;
		if (state != VISUAL)
			vshow(dot, NOLINE);
		else {
			i += LINE(vcline - 1);
			vopen(dot, i);
			if (value(vi_SLOWOPEN))
				vscrap();
			else
				vsync1(LINE(vcline));
		}
		switch (ch) {
		case 'r':
			break;
		case 'a':
			if (value(vi_TERSE)) {
				vshowmode(gettext("A"));
			} else {
				vshowmode(gettext("APPEND MODE"));
			}
			break;
		case 's':
			if (value(vi_TERSE)) {
				vshowmode(gettext("S"));
			} else {
				vshowmode(gettext("SUBSTITUTE MODE"));
			}
			break;
		case 'c':
			if (value(vi_TERSE)) {
				vshowmode(gettext("C"));
			} else {
				vshowmode(gettext("CHANGE MODE"));
			}
			break;
		case 'R':
			if (value(vi_TERSE)) {
				vshowmode(gettext("R"));
			} else {
				vshowmode(gettext("REPLACE MODE"));
			}
			break;
		case 'i':
			if (value(vi_TERSE)) {
				vshowmode(gettext("I"));
			} else {
				vshowmode(gettext("INSERT MODE"));
			}
			break;
		case 'o':
			if (value(vi_TERSE)) {
				vshowmode(gettext("O"));
			} else {
				vshowmode(gettext("OPEN MODE"));
			}
			break;
		default:
			if (value(vi_TERSE)) {
				vshowmode(gettext("I"));
			} else {
				vshowmode(gettext("INPUT MODE"));
			}
		}
		strcLIN(gcursor);
		/* zero genbuf */
		*gcursor = 0;
		cursor = linebuf;
		vgotoCL(nqcolumn(cursor - 1, genbuf));
	} /* end for (;;) loop in vappend() */

	if (imultlinecnt && gotNL) {
		imultlinerep(savecnt, startsrcline, startsrccol, endsrccol);
	} else if (omultlinecnt) {
		omultlinerep(savecnt, startsrcline, endsrccol);
#ifdef XPG6
	} else if (savecnt > 1 && ch == 'r' && gotNL) {
		/*
		 * XPG6 assertion 313 & 254 : Position cursor for [count]r\n
		 * then insert [count -1] newlines.
		 */
		endsrccol = gcursor - genbuf - 1;
		rmultlinerep(savecnt, endsrccol);
#endif /* XPG6 */
	}

	/*
	 * All done with insertion, position the cursor
	 * and sync the screen.
	 */
	hold = oldhold;
	if ((imultlinecnt && gotNL) || omultlinecnt) {
		fixdisplay();
#ifdef XPG6
	} else if (savecnt > 1 && ch == 'r' && gotNL) {
		fixdisplay();
		/*
		 * XPG6 assertion 313 & 254 [count]r\n : Set flag to call
		 * fixdisplay() after operate() has finished.  To be sure that
		 * the text (after the last \n followed by an indent) is always
		 * displayed, fixdisplay() is called right before getting
		 * the next command.
		 */
		redisplay = 1;
#endif /* XPG6 */
	} else if (cursor > linebuf) {
		cursor = lastchr(linebuf, cursor);
#ifdef XPG6
		/*
		 * XPG6 assertion 313 & 254 [count]r\n :
		 * For 'r' command, when the replacement char causes new
		 * lines to be created, point cursor to first non-blank.
		 * The old code, ie: cursor = lastchr(linebuf, cursor);
		 * set cursor to the blank before the first non-blank
		 * for r\n
		 */
		if (ch == 'r' && gotNL && isblank((int)*cursor))
			++cursor;
#endif /* XPG6 */
	}
	if (state != HARDOPEN)
		vsyncCL();
	else if (cursor > linebuf)
		back1();
	doomed = 0;
	wcursor = cursor;
	(void) vmove();
}
Пример #26
0
void
XDrawString_90(XWindow *xw, Drawable d,
               int x, int y, char *string, int length) {
  int i, j;
  XCharStruct size;
  unsigned int width, height;
  unsigned int x0, y0;
  XImage *in, *out;
  Pixmap pix;
  XGCValues val;

  XGetGCValues(DISPLAY(xw), xw->gc, GCForeground | GCBackground, &val);

  XTextSize(xw->font->font_core, string, length, &size);
  
  width  = -size.lbearing + size.rbearing;
  height =  size.ascent   + size.descent;
  x0     = -size.lbearing;
  y0     =  size.ascent;

  pix = XCreatePixmap(DISPLAY(xw), 
                      ROOT(xw),
                      width, height, 
                      DEPTH(xw));
  
  /* Background Fill */
  XSetForeground(DISPLAY(xw), xw->gc, val.background);
  XFillRectangle(DISPLAY(xw), pix, xw->gc, 0, 0, width, height);
  XSetForeground(DISPLAY(xw), xw->gc, val.foreground);

  XDrawString(DISPLAY(xw), pix, xw->gc, x0, y0, string, length);

  /* Convert from pixmap to image */
  in = XGetImage(DISPLAY(xw), pix, 0,0, width, height, AllPlanes, ZPixmap);
  XFreePixmap(DISPLAY(xw), pix);
  
  /* Create Image with Width and Height exchanged */
  out = XCreateImage(DISPLAY(xw),
                     VISUAL(xw),
                     DEPTH(xw),
                     ZPixmap, 0, NULL, height, width, 32, 0);
  out->data = (char *) malloc(sizeof(char) * width * out->bytes_per_line);

  /* "Rotate" Image */
  for(j = 0; j < (int)height; j++) {
      for(i = 0; i < (int)width; i++) {
      /* width - i - 1 : Flip the Image Vertically  */
      XPutPixel(out, j, width - i - 1, XGetPixel(in, i, j));
    }
  }
  pix = XCreatePixmap(DISPLAY(xw),
                      ROOT(xw),
                      height, width, 
                      DEPTH(xw));
  XPutImage(DISPLAY(xw), pix, xw->gc, out, 0, 0, 0, 0, height, width);
  XCopyArea(DISPLAY(xw), pix, d, xw->gc, 0, 0, height, width, x, y);

  XFreePixmap(DISPLAY(xw), pix);
  XDestroyImage(out);
  XDestroyImage(in);
}
Пример #27
0
void studrenDrawTriangle(S_Renderer *pRenderer,
                         S_Coords *v1, S_Coords *v2, S_Coords *v3,
                         S_Coords *n1, S_Coords *n2, S_Coords *n3,
						 S_Coords *t0, S_Coords *t1, S_Coords *t2,
                         int x1, int y1,
                         int x2, int y2,
                         int x3, int y3,
						 double h1, double h2, double h3
                         )
{

	int         minx, miny, maxx, maxy;
	int         a1, a2, a3, b1, b2, b3, c1, c2, c3;
	int         s1, s2, s3;
	int         x, y, e1, e2, e3;
	double      alpha, beta, gamma, w1, w2, w3, z, u, v;
	S_RGBA      col1, col2, col3, color;

	IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3);

	/* vypocet barev ve vrcholech */
	col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
	col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
	col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

	/* obalka trojuhleniku */
	minx = MIN(x1, MIN(x2, x3));
	maxx = MAX(x1, MAX(x2, x3));
	miny = MIN(y1, MIN(y2, y3));
	maxy = MAX(y1, MAX(y2, y3));

	/* oriznuti podle rozmeru okna */
	miny = MAX(miny, 0);
	maxy = MIN(maxy, pRenderer->frame_h - 1);
	minx = MAX(minx, 0);
	maxx = MIN(maxx, pRenderer->frame_w - 1);

	/* Pineduv alg. rasterizace troj.
	   hranova fce je obecna rovnice primky Ax + By + C = 0
	   primku prochazejici body (x1, y1) a (x2, y2) urcime jako
	   (y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */

	/* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */
	a1 = y1 - y2;
	a2 = y2 - y3;
	a3 = y3 - y1;
	b1 = x2 - x1;
	b2 = x3 - x2;
	b3 = x1 - x3;

	/* koeficient C */
	c1 = x1 * y2 - x2 * y1;
	c2 = x2 * y3 - x3 * y2;
	c3 = x3 * y1 - x1 * y3;

	/* vypocet hranove fce (vzdalenost od primky) pro protejsi body */
	s1 = a1 * x3 + b1 * y3 + c1;
	s2 = a2 * x1 + b2 * y1 + c2;
	s3 = a3 * x2 + b3 * y2 + c3;

	if ( !s1 || !s2 || !s3 )
	{
		return;
	}

	/* normalizace, aby vzdalenost od primky byla kladna uvnitr trojuhelniku */
	if( s1 < 0 )
	{
		a1 *= -1;
		b1 *= -1;
		c1 *= -1;
	}
	if( s2 < 0 )
	{
		a2 *= -1;
		b2 *= -1;
		c2 *= -1;
	}
	if( s3 < 0 )
	{
		a3 *= -1;
		b3 *= -1;
		c3 *= -1;
	}

	/* koeficienty pro barycentricke souradnice */
	alpha = 1.0 / ABS(s2);
	beta = 1.0 / ABS(s3);
	gamma = 1.0 / ABS(s1);

	S_RGBA newColor;
	/* vyplnovani... */
	for( y = miny; y <= maxy; ++y )
	{
		/* inicilizace hranove fce v bode (minx, y) */
		e1 = a1 * minx + b1 * y + c1;
		e2 = a2 * minx + b2 * y + c2;
		e3 = a3 * minx + b3 * y + c3;

		for( x = minx; x <= maxx; ++x )
		{
			if( e1 >= 0 && e2 >= 0 && e3 >= 0 )
			{
				/* interpolace pomoci barycentrickych souradnic
				   e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */
				w1 = alpha * e2;
				w2 = beta * e3;
				w3 = gamma * e1;

				/* interpolace z-souradnice */
				z = w1 * v1->z + w2 * v2->z + w3 * v3->z;

				double jmenovatel = w1 / h1 + w2 / h2 + w3 / h3;
				u = (w1 * t0->x / h1) + (w2 * t1->x / h2) + (w3 * t2->x / h3);
				v = (w1 * t0->y / h1) + (w2 * t1->y / h2) + (w3 * t2->y / h3);

				u = u / jmenovatel;
				v = v / jmenovatel;

				newColor = studrenTextureValue((S_StudentRenderer *)pRenderer, u, v);


				/* interpolace barvy */
				color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red) * (newColor.red / 255.0);
				color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green) * (newColor.green / 255.0);
				color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue) * (newColor.blue / 255.0);
				color.alpha = 255;

				/* vykresleni bodu */
				if( z < DEPTH(pRenderer, x, y) )
				{
					PIXEL(pRenderer, x, y) = color;
					DEPTH(pRenderer, x, y) = z;
				}
			}

			/* hranova fce o pixel vedle */
			e1 += a1;
			e2 += a2;
			e3 += a3;
		}
	}
}
Пример #28
0
void studrenDrawTriangle(S_Renderer *pRenderer,
                         S_Coords *v1, S_Coords *v2, S_Coords *v3,
                         S_Coords *n1, S_Coords *n2, S_Coords *n3,
                         int x1, int y1,
                         int x2, int y2,
                         int x3, int y3
                         )
{
    // oblast trojuhelniku
    int min[2] = {
        MIN(x1, MIN(x2, x3)),
        MIN(y1, MIN(y2, y3))
    };
    int max[2] = {
        MAX(x1, MAX(x2, x3)),
        MAX(y1, MAX(y2, y3))
    };

    // oriznuti rozmerem okna
    min[0] = MAX(min[0], 0);
    min[1] = MAX(min[1], 0);
    max[0] = MIN(max[0], pRenderer->frame_w - 1);
    max[1] = MIN(max[1], pRenderer->frame_h - 1);

    // pro urceni hranic trojuhelnika pouzijeme pineduv algoritmus
    // hranova funkce je rovnice Ax + By + C = 0
    // A,B je normalovy vektor primky, tzn. (-dy, dx)
    // C vyjadrime jako x1y2 - x2y1
    int A[3] = {
        { y1 - y2 },
        { y2 - y3 },
        { y3 - y1 }
    };
    int B[3] = {
        { x2 - x1 },
        { x3 - x2 },
        { x1 - x3 }
    };
    int C[3] = {
        { x1 * y2 - x2 * y1 },
        { x2 * y3 - x3 * y2 },
        { x3 * y1 - x1 * y3 }
    };

    // do hranove funkce dosadime protejsi vrcholy
    // provedeme normalizaci, aby kladna strana byla uvnitr oblasti
    int s0 = A[0] * x3 + B[0] * y3 + C[0];
    int s1 = A[1] * x1 + B[1] * y1 + C[1];
    int s2 = A[2] * x2 + B[2] * y2 + C[2];

    if (s0 < 0) {
        A[0] *= -1; B[0] *= -1; C[0] *= -1;
        s0 *= -1;
    }
    if (s1 < 0) {
        A[1] *= -1; B[1] *= -1; C[1] *= -1;
        s1 *= -1;
    }
    if (s2 < 0) {
        A[2] *= -1; B[2] *= -1; C[2] *= -1;
        s2 *= -1;
    }

    double _s0 = 1.0f / (double)s0;
    double _s1 = 1.0f / (double)s1;
    double _s2 = 1.0f / (double)s2;

    /* gourandovo stinovani */
    //S_RGBA color, b1, b2, b3;
    //b1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
    //b2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
    //b3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

    // vyplnovani pinedovim algoritmem
    for (int y = min[1]; y <= max[1]; ++y) {
        int e[3] = {
            A[0] * min[0] + B[0] * y + C[0],
            A[1] * min[0] + B[1] * y + C[1],
            A[2] * min[0] + B[2] * y + C[2]
        };

        for (int x = min[0]; x <= max[0]; ++x) {
            // uvnitr trojuhelniku jsou cisla kladna
            if (e[0] >= 0 && e[1] >= 0 && e[2] >= 0) {

                // spocitame barycentricke koeficienty u,v,w
                double u = e[1] * _s1;
                double v = e[2] * _s2;
                double w = e[0] * _s0;

                // nemelo by nastat, protoze jsme uvnitr trojuhelniku
                //if (u < 0.0f || u > 1.0f) continue;
                //if (v < 0.0f || v > 1.0f) continue;
                //if (w < 0.0f || w > 1.0f) continue;

                // bod v trojuhelniku pred projekci ve 3D
                S_Coords pt = makeCoords(
                    u * v1->x + v * v2->x + w * v3->x,
                    u * v1->y + v * v2->y + w * v3->y,
                    u * v1->z + v * v2->z + w * v3->z);

                /* gourandovo stinovani */
                //double r = u * b1.red   + v * b2.red   + w * b3.red;
                //double g = u * b1.green + v * b2.green + w * b3.green;
                //double b = u * b1.blue  + v * b2.blue  + w * b3.blue;
                //double a = u * b1.alpha + v * b2.alpha + w * b3.alpha;

                //r = MIN(255.0f, MAX(r, 0.0f));
                //g = MIN(255.0f, MAX(g, 0.0f));
                //b = MIN(255.0f, MAX(b, 0.0f));
                //a = MIN(255.0f, MAX(a, 0.0f));

                //color.red   = ROUND2BYTE(r);
                //color.green = ROUND2BYTE(g);
                //color.blue  = ROUND2BYTE(b);
                //color.alpha = ROUND2BYTE(a);

                // vektor smerujici od bodu ke kamere
                S_Coords P_Cam = makeCoords(
                    -pt.x,
                    -pt.y,
                    -pRenderer->camera_dist - pt.z);

                // vykreslime jen blizsi body
                double depth = sqrt(P_Cam.x * P_Cam.x + P_Cam.y * P_Cam.y + P_Cam.z * P_Cam.z);
                if (depth <= DEPTH(pRenderer, x, y))
                {
                    // normala bodu
                    S_Coords n = makeCoords(
                        u * n1->x + v * n2->x + w * n3->x,
                        u * n1->y + v * n2->y + w * n3->y,
                        u * n1->z + v * n2->z + w * n3->z);
                    coordsNormalize(&n);

                    S_RGBA color;
                    color = pRenderer->calcReflectanceFunc(pRenderer, &pt, &n);

                    /* vybarvi objekt normalou */
                    //color.red = ROUND2BYTE(255.0f * (n.x / 2.0f + 0.5f));
                    //color.green = ROUND2BYTE(255.0f * (n.y / 2.0f + 0.5f));
                    //color.blue = ROUND2BYTE(255.0f * (-n.z / 2.0f + 0.5f));
                    //color.alpha = 255;

                    DEPTH(pRenderer, x, y) = depth;
                    PIXEL(pRenderer, x, y) = color;
                }
            }

            // Ei(x+1,y) = Ei(x,y) + dy
            e[0] += A[0];
            e[1] += A[1];
            e[2] += A[2];
        }
    }
}