From 8646689a297b8188fac13d5dd4ee7011a940ac06 Mon Sep 17 00:00:00 2001
From: Etienne Brateau <etienne.brateau@ensiie.fr>
Date: Wed, 18 Jul 2018 23:56:28 +0200
Subject: [PATCH] First pass splitting log.c

---
 log/src/gate.c   |  527 +++++
 log/src/label.c  |  388 ++++
 log/src/log.c    | 5798 ++++++----------------------------------------
 log/src/page.c   |  110 +
 log/src/screen.c | 2426 +++++++++++++++++++
 log/src/tool.c   |  200 ++
 log/src/wire.c   |  663 ++++++
 7 files changed, 5054 insertions(+), 5058 deletions(-)
 create mode 100644 log/src/gate.c
 create mode 100644 log/src/label.c
 create mode 100644 log/src/page.c
 create mode 100644 log/src/screen.c
 create mode 100644 log/src/tool.c
 create mode 100644 log/src/wire.c

diff --git a/log/src/gate.c b/log/src/gate.c
new file mode 100644
index 0000000..c2a6dd1
--- /dev/null
+++ b/log/src/gate.c
@@ -0,0 +1,527 @@
+
+#include <p2c/p2c.h>
+
+/*================  INSIDEGATE  ==================*/
+/*=                                              =*/
+/*=  Check if inside a gate's "yellow box."      =*/
+/*=                                              =*/
+/*================================================*/
+
+/* new version by Tim Edwards, Dec 1996 */
+
+static int insidegate(log_grec *g, short x, short y)
+{
+	short xx1, xx2, yy1, yy2, z;
+	short loc_x1, loc_x2;
+	log_krec *WITH;
+
+	x = (x - g->x) * log_scale0;
+	y = (y - g->y) * log_scale0;
+	WITH = g->kind;
+	loc_x1 = WITH->x1;
+	loc_x2 = WITH->x2;
+
+	/* Modify x1 position for length of text on TO/FROM-type gates */
+
+	if (WITH->flag.U3.named && g->sig > 0)
+	{
+		char STR1[256];
+		short xwid = m_strwidth(NULL, strrtrim(strcpy(STR1,
+						gg.signaltab[g->sig - 1].name))) - NAMEGAP;
+
+		if (WITH->flag.U3.nright)
+		{
+			if (xwid > loc_x2) loc_x2 = xwid;
+		}
+		else
+		{
+			if (-xwid < loc_x1) loc_x1 = -xwid;
+		}
+	}
+
+	if (g->rot == 0)
+	{
+		return (loc_x1 <= x && x <= loc_x2 && WITH->y1 <= y && y <= WITH->y2);
+	}
+	else
+	{
+		z = g->rot;
+		xx1 = loc_x1 * log_rotxx[z] + WITH->y1 * log_rotyx[z];
+		xx2 = loc_x2 * log_rotxx[z] + WITH->y2 * log_rotyx[z];
+		sortshints(&xx1, &xx2);
+		yy1 = loc_x1 * log_rotxy[z] + WITH->y1 * log_rotyy[z];
+		yy2 = loc_x2 * log_rotxy[z] + WITH->y2 * log_rotyy[z];
+		sortshints(&yy1, &yy2);
+		return (xx1 <= x && x <= xx2 && yy1 <= y && y <= yy2);
+	}
+}
+
+#define rtn             "ERAGATE"
+
+/*==================  ERAGATE  ===================*/
+/*=                                              =*/
+/*=  Erase a gate (including LED's and other     =*/
+/*=     "magic" stuff) using grid coordinates.   =*/
+/*=                                              =*/
+/*================================================*/
+
+static void eragate(log_grec *g)
+{
+	log_grec *g1, *g2;
+
+	if (g->conflict || g->oconflict)
+	{
+		g1 = gateconflictbase;
+		g2 = NULL;
+		while (g1 != NULL && g1 != g)
+		{
+			g2 = g1;
+			g1 = g1->confnext;
+		}
+
+		if (g1 == NULL)
+			report(10, rtn);
+		else if (g2 == NULL)
+			gateconflictbase = g->confnext;
+		else
+			g2->confnext = g->confnext;
+		g->conflict = false;
+		g->conflict1 = false;
+		g->conflict2 = false;
+		g->oconflict = false;
+	}
+	drawgatec(g->x, g->y, g->g, gg.color.backgr);
+	gsignallabel(g->x, g->y, g, gg.color.backgr);
+	if (g->kind->numpnums > 0)
+		drawpnums(g, gg.color.backgr);
+	drawgatedotsc(g->x, g->y, g->g, gg.color.backgr);
+	calltoolgate(g, act_erasegate);
+}
+
+#undef rtn
+
+/*==================  LINKGATE  ==================*/
+/*=                                              =*/
+/*=  Add a gate to the gate list.                =*/
+/*=                                              =*/
+/*================================================*/
+
+static void linkgate(log_grec **g)
+{
+	(*g)->next = gg.gbase[gg.curpage - 1];
+	gg.gbase[gg.curpage - 1] = *g;
+	chpageplace((int)gg.curpage, (*g)->x - (*g)->kind->bbmax,
+			(*g)->y - (*g)->kind->bbmax, (*g)->x + (*g)->kind->bbmax,
+			(*g)->y + (*g)->kind->bbmax);
+}
+
+/*===================  NEWGATE  ==================*/
+/*=                                              =*/
+/*=  Create a gate.                              =*/
+/*=                                              =*/
+/*================================================*/
+
+static void newgptr(log_grec **g)
+{
+	if (freegate == NULL)
+	{
+		*g = (log_grec *)Malloc(sizeof(log_grec));
+	}
+	else
+	{
+		*g = freegate;
+		freegate = freegate->next;
+	}
+}
+
+
+static void newgate2(log_grec **g, short gt, short sig, log_gattrrec *attrs)
+{
+	short i;
+	char name[256];
+
+	newgptr(g);
+	(*g)->g = gt;
+	(*g)->rot = gt / log_kindoffset;
+	(*g)->kind = kind[(gt & (log_kindoffset - 1)) - 1];
+	(*g)->vars = (na_long)0;
+	(*g)->conflict = false;
+	(*g)->conflict1 = false;
+	(*g)->conflict2 = false;
+	(*g)->oconflict = false;
+	(*g)->dimcolor = false;
+	(*g)->pin = (log_nrec **)Malloc((*g)->kind->numpins * sizeof(log_nrec *));
+	(*g)->pinpos = (log_pinposrec *)
+		Malloc((*g)->kind->numpins * sizeof(log_pinposrec));
+	if (attrs != NULL)
+		copyattrs(&(*g)->attr, attrs, (*g)->kind->numattrs, (*g)->kind->attr);
+	else
+		newattrs(&(*g)->attr, (*g)->kind->numattrs, (*g)->kind->attr);
+
+	if (sig != 0)
+	{
+		(*g)->sig = sig;
+	}
+	else if ((*g)->kind->simtype == simtype_common)
+	{
+		*name = '\0';
+		i = 1;
+		while ((*g)->kind->proc[i - 1] != '\0')
+		{
+			sprintf(name + strlen(name), "%c", (*g)->kind->proc[i - 1]);
+			i++;
+		}
+		(*g)->sig = getsignal(0, name);
+	}
+	else
+	{
+		(*g)->sig = 0;
+	}
+	(*g)->info = (na_long)0;
+	(*g)->temp = (na_long)0;
+	gg.actflag = (attrs != NULL);
+	calltoolgate(*g, act_newgate);
+}
+
+
+static void newgate(log_grec **g, short gt)
+{
+	newgate2(g, gt, 0, NULL);
+}
+
+
+/*================  COPYGATE  ====================*/
+/*=                                              =*/
+/*=  Make a copy of a gate (unlinked).           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void copygate(log_grec *old, log_grec **g)
+{
+	long i, FORLIM;
+
+	newgptr(g);
+	**g = *old;
+	if ((*g)->conflict || (*g)->oconflict)
+	{
+		(*g)->confnext = gateconflictbase;
+		gateconflictbase = *g;
+	}
+	(*g)->pin = (log_nrec **)Malloc((*g)->kind->numpins * sizeof(log_nrec *));
+	FORLIM = (*g)->kind->numpins;
+	for (i = 0; i < FORLIM; i++)
+		(*g)->pin[i] = old->pin[i];
+	(*g)->pinpos = (log_pinposrec *)
+		Malloc((*g)->kind->numpins * sizeof(log_pinposrec));
+	FORLIM = (*g)->kind->numpins;
+	for (i = 0; i < FORLIM; i++)
+		(*g)->pinpos[i] = old->pinpos[i];
+	copyattrs(&(*g)->attr, old->attr, (*g)->kind->numattrs, (*g)->kind->attr);
+	(*g)->info = (na_long)0;
+	gg.actgate2 = old;
+	calltoolgate(*g, act_copygate);
+}
+
+
+/*==================  UNLKGATE  ==================*/
+/*=                                              =*/
+/*=  Remove a gate from gate list.               =*/
+/*=                                              =*/
+/*================================================*/
+
+static void unlkgate(log_grec **g)
+{
+	log_grec *g1;
+
+	g1 = gg.gbase[gg.curpage - 1];
+	while (g1 != NULL && g1->next != *g)
+		g1 = g1->next;
+	if (g1 == NULL)
+		gg.gbase[gg.curpage - 1] = (*g)->next;
+	else
+		g1->next = (*g)->next;
+	chpageplace((int)gg.curpage, (*g)->x - (*g)->kind->bbmax,
+			(*g)->y - (*g)->kind->bbmax, (*g)->x + (*g)->kind->bbmax,
+			(*g)->y + (*g)->kind->bbmax);
+}
+
+
+/*===============  DISPOSEGATE  ==================*/
+/*=                                              =*/
+/*=  Dispose of a gate.                          =*/
+/*=                                              =*/
+/*================================================*/
+
+static void disposegptr(log_grec **g)
+{
+	(*g)->next = freegate;
+	freegate = *g;
+}
+
+
+#define rtn             "DISPOSEGATE"
+
+
+static void disposegate(log_grec **g)
+{
+	log_grec *g1, *g2;
+
+	if ((*g)->conflict || (*g)->oconflict)
+	{
+		g1 = gateconflictbase;
+		g2 = NULL;
+		while (g1 != NULL && g1 != *g)
+		{
+			g2 = g1;
+			g1 = g1->confnext;
+		}
+		if (g1 == NULL)
+			report(10, rtn);
+		else if (g2 == NULL)
+			gateconflictbase = (*g)->confnext;
+		else
+			g2->confnext = (*g)->confnext;
+	}
+	if (*g == gg.probegate)
+		gg.probegate = NULL;
+	calltoolgate(*g, act_disposegate);
+	disposeattrs(&(*g)->attr, (*g)->kind->numattrs, (*g)->kind->attr);
+	Free((*g)->pin);
+	Free((*g)->pinpos);
+	disposegptr(g);
+}
+
+#undef rtn
+
+/*================  CLOSERGATE  ==================*/
+/*=                                              =*/
+/*=  Find which gate (if any) is under cursor.   =*/
+/*=  Also checks for textual labels.             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void closergate(short x, short y)
+{
+	if (gg.textinvisible)
+		gg.nearlabel = NULL;
+	else {
+		gg.nearlabel = gg.lbase[gg.curpage - 1];
+		while (gg.nearlabel != NULL &&
+				(x < gg.nearlabel->x ||
+				 x > gg.nearlabel->x + m_strwidth(logfont_lfont,
+					 gg.nearlabel->name) / gg.scale ||
+				 y < gg.nearlabel->y || y > gg.nearlabel->y + 2)) {
+			gg.nearlabel = gg.nearlabel->next;
+		}
+	}
+	if (gg.nearlabel != NULL) {
+		gg.nearbox = NULL;
+		gg.neargate = NULL;
+		return;
+	}
+	if (!gg.textinvisible) {
+		gg.nearbox = gg.bbase[gg.curpage - 1];
+		while (gg.nearbox != NULL &&
+				((x != gg.nearbox->x1 && x != gg.nearbox->x2 &&
+				  y != gg.nearbox->y1 &&
+				  y != gg.nearbox->y2) || x < gg.nearbox->x1 ||
+				 x > gg.nearbox->x2 || y < gg.nearbox->y1 || y > gg.nearbox->y2))
+			gg.nearbox = gg.nearbox->next;
+	} else
+		gg.nearbox = NULL;
+	if (gg.nearbox != NULL)
+	{
+		gg.neargate = NULL;
+		return;
+	}
+	gg.neargate = gg.gbase[gg.curpage - 1];
+	while (gg.neargate != NULL && !insidegate(gg.neargate, x, y))
+		gg.neargate = gg.neargate->next;
+}
+
+#define rtn             "CHGGATE"
+
+
+static void chggate(log_grec *g, int i, log_nrec *oldnode, log_nrec *n)
+{
+	log_hwrec *hw;
+	log_vwrec *vw;
+	log_grec *g1;
+	short j, k, savepg, pg, x, y, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Change gate %ld pin %d to node %ld\n",
+				(long)g, i, (long)n);
+	j = i;
+	do
+	{
+		if (g->pin[j - 1] == oldnode)
+		{
+			switchnode(&g->pin[j - 1], n);
+			/* if (j <> i) then  */
+			/*unsafe optimization*/
+			x = g->pinpos[j - 1].x;
+			y = g->pinpos[j - 1].y;
+			hw = gg.hwbase[gg.curpage - 1];
+			while (hw != NULL)
+			{
+				if (hw->x1 <= x && x <= hw->x2 && hw->y == y && hw->node == oldnode)
+					chghw(hw, oldnode, n);
+				hw = hw->next;
+			}
+			vw = gg.vwbase[gg.curpage - 1];
+			while (vw != NULL)
+			{
+				if (vw->y1 <= y && y <= vw->y2 && vw->x == x && vw->node == oldnode)
+					chgvw(vw, oldnode, n);
+				vw = vw->next;
+			}
+			g1 = gg.gbase[gg.curpage - 1];
+			while (g1 != NULL)
+			{
+				if (g1 != g && P_imax2((long)abs(g1->x - x), (long)abs(g1->y - y)) <=
+						g1->kind->bbmax) {
+					FORLIM = g1->kind->numpins;
+					for (k = 1; k <= FORLIM; k++) {
+						if (x == g1->pinpos[k - 1].x && y == g1->pinpos[k - 1].y &&
+								g1->pin[k - 1] == oldnode)
+							chggate(g1, k, oldnode, n);
+					}
+				}
+				g1 = g1->next;
+			}
+		}
+		j = g->kind->pin[j - 1].c;
+	} while (j != i && j != 0);
+	if (i != 1 || g->kind->simtype != simtype_common || g->sig == 0 ||
+			gg.signaltab[g->sig - 1].np != oldnode)
+		return;
+	switchnode(&gg.signaltab[g->sig - 1].np, n);
+	savepg = gg.curpage;
+	FORLIM = gg.numpages;
+	for (pg = 1; pg <= FORLIM; pg++)
+	{
+		gg.curpage = pg;
+		g1 = gg.gbase[gg.curpage - 1];
+		while (g1 != NULL)
+		{
+			if (g1->kind->simtype == simtype_common && g1->sig == g->sig &&
+					g1->pin[0] == oldnode)
+				chggate(g1, 1, oldnode, n);
+			g1 = g1->next;
+		}
+	}
+	gg.curpage = savepg;
+}
+
+#undef rtn
+
+static void chggatepin(log_grec *g, short i, log_nrec **oldnode, log_nrec **savenode)
+{
+	log_nrec *n;
+	log_hwrec *hw;
+	log_vwrec *vw;
+	log_grec *g1;
+	short j, x, y, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Change gate %ld pin %d from node %ld\n",
+				(long)g, i, (long)(*oldnode));
+	x = g->pinpos[i - 1].x;
+	y = g->pinpos[i - 1].y;
+	hw = gg.hwbase[gg.curpage - 1];
+	while (hw != NULL)
+	{
+		if (hw->x1 <= x && x <= hw->x2 && hw->y == y && hw->node == *oldnode)
+		{
+			delgetnode(savenode, oldnode, &n);
+			if (n != *oldnode)
+				chghw(hw, *oldnode, n);
+		}
+		hw = hw->next;
+	}
+	vw = gg.vwbase[gg.curpage - 1];
+	while (vw != NULL)
+	{
+		if (vw->y1 <= y && y <= vw->y2 && vw->x == x && vw->node == *oldnode)
+		{
+			delgetnode(savenode, oldnode, &n);
+			if (n != *oldnode)
+				chgvw(vw, *oldnode, n);
+		}
+		vw = vw->next;
+	}
+	g1 = gg.gbase[gg.curpage - 1];
+	while (g1 != NULL)
+	{
+		if (g1 != g &&
+				P_imax2((long)abs(g1->x - x), (long)abs(g1->y - y)) <= g1->kind->bbmax)
+		{
+			FORLIM = g1->kind->numpins;
+			for (j = 1; j <= FORLIM; j++)
+			{
+				if (x == g1->pinpos[j - 1].x && y == g1->pinpos[j - 1].y &&
+						g1->pin[j - 1] == *oldnode) {
+					delgetnode(savenode, oldnode, &n);
+					if (n != *oldnode)
+						chggate(g1, j, *oldnode, n);
+				}
+			}
+		}
+		g1 = g1->next;
+	}
+}
+
+
+static void disconnectgate(log_grec *g)
+{
+	log_nrec *savenode;
+	short i, j;
+	log_nrec **oldnode;
+	long done[log_maxpins / 32 + 2];
+	short FORLIM;
+	long SET[9];
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Disconnect gate %ld\n", (long)g);
+	stamp(&g->kind->simtype->netstamp);
+	calltoolgate(g, act_disconnectgate);
+	oldnode = (log_nrec **)Malloc(g->kind->numpins * sizeof(log_nrec *));
+	FORLIM = g->kind->numpins;
+	for (i = 0; i < FORLIM; i++)
+	{
+		oldnode[i] = g->pin[i];
+		stamp(&oldnode[i]->simtype->netstamp);
+		switchnode(&g->pin[i], NULL);
+	}
+	P_expset(done, 0L);
+	FORLIM = g->kind->numpins;
+	for (i = 1; i <= FORLIM; i++)
+	{
+		if (!P_inset(i, done))
+		{
+			j = i;
+			if (i == 1 && g->kind->simtype == simtype_common && g->sig != 0)
+				savenode = NULL;
+			else
+				savenode = oldnode[i - 1];
+			do {
+				chggatepin(g, j, &oldnode[i - 1], &savenode);
+				P_addset(done, j);
+				j = g->kind->pin[j - 1].c;
+			} while (j != i && j != 0);
+		}
+	}
+	unlkgate(&g);
+}
+
+
+static void delgate(log_grec *g)
+{
+	clipon();
+	eragate(g);
+	disconnectgate(g);
+	disposegate(&g);
+	clipoff();
+}
+
diff --git a/log/src/label.c b/log/src/label.c
new file mode 100644
index 0000000..8ab234f
--- /dev/null
+++ b/log/src/label.c
@@ -0,0 +1,388 @@
+
+#include <p2c/p2c.j>
+
+/**
+ *  @param lbl: list of character to parse
+ *  @param numattrs: number of found attributs
+ *  @param attr: vector containing parsed attributs
+ */
+static void parselabel(na_strlist_t **lbl, short *numattrs, log_kattrrec **attr)
+{
+	short j, j1, j2, j3, yy, maxx;
+	na_strlist_t *l1, *l2, *l3, *attrnames;
+	char buf[256];
+	int haveprec;
+	log_kattrrec *WITH;
+	char STR1[256];
+	char STR2[256];
+	short FORLIM;
+
+	j = 1;
+	*numattrs = 0;
+	attrnames = NULL;
+	l1 = *lbl;
+	// boucle qui compte le nombre d'attribut
+	while (l1 != NULL) {
+		j = strposc(l1->s, ':', 1L);
+		if (j != 0 && j != strpos2(l1->s, "::", 1))
+			(*numattrs)++;
+
+		l1->value = (na_long)strlen(l1->s);
+		l1 = l1->next;
+	}
+	*attr = (log_kattrrec *)Malloc(*numattrs * kattrrecsize);
+	maxx = 0;
+	l1 = *lbl;
+	j = 1;
+	yy = 0;
+	// On parcours de nouveau la liste de string
+	while (l1 != NULL)
+	{
+		j1 = strposc(l1->s, ':', 1L);
+		// Si c'est bien un attribut
+		if (j1 != 0 && j1 != strpos2(l1->s, "::", 1))
+		{
+			WITH = &(*attr)[j - 1];
+			WITH->vr = 0;
+			WITH->vra = 0;
+			strcpy(STR1, strltrim(l1->s));
+			strcpy(l1->s, STR1); // TODO optimiser
+			// elimine les [ ] si autour de l'attribut
+			while (l1->s[0] == '[')
+			{
+				j2 = strposc(l1->s, ']', 1L);
+				if (j2 < 3)
+					continue;
+				l2 = strlist_append(&attrnames, strpart(STR1, l1->s, 2, j2 - 1));
+				l2->value = (na_long)((long)j);
+				strcpy_overlap(l1->s, l1->s + j2);
+				strcpy(STR1, strltrim(l1->s));
+				strcpy(l1->s, STR1); // TODO optimiser
+			}
+			j2 = strposc(l1->s, ';', 1L);
+			if (j2 != 0 && j2 < j1)
+			{
+				sprintf(buf, "%.*s", j2 - 1, l1->s);
+				strrtrim(buf);
+				j3 = 1;
+				// Recherche si l'attribut à déjà été défini
+				while (j3 < j && WITH->vra == 0)
+				{
+					if ((*attr)[j3 - 1].dtype == 'V')
+					{
+						l2 = (*attr)[j3 - 1].UU.U86.v;
+						while (l2 != NULL && strcicmp(l2->s, buf) != 0)
+							l2 = l2->next;
+
+						if (l2 != NULL) {
+							WITH->vr = (long)l2->value;
+							WITH->vra = j3;
+						}
+					}
+					j3++;
+				}
+				strcpy_overlap(l1->s, l1->s + j2);
+			}
+			if (l1->s[0] == ' ')
+			{
+				strcpy(STR1, strltrim(l1->s));
+				strcpy(l1->s, STR1); // TODO optimiser
+			}
+			WITH->prec = 0;
+			haveprec = false;
+			while (isdigit(l1->s[0]))
+			{
+				WITH->prec = WITH->prec * 10 + l1->s[0] - 48;
+				haveprec = true;
+				strcpy_overlap(l1->s, l1->s + 1);
+			}
+			if (l1->s[0] == ' ')
+			{
+				strcpy(STR1, strltrim(l1->s));
+				strcpy(l1->s, STR1);
+			}
+			WITH->opt = false;
+			do
+			{
+				WITH->dtype = toupper(l1->s[0]);
+				if (l1->s[0] != ':')
+				{
+					do
+					{
+						strcpy_overlap(l1->s, l1->s + 1);
+					}
+					while (l1->s[0] == ' ');
+				}
+				if (WITH->dtype == 'O')
+					WITH->opt = true;
+
+			}
+			while (WITH->dtype == 'O');
+
+			if (WITH->dtype == 'F' || WITH->dtype == 'U' || WITH->dtype == 'R')
+			{
+				*WITH->UU.U82.u = '\0';
+				if (WITH->dtype == 'F' || WITH->dtype == 'U')
+				{
+					while (l1->s[0] != ',' && l1->s[0] != ':')
+					{
+						if (l1->s[0] != ' ' && strlen(WITH->UU.U82.u) < 3)
+							sprintf(WITH->UU.U82.u + strlen(WITH->UU.U82.u), "%c", l1->s[0]);
+
+						strcpy_overlap(l1->s, l1->s + 1);
+					}
+					if (l1->s[0] == ',')
+						strcpy_overlap(l1->s, l1->s + 1);
+
+					strcpy(STR1, strltrim(l1->s));
+					strcpy(l1->s, STR1);
+				}
+				*buf = '\0';
+				while (l1->s[0] != ':')
+				{
+					sprintf(buf + strlen(buf), "%c", l1->s[0]);
+					strcpy_overlap(l1->s, l1->s + 1);
+				}
+				WITH->UU.U82.r = 0.0;
+				WITH->blnk = true;
+				if (*buf != '\0')
+				{
+					readreal(buf, &WITH->UU.U82.r);
+					WITH->blnk = false;
+				}
+				if (!haveprec)
+					WITH->prec = 0;
+
+			}
+			else if (WITH->dtype == 'I')
+			{
+				WITH->UU.U73.i1 = 0;
+				WITH->blnk = true;
+				while (isdigit(l1->s[0]))
+				{
+					WITH->UU.U73.i1 = WITH->UU.U73.i1 * 10 + l1->s[0] - 48;
+					strcpy_overlap(l1->s, l1->s + 1);
+					WITH->blnk = false;
+				}
+				if (!haveprec)
+					WITH->prec = 1;
+
+			}
+			else if (WITH->dtype == 'H')
+			{
+				WITH->UU.U73.i1 = 0;
+				j1 = 0;
+				WITH->blnk = true;
+				while ((l1->s[0] >= 'a' && l1->s[0] <= 'f') ||
+						(l1->s[0] >= 'A' && l1->s[0] <= 'F') || isdigit(l1->s[0]))
+				{
+					WITH->UU.U73.i1 = WITH->UU.U73.i1 * 10 + l1->s[0] - 48;
+					if (l1->s[0] >= 'A')
+						WITH->UU.U73.i1 -= 7;
+
+					if (l1->s[0] >= 'a')
+						WITH->UU.U73.i1 -= 32;
+
+					strcpy_overlap(l1->s, l1->s + 1);
+					j1++;
+					WITH->blnk = false;
+				}
+				if (!haveprec)
+				{
+					if (j1 != 0)
+						WITH->prec = j1;
+					else
+						WITH->prec = 1;
+				}
+			}
+			else if (WITH->dtype == 'C')
+			{
+				j1 = strposc(l1->s, ':', 1L);
+				sprintf(buf, "%.*s", j1 - 1, l1->s);
+				strrtrim(buf);
+				strcpy_overlap(l1->s, l1->s + j1 - 1);
+				if (!haveprec)
+					WITH->prec = 255;
+
+				if (strlen(buf) > WITH->prec)
+					buf[WITH->prec] = '\0';
+
+				WITH->UU.c = (char *)Malloc(WITH->prec + 1L);
+				strcpy(WITH->UU.c, buf);
+				WITH->blnk = (*buf == '\0');
+			}
+			else if (WITH->dtype == 'A')
+			{
+				j1 = strposc(l1->s, ':', 1L);
+				sprintf(buf, "%.*s", j1 - 1, l1->s);
+				strrtrim(buf);
+				strcpy_overlap(l1->s, l1->s + j1 - 1);
+				WITH->prec = 255;
+				WITH->UU.sp = strdup(buf);
+				WITH->blnk = (*buf == '\0');
+			}
+			else if (WITH->dtype == 'B')
+			{
+				WITH->blnk = false;
+				if (l1->s[0] == 'y' || l1->s[0] == 'Y' || l1->s[0] == 't' || l1->s[0] == 'T')
+					WITH->UU.b = true;
+				else if (l1->s[0] == 'n' || l1->s[0] == 'N' || l1->s[0] == 'f' || l1->s[0] == 'F')
+					WITH->UU.b = false;
+				else
+					WITH->blnk = true;
+
+				if (l1->s[0] == 'x' || l1->s[0] == 'X' || l1->s[0] == 'f' ||
+						l1->s[0] == 'F' || l1->s[0] == 't' || l1->s[0] == 'T')
+					WITH->prec = 2;
+				else
+					WITH->prec = 1;
+			}
+			else if (WITH->dtype == 'V')
+			{
+				strlist_init(&l2);
+				WITH->UU.U86.nv = 0;
+				do
+				{
+					*buf = '\0';
+					while (l1->s[0] != ',' && l1->s[0] != ':')
+					{
+						sprintf(buf + strlen(buf), "%c", l1->s[0]);
+						strcpy_overlap(l1->s, l1->s + 1);
+					}
+					if (l1->s[0] == ',')
+						strcpy_overlap(l1->s, l1->s + 1);
+
+					l3= strlist_append(&l2,strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf)))));
+					l3->value = (na_long)((long)WITH->UU.U86.nv);
+					WITH->UU.U86.nv++;
+					strcpy(STR1, strltrim(l1->s));
+					strcpy(l1->s, STR1);
+				}
+				while (l1->s[0] != ':');
+				WITH->UU.U86.v = l2;
+				WITH->blnk = false;
+				if (haveprec)
+					WITH->UU.U86.dv = WITH->prec;
+				else
+					WITH->UU.U86.dv = 0;
+
+				WITH->prec = 1;
+			}
+			else
+			{
+				WITH->dtype = 'R';
+				WITH->UU.U82.r = 0.0;
+				WITH->blnk = true;
+				if (!haveprec)
+					WITH->prec = 0;
+			}
+			if (WITH->blnk)
+				WITH->opt = true;
+
+			j1 = strposc(l1->s, ':', 1L);
+			strcpy_overlap(l1->s, l1->s + j1);
+			j++;
+			WITH->y = yy;
+			if (strlen(l1->s) > maxx)
+				maxx = strlen(l1->s);
+
+		}
+		j1 = 1;
+		while (j1 < strlen(l1->s))
+		{
+			if (l1->s[j1 - 1] == ':' && l1->s[j1] == ':')
+				strcpy_overlap(l1->s + j1 - 1, l1->s + j1);
+			j1++;
+		}
+		yy++;
+		l1 = l1->next;
+	}
+	if (attrnames != NULL) {
+		l1 = strlist_insert(lbl, "");
+		l1->kind = '\001';
+		l1->value = (void *)attrnames;
+	}
+	FORLIM = *numattrs;
+	for (j = 0; j < FORLIM; j++)
+		(*attr)[j].x = maxx + 1;
+}
+
+/*==================  ERALABEL  ==================*/
+/*=                                              =*/
+/*=  Erase a text label from the screen.         =*/
+/*=                                              =*/
+/*================================================*/
+
+static void eralabel(log_lrec *l)
+{
+	m_color((long)gg.color.backgr);
+	m_drawstr(l->x * gg.scale - gg.xoff, l->y * gg.scale - gg.yoff + 2,
+			logfont_lfont, l->name);
+}
+
+
+/*==================  XORLABEL  ==================*/
+/*=                                              =*/
+/*=  XOR a text label onto the screen.           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void xorlabel(short x, short y, log_lrec *l)
+{
+	m_colormode((long)m_xor);
+	m_color((long)gg.color.labeltext);
+	m_drawstr(x * gg.scale - gg.xoff, y * gg.scale - gg.yoff + 2, logfont_lfont,
+			l->name);
+	m_colormode((long)m_normal);
+}
+
+/*==================  NEWLABEL  ==================*/
+/*=                                              =*/
+/*=  Create a Label.                             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void linklabel(log_lrec *l)
+{
+	l->next = gg.lbase[gg.curpage - 1];
+	gg.lbase[gg.curpage - 1] = l;
+	stamp(&gg.labelstamp);
+}
+
+
+static void newlabel(log_lrec **l)
+{
+	*l = (log_lrec *)Malloc(sizeof(log_lrec));
+	(*l)->temp = (na_long)0;
+	linklabel(*l);
+}
+
+
+/*================  DISPLABEL  ===================*/
+/*=                                              =*/
+/*=  Dispose of a text label.                    =*/
+/*=                                              =*/
+/*================================================*/
+
+static void unlinklabel(log_lrec *l)
+{
+	log_lrec *l1;
+
+	l1 = gg.lbase[gg.curpage - 1];
+	while (l1 != NULL && l1->next != l)
+		l1 = l1->next;
+	if (l1 == NULL)
+		gg.lbase[gg.curpage - 1] = l->next;
+	else
+		l1->next = l->next;
+	chpageplace((int)gg.curpage, l->x, l->y, l->x + l->w, l->y + 2);
+	stamp(&gg.labelstamp);
+}
+
+
+static void displabel(log_lrec **l)
+{
+	unlinklabel(*l);
+	Free(*l);
+}
+
diff --git a/log/src/log.c b/log/src/log.c
index 8e0de4d..8be65cc 100644
--- a/log/src/log.c
+++ b/log/src/log.c
@@ -18,14 +18,10 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
-   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
+   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 /*
-
-
-
    Logic Simulator   Version 4.1
    For HP 9836C
 
@@ -33,8 +29,6 @@
    Copyright (c)  1985
 
    David Gillespie
-
-
 */
 
 
@@ -315,10 +309,6 @@ typedef struct baseptrs {
 
 
 
-
-
-
-
 /* 0*/
 /* If the pen is in "this" sector, */
 /* 1*/
@@ -603,93 +593,6 @@ extern void nc_cursor_on ();
 extern void nc_cursor_off ();
 
 
-
-/*=================  INITSCREEN  =================*/
-/*=                                              =*/
-/*=  Initialize color graphics, graphics tablet, =*/
-/*=     low-level flags & variables              =*/
-/*=                                              =*/
-/*================================================*/
-
-static void initcolormap()
-{
-	m_setcolor((long)log_gray, 4L, 4L, 4L);
-	m_setcolor((long)log_red, 15L, 0L, 0L);
-	m_setcolor((long)log_green, 0L, 15L, 0L);
-	m_setcolor((long)log_yellow, 15L, 15L, 0L);
-	if (eightcolors) {
-		m_setcolor((long)log_cred8, 15L, 0L, 0L);
-		m_setcolor((long)log_black8, 0L, 0L, 0L);
-	} else {
-		m_setcolor((long)log_mred, 11L, 0L, 0L);
-		m_setcolor((long)log_orange, 15L, 9L, 0L);
-	}
-	m_setcolor((long)log_cyan, 0L, 15L, 15L);
-	m_setcolor((long)log_white, 15L, 15L, 15L);
-	m_setcolor((long)log_black, 0L, 0L, 0L);
-	m_setcolor((long)log_pink, 15L, 9L, 9L);
-	m_setcolor((long)log_dyellow, 12L, 12L, 0L);
-	m_setcolor((long)log_xgreen, 0L, 13L, 0L);
-	m_setcolor((long)log_dcyan, 0L, 10L, 10L);
-	m_setcolor((long)log_dred, 8L, 0L, 0L);
-	m_setcolor((long)log_lgray, 10L, 10L, 10L);
-	m_setcolor((long)log_cred, 15L, 0L, 0L);
-	m_vseecolors(0L, 16L, rcolormap, gcolormap, bcolormap);
-}
-
-
-static void fixcolormap()
-{
-	m_vsetcolors(0L, 16L, rcolormap, gcolormap, bcolormap);
-	recolor_log_cursors(gg.color.cursor, true);
-}
-
-
-
-static void initscreen()
-{
-	m_init_screen();
-	m_upside_down();
-	m_setlinestyle(1L, 0xf0f0L);
-	m_setlinestyle(2L, 0xaaaaL);
-	m_setfont(logfont_lfont);
-	init_X_screen();
-	onescreen = nc_alphashared();
-	eightcolors = (m_maxcolor <= 7);
-
-	txacross = nc_curWindow->width - 1;
-	txdown = nc_curWindow->height - 1;
-	across = m_across;
-	down = m_down;
-	baseline = down - 53;   /* Position of baseline on screen */
-	line1 = down - 43;   /* Position of first text line in menu */
-	line2 = down - 23;   /* Position of second text line in menu */
-	histdown = down - 26;
-	histdivsacross = (double)(across - histleft) / histdivision;
-	histvalrange = (double)histdown / histdivision * 5;
-	kindgroupsize = (across - 160) / kindgroupspacing;
-	kindgroupleft = (across - kindgroupsize * kindgroupspacing) / 2;
-	kindgroupright = kindgroupleft + kindgroupsize * kindgroupspacing;
-	kindgroupstart = kindgroupleft + kindgroupspacing / 2;
-	kindgroupbase = (baseline + down) / 2;
-
-	printf("\200\210");
-	SETRUNLIGHT(' ');
-
-	cursorflag = false;
-	gg.stillnear = true;
-}
-
-
-static void initscreen2()
-{
-	initscreen();
-	m_clear();
-	m_graphics_on();
-}
-
-
-
 static char *ioresult_message(char *Result, long iores)
 {
 	char s[81];
@@ -737,47 +640,6 @@ static void warning()
 }
 
 
-/*==================  NOBLINK  ===================*/
-/*=                                              =*/
-/*=  Turn off the stupid blinking Alpha cursor.  =*/
-/*=                                              =*/
-/*================================================*/
-
-static void noblink()
-{
-	nc_cursXY(-1, -1);
-	/*  oldx := xpos;
-oldy := ypos;
-xpos := -1;
-ypos := -1;
-call(updatecursorhook);
-xpos := oldx;
-ypos := oldy; */
-}
-
-
-
-
-static void clearalpha()
-{
-	if (!onescreen)
-	{
-		printf("\f");
-		noblink();
-		m_alpha_off();
-	}
-	nk_gotoxy(0, 0);
-}
-
-
-static void showalpha()
-{
-	m_graphics_off();
-	m_alpha_on();
-}
-
-
-
 static void clearshowalpha ();
 
 /*===================  REPORT  ===================*/
@@ -815,3694 +677,942 @@ static void report(short num, char *s)
 }
 
 
-/*===================  LINE  =====================*/
+/*==================  SETMODE  ===================*/
 /*=                                              =*/
-/*=  Draw a line in grid coordinates.            =*/
+/*=  Draw a word in the "mode" location of       =*/
+/*=     the menu area.                           =*/
 /*=                                              =*/
 /*================================================*/
 
-static void line(short x1, short y1, short x2, short y2)
-{
-	m_drawline(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
-			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
-}
-
-
-/*===================  HLINE  ====================*/
-/*=                                              =*/
-/*=  Draw a horizontal line in grid coordinates. =*/
-/*=                                              =*/
-/*=                                              =*/
-/*================================================*/
+static void refreditmode ();
 
-static void hline(short x1, short x2, short y)
+static void log_setmode(const char *s)
 {
-	short yy;
+	time_t h;
+	char *cp;
 
-	yy = y * gg.scale - gg.yoff;
-	m_drawline(x1 * gg.scale - gg.xoff, (long)yy, x2 * gg.scale - gg.xoff, (long)yy);
+	remcursor();
+	clipoff();
+	m_color((long)gg.color.backgr);
+	if (gg.showpage > 0)
+		drawstr2(across + menux3, line2, modename);
+	refreditmode();   /*may have been trashed by previous mode name*/
+	if (*s != '\0')
+	{
+		strcpy(modename, s);
+		modeflag = true;
+		m_color((long)gg.color.selword);
+	}
+	else
+	{
+		if (gg.probekind != NULL)
+		{
+			strcpy(modename, gg.probekind->name);
+			m_color((long)gg.color.selword);
+		}
+		else
+		{
+			time(&h);
+			cp = ctime(&h);
+			sprintf(modename, "%.5s", cp + 11);
+			modetime = timers_sysclock() / 6000;
+			if (!strcmp(modename, "00:00"))
+				strcpy(modename, "__@/ ");
+			m_color((long)gg.color.menuword);
+		}
+		modeflag = false;
+		modeprobekind = gg.probekind;
+	}
+	if (gg.showpage > 0)
+		drawstr2(across + menux3, line2, modename);
 }
 
 
-/*===================  VLINE  ====================*/
-/*=                                              =*/
-/*=  Draw a vertical line in grid coordinates.   =*/
-/*=                                              =*/
-/*=                                              =*/
-/*================================================*/
-
-static void vline(short x, short y1, short y2)
+static void dounits(char *s, double *r)
 {
-	short xx;
-
-	xx = x * gg.scale - gg.xoff;
-	m_drawline((long)xx, y1 * gg.scale - gg.yoff, (long)xx,
-			y2 * gg.scale - gg.yoff);
-}
-
-
-/*===================  POINT  ====================*/
-/*=                                              =*/
-/*=  Draw a point in grid coordinates.           =*/
-/*=                                              =*/
-/*================================================*/
+	char ch;
 
-static void point(short x, short y)
-{
-	m_drawpoint(x * gg.scale - gg.xoff, y * gg.scale - gg.yoff);
+	if (*s == '\0')
+		return;
+	ch = s[0];
+	if (ch >= 'a')
+		ch -= 32;
+	if (ch == 'F')
+	{
+		*r *= 1e-15;
+		return;
+	}
+	if (ch == 'P')
+	{
+		*r *= 1e-12;
+		return;
+	}
+	if (ch == 'N')
+	{
+		*r *= 1e-9;
+		return;
+	}
+	if (ch == 'U')
+	{
+		*r *= 1e-6;
+		return;
+	}
+	if (ch == 'K')
+	{
+		*r *= 1e3;
+		return;
+	}
+	if (ch == 'G')
+	{
+		*r *= 1e9;
+		return;
+	}
+	if (ch == 'T')
+	{
+		*r *= 1e12;
+		return;
+	}
+	if (ch != 'M')
+		return;
+	if (strlen(s) >= 3 && (s[1] == 'E' || s[1] == 'e') &&
+			(s[2] == 'G' || s[2] == 'g'))
+		*r *= 1e6;
+	else
+		*r *= 1e-3;
 }
 
 
-/*===================  RECT  =====================*/
-/*=                                              =*/
-/*=  Draw a rectangle in grid coordinates.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static void rect(short x1, short y1, short x2, short y2)
+static void readreal(char *s_, double *r)
 {
-	m_drawrect(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
-			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
-}
-
-/*====================  BOX  =====================*/
-/*=                                              =*/
-/*=  Draw a filled rectangle in grid coords.     =*/
-/*=                                              =*/
-/*================================================*/
+	char s[256];
+	long i;
+	char *STR1;
+	char STR2[256];
 
-static void box(short x1, short y1, short x2, short y2)
-{
-	m_fillrect(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
-			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
+	strcpy(s, s_);
+	if (!(*s != '\0' &&
+				(s[0] == '.' || s[0] == '+' || s[0] == '-' || isdigit(s[0]))))
+		return;
+	*r = strtod(s, &STR1);
+	i = STR1 - s + 1;
+	strcpy_overlap(s, s + i - 1);
+	strcpy(STR2, strltrim(s));
+	strcpy(s, STR2);
+	dounits(s, r);
 }
 
-/*=================  DRAWSTR2  ===================*/
-/*=                                              =*/
-/*=  Draw a text string.                         =*/
-/*=                                              =*/
-/*================================================*/
 
-static void drawstr2(short x, short y, char *s)
+static void strwordx(char *buf, char *wrd)
 {
-	long save;
+	size_t i;
+	char STR1[256];
+	char STR2[256];
 
-	if (m_curcolor() < 16)
+	strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf))));
+	strcpy(buf, STR1);
+	if (*buf != '"')
 	{
-		save = m_curcolor();
-		m_color((long)gg.color.backgr);
-		m_fillrect(x - 1L, y - 2L, x + m_strwidth(logfont_lfont, s), y + 9L);
-		m_color(save);
+		strword(buf, wrd);
+		return;
 	}
-	m_move((long)x, (long)y);
-	m_displaytext(s);
+	i = strposc(buf, '"', 2L);
+	if (i == 0)
+		i = strlen(buf) + 1;
+	strpart(wrd, buf, 2, i - 1);
+	strcpy_overlap(buf, buf + i);
 }
 
 
-static void rightstr2(short x, short y, char *s)
+static void getword(char *buf, char *wrd)
 {
-	long save;
+	char STR1[256];
+	char STR2[256];
 
-	if (m_curcolor() < 16)
+	strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf))));
+	strcpy(buf, STR1);
+	if (*buf == '"')
+		strwordx(buf, wrd);
+	else
 	{
-		save = m_curcolor();
-		m_color((long)gg.color.backgr);
-		m_fillrect(x + m_strwidth(logfont_lfont, s) - 1, y - 2L, x + 1L, y + 9L);
-		m_color(save);
+		strwordx(buf, wrd);
+		strupper(wrd, wrd);
 	}
-	m_rightstr((long)x, (long)y, logfont_lfont, s);
 }
 
 
-static void centerstr2(short x, short y, char *s)
+static long getint(char *s, long def)
 {
-	short w;
-	long save;
+	char w[10];
+	long i, j, sign;
+	int valid;
+	long FORLIM;
 
-	if (m_curcolor() < 16)
+	getword(s, w);
+	if (*w == '-')
 	{
-		save = m_curcolor();
-		m_color((long)gg.color.backgr);
-		w = m_strwidth(logfont_lfont, s) / 2 + 2;
-		m_fillrect((long)(x - w), y - 2L, (long)(x + w), y + 9L);
-		m_color(save);
+		strcpy_overlap(w, w + 1);
+		sign = -1;
+	}
+	else
+	{
+		sign = 1;
+	}
+	j = 0;
+	valid = true;
+	FORLIM = strlen(w);
+	for (i = 0; i < FORLIM; i++)
+	{
+		if (w[i] < '0' || w[i] > '9')
+			valid = false;
+		else
+			j = j * 10 + w[i] - 48;
 	}
-	m_centerstr((long)x, (long)y, logfont_lfont, s);
-}
 
+	if (*w != '\0' && valid)
+		return (j * sign);
+	else
+		return def;
+}
 
-/*=================  DRAWNUM1  ===================*/
-/*=                                              =*/
-/*=  Draw a single digit at the specified        =*/
-/*=     position (screen coordinates).           =*/
-/*=                                              =*/
-/*================================================*/
 
-static void drawnum1(short x, short y, short n)
+static void pgetint(char *buf, long *i, long def)
 {
-	char s[2];
-
-	m_move((long)x, (long)y);
-	strcpy(s, " ");
-	s[0] = n + '0';
-	m_displaytext(s);
+	*i = getint(buf, def);
 }
 
 
-/*=================  DRAWNUM2  ===================*/
-/*=                                              =*/
-/*=  Draw a two-digit number at the specified    =*/
-/*=     position (screen coordinates).           =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawnum2(short x, short y, short n)
+static double getreal(char *s, double def)
 {
-	char s[3];
+	char w[81];
+	double r;
 
-	m_move((long)x, (long)y);
-	strcpy(s, "  ");
-	if (n >= 10)
-		s[0] = n / 10 + '0';
-	s[1] = n % 10 + '0';
-	m_displaytext(s);
+	getword(s, w);
+	r = def;
+	TRY(try1);
+	readreal(w, &r);
+	RECOVER(try1);
+	if (P_escapecode == -20)
+		_Escape(P_escapecode);
+	r = def;
+	ENDTRY(try1);
+	return r;
 }
 
-
-static void xformcoords(log_grec *g, short *x, short *y)
+static void pgetreal(char *buf, double *r, double def)
 {
-	short xx, yy;
-
-	if (g == NULL)
-	{
-		*x = *x * gg.scale - gg.xoff;
-		*y = *y * gg.scale - gg.yoff;
-		return;
-	}
-	xx = *x * gg.scale;
-	yy = *y * gg.scale;
-	*x = g->x * gg.scale - gg.xoff +
-		(log_rotxx[g->rot] * xx + log_rotyx[g->rot] * yy) / log_scale0;
-	*y = g->y * gg.scale - gg.yoff +
-		(log_rotxy[g->rot] * xx + log_rotyy[g->rot] * yy) / log_scale0;
+	*r = getreal(buf, def);
 }
 
 
-static void plainxformcoords(log_grec *g, short *x, short *y)
+static void getbool(char *buf, int *b)
 {
-	short xx;
+	char w[17];
 
-	if (g == NULL)
+	getword(buf, w);
+	if (!strcmp(w, "ON") || !strcmp(w, "YES") || !strcmp(w, "Y") ||
+			!strcmp(w, "RABBITS"))
+	{   /*avoid*/
+		*b = true;
+		return;
+	}
+	if (!strcmp(w, "OFF") || !strcmp(w, "NO") || !strcmp(w, "N"))
 	{
-		*x *= log_scale0;
-		*y *= log_scale0;
+		*b = false;
 		return;
 	}
-	xx = *x;
-	*x = g->x * log_scale0 + log_rotxx[g->rot] * xx + log_rotyx[g->rot] * *y;
-	*y = g->y * log_scale0 + log_rotxy[g->rot] * xx + log_rotyy[g->rot] * *y;
+	
+	if (!strcmp(w, "?"))
+		tempverbose = true;
+	else if (*w == '\0')
+		*b = !*b;
 }
 
 
-/*==================  CLIPON  ====================*/
+/*=================  SORTSHINTS  =================*/
 /*=                                              =*/
-/*=  Allow drawing only in the working area.     =*/
+/*=  Put two shortint variables into increasing  =*/
+/*=     numerical order.                         =*/
 /*=                                              =*/
 /*================================================*/
 
-static void clipon()
+static void sortshints(short *x, short *y)
 {
-	m_clip(0L, 0L, (long)across, baseline - 1L);
+	short temp;
+
+	if (*x <= *y)
+		return;
+	temp = *x;
+	*x = *y;
+	*y = temp;
 }
 
 
-/*==================  CLIPOFF  ===================*/
+/*=================  TESTPROBE  ==================*/
 /*=                                              =*/
-/*=  Allow drawing in working area and menus.    =*/
+/*=  Find which wire, pin, or gate the Probe     =*/
+/*=     is touching and set PROBENODE or         =*/
+/*=     PROBEGATE to its address.                =*/
 /*=                                              =*/
 /*================================================*/
 
-static void clipoff()
+static void unprobe()
 {
-	m_noclip();
+	gg.probenode = NULL;
+	gg.probegate = NULL;
+	gg.probepin = 0;
+	gg.probesimtype = NULL;
+	gg.probekind = NULL;
+	gg.probehwire = NULL;
+	gg.probevwire = NULL;
+	probeflag = false;
 }
 
-/*==================  UERASE  ====================*/
-/*=                                              =*/
-/*=  Erase a rectangular area of the screen      =*/
-/*=     using screen coordinates.                =*/
-/*=                                              =*/
-/*================================================*/
 
-static void uerase(short x1, short y1, short x2, short y2)
+static log_krec *peninkind(short xx, short yy)
 {
-	m_color((long)gg.color.backgr);
-	m_fillrect((long)x1, (long)y1, (long)x2, (long)y2);
-}
-
-
-/*===================  ERASE  ====================*/
-/*=                                              =*/
-/*=  Erase a rectangular area of the screen      =*/
-/*=     using grid coordinates.                  =*/
-/*=                                              =*/
-/*================================================*/
+	log_krec *Result;
+	short i;
 
-static void erase(short x1, short y1, short x2, short y2)
-{
-	m_color((long)gg.color.backgr);
-	box(x1, y1, x2, y2);
+	Result = NULL;
+	if (!(P_ibetween((long)kindgroupleft, (long)xx, kindgroupright - 1L) &&
+				P_ibetween((long)baseline, (long)yy, (long)down)))
+		return Result;
+	i = kindgroup[(xx - kindgroupleft) / kindgroupspacing];
+	if (i > 0)
+		return (kind[(i & (log_kindoffset - 1)) - 1]);
+	return Result;
 }
 
 
-/*================  NORABBITS  ===================*/
-/*=                                              =*/
-/*=  Make sure there are no rabbits on the       =*/
-/*=     screen.                                  =*/
-/*=                                              =*/
-/*================================================*/
-
-static void norabbits()
+static void testprobe(short xx, short yy)
 {
-	short i;
+	log_grec *g;
+	log_krec *k;
+	short i, x, y;
+	log_hwrec *hw;
+	log_vwrec *vw;
+	short FORLIM;
 
-	clipoff();
-	for (i = 0; i < rabtabsize; i++)
+	x = (xx + gg.hscale + gg.xoff) / gg.scale;
+	y = (yy + gg.hscale + gg.yoff) / gg.scale;
+	unprobe();
+	if (gg.showpage > 0 && !gg.invisible && !gg.showconflicts)
 	{
-		if (rabtable[i].next == 1)
+		if (gg.incircuit)
+		{
+			g = gg.gbase[gg.curpage - 1];
+			while (g != NULL && gg.probegate == NULL)
+			{
+				k = g->kind;
+				if (g->x >= x - k->bbmax && g->x <= x + k->bbmax &&
+						g->y >= y - k->bbmax && g->y <= y + k->bbmax)
+				{
+					if (insidegate(g, x, y))
+					{
+						gg.probegate = g;
+					}
+					else if (g->kind->simtype->simtype >= 8)
+					{
+						FORLIM = g->kind->numpins;
+						for (i = 1; i <= FORLIM; i++) {
+							if (x == g->pinpos[i - 1].x && y == g->pinpos[i - 1].y)
+							{
+								gg.probegate = g;
+								gg.probenode = g->pin[i - 1];
+								gg.probepin = i;
+							}
+						}
+					}
+				}
+				g = g->next;
+			}
+			hw = gg.hwbase[gg.curpage - 1];
+			while (hw != NULL && gg.probenode == NULL)
+			{
+				if (hw->x1 <= x && x <= hw->x2 && hw->y == y)
+				{
+					gg.probehwire = hw;
+					gg.probenode = hw->node;
+				}
+				hw = hw->next;
+			}
+			vw = gg.vwbase[gg.curpage - 1];
+			while (vw != NULL && gg.probenode == NULL)
+			{
+				if (vw->y1 <= y && y <= vw->y2 && vw->x == x)
+				{
+					gg.probevwire = vw;
+					gg.probenode = vw->node;
+				}
+				vw = vw->next;
+			}
+		}
+		else
 		{
-			m_bunny((long)rabtable[i].x, (long)rabtable[i].y);
-			rabtable[i].next = 0;
+			gg.probekind = peninkind(xx, yy);
 		}
 	}
-	rabflag = false;
+	if (gg.probegate != NULL)
+		gg.probekind = gg.probegate->kind;
+	if (gg.probenode != NULL)
+		gg.probesimtype = gg.probenode->simtype;
+	else if (gg.probekind != NULL)
+		gg.probesimtype = gg.probekind->simtype;
 }
 
 
-/*================  ADDRABBIT  ===================*/
-/*=                                              =*/
-/*=  Draw a rabbit on the screen.                =*/
-/*=                                              =*/
-/*================================================*/
-
-static void addrabbit()
+static void checkprobe(short xx, short yy)
 {
-	short i, j, rx, ry;
-	int nogood;
-	rablistrec *WITH;
+	short x, y;
 
-	clipoff();
-	j = -1;
-	for (i = 1; i <= rabtabsize; i++)
+	x = (xx + gg.hscale + gg.xoff) / gg.scale;
+	y = (yy + gg.hscale + gg.yoff) / gg.scale;
+	if (gg.probegate != NULL &&
+			(gg.probegate->x < x - gg.probekind->bbmax ||
+			 gg.probegate->x > x + gg.probekind->bbmax ||
+			 gg.probegate->y < y - gg.probekind->bbmax ||
+			 gg.probegate->y > y + gg.probekind->bbmax))
 	{
-		if (rabtable[i - 1].next == 0)
-			j = i;
+		unprobe();
+		return;
 	}
-	if (j == -1)
+
+	if (gg.probekind != NULL && gg.probegate == NULL &&
+			peninkind(xx, yy) != gg.probekind)
 	{
-		j = P_rand(&gg.rndseed, (long)rabtabsize) + 1;
-		m_bunny((long)rabtable[j - 1].x, (long)rabtable[j - 1].y);
-		rabtable[j - 1].next = 0;
+		unprobe();
+		return;
 	}
-	do
-	{
-		rx = P_rand(&gg.rndseed, across - 24L);
-		ry = P_rand(&gg.rndseed, baseline - 40L) + down - baseline + 30;
-		nogood = false;
-		for (i = 0; i < rabtabsize; i++)
-		{
-			WITH = &rabtable[i];
-			if (WITH->next == 1)
-			{
-				if (WITH->x + 24 >= rx && WITH->x <= rx + 24 && WITH->y + 26 >= ry &&
-						WITH->y <= ry + 26)
-					nogood = true;
-			}
-		}
-	} while (nogood);
-	rabtable[j - 1].next = 1;
-	rabtable[j - 1].x = rx;
-	rabtable[j - 1].y = ry;
-	m_bunny((long)rx, (long)ry);
-	rabflag = true;
-	rabtime = timers_sysclock();
-}
 
+	if (gg.probehwire != NULL &&
+			(gg.probehwire->x1 > x || x > gg.probehwire->x2 ||
+			 gg.probehwire->y != y))
+		unprobe();
+	else if (gg.probevwire != NULL &&
+			(gg.probevwire->y1 > y || y > gg.probevwire->y2 ||
+			 gg.probevwire->x != x))
+		unprobe();
+}
 
-/*==================  HVLINE  ====================*/
-/*=                                              =*/
-/*=  Attempt to force a line to be horizontal    =*/
-/*=     or vertical.  If possible, second pair   =*/
-/*=     of coordinates is changed appropriately. =*/
-/*=                                              =*/
-/*=  Returns true if possible, false if not.     =*/
-/*=                                              =*/
-/*================================================*/
 
-static int hvline(short x1, short y1, short *x2, short *y2)
+static void stamp(long *i)
 {
-	int Result;
-
-	Result = true;
-	if (x1 == *x2 && y1 == *y2)
-		return false;
-	if (abs(*x2 - x1) > abs(*y2 - y1) && abs(*y2 - y1) < abs(*x2 - x1) / 3 + 20)
-	{   /*7/14/88*/
-		*y2 = y1;
-		return Result;
-	}
-	if (abs(*y2 - y1) <= abs(*x2 - x1) ||
-			abs(*x2 - x1) >= abs(*y2 - y1) / 3 + 20)
-		/*7/14/88*/
-		return false;
-	*x2 = x1;
-	return Result;
+	gg.curstamp++;
+	*i = gg.curstamp;
 }
 
 
-/*===================  FIXXY  ====================*/
-/*=                                              =*/
-/*=  Adjust screen coordinates so that they are  =*/
-/*=     aligned to the nearest grid point.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static void fixxy(short *x, short *y)
+static void send_general(log_tool *sim, char *act)
 {
-	*x = (*x + gg.xoff + gg.hscale) / gg.scale * gg.scale - gg.xoff;
-	*y = (*y + gg.yoff + gg.hscale) / gg.scale * gg.scale - gg.yoff;
+	char savefunc[17];
+
+	strcpy(savefunc, gg.genfunc);
+	strcpy(gg.genfunc, act);
+	calltool(sim, act_general);
+	strcpy(gg.genfunc, savefunc);
 }
 
-/*================  NOCROSSHAIR  =================*/
-/*=                                              =*/
-/*=  Turn off crosshair (no effect until next    =*/
-/*=     call of CURSOR).                         =*/
-/*=                                              =*/
-/*================================================*/
 
-static void nocrosshair()
+static void send_gennode(log_nrec *n, char *act)
 {
-	chairflag2 = false;
-}
+	char savefunc[17];
 
+	strcpy(savefunc, gg.genfunc);
+	strcpy(gg.genfunc, act);
+	calltoolnode(n, act_gennode);
+	strcpy(gg.genfunc, savefunc);
+}
 
-/*=================  CROSSHAIR  ==================*/
-/*=                                              =*/
-/*=  Move the crosshair to a particular position =*/
-/*=     in grid coordinates.                     =*/
-/*=                                              =*/
-/*================================================*/
 
-static void crosshair(short x, short y)
+static void send_genkind(log_krec *k, char *act)
 {
-	chairx = x * gg.scale - gg.xoff;
-	chairy = y * gg.scale - gg.yoff;
-	chairflag2 = true;
-}
+	char savefunc[17];
 
-/*=================  XORCURSOR  ==================*/
-/*=                                              =*/
-/*=  Draw the cursor on the screen.              =*/
-/*=  The exact shape drawn depends upon the      =*/
-/*=     current mode.                            =*/
-/*=  If the cursor is already on the screen, it  =*/
-/*=     is removed.                              =*/
-/*=                                              =*/
-/*=  Possible cursors:                           =*/
-/*=     Arrow (normal).                          =*/
-/*=     Probe (if Logic Probe mode).             =*/
-/*=     Big crosshair (if "Grid" mode on).       =*/
-/*=     Long arrow (if Copy command).            =*/
-/*=     Scissors (if Delete command).            =*/
-/*=     Rectangle (if Paste command).            =*/
-/*=     Green line (if drawing a wire).          =*/
-/*=     Rabbit (if Rabbit mode).                 =*/
-/*=                                              =*/
-/*================================================*/
-
-static void xorcursor()
-{
-	long curcm;
-	short cx0, cy0;
-
-	gg.cx_min = 0;
-	gg.cx_max = across;
-	gg.cy_min = 0;
-	gg.cy_max = baseline - 1;
-	curcm = m_curcolormode();
-	m_colormode((long)m_xor);
-	m_color((long)gg.color.cursor);
-	if (!chairflag || cursortype == grid)
-	{
-		if (cursortype != normal && cursy < baseline)
-		{
-			switch (cursortype)
-			{
+	strcpy(savefunc, gg.genfunc);
+	strcpy(gg.genfunc, act);
+	calltoolkind(k, act_genkind);
+	strcpy(gg.genfunc, savefunc);
+}
 
-				case grid:
-					choose_log_cursor(0);
-					if (chairflag) {
-						m_drawline(cursx1 - 3L, cursy1 - 5L, cursx1 + 3L, cursy1 + 5L);
-						m_drawline(cursx1 - 3L, cursy1 + 5L, cursx1 + 3L, cursy1 - 5L);
-					}
-					cx0 = (cursx + gg.xoff) / gg.scale * gg.scale - gg.xoff;
-					cy0 = (cursy + gg.yoff) / gg.scale * gg.scale - gg.yoff;
-					m_drawline(0L, (long)cy0, (long)across, (long)cy0);
-					m_drawline((long)cx0, 0L, (long)cx0, baseline - 1L);
-					break;
 
-				case delete__:
-					choose_log_cursor(2);
-					break;
+static void send_gengate(log_grec *g, char *act)
+{
+	char savefunc[17];
 
-				case copy_:
-					choose_log_cursor(1);
-					break;
+	strcpy(savefunc, gg.genfunc);
+	strcpy(gg.genfunc, act);
+	calltoolgate(g, act_gengate);
+	strcpy(gg.genfunc, savefunc);
+}
 
-				case boxcursor:
-					choose_log_cursor(4);
-					break;
 
-				case paste:
-					choose_log_cursor(0);
-					cx0 = (cursx + gg.xoff + 2) / gg.scale;
-					cy0 = (cursy + gg.yoff + 2) / gg.scale;
-					m_saveclip();
-					m_clip(0L, 0L, (long)across, baseline - 1L);
-					gg.cx_min = cx0;
-					gg.cx_max = cx0 + copybuf.dxcopy;
-					gg.cy_min = cy0;
-					gg.cy_max = cy0 + copybuf.dycopy;
-					rect(gg.cx_min, gg.cy_min, gg.cx_max, gg.cy_max);
-					m_unclip();
-					break;
+static void send_all(char *act)
+{
+	log_tool *tp;
+	char savefunc[17];
 
-				default:
-					break;
-			}
-		}
-		else
-		{
-			if (rabbits && !avoidrabbits && cursy < baseline)
-			{
-				choose_log_cursor(0);
-				if (cursx < 45)
-					m_bunny(0L, cursy - 17L);
-				else
-					m_bunny(cursx - 45L, cursy - 17L);
-			}
-			else if (gg.probemode)
-			{
-				choose_log_cursor(3);
-			}
-			else
-			{
-				choose_log_cursor(0);
-			}
-		}
-	}
-	if (chairflag)
+	strcpy(savefunc, gg.genfunc);
+	tp = gg.toolbase;
+	while (tp != NULL)
 	{
-		if (rbandflag)
-		{
-			choose_log_cursor(0);
-			if (vlsi)
-				m_color((long)gg.color.wire[curwcolor - log_wcol_normal]);
-			else
-				m_color((long)gg.color.xwire);
-			m_drawline((long)cursx1, (long)cursy1, (long)cursx2, (long)cursy2);
-		}
-		else
+		if (tp->ready && tp->simulator)
 		{
-			choose_log_cursor(0);
+			strcpy(gg.genfunc, act);
+			calltool(tp, act_general);
 		}
+		tp = tp->next;
 	}
-	oldcursortype = cursortype;
-	m_colormode(curcm);
-
-	/*and (cursy < baseline)*/
+	strcpy(gg.genfunc, savefunc);
 }
 
 
-/*=================  HIDECURSOR  =================*/
-/*=                                              =*/
-/*=  Used to remove cursor from screen while     =*/
-/*=     drawing graphics.                        =*/
-/*=                                              =*/
-/*================================================*/
-
-static void hidecursor()
+static void send_allnodes(char *act)
 {
-	if (cursorflag)
-		xorcursor();
+	log_tool *tp;
+	char savefunc[17];
+
+	strcpy(savefunc, gg.genfunc);
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		if (tp->ready && tp->simulator)
+		{
+			strcpy(gg.genfunc, act);
+			gg.actnode = NULL;
+			calltool(tp, act_gennode);
+		}
+		tp = tp->next;
+	}
+	strcpy(gg.genfunc, savefunc);
 }
 
 
-static void hidecursor_hook()
+static void send_allkinds(char *act)
 {
-	if (!cursorhide)
-		hidecursor();
-	cursorhide = true;
+	log_tool *tp;
+	char savefunc[17];
+
+	strcpy(savefunc, gg.genfunc);
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		if (tp->ready && tp->simulator)
+		{
+			strcpy(gg.genfunc, act);
+			gg.actkind = NULL;
+			calltool(tp, act_genkind);
+		}
+		tp = tp->next;
+	}
+	strcpy(gg.genfunc, savefunc);
 }
 
 
-static void unhidecursor_hook()
+static void send_allgates(char *act)
 {
-	if (cursorhide)
-		hidecursor();
-	cursorhide = false;
+	log_tool *tp;
+	char savefunc[17];
+
+	strcpy(savefunc, gg.genfunc);
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		if (tp->ready && tp->simulator)
+		{
+			strcpy(gg.genfunc, act);
+			gg.actgate = NULL;
+			calltool(tp, act_gengate);
+		}
+		tp = tp->next;
+	}
+	strcpy(gg.genfunc, savefunc);
 }
 
 
-static void hidecursorrect_hook(long x1, long y1, long x2, long y2)
+static long glowcol(log_nrec *n, long def)
 {
-	if (!cursorhide && x1 <= gg.cx_max && x2 >= gg.cx_min && y1 <= gg.cy_max &&
-			y2 >= gg.cy_min)
-		hidecursor_hook();
+	gg.actx = def;
+	calltoolnode(n, act_glowcol);
+	return (gg.actx);
 }
 
 
-/*================  DRAWCURSOR  ==================*/
-/*=                                              =*/
-/*=  Position the cursor to a particular point   =*/
-/*=     (screen coordinates).                    =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawcursor(short x, short y)
+static void resetmessages()
 {
-	if (x != cursx || y != cursy || !cursorflag || cursortype != oldcursortype)
-	{
-		if (cursorflag && !cursorhide)
-			xorcursor();
-		cursx = x;
-		cursy = y;
-		cursx1 = chairx;
-		cursy1 = chairy;
-		cursx2 = x;
-		cursy2 = y;
-		chairflag = chairflag2;
-		if (chairflag)
-		{
-			chairflag = true;
-			fixxy(&cursx2, &cursy2);
-			rbandflag = (abs(cursx1 - cursx2) + abs(cursy1 - cursy2) >= gg.scale &&
-					hvline(cursx1, cursy1, &cursx2, &cursy2));
-		}
-		xorcursor();
-	}
-	else
+	short opos;
+
+	opos = messagepos;
+	messagepos = topmessagepos;
+	messageright = 0;
+	if (messagepos != opos)
 	{
-		if (!cursorflag && !cursorhide)
-			xorcursor();
+		calltools(act_clearmsg);
+		stamp(&gg.msgstamp);
 	}
-	cursorflag = true;
-	cursorhide = false;
 }
 
-/*=================  REMCURSOR  ==================*/
+
+/*====================  PEN  =====================*/
+/*=                                              =*/
+/*=  Find the position of the pen.  Returns:     =*/
+/*=     D, D0 if the pen is/was down;            =*/
+/*=     N, N0 if the pen is/was near;            =*/
+/*=     DN, UP if the pen is pressed/released;   =*/
+/*=     NR if pen remains near;                  =*/
+/*=     OFFSCREEN if pen is off the screen edge; =*/
+/*=     PX, PY, PX0, PY0 = new/old position;     =*/
+/*=     FX, FY = position in grid coordinates;   =*/
+/*=     MENUBOX = menu box number (0-15);        =*/
 /*=                                              =*/
-/*=  Take the cursor off the screen.             =*/
+/*=  Also draws the cursor, runs logic probe,    =*/
+/*=     and handles Rabbit mode.                 =*/
 /*=                                              =*/
 /*================================================*/
 
-static void remcursor()
+static void show_events()
 {
-	prevcursorflag = cursorflag;
-	if (cursorflag)
-		xorcursor();
-	cursorflag = false;
-	cursorhide = false;
+	/*zEMBED
+	  char buf[30];
+	  extern int m_events_received;
+	  static int old_events, old_serial, old_time;
+	  int serial, time = timers_sysclock() / 200;
+	  sprintf(buf, "%d", m_events_received);
+	  m_color(log_red);
+	  if (m_events_received > old_events)
+	  drawstr2(5, 20, buf);
+	  old_events = m_events_received;
+	  sprintf(buf, "%d", serial = XNextRequest(m_display));
+	  if (serial > old_serial && time != old_time)
+	  drawstr2(5, 29, buf),
+	  old_serial = serial + 2,
+	  old_time = time;
+	  */
 }
 
 
-/*================  RESTORECURSOR  ===============*/
+/*==================  POLLKBD2  ==================*/
 /*=                                              =*/
-/*=  Restore the cursor to its previous on/off   =*/
-/*=     status.                                  =*/
+/*=  Return TRUE if a key has been pressed       =*/
+/*=     (via keyboard or menu boxes).            =*/
 /*=                                              =*/
 /*================================================*/
 
-static void restorecursor()
+static int pollkbd2()
 {
-	if (prevcursorflag != cursorflag)
-		xorcursor();
-	cursorflag = prevcursorflag;
+	return (nk_keybufsize() != 0 || pushedbackkey != '\0');
 }
 
 
-/*==================  SETMODE  ===================*/
-/*=                                              =*/
-/*=  Draw a word in the "mode" location of       =*/
-/*=     the menu area.                           =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refreditmode ();
-
-static void log_setmode(const char *s)
+static void pen()
 {
-	time_t h;
-	char *cp;
 
-	remcursor();
-	clipoff();
-	m_color((long)gg.color.backgr);
-	if (gg.showpage > 0)
-		drawstr2(across + menux3, line2, modename);
-	refreditmode();   /*may have been trashed by previous mode name*/
-	if (*s != '\0')
-	{
-		strcpy(modename, s);
-		modeflag = true;
-		m_color((long)gg.color.selword);
-	}
-	else
-	{
-		if (gg.probekind != NULL)
-		{
-			strcpy(modename, gg.probekind->name);
-			m_color((long)gg.color.selword);
-		}
-		else
-		{
-			time(&h);
-			cp = ctime(&h);
-			sprintf(modename, "%.5s", cp + 11);
-			modetime = timers_sysclock() / 6000;
-			if (!strcmp(modename, "00:00"))
-				strcpy(modename, "__@/ ");
-			m_color((long)gg.color.menuword);
-		}
-		modeflag = false;
-		modeprobekind = gg.probekind;
-	}
-	if (gg.showpage > 0)
-		drawstr2(across + menux3, line2, modename);
-}
+#define ALERTNESS 2 /* Time to get bored (in cs) */
+#define DOZETIME  5 /* Time to sleep after nodding off */
 
+	long x, y;
+	short i, rx, ry, cred;
+	/* static int pollkbd2(void); */
+	static int oldx, oldy;
+	static long awake;
+	long now;
+	char rval, gval, bval;
 
-static void dounits(char *s, double *r)
-{
-	char ch;
 
-	if (*s == '\0')
-		return;
-	ch = s[0];
-	if (ch >= 'a')
-		ch -= 32;
-	if (ch == 'F')
+	/* the following section improves idling behavior       */
+	/* contributed by Nick Bailey (een6njb@sun.leeds.ac.uk) */
+
+	/* Keep on your toes if s/he's still twitching about! */
+	now = timers_sysclock();
+	if (gg.t.x!=oldx || gg.t.y!=oldy || pollkbd2() || gg.busyflag)
 	{
-		*r *= 1e-15;
-		return;
+		awake = now;
+		oldx = gg.t.x; oldy = gg.t.y;
 	}
-	if (ch == 'P')
-	{
-		*r *= 1e-12;
-		return;
-	}
-	if (ch == 'N')
-	{
-		*r *= 1e-9;
-		return;
-	}
-	if (ch == 'U')
-	{
-		*r *= 1e-6;
-		return;
-	}
-	if (ch == 'K')
-	{
-		*r *= 1e3;
-		return;
-	}
-	if (ch == 'G')
-	{
-		*r *= 1e9;
-		return;
-	}
-	if (ch == 'T')
-	{
-		*r *= 1e12;
-		return;
-	}
-	if (ch != 'M')
-		return;
-	if (strlen(s) >= 3 && (s[1] == 'E' || s[1] == 'e') &&
-			(s[2] == 'G' || s[2] == 'g'))
-		*r *= 1e6;
-	else
-		*r *= 1e-3;
-}
-
-
-static void readreal(char *s_, double *r)
-{
-	char s[256];
-	long i;
-	char *STR1;
-	char STR2[256];
-
-	strcpy(s, s_);
-	if (!(*s != '\0' &&
-				(s[0] == '.' || s[0] == '+' || s[0] == '-' || isdigit(s[0]))))
-		return;
-	*r = strtod(s, &STR1);
-	i = STR1 - s + 1;
-	strcpy_overlap(s, s + i - 1);
-	strcpy(STR2, strltrim(s));
-	strcpy(s, STR2);
-	dounits(s, r);
-}
-
-
-static void strwordx(char *buf, char *wrd)
-{
-	short i;
-	char STR1[256];
-	char STR2[256];
-
-	strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf))));
-	strcpy(buf, STR1);
-	if (*buf != '"')
-	{
-		strword(buf, wrd);
-		return;
-	}
-	i = strposc(buf, '"', 2L);
-	if (i == 0)
-		i = strlen(buf) + 1;
-	strpart(wrd, buf, 2, i - 1);
-	strcpy_overlap(buf, buf + i);
-}
-
-
-static void getword(char *buf, char *wrd)
-{
-	char STR1[256];
-	char STR2[256];
-
-	strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf))));
-	strcpy(buf, STR1);
-	if (*buf == '"')
-		strwordx(buf, wrd);
-	else
-	{
-		strwordx(buf, wrd);
-		strupper(wrd, wrd);
-	}
-}
-
-
-static long getint(char *s, long def)
-{
-	char w[10];
-	long i, j, sign;
-	int valid;
-	long FORLIM;
-
-	getword(s, w);
-	if (*w == '-')
-	{
-		strcpy_overlap(w, w + 1);
-		sign = -1;
-	}
-	else
-	{
-		sign = 1;
-	}
-	j = 0;
-	valid = true;
-	FORLIM = strlen(w);
-	for (i = 0; i < FORLIM; i++)
-	{
-		if (w[i] < '0' || w[i] > '9')
-			valid = false;
-		else
-			j = j * 10 + w[i] - 48;
-	}
-
-	if (*w != '\0' && valid)
-		return (j * sign);
-	else
-		return def;
-}
-
-
-static void pgetint(char *buf, long *i, long def)
-{
-	*i = getint(buf, def);
-}
-
+	/* Be friendly when not running something important */
+	if (now-awake > (unsigned long)ALERTNESS)
+		microsleep((unsigned long)10000*DOZETIME);
 
-static double getreal(char *s, double def)
-{
-	char w[81];
-	double r;
+	/* end of idling-improvement section */
 
-	getword(s, w);
-	r = def;
-	TRY(try1);
-	readreal(w, &r);
-	RECOVER(try1);
+	TRY(try3);
+	gg.t0 = gg.t;
+	m_readpen(&gg.t);
+	show_events();
+	gg.stillnear = (gg.stillnear && gg.t.near_);
+	gg.incircuit = (gg.t.y < baseline && gg.showpage > 0);
+	RECOVER(try3);
 	if (P_escapecode == -20)
 		_Escape(P_escapecode);
-	r = def;
-	ENDTRY(try1);
-	return r;
-}
-
-static void pgetreal(char *buf, double *r, double def)
-{
-	*r = getreal(buf, def);
-}
-
-
-static void getbool(char *buf, int *b)
-{
-	char w[17];
-
-	getword(buf, w);
-	if (!strcmp(w, "ON") || !strcmp(w, "YES") || !strcmp(w, "Y") ||
-			!strcmp(w, "RABBITS"))
-	{   /*avoid*/
-		*b = true;
-		return;
-	}
-	if (!strcmp(w, "OFF") || !strcmp(w, "NO") || !strcmp(w, "N"))
+	printf("Graphics tablet error\n");
+	m_init_pen(tabletaddr);
+	m_alpha_on();
+	ENDTRY(try3);
+	if (snapflag && gg.incircuit)
 	{
-		*b = false;
-		return;
+		gg.t.x = (gg.t.x + gg.hscale + gg.xoff) / gg.scale * gg.scale - gg.xoff;
+		gg.t.y = (gg.t.y + gg.hscale + gg.yoff) / gg.scale * gg.scale - gg.yoff;
 	}
-	
-	if (!strcmp(w, "?"))
-		tempverbose = true;
-	else if (*w == '\0')
-		*b = !*b;
-}
-
-
-/*=================  SORTSHINTS  =================*/
-/*=                                              =*/
-/*=  Put two shortint variables into increasing  =*/
-/*=     numerical order.                         =*/
-/*=                                              =*/
-/*================================================*/
-
-static void sortshints(short *x, short *y)
-{
-	short temp;
-
-	if (*x <= *y)
-		return;
-	temp = *x;
-	*x = *y;
-	*y = temp;
-}
-
-
-/*================  INSIDEGATE  ==================*/
-/*=                                              =*/
-/*=  Check if inside a gate's "yellow box."      =*/
-/*=                                              =*/
-/*================================================*/
-
-/* new version by Tim Edwards, Dec 1996 */
-
-static int insidegate(log_grec *g, short x, short y)
-{
-	short xx1, xx2, yy1, yy2, z;
-	short loc_x1, loc_x2;
-	log_krec *WITH;
 
-	x = (x - g->x) * log_scale0;
-	y = (y - g->y) * log_scale0;
-	WITH = g->kind;
-	loc_x1 = WITH->x1;
-	loc_x2 = WITH->x2;
+	if (gg.t.x < 0)
+		gg.t.x = 0;
+	else if (gg.t.x > across)
+		gg.t.x = across;
 
-	/* Modify x1 position for length of text on TO/FROM-type gates */
+	if (gg.t.y < 0)
+		gg.t.y = 0;
+	else if (gg.t.y > down)
+		gg.t.y = down;
 
-	if (WITH->flag.U3.named && g->sig > 0)
+	if (gg.t.near_ && !gg.t.depressed)
 	{
-		char STR1[256];
-		short xwid = m_strwidth(NULL, strrtrim(strcpy(STR1,
-						gg.signaltab[g->sig - 1].name))) - NAMEGAP;
-
-		if (WITH->flag.U3.nright)
-		{
-			if (xwid > loc_x2) loc_x2 = xwid;
-		}
-		else
+		rx = gg.t.x * 5 / across;
+		ry = gg.t.y * 5 / down;
+		if (rx != rablist[rabstate].x || ry != rablist[rabstate].y)
 		{
-			if (-xwid < loc_x1) loc_x1 = -xwid;
-		}
-	}
-
-	if (g->rot == 0)
-	{
-		return (loc_x1 <= x && x <= loc_x2 && WITH->y1 <= y && y <= WITH->y2);
-	}
-	else
-	{
-		z = g->rot;
-		xx1 = loc_x1 * log_rotxx[z] + WITH->y1 * log_rotyx[z];
-		xx2 = loc_x2 * log_rotxx[z] + WITH->y2 * log_rotyx[z];
-		sortshints(&xx1, &xx2);
-		yy1 = loc_x1 * log_rotxy[z] + WITH->y1 * log_rotyy[z];
-		yy2 = loc_x2 * log_rotxy[z] + WITH->y2 * log_rotyy[z];
-		sortshints(&yy1, &yy2);
-		return (xx1 <= x && x <= xx2 && yy1 <= y && y <= yy2);
-	}
-}
-
-
-/*=================  TESTPROBE  ==================*/
-/*=                                              =*/
-/*=  Find which wire, pin, or gate the Probe     =*/
-/*=     is touching and set PROBENODE or         =*/
-/*=     PROBEGATE to its address.                =*/
-/*=                                              =*/
-/*================================================*/
-
-static void unprobe()
-{
-	gg.probenode = NULL;
-	gg.probegate = NULL;
-	gg.probepin = 0;
-	gg.probesimtype = NULL;
-	gg.probekind = NULL;
-	gg.probehwire = NULL;
-	gg.probevwire = NULL;
-	probeflag = false;
-}
-
-
-static log_krec *peninkind(short xx, short yy)
-{
-	log_krec *Result;
-	short i;
-
-	Result = NULL;
-	if (!(P_ibetween((long)kindgroupleft, (long)xx, kindgroupright - 1L) &&
-				P_ibetween((long)baseline, (long)yy, (long)down)))
-		return Result;
-	i = kindgroup[(xx - kindgroupleft) / kindgroupspacing];
-	if (i > 0)
-		return (kind[(i & (log_kindoffset - 1)) - 1]);
-	return Result;
-}
-
-
-static void testprobe(short xx, short yy)
-{
-	log_grec *g;
-	log_krec *k;
-	short i, x, y;
-	log_hwrec *hw;
-	log_vwrec *vw;
-	short FORLIM;
-
-	x = (xx + gg.hscale + gg.xoff) / gg.scale;
-	y = (yy + gg.hscale + gg.yoff) / gg.scale;
-	unprobe();
-	if (gg.showpage > 0 && !gg.invisible && !gg.showconflicts)
-	{
-		if (gg.incircuit)
-		{
-			g = gg.gbase[gg.curpage - 1];
-			while (g != NULL && gg.probegate == NULL)
-			{
-				k = g->kind;
-				if (g->x >= x - k->bbmax && g->x <= x + k->bbmax &&
-						g->y >= y - k->bbmax && g->y <= y + k->bbmax)
-				{
-					if (insidegate(g, x, y))
-					{
-						gg.probegate = g;
-					}
-					else if (g->kind->simtype->simtype >= 8)
-					{
-						FORLIM = g->kind->numpins;
-						for (i = 1; i <= FORLIM; i++) {
-							if (x == g->pinpos[i - 1].x && y == g->pinpos[i - 1].y)
-							{
-								gg.probegate = g;
-								gg.probenode = g->pin[i - 1];
-								gg.probepin = i;
-							}
-						}
-					}
-				}
-				g = g->next;
-			}
-			hw = gg.hwbase[gg.curpage - 1];
-			while (hw != NULL && gg.probenode == NULL)
-			{
-				if (hw->x1 <= x && x <= hw->x2 && hw->y == y)
-				{
-					gg.probehwire = hw;
-					gg.probenode = hw->node;
-				}
-				hw = hw->next;
-			}
-			vw = gg.vwbase[gg.curpage - 1];
-			while (vw != NULL && gg.probenode == NULL)
-			{
-				if (vw->y1 <= y && y <= vw->y2 && vw->x == x)
-				{
-					gg.probevwire = vw;
-					gg.probenode = vw->node;
-				}
-				vw = vw->next;
-			}
-		}
-		else
-		{
-			gg.probekind = peninkind(xx, yy);
-		}
-	}
-	if (gg.probegate != NULL)
-		gg.probekind = gg.probegate->kind;
-	if (gg.probenode != NULL)
-		gg.probesimtype = gg.probenode->simtype;
-	else if (gg.probekind != NULL)
-		gg.probesimtype = gg.probekind->simtype;
-}
-
-
-static void checkprobe(short xx, short yy)
-{
-	short x, y;
-
-	x = (xx + gg.hscale + gg.xoff) / gg.scale;
-	y = (yy + gg.hscale + gg.yoff) / gg.scale;
-	if (gg.probegate != NULL &&
-			(gg.probegate->x < x - gg.probekind->bbmax ||
-			 gg.probegate->x > x + gg.probekind->bbmax ||
-			 gg.probegate->y < y - gg.probekind->bbmax ||
-			 gg.probegate->y > y + gg.probekind->bbmax))
-	{
-		unprobe();
-		return;
-	}
-
-	if (gg.probekind != NULL && gg.probegate == NULL &&
-			peninkind(xx, yy) != gg.probekind)
-	{
-		unprobe();
-		return;
-	}
-
-	if (gg.probehwire != NULL &&
-			(gg.probehwire->x1 > x || x > gg.probehwire->x2 ||
-			 gg.probehwire->y != y))
-		unprobe();
-	else if (gg.probevwire != NULL &&
-			(gg.probevwire->y1 > y || y > gg.probevwire->y2 ||
-			 gg.probevwire->x != x))
-		unprobe();
-}
-
-
-
-/**
- *  @param lbl: list of character to parse
- *  @param numattrs: number of found attributs
- *  @param attr: vector containing parsed attributs
- */
-static void parselabel(na_strlist_t **lbl, short *numattrs, log_kattrrec **attr)
-{
-	short j, j1, j2, j3, yy, maxx;
-	na_strlist_t *l1, *l2, *l3, *attrnames;
-	char buf[256];
-	int haveprec;
-	log_kattrrec *WITH;
-	char STR1[256];
-	char STR2[256];
-	short FORLIM;
-
-	j = 1;
-	*numattrs = 0;
-	attrnames = NULL;
-	l1 = *lbl;
-	// boucle qui compte le nombre d'attribut
-	while (l1 != NULL) {
-		j = strposc(l1->s, ':', 1L);
-		if (j != 0 && j != strpos2(l1->s, "::", 1))
-			(*numattrs)++;
-
-		l1->value = (na_long)strlen(l1->s);
-		l1 = l1->next;
-	}
-	*attr = (log_kattrrec *)Malloc(*numattrs * kattrrecsize);
-	maxx = 0;
-	l1 = *lbl;
-	j = 1;
-	yy = 0;
-	// On parcours de nouveau la liste de string
-	while (l1 != NULL)
-	{
-		j1 = strposc(l1->s, ':', 1L);
-		// Si c'est bien un attribut
-		if (j1 != 0 && j1 != strpos2(l1->s, "::", 1))
-		{
-			WITH = &(*attr)[j - 1];
-			WITH->vr = 0;
-			WITH->vra = 0;
-			strcpy(STR1, strltrim(l1->s));
-			strcpy(l1->s, STR1); // TODO optimiser
-			// elimine les [ ] si autour de l'attribut
-			while (l1->s[0] == '[')
-			{
-				j2 = strposc(l1->s, ']', 1L);
-				if (j2 < 3)
-					continue;
-				l2 = strlist_append(&attrnames, strpart(STR1, l1->s, 2, j2 - 1));
-				l2->value = (na_long)((long)j);
-				strcpy_overlap(l1->s, l1->s + j2);
-				strcpy(STR1, strltrim(l1->s));
-				strcpy(l1->s, STR1); // TODO optimiser
-			}
-			j2 = strposc(l1->s, ';', 1L);
-			if (j2 != 0 && j2 < j1)
-			{
-				sprintf(buf, "%.*s", j2 - 1, l1->s);
-				strrtrim(buf);
-				j3 = 1;
-				// Recherche si l'attribut à déjà été défini
-				while (j3 < j && WITH->vra == 0)
-				{
-					if ((*attr)[j3 - 1].dtype == 'V')
-					{
-						l2 = (*attr)[j3 - 1].UU.U86.v;
-						while (l2 != NULL && strcicmp(l2->s, buf) != 0)
-							l2 = l2->next;
-
-						if (l2 != NULL) {
-							WITH->vr = (long)l2->value;
-							WITH->vra = j3;
-						}
-					}
-					j3++;
-				}
-				strcpy_overlap(l1->s, l1->s + j2);
-			}
-			if (l1->s[0] == ' ')
-			{
-				strcpy(STR1, strltrim(l1->s));
-				strcpy(l1->s, STR1); // TODO optimiser
-			}
-			WITH->prec = 0;
-			haveprec = false;
-			while (isdigit(l1->s[0]))
-			{
-				WITH->prec = WITH->prec * 10 + l1->s[0] - 48;
-				haveprec = true;
-				strcpy_overlap(l1->s, l1->s + 1);
-			}
-			if (l1->s[0] == ' ')
-			{
-				strcpy(STR1, strltrim(l1->s));
-				strcpy(l1->s, STR1);
-			}
-			WITH->opt = false;
+			i = abs(rablist[rabstate].next) - 1;
 			do
 			{
-				WITH->dtype = toupper(l1->s[0]);
-				if (l1->s[0] != ':')
-				{
-					do
-					{
-						strcpy_overlap(l1->s, l1->s + 1);
-					}
-					while (l1->s[0] == ' ');
-				}
-				if (WITH->dtype == 'O')
-					WITH->opt = true;
-
-			}
-			while (WITH->dtype == 'O');
-
-			if (WITH->dtype == 'F' || WITH->dtype == 'U' || WITH->dtype == 'R')
-			{
-				*WITH->UU.U82.u = '\0';
-				if (WITH->dtype == 'F' || WITH->dtype == 'U')
-				{
-					while (l1->s[0] != ',' && l1->s[0] != ':')
-					{
-						if (l1->s[0] != ' ' && strlen(WITH->UU.U82.u) < 3)
-							sprintf(WITH->UU.U82.u + strlen(WITH->UU.U82.u), "%c", l1->s[0]);
-
-						strcpy_overlap(l1->s, l1->s + 1);
-					}
-					if (l1->s[0] == ',')
-						strcpy_overlap(l1->s, l1->s + 1);
-
-					strcpy(STR1, strltrim(l1->s));
-					strcpy(l1->s, STR1);
-				}
-				*buf = '\0';
-				while (l1->s[0] != ':')
-				{
-					sprintf(buf + strlen(buf), "%c", l1->s[0]);
-					strcpy_overlap(l1->s, l1->s + 1);
-				}
-				WITH->UU.U82.r = 0.0;
-				WITH->blnk = true;
-				if (*buf != '\0')
-				{
-					readreal(buf, &WITH->UU.U82.r);
-					WITH->blnk = false;
-				}
-				if (!haveprec)
-					WITH->prec = 0;
-
-			}
-			else if (WITH->dtype == 'I')
-			{
-				WITH->UU.U73.i1 = 0;
-				WITH->blnk = true;
-				while (isdigit(l1->s[0]))
-				{
-					WITH->UU.U73.i1 = WITH->UU.U73.i1 * 10 + l1->s[0] - 48;
-					strcpy_overlap(l1->s, l1->s + 1);
-					WITH->blnk = false;
-				}
-				if (!haveprec)
-					WITH->prec = 1;
-
-			}
-			else if (WITH->dtype == 'H')
-			{
-				WITH->UU.U73.i1 = 0;
-				j1 = 0;
-				WITH->blnk = true;
-				while ((l1->s[0] >= 'a' && l1->s[0] <= 'f') ||
-						(l1->s[0] >= 'A' && l1->s[0] <= 'F') || isdigit(l1->s[0]))
-				{
-					WITH->UU.U73.i1 = WITH->UU.U73.i1 * 10 + l1->s[0] - 48;
-					if (l1->s[0] >= 'A')
-						WITH->UU.U73.i1 -= 7;
-
-					if (l1->s[0] >= 'a')
-						WITH->UU.U73.i1 -= 32;
-
-					strcpy_overlap(l1->s, l1->s + 1);
-					j1++;
-					WITH->blnk = false;
-				}
-				if (!haveprec)
-				{
-					if (j1 != 0)
-						WITH->prec = j1;
-					else
-						WITH->prec = 1;
-				}
-			}
-			else if (WITH->dtype == 'C')
-			{
-				j1 = strposc(l1->s, ':', 1L);
-				sprintf(buf, "%.*s", j1 - 1, l1->s);
-				strrtrim(buf);
-				strcpy_overlap(l1->s, l1->s + j1 - 1);
-				if (!haveprec)
-					WITH->prec = 255;
-
-				if (strlen(buf) > WITH->prec)
-					buf[WITH->prec] = '\0';
-
-				WITH->UU.c = (char *)Malloc(WITH->prec + 1L);
-				strcpy(WITH->UU.c, buf);
-				WITH->blnk = (*buf == '\0');
-			}
-			else if (WITH->dtype == 'A')
-			{
-				j1 = strposc(l1->s, ':', 1L);
-				sprintf(buf, "%.*s", j1 - 1, l1->s);
-				strrtrim(buf);
-				strcpy_overlap(l1->s, l1->s + j1 - 1);
-				WITH->prec = 255;
-				WITH->UU.sp = strdup(buf);
-				WITH->blnk = (*buf == '\0');
-			}
-			else if (WITH->dtype == 'B')
-			{
-				WITH->blnk = false;
-				if (l1->s[0] == 'y' || l1->s[0] == 'Y' || l1->s[0] == 't' || l1->s[0] == 'T')
-					WITH->UU.b = true;
-				else if (l1->s[0] == 'n' || l1->s[0] == 'N' || l1->s[0] == 'f' || l1->s[0] == 'F')
-					WITH->UU.b = false;
-				else
-					WITH->blnk = true;
-
-				if (l1->s[0] == 'x' || l1->s[0] == 'X' || l1->s[0] == 'f' ||
-						l1->s[0] == 'F' || l1->s[0] == 't' || l1->s[0] == 'T')
-					WITH->prec = 2;
-				else
-					WITH->prec = 1;
-			}
-			else if (WITH->dtype == 'V')
+				i++;
+			} while ((rablist[i].x != rx || rablist[i].y != ry) &&
+					rablist[i].next < 0);
+			if (rablist[i].x == rx && rablist[i].y == ry)
 			{
-				strlist_init(&l2);
-				WITH->UU.U86.nv = 0;
-				do
+				if (i == rablistsize)
 				{
-					*buf = '\0';
-					while (l1->s[0] != ',' && l1->s[0] != ':')
+					remcursor();
+					rabbits = !rabbits;
+					if (rabbits && !gg.quiet)
 					{
-						sprintf(buf + strlen(buf), "%c", l1->s[0]);
-						strcpy_overlap(l1->s, l1->s + 1);
+						i = 1;
+						x = timers_sysclock();
+						do
+						{
+							y = discomadness[i - 1].time;
+							BEEPER(discomadness[i - 1].note, (int)y);
+							do
+							{
+							} while (timers_sysclock() <= x + y);
+							/* nothing */
+							i++;
+							x = timers_sysclock();
+						} while (y != 0);
 					}
-					if (l1->s[0] == ',')
-						strcpy_overlap(l1->s, l1->s + 1);
-
-					l3= strlist_append(&l2,strcpy(STR1, strltrim(strrtrim(strcpy(STR2, buf)))));
-					l3->value = (na_long)((long)WITH->UU.U86.nv);
-					WITH->UU.U86.nv++;
-					strcpy(STR1, strltrim(l1->s));
-					strcpy(l1->s, STR1);
-				}
-				while (l1->s[0] != ':');
-				WITH->UU.U86.v = l2;
-				WITH->blnk = false;
-				if (haveprec)
-					WITH->UU.U86.dv = WITH->prec;
-				else
-					WITH->UU.U86.dv = 0;
-
-				WITH->prec = 1;
-			}
-			else
-			{
-				WITH->dtype = 'R';
-				WITH->UU.U82.r = 0.0;
-				WITH->blnk = true;
-				if (!haveprec)
-					WITH->prec = 0;
-			}
-			if (WITH->blnk)
-				WITH->opt = true;
-
-			j1 = strposc(l1->s, ':', 1L);
-			strcpy_overlap(l1->s, l1->s + j1);
-			j++;
-			WITH->y = yy;
-			if (strlen(l1->s) > maxx)
-				maxx = strlen(l1->s);
-
-		}
-		j1 = 1;
-		while (j1 < strlen(l1->s))
-		{
-			if (l1->s[j1 - 1] == ':' && l1->s[j1] == ':')
-				strcpy_overlap(l1->s + j1 - 1, l1->s + j1);
-			j1++;
-		}
-		yy++;
-		l1 = l1->next;
-	}
-	if (attrnames != NULL) {
-		l1 = strlist_insert(lbl, "");
-		l1->kind = '\001';
-		l1->value = (void *)attrnames;
-	}
-	FORLIM = *numattrs;
-	for (j = 0; j < FORLIM; j++)
-		(*attr)[j].x = maxx + 1;
-}
-
-
-static void stamp(long *i)
-{
-	gg.curstamp++;
-	*i = gg.curstamp;
-}
-
-
-static void newtool(log_tool **t, char *name)
-{
-	log_tool *t2;
-
-	*t = (log_tool *)Malloc(sizeof(log_tool));
-	strcpy((*t)->name, name);
-	(*t)->ready = false;
-	(*t)->simulator = false;
-	(*t)->keep = false;
-	(*t)->nostatus = false;
-	(*t)->fname = NULL;
-	(*t)->comment = (char *)Malloc(256);
-	*(*t)->comment = '\0';
-	(*t)->info = (na_long)0;
-	(*t)->nlbl = NULL;
-	(*t)->hlbl = NULL;
-	(*t)->shortname = (char *)Malloc(33);
-	strcpy((*t)->shortname, name);
-	stamp(&(*t)->netstamp);
-	(*t)->deltatime = 0.0;
-	t2 = gg.toolbase;
-	while (t2 != NULL && t2->next != NULL)
-		t2 = t2->next;
-	if (t2 == NULL)
-		gg.toolbase = *t;
-	else
-		t2->next = *t;
-	(*t)->next = NULL;
-}
-
-
-static log_tool *findtool(char *name_)
-{
-	log_tool *Result;
-	char name[17];
-	log_tool *lp;
-	char savefunc[17];
-	char saveargs[256];
-	char suffix[51];
-	void (*proc) (log_action_t *act);
-	int ready;
-	cnfrec *cnfp;
-
-	strcpy(name, name_);
-	strcpy(savefunc, gg.func);
-	strcpy(saveargs, gg.funcarg);
-	lp = gg.toolbase;
-	while (lp != NULL && strcmp(lp->name, name))
-		lp = lp->next;
-	if (lp == NULL)
-		newtool(&lp, name);
-	if (!lp->ready)
-	{
-		sprintf(suffix, "LOG_%s_PROC", name);
-		ready = newci_findprocedure2(suffix, (void(**) ())(&proc));
-		if (gg.traceflag)
-			fprintf(tracefile, "Findtool to load: %s -  %s.\n", suffix, lp->fname);
-		
-		if (!ready && lp->fname != NULL)
-		{
-			TRY(try2);
-			newci_fixfname(lp->fname, "code", "");
-			if (gg.traceflag)
-				fprintf(tracefile, "Findtool, loading %s\n", lp->fname);
-			newci_loadprogram(lp->fname);
-			RECOVER(try2);
-			if (P_escapecode == -20)
-				_Escape(P_escapecode);
-			ENDTRY(try2);
-			ready = newci_findprocedure2(suffix, (void(**) ())(&proc));
-			if (gg.traceflag)
-				fprintf(tracefile, "Findtool, ready=%s\n", ready ? " TRUE" : "FALSE");
-		}
-		
-		if (ready)
-		{
-			lp->proc = proc;
-			gg.action = act_init;
-			gg.acttool = lp;
-			(*proc)(&gg);
-			if (lp->ready)
-			{
-				cnfp = cnfbase;
-				while (cnfp != NULL)
-				{
-					if (!strcmp(cnfp->tool, name))
-					{
-						doingcnffunction = true;
-						gg.action = act_cnf;
-						strcpy(gg.funcarg, cnfp->s);
-						getword(gg.funcarg, gg.func);
-						(*proc)(&gg);
-						doingcnffunction = false;
-					}
-					cnfp = cnfp->next;
-				}
-				gg.action = act_color;
-				(*proc)(&gg);
-				gg.action = act_endinit;
-				(*proc)(&gg);
-				lp->nexttstep = 0.0;
-				lp->nnumattrs = 0;
-				lp->nattr = NULL;
-				if (lp->nlbl != NULL)
-					parselabel(&lp->nlbl, &lp->nnumattrs, &lp->nattr);
-				lp->hnumattrs = 0;
-				lp->hattr = NULL;
-				if (lp->hlbl != NULL)
-					parselabel(&lp->hlbl, &lp->hnumattrs, &lp->hattr);
-			}
-		}
-	}
-	Result = lp;
-	strcpy(gg.func, savefunc);
-	strcpy(gg.funcarg, saveargs);
-	return Result;
-}
-
-
-static void calltool(log_tool *t, log_actionkinds act)
-{
-	log_tool *savetool;
-
-	savetool = gg.acttool;
-	gg.action = act;
-	gg.acttool = t;
-	(*t->proc)(&gg);
-	gg.acttool = savetool;
-}
-
-
-static void calltoolgate(log_grec *g, log_actionkinds act)
-{
-	gg.actgate = g;
-	calltool(g->kind->simtype, act);
-}
-
-
-static void calltoolnode(log_nrec *n, log_actionkinds act)
-{
-	gg.actnode = n;
-	calltool(n->simtype, act);
-}
-
-static void calltoolkind(log_krec *k, log_actionkinds act)
-{
-	gg.actkind = k;
-	calltool(k->simtype, act);
-}
-
-static void calltools(log_actionkinds act)
-{
-	log_tool *tp;
-
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready)
-			calltool(tp, act);
-		tp = tp->next;
-	}
-}
-
-
-static void callsimtools(log_actionkinds act)
-{
-	log_tool *tp;
-
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready && tp->simulator)
-			calltool(tp, act);
-		tp = tp->next;
-	}
-}
-
-
-static void send_general(log_tool *sim, char *act)
-{
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	strcpy(gg.genfunc, act);
-	calltool(sim, act_general);
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_gennode(log_nrec *n, char *act)
-{
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	strcpy(gg.genfunc, act);
-	calltoolnode(n, act_gennode);
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_genkind(log_krec *k, char *act)
-{
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	strcpy(gg.genfunc, act);
-	calltoolkind(k, act_genkind);
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_gengate(log_grec *g, char *act)
-{
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	strcpy(gg.genfunc, act);
-	calltoolgate(g, act_gengate);
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_all(char *act)
-{
-	log_tool *tp;
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready && tp->simulator)
-		{
-			strcpy(gg.genfunc, act);
-			calltool(tp, act_general);
-		}
-		tp = tp->next;
-	}
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_allnodes(char *act)
-{
-	log_tool *tp;
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready && tp->simulator)
-		{
-			strcpy(gg.genfunc, act);
-			gg.actnode = NULL;
-			calltool(tp, act_gennode);
-		}
-		tp = tp->next;
-	}
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_allkinds(char *act)
-{
-	log_tool *tp;
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready && tp->simulator)
-		{
-			strcpy(gg.genfunc, act);
-			gg.actkind = NULL;
-			calltool(tp, act_genkind);
-		}
-		tp = tp->next;
-	}
-	strcpy(gg.genfunc, savefunc);
-}
-
-
-static void send_allgates(char *act)
-{
-	log_tool *tp;
-	char savefunc[17];
-
-	strcpy(savefunc, gg.genfunc);
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		if (tp->ready && tp->simulator)
-		{
-			strcpy(gg.genfunc, act);
-			gg.actgate = NULL;
-			calltool(tp, act_gengate);
-		}
-		tp = tp->next;
-	}
-	strcpy(gg.genfunc, savefunc);
-}
-
-static void closetool(log_tool *tp)
-{
-	if (tp->ready)
-		calltool(tp, act_exit);
-	tp->ready = false;
-}
-
-
-static void closetools()
-{
-	log_tool *tp;
-
-	tp = gg.toolbase;
-	while (tp != NULL)
-	{
-		closetool(tp);
-		tp = tp->next;
-	}
-}
-
-
-static long glowcol(log_nrec *n, long def)
-{
-	gg.actx = def;
-	calltoolnode(n, act_glowcol);
-	return (gg.actx);
-}
-
-
-static void resetmessages()
-{
-	short opos;
-
-	opos = messagepos;
-	messagepos = topmessagepos;
-	messageright = 0;
-	if (messagepos != opos)
-	{
-		calltools(act_clearmsg);
-		stamp(&gg.msgstamp);
-	}
-}
-
-
-/*================  CLEARSCREEN  =================*/
-/*=                                              =*/
-/*=  Clear the screen.                           =*/
-/*=                                              =*/
-/*================================================*/
-
-static void clearscreen()
-{
-	remcursor();
-	m_noclip();
-	m_vsetcolors((long)gg.color.backgr, 1L, &rcolormap[gg.color.backgr],
-			&gcolormap[gg.color.backgr], &bcolormap[gg.color.backgr]);
-	m_color((long)gg.color.backgr);
-	m_fillrect(0L, 0L, (long)across, (long)down);
-	fixcolormap();
-	resetmessages();
-	bottomcount = 0;
-	gg.showpage = 0;
-}
-
-
-static void clearshowalpha()
-{
-	if (onescreen)
-		clearscreen();
-	printf("\f");
-	nk_gotoxy(0, 0);
-	noblink();
-	showalpha();
-}
-
-
-/*====================  PEN  =====================*/
-/*=                                              =*/
-/*=  Find the position of the pen.  Returns:     =*/
-/*=     D, D0 if the pen is/was down;            =*/
-/*=     N, N0 if the pen is/was near;            =*/
-/*=     DN, UP if the pen is pressed/released;   =*/
-/*=     NR if pen remains near;                  =*/
-/*=     OFFSCREEN if pen is off the screen edge; =*/
-/*=     PX, PY, PX0, PY0 = new/old position;     =*/
-/*=     FX, FY = position in grid coordinates;   =*/
-/*=     MENUBOX = menu box number (0-15);        =*/
-/*=                                              =*/
-/*=  Also draws the cursor, runs logic probe,    =*/
-/*=     and handles Rabbit mode.                 =*/
-/*=                                              =*/
-/*================================================*/
-
-static void show_events()
-{
-	/*zEMBED
-	  char buf[30];
-	  extern int m_events_received;
-	  static int old_events, old_serial, old_time;
-	  int serial, time = timers_sysclock() / 200;
-	  sprintf(buf, "%d", m_events_received);
-	  m_color(log_red);
-	  if (m_events_received > old_events)
-	  drawstr2(5, 20, buf);
-	  old_events = m_events_received;
-	  sprintf(buf, "%d", serial = XNextRequest(m_display));
-	  if (serial > old_serial && time != old_time)
-	  drawstr2(5, 29, buf),
-	  old_serial = serial + 2,
-	  old_time = time;
-	  */
-}
-
-
-/*==================  POLLKBD2  ==================*/
-/*=                                              =*/
-/*=  Return TRUE if a key has been pressed       =*/
-/*=     (via keyboard or menu boxes).            =*/
-/*=                                              =*/
-/*================================================*/
-
-static int pollkbd2()
-{
-	return (nk_keybufsize() != 0 || pushedbackkey != '\0');
-}
-
-
-static void pen()
-{
-
-#define ALERTNESS 2 /* Time to get bored (in cs) */
-#define DOZETIME  5 /* Time to sleep after nodding off */
-
-	long x, y;
-	short i, rx, ry, cred;
-	/* static int pollkbd2(void); */
-	static int oldx, oldy;
-	static long awake;
-	long now;
-	char rval, gval, bval;
-
-
-	/* the following section improves idling behavior       */
-	/* contributed by Nick Bailey (een6njb@sun.leeds.ac.uk) */
-
-	/* Keep on your toes if s/he's still twitching about! */
-	now = timers_sysclock();
-	if (gg.t.x!=oldx || gg.t.y!=oldy || pollkbd2() || gg.busyflag)
-	{
-		awake = now;
-		oldx = gg.t.x; oldy = gg.t.y;
-	}
-	/* Be friendly when not running something important */
-	if (now-awake > (unsigned long)ALERTNESS)
-		microsleep((unsigned long)10000*DOZETIME);
-
-	/* end of idling-improvement section */
-
-	TRY(try3);
-	gg.t0 = gg.t;
-	m_readpen(&gg.t);
-	show_events();
-	gg.stillnear = (gg.stillnear && gg.t.near_);
-	gg.incircuit = (gg.t.y < baseline && gg.showpage > 0);
-	RECOVER(try3);
-	if (P_escapecode == -20)
-		_Escape(P_escapecode);
-	printf("Graphics tablet error\n");
-	m_init_pen(tabletaddr);
-	m_alpha_on();
-	ENDTRY(try3);
-	if (snapflag && gg.incircuit)
-	{
-		gg.t.x = (gg.t.x + gg.hscale + gg.xoff) / gg.scale * gg.scale - gg.xoff;
-		gg.t.y = (gg.t.y + gg.hscale + gg.yoff) / gg.scale * gg.scale - gg.yoff;
-	}
-
-	if (gg.t.x < 0)
-		gg.t.x = 0;
-	else if (gg.t.x > across)
-		gg.t.x = across;
-
-	if (gg.t.y < 0)
-		gg.t.y = 0;
-	else if (gg.t.y > down)
-		gg.t.y = down;
-
-	if (gg.t.near_ && !gg.t.depressed)
-	{
-		rx = gg.t.x * 5 / across;
-		ry = gg.t.y * 5 / down;
-		if (rx != rablist[rabstate].x || ry != rablist[rabstate].y)
-		{
-			i = abs(rablist[rabstate].next) - 1;
-			do
-			{
-				i++;
-			} while ((rablist[i].x != rx || rablist[i].y != ry) &&
-					rablist[i].next < 0);
-			if (rablist[i].x == rx && rablist[i].y == ry)
-			{
-				if (i == rablistsize)
-				{
-					remcursor();
-					rabbits = !rabbits;
-					if (rabbits && !gg.quiet)
-					{
-						i = 1;
-						x = timers_sysclock();
-						do
-						{
-							y = discomadness[i - 1].time;
-							BEEPER(discomadness[i - 1].note, (int)y);
-							do
-							{
-							} while (timers_sysclock() <= x + y);
-							/* nothing */
-							i++;
-							x = timers_sysclock();
-						} while (y != 0);
-					}
-					rabstate = 0;
-				} else
-					rabstate = i;
-			} else
-				rabstate = 0;
-		}
-	}
-	else
-	{
-		rabstate = 0;
-	}
-
-	if (gg.probemode)
-	{
-		if (cursx != gg.t.x || cursy != gg.t.y)
-		{
-			if (gg.probesimtype != NULL)
-				checkprobe((int)gg.t.x, (int)gg.t.y);
-			probeflag = false;
-			drawcursor((int)gg.t.x, (int)gg.t.y);
-		}
-		else
-		{
-			if (!cursorflag)
-				drawcursor((int)gg.t.x, (int)gg.t.y);
-			if (!probeflag)
-			{
-				testprobe((int)gg.t.x, (int)gg.t.y);
-				probeflag = true;
-			}
-		}
-
-		if (!gg.t.near_ && briefprobe)
-		{
-			remcursor();
-			gg.probemode = false;
-		}
-	}
-	else
-	{
-		briefprobe = false;
-		if (gg.probesimtype != NULL)
-			unprobe();
-		if (gg.t.near_)
-			drawcursor((int)gg.t.x, (int)gg.t.y);
-		else
-			remcursor();
-	}
-	cred = gg.color.conflict;
-	if (anyconflicts && (cred == log_cred || cred == log_cred8) &&
-			(rcolormap[cred] == 255 || gcolormap[cred] == 255 ||
-			 bcolormap[cred] == 255))
-	{
-		x = timers_sysclock() * 6 % 137 + 119;
-		rval = (char)(x * rcolormap[cred] / 255);
-		gval = (char)(x * gcolormap[cred] / 255);
-		bval = (char)(x * bcolormap[cred] / 255);
-		m_vsetcolors((long)cred, 1L, (unsigned char *) &rval,
-				(unsigned char *) &gval, (unsigned char *) &bval);
-	}
-
-	if (gg.t.moving)
-	{
-		gg.fastspeed = gg.fastmin;
-		fastsavetime = timers_sysclock();
-	}
-	else if (gg.fastspeed < gg.fastmax &&
-			timers_sysclock() > fastsavetime + gg.fastrate)
-	{
-		gg.fastspeed++;
-		fastsavetime = timers_sysclock();
-	}
-	gg.gridx = (gg.t.x + gg.hscale + gg.xoff) / gg.scale;
-	gg.gridy = (gg.t.y + gg.hscale + gg.yoff) / gg.scale;
-}
-
-
-/*=================  JUSTTAP  ====================*/
-/*=                                              =*/
-/*=  Return TRUE if pen was tapped.  Return      =*/
-/*=     FALSE if pen was held and/or moved.      =*/
-/*=                                              =*/
-/*================================================*/
-
-static int justtap()
-{
-	long t0;
-	short tx, ty;
-
-	t0 = timers_sysclock() + tapdelay;
-	tx = gg.t.x;
-	ty = gg.t.y;
-	do
-	{
-		pen();
-	} while (gg.t.depressed && labs(gg.t.x - tx) <= taptolerance &&
-			labs(gg.t.y - ty) <= taptolerance && timers_sysclock() <= t0);
-	return (!gg.t.depressed);
-}
-
-
-/*==================  TESTKEY2  ==================*/
-/*=                                              =*/
-/*=  Return the most recently pressed key.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static char testkey2()
-{
-	if (pushedbackkey != '\0')
-		return pushedbackkey;
-	else if (pollkbd2())
-		return (nk_testkey(0));
-	else
-		return ' ';
-}
-
-
-/*==================  INKEY2  ====================*/
-/*=                                              =*/
-/*=  Return a keystroke.  Key is removed from    =*/
-/*=     the buffer.                              =*/
-/*=                                              =*/
-/*================================================*/
-
-static char inkey2()
-{
-	char ch;
-
-	do
-	{
-	} while (!pollkbd2());
-	if (pushedbackkey != '\0')
-	{
-		realkey = pushedbackkey;
-		pushedbackkey = '\0';
-	}
-	else
-	{
-		realkey = nk_getkey();
-	}
-	ch = realkey;
-	if ((ch & 255) >= 168 && (ch & 255) <= 239 && nk_capslock)
-	{
-		if ((ch & 255) <= 193)
-		{
-			ch += 46;
-		} else if ((ch & 255) >= 214)
-		{
-			ch -= 46;
-		}
-	}
-	gg.fastspeed = gg.fastmin;
-	return ch;
-}
-
-
-static void inkey3(char *ch)
-{
-	*ch = inkey2();
-}
-
-
-static char inkey4()
-{
-	/* undo CAPSLOCK key */
-	char ch;
-
-	ch = inkey2();
-	if (!nk_capslock)
-		return ch;
-	if (isupper(ch))
-		ch += 32;
-	else if (islower(ch))
-		ch -= 32;
-	return ch;
-}
-
-
-static void ungetkey2(char ch)
-{
-	pushedbackkey = ch;
-}
-
-
-/*===============  WAITFORKEY  ===================*/
-/*=                                              =*/
-/*=  Wait until a key is pressed (but ignore it) =*/
-/*=                                              =*/
-/*================================================*/
-
-static void waitforkey()
-{
-	char ch;
-
-	while (pollkbd2())
-		ch = inkey2();
-	do
-	{
-		pen();
-	} while (!(pollkbd2() || (gg.t.dn && gg.t.off)));
-	if (pollkbd2())
-		ch = inkey2();
-}
-
-
-/*===================  INBOX  ====================*/
-/*=                                              =*/
-/*=  Return TRUE if cursor is inside a certain   =*/
-/*=     rectangular area (screen coordinates).   =*/
-/*=                                              =*/
-/*================================================*/
-
-static int inbox(short x, short y, short x1, short y1)
-{
-	return (gg.t.x >= x && gg.t.y >= y && gg.t.x <= x + x1 && gg.t.y <= y + y1);
-}
-
-
-/*================  UDRAWGATEC  ==================*/
-/*=                                              =*/
-/*=  Draw a gate of specified color at a         =*/
-/*=     certain position (screen coordinates).   =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawvector2(log_vectorrec *v, long x1, long y1, long x2, long y2)
-{
-	long diam, savecol, coord;
-
-	switch (v->vkind)
-	{
-
-		case 'v':
-			m_drawline(x1, y1, x2, y2);
-			break;
-
-		case 'C':
-			diam = P_imax2(labs(x1 - x2), labs(y1 - y2));
-			switch (diam)
-			{
-
-				case 3:
-					if (x1 == x2)
-					{
-						coord = P_imin2(y1, y2);
-						m_move2(x1, coord);
-						m_draw(x1 + 2, coord + 1);
-						m_draw(x1 + 2, coord + 2);
-						m_draw(x1, coord + 3);
-						m_draw(x1 - 2, coord + 2);
-						m_draw(x1 - 2, coord + 1);
-						m_draw(x1, coord);
-					}
-					else if (y1 == y2)
-					{
-						coord = P_imin2(x1, x2);
-						m_move2(coord, y1);
-						m_draw(coord + 1, y1 + 2);
-						m_draw(coord + 2, y1 + 2);
-						m_draw(coord + 3, y1);
-						m_draw(coord + 2, y1 - 2);
-						m_draw(coord + 1, y1 - 2);
-						m_draw(coord, y1);
-					}
-					else
-					{
-						m_circle((x1 + x2) / 2, (y1 + y2) / 2, 1L);
-					}
-					break;
-
-				case 5:
-					if (x1 == x2)
-					{
-						coord = P_imin2(y1, y2);
-						m_move2(x1, coord);
-						m_draw(x1 + 3, coord + 1);
-						m_draw(x1 + 3, coord + 4);
-						m_draw(x1, coord + 5);
-						m_draw(x1 - 3, coord + 4);
-						m_draw(x1 - 3, coord + 1);
-						m_draw(x1, coord);
-					}
-					else if (y1 == y2)
-					{
-						coord = P_imin2(x1, x2);
-						m_move2(coord, y1);
-						m_draw(coord + 1, y1 + 3);
-						m_draw(coord + 4, y1 + 3);
-						m_draw(coord + 5, y1);
-						m_draw(coord + 4, y1 - 3);
-						m_draw(coord + 1, y1 - 3);
-						m_draw(coord, y1);
-					}
-					else
-					{
-						m_circle((x1 + x2) / 2, (y1 + y2) / 2, 2L);
-					}
-					break;
-
-				default:
-					m_circle((x1 + x2) / 2, (y1 + y2) / 2, diam / 2);
-					break;
-			}
-			break;
-
-		case 'e':
-			savecol = m_curcolor();
-			m_color(m_trans);
-			m_ellipse((x1 + x2) / 2, (y1 + y2) / 2, (x1 - x2) / 2, (y1 - y2) / 2,
-					savecol);
-			m_color(savecol);
-			break;
-
-		case 'E':
-			m_ellipse((x1 + x2) / 2, (y1 + y2) / 2, (x1 - x2) / 2, (y1 - y2) / 2,
-					m_curcolor());
-			break;
-
-		case 'r':   /*should do a true roundrect*/
-			m_drawrect(x1, y1, x2, y2);
-			break;
-	}
-}
-
-
-static void drawvector4(log_vectorrec *v, long x1, long y1, long x2, long y2, long x3, long y3, long x4, long y4)
-{
-	long xarr[4], yarr[4];
-
-	switch (v->vkind)
-	{
-
-		case 'c':
-			m_bezier(x1, y1, x2, y2, x3, y3, x4, y4);
-			break;
-
-		case 'F':
-			xarr[0] = x1;
-			yarr[0] = y1;
-			xarr[1] = x2;
-			yarr[1] = y2;
-			xarr[2] = x3;
-			yarr[2] = y3;
-			xarr[3] = x4;
-			yarr[3] = y4;
-			m_fillpoly(4L, (int *) xarr, (int *) yarr);
-			break;
-	}
-}
-
-
-#define big1            "0.,+123-456*789/\0()^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
-#define big2            "0.,\000123-456\000789 "
-
-
-static void drawtext(log_vectorrec *v, long scale, long rot, long xx, long yy)
-{
-	long sc, i, j, tx, ty;
-	char mode;
-	char buf[256];
-	long FORLIM;
-
-	sc = v->UU.U116.tsize * scale;
-	if (sc >= log_scale0 * 70)
-	{
-		tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
-			(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
-		ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
-			(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
-		i = strposc(v->UU.U116.sp, '$', 1L);
-		if (i > 0 && i < strlen(v->UU.U116.sp))
-		{
-			strcpy(buf, v->UU.U116.sp);
-			mode = 'X';
-			while (i <= strlen(buf)) {
-				if (buf[i - 1] == '$' && i < strlen(buf))
-				{
-					switch (toupper(buf[i]))
-					{
-
-						case '$':
-							strcpy_overlap(buf + i - 1, buf + i);
-							i++;
-							break;
-
-						case 'P':
-						case 'B':
-						case 'O':
-						case 'X':
-							mode = toupper(buf[i]);   /*close enough*/
-							strcpy_overlap(buf + i - 1, buf + i + 1);
-							break;
-
-						default:
-							i++;
-							break;
-					}
-					continue;
-				}
-				switch (mode)
-				{
-
-					case 'P':
-						j = strposc("0.,+123-456*789/E()^", buf[i - 1], 1L);
-						if (j > 0)
-							buf[i - 1] = (char)(j + 147);
-						break;
-
-					case 'B':
-						j = strposc("0.,+123-456*789/\0()^ABCDEFGHIJKLMNOPQRSTUVWXYZ",
-								toupper(buf[i - 1]), 1L);
-						if (j > 20)
-							buf[i - 1] = (char)(j + 147);
-						else if (j > 0)
-							buf[i - 1] = (char)(j + 127);
-						break;
-
-					case 'O':
-						j = strposc("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
-								toupper(buf[i - 1]), 1L);
-						if (j > 0)
-							buf[i - 1] = (char)(j + 213);
-						break;
-				}
-				i++;
-			}
-			switch (tx)
-			{
-
-				case -1:
-					m_drawstr(xx, yy - (ty + 1) * 3, NULL, buf);
-					break;
-
-				case 0:
-					m_centerstr(xx, yy - (ty + 1) * 3, NULL, buf);
-					break;
-
-				case 1:
-					m_rightstr(xx, yy - (ty + 1) * 3, NULL, buf);
-					break;
-			}
-			return;
-		}
-		switch (tx)
-		{
-
-			case -1:
-				m_drawstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
-				break;
-
-			case 0:
-				m_centerstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
-				break;
-
-			case 1:
-				m_rightstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
-				break;
-		}
-		return;
-	}
-	if (sc < log_scale0 * 40)
-		return;
-	if (sc >= log_scale0 * 50) {
-		if (!strsubset(v->UU.U116.sp, big1))
-			return;
-		buf[strlen(v->UU.U116.sp)] = '\0';
-		FORLIM = strlen(v->UU.U116.sp);
-		for (i = 0; i < FORLIM; i++) {
-			j = strposc(big1, v->UU.U116.sp[i], 1L);
-			if (j <= 20)
-				buf[i] = (char)(j + 127);
-			else if (j <= 46)
-				buf[i] = (char)(j + 147);
-			else if (j <= 72)
-				buf[i] = (char)(j + 121);
-			else
-				buf[i] = ' ';
-		}
-		tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
-			(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
-		ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
-			(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
-		switch (tx)
-		{
-
-			case -1:
-				m_drawstr(xx, yy - (ty + 2) * 2, NULL, buf);
-				break;
-
-			case 0:
-				m_centerstr(xx, yy - (ty + 2) * 2, NULL, buf);
-				break;
-
-			case 1:
-				m_rightstr(xx, yy - (ty + 2) * 2, NULL, buf);
-				break;
-		}
-		return;
-	}
-	if (!strsubset(v->UU.U116.sp, big2))
-		return;
-	buf[strlen(v->UU.U116.sp)] = '\0';
-	FORLIM = strlen(v->UU.U116.sp);
-	for (i = 0; i < FORLIM; i++)
-	{
-		j = strposc(big2, v->UU.U116.sp[i], 1L);
-		if (j <= 15)
-			buf[i] = (char)(j + 193);
-		else
-			buf[i] = ' ';
-	}
-	tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
-		(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
-	ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
-		(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
-	switch (tx)
-	{
-
-		case -1:
-			m_drawstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
-			break;
-
-		case 0:
-			m_centerstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
-			break;
-
-		case 1:
-			m_rightstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
-			break;
-	}
-}
-
-#undef big1
-#undef big2
-
-
-static void plaindrawgatec(short x, short y, short g, short c)
-{
-	short i, z, rxx, rxy, ryx, ryy;
-	log_krec *k;
-	int hascolor;
-	short FORLIM;
-	log_vectorrec *WITH1;
-
-	k = kind[(g & (log_kindoffset - 1)) - 1];
-	z = log_scale0 * k->bbmax + 2;
-	if (x < -z || x > across + z || y < -z || y > down + z)
-		return;
-	hidecursor();
-	hascolor = (c != gg.color.backgr && c != gg.color.conflict);
-	m_color((long)c);
-	if (g < log_kindoffset)
-	{
-		FORLIM = k->numvects;
-		for (i = 0; i < FORLIM; i++)
-		{
-			WITH1 = &k->vector[i];
-			switch (WITH1->vkind)
-			{
-
-				case '1':
-					if (hascolor)
-						m_color((long)c);
-					break;
-
-				case '2':
-					if (hascolor)
-						m_color((long)gategreen);
-					break;
-
-				case '3':
-					if (hascolor)
-						m_color((long)gateyellow);
-					break;
-
-				case '4':
-					if (hascolor)
-						m_color((long)gatered);
-					break;
-
-				case '5':
-					if (hascolor)
-						m_color((long)gateorange);
-					break;
-
-				case '6':
-					if (hascolor)
-						m_color((long)gateblack);
-					break;
-
-				case '7':
-					if (hascolor)
-						m_color((long)gatewhite);
-					break;
-
-				case 'v':
-				case 'C':
-				case 'e':
-				case 'E':
-				case 'r':
-					drawvector2(&k->vector[i], (long)(x + WITH1->x1),
-							(long)(y + WITH1->y1), (long)(x + WITH1->UU.U99.x2),
-							(long)(y + WITH1->UU.U99.y2));
-					break;
-
-				case 'c':
-				case 'F':
-					drawvector4(&k->vector[i], (long)(x + WITH1->x1),
-							(long)(y + WITH1->y1), (long)(x + WITH1->UU.U99.x2),
-							(long)(y + WITH1->UU.U99.y2), (long)(x + WITH1->UU.U99.x3),
-							(long)(y + WITH1->UU.U99.y3), (long)(x + WITH1->UU.U99.x4),
-							(long)(y + WITH1->UU.U99.y4));
-					break;
-
-				case 't':
-					drawtext(&k->vector[i], (long)log_scale0, 0L, (long)(x + WITH1->x1),
-							(long)(y + WITH1->y1));
-					break;
-			}
-		}
-	}
-	else
-	{
-		z = g / log_kindoffset;
-		rxx = log_rotxx[z];
-		rxy = log_rotxy[z];
-		ryx = log_rotyx[z];
-		ryy = log_rotyy[z];
-		FORLIM = k->numvects;
-		for (i = 0; i < FORLIM; i++)
-		{
-			WITH1 = &k->vector[i];
-			switch (WITH1->vkind)
-			{
-
-				case '1':
-					if (hascolor)
-						m_color((long)c);
-					break;
-
-				case '2':
-					if (hascolor)
-						m_color((long)gategreen);
-					break;
-
-				case '3':
-					if (hascolor)
-						m_color((long)gateyellow);
-					break;
-
-				case '4':
-					if (hascolor)
-						m_color((long)gatered);
-					break;
-
-				case '5':
-					if (hascolor)
-						m_color((long)gateorange);
-					break;
-
-				case '6':
-					if (hascolor)
-						m_color((long)gateblack);
-					break;
-
-				case '7':
-					if (hascolor)
-						m_color((long)gatewhite);
-					break;
-
-				case 'v':
-				case 'C':
-				case 'e':
-				case 'E':
-				case 'r':
-					drawvector2(&k->vector[i],
-							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
-							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy),
-							(long)(x + WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx),
-							(long)(y + WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy));
-					break;
-
-				case 'c':
-				case 'F':
-					drawvector4(&k->vector[i],
-							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
-							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy),
-							(long)(x + WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx),
-							(long)(y + WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy),
-							(long)(x + WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx),
-							(long)(y + WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy),
-							(long)(x + WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx),
-							(long)(y + WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy));
-					break;
-
-				case 't':
-					drawtext(&k->vector[i], (long)log_scale0, (long)z,
-							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
-							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy));
-					break;
-			}
-		}
-	}
-	hidecursor();
-}
-
-
-static void udrawgatec(short x, short y, short g, short c)
-{
-	short i, z, rxx, rxy, ryx, ryy;
-	log_krec *k;
-	int hascolor;
-	short FORLIM;
-	log_vectorrec *WITH1;
-
-	if (g == 0)
-	{
-		hidecursor();
-		m_color((long)c);
-		m_drawpoint((long)x, (long)y);
-		hidecursor();
-		return;
-	}
-	k = kind[(g & (log_kindoffset - 1)) - 1];
-	if (k->bbmax <= maxsafescale)
-	{
-		plaindrawgatec(x, y, g, c);
-		return;
-	}
-	hascolor = (c != gg.color.backgr);
-	z = log_scale0 * k->bbmax + 2;
-	if (x < -z || x > across + z || y < -z || y > down + z)
-		return;
-	z = g / log_kindoffset;
-	rxx = log_rotxx[z] * maxsafescale;
-	rxy = log_rotxy[z] * maxsafescale;
-	ryx = log_rotyx[z] * maxsafescale;
-	ryy = log_rotyy[z] * maxsafescale;
-	hidecursor();
-	m_color((long)c);
-	FORLIM = k->numvects;
-	for (i = 0; i < FORLIM; i++)
-	{
-		WITH1 = &k->vector[i];
-		switch (WITH1->vkind)
-		{
-
-			case '1':
-				if (hascolor)
-					m_color((long)c);
-				break;
-
-			case '2':
-				if (hascolor)
-					m_color((long)gategreen);
-				break;
-
-			case '3':
-				if (hascolor)
-					m_color((long)gateyellow);
-				break;
-
-			case '4':
-				if (hascolor)
-					m_color((long)gatered);
-				break;
-
-			case '5':
-				if (hascolor)
-					m_color((long)gateorange);
-				break;
-
-			case '6':
-				if (hascolor)
-					m_color((long)gateblack);
-				break;
-
-			case '7':
-				if (hascolor)
-					m_color((long)gatewhite);
-				break;
-
-			case 'v':
-			case 'C':
-			case 'e':
-			case 'E':
-			case 'r':
-				drawvector2(&k->vector[i],
-						(long)(x + (WITH1->x1 * rxx + WITH1->y1 * ryx) / k->bbmax),
-						(long)(y + (WITH1->x1 * rxy + WITH1->y1 * ryy) / k->bbmax),
-						(long)(x + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / k->bbmax),
-						(long)(y + (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / k->bbmax));
-				break;
-
-			case 'c':
-			case 'F':
-				drawvector4(&k->vector[i], (long)(x + (WITH1->x1 * rxx +
-								WITH1->y1 * ryx) / k->bbmax), (long)
-						(y + (WITH1->x1 * rxy + WITH1->y1 * ryy) / k->bbmax), (long)
-						(x + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / k->bbmax),
-						(long)
-						(y + (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / k->bbmax),
-						(long)
-						(x + (WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx) / k->bbmax),
-						(long)
-						(y + (WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy) / k->bbmax),
-						(long)
-						(x + (WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx) / k->bbmax),
-						(long)
-						(y + (WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy) / k->bbmax));
-				break;
-		}
-	}
-	hidecursor();
-}
-
-
-/*=================  DRAWGATEC  ==================*/
-/*=                                              =*/
-/*=  Draw a gate of specified color at a         =*/
-/*=     certain position (grid coordinates).     =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawgatedotsc(short x, short y, short g, short c)
-{
-	short i, z, rxx, rxy, ryx, ryy;
-	log_krec *WITH;
-	short FORLIM;
-
-	if (g == 0 || vlsi)
-		return;
-	m_color((long)c);
-	z = g / log_kindoffset;
-	if (z != 0)
-	{
-		rxx = log_rotxx[z];
-		rxy = log_rotxy[z];
-		ryx = log_rotyx[z];
-		ryy = log_rotyy[z];
-		WITH = kind[(g & (log_kindoffset - 1)) - 1];
-		FORLIM = WITH->numpins;
-		for (i = 0; i < FORLIM; i++)
-			point(x + WITH->pin[i].x * rxx + WITH->pin[i].y * ryx,
-					y + WITH->pin[i].x * rxy + WITH->pin[i].y * ryy);
-		return;
-	}
-	WITH = kind[(g & (log_kindoffset - 1)) - 1];
-	FORLIM = WITH->numpins;
-	for (i = 0; i < FORLIM; i++)
-		point(x + WITH->pin[i].x, y + WITH->pin[i].y);
-}
-
-
-static void drawgatec(short x, short y, short g, short c)
-{
-	short i, xx, yy, z, rxx, rxy, ryx, ryy;
-	long savecol;
-	int hascolor;
-	log_krec *WITH;
-	short FORLIM;
-	log_vectorrec *WITH1;
-
-	if (zoom == 0)
-	{
-		plaindrawgatec((int)(x * gg.scale - gg.xoff),
-				(int)(y * gg.scale - gg.yoff), g, c);
-	}
-	else
-	{
-		z = g / log_kindoffset;
-		rxx = log_rotxx[z] * gg.scale;
-		rxy = log_rotxy[z] * gg.scale;
-		ryx = log_rotyx[z] * gg.scale;
-		ryy = log_rotyy[z] * gg.scale;
-		xx = x * gg.scale - gg.xoff;
-		yy = y * gg.scale - gg.yoff;
-		hidecursor();
-		m_color((long)c);
-		hascolor = (c != gg.color.backgr && c != gg.color.conflict);
-		WITH = kind[(g & (log_kindoffset - 1)) - 1];
-		FORLIM = WITH->numvects;
-		for (i = 0; i < FORLIM; i++)
-		{
-			WITH1 = &WITH->vector[i];
-			switch (WITH1->vkind)
-			{
-
-				case '1':
-					if (hascolor)
-						m_color((long)c);
-					break;
-
-				case '2':
-					if (hascolor)
-						m_color((long)gategreen);
-					break;
-
-				case '3':
-					if (hascolor)
-						m_color((long)gateyellow);
-					break;
-
-				case '4':
-					if (hascolor)
-						m_color((long)gatered);
-					break;
-
-				case '5':
-					if (hascolor)
-						m_color((long)gateorange);
-					break;
-
-				case '6':
-					if (hascolor)
-						m_color((long)gateblack);
-					break;
-
-				case '7':
-					if (hascolor)
-						m_color((long)gatewhite);
-					break;
-
-				case 'v':
-				case 'r':
-					drawvector2(
-							&WITH->vector[i],
-							(long)(xx + (WITH1->x1 * rxx + WITH1->y1 * ryx) / log_scale0),
-							(long)(yy + (WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0),
-							(long)
-							(xx + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / log_scale0),
-							(long)
-							(yy +
-							 (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / log_scale0));
-					break;
-
-				case 'C':
-					m_circle(xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx + (WITH1->y1 +
-									WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
-							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy + (WITH1->y1 + WITH1->
-									UU.U99.y2) * ryy) / (log_scale0 * 2L),
-							P_imax2((long)abs((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
-									(WITH1->y1 - WITH1->UU.U99.y2) * ryx),
-								(long)abs((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
-									(WITH1->y1 - WITH1->UU.U99.y2) * ryy)) /
-							(log_scale0 * 2));
-					break;
-
-				case 'e':
-					savecol = m_curcolor();
-					m_color(m_trans);
-					m_ellipse(
-							xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx +
-								(WITH1->y1 + WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
-							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy +
-								(WITH1->y1 + WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
-							((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
-							 (WITH1->y1 - WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
-							((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
-							 (WITH1->y1 - WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
-							savecol);
-					m_color(savecol);
-					break;
-
-				case 'E':
-					m_ellipse(
-							xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx +
-								(WITH1->y1 + WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
-							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy +
-								(WITH1->y1 + WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
-							((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
-							 (WITH1->y1 - WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
-							((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
-							 (WITH1->y1 - WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
-							m_curcolor());
-					break;
-
-				case 'c':
-				case 'F':
-					drawvector4(&WITH->vector[i], (long)(xx + (WITH1->x1 * rxx +
-									WITH1->y1 * ryx) / log_scale0), (long)(yy +
-									(WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0), (long)(xx +
-										(WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / log_scale0),
-							(long)(yy +
-								(WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / log_scale0),
-							(long)(xx +
-								(WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx) / log_scale0),
-							(long)(yy +
-								(WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy) / log_scale0),
-							(long)(xx +
-								(WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx) / log_scale0),
-							(long)(yy + (WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy) /
-								log_scale0));
-					break;
-
-				case 't':
-					drawtext(&WITH->vector[i], (long)gg.scale, (long)z,
-							(long)(xx + (WITH1->x1 * rxx + WITH1->y1 * ryx) / log_scale0),
-							(long)(yy + (WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0));
-					break;
-			}
-		}
-		hidecursor();
-	}
-	if ((c == gg.color.gate || c == gg.color.dimgate) && !suppressdots)
-		drawgatedotsc(x, y, g, gg.color.gatepin);
-}
-
-
-static void signallabel(short x, short y, short gtype, short sig, short c)
-{
-	log_krec *k;
-	char STR1[256];
-
-	k = kind[(gtype & (log_kindoffset - 1)) - 1];
-	if (!(sig != 0 && k->flag.U3.named))
-		return;
-	remcursor();
-	m_color((long)c);
-	if (k->flag.U3.nright != (gtype / log_kindoffset == 0))
-		drawstr2((int)(x - m_strwidth(NULL,
-						strrtrim(strcpy(STR1, gg.signaltab[sig - 1].name))) + NAMEGAP),
-				y - 3, gg.signaltab[sig - 1].name);
-	else
-		drawstr2(x - NAMEGAP, y - 3, gg.signaltab[sig - 1].name);
-}
-
-
-static void gsignallabel(short x, short y, log_grec *g, short c)
-{
-	signallabel((int)(x * gg.scale - gg.xoff), (int)(y * gg.scale - gg.yoff),
-			g->g, g->sig, c);
-}
-
-
-typedef enum {inside,north,east,south,west} placement;
-
-static void drawpnums(log_grec *g, short c)
-{
-	short rxx, rxy, ryx, ryy, i, j, k;
-	char s[7];
-	log_krec *WITH;
-	short FORLIM, FORLIM1;
-	int tx,ty,ex,ey;
-	int minx,miny,maxx,maxy;
-	placement p = inside;
-	long hw;
-
-	if (zoom <= 0 || gg.textinvisible || gg.pnuminvisible)
-		return;
-	m_color((long)c);
-	rxx = log_rotxx[g->rot];
-	rxy = log_rotxy[g->rot];
-	ryx = log_rotyx[g->rot];
-	ryy = log_rotyy[g->rot];
-	WITH = g->kind;
-
-	/* use grab rectangle to determine which edge this pin is attached to. */
-	minx = ( WITH->x1 * rxx + WITH->y1 * ryx);
-	miny = ( WITH->x1 * rxy + WITH->y1 * ryy);
-	maxx = ( WITH->x2 * rxx + WITH->y2 * ryx);
-	maxy = ( WITH->x2 * rxy + WITH->y2 * ryy);
-
-	FORLIM = WITH->numpnums;
-	for (i = 0; i < FORLIM; i++)
-	{
-		sprintf(s, "%d", WITH->pnum[i].num);
-		hw = strlen(s) * 5 / 2;
-		ex = (WITH->pnum[i].x * rxx + WITH->pnum[i].y * ryx);
-		ey = (WITH->pnum[i].x * rxy + WITH->pnum[i].y * ryy);
-		if (ex < minx)
-		{
-			p = west;
-		}
-		else if (ex > maxx)
-		{
-			p = east;
-		}
-		else if (ey < miny)
-		{
-			p = north;
-		}
-		else if (ey > maxy)
-		{
-			p = south;
-		}
-		tx = g->x * gg.scale + ex * gg.scale / log_scale0 - gg.xoff;
-		ty = g->y * gg.scale + ey * gg.scale / log_scale0 - gg.yoff;
-		switch (p)
-		{
-			case west:
-				tx -= 5;
-				break;
-			case east:
-				tx += 5;
-				break;
-			case north:
-				tx -= hw;
-				ty -= 9;
-				break;
-			case south:
-				tx -= hw;
-				ty += 5;
-				break;
-
-			default:
-				break;
-		}
-
-		if (p == west)
-			m_rightstr(tx,ty,NULL,s);
-		else
-			m_drawstr(tx,ty,NULL,s);
-	}
-}
-
-#undef fromtab
-#undef totab
-
-
-static void setscale (short s);
-
-
-static void kdrawgatec(short i, short c)
-{
-	short x, y;
-	short ozoom = zoom;
-
-	x = (i - 1) * kindgroupspacing + kindgroupstart;
-	y = (down + baseline) / 2;
-	udrawgatec(x, y, kindgroup[i - 1], c);
-	setscale(0);
-	if (kindgroup[i - 1] != 0)
-		signallabel(x, y, kindgroup[i - 1], kindsig[i - 1], c);
-	setscale(ozoom);
-}
-
-
-/*=================  DRAWGATEX  ==================*/
-/*=                                              =*/
-/*=  Draw a gate.  If it is a TO or FROM gate,   =*/
-/*=     draw its name as well.                   =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawgatexc(log_grec *g, short c)
-{
-	if (g->dimcolor && c == gg.color.gate)
-		c = gg.color.dimgate;
-	drawgatec(g->x, g->y, g->g, c);
-	if (!gg.textinvisible)
-		gsignallabel(g->x, g->y, g, gg.color.signal);
-	if (g->kind->numpnums > 0)
-		drawpnums(g, gg.color.pinnum);
-}
-
-
-static void drawgatex(log_grec *g)
-{
-	drawgatexc(g, gg.color.gate);
-}
-
-
-static void setdimgate(log_grec *g, int dim)
-{
-	log_grec *g1;
-
-	if (g->dimcolor == dim)
-		return;
-	g->dimcolor = dim;
-	if (gg.showpage <= 0)
-		return;
-	g1 = gg.gbase[gg.showpage - 1];
-	while (g1 != NULL && g1 != g)
-		g1 = g1->next;
-	if (g1 != g)
-		return;
-	m_saveclip();
-	clipon();
-	drawgatex(g);
-	m_unclip();
-}
-
-
-#define rtn             "ERAGATE"
-
-
-/*==================  ERAGATE  ===================*/
-/*=                                              =*/
-/*=  Erase a gate (including LED's and other     =*/
-/*=     "magic" stuff) using grid coordinates.   =*/
-/*=                                              =*/
-/*================================================*/
-
-static void eragate(log_grec *g)
-{
-	log_grec *g1, *g2;
+					rabstate = 0;
+				} else
+					rabstate = i;
+			} else
+				rabstate = 0;
+		}
+	}
+	else
+	{
+		rabstate = 0;
+	}
 
-	if (g->conflict || g->oconflict)
+	if (gg.probemode)
 	{
-		g1 = gateconflictbase;
-		g2 = NULL;
-		while (g1 != NULL && g1 != g)
+		if (cursx != gg.t.x || cursy != gg.t.y)
 		{
-			g2 = g1;
-			g1 = g1->confnext;
+			if (gg.probesimtype != NULL)
+				checkprobe((int)gg.t.x, (int)gg.t.y);
+			probeflag = false;
+			drawcursor((int)gg.t.x, (int)gg.t.y);
 		}
-		
-		if (g1 == NULL)
-			report(10, rtn);
-		else if (g2 == NULL)
-			gateconflictbase = g->confnext;
 		else
-			g2->confnext = g->confnext;
-		g->conflict = false;
-		g->conflict1 = false;
-		g->conflict2 = false;
-		g->oconflict = false;
-	}
-	drawgatec(g->x, g->y, g->g, gg.color.backgr);
-	gsignallabel(g->x, g->y, g, gg.color.backgr);
-	if (g->kind->numpnums > 0)
-		drawpnums(g, gg.color.backgr);
-	drawgatedotsc(g->x, g->y, g->g, gg.color.backgr);
-	calltoolgate(g, act_erasegate);
-}
-
-#undef rtn
-
-
-/*================  DRAWSOLDERC  =================*/
-/*=                                              =*/
-/*=  Draw a solder point at a certain position   =*/
-/*=     (grid coordinates).                      =*/
-/*=                                              =*/
-/*================================================*/
+		{
+			if (!cursorflag)
+				drawcursor((int)gg.t.x, (int)gg.t.y);
+			if (!probeflag)
+			{
+				testprobe((int)gg.t.x, (int)gg.t.y);
+				probeflag = true;
+			}
+		}
 
-static void drawsolderc(short x, short y, short c)
-{
-	if (!showsolder)
-		return;
-	if (vlsi)
+		if (!gg.t.near_ && briefprobe)
+		{
+			remcursor();
+			gg.probemode = false;
+		}
+	}
+	else
 	{
-		if (c == gg.color.conflict || c == gg.color.backgr)
-			m_color((long)c);
+		briefprobe = false;
+		if (gg.probesimtype != NULL)
+			unprobe();
+		if (gg.t.near_)
+			drawcursor((int)gg.t.x, (int)gg.t.y);
 		else
-			m_color((long)gg.color.vlsicut);
-		x = x * gg.scale - gg.xoff;
-		y = y * gg.scale - gg.yoff;
-		m_drawline(x - 3L, y - 3L, x + 3L, y + 3L);
-		m_drawline(x - 3L, y + 3L, x + 3L, y - 3L);
-		m_drawline(x - 2L, y - 3L, x + 4L, y + 3L);
-		m_drawline(x - 2L, y + 3L, x + 4L, y - 3L);
-		return;
+			remcursor();
+	}
+	cred = gg.color.conflict;
+	if (anyconflicts && (cred == log_cred || cred == log_cred8) &&
+			(rcolormap[cred] == 255 || gcolormap[cred] == 255 ||
+			 bcolormap[cred] == 255))
+	{
+		x = timers_sysclock() * 6 % 137 + 119;
+		rval = (char)(x * rcolormap[cred] / 255);
+		gval = (char)(x * gcolormap[cred] / 255);
+		bval = (char)(x * bcolormap[cred] / 255);
+		m_vsetcolors((long)cred, 1L, (unsigned char *) &rval,
+				(unsigned char *) &gval, (unsigned char *) &bval);
 	}
-	m_color((long)c);
-	x = x * gg.scale - gg.xoff;
-	y = y * gg.scale - gg.yoff;
-	m_drawline(x - 1L, y - 2L, x + 1L, y - 2L);
-	m_drawline(x - 2L, y - 1L, x + 2L, y - 1L);
-	m_drawline(x - 2L, (long)y, x + 2L, (long)y);
-	m_drawline(x - 2L, y + 1L, x + 2L, y + 1L);
-	m_drawline(x - 1L, y + 2L, x + 1L, y + 2L);
-}
-
-
-/*=================  DRAWTRANSC  =================*/
-/*=                                              =*/
-/*=  Draw a VLSI transistor at a certain         =*/
-/*=     position (grid coordinates).             =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawtransc(short x, short y, short c)
-{
-	if (!vlsi)
-		return;
-	if (c == gg.color.solder)
-		m_color((long)gg.color.vlsicut);
-	else
-		m_color((long)c);
-	x = x * gg.scale - gg.xoff;
-	y = y * gg.scale - gg.yoff;
-	m_circle((long)x, (long)y, 4L);
-}
-
-
-/*==================  ERALABEL  ==================*/
-/*=                                              =*/
-/*=  Erase a text label from the screen.         =*/
-/*=                                              =*/
-/*================================================*/
-
-static void eralabel(log_lrec *l)
-{
-	m_color((long)gg.color.backgr);
-	m_drawstr(l->x * gg.scale - gg.xoff, l->y * gg.scale - gg.yoff + 2,
-			logfont_lfont, l->name);
-}
-
-
-/*==================  XORLABEL  ==================*/
-/*=                                              =*/
-/*=  XOR a text label onto the screen.           =*/
-/*=                                              =*/
-/*================================================*/
 
-static void xorlabel(short x, short y, log_lrec *l)
-{
-	m_colormode((long)m_xor);
-	m_color((long)gg.color.labeltext);
-	m_drawstr(x * gg.scale - gg.xoff, y * gg.scale - gg.yoff + 2, logfont_lfont,
-			l->name);
-	m_colormode((long)m_normal);
+	if (gg.t.moving)
+	{
+		gg.fastspeed = gg.fastmin;
+		fastsavetime = timers_sysclock();
+	}
+	else if (gg.fastspeed < gg.fastmax &&
+			timers_sysclock() > fastsavetime + gg.fastrate)
+	{
+		gg.fastspeed++;
+		fastsavetime = timers_sysclock();
+	}
+	gg.gridx = (gg.t.x + gg.hscale + gg.xoff) / gg.scale;
+	gg.gridy = (gg.t.y + gg.hscale + gg.yoff) / gg.scale;
 }
 
 
-/*==================  DRAWBOXC  ==================*/
+/*=================  JUSTTAP  ====================*/
 /*=                                              =*/
-/*=  Draw a dashed box on the screen.            =*/
+/*=  Return TRUE if pen was tapped.  Return      =*/
+/*=     FALSE if pen was held and/or moved.      =*/
 /*=                                              =*/
 /*================================================*/
 
-static void drawboxc0(short x1, short y1, short x2, short y2, short c)
+static int justtap()
 {
-	m_color((long)c);
-	m_linestyle(1L);
-	rect(x1, y1, x2, y2);
-	m_linestyle(0L);
-}
-
+	long t0;
+	short tx, ty;
 
-static void drawboxc(log_brec *b, short  c)
-{
-	drawboxc0(b->x1, b->y1, b->x2, b->y2, c);
+	t0 = timers_sysclock() + tapdelay;
+	tx = gg.t.x;
+	ty = gg.t.y;
+	do
+	{
+		pen();
+	} while (gg.t.depressed && labs(gg.t.x - tx) <= taptolerance &&
+			labs(gg.t.y - ty) <= taptolerance && timers_sysclock() <= t0);
+	return (!gg.t.depressed);
 }
 
 
-/*================  DRAWMARKERSC  ================*/
+/*==================  TESTKEY2  ==================*/
 /*=                                              =*/
-/*=  Draw the printing markers on the screen.    =*/
+/*=  Return the most recently pressed key.       =*/
 /*=                                              =*/
 /*================================================*/
 
-static void drawmarkersc(short c)
+static char testkey2()
 {
-	clipon();
-	m_color((long)c);
-	hline(gg.markerx1, gg.markerx1 + 2, gg.markery1);
-	vline(gg.markerx1, gg.markery1, gg.markery1 + 2);
-	hline(gg.markerx2 - 2, gg.markerx2, gg.markery2);
-	vline(gg.markerx2, gg.markery2 - 2, gg.markery2);
-	clipoff();
+	if (pushedbackkey != '\0')
+		return pushedbackkey;
+	else if (pollkbd2())
+		return (nk_testkey(0));
+	else
+		return ' ';
 }
 
 
-/*=================  DRAWNODEC  ==================*/
+/*==================  INKEY2  ====================*/
 /*=                                              =*/
-/*=  Draw all wires and solder points in a       =*/
-/*=     particular node, in color C.             =*/
+/*=  Return a keystroke.  Key is removed from    =*/
+/*=     the buffer.                              =*/
 /*=                                              =*/
 /*================================================*/
 
-static void drawnodec(log_nrec *n, short c)
+static char inkey2()
 {
-	log_hwrec *hw;
-	log_vwrec *vw;
-	log_srec *s;
-
-	if (gg.invisible || (gg.showconflicts == true && n->conflict == false))
-		return;
+	char ch;
 
-	hidecursor();
-	if ((unsigned)c > 15)
+	do
 	{
-		if (gg.glowmode && gg.showpage > 0)
-			c = glowcol(n, (long)gg.color.wire[0]);
-		else
-			c = gg.color.wire[0];
-	}
-	if (vlsi && c == gg.color.wire[0])
+	} while (!pollkbd2());
+	if (pushedbackkey != '\0')
 	{
-		hw = gg.hwbase[gg.curpage - 1];
-		while (hw != NULL)
-		{
-			if (hw->node == n && hw != gg.movinghw)
-			{
-				m_color((long)gg.color.wire[hw->wcolr - log_wcol_normal]);
-				hline(hw->x1, hw->x2, hw->y);
-			}
-			hw = hw->next;
-		}
-		vw = gg.vwbase[gg.curpage - 1];
-		while (vw != NULL)
-		{
-			if (vw->node == n && vw != gg.movingvw)
-			{
-				m_color((long)gg.color.wire[vw->wcolr - log_wcol_normal]);
-				vline(vw->x, vw->y1, vw->y2);
-			}
-			vw = vw->next;
-		}
+		realkey = pushedbackkey;
+		pushedbackkey = '\0';
 	}
 	else
 	{
-		m_color((long)c);
-		hw = gg.hwbase[gg.curpage - 1];
-		while (hw != NULL) {
-			if (hw->node == n && hw != gg.movinghw)
-				hline(hw->x1, hw->x2, hw->y);
-			hw = hw->next;
-		}
-		vw = gg.vwbase[gg.curpage - 1];
-		while (vw != NULL)
-		{
-			if (vw->node == n && vw != gg.movingvw)
-				vline(vw->x, vw->y1, vw->y2);
-			vw = vw->next;
-		}
+		realkey = nk_getkey();
 	}
-	if (showsolder)
+	ch = realkey;
+	if ((ch & 255) >= 168 && (ch & 255) <= 239 && nk_capslock)
 	{
-		s = gg.sbase[gg.curpage - 1];
-		while (s != NULL)
+		if ((ch & 255) <= 193)
 		{
-			if ((s->hwire != NULL && s->hwire->node == n) ||
-					(s->vwire != NULL && s->vwire->node == n))
-				drawsolderc(s->x, s->y, c);
-			s = s->next;
+			ch += 46;
+		} else if ((ch & 255) >= 214)
+		{
+			ch -= 46;
 		}
 	}
-	hidecursor();
-}
-
-
-/*=================  DRAWNODE  ===================*/
-/*=                                              =*/
-/*=  Draw all wires and solder points in a       =*/
-/*=     particular node.                         =*/
-/*=                                              =*/
-/*================================================*/
-
-static void drawnode(log_nrec *n)
-{
-	drawnodec(n, -1);
-}
-
-
-/*================  REFRPAGEDISP  ================*/
-/*=                                              =*/
-/*=  Refresh the page-number display.            =*/
-/*=                                              =*/
-/*================================================*/
-
-static int pageempty (int pg);
-
-
-static void refrpagedisp()
-{
-	short num;
-
-	m_color((long)gg.color.page1);
-	drawstr2(across - 49, 2, "PAGE");
-	m_color((long)gg.color.page2);
-	drawnum2(across - 14, 2, (int)gg.curpage);
-	m_color((long)gg.color.page3);
-	drawstr2(across - 35, 14, "OF");
-	m_color((long)gg.color.page4);
-	num = gg.numpages;
-	while (num > gg.curpage && pageempty(num))
-		num--;
-	drawnum2(across - 14, 14, num);
+	gg.fastspeed = gg.fastmin;
+	return ch;
 }
 
 
-/*================  REFREDITMODE  ================*/
-/*=                                              =*/
-/*=  Refresh the editing mode in the menus.      =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refreditmode()
+static void inkey3(char *ch)
 {
-	hidecursor();
-	m_color((long)gg.color.backgr);
-	m_fillrect(across + menux4 - 1L, line2 - 2L, across + menux4 + 30L,
-			line2 + 9L);
-	switch (cureditmode)
-	{
-
-		case 1:
-			m_color((long)gg.color.menuword);
-			drawstr2(across + menux4, line2, "ROT");
-			break;
-
-		case 2:
-			m_color((long)gg.color.menuword);
-			drawstr2(across + menux4, line2, "MIR-");
-			break;
-
-		case 3:
-			m_color((long)gg.color.menuword);
-			drawstr2(across + menux4, line2, "MIR|");
-			break;
-
-		case 4:
-			m_color((long)gg.color.selword);
-			drawstr2(across + menux4, line2, "CNFG");
-			break;
-	}
-	hidecursor();
+	*ch = inkey2();
 }
 
 
-/*===============  REFRBASELINE  =================*/
-/*=                                              =*/
-/*=  Refresh the baseline to the correct color.  =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refrbaseline(int always)
+static char inkey4()
 {
-	short c;
+	/* undo CAPSLOCK key */
+	char ch;
 
-	if (anyconflicts)
-		c = gg.color.conflict;
-	else
-		c = gg.baselinecolor;
-	if (!(c != gg.color.curbaseline || always))
-		return;
-	clipoff();
-	gg.color.curbaseline = c;
-	hidecursor();
-	m_color((long)c);
-	m_fillrect(0L, (long)baseline, (long)kindgroupleft, baseline + 1L);
-	m_fillrect((long)kindgroupright, (long)baseline, (long)across,
-			baseline + 1L);
-	hidecursor();
+	ch = inkey2();
+	if (!nk_capslock)
+		return ch;
+	if (isupper(ch))
+		ch += 32;
+	else if (islower(ch))
+		ch -= 32;
+	return ch;
 }
 
 
-#define rtn             "REFRESH"
+static void ungetkey2(char ch)
+{
+	pushedbackkey = ch;
+}
 
 
-/*===================  REFRESH  ==================*/
+/*===============  WAITFORKEY  ===================*/
 /*=                                              =*/
-/*=  Refresh the screen (does not clear, so may  =*/
-/*=     be used to "clean up" existing screen).  =*/
+/*=  Wait until a key is pressed (but ignore it) =*/
 /*=                                              =*/
 /*================================================*/
 
-static void refresh()
+static void waitforkey()
 {
-	long x1, y1, x2, y2;
-	log_grec *g;
-	log_hwrec *hw;
-	log_vwrec *vw;
-	log_nrec *n;
-	log_srec *s;
-	log_lrec *l;
-	log_brec *b;
-
-	stamp(&gg.refrstamp);
-	gg.showpage = gg.curpage;
-	showsolder = (zoom > -1 && (vlsi || !gg.glowmode || glowsolder));
-	x1 = (gg.xoff - 30) / gg.scale;
-	y1 = (gg.yoff - 30) / gg.scale;
-	x2 = (gg.xoff + across + 30) / gg.scale;
-	y2 = (gg.yoff + down + 30) / gg.scale;
-	refrtimer = -1;
-	remcursor();
-	clipon();
-	refrpagedisp();
-	if (!gg.invisible && !gg.showconflicts)
-	{
-		working();
-		suppressdots = gg.dotsvisible;
-		g = gg.gbase[gg.curpage - 1];
-		while (g != NULL)
-		{
-			if (P_ibetweenm(x1, (long)g->x, x2, (long)g->kind->bbmax) &&
-					P_ibetweenm(y1, (long)g->y, y2, (long)g->kind->bbmax))
-				drawgatex(g);
-			g = g->next;
-		}
-		suppressdots = false;
-		working();
-		if (gg.glowmode)
-		{
-			hw = gg.hwbase[gg.curpage - 1];
-			while (hw != NULL)
-			{
-				if (hw->y > y1 && hw->y < y2 && hw != gg.movinghw)
-				{
-					m_color(glowcol(hw->node,
-								(long)gg.color.wire[hw->wcolr - log_wcol_normal]));
-					hline(hw->x1, hw->x2, hw->y);
-				}
-				hw = hw->next;
-			}
-			working();
-			vw = gg.vwbase[gg.curpage - 1];
-			while (vw != NULL)
-			{
-				if (vw->x > x1 && vw->x < x2 && vw != gg.movingvw)
-				{
-					m_color(glowcol(vw->node,
-								(long)gg.color.wire[vw->wcolr - log_wcol_normal]));
-					vline(vw->x, vw->y1, vw->y2);
-				}
-				vw = vw->next;
-			}
-			working();
-			if (showsolder)
-			{
-				s = gg.sbase[gg.curpage - 1];
-				while (s != NULL)
-				{
-					if (s->hwire != NULL)
-						n = s->hwire->node;
-					else
-						n = s->vwire->node;
-					drawsolderc(s->x, s->y, (int)glowcol(n, (long)gg.color.solder));
-					s = s->next;
-				}
-			}
-		}
-		else
-		{
-			m_color((long)gg.color.wire[0]);
-			hw = gg.hwbase[gg.curpage - 1];
-			while (hw != NULL)
-			{
-				if (hw->y > y1 && hw->y < y2 && hw != gg.movinghw)
-				{
-					if (vlsi)
-						m_color((long)gg.color.wire[hw->wcolr - log_wcol_normal]);
-					hline(hw->x1, hw->x2, hw->y);
-				}
-				hw = hw->next;
-			}
-			working();
-			vw = gg.vwbase[gg.curpage - 1];
-			while (vw != NULL)
-			{
-				if (vw->x > x1 && vw->x < x2 && vw != gg.movingvw)
-				{
-					if (vlsi)
-						m_color((long)gg.color.wire[vw->wcolr - log_wcol_normal]);
-					vline(vw->x, vw->y1, vw->y2);
-				}
-				vw = vw->next;
-			}
-			working();
-			if (showsolder)
-			{
-				s = gg.sbase[gg.curpage - 1];
-				while (s != NULL)
-				{
-					if (s->hwire != NULL)
-						n = s->hwire->node;
-					else
-						n = s->vwire->node;
-					drawsolderc(s->x, s->y, gg.color.solder);
-					s = s->next;
-				}
-			}
-		}
+	char ch;
 
-		if (gg.dotsvisible)
-		{
-			g = gg.gbase[gg.curpage - 1];
-			while (g != NULL)
-			{
-				if (g->x > x1 && g->x < x2 && g->y > y1 && g->y < y2)
-					drawgatedotsc(g->x, g->y, g->g, gg.color.gatepin);
-				g = g->next;
-			}
-		}
-	}
-	else
-	{
-		working();
-		g = gg.gbase[gg.curpage - 1];
-		while (g != NULL)
-		{
-			if (g->kind->flag.U3.visible)
-				drawgatex(g);
-			g = g->next;
-		}
-	}
-	working();
-	if (!gg.textinvisible)
+	while (pollkbd2())
+		ch = inkey2();
+	do
 	{
-		b = gg.bbase[gg.curpage - 1];
-		while (b != NULL)
-		{
-			drawboxc(b, gg.color.dashbox);
-			b = b->next;
-		}
-		working();
-		l = gg.lbase[gg.curpage - 1];
-		m_color((long)gg.color.labeltext);
-		while (l != NULL)
-		{
-			if (l->y > y1 && l->y < y2)
-			{
-				m_drawstr(l->x * gg.scale - gg.xoff, l->y * gg.scale - gg.yoff + 2,
-						logfont_lfont, l->name);
-			}
-			l = l->next;
-		}
-	}
-	working();
-	if (gg.markers)
-		drawmarkersc(gg.color.marker);
-	if (memavail() < memtolerance)
-		message("Low on memory!");
-	clipoff();
-	restorecursor();
+		pen();
+	} while (!(pollkbd2() || (gg.t.dn && gg.t.off)));
+	if (pollkbd2())
+		ch = inkey2();
 }
 
-#undef rtn
-
 
-/*=================  REFRESHSOON  ================*/
+/*===================  INBOX  ====================*/
 /*=                                              =*/
-/*=  Screen is messed up, so refresh it as soon  =*/
-/*=     as the user stops moving around.         =*/
+/*=  Return TRUE if cursor is inside a certain   =*/
+/*=     rectangular area (screen coordinates).   =*/
 /*=                                              =*/
 /*================================================*/
 
-static void refreshsoon()
+static int inbox(short x, short y, short x1, short y1)
 {
-	refrtimer0 = refrdelay;
-	refrtimer = refrdelay;
-	gg.refrflag = true;
+	return (gg.t.x >= x && gg.t.y >= y && gg.t.x <= x + x1 && gg.t.y <= y + y1);
 }
 
 
@@ -4683,79 +1793,6 @@ static void closedumpfiles()
 }
 
 
-/*==================  REFRMENU  ==================*/
-/*=                                              =*/
-/*=  Clear and redraw menu area of screen.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refrmenu()
-{
-	short i, FORLIM;
-
-	working();
-	remcursor();
-	uerase(0, baseline + 2, across, down);
-	clipoff();
-	refrbaseline(true);
-	m_color((long)gg.color.backgr);
-	m_fillrect(kindgroupleft + 1L, (long)baseline, kindgroupright - 1L,
-			baseline + 1L);
-	m_color((long)gg.color.menuword);
-	drawstr2(menux1, line1, "Frills");
-	drawstr2(menux2, line1, "Editing");
-	drawstr2(menux1, line2, "HELP");
-	drawstr2(menux2, line2, "CAT");
-	drawstr2(across + menux3, line1, "Cursor");
-	drawstr2(across + menux4, line1, "Misc");
-	refreditmode();
-	if (modeflag)
-		log_setmode(modename);
-	else
-		log_setmode("");
-	FORLIM = kindgroupsize;
-	for (i = 1; i <= FORLIM; i++)
-		kdrawgatec(i, gg.color.kindgate);
-}
-
-
-static void beginbottom()
-{
-	remcursor();
-	clipoff();
-	bottomcount++;
-	if (m_autoraise)
-	{
-		clearshowalpha();
-	}
-	else
-	{
-		clearalpha();
-	}
-	nk_gotoxy(0, txdown - 1);
-}
-
-
-static void endbottom()
-{
-	remcursor();
-	bottomcount--;
-	if (m_autoraise)
-	{
-		if (bottomcount < 1)   /* fix from WES */
-		{
-			bottomcount =0;
-			m_graphics_on();
-		}
-	}
-	else
-	{
-		m_graphics_on();   /* switch back to the graphics window */
-	}
-	clearalpha();
-}
-
-
 /*=================  BEGINERROR  =================*/
 /*=                                              =*/
 /*=  Clear the menu area for an error message.   =*/
@@ -4766,130 +1803,22 @@ static void beginerror()
 {
 	beginbottom();
 	strlist_empty(&thingstodo);
-	warning();
-}
-
-
-/*==================  ENDERROR  ==================*/
-/*=                                              =*/
-/*=  Clean up after displaying an error message. =*/
-/*=                                              =*/
-/*================================================*/
-
-static void enderror()
-{
-	printf("  Press any key to continue.");
-	m_alpha_on();
-	waitforkey();
-	endbottom();
-}
-
-
-/*================  REFRSCREEN1  =================*/
-/*=                                              =*/
-/*=  Clear and redraw working area of screen.    =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refrscreen1()
-{
-	m_colormode((long)m_normal);
-	m_noclip();
-	remcursor();
-	uerase(0, 0, across, baseline - 1);
-	resetmessages();
-	refresh();
-	gg.refrflag = true;
-}
-
-
-/*=================  REFRSCREEN  =================*/
-/*=                                              =*/
-/*=  Clear and redraw entire screen.             =*/
-/*=                                              =*/
-/*================================================*/
-
-static void refrscreen()
-{
-	gg.showpage = gg.curpage;
-	bottomcount = 0;
-	m_colormode((long)m_normal);
-	m_noclip();
-	fixcolormap();
-	clearalpha();
-	refrmenu();
-	refrscreen1();
-	m_graphics_on();
-}
-
-
-static void resize_screen()
-{
-	initscreen2();
-	refrscreen();
-}
-
-static void chpage(short pg)
-{
-	log_regrec *r;
-
-	stamp(&gg.pagestamp[pg - 1]);
-	gg.pagechanged[pg - 1] = true;
-	r = gg.pageregions[pg - 1];
-	while (r != NULL) {
-		stamp(&r->regstamp);
-		r = r->next;
-	}
-}
-
-
-static void chpageplace(short pg, short x1, short y1, short x2, short y2)
-{
-	log_regrec *r;
-
-	stamp(&gg.pagestamp[pg - 1]);
-	gg.pagechanged[pg - 1] = true;
-	r = gg.pageregions[pg - 1];
-	if (r == NULL)
-		return;
-	sortshints(&x1, &x2);
-	sortshints(&y1, &y2);
-	while (r != NULL)
-	{
-		if (r->x1 <= x2 && x1 <= r->x2 && r->y1 <= y2 && y1 <= r->y2)
-			stamp(&r->regstamp);
-		r = r->next;
-	}
-}
-
-
-static int pageempty(int pg)
-{
-	return (gg.gbase[pg - 1] == NULL && gg.hwbase[pg - 1] == NULL &&
-			gg.vwbase[pg - 1] == NULL && gg.bbase[pg - 1] == NULL &&
-			gg.lbase[pg - 1] == NULL);
-}
-
-
-static int pagenull(short pg)
-{
-	return (pageempty(pg) && gg.pageregions[pg - 1] == NULL);
+	warning();
 }
 
-static int pagechanged(short pg)
-{
-	return (gg.pagechanged[pg - 1] && !pageempty(pg));
-}
 
+/*==================  ENDERROR  ==================*/
+/*=                                              =*/
+/*=  Clean up after displaying an error message. =*/
+/*=                                              =*/
+/*================================================*/
 
-static int anychanged()
+static void enderror()
 {
-	short i;
-
-	i = 1;
-	while (i <= gg.numpages && !pagechanged(i))
-		i++;
-	return (i <= gg.numpages);
+	printf("  Press any key to continue.");
+	m_alpha_on();
+	waitforkey();
+	endbottom();
 }
 
 
@@ -5512,192 +2441,15 @@ static void clearconflicts(log_tool *tool)
 static short getsignal (int d, char *n);
 
 
-/*===================  NEWHW  ====================*/
-/*=                                              =*/
-/*=  Create a Horizontal Wire.                   =*/
-/*=                                              =*/
-/*================================================*/
-
-static void newhw(log_hwrec **hw)
-{
-	*hw = (log_hwrec *)Malloc(sizeof(log_hwrec));
-	(*hw)->next = gg.hwbase[gg.curpage - 1];
-	gg.hwbase[gg.curpage - 1] = *hw;
-	(*hw)->temp = (na_long)0;
-}
-
-
-#define rtn             "DISPHW"
-
-
-/*==================  DISPHW  ====================*/
-/*=                                              =*/
-/*=  Dispose of a Horizontal Wire.               =*/
-/*=                                              =*/
-/*================================================*/
-
-static void disphw(log_hwrec **hw)
-{
-	log_hwrec *hw1;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Dispose hwire %ld\n", (long)(*hw));
-	if (*hw == NULL)
-		return;
-	hw1 = gg.hwbase[gg.curpage - 1];
-	if (*hw == hw1)
-	{
-		gg.hwbase[gg.curpage - 1] = (*hw)->next;
-	}
-	else
-	{
-		while (hw1 != NULL && hw1->next != *hw)
-			hw1 = hw1->next;
-		if (hw1 == NULL)
-			report(10, rtn);
-		else
-			hw1->next = (*hw)->next;
-	}
-	chpageplace((int)gg.curpage, (*hw)->x1, (*hw)->y, (*hw)->x2, (*hw)->y);
-	Free(*hw);
-}
-
-#undef rtn
-
-
-/*===================  NEWVW  ====================*/
-/*=                                              =*/
-/*=  Create a Vertical Wire.                     =*/
-/*=                                              =*/
-/*================================================*/
-
-static void newvw(log_vwrec **vw)
-{
-	*vw = (log_vwrec *)Malloc(sizeof(log_vwrec));
-	(*vw)->next = gg.vwbase[gg.curpage - 1];
-	gg.vwbase[gg.curpage - 1] = *vw;
-	(*vw)->temp = (na_long)0;
-}
-
-
-#define rtn             "DISW"
-
-
-/*==================  DISW  ====================*/
-/*=                                              =*/
-/*=  Dispose of a Vertical Wire.                 =*/
-/*=                                              =*/
-/*================================================*/
-
-static void dispvw(log_vwrec **vw)
-{
-	log_vwrec *vw1;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Dispose vwire %ld\n", (long)(*vw));
-	if (*vw == NULL)
-		return;
-	vw1 = gg.vwbase[gg.curpage - 1];
-	if (*vw == vw1)
-	{
-		gg.vwbase[gg.curpage - 1] = (*vw)->next;
-	}
-	else
-	{
-		while (vw1 != NULL && vw1->next != *vw)
-			vw1 = vw1->next;
-		if (vw1 == NULL)
-			report(10, rtn);
-		else
-			vw1->next = (*vw)->next;
-	}
-	chpageplace((int)gg.curpage, (*vw)->x, (*vw)->y1, (*vw)->x, (*vw)->y2);
-	Free(*vw);
-}
-
-#undef rtn
-
-
-/*==================  NEWSOLDER  =================*/
-/*=                                              =*/
-/*=  Create a solder point.                      =*/
-/*=                                              =*/
-/*================================================*/
-
-static void newsolder(log_srec **s)
-{
-	*s = (log_srec *)Malloc(sizeof(log_srec));
-	(*s)->next = gg.sbase[gg.curpage - 1];
-	gg.sbase[gg.curpage - 1] = *s;
-	(*s)->hwire = NULL;
-	(*s)->hwire2 = NULL;
-	(*s)->vwire = NULL;
-	(*s)->vwire2 = NULL;
-	(*s)->temp = (na_long)0;
-}
-
-
-#define rtn             "DISPSOLDER"
-
-
-/*================  DISPSOLDER  ==================*/
-/*=                                              =*/
-/*=  Dispose of a solder point.                  =*/
-/*=                                              =*/
-/*================================================*/
-
-static void dispsolder(log_srec **s)
-{
-	log_srec *s1;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Dispose solder %ld\n", (long)(*s));
-	if (*s == NULL)
-		return;
-	s1 = gg.sbase[gg.curpage - 1];
-	if (*s == s1)
-	{
-		gg.sbase[gg.curpage - 1] = (*s)->next;
-	}
-	else
-	{
-		while (s1 != NULL && s1->next != *s)
-			s1 = s1->next;
-		if (s1 == NULL)
-			report(10, rtn);
-		else
-			s1->next = (*s)->next;
-	}
-	chpageplace((int)gg.curpage, (*s)->x, (*s)->y, (*s)->x, (*s)->y);
-	Free(*s);
-}
-
-#undef rtn
-
-
-/*==================  LINKGATE  ==================*/
-/*=                                              =*/
-/*=  Add a gate to the gate list.                =*/
-/*=                                              =*/
-/*================================================*/
-
-static void linkgate(log_grec **g)
-{
-	(*g)->next = gg.gbase[gg.curpage - 1];
-	gg.gbase[gg.curpage - 1] = *g;
-	chpageplace((int)gg.curpage, (*g)->x - (*g)->kind->bbmax,
-			(*g)->y - (*g)->kind->bbmax, (*g)->x + (*g)->kind->bbmax,
-			(*g)->y + (*g)->kind->bbmax);
-}
-
-
 static void newattrs(log_gattrrec **gattr, short numattrs, log_kattrrec *kattr)
 {
 	short i;
 
 	*gattr = (log_gattrrec *)Malloc(numattrs * gattrrecsize);
-	for (i = 0; i < numattrs; i++) {
-		switch (kattr[i].dtype) {
+	for (i = 0; i < numattrs; i++)
+	{
+		switch (kattr[i].dtype)
+		{
 
 			case 'R':
 			case 'U':
@@ -5727,284 +2479,56 @@ static void newattrs(log_gattrrec **gattr, short numattrs, log_kattrrec *kattr)
 				(*gattr)[i].UU.nv = kattr[i].UU.U86.dv;
 				break;
 		}
-		(*gattr)[i].blnk = kattr[i].blnk;
-		(*gattr)[i].changed = false;
-	}
-}
-
-
-static void disposeattrs(log_gattrrec **gattr, short numattrs, log_kattrrec *kattr)
-{
-	short i;
-
-	for (i = 0; i < numattrs; i++)
-	{
-		switch (kattr[i].dtype)
-		{
-
-			case 'C':
-				Free((*gattr)[i].UU.c);
-				break;
-
-			case 'A':
-				strdispose(&(*gattr)[i].UU.sp);
-				break;
-		}
-	}
-	Free(*gattr);
-}
-
-
-static void copyattrs(log_gattrrec **gattr, log_gattrrec *oldattr, short numattrs, log_kattrrec *kattr)
-{
-	short i;
-
-	*gattr = (log_gattrrec *)Malloc(numattrs * gattrrecsize);
-	for (i = 0; i < numattrs; i++)
-	{
-		(*gattr)[i] = oldattr[i];
-		switch (kattr[i].dtype)
-		{
-
-			case 'C':
-				(*gattr)[i].UU.c = (char *)Malloc(kattr[i].prec + 1L);
-				strcpy((*gattr)[i].UU.c, oldattr[i].UU.c);
-				break;
-
-			case 'A':
-				(*gattr)[i].UU.sp = strdup(oldattr[i].UU.sp);
-				break;
-		}
-	}
-}
-
-
-/*===================  NEWGATE  ==================*/
-/*=                                              =*/
-/*=  Create a gate.                              =*/
-/*=                                              =*/
-/*================================================*/
-
-static void newgptr(log_grec **g)
-{
-	if (freegate == NULL)
-	{
-		*g = (log_grec *)Malloc(sizeof(log_grec));
-	}
-	else
-	{
-		*g = freegate;
-		freegate = freegate->next;
-	}
-}
-
-
-static void newgate2(log_grec **g, short gt, short sig, log_gattrrec *attrs)
-{
-	short i;
-	char name[256];
-
-	newgptr(g);
-	(*g)->g = gt;
-	(*g)->rot = gt / log_kindoffset;
-	(*g)->kind = kind[(gt & (log_kindoffset - 1)) - 1];
-	(*g)->vars = (na_long)0;
-	(*g)->conflict = false;
-	(*g)->conflict1 = false;
-	(*g)->conflict2 = false;
-	(*g)->oconflict = false;
-	(*g)->dimcolor = false;
-	(*g)->pin = (log_nrec **)Malloc((*g)->kind->numpins * sizeof(log_nrec *));
-	(*g)->pinpos = (log_pinposrec *)
-		Malloc((*g)->kind->numpins * sizeof(log_pinposrec));
-	if (attrs != NULL)
-		copyattrs(&(*g)->attr, attrs, (*g)->kind->numattrs, (*g)->kind->attr);
-	else
-		newattrs(&(*g)->attr, (*g)->kind->numattrs, (*g)->kind->attr);
-	
-	if (sig != 0)
-	{
-		(*g)->sig = sig;
-	}
-	else if ((*g)->kind->simtype == simtype_common)
-	{
-		*name = '\0';
-		i = 1;
-		while ((*g)->kind->proc[i - 1] != '\0')
-		{
-			sprintf(name + strlen(name), "%c", (*g)->kind->proc[i - 1]);
-			i++;
-		}
-		(*g)->sig = getsignal(0, name);
-	}
-	else
-	{
-		(*g)->sig = 0;
-	}
-	(*g)->info = (na_long)0;
-	(*g)->temp = (na_long)0;
-	gg.actflag = (attrs != NULL);
-	calltoolgate(*g, act_newgate);
-}
-
-
-static void newgate(log_grec **g, short gt)
-{
-	newgate2(g, gt, 0, NULL);
-}
-
-
-/*================  COPYGATE  ====================*/
-/*=                                              =*/
-/*=  Make a copy of a gate (unlinked).           =*/
-/*=                                              =*/
-/*================================================*/
-
-static void copygate(log_grec *old, log_grec **g)
-{
-	long i, FORLIM;
-
-	newgptr(g);
-	**g = *old;
-	if ((*g)->conflict || (*g)->oconflict)
-	{
-		(*g)->confnext = gateconflictbase;
-		gateconflictbase = *g;
-	}
-	(*g)->pin = (log_nrec **)Malloc((*g)->kind->numpins * sizeof(log_nrec *));
-	FORLIM = (*g)->kind->numpins;
-	for (i = 0; i < FORLIM; i++)
-		(*g)->pin[i] = old->pin[i];
-	(*g)->pinpos = (log_pinposrec *)
-		Malloc((*g)->kind->numpins * sizeof(log_pinposrec));
-	FORLIM = (*g)->kind->numpins;
-	for (i = 0; i < FORLIM; i++)
-		(*g)->pinpos[i] = old->pinpos[i];
-	copyattrs(&(*g)->attr, old->attr, (*g)->kind->numattrs, (*g)->kind->attr);
-	(*g)->info = (na_long)0;
-	gg.actgate2 = old;
-	calltoolgate(*g, act_copygate);
-}
-
-
-/*==================  UNLKGATE  ==================*/
-/*=                                              =*/
-/*=  Remove a gate from gate list.               =*/
-/*=                                              =*/
-/*================================================*/
-
-static void unlkgate(log_grec **g)
-{
-	log_grec *g1;
-
-	g1 = gg.gbase[gg.curpage - 1];
-	while (g1 != NULL && g1->next != *g)
-		g1 = g1->next;
-	if (g1 == NULL)
-		gg.gbase[gg.curpage - 1] = (*g)->next;
-	else
-		g1->next = (*g)->next;
-	chpageplace((int)gg.curpage, (*g)->x - (*g)->kind->bbmax,
-			(*g)->y - (*g)->kind->bbmax, (*g)->x + (*g)->kind->bbmax,
-			(*g)->y + (*g)->kind->bbmax);
-}
-
-
-/*===============  DISPOSEGATE  ==================*/
-/*=                                              =*/
-/*=  Dispose of a gate.                          =*/
-/*=                                              =*/
-/*================================================*/
-
-static void disposegptr(log_grec **g)
-{
-	(*g)->next = freegate;
-	freegate = *g;
-}
-
-
-#define rtn             "DISPOSEGATE"
-
 
-static void disposegate(log_grec **g)
-{
-	log_grec *g1, *g2;
-
-	if ((*g)->conflict || (*g)->oconflict)
-	{
-		g1 = gateconflictbase;
-		g2 = NULL;
-		while (g1 != NULL && g1 != *g)
-		{
-			g2 = g1;
-			g1 = g1->confnext;
-		}
-		if (g1 == NULL)
-			report(10, rtn);
-		else if (g2 == NULL)
-			gateconflictbase = (*g)->confnext;
-		else
-			g2->confnext = (*g)->confnext;
+		(*gattr)[i].blnk = kattr[i].blnk;
+		(*gattr)[i].changed = false;
 	}
-	if (*g == gg.probegate)
-		gg.probegate = NULL;
-	calltoolgate(*g, act_disposegate);
-	disposeattrs(&(*g)->attr, (*g)->kind->numattrs, (*g)->kind->attr);
-	Free((*g)->pin);
-	Free((*g)->pinpos);
-	disposegptr(g);
 }
 
-#undef rtn
-
-/*==================  NEWLABEL  ==================*/
-/*=                                              =*/
-/*=  Create a Label.                             =*/
-/*=                                              =*/
-/*================================================*/
 
-static void linklabel(log_lrec *l)
+static void disposeattrs(log_gattrrec **gattr, short numattrs, log_kattrrec *kattr)
 {
-	l->next = gg.lbase[gg.curpage - 1];
-	gg.lbase[gg.curpage - 1] = l;
-	stamp(&gg.labelstamp);
-}
+	short i;
 
+	for (i = 0; i < numattrs; i++)
+	{
+		switch (kattr[i].dtype)
+		{
 
-static void newlabel(log_lrec **l)
-{
-	*l = (log_lrec *)Malloc(sizeof(log_lrec));
-	(*l)->temp = (na_long)0;
-	linklabel(*l);
-}
+			case 'C':
+				Free((*gattr)[i].UU.c);
+				break;
 
+			case 'A':
+				strdispose(&(*gattr)[i].UU.sp);
+				break;
+		}
+	}
+	Free(*gattr);
+}
 
-/*================  DISPLABEL  ===================*/
-/*=                                              =*/
-/*=  Dispose of a text label.                    =*/
-/*=                                              =*/
-/*================================================*/
 
-static void unlinklabel(log_lrec *l)
+static void copyattrs(log_gattrrec **gattr, log_gattrrec *oldattr, short numattrs, log_kattrrec *kattr)
 {
-	log_lrec *l1;
+	short i;
 
-	l1 = gg.lbase[gg.curpage - 1];
-	while (l1 != NULL && l1->next != l)
-		l1 = l1->next;
-	if (l1 == NULL)
-		gg.lbase[gg.curpage - 1] = l->next;
-	else
-		l1->next = l->next;
-	chpageplace((int)gg.curpage, l->x, l->y, l->x + l->w, l->y + 2);
-	stamp(&gg.labelstamp);
-}
+	*gattr = (log_gattrrec *)Malloc(numattrs * gattrrecsize);
+	for (i = 0; i < numattrs; i++)
+	{
+		(*gattr)[i] = oldattr[i];
+		switch (kattr[i].dtype)
+		{
 
+			case 'C':
+				(*gattr)[i].UU.c = (char *)Malloc(kattr[i].prec + 1L);
+				strcpy((*gattr)[i].UU.c, oldattr[i].UU.c);
+				break;
 
-static void displabel(log_lrec **l)
-{
-	unlinklabel(*l);
-	Free(*l);
+			case 'A':
+				(*gattr)[i].UU.sp = strdup(oldattr[i].UU.sp);
+				break;
+		}
+	}
 }
 
 
@@ -6583,50 +3107,6 @@ static void setscale(short s)
 }
 
 
-/*==================  NEWPAGE  ===================*/
-/*=                                              =*/
-/*=  Switch to a new page.                       =*/
-/*=                                              =*/
-/*================================================*/
-
-static void newpage(short p)
-{
-	short i;
-
-	garbagecoll();
-	for (i = gg.numpages; i < p; i++)
-	{
-		xoffp[i] = (origin + across / 2) * gg.scale / log_scale0 - across / 2;
-		yoffp[i] = (origin + baseline / 2) * gg.scale / log_scale0 - baseline / 2;
-		gatecount[i] = 0;
-		gg.gbase[i] = NULL;
-		gg.sbase[i] = NULL;
-		gg.hwbase[i] = NULL;
-		gg.vwbase[i] = NULL;
-		gg.lbase[i] = NULL;
-		gg.bbase[i] = NULL;
-		gg.pagechanged[i] = false;
-		stamp(&gg.pagestamp[i]);
-		gg.pageregions[i] = NULL;
-		curfilename[i] = NULL;
-		vlsimode[i] = vlsi;
-	}
-	if (p != gg.curpage)
-	{
-		xoffp[gg.curpage - 1] = gg.xoff;
-		yoffp[gg.curpage - 1] = gg.yoff;
-		gg.xoff = xoffp[p - 1];
-		gg.yoff = yoffp[p - 1];
-		vlsi = vlsimode[p - 1];
-		curwcolor = log_wcol_normal;
-		gg.numpages = P_imax2((long)p, gg.numpages);
-		gg.curpage = p;
-		realcurpage = p;
-	}
-	while (gg.numpages > gg.curpage && pagenull((int)gg.numpages))
-		gg.numpages--;
-}
-
 static void setupregion(log_regrec **r, short pagenum)
 {
 	log_regrec *r2;
@@ -7529,442 +4009,28 @@ static void trykbd()
 				if (moving)
 					ch = inkey2();
 			} while (moving && labs(yoff0) <= baseline - 10);
-			refrfunc();
-			break;
-
-		default:
-			mp = macrobase;
-			while (mp != NULL && mp->key != ch)
-				mp = mp->next;
-			if (mp != NULL)
-				assertfunc(mp->name);
-			break;
-	}
-}
-
-
-static void trykbdscroll()
-{
-	immedscroll = true;
-	trykbd();
-	immedscroll = false;
-	scroll();
-}
-
-
-/*================  CLOSERGATE  ==================*/
-/*=                                              =*/
-/*=  Find which gate (if any) is under cursor.   =*/
-/*=  Also checks for textual labels.             =*/
-/*=                                              =*/
-/*================================================*/
-
-static void closergate(short x, short y)
-{
-	if (gg.textinvisible)
-		gg.nearlabel = NULL;
-	else {
-		gg.nearlabel = gg.lbase[gg.curpage - 1];
-		while (gg.nearlabel != NULL &&
-				(x < gg.nearlabel->x ||
-				 x > gg.nearlabel->x + m_strwidth(logfont_lfont,
-					 gg.nearlabel->name) / gg.scale ||
-				 y < gg.nearlabel->y || y > gg.nearlabel->y + 2)) {
-			gg.nearlabel = gg.nearlabel->next;
-		}
-	}
-	if (gg.nearlabel != NULL) {
-		gg.nearbox = NULL;
-		gg.neargate = NULL;
-		return;
-	}
-	if (!gg.textinvisible) {
-		gg.nearbox = gg.bbase[gg.curpage - 1];
-		while (gg.nearbox != NULL &&
-				((x != gg.nearbox->x1 && x != gg.nearbox->x2 &&
-				  y != gg.nearbox->y1 &&
-				  y != gg.nearbox->y2) || x < gg.nearbox->x1 ||
-				 x > gg.nearbox->x2 || y < gg.nearbox->y1 || y > gg.nearbox->y2))
-			gg.nearbox = gg.nearbox->next;
-	} else
-		gg.nearbox = NULL;
-	if (gg.nearbox != NULL)
-	{
-		gg.neargate = NULL;
-		return;
-	}
-	gg.neargate = gg.gbase[gg.curpage - 1];
-	while (gg.neargate != NULL && !insidegate(gg.neargate, x, y))
-		gg.neargate = gg.neargate->next;
-}
-
-/*================  CLOSERWIRE  ==================*/
-/*=                                              =*/
-/*=  Find which wire(s) are under the cursor,    =*/
-/*=     if any.                                  =*/
-/*=                                              =*/
-/*================================================*/
-
-static void closerwire(short x, short y)
-{
-	if (gg.invisible || gg.showconflicts)
-	{
-		gg.nearhw = NULL;
-		gg.nearvw = NULL;
-		return;
-	}
-	gg.nearhw = gg.hwbase[gg.curpage - 1];
-	while (gg.nearhw != NULL &&
-			(gg.nearhw->y != y || gg.nearhw->x1 > x || gg.nearhw->x2 < x))
-		gg.nearhw = gg.nearhw->next;
-	gg.nearvw = gg.vwbase[gg.curpage - 1];
-	while (gg.nearvw != NULL &&
-			(gg.nearvw->x != x || gg.nearvw->y1 > y || gg.nearvw->y2 < y))
-		gg.nearvw = gg.nearvw->next;
-}
-
-/*assumes hw <> nil if hw2 <> nil*/
-
-#define rtn             "ADDSOLDER"
-
-
-/*=================  ADDSOLDER  ==================*/
-/*=                                              =*/
-/*=  Add a solder point between two wires.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static void addsolder(short x, short y, log_hwrec *hw, log_hwrec *hw2, log_vwrec *vw, log_vwrec *vw2)
-{
-	log_srec *s;
-	log_nrec *n;
-
-	s = gg.sbase[gg.curpage - 1];
-	while (s != NULL && (s->x != x || s->y != y))
-		s = s->next;
-	if (s == NULL) {
-		newsolder(&s);
-		s->x = x;
-		s->y = y;
-		chpageplace((int)gg.curpage, x, y, x, y);
-		s->hwire = NULL;
-		s->hwire2 = NULL;
-		s->vwire = NULL;
-		s->vwire2 = NULL;
-		n = NULL;
-		if (hw != NULL)
-			n = hw->node;
-		if (vw != NULL && n == NULL)
-			n = vw->node;
-		hidecursor();
-		if (gg.glowmode && n != NULL)
-			drawsolderc(x, y, (int)glowcol(n, (long)gg.color.solder));
-		else
-			drawsolderc(x, y, gg.color.solder);
-		hidecursor();
-	}
-	if (hw != NULL && hw != s->hwire && hw != s->hwire2)
-	{
-		if (s->hwire == NULL)
-			s->hwire = hw;
-		else if (s->hwire2 == NULL)
-			s->hwire2 = hw2;
-		else
-			report(1, rtn);
-	}
-	if (hw2 != NULL && hw2 != s->hwire && hw2 != s->hwire2)
-	{
-		if (s->hwire2 == NULL)
-			s->hwire2 = hw2;
-		else
-			report(2, rtn);
-	}
-	if (vw != NULL && vw != s->vwire && vw != s->vwire2)
-	{
-		if (s->vwire == NULL)
-			s->vwire = vw;
-		else if (s->vwire2 == NULL)
-			s->vwire2 = vw;
-		else
-			report(3, rtn);
-	}
-	if (vw2 != NULL && vw2 != s->vwire && vw2 != s->vwire2)
-	{
-		if (s->vwire2 == NULL)
-			s->vwire2 = vw2;
-		else
-			report(4, rtn);
-	}
-	if (gg.traceflag)
-		fprintf(tracefile, "Add solder %ld\n", (long)s);
-}
-
-#undef rtn
-
-
-/*=================  FINDSOLDER  =================*/
-/*=                                              =*/
-/*=  Find a solder point at specified position.  =*/
-/*=                                              =*/
-/*================================================*/
-
-static log_srec *findsolder(short x, short y)
-{
-	log_srec *s;
-
-	s = gg.sbase[gg.curpage - 1];
-	while (s != NULL && (s->x != x || s->y != y))
-		s = s->next;
-	return s;
-}
-
-
-/*=================  ADDSOLDERT  =================*/
-/*=                                              =*/
-/*=  Add a solder point at a T-intersection of   =*/
-/*=     two wires.                               =*/
-/*=                                              =*/
-/*================================================*/
-
-static void addsoldert(log_hwrec *hw, log_vwrec *vw)
-{
-	if (hw->x1 == vw->x && hw->y != vw->y1 && hw->y != vw->y2)
-	{
-		addsolder(hw->x1, hw->y, hw, NULL, vw, NULL);
-		return;
-	}
-	if (hw->x2 == vw->x && hw->y != vw->y1 && hw->y != vw->y2)
-	{
-		addsolder(hw->x2, hw->y, hw, NULL, vw, NULL);
-		return;
-	}
-	if (hw->y == vw->y1 && hw->x1 != vw->x && hw->x2 != vw->x)
-		addsolder(vw->x, vw->y1, hw, NULL, vw, NULL);
-	else if (hw->y == vw->y2 && hw->x1 != vw->x && hw->x2 != vw->x)
-		addsolder(vw->x, vw->y2, hw, NULL, vw, NULL);
-}
-
-
-/*==================  CHGHW/VW  ==================*/
-/*=                                              =*/
-/*=  Used for deleting wires (see DELHWIRE).     =*/
-/*=                                              =*/
-/*================================================*/
-
-static void chggate (log_grec *g, int i, log_nrec *oldnode, log_nrec *n);
-
-static void chgvw (log_vwrec *vw, log_nrec *oldnode, log_nrec *n);
-
-
-#define rtn             "CHGHW"
-
-
-static void chghw(log_hwrec *hw, log_nrec *oldnode, log_nrec *n)
-{
-	log_vwrec *vw;
-	log_hwrec *hw1;
-	log_grec *g;
-	log_srec *s;
-	short i, px, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Change hwire %ld to node %ld\n", (long)hw, (long)n);
-	switchnode(&hw->node, n);
-	g = gg.gbase[gg.curpage - 1];
-	while (g != NULL)
-	{
-		if (abs(g->y - hw->y) <= g->kind->bbmax &&
-				P_ibetweenm((long)hw->x1, (long)g->x, (long)hw->x2,
-					(long)g->kind->bbmax))
-		{
-			FORLIM = g->kind->numpins;
-			for (i = 1; i <= FORLIM; i++)
-			{
-				px = g->pinpos[i - 1].x;
-				if (hw->x1 <= px && px <= hw->x2 && g->pinpos[i - 1].y == hw->y &&
-						g->pin[i - 1] == oldnode)
-					chggate(g, i, oldnode, n);
-			}
-		}
-		g = g->next;
-	}
-	vw = gg.vwbase[gg.curpage - 1];
-	while (vw != NULL)
-	{
-		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
-				hw->y <= vw->y2 && vw->node == oldnode)
-		{
-			if ((hw->x1 == vw->x || hw->x2 == vw->x || vw->y1 == hw->y ||
-						vw->y2 == hw->y) &&
-					(hw->wcolr == vw->wcolr || hw->wcolr == log_wcol_blue ||
-					 vw->wcolr == log_wcol_blue))
-				chgvw(vw, oldnode, n);
-			else
-			{  /*vlsi only*/
-				s = gg.sbase[gg.curpage - 1];
-				while (s != NULL && (s->x != vw->x || s->y != hw->y))
-					s = s->next;
-				if (s != NULL)
-					chgvw(vw, oldnode, n);
-			}
-		}
-		vw = vw->next;
-	}
-	hw1 = gg.hwbase[gg.curpage - 1];
-	while (hw1 != NULL && vlsi)
-	{
-		if (hw->y == hw1->y && (hw->x1 == hw1->x2 || hw->x2 == hw1->x1) &&
-				(hw->wcolr == log_wcol_blue || hw1->wcolr == log_wcol_blue) &&
-				hw1->node == oldnode)
-			chghw(hw1, oldnode, n);
-		hw1 = hw1->next;
-	}
-}
-
-#undef rtn
-
-
-#define rtn             "CHGVW"
-
-
-static void chgvw(log_vwrec *vw, log_nrec *oldnode, log_nrec *n)
-{
-	log_hwrec *hw;
-	log_vwrec *vw1;
-	log_grec *g;
-	log_srec *s;
-	short i, py, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Change vwire %ld to node %ld\n", (long)vw, (long)n);
-	switchnode(&vw->node, n);
-	g = gg.gbase[gg.curpage - 1];
-	while (g != NULL)
-	{
-		if (abs(g->x - vw->x) <= g->kind->bbmax &&
-				P_ibetweenm((long)vw->y1, (long)g->y, (long)vw->y2,
-					(long)g->kind->bbmax))
-		{
-			FORLIM = g->kind->numpins;
-			for (i = 1; i <= FORLIM; i++)
-			{
-				py = g->pinpos[i - 1].y;
-				if (vw->y1 <= py && py <= vw->y2 && g->pinpos[i - 1].x == vw->x &&
-						g->pin[i - 1] == oldnode)
-					chggate(g, i, oldnode, n);
-			}
-		}
-		g = g->next;
-	}
-	hw = gg.hwbase[gg.curpage - 1];
-	while (hw != NULL)
-	{
-		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
-				hw->y <= vw->y2 && hw->node == oldnode) {
-			if (hw->x1 == vw->x || hw->x2 == vw->x || vw->y1 == hw->y ||
-					vw->y2 == hw->y)
-				chghw(hw, oldnode, n);
-			else
-			{
-				s = gg.sbase[gg.curpage - 1];
-				while (s != NULL && (s->x != vw->x || s->y != hw->y))
-					s = s->next;
-				if (s != NULL)
-					chghw(hw, oldnode, n);
-			}
-		}
-		hw = hw->next;
-	}
-	vw1 = gg.vwbase[gg.curpage - 1];
-	while (vw1 != NULL && vlsi)
-	{
-		if (vw->x == vw1->x && (vw->y1 == vw1->y2 || vw->y2 == vw1->y1) &&
-				(vw->wcolr == log_wcol_blue || vw1->wcolr == log_wcol_blue) &&
-				vw1->node == oldnode)
-			chgvw(vw1, oldnode, n);
-		vw1 = vw1->next;
+			refrfunc();
+			break;
+
+		default:
+			mp = macrobase;
+			while (mp != NULL && mp->key != ch)
+				mp = mp->next;
+			if (mp != NULL)
+				assertfunc(mp->name);
+			break;
 	}
 }
 
-#undef rtn
-
-#define rtn             "CHGGATE"
 
-
-static void chggate(log_grec *g, int i, log_nrec *oldnode, log_nrec *n)
+static void trykbdscroll()
 {
-	log_hwrec *hw;
-	log_vwrec *vw;
-	log_grec *g1;
-	short j, k, savepg, pg, x, y, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Change gate %ld pin %d to node %ld\n",
-				(long)g, i, (long)n);
-	j = i;
-	do
-	{
-		if (g->pin[j - 1] == oldnode)
-		{
-			switchnode(&g->pin[j - 1], n);
-			/* if (j <> i) then  */
-			/*unsafe optimization*/
-			x = g->pinpos[j - 1].x;
-			y = g->pinpos[j - 1].y;
-			hw = gg.hwbase[gg.curpage - 1];
-			while (hw != NULL)
-			{
-				if (hw->x1 <= x && x <= hw->x2 && hw->y == y && hw->node == oldnode)
-					chghw(hw, oldnode, n);
-				hw = hw->next;
-			}
-			vw = gg.vwbase[gg.curpage - 1];
-			while (vw != NULL)
-			{
-				if (vw->y1 <= y && y <= vw->y2 && vw->x == x && vw->node == oldnode)
-					chgvw(vw, oldnode, n);
-				vw = vw->next;
-			}
-			g1 = gg.gbase[gg.curpage - 1];
-			while (g1 != NULL)
-			{
-				if (g1 != g && P_imax2((long)abs(g1->x - x), (long)abs(g1->y - y)) <=
-						g1->kind->bbmax) {
-					FORLIM = g1->kind->numpins;
-					for (k = 1; k <= FORLIM; k++) {
-						if (x == g1->pinpos[k - 1].x && y == g1->pinpos[k - 1].y &&
-								g1->pin[k - 1] == oldnode)
-							chggate(g1, k, oldnode, n);
-					}
-				}
-				g1 = g1->next;
-			}
-		}
-		j = g->kind->pin[j - 1].c;
-	} while (j != i && j != 0);
-	if (i != 1 || g->kind->simtype != simtype_common || g->sig == 0 ||
-			gg.signaltab[g->sig - 1].np != oldnode)
-		return;
-	switchnode(&gg.signaltab[g->sig - 1].np, n);
-	savepg = gg.curpage;
-	FORLIM = gg.numpages;
-	for (pg = 1; pg <= FORLIM; pg++)
-	{
-		gg.curpage = pg;
-		g1 = gg.gbase[gg.curpage - 1];
-		while (g1 != NULL)
-		{
-			if (g1->kind->simtype == simtype_common && g1->sig == g->sig &&
-					g1->pin[0] == oldnode)
-				chggate(g1, 1, oldnode, n);
-			g1 = g1->next;
-		}
-	}
-	gg.curpage = savepg;
+	immedscroll = true;
+	trykbd();
+	immedscroll = false;
+	scroll();
 }
 
-#undef rtn
-
 /* Local variables for wantsolder: */
 struct LOC_wantsolder
 {
@@ -7998,33 +4064,6 @@ static void markcolor(hw, LINK)
 }
 
 
-
-
-/*=================  DELHWIRE  ===================*/
-/*=================  DELVWIRE  ===================*/
-/*=                                              =*/
-/*=  Delete a horizontal or vertical wire.       =*/
-/*=                                              =*/
-/*================================================*/
-
-static int wantsolder(s)
-	log_srec *s;
-{
-	struct LOC_wantsolder V;
-
-	V.hasred = false;
-	V.hasgreen = false;
-	V.hasyellow = false;
-	V.hasblue = false;
-	markcolor(&s->hwire, &V);
-	markcolor(&s->hwire2, &V);
-	markcolor((log_hwrec **)(&s->vwire), &V);
-	markcolor((log_hwrec **)(&s->vwire2), &V);
-	return (V.hasblue && (V.hasgreen || V.hasyellow || V.hasred));
-}
-
-
-
 static void delgetnode(save, old, n)
 	log_nrec **save, **old, **n;
 {
@@ -8039,276 +4078,6 @@ else
 }
 
 
-static void delhwire(hw)
-	log_hwrec *hw;
-{
-	log_vwrec *vw;
-	log_hwrec *hw1;
-	log_srec *s, *s1;
-	log_nrec *oldnode, *n, *savenode;
-	log_grec *g;
-	short i, x, y, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Delete hwire %ld\n", (long)hw);
-	working();
-	clipon();
-	m_color((long)gg.color.backgr);
-	hline(hw->x1, hw->x2, hw->y);
-	oldnode = hw->node;
-	stamp(&oldnode->simtype->netstamp);
-	switchnode(&hw->node, NULL);
-	savenode = oldnode;
-	s = gg.sbase[gg.curpage - 1];
-	while (s != NULL) {
-		s1 = s->next;
-		if (s->hwire == hw || s->hwire2 == hw) {
-			if (s->hwire == hw)
-				s->hwire = s->hwire2;
-			s->hwire2 = NULL;
-			if (!wantsolder(s)) {
-				drawsolderc(s->x, s->y, gg.color.backgr);
-				dispsolder(&s);
-			} else {
-				if (gg.traceflag)
-					fprintf(tracefile, "DELHW keeping solder %ld\n", (long)s);
-			}
-		}
-		s = s1;
-	}
-	vw = gg.vwbase[gg.curpage - 1];
-	while (vw != NULL) {
-		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
-				hw->y <= vw->y2 && vw->node == oldnode) {
-			delgetnode(&savenode, &oldnode, &n);
-			if (n != oldnode)
-				chgvw(vw, oldnode, n);
-		}
-		vw = vw->next;
-	}
-	hw1 = gg.hwbase[gg.curpage - 1];
-	while (hw1 != NULL && vlsi) {
-		if (hw->y == hw1->y && (hw1->x1 == hw->x2 || hw1->x2 == hw->x1) &&
-				hw1->node == oldnode) {
-			delgetnode(&savenode, &oldnode, &n);
-			if (n != oldnode)
-				chghw(hw1, oldnode, n);
-		}
-		hw1 = hw1->next;
-	}
-	g = gg.gbase[gg.curpage - 1];
-	while (g != NULL) {
-		if (abs(g->y - hw->y) <= g->kind->bbmax &&
-				P_ibetweenm((long)hw->x1, (long)g->x, (long)hw->x2,
-					(long)g->kind->bbmax)) {
-			FORLIM = g->kind->numpins;
-			for (i = 1; i <= FORLIM; i++) {
-				if (g->pin[i - 1] == oldnode) {
-					x = g->pinpos[i - 1].x;
-					y = g->pinpos[i - 1].y;
-					if (hw->x1 <= x && x <= hw->x2 && y == hw->y) {
-						delgetnode(&savenode, &oldnode, &n);
-						if (n != oldnode)
-							chggate(g, i, oldnode, n);
-					}
-				}
-			}
-		}
-		g = g->next;
-	}
-	disphw(&hw);
-	clipoff();
-}
-
-
-static void delvwire(vw)
-	log_vwrec *vw;
-{
-	log_hwrec *hw;
-	log_vwrec *vw1;
-	log_srec *s, *s1;
-	log_nrec *oldnode, *n, *savenode;
-	log_grec *g;
-	short i, x, y, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Delete vwire %ld\n", (long)vw);
-	working();
-	clipon();
-	m_color((long)gg.color.backgr);
-	vline(vw->x, vw->y1, vw->y2);
-	oldnode = vw->node;
-	stamp(&oldnode->simtype->netstamp);
-	switchnode(&vw->node, NULL);
-	savenode = oldnode;
-	s = gg.sbase[gg.curpage - 1];
-	while (s != NULL) {
-		s1 = s->next;
-		if (s->vwire == vw || s->vwire2 == vw) {
-			if (s->vwire == vw)
-				s->vwire = s->vwire2;
-			s->vwire2 = NULL;
-			if (!wantsolder(s)) {
-				drawsolderc(s->x, s->y, gg.color.backgr);
-				dispsolder(&s);
-			} else {
-				if (gg.traceflag)
-					fprintf(tracefile, "DELVW keeping solder %ld\n", (long)s);
-			}
-		}
-		s = s1;
-	}
-	hw = gg.hwbase[gg.curpage - 1];
-	while (hw != NULL) {
-		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
-				hw->y <= vw->y2 && hw->node == oldnode) {
-			delgetnode(&savenode, &oldnode, &n);
-			if (n != oldnode)
-				chghw(hw, oldnode, n);
-		}
-		hw = hw->next;
-	}
-	vw1 = gg.vwbase[gg.curpage - 1];
-	while (vw1 != NULL && vlsi) {
-		if (vw->x == vw1->x && (vw1->y1 == vw->y2 || vw1->y2 == vw->y1) &&
-				vw1->node == oldnode) {
-			delgetnode(&savenode, &oldnode, &n);
-			if (n != oldnode)
-				chgvw(vw1, oldnode, n);
-		}
-		vw1 = vw1->next;
-	}
-	g = gg.gbase[gg.curpage - 1];
-	while (g != NULL) {
-		if (abs(g->x - vw->x) <= g->kind->bbmax &&
-				P_ibetweenm((long)vw->y1, (long)g->y, (long)vw->y2,
-					(long)g->kind->bbmax)) {
-			FORLIM = g->kind->numpins;
-			for (i = 1; i <= FORLIM; i++) {
-				if (g->pin[i - 1] == oldnode) {
-					x = g->pinpos[i - 1].x;
-					y = g->pinpos[i - 1].y;
-					if (vw->y1 <= y && y <= vw->y2 && x == vw->x) {
-						delgetnode(&savenode, &oldnode, &n);
-						if (n != oldnode)
-							chggate(g, i, oldnode, n);
-					}
-				}
-			}
-		}
-		g = g->next;
-	}
-	vw1 = vw;
-	dispvw(&vw);
-	clipoff();
-}
-
-
-static void chggatepin(g, i, oldnode, savenode)
-	log_grec *g;
-	short i;
-	log_nrec **oldnode, **savenode;
-{
-	log_nrec *n;
-	log_hwrec *hw;
-	log_vwrec *vw;
-	log_grec *g1;
-	short j, x, y, FORLIM;
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Change gate %ld pin %d from node %ld\n",
-				(long)g, i, (long)(*oldnode));
-	x = g->pinpos[i - 1].x;
-	y = g->pinpos[i - 1].y;
-	hw = gg.hwbase[gg.curpage - 1];
-	while (hw != NULL) {
-		if (hw->x1 <= x && x <= hw->x2 && hw->y == y && hw->node == *oldnode) {
-			delgetnode(savenode, oldnode, &n);
-			if (n != *oldnode)
-				chghw(hw, *oldnode, n);
-		}
-		hw = hw->next;
-	}
-	vw = gg.vwbase[gg.curpage - 1];
-	while (vw != NULL) {
-		if (vw->y1 <= y && y <= vw->y2 && vw->x == x && vw->node == *oldnode) {
-			delgetnode(savenode, oldnode, &n);
-			if (n != *oldnode)
-				chgvw(vw, *oldnode, n);
-		}
-		vw = vw->next;
-	}
-	g1 = gg.gbase[gg.curpage - 1];
-	while (g1 != NULL) {
-		if (g1 != g &&
-				P_imax2((long)abs(g1->x - x), (long)abs(g1->y - y)) <= g1->kind->bbmax) {
-			FORLIM = g1->kind->numpins;
-			for (j = 1; j <= FORLIM; j++) {
-				if (x == g1->pinpos[j - 1].x && y == g1->pinpos[j - 1].y &&
-						g1->pin[j - 1] == *oldnode) {
-					delgetnode(savenode, oldnode, &n);
-					if (n != *oldnode)
-						chggate(g1, j, *oldnode, n);
-				}
-			}
-		}
-		g1 = g1->next;
-	}
-}
-
-
-static void disconnectgate(g)
-	log_grec *g;
-{
-	log_nrec *savenode;
-	short i, j;
-	log_nrec **oldnode;
-	long done[log_maxpins / 32 + 2];
-	short FORLIM;
-	long SET[9];
-
-	if (gg.traceflag)
-		fprintf(tracefile, "Disconnect gate %ld\n", (long)g);
-	stamp(&g->kind->simtype->netstamp);
-	calltoolgate(g, act_disconnectgate);
-	oldnode = (log_nrec **)Malloc(g->kind->numpins * sizeof(log_nrec *));
-	FORLIM = g->kind->numpins;
-	for (i = 0; i < FORLIM; i++) {
-		oldnode[i] = g->pin[i];
-		stamp(&oldnode[i]->simtype->netstamp);
-		switchnode(&g->pin[i], NULL);
-	}
-	P_expset(done, 0L);
-	FORLIM = g->kind->numpins;
-	for (i = 1; i <= FORLIM; i++) {
-		if (!P_inset(i, done)) {
-			j = i;
-			if (i == 1 && g->kind->simtype == simtype_common && g->sig != 0)
-				savenode = NULL;
-			else
-				savenode = oldnode[i - 1];
-			do {
-				chggatepin(g, j, &oldnode[i - 1], &savenode);
-				P_addset(done, j);
-				j = g->kind->pin[j - 1].c;
-			} while (j != i && j != 0);
-		}
-	}
-	unlkgate(&g);
-}
-
-
-static void delgate(g)
-	log_grec *g;
-{
-	clipon();
-	eragate(g);
-	disconnectgate(g);
-	disposegate(&g);
-	clipoff();
-}
-
-
 static void confirmsimtype(n)
 	log_nrec *n;
 {
@@ -8626,9 +4395,6 @@ static int trycombinenodes(n1, n2)
 }
 
 
-
-
-
 static void fryhwire(hw)
 	log_hwrec *hw;
 {
@@ -8769,7 +4535,6 @@ static void dispblobs(blbase)
 #define rtn             "ADDHWIRE"
 
 
-/*==================  ADDHWIRE  ==================*/
 /*==================  ADDVWIRE  ==================*/
 /*=                                              =*/
 /*=  ADDHWIRE:                                   =*/
@@ -9815,9 +5580,6 @@ static void yardstickcommand()
 }
 
 
-
-
-
 /*=================  ADDGATE1  ===================*/
 /*=                                              =*/
 /*=  Add a gate to the circuit.  Initialize all  =*/
@@ -9867,7 +5629,6 @@ static void addgate2(x, y, gtype, sig, attrs)
 }
 
 
-
 static void addgate1(x, y, gtype)
 	short x, y, gtype;
 {
@@ -9875,7 +5636,6 @@ static void addgate1(x, y, gtype)
 }
 
 
-
 static void uaddgate(x, y, gtype)
 	short x, y, gtype;
 {
@@ -9906,9 +5666,6 @@ static void uaddgate(x, y, gtype)
 
 
 
-
-
-
 /*==================  ADDGATE  ===================*/
 /*=                                              =*/
 /*=  Move a gate into position, then add to      =*/
@@ -11695,9 +7452,6 @@ static void closevert()
 }
 
 
-
-
-
 static void centercommand()
 {
 	log_grec *g;
@@ -11758,55 +7512,6 @@ static void centercommand()
 }
 
 
-/*=================  SHOWCATALOG  ================*/
-/*=                                              =*/
-/*=  Switch screen to catalog (TRUE) or circuit  =*/
-/*=     (FALSE).                                 =*/
-/*=                                              =*/
-/*================================================*/
-
-static void showcatalog()
-{
-	short i;
-	catboxrec *cb;
-	short x1, y1, x2, y2, FORLIM;
-
-	clearscreen();
-	gg.showpage = log_page_cat;
-	FORLIM = maxkinds;
-	for (i = 1; i <= FORLIM; i++) {
-		if (kind[i - 1] != NULL) {
-			/* p2c: log.text, line 11731:
-			 * Note: Using % for possibly-negative arguments [317] */
-			udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
-					(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
-					gg.color.catgate);
-		}
-	}
-	cb = catboxes;
-	while (cb != NULL) {
-		x1 = (cb->pos - 1) % catwidth * gridcen * 2;
-		/* p2c: log.text, line 11738:
-		 * Note: Using % for possibly-negative arguments [317] */
-		y1 = (cb->pos - 1) / catwidth * gridcen * 2;
-		x2 = ((cb->pos + cb->count - 2) % catwidth + 1) * gridcen * 2;
-		/* p2c: log.text, line 11740:
-		 * Note: Using % for possibly-negative arguments [317] */
-		y2 = ((cb->pos + cb->count - 2) / catwidth + 1) * gridcen * 2;
-		m_color((long)catboxcolor);
-		m_linestyle(2L);
-		m_drawline((long)x1, (long)y1, (long)x2, (long)y1);
-		m_linestyle(2L);
-		m_drawline((long)x1, (long)y2, (long)x2, (long)y2);
-		m_linestyle(2L);
-		m_drawline((long)x1, (long)y1, (long)x1, (long)y2);
-		m_linestyle(2L);
-		m_drawline((long)x2, (long)y1, (long)x2, (long)y2);
-		m_linestyle(0L);
-		cb = cb->next;
-	}
-}
-
 /*================  COMPARESTR  ==================*/
 /*=                                              =*/
 /*=  Compare string S with template string T.    =*/
@@ -12755,12 +8460,6 @@ static void gatedefinitioncommand()
 }
 
 
-
-
-
-
-
-
 /*================  LISTLIBRARY  =================*/
 /*=                                              =*/
 /*=  List the gates available in the library.    =*/
@@ -14575,15 +10274,6 @@ const fliparr flips = {
 };
 
 
-
-
-
-
-
-
-
-
-
 static short doflip(rot, mode)
 	short rot, mode;
 {
@@ -14591,8 +10281,6 @@ static short doflip(rot, mode)
 }
 
 
-
-
 /*==================  FLIPGATE  ==================*/
 /*=                                              =*/
 /*=  Flip a gate in the circuit.                 =*/
@@ -21115,10 +16803,6 @@ static void readcnf(char *fn_, struct LOC_initialize *LINK)
 	/*obsolete*/
 }
 
-
-
-
-
 /*==================  INITIALIZE  ================*/
 /*=                                              =*/
 /*=  Initialize all variables.  Read basic gates =*/
@@ -21757,8 +17441,6 @@ static void shownews()
 }
 
 
-
-
 /*================  MAIN PROGRAM  ================*/
 /*=                                              =*/
 /*=  Initialize.                                 =*/
diff --git a/log/src/page.c b/log/src/page.c
new file mode 100644
index 0000000..0a93e3f
--- /dev/null
+++ b/log/src/page.c
@@ -0,0 +1,110 @@
+
+#include <p2c/p2c.h>
+
+static void chpage(short pg)
+{
+	log_regrec *r;
+
+	stamp(&gg.pagestamp[pg - 1]);
+	gg.pagechanged[pg - 1] = true;
+	r = gg.pageregions[pg - 1];
+	while (r != NULL) {
+		stamp(&r->regstamp);
+		r = r->next;
+	}
+}
+
+
+static void chpageplace(short pg, short x1, short y1, short x2, short y2)
+{
+	log_regrec *r;
+
+	stamp(&gg.pagestamp[pg - 1]);
+	gg.pagechanged[pg - 1] = true;
+	r = gg.pageregions[pg - 1];
+	if (r == NULL)
+		return;
+	sortshints(&x1, &x2);
+	sortshints(&y1, &y2);
+	while (r != NULL)
+	{
+		if (r->x1 <= x2 && x1 <= r->x2 && r->y1 <= y2 && y1 <= r->y2)
+			stamp(&r->regstamp);
+		r = r->next;
+	}
+}
+
+
+static int pageempty(int pg)
+{
+	return (gg.gbase[pg - 1] == NULL && gg.hwbase[pg - 1] == NULL &&
+			gg.vwbase[pg - 1] == NULL && gg.bbase[pg - 1] == NULL &&
+			gg.lbase[pg - 1] == NULL);
+}
+
+
+static int pagenull(short pg)
+{
+	return (pageempty(pg) && gg.pageregions[pg - 1] == NULL);
+}
+
+static int pagechanged(short pg)
+{
+	return (gg.pagechanged[pg - 1] && !pageempty(pg));
+}
+
+
+static int anychanged()
+{
+	short i;
+
+	i = 1;
+	while (i <= gg.numpages && !pagechanged(i))
+		i++;
+	return (i <= gg.numpages);
+}
+
+/*==================  NEWPAGE  ===================*/
+/*=                                              =*/
+/*=  Switch to a new page.                       =*/
+/*=                                              =*/
+/*================================================*/
+
+static void newpage(short p)
+{
+	short i;
+
+	garbagecoll();
+	for (i = gg.numpages; i < p; i++)
+	{
+		xoffp[i] = (origin + across / 2) * gg.scale / log_scale0 - across / 2;
+		yoffp[i] = (origin + baseline / 2) * gg.scale / log_scale0 - baseline / 2;
+		gatecount[i] = 0;
+		gg.gbase[i] = NULL;
+		gg.sbase[i] = NULL;
+		gg.hwbase[i] = NULL;
+		gg.vwbase[i] = NULL;
+		gg.lbase[i] = NULL;
+		gg.bbase[i] = NULL;
+		gg.pagechanged[i] = false;
+		stamp(&gg.pagestamp[i]);
+		gg.pageregions[i] = NULL;
+		curfilename[i] = NULL;
+		vlsimode[i] = vlsi;
+	}
+	if (p != gg.curpage)
+	{
+		xoffp[gg.curpage - 1] = gg.xoff;
+		yoffp[gg.curpage - 1] = gg.yoff;
+		gg.xoff = xoffp[p - 1];
+		gg.yoff = yoffp[p - 1];
+		vlsi = vlsimode[p - 1];
+		curwcolor = log_wcol_normal;
+		gg.numpages = P_imax2((long)p, gg.numpages);
+		gg.curpage = p;
+		realcurpage = p;
+	}
+	while (gg.numpages > gg.curpage && pagenull((int)gg.numpages))
+		gg.numpages--;
+}
+
diff --git a/log/src/screen.c b/log/src/screen.c
new file mode 100644
index 0000000..177e838
--- /dev/null
+++ b/log/src/screen.c
@@ -0,0 +1,2426 @@
+/* "LOG", the circuit editing and simulation system,
+   "DigLOG", the digital simulator for LOG.
+   Copyright (C) 1985, 1990 David Gillespie.
+   Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
+
+   "AnaLOG", the analog simulator for LOG.
+   Copyright (C) 1985, 1990 John Lazzaro.
+   Author's address: lazzaro@csvax.caltech.edu; 256-80 Caltech.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation (any version).
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   */
+
+/*
+   Logic Simulator   Version 4.1
+   For HP 9836C
+
+   Copyright (c)  1985
+
+   David Gillespie
+   */
+
+#include <p2c/p2c.h>
+
+
+/*=================  INITSCREEN  =================*/
+/*=                                              =*/
+/*=  Initialize color graphics, graphics tablet, =*/
+/*=     low-level flags & variables              =*/
+/*=                                              =*/
+/*================================================*/
+
+static void initcolormap()
+{
+	m_setcolor((long)log_gray, 4L, 4L, 4L);
+	m_setcolor((long)log_red, 15L, 0L, 0L);
+	m_setcolor((long)log_green, 0L, 15L, 0L);
+	m_setcolor((long)log_yellow, 15L, 15L, 0L);
+	if (eightcolors) {
+		m_setcolor((long)log_cred8, 15L, 0L, 0L);
+		m_setcolor((long)log_black8, 0L, 0L, 0L);
+	} else {
+		m_setcolor((long)log_mred, 11L, 0L, 0L);
+		m_setcolor((long)log_orange, 15L, 9L, 0L);
+	}
+	m_setcolor((long)log_cyan, 0L, 15L, 15L);
+	m_setcolor((long)log_white, 15L, 15L, 15L);
+	m_setcolor((long)log_black, 0L, 0L, 0L);
+	m_setcolor((long)log_pink, 15L, 9L, 9L);
+	m_setcolor((long)log_dyellow, 12L, 12L, 0L);
+	m_setcolor((long)log_xgreen, 0L, 13L, 0L);
+	m_setcolor((long)log_dcyan, 0L, 10L, 10L);
+	m_setcolor((long)log_dred, 8L, 0L, 0L);
+	m_setcolor((long)log_lgray, 10L, 10L, 10L);
+	m_setcolor((long)log_cred, 15L, 0L, 0L);
+	m_vseecolors(0L, 16L, rcolormap, gcolormap, bcolormap);
+}
+
+
+static void fixcolormap()
+{
+	m_vsetcolors(0L, 16L, rcolormap, gcolormap, bcolormap);
+	recolor_log_cursors(gg.color.cursor, true);
+}
+
+
+
+static void initscreen()
+{
+	m_init_screen();
+	m_upside_down();
+	m_setlinestyle(1L, 0xf0f0L);
+	m_setlinestyle(2L, 0xaaaaL);
+	m_setfont(logfont_lfont);
+	init_X_screen();
+	onescreen = nc_alphashared();
+	eightcolors = (m_maxcolor <= 7);
+
+	txacross = nc_curWindow->width - 1;
+	txdown = nc_curWindow->height - 1;
+	across = m_across;
+	down = m_down;
+	baseline = down - 53;   /* Position of baseline on screen */
+	line1 = down - 43;   /* Position of first text line in menu */
+	line2 = down - 23;   /* Position of second text line in menu */
+	histdown = down - 26;
+	histdivsacross = (double)(across - histleft) / histdivision;
+	histvalrange = (double)histdown / histdivision * 5;
+	kindgroupsize = (across - 160) / kindgroupspacing;
+	kindgroupleft = (across - kindgroupsize * kindgroupspacing) / 2;
+	kindgroupright = kindgroupleft + kindgroupsize * kindgroupspacing;
+	kindgroupstart = kindgroupleft + kindgroupspacing / 2;
+	kindgroupbase = (baseline + down) / 2;
+
+	printf("\200\210");
+	SETRUNLIGHT(' ');
+
+	cursorflag = false;
+	gg.stillnear = true;
+}
+
+
+static void initscreen2()
+{
+	initscreen();
+	m_clear();
+	m_graphics_on();
+}
+
+/*==================  NOBLINK  ===================*/
+/*=                                              =*/
+/*=  Turn off the stupid blinking Alpha cursor.  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void noblink()
+{
+	nc_cursXY(-1, -1);
+	/*  oldx := xpos;
+oldy := ypos;
+xpos := -1;
+ypos := -1;
+call(updatecursorhook);
+xpos := oldx;
+ypos := oldy; */
+}
+
+
+static void clearalpha()
+{
+	if (!onescreen)
+	{
+		printf("\f");
+		noblink();
+		m_alpha_off();
+	}
+	nk_gotoxy(0, 0);
+}
+
+
+static void showalpha()
+{
+	m_graphics_off();
+	m_alpha_on();
+}
+
+/*===================  LINE  =====================*/
+/*=                                              =*/
+/*=  Draw a line in grid coordinates.            =*/
+/*=                                              =*/
+/*================================================*/
+
+static void line(short x1, short y1, short x2, short y2)
+{
+	m_drawline(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
+			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
+}
+
+
+/*===================  HLINE  ====================*/
+/*=                                              =*/
+/*=  Draw a horizontal line in grid coordinates. =*/
+/*=                                              =*/
+/*=                                              =*/
+/*================================================*/
+
+static void hline(short x1, short x2, short y)
+{
+	short yy;
+
+	yy = y * gg.scale - gg.yoff;
+	m_drawline(x1 * gg.scale - gg.xoff, (long)yy, x2 * gg.scale - gg.xoff, (long)yy);
+}
+
+
+/*===================  VLINE  ====================*/
+/*=                                              =*/
+/*=  Draw a vertical line in grid coordinates.   =*/
+/*=                                              =*/
+/*=                                              =*/
+/*================================================*/
+
+static void vline(short x, short y1, short y2)
+{
+	short xx;
+
+	xx = x * gg.scale - gg.xoff;
+	m_drawline((long)xx, y1 * gg.scale - gg.yoff, (long)xx,
+			y2 * gg.scale - gg.yoff);
+}
+
+
+/*===================  POINT  ====================*/
+/*=                                              =*/
+/*=  Draw a point in grid coordinates.           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void point(short x, short y)
+{
+	m_drawpoint(x * gg.scale - gg.xoff, y * gg.scale - gg.yoff);
+}
+
+
+/*===================  RECT  =====================*/
+/*=                                              =*/
+/*=  Draw a rectangle in grid coordinates.       =*/
+/*=                                              =*/
+/*================================================*/
+
+static void rect(short x1, short y1, short x2, short y2)
+{
+	m_drawrect(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
+			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
+}
+
+/*====================  BOX  =====================*/
+/*=                                              =*/
+/*=  Draw a filled rectangle in grid coords.     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void box(short x1, short y1, short x2, short y2)
+{
+	m_fillrect(x1 * gg.scale - gg.xoff, y1 * gg.scale - gg.yoff,
+			x2 * gg.scale - gg.xoff, y2 * gg.scale - gg.yoff);
+}
+
+/*=================  DRAWSTR2  ===================*/
+/*=                                              =*/
+/*=  Draw a text string.                         =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawstr2(short x, short y, char *s)
+{
+	long save;
+
+	if (m_curcolor() < 16)
+	{
+		save = m_curcolor();
+		m_color((long)gg.color.backgr);
+		m_fillrect(x - 1L, y - 2L, x + m_strwidth(logfont_lfont, s), y + 9L);
+		m_color(save);
+	}
+	m_move((long)x, (long)y);
+	m_displaytext(s);
+}
+
+
+static void rightstr2(short x, short y, char *s)
+{
+	long save;
+
+	if (m_curcolor() < 16)
+	{
+		save = m_curcolor();
+		m_color((long)gg.color.backgr);
+		m_fillrect(x + m_strwidth(logfont_lfont, s) - 1, y - 2L, x + 1L, y + 9L);
+		m_color(save);
+	}
+	m_rightstr((long)x, (long)y, logfont_lfont, s);
+}
+
+
+static void centerstr2(short x, short y, char *s)
+{
+	short w;
+	long save;
+
+	if (m_curcolor() < 16)
+	{
+		save = m_curcolor();
+		m_color((long)gg.color.backgr);
+		w = m_strwidth(logfont_lfont, s) / 2 + 2;
+		m_fillrect((long)(x - w), y - 2L, (long)(x + w), y + 9L);
+		m_color(save);
+	}
+	m_centerstr((long)x, (long)y, logfont_lfont, s);
+}
+
+
+/*=================  DRAWNUM1  ===================*/
+/*=                                              =*/
+/*=  Draw a single digit at the specified        =*/
+/*=     position (screen coordinates).           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawnum1(short x, short y, short n)
+{
+	char s[2];
+
+	m_move((long)x, (long)y);
+	strcpy(s, " ");
+	s[0] = n + '0';
+	m_displaytext(s);
+}
+
+
+/*=================  DRAWNUM2  ===================*/
+/*=                                              =*/
+/*=  Draw a two-digit number at the specified    =*/
+/*=     position (screen coordinates).           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawnum2(short x, short y, short n)
+{
+	char s[3];
+
+	m_move((long)x, (long)y);
+	strcpy(s, "  ");
+	if (n >= 10)
+		s[0] = n / 10 + '0';
+	s[1] = n % 10 + '0';
+	m_displaytext(s);
+}
+
+
+static void xformcoords(log_grec *g, short *x, short *y)
+{
+	short xx, yy;
+
+	if (g == NULL)
+	{
+		*x = *x * gg.scale - gg.xoff;
+		*y = *y * gg.scale - gg.yoff;
+		return;
+	}
+	xx = *x * gg.scale;
+	yy = *y * gg.scale;
+	*x = g->x * gg.scale - gg.xoff +
+		(log_rotxx[g->rot] * xx + log_rotyx[g->rot] * yy) / log_scale0;
+	*y = g->y * gg.scale - gg.yoff +
+		(log_rotxy[g->rot] * xx + log_rotyy[g->rot] * yy) / log_scale0;
+}
+
+
+static void plainxformcoords(log_grec *g, short *x, short *y)
+{
+	short xx;
+
+	if (g == NULL)
+	{
+		*x *= log_scale0;
+		*y *= log_scale0;
+		return;
+	}
+	xx = *x;
+	*x = g->x * log_scale0 + log_rotxx[g->rot] * xx + log_rotyx[g->rot] * *y;
+	*y = g->y * log_scale0 + log_rotxy[g->rot] * xx + log_rotyy[g->rot] * *y;
+}
+
+
+/*==================  CLIPON  ====================*/
+/*=                                              =*/
+/*=  Allow drawing only in the working area.     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void clipon()
+{
+	m_clip(0L, 0L, (long)across, baseline - 1L);
+}
+
+
+/*==================  CLIPOFF  ===================*/
+/*=                                              =*/
+/*=  Allow drawing in working area and menus.    =*/
+/*=                                              =*/
+/*================================================*/
+
+static void clipoff()
+{
+	m_noclip();
+}
+
+/*==================  UERASE  ====================*/
+/*=                                              =*/
+/*=  Erase a rectangular area of the screen      =*/
+/*=     using screen coordinates.                =*/
+/*=                                              =*/
+/*================================================*/
+
+static void uerase(short x1, short y1, short x2, short y2)
+{
+	m_color((long)gg.color.backgr);
+	m_fillrect((long)x1, (long)y1, (long)x2, (long)y2);
+}
+
+
+/*===================  ERASE  ====================*/
+/*=                                              =*/
+/*=  Erase a rectangular area of the screen      =*/
+/*=     using grid coordinates.                  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void erase(short x1, short y1, short x2, short y2)
+{
+	m_color((long)gg.color.backgr);
+	box(x1, y1, x2, y2);
+}
+
+
+/*================  NORABBITS  ===================*/
+/*=                                              =*/
+/*=  Make sure there are no rabbits on the       =*/
+/*=     screen.                                  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void norabbits()
+{
+	short i;
+
+	clipoff();
+	for (i = 0; i < rabtabsize; i++)
+	{
+		if (rabtable[i].next == 1)
+		{
+			m_bunny((long)rabtable[i].x, (long)rabtable[i].y);
+			rabtable[i].next = 0;
+		}
+	}
+	rabflag = false;
+}
+
+
+/*================  ADDRABBIT  ===================*/
+/*=                                              =*/
+/*=  Draw a rabbit on the screen.                =*/
+/*=                                              =*/
+/*================================================*/
+
+static void addrabbit()
+{
+	short i, j, rx, ry;
+	int nogood;
+	rablistrec *WITH;
+
+	clipoff();
+	j = -1;
+	for (i = 1; i <= rabtabsize; i++)
+	{
+		if (rabtable[i - 1].next == 0)
+			j = i;
+	}
+	if (j == -1)
+	{
+		j = P_rand(&gg.rndseed, (long)rabtabsize) + 1;
+		m_bunny((long)rabtable[j - 1].x, (long)rabtable[j - 1].y);
+		rabtable[j - 1].next = 0;
+	}
+	do
+	{
+		rx = P_rand(&gg.rndseed, across - 24L);
+		ry = P_rand(&gg.rndseed, baseline - 40L) + down - baseline + 30;
+		nogood = false;
+		for (i = 0; i < rabtabsize; i++)
+		{
+			WITH = &rabtable[i];
+			if (WITH->next == 1)
+			{
+				if (WITH->x + 24 >= rx && WITH->x <= rx + 24 && WITH->y + 26 >= ry &&
+						WITH->y <= ry + 26)
+					nogood = true;
+			}
+		}
+	} while (nogood);
+	rabtable[j - 1].next = 1;
+	rabtable[j - 1].x = rx;
+	rabtable[j - 1].y = ry;
+	m_bunny((long)rx, (long)ry);
+	rabflag = true;
+	rabtime = timers_sysclock();
+}
+
+
+/*==================  HVLINE  ====================*/
+/*=                                              =*/
+/*=  Attempt to force a line to be horizontal    =*/
+/*=     or vertical.  If possible, second pair   =*/
+/*=     of coordinates is changed appropriately. =*/
+/*=                                              =*/
+/*=  Returns true if possible, false if not.     =*/
+/*=                                              =*/
+/*================================================*/
+
+static int hvline(short x1, short y1, short *x2, short *y2)
+{
+	int Result;
+
+	Result = true;
+	if (x1 == *x2 && y1 == *y2)
+		return false;
+	if (abs(*x2 - x1) > abs(*y2 - y1) && abs(*y2 - y1) < abs(*x2 - x1) / 3 + 20)
+	{   /*7/14/88*/
+		*y2 = y1;
+		return Result;
+	}
+	if (abs(*y2 - y1) <= abs(*x2 - x1) ||
+			abs(*x2 - x1) >= abs(*y2 - y1) / 3 + 20)
+		/*7/14/88*/
+		return false;
+	*x2 = x1;
+	return Result;
+}
+
+
+/*===================  FIXXY  ====================*/
+/*=                                              =*/
+/*=  Adjust screen coordinates so that they are  =*/
+/*=     aligned to the nearest grid point.       =*/
+/*=                                              =*/
+/*================================================*/
+
+static void fixxy(short *x, short *y)
+{
+	*x = (*x + gg.xoff + gg.hscale) / gg.scale * gg.scale - gg.xoff;
+	*y = (*y + gg.yoff + gg.hscale) / gg.scale * gg.scale - gg.yoff;
+}
+
+/*================  NOCROSSHAIR  =================*/
+/*=                                              =*/
+/*=  Turn off crosshair (no effect until next    =*/
+/*=     call of CURSOR).                         =*/
+/*=                                              =*/
+/*================================================*/
+
+static void nocrosshair()
+{
+	chairflag2 = false;
+}
+
+
+/*=================  CROSSHAIR  ==================*/
+/*=                                              =*/
+/*=  Move the crosshair to a particular position =*/
+/*=     in grid coordinates.                     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void crosshair(short x, short y)
+{
+	chairx = x * gg.scale - gg.xoff;
+	chairy = y * gg.scale - gg.yoff;
+	chairflag2 = true;
+}
+
+/*=================  XORCURSOR  ==================*/
+/*=                                              =*/
+/*=  Draw the cursor on the screen.              =*/
+/*=  The exact shape drawn depends upon the      =*/
+/*=     current mode.                            =*/
+/*=  If the cursor is already on the screen, it  =*/
+/*=     is removed.                              =*/
+/*=                                              =*/
+/*=  Possible cursors:                           =*/
+/*=     Arrow (normal).                          =*/
+/*=     Probe (if Logic Probe mode).             =*/
+/*=     Big crosshair (if "Grid" mode on).       =*/
+/*=     Long arrow (if Copy command).            =*/
+/*=     Scissors (if Delete command).            =*/
+/*=     Rectangle (if Paste command).            =*/
+/*=     Green line (if drawing a wire).          =*/
+/*=     Rabbit (if Rabbit mode).                 =*/
+/*=                                              =*/
+/*================================================*/
+
+static void xorcursor()
+{
+	long curcm;
+	short cx0, cy0;
+
+	gg.cx_min = 0;
+	gg.cx_max = across;
+	gg.cy_min = 0;
+	gg.cy_max = baseline - 1;
+	curcm = m_curcolormode();
+	m_colormode((long)m_xor);
+	m_color((long)gg.color.cursor);
+	if (!chairflag || cursortype == grid)
+	{
+		if (cursortype != normal && cursy < baseline)
+		{
+			switch (cursortype)
+			{
+
+				case grid:
+					choose_log_cursor(0);
+					if (chairflag) {
+						m_drawline(cursx1 - 3L, cursy1 - 5L, cursx1 + 3L, cursy1 + 5L);
+						m_drawline(cursx1 - 3L, cursy1 + 5L, cursx1 + 3L, cursy1 - 5L);
+					}
+					cx0 = (cursx + gg.xoff) / gg.scale * gg.scale - gg.xoff;
+					cy0 = (cursy + gg.yoff) / gg.scale * gg.scale - gg.yoff;
+					m_drawline(0L, (long)cy0, (long)across, (long)cy0);
+					m_drawline((long)cx0, 0L, (long)cx0, baseline - 1L);
+					break;
+
+				case delete__:
+					choose_log_cursor(2);
+					break;
+
+				case copy_:
+					choose_log_cursor(1);
+					break;
+
+				case boxcursor:
+					choose_log_cursor(4);
+					break;
+
+				case paste:
+					choose_log_cursor(0);
+					cx0 = (cursx + gg.xoff + 2) / gg.scale;
+					cy0 = (cursy + gg.yoff + 2) / gg.scale;
+					m_saveclip();
+					m_clip(0L, 0L, (long)across, baseline - 1L);
+					gg.cx_min = cx0;
+					gg.cx_max = cx0 + copybuf.dxcopy;
+					gg.cy_min = cy0;
+					gg.cy_max = cy0 + copybuf.dycopy;
+					rect(gg.cx_min, gg.cy_min, gg.cx_max, gg.cy_max);
+					m_unclip();
+					break;
+
+				default:
+					break;
+			}
+		}
+		else
+		{
+			if (rabbits && !avoidrabbits && cursy < baseline)
+			{
+				choose_log_cursor(0);
+				if (cursx < 45)
+					m_bunny(0L, cursy - 17L);
+				else
+					m_bunny(cursx - 45L, cursy - 17L);
+			}
+			else if (gg.probemode)
+			{
+				choose_log_cursor(3);
+			}
+			else
+			{
+				choose_log_cursor(0);
+			}
+		}
+	}
+	if (chairflag)
+	{
+		if (rbandflag)
+		{
+			choose_log_cursor(0);
+			if (vlsi)
+				m_color((long)gg.color.wire[curwcolor - log_wcol_normal]);
+			else
+				m_color((long)gg.color.xwire);
+			m_drawline((long)cursx1, (long)cursy1, (long)cursx2, (long)cursy2);
+		}
+		else
+		{
+			choose_log_cursor(0);
+		}
+	}
+	oldcursortype = cursortype;
+	m_colormode(curcm);
+
+	/*and (cursy < baseline)*/
+}
+
+
+/*=================  HIDECURSOR  =================*/
+/*=                                              =*/
+/*=  Used to remove cursor from screen while     =*/
+/*=     drawing graphics.                        =*/
+/*=                                              =*/
+/*================================================*/
+
+static void hidecursor()
+{
+	if (cursorflag)
+		xorcursor();
+}
+
+
+static void hidecursor_hook()
+{
+	if (!cursorhide)
+		hidecursor();
+	cursorhide = true;
+}
+
+
+static void unhidecursor_hook()
+{
+	if (cursorhide)
+		hidecursor();
+	cursorhide = false;
+}
+
+
+static void hidecursorrect_hook(long x1, long y1, long x2, long y2)
+{
+	if (!cursorhide && x1 <= gg.cx_max && x2 >= gg.cx_min && y1 <= gg.cy_max &&
+			y2 >= gg.cy_min)
+		hidecursor_hook();
+}
+
+
+/*================  DRAWCURSOR  ==================*/
+/*=                                              =*/
+/*=  Position the cursor to a particular point   =*/
+/*=     (screen coordinates).                    =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawcursor(short x, short y)
+{
+	if (x != cursx || y != cursy || !cursorflag || cursortype != oldcursortype)
+	{
+		if (cursorflag && !cursorhide)
+			xorcursor();
+		cursx = x;
+		cursy = y;
+		cursx1 = chairx;
+		cursy1 = chairy;
+		cursx2 = x;
+		cursy2 = y;
+		chairflag = chairflag2;
+		if (chairflag)
+		{
+			chairflag = true;
+			fixxy(&cursx2, &cursy2);
+			rbandflag = (abs(cursx1 - cursx2) + abs(cursy1 - cursy2) >= gg.scale &&
+					hvline(cursx1, cursy1, &cursx2, &cursy2));
+		}
+		xorcursor();
+	}
+	else
+	{
+		if (!cursorflag && !cursorhide)
+			xorcursor();
+	}
+	cursorflag = true;
+	cursorhide = false;
+}
+
+/*=================  REMCURSOR  ==================*/
+/*=                                              =*/
+/*=  Take the cursor off the screen.             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void remcursor()
+{
+	prevcursorflag = cursorflag;
+	if (cursorflag)
+		xorcursor();
+	cursorflag = false;
+	cursorhide = false;
+}
+
+
+/*================  RESTORECURSOR  ===============*/
+/*=                                              =*/
+/*=  Restore the cursor to its previous on/off   =*/
+/*=     status.                                  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void restorecursor()
+{
+	if (prevcursorflag != cursorflag)
+		xorcursor();
+	cursorflag = prevcursorflag;
+}
+
+/*================  CLEARSCREEN  =================*/
+/*=                                              =*/
+/*=  Clear the screen.                           =*/
+/*=                                              =*/
+/*================================================*/
+
+static void clearscreen()
+{
+	remcursor();
+	m_noclip();
+	m_vsetcolors((long)gg.color.backgr, 1L, &rcolormap[gg.color.backgr],
+			&gcolormap[gg.color.backgr], &bcolormap[gg.color.backgr]);
+	m_color((long)gg.color.backgr);
+	m_fillrect(0L, 0L, (long)across, (long)down);
+	fixcolormap();
+	resetmessages();
+	bottomcount = 0;
+	gg.showpage = 0;
+}
+
+
+static void clearshowalpha()
+{
+	if (onescreen)
+		clearscreen();
+	printf("\f");
+	nk_gotoxy(0, 0);
+	noblink();
+	showalpha();
+}
+
+/*================  UDRAWGATEC  ==================*/
+/*=                                              =*/
+/*=  Draw a gate of specified color at a         =*/
+/*=     certain position (screen coordinates).   =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawvector2(log_vectorrec *v, long x1, long y1, long x2, long y2)
+{
+	long diam, savecol, coord;
+
+	switch (v->vkind)
+	{
+
+		case 'v':
+			m_drawline(x1, y1, x2, y2);
+			break;
+
+		case 'C':
+			diam = P_imax2(labs(x1 - x2), labs(y1 - y2));
+			switch (diam)
+			{
+
+				case 3:
+					if (x1 == x2)
+					{
+						coord = P_imin2(y1, y2);
+						m_move2(x1, coord);
+						m_draw(x1 + 2, coord + 1);
+						m_draw(x1 + 2, coord + 2);
+						m_draw(x1, coord + 3);
+						m_draw(x1 - 2, coord + 2);
+						m_draw(x1 - 2, coord + 1);
+						m_draw(x1, coord);
+					}
+					else if (y1 == y2)
+					{
+						coord = P_imin2(x1, x2);
+						m_move2(coord, y1);
+						m_draw(coord + 1, y1 + 2);
+						m_draw(coord + 2, y1 + 2);
+						m_draw(coord + 3, y1);
+						m_draw(coord + 2, y1 - 2);
+						m_draw(coord + 1, y1 - 2);
+						m_draw(coord, y1);
+					}
+					else
+					{
+						m_circle((x1 + x2) / 2, (y1 + y2) / 2, 1L);
+					}
+					break;
+
+				case 5:
+					if (x1 == x2)
+					{
+						coord = P_imin2(y1, y2);
+						m_move2(x1, coord);
+						m_draw(x1 + 3, coord + 1);
+						m_draw(x1 + 3, coord + 4);
+						m_draw(x1, coord + 5);
+						m_draw(x1 - 3, coord + 4);
+						m_draw(x1 - 3, coord + 1);
+						m_draw(x1, coord);
+					}
+					else if (y1 == y2)
+					{
+						coord = P_imin2(x1, x2);
+						m_move2(coord, y1);
+						m_draw(coord + 1, y1 + 3);
+						m_draw(coord + 4, y1 + 3);
+						m_draw(coord + 5, y1);
+						m_draw(coord + 4, y1 - 3);
+						m_draw(coord + 1, y1 - 3);
+						m_draw(coord, y1);
+					}
+					else
+					{
+						m_circle((x1 + x2) / 2, (y1 + y2) / 2, 2L);
+					}
+					break;
+
+				default:
+					m_circle((x1 + x2) / 2, (y1 + y2) / 2, diam / 2);
+					break;
+			}
+			break;
+
+		case 'e':
+			savecol = m_curcolor();
+			m_color(m_trans);
+			m_ellipse((x1 + x2) / 2, (y1 + y2) / 2, (x1 - x2) / 2, (y1 - y2) / 2,
+					savecol);
+			m_color(savecol);
+			break;
+
+		case 'E':
+			m_ellipse((x1 + x2) / 2, (y1 + y2) / 2, (x1 - x2) / 2, (y1 - y2) / 2,
+					m_curcolor());
+			break;
+
+		case 'r':   /*should do a true roundrect*/
+			m_drawrect(x1, y1, x2, y2);
+			break;
+	}
+}
+
+
+static void drawvector4(log_vectorrec *v, long x1, long y1, long x2, long y2, long x3, long y3, long x4, long y4)
+{
+	long xarr[4], yarr[4];
+
+	switch (v->vkind)
+	{
+
+		case 'c':
+			m_bezier(x1, y1, x2, y2, x3, y3, x4, y4);
+			break;
+
+		case 'F':
+			xarr[0] = x1;
+			yarr[0] = y1;
+			xarr[1] = x2;
+			yarr[1] = y2;
+			xarr[2] = x3;
+			yarr[2] = y3;
+			xarr[3] = x4;
+			yarr[3] = y4;
+			m_fillpoly(4L, (int *) xarr, (int *) yarr);
+			break;
+	}
+}
+
+
+#define big1            "0.,+123-456*789/\0()^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
+#define big2            "0.,\000123-456\000789 "
+
+
+static void drawtext(log_vectorrec *v, long scale, long rot, long xx, long yy)
+{
+	long sc, i, j, tx, ty;
+	char mode;
+	char buf[256];
+	long FORLIM;
+
+	sc = v->UU.U116.tsize * scale;
+	if (sc >= log_scale0 * 70)
+	{
+		tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
+			(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
+		ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
+			(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
+		i = strposc(v->UU.U116.sp, '$', 1L);
+		if (i > 0 && i < strlen(v->UU.U116.sp))
+		{
+			strcpy(buf, v->UU.U116.sp);
+			mode = 'X';
+			while (i <= strlen(buf)) {
+				if (buf[i - 1] == '$' && i < strlen(buf))
+				{
+					switch (toupper(buf[i]))
+					{
+
+						case '$':
+							strcpy_overlap(buf + i - 1, buf + i);
+							i++;
+							break;
+
+						case 'P':
+						case 'B':
+						case 'O':
+						case 'X':
+							mode = toupper(buf[i]);   /*close enough*/
+							strcpy_overlap(buf + i - 1, buf + i + 1);
+							break;
+
+						default:
+							i++;
+							break;
+					}
+					continue;
+				}
+				switch (mode)
+				{
+
+					case 'P':
+						j = strposc("0.,+123-456*789/E()^", buf[i - 1], 1L);
+						if (j > 0)
+							buf[i - 1] = (char)(j + 147);
+						break;
+
+					case 'B':
+						j = strposc("0.,+123-456*789/\0()^ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+								toupper(buf[i - 1]), 1L);
+						if (j > 20)
+							buf[i - 1] = (char)(j + 147);
+						else if (j > 0)
+							buf[i - 1] = (char)(j + 127);
+						break;
+
+					case 'O':
+						j = strposc("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
+								toupper(buf[i - 1]), 1L);
+						if (j > 0)
+							buf[i - 1] = (char)(j + 213);
+						break;
+				}
+				i++;
+			}
+			switch (tx)
+			{
+
+				case -1:
+					m_drawstr(xx, yy - (ty + 1) * 3, NULL, buf);
+					break;
+
+				case 0:
+					m_centerstr(xx, yy - (ty + 1) * 3, NULL, buf);
+					break;
+
+				case 1:
+					m_rightstr(xx, yy - (ty + 1) * 3, NULL, buf);
+					break;
+			}
+			return;
+		}
+		switch (tx)
+		{
+
+			case -1:
+				m_drawstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
+				break;
+
+			case 0:
+				m_centerstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
+				break;
+
+			case 1:
+				m_rightstr(xx, yy - (ty + 1) * 3, NULL, v->UU.U116.sp);
+				break;
+		}
+		return;
+	}
+	if (sc < log_scale0 * 40)
+		return;
+	if (sc >= log_scale0 * 50) {
+		if (!strsubset(v->UU.U116.sp, big1))
+			return;
+		buf[strlen(v->UU.U116.sp)] = '\0';
+		FORLIM = strlen(v->UU.U116.sp);
+		for (i = 0; i < FORLIM; i++) {
+			j = strposc(big1, v->UU.U116.sp[i], 1L);
+			if (j <= 20)
+				buf[i] = (char)(j + 127);
+			else if (j <= 46)
+				buf[i] = (char)(j + 147);
+			else if (j <= 72)
+				buf[i] = (char)(j + 121);
+			else
+				buf[i] = ' ';
+		}
+		tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
+			(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
+		ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
+			(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
+		switch (tx)
+		{
+
+			case -1:
+				m_drawstr(xx, yy - (ty + 2) * 2, NULL, buf);
+				break;
+
+			case 0:
+				m_centerstr(xx, yy - (ty + 2) * 2, NULL, buf);
+				break;
+
+			case 1:
+				m_rightstr(xx, yy - (ty + 2) * 2, NULL, buf);
+				break;
+		}
+		return;
+	}
+	if (!strsubset(v->UU.U116.sp, big2))
+		return;
+	buf[strlen(v->UU.U116.sp)] = '\0';
+	FORLIM = strlen(v->UU.U116.sp);
+	for (i = 0; i < FORLIM; i++)
+	{
+		j = strposc(big2, v->UU.U116.sp[i], 1L);
+		if (j <= 15)
+			buf[i] = (char)(j + 193);
+		else
+			buf[i] = ' ';
+	}
+	tx = (v->UU.U116.torg % 3 - 1) * log_rotxx[rot] +
+		(v->UU.U116.torg / 3 - 1) * log_rotyx[rot];
+	ty = (v->UU.U116.torg % 3 - 1) * log_rotxy[rot] +
+		(v->UU.U116.torg / 3 - 1) * log_rotyy[rot];
+	switch (tx)
+	{
+
+		case -1:
+			m_drawstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
+			break;
+
+		case 0:
+			m_centerstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
+			break;
+
+		case 1:
+			m_rightstr(xx, yy - (ty + 1) * 2 - 3, NULL, buf);
+			break;
+	}
+}
+
+#undef big1
+#undef big2
+
+
+static void plaindrawgatec(short x, short y, short g, short c)
+{
+	short i, z, rxx, rxy, ryx, ryy;
+	log_krec *k;
+	int hascolor;
+	short FORLIM;
+	log_vectorrec *WITH1;
+
+	k = kind[(g & (log_kindoffset - 1)) - 1];
+	z = log_scale0 * k->bbmax + 2;
+	if (x < -z || x > across + z || y < -z || y > down + z)
+		return;
+	hidecursor();
+	hascolor = (c != gg.color.backgr && c != gg.color.conflict);
+	m_color((long)c);
+	if (g < log_kindoffset)
+	{
+		FORLIM = k->numvects;
+		for (i = 0; i < FORLIM; i++)
+		{
+			WITH1 = &k->vector[i];
+			switch (WITH1->vkind)
+			{
+
+				case '1':
+					if (hascolor)
+						m_color((long)c);
+					break;
+
+				case '2':
+					if (hascolor)
+						m_color((long)gategreen);
+					break;
+
+				case '3':
+					if (hascolor)
+						m_color((long)gateyellow);
+					break;
+
+				case '4':
+					if (hascolor)
+						m_color((long)gatered);
+					break;
+
+				case '5':
+					if (hascolor)
+						m_color((long)gateorange);
+					break;
+
+				case '6':
+					if (hascolor)
+						m_color((long)gateblack);
+					break;
+
+				case '7':
+					if (hascolor)
+						m_color((long)gatewhite);
+					break;
+
+				case 'v':
+				case 'C':
+				case 'e':
+				case 'E':
+				case 'r':
+					drawvector2(&k->vector[i], (long)(x + WITH1->x1),
+							(long)(y + WITH1->y1), (long)(x + WITH1->UU.U99.x2),
+							(long)(y + WITH1->UU.U99.y2));
+					break;
+
+				case 'c':
+				case 'F':
+					drawvector4(&k->vector[i], (long)(x + WITH1->x1),
+							(long)(y + WITH1->y1), (long)(x + WITH1->UU.U99.x2),
+							(long)(y + WITH1->UU.U99.y2), (long)(x + WITH1->UU.U99.x3),
+							(long)(y + WITH1->UU.U99.y3), (long)(x + WITH1->UU.U99.x4),
+							(long)(y + WITH1->UU.U99.y4));
+					break;
+
+				case 't':
+					drawtext(&k->vector[i], (long)log_scale0, 0L, (long)(x + WITH1->x1),
+							(long)(y + WITH1->y1));
+					break;
+			}
+		}
+	}
+	else
+	{
+		z = g / log_kindoffset;
+		rxx = log_rotxx[z];
+		rxy = log_rotxy[z];
+		ryx = log_rotyx[z];
+		ryy = log_rotyy[z];
+		FORLIM = k->numvects;
+		for (i = 0; i < FORLIM; i++)
+		{
+			WITH1 = &k->vector[i];
+			switch (WITH1->vkind)
+			{
+
+				case '1':
+					if (hascolor)
+						m_color((long)c);
+					break;
+
+				case '2':
+					if (hascolor)
+						m_color((long)gategreen);
+					break;
+
+				case '3':
+					if (hascolor)
+						m_color((long)gateyellow);
+					break;
+
+				case '4':
+					if (hascolor)
+						m_color((long)gatered);
+					break;
+
+				case '5':
+					if (hascolor)
+						m_color((long)gateorange);
+					break;
+
+				case '6':
+					if (hascolor)
+						m_color((long)gateblack);
+					break;
+
+				case '7':
+					if (hascolor)
+						m_color((long)gatewhite);
+					break;
+
+				case 'v':
+				case 'C':
+				case 'e':
+				case 'E':
+				case 'r':
+					drawvector2(&k->vector[i],
+							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
+							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy),
+							(long)(x + WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx),
+							(long)(y + WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy));
+					break;
+
+				case 'c':
+				case 'F':
+					drawvector4(&k->vector[i],
+							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
+							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy),
+							(long)(x + WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx),
+							(long)(y + WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy),
+							(long)(x + WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx),
+							(long)(y + WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy),
+							(long)(x + WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx),
+							(long)(y + WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy));
+					break;
+
+				case 't':
+					drawtext(&k->vector[i], (long)log_scale0, (long)z,
+							(long)(x + WITH1->x1 * rxx + WITH1->y1 * ryx),
+							(long)(y + WITH1->x1 * rxy + WITH1->y1 * ryy));
+					break;
+			}
+		}
+	}
+	hidecursor();
+}
+
+
+static void udrawgatec(short x, short y, short g, short c)
+{
+	short i, z, rxx, rxy, ryx, ryy;
+	log_krec *k;
+	int hascolor;
+	short FORLIM;
+	log_vectorrec *WITH1;
+
+	if (g == 0)
+	{
+		hidecursor();
+		m_color((long)c);
+		m_drawpoint((long)x, (long)y);
+		hidecursor();
+		return;
+	}
+	k = kind[(g & (log_kindoffset - 1)) - 1];
+	if (k->bbmax <= maxsafescale)
+	{
+		plaindrawgatec(x, y, g, c);
+		return;
+	}
+	hascolor = (c != gg.color.backgr);
+	z = log_scale0 * k->bbmax + 2;
+	if (x < -z || x > across + z || y < -z || y > down + z)
+		return;
+	z = g / log_kindoffset;
+	rxx = log_rotxx[z] * maxsafescale;
+	rxy = log_rotxy[z] * maxsafescale;
+	ryx = log_rotyx[z] * maxsafescale;
+	ryy = log_rotyy[z] * maxsafescale;
+	hidecursor();
+	m_color((long)c);
+	FORLIM = k->numvects;
+	for (i = 0; i < FORLIM; i++)
+	{
+		WITH1 = &k->vector[i];
+		switch (WITH1->vkind)
+		{
+
+			case '1':
+				if (hascolor)
+					m_color((long)c);
+				break;
+
+			case '2':
+				if (hascolor)
+					m_color((long)gategreen);
+				break;
+
+			case '3':
+				if (hascolor)
+					m_color((long)gateyellow);
+				break;
+
+			case '4':
+				if (hascolor)
+					m_color((long)gatered);
+				break;
+
+			case '5':
+				if (hascolor)
+					m_color((long)gateorange);
+				break;
+
+			case '6':
+				if (hascolor)
+					m_color((long)gateblack);
+				break;
+
+			case '7':
+				if (hascolor)
+					m_color((long)gatewhite);
+				break;
+
+			case 'v':
+			case 'C':
+			case 'e':
+			case 'E':
+			case 'r':
+				drawvector2(&k->vector[i],
+						(long)(x + (WITH1->x1 * rxx + WITH1->y1 * ryx) / k->bbmax),
+						(long)(y + (WITH1->x1 * rxy + WITH1->y1 * ryy) / k->bbmax),
+						(long)(x + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / k->bbmax),
+						(long)(y + (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / k->bbmax));
+				break;
+
+			case 'c':
+			case 'F':
+				drawvector4(&k->vector[i], (long)(x + (WITH1->x1 * rxx +
+								WITH1->y1 * ryx) / k->bbmax), (long)
+						(y + (WITH1->x1 * rxy + WITH1->y1 * ryy) / k->bbmax), (long)
+						(x + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / k->bbmax),
+						(long)
+						(y + (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / k->bbmax),
+						(long)
+						(x + (WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx) / k->bbmax),
+						(long)
+						(y + (WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy) / k->bbmax),
+						(long)
+						(x + (WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx) / k->bbmax),
+						(long)
+						(y + (WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy) / k->bbmax));
+				break;
+		}
+	}
+	hidecursor();
+}
+
+
+/*=================  DRAWGATEC  ==================*/
+/*=                                              =*/
+/*=  Draw a gate of specified color at a         =*/
+/*=     certain position (grid coordinates).     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawgatedotsc(short x, short y, short g, short c)
+{
+	short i, z, rxx, rxy, ryx, ryy;
+	log_krec *WITH;
+	short FORLIM;
+
+	if (g == 0 || vlsi)
+		return;
+	m_color((long)c);
+	z = g / log_kindoffset;
+	if (z != 0)
+	{
+		rxx = log_rotxx[z];
+		rxy = log_rotxy[z];
+		ryx = log_rotyx[z];
+		ryy = log_rotyy[z];
+		WITH = kind[(g & (log_kindoffset - 1)) - 1];
+		FORLIM = WITH->numpins;
+		for (i = 0; i < FORLIM; i++)
+			point(x + WITH->pin[i].x * rxx + WITH->pin[i].y * ryx,
+					y + WITH->pin[i].x * rxy + WITH->pin[i].y * ryy);
+		return;
+	}
+	WITH = kind[(g & (log_kindoffset - 1)) - 1];
+	FORLIM = WITH->numpins;
+	for (i = 0; i < FORLIM; i++)
+		point(x + WITH->pin[i].x, y + WITH->pin[i].y);
+}
+
+
+static void drawgatec(short x, short y, short g, short c)
+{
+	short i, xx, yy, z, rxx, rxy, ryx, ryy;
+	long savecol;
+	int hascolor;
+	log_krec *WITH;
+	short FORLIM;
+	log_vectorrec *WITH1;
+
+	if (zoom == 0)
+	{
+		plaindrawgatec((int)(x * gg.scale - gg.xoff),
+				(int)(y * gg.scale - gg.yoff), g, c);
+	}
+	else
+	{
+		z = g / log_kindoffset;
+		rxx = log_rotxx[z] * gg.scale;
+		rxy = log_rotxy[z] * gg.scale;
+		ryx = log_rotyx[z] * gg.scale;
+		ryy = log_rotyy[z] * gg.scale;
+		xx = x * gg.scale - gg.xoff;
+		yy = y * gg.scale - gg.yoff;
+		hidecursor();
+		m_color((long)c);
+		hascolor = (c != gg.color.backgr && c != gg.color.conflict);
+		WITH = kind[(g & (log_kindoffset - 1)) - 1];
+		FORLIM = WITH->numvects;
+		for (i = 0; i < FORLIM; i++)
+		{
+			WITH1 = &WITH->vector[i];
+			switch (WITH1->vkind)
+			{
+
+				case '1':
+					if (hascolor)
+						m_color((long)c);
+					break;
+
+				case '2':
+					if (hascolor)
+						m_color((long)gategreen);
+					break;
+
+				case '3':
+					if (hascolor)
+						m_color((long)gateyellow);
+					break;
+
+				case '4':
+					if (hascolor)
+						m_color((long)gatered);
+					break;
+
+				case '5':
+					if (hascolor)
+						m_color((long)gateorange);
+					break;
+
+				case '6':
+					if (hascolor)
+						m_color((long)gateblack);
+					break;
+
+				case '7':
+					if (hascolor)
+						m_color((long)gatewhite);
+					break;
+
+				case 'v':
+				case 'r':
+					drawvector2(
+							&WITH->vector[i],
+							(long)(xx + (WITH1->x1 * rxx + WITH1->y1 * ryx) / log_scale0),
+							(long)(yy + (WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0),
+							(long)
+							(xx + (WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / log_scale0),
+							(long)
+							(yy +
+							 (WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / log_scale0));
+					break;
+
+				case 'C':
+					m_circle(xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx + (WITH1->y1 +
+									WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
+							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy + (WITH1->y1 + WITH1->
+									UU.U99.y2) * ryy) / (log_scale0 * 2L),
+							P_imax2((long)abs((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
+									(WITH1->y1 - WITH1->UU.U99.y2) * ryx),
+								(long)abs((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
+									(WITH1->y1 - WITH1->UU.U99.y2) * ryy)) /
+							(log_scale0 * 2));
+					break;
+
+				case 'e':
+					savecol = m_curcolor();
+					m_color(m_trans);
+					m_ellipse(
+							xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx +
+								(WITH1->y1 + WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
+							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy +
+								(WITH1->y1 + WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
+							((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
+							 (WITH1->y1 - WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
+							((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
+							 (WITH1->y1 - WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
+							savecol);
+					m_color(savecol);
+					break;
+
+				case 'E':
+					m_ellipse(
+							xx + ((WITH1->x1 + WITH1->UU.U99.x2) * rxx +
+								(WITH1->y1 + WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
+							yy + ((WITH1->x1 + WITH1->UU.U99.x2) * rxy +
+								(WITH1->y1 + WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
+							((WITH1->x1 - WITH1->UU.U99.x2) * rxx +
+							 (WITH1->y1 - WITH1->UU.U99.y2) * ryx) / (log_scale0 * 2L),
+							((WITH1->x1 - WITH1->UU.U99.x2) * ryx +
+							 (WITH1->y1 - WITH1->UU.U99.y2) * ryy) / (log_scale0 * 2L),
+							m_curcolor());
+					break;
+
+				case 'c':
+				case 'F':
+					drawvector4(&WITH->vector[i], (long)(xx + (WITH1->x1 * rxx +
+									WITH1->y1 * ryx) / log_scale0), (long)(yy +
+									(WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0), (long)(xx +
+										(WITH1->UU.U99.x2 * rxx + WITH1->UU.U99.y2 * ryx) / log_scale0),
+							(long)(yy +
+								(WITH1->UU.U99.x2 * rxy + WITH1->UU.U99.y2 * ryy) / log_scale0),
+							(long)(xx +
+								(WITH1->UU.U99.x3 * rxx + WITH1->UU.U99.y3 * ryx) / log_scale0),
+							(long)(yy +
+								(WITH1->UU.U99.x3 * rxy + WITH1->UU.U99.y3 * ryy) / log_scale0),
+							(long)(xx +
+								(WITH1->UU.U99.x4 * rxx + WITH1->UU.U99.y4 * ryx) / log_scale0),
+							(long)(yy + (WITH1->UU.U99.x4 * rxy + WITH1->UU.U99.y4 * ryy) /
+								log_scale0));
+					break;
+
+				case 't':
+					drawtext(&WITH->vector[i], (long)gg.scale, (long)z,
+							(long)(xx + (WITH1->x1 * rxx + WITH1->y1 * ryx) / log_scale0),
+							(long)(yy + (WITH1->x1 * rxy + WITH1->y1 * ryy) / log_scale0));
+					break;
+			}
+		}
+		hidecursor();
+	}
+	if ((c == gg.color.gate || c == gg.color.dimgate) && !suppressdots)
+		drawgatedotsc(x, y, g, gg.color.gatepin);
+}
+
+
+static void signallabel(short x, short y, short gtype, short sig, short c)
+{
+	log_krec *k;
+	char STR1[256];
+
+	k = kind[(gtype & (log_kindoffset - 1)) - 1];
+	if (!(sig != 0 && k->flag.U3.named))
+		return;
+	remcursor();
+	m_color((long)c);
+	if (k->flag.U3.nright != (gtype / log_kindoffset == 0))
+		drawstr2((int)(x - m_strwidth(NULL,
+						strrtrim(strcpy(STR1, gg.signaltab[sig - 1].name))) + NAMEGAP),
+				y - 3, gg.signaltab[sig - 1].name);
+	else
+		drawstr2(x - NAMEGAP, y - 3, gg.signaltab[sig - 1].name);
+}
+
+
+static void gsignallabel(short x, short y, log_grec *g, short c)
+{
+	signallabel((int)(x * gg.scale - gg.xoff), (int)(y * gg.scale - gg.yoff),
+			g->g, g->sig, c);
+}
+
+
+typedef enum {inside,north,east,south,west} placement;
+
+static void drawpnums(log_grec *g, short c)
+{
+	short rxx, rxy, ryx, ryy, i, j, k;
+	char s[7];
+	log_krec *WITH;
+	short FORLIM, FORLIM1;
+	int tx,ty,ex,ey;
+	int minx,miny,maxx,maxy;
+	placement p = inside;
+	long hw;
+
+	if (zoom <= 0 || gg.textinvisible || gg.pnuminvisible)
+		return;
+	m_color((long)c);
+	rxx = log_rotxx[g->rot];
+	rxy = log_rotxy[g->rot];
+	ryx = log_rotyx[g->rot];
+	ryy = log_rotyy[g->rot];
+	WITH = g->kind;
+
+	/* use grab rectangle to determine which edge this pin is attached to. */
+	minx = ( WITH->x1 * rxx + WITH->y1 * ryx);
+	miny = ( WITH->x1 * rxy + WITH->y1 * ryy);
+	maxx = ( WITH->x2 * rxx + WITH->y2 * ryx);
+	maxy = ( WITH->x2 * rxy + WITH->y2 * ryy);
+
+	FORLIM = WITH->numpnums;
+	for (i = 0; i < FORLIM; i++)
+	{
+		sprintf(s, "%d", WITH->pnum[i].num);
+		hw = strlen(s) * 5 / 2;
+		ex = (WITH->pnum[i].x * rxx + WITH->pnum[i].y * ryx);
+		ey = (WITH->pnum[i].x * rxy + WITH->pnum[i].y * ryy);
+		if (ex < minx)
+		{
+			p = west;
+		}
+		else if (ex > maxx)
+		{
+			p = east;
+		}
+		else if (ey < miny)
+		{
+			p = north;
+		}
+		else if (ey > maxy)
+		{
+			p = south;
+		}
+		tx = g->x * gg.scale + ex * gg.scale / log_scale0 - gg.xoff;
+		ty = g->y * gg.scale + ey * gg.scale / log_scale0 - gg.yoff;
+		switch (p)
+		{
+			case west:
+				tx -= 5;
+				break;
+			case east:
+				tx += 5;
+				break;
+			case north:
+				tx -= hw;
+				ty -= 9;
+				break;
+			case south:
+				tx -= hw;
+				ty += 5;
+				break;
+
+			default:
+				break;
+		}
+
+		if (p == west)
+			m_rightstr(tx,ty,NULL,s);
+		else
+			m_drawstr(tx,ty,NULL,s);
+	}
+}
+
+#undef fromtab
+#undef totab
+
+
+static void setscale (short s);
+
+
+static void kdrawgatec(short i, short c)
+{
+	short x, y;
+	short ozoom = zoom;
+
+	x = (i - 1) * kindgroupspacing + kindgroupstart;
+	y = (down + baseline) / 2;
+	udrawgatec(x, y, kindgroup[i - 1], c);
+	setscale(0);
+	if (kindgroup[i - 1] != 0)
+		signallabel(x, y, kindgroup[i - 1], kindsig[i - 1], c);
+	setscale(ozoom);
+}
+
+
+/*=================  DRAWGATEX  ==================*/
+/*=                                              =*/
+/*=  Draw a gate.  If it is a TO or FROM gate,   =*/
+/*=     draw its name as well.                   =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawgatexc(log_grec *g, short c)
+{
+	if (g->dimcolor && c == gg.color.gate)
+		c = gg.color.dimgate;
+	drawgatec(g->x, g->y, g->g, c);
+	if (!gg.textinvisible)
+		gsignallabel(g->x, g->y, g, gg.color.signal);
+	if (g->kind->numpnums > 0)
+		drawpnums(g, gg.color.pinnum);
+}
+
+
+static void drawgatex(log_grec *g)
+{
+	drawgatexc(g, gg.color.gate);
+}
+
+
+static void setdimgate(log_grec *g, int dim)
+{
+	log_grec *g1;
+
+	if (g->dimcolor == dim)
+		return;
+	g->dimcolor = dim;
+	if (gg.showpage <= 0)
+		return;
+	g1 = gg.gbase[gg.showpage - 1];
+	while (g1 != NULL && g1 != g)
+		g1 = g1->next;
+	if (g1 != g)
+		return;
+	m_saveclip();
+	clipon();
+	drawgatex(g);
+	m_unclip();
+}
+
+/*================  DRAWSOLDERC  =================*/
+/*=                                              =*/
+/*=  Draw a solder point at a certain position   =*/
+/*=     (grid coordinates).                      =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawsolderc(short x, short y, short c)
+{
+	if (!showsolder)
+		return;
+	if (vlsi)
+	{
+		if (c == gg.color.conflict || c == gg.color.backgr)
+			m_color((long)c);
+		else
+			m_color((long)gg.color.vlsicut);
+		x = x * gg.scale - gg.xoff;
+		y = y * gg.scale - gg.yoff;
+		m_drawline(x - 3L, y - 3L, x + 3L, y + 3L);
+		m_drawline(x - 3L, y + 3L, x + 3L, y - 3L);
+		m_drawline(x - 2L, y - 3L, x + 4L, y + 3L);
+		m_drawline(x - 2L, y + 3L, x + 4L, y - 3L);
+		return;
+	}
+	m_color((long)c);
+	x = x * gg.scale - gg.xoff;
+	y = y * gg.scale - gg.yoff;
+	m_drawline(x - 1L, y - 2L, x + 1L, y - 2L);
+	m_drawline(x - 2L, y - 1L, x + 2L, y - 1L);
+	m_drawline(x - 2L, (long)y, x + 2L, (long)y);
+	m_drawline(x - 2L, y + 1L, x + 2L, y + 1L);
+	m_drawline(x - 1L, y + 2L, x + 1L, y + 2L);
+}
+
+
+/*=================  DRAWTRANSC  =================*/
+/*=                                              =*/
+/*=  Draw a VLSI transistor at a certain         =*/
+/*=     position (grid coordinates).             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawtransc(short x, short y, short c)
+{
+	if (!vlsi)
+		return;
+	if (c == gg.color.solder)
+		m_color((long)gg.color.vlsicut);
+	else
+		m_color((long)c);
+	x = x * gg.scale - gg.xoff;
+	y = y * gg.scale - gg.yoff;
+	m_circle((long)x, (long)y, 4L);
+}
+
+/*==================  DRAWBOXC  ==================*/
+/*=                                              =*/
+/*=  Draw a dashed box on the screen.            =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawboxc0(short x1, short y1, short x2, short y2, short c)
+{
+	m_color((long)c);
+	m_linestyle(1L);
+	rect(x1, y1, x2, y2);
+	m_linestyle(0L);
+}
+
+
+static void drawboxc(log_brec *b, short  c)
+{
+	drawboxc0(b->x1, b->y1, b->x2, b->y2, c);
+}
+
+
+/*================  DRAWMARKERSC  ================*/
+/*=                                              =*/
+/*=  Draw the printing markers on the screen.    =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawmarkersc(short c)
+{
+	clipon();
+	m_color((long)c);
+	hline(gg.markerx1, gg.markerx1 + 2, gg.markery1);
+	vline(gg.markerx1, gg.markery1, gg.markery1 + 2);
+	hline(gg.markerx2 - 2, gg.markerx2, gg.markery2);
+	vline(gg.markerx2, gg.markery2 - 2, gg.markery2);
+	clipoff();
+}
+
+
+/*=================  DRAWNODEC  ==================*/
+/*=                                              =*/
+/*=  Draw all wires and solder points in a       =*/
+/*=     particular node, in color C.             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawnodec(log_nrec *n, short c)
+{
+	log_hwrec *hw;
+	log_vwrec *vw;
+	log_srec *s;
+
+	if (gg.invisible || (gg.showconflicts == true && n->conflict == false))
+		return;
+
+	hidecursor();
+	if ((unsigned)c > 15)
+	{
+		if (gg.glowmode && gg.showpage > 0)
+			c = glowcol(n, (long)gg.color.wire[0]);
+		else
+			c = gg.color.wire[0];
+	}
+	if (vlsi && c == gg.color.wire[0])
+	{
+		hw = gg.hwbase[gg.curpage - 1];
+		while (hw != NULL)
+		{
+			if (hw->node == n && hw != gg.movinghw)
+			{
+				m_color((long)gg.color.wire[hw->wcolr - log_wcol_normal]);
+				hline(hw->x1, hw->x2, hw->y);
+			}
+			hw = hw->next;
+		}
+		vw = gg.vwbase[gg.curpage - 1];
+		while (vw != NULL)
+		{
+			if (vw->node == n && vw != gg.movingvw)
+			{
+				m_color((long)gg.color.wire[vw->wcolr - log_wcol_normal]);
+				vline(vw->x, vw->y1, vw->y2);
+			}
+			vw = vw->next;
+		}
+	}
+	else
+	{
+		m_color((long)c);
+		hw = gg.hwbase[gg.curpage - 1];
+		while (hw != NULL) {
+			if (hw->node == n && hw != gg.movinghw)
+				hline(hw->x1, hw->x2, hw->y);
+			hw = hw->next;
+		}
+		vw = gg.vwbase[gg.curpage - 1];
+		while (vw != NULL)
+		{
+			if (vw->node == n && vw != gg.movingvw)
+				vline(vw->x, vw->y1, vw->y2);
+			vw = vw->next;
+		}
+	}
+	if (showsolder)
+	{
+		s = gg.sbase[gg.curpage - 1];
+		while (s != NULL)
+		{
+			if ((s->hwire != NULL && s->hwire->node == n) ||
+					(s->vwire != NULL && s->vwire->node == n))
+				drawsolderc(s->x, s->y, c);
+			s = s->next;
+		}
+	}
+	hidecursor();
+}
+
+
+/*=================  DRAWNODE  ===================*/
+/*=                                              =*/
+/*=  Draw all wires and solder points in a       =*/
+/*=     particular node.                         =*/
+/*=                                              =*/
+/*================================================*/
+
+static void drawnode(log_nrec *n)
+{
+	drawnodec(n, -1);
+}
+
+/*================  REFRPAGEDISP  ================*/
+/*=                                              =*/
+/*=  Refresh the page-number display.            =*/
+/*=                                              =*/
+/*================================================*/
+
+static int pageempty (int pg);
+
+
+static void refrpagedisp()
+{
+	short num;
+
+	m_color((long)gg.color.page1);
+	drawstr2(across - 49, 2, "PAGE");
+	m_color((long)gg.color.page2);
+	drawnum2(across - 14, 2, (int)gg.curpage);
+	m_color((long)gg.color.page3);
+	drawstr2(across - 35, 14, "OF");
+	m_color((long)gg.color.page4);
+	num = gg.numpages;
+	while (num > gg.curpage && pageempty(num))
+		num--;
+	drawnum2(across - 14, 14, num);
+}
+
+
+/*================  REFREDITMODE  ================*/
+/*=                                              =*/
+/*=  Refresh the editing mode in the menus.      =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refreditmode()
+{
+	hidecursor();
+	m_color((long)gg.color.backgr);
+	m_fillrect(across + menux4 - 1L, line2 - 2L, across + menux4 + 30L,
+			line2 + 9L);
+	switch (cureditmode)
+	{
+
+		case 1:
+			m_color((long)gg.color.menuword);
+			drawstr2(across + menux4, line2, "ROT");
+			break;
+
+		case 2:
+			m_color((long)gg.color.menuword);
+			drawstr2(across + menux4, line2, "MIR-");
+			break;
+
+		case 3:
+			m_color((long)gg.color.menuword);
+			drawstr2(across + menux4, line2, "MIR|");
+			break;
+
+		case 4:
+			m_color((long)gg.color.selword);
+			drawstr2(across + menux4, line2, "CNFG");
+			break;
+	}
+	hidecursor();
+}
+
+
+/*===============  REFRBASELINE  =================*/
+/*=                                              =*/
+/*=  Refresh the baseline to the correct color.  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refrbaseline(int always)
+{
+	short c;
+
+	if (anyconflicts)
+		c = gg.color.conflict;
+	else
+		c = gg.baselinecolor;
+	if (!(c != gg.color.curbaseline || always))
+		return;
+	clipoff();
+	gg.color.curbaseline = c;
+	hidecursor();
+	m_color((long)c);
+	m_fillrect(0L, (long)baseline, (long)kindgroupleft, baseline + 1L);
+	m_fillrect((long)kindgroupright, (long)baseline, (long)across,
+			baseline + 1L);
+	hidecursor();
+}
+
+
+#define rtn             "REFRESH"
+
+
+/*===================  REFRESH  ==================*/
+/*=                                              =*/
+/*=  Refresh the screen (does not clear, so may  =*/
+/*=     be used to "clean up" existing screen).  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refresh()
+{
+	long x1, y1, x2, y2;
+	log_grec *g;
+	log_hwrec *hw;
+	log_vwrec *vw;
+	log_nrec *n;
+	log_srec *s;
+	log_lrec *l;
+	log_brec *b;
+
+	stamp(&gg.refrstamp);
+	gg.showpage = gg.curpage;
+	showsolder = (zoom > -1 && (vlsi || !gg.glowmode || glowsolder));
+	x1 = (gg.xoff - 30) / gg.scale;
+	y1 = (gg.yoff - 30) / gg.scale;
+	x2 = (gg.xoff + across + 30) / gg.scale;
+	y2 = (gg.yoff + down + 30) / gg.scale;
+	refrtimer = -1;
+	remcursor();
+	clipon();
+	refrpagedisp();
+	if (!gg.invisible && !gg.showconflicts)
+	{
+		working();
+		suppressdots = gg.dotsvisible;
+		g = gg.gbase[gg.curpage - 1];
+		while (g != NULL)
+		{
+			if (P_ibetweenm(x1, (long)g->x, x2, (long)g->kind->bbmax) &&
+					P_ibetweenm(y1, (long)g->y, y2, (long)g->kind->bbmax))
+				drawgatex(g);
+			g = g->next;
+		}
+		suppressdots = false;
+		working();
+		if (gg.glowmode)
+		{
+			hw = gg.hwbase[gg.curpage - 1];
+			while (hw != NULL)
+			{
+				if (hw->y > y1 && hw->y < y2 && hw != gg.movinghw)
+				{
+					m_color(glowcol(hw->node,
+								(long)gg.color.wire[hw->wcolr - log_wcol_normal]));
+					hline(hw->x1, hw->x2, hw->y);
+				}
+				hw = hw->next;
+			}
+			working();
+			vw = gg.vwbase[gg.curpage - 1];
+			while (vw != NULL)
+			{
+				if (vw->x > x1 && vw->x < x2 && vw != gg.movingvw)
+				{
+					m_color(glowcol(vw->node,
+								(long)gg.color.wire[vw->wcolr - log_wcol_normal]));
+					vline(vw->x, vw->y1, vw->y2);
+				}
+				vw = vw->next;
+			}
+			working();
+			if (showsolder)
+			{
+				s = gg.sbase[gg.curpage - 1];
+				while (s != NULL)
+				{
+					if (s->hwire != NULL)
+						n = s->hwire->node;
+					else
+						n = s->vwire->node;
+					drawsolderc(s->x, s->y, (int)glowcol(n, (long)gg.color.solder));
+					s = s->next;
+				}
+			}
+		}
+		else
+		{
+			m_color((long)gg.color.wire[0]);
+			hw = gg.hwbase[gg.curpage - 1];
+			while (hw != NULL)
+			{
+				if (hw->y > y1 && hw->y < y2 && hw != gg.movinghw)
+				{
+					if (vlsi)
+						m_color((long)gg.color.wire[hw->wcolr - log_wcol_normal]);
+					hline(hw->x1, hw->x2, hw->y);
+				}
+				hw = hw->next;
+			}
+			working();
+			vw = gg.vwbase[gg.curpage - 1];
+			while (vw != NULL)
+			{
+				if (vw->x > x1 && vw->x < x2 && vw != gg.movingvw)
+				{
+					if (vlsi)
+						m_color((long)gg.color.wire[vw->wcolr - log_wcol_normal]);
+					vline(vw->x, vw->y1, vw->y2);
+				}
+				vw = vw->next;
+			}
+			working();
+			if (showsolder)
+			{
+				s = gg.sbase[gg.curpage - 1];
+				while (s != NULL)
+				{
+					if (s->hwire != NULL)
+						n = s->hwire->node;
+					else
+						n = s->vwire->node;
+					drawsolderc(s->x, s->y, gg.color.solder);
+					s = s->next;
+				}
+			}
+		}
+
+		if (gg.dotsvisible)
+		{
+			g = gg.gbase[gg.curpage - 1];
+			while (g != NULL)
+			{
+				if (g->x > x1 && g->x < x2 && g->y > y1 && g->y < y2)
+					drawgatedotsc(g->x, g->y, g->g, gg.color.gatepin);
+				g = g->next;
+			}
+		}
+	}
+	else
+	{
+		working();
+		g = gg.gbase[gg.curpage - 1];
+		while (g != NULL)
+		{
+			if (g->kind->flag.U3.visible)
+				drawgatex(g);
+			g = g->next;
+		}
+	}
+	working();
+	if (!gg.textinvisible)
+	{
+		b = gg.bbase[gg.curpage - 1];
+		while (b != NULL)
+		{
+			drawboxc(b, gg.color.dashbox);
+			b = b->next;
+		}
+		working();
+		l = gg.lbase[gg.curpage - 1];
+		m_color((long)gg.color.labeltext);
+		while (l != NULL)
+		{
+			if (l->y > y1 && l->y < y2)
+			{
+				m_drawstr(l->x * gg.scale - gg.xoff, l->y * gg.scale - gg.yoff + 2,
+						logfont_lfont, l->name);
+			}
+			l = l->next;
+		}
+	}
+	working();
+	if (gg.markers)
+		drawmarkersc(gg.color.marker);
+	if (memavail() < memtolerance)
+		message("Low on memory!");
+	clipoff();
+	restorecursor();
+}
+
+#undef rtn
+
+
+/*=================  REFRESHSOON  ================*/
+/*=                                              =*/
+/*=  Screen is messed up, so refresh it as soon  =*/
+/*=     as the user stops moving around.         =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refreshsoon()
+{
+	refrtimer0 = refrdelay;
+	refrtimer = refrdelay;
+	gg.refrflag = true;
+}
+
+/*==================  REFRMENU  ==================*/
+/*=                                              =*/
+/*=  Clear and redraw menu area of screen.       =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refrmenu()
+{
+	short i, FORLIM;
+
+	working();
+	remcursor();
+	uerase(0, baseline + 2, across, down);
+	clipoff();
+	refrbaseline(true);
+	m_color((long)gg.color.backgr);
+	m_fillrect(kindgroupleft + 1L, (long)baseline, kindgroupright - 1L,
+			baseline + 1L);
+	m_color((long)gg.color.menuword);
+	drawstr2(menux1, line1, "Frills");
+	drawstr2(menux2, line1, "Editing");
+	drawstr2(menux1, line2, "HELP");
+	drawstr2(menux2, line2, "CAT");
+	drawstr2(across + menux3, line1, "Cursor");
+	drawstr2(across + menux4, line1, "Misc");
+	refreditmode();
+	if (modeflag)
+		log_setmode(modename);
+	else
+		log_setmode("");
+	FORLIM = kindgroupsize;
+	for (i = 1; i <= FORLIM; i++)
+		kdrawgatec(i, gg.color.kindgate);
+}
+
+
+static void beginbottom()
+{
+	remcursor();
+	clipoff();
+	bottomcount++;
+	if (m_autoraise)
+	{
+		clearshowalpha();
+	}
+	else
+	{
+		clearalpha();
+	}
+	nk_gotoxy(0, txdown - 1);
+}
+
+
+static void endbottom()
+{
+	remcursor();
+	bottomcount--;
+	if (m_autoraise)
+	{
+		if (bottomcount < 1)   /* fix from WES */
+		{
+			bottomcount =0;
+			m_graphics_on();
+		}
+	}
+	else
+	{
+		m_graphics_on();   /* switch back to the graphics window */
+	}
+	clearalpha();
+}
+
+/*================  REFRSCREEN1  =================*/
+/*=                                              =*/
+/*=  Clear and redraw working area of screen.    =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refrscreen1()
+{
+	m_colormode((long)m_normal);
+	m_noclip();
+	remcursor();
+	uerase(0, 0, across, baseline - 1);
+	resetmessages();
+	refresh();
+	gg.refrflag = true;
+}
+
+
+/*=================  REFRSCREEN  =================*/
+/*=                                              =*/
+/*=  Clear and redraw entire screen.             =*/
+/*=                                              =*/
+/*================================================*/
+
+static void refrscreen()
+{
+	gg.showpage = gg.curpage;
+	bottomcount = 0;
+	m_colormode((long)m_normal);
+	m_noclip();
+	fixcolormap();
+	clearalpha();
+	refrmenu();
+	refrscreen1();
+	m_graphics_on();
+}
+
+static void resize_screen()
+{
+	initscreen2();
+	initscreen();
+}
+
+/*=================  SHOWCATALOG  ================*/
+/*=                                              =*/
+/*=  Switch screen to catalog (TRUE) or circuit  =*/
+/*=     (FALSE).                                 =*/
+/*=                                              =*/
+/*================================================*/
+
+static void showcatalog()
+{
+	short i;
+	catboxrec *cb;
+	short x1, y1, x2, y2, FORLIM;
+
+	clearscreen();
+	gg.showpage = log_page_cat;
+	FORLIM = maxkinds;
+	for (i = 1; i <= FORLIM; i++)
+	{
+		if (kind[i - 1] != NULL)
+		{
+			udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
+					(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
+					gg.color.catgate);
+		}
+	}
+	cb = catboxes;
+	while (cb != NULL)
+	{
+		x1 = (cb->pos - 1) % catwidth * gridcen * 2;
+		y1 = (cb->pos - 1) / catwidth * gridcen * 2;
+		x2 = ((cb->pos + cb->count - 2) % catwidth + 1) * gridcen * 2;
+		y2 = ((cb->pos + cb->count - 2) / catwidth + 1) * gridcen * 2;
+		m_color((long)catboxcolor);
+		m_linestyle(2L);
+		m_drawline((long)x1, (long)y1, (long)x2, (long)y1);
+		m_linestyle(2L);
+		m_drawline((long)x1, (long)y2, (long)x2, (long)y2);
+		m_linestyle(2L);
+		m_drawline((long)x1, (long)y1, (long)x1, (long)y2);
+		m_linestyle(2L);
+		m_drawline((long)x2, (long)y1, (long)x2, (long)y2);
+		m_linestyle(0L);
+		cb = cb->next;
+	}
+}
+
+
diff --git a/log/src/tool.c b/log/src/tool.c
new file mode 100644
index 0000000..017c6c1
--- /dev/null
+++ b/log/src/tool.c
@@ -0,0 +1,200 @@
+
+#include <log/log.h>
+
+static void newtool(log_tool **t, char *name)
+{
+	log_tool *t2;
+
+	*t = (log_tool *)Malloc(sizeof(log_tool));
+	strcpy((*t)->name, name);
+	(*t)->ready = false;
+	(*t)->simulator = false;
+	(*t)->keep = false;
+	(*t)->nostatus = false;
+	(*t)->fname = NULL;
+	(*t)->comment = (char *)Malloc(256);
+	*(*t)->comment = '\0';
+	(*t)->info = (na_long)0;
+	(*t)->nlbl = NULL;
+	(*t)->hlbl = NULL;
+	(*t)->shortname = (char *)Malloc(33);
+	strcpy((*t)->shortname, name);
+	stamp(&(*t)->netstamp);
+	(*t)->deltatime = 0.0;
+	t2 = gg.toolbase;
+	while (t2 != NULL && t2->next != NULL)
+		t2 = t2->next;
+	if (t2 == NULL)
+		gg.toolbase = *t;
+	else
+		t2->next = *t;
+	(*t)->next = NULL;
+}
+
+
+static log_tool *findtool(char *name_)
+{
+	log_tool *Result;
+	char name[17];
+	log_tool *lp;
+	char savefunc[17];
+	char saveargs[256];
+	char suffix[51];
+	void (*proc) (log_action_t *act);
+	int ready;
+	cnfrec *cnfp;
+
+	strcpy(name, name_);
+	strcpy(savefunc, gg.func);
+	strcpy(saveargs, gg.funcarg);
+	lp = gg.toolbase;
+	while (lp != NULL && strcmp(lp->name, name))
+		lp = lp->next;
+	if (lp == NULL)
+		newtool(&lp, name);
+	if (!lp->ready)
+	{
+		sprintf(suffix, "LOG_%s_PROC", name);
+		ready = newci_findprocedure2(suffix, (void(**) ())(&proc));
+		if (gg.traceflag)
+			fprintf(tracefile, "Findtool to load: %s -  %s.\n", suffix, lp->fname);
+
+		if (!ready && lp->fname != NULL)
+		{
+			TRY(try2);
+			newci_fixfname(lp->fname, "code", "");
+			if (gg.traceflag)
+				fprintf(tracefile, "Findtool, loading %s\n", lp->fname);
+			newci_loadprogram(lp->fname);
+			RECOVER(try2);
+			if (P_escapecode == -20)
+				_Escape(P_escapecode);
+			ENDTRY(try2);
+			ready = newci_findprocedure2(suffix, (void(**) ())(&proc));
+			if (gg.traceflag)
+				fprintf(tracefile, "Findtool, ready=%s\n", ready ? " TRUE" : "FALSE");
+		}
+
+		if (ready)
+		{
+			lp->proc = proc;
+			gg.action = act_init;
+			gg.acttool = lp;
+			(*proc)(&gg);
+			if (lp->ready)
+			{
+				cnfp = cnfbase;
+				while (cnfp != NULL)
+				{
+					if (!strcmp(cnfp->tool, name))
+					{
+						doingcnffunction = true;
+						gg.action = act_cnf;
+						strcpy(gg.funcarg, cnfp->s);
+						getword(gg.funcarg, gg.func);
+						(*proc)(&gg);
+						doingcnffunction = false;
+					}
+					cnfp = cnfp->next;
+				}
+				gg.action = act_color;
+				(*proc)(&gg);
+				gg.action = act_endinit;
+				(*proc)(&gg);
+				lp->nexttstep = 0.0;
+				lp->nnumattrs = 0;
+				lp->nattr = NULL;
+				if (lp->nlbl != NULL)
+					parselabel(&lp->nlbl, &lp->nnumattrs, &lp->nattr);
+				lp->hnumattrs = 0;
+				lp->hattr = NULL;
+				if (lp->hlbl != NULL)
+					parselabel(&lp->hlbl, &lp->hnumattrs, &lp->hattr);
+			}
+		}
+	}
+	Result = lp;
+	strcpy(gg.func, savefunc);
+	strcpy(gg.funcarg, saveargs);
+	return Result;
+}
+
+
+static void calltool(log_tool *t, log_actionkinds act)
+{
+	log_tool *savetool;
+
+	savetool = gg.acttool;
+	gg.action = act;
+	gg.acttool = t;
+	(*t->proc)(&gg);
+	gg.acttool = savetool;
+}
+
+
+static void calltoolgate(log_grec *g, log_actionkinds act)
+{
+	gg.actgate = g;
+	calltool(g->kind->simtype, act);
+}
+
+
+static void calltoolnode(log_nrec *n, log_actionkinds act)
+{
+	gg.actnode = n;
+	calltool(n->simtype, act);
+}
+
+static void calltoolkind(log_krec *k, log_actionkinds act)
+{
+	gg.actkind = k;
+	calltool(k->simtype, act);
+}
+
+static void calltools(log_actionkinds act)
+{
+	log_tool *tp;
+
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		if (tp->ready)
+			calltool(tp, act);
+		tp = tp->next;
+	}
+}
+
+
+static void callsimtools(log_actionkinds act)
+{
+	log_tool *tp;
+
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		if (tp->ready && tp->simulator)
+			calltool(tp, act);
+		tp = tp->next;
+	}
+}
+
+static void closetool(log_tool *tp)
+{
+	if (tp->ready)
+		calltool(tp, act_exit);
+	tp->ready = false;
+}
+
+
+static void closetools()
+{
+	log_tool *tp;
+
+	tp = gg.toolbase;
+	while (tp != NULL)
+	{
+		closetool(tp);
+		tp = tp->next;
+	}
+}
+
diff --git a/log/src/wire.c b/log/src/wire.c
new file mode 100644
index 0000000..fc378ab
--- /dev/null
+++ b/log/src/wire.c
@@ -0,0 +1,663 @@
+
+#include <p2c/p2c.h>
+
+/*===================  NEWHW  ====================*/
+/*=                                              =*/
+/*=  Create a Horizontal Wire.                   =*/
+/*=                                              =*/
+/*================================================*/
+
+static void newhw(log_hwrec **hw)
+{
+	*hw = (log_hwrec *)Malloc(sizeof(log_hwrec));
+	(*hw)->next = gg.hwbase[gg.curpage - 1];
+	gg.hwbase[gg.curpage - 1] = *hw;
+	(*hw)->temp = (na_long)0;
+}
+
+
+#define rtn             "DISPHW"
+
+
+/*==================  DISPHW  ====================*/
+/*=                                              =*/
+/*=  Dispose of a Horizontal Wire.               =*/
+/*=                                              =*/
+/*================================================*/
+
+static void disphw(log_hwrec **hw)
+{
+	log_hwrec *hw1;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Dispose hwire %ld\n", (long)(*hw));
+	if (*hw == NULL)
+		return;
+	hw1 = gg.hwbase[gg.curpage - 1];
+	if (*hw == hw1)
+	{
+		gg.hwbase[gg.curpage - 1] = (*hw)->next;
+	}
+	else
+	{
+		while (hw1 != NULL && hw1->next != *hw)
+			hw1 = hw1->next;
+		if (hw1 == NULL)
+			report(10, rtn);
+		else
+			hw1->next = (*hw)->next;
+	}
+	chpageplace((int)gg.curpage, (*hw)->x1, (*hw)->y, (*hw)->x2, (*hw)->y);
+	Free(*hw);
+}
+
+#undef rtn
+
+
+/*===================  NEWVW  ====================*/
+/*=                                              =*/
+/*=  Create a Vertical Wire.                     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void newvw(log_vwrec **vw)
+{
+	*vw = (log_vwrec *)Malloc(sizeof(log_vwrec));
+	(*vw)->next = gg.vwbase[gg.curpage - 1];
+	gg.vwbase[gg.curpage - 1] = *vw;
+	(*vw)->temp = (na_long)0;
+}
+
+
+#define rtn             "DISW"
+
+
+/*==================  DISW  ====================*/
+/*=                                              =*/
+/*=  Dispose of a Vertical Wire.                 =*/
+/*=                                              =*/
+/*================================================*/
+
+static void dispvw(log_vwrec **vw)
+{
+	log_vwrec *vw1;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Dispose vwire %ld\n", (long)(*vw));
+	if (*vw == NULL)
+		return;
+	vw1 = gg.vwbase[gg.curpage - 1];
+	if (*vw == vw1)
+	{
+		gg.vwbase[gg.curpage - 1] = (*vw)->next;
+	}
+	else
+	{
+		while (vw1 != NULL && vw1->next != *vw)
+			vw1 = vw1->next;
+		if (vw1 == NULL)
+			report(10, rtn);
+		else
+			vw1->next = (*vw)->next;
+	}
+	chpageplace((int)gg.curpage, (*vw)->x, (*vw)->y1, (*vw)->x, (*vw)->y2);
+	Free(*vw);
+}
+
+#undef rtn
+
+/*==================  NEWSOLDER  =================*/
+/*=                                              =*/
+/*=  Create a solder point.                      =*/
+/*=                                              =*/
+/*================================================*/
+
+static void newsolder(log_srec **s)
+{
+	*s = (log_srec *)Malloc(sizeof(log_srec));
+	(*s)->next = gg.sbase[gg.curpage - 1];
+	gg.sbase[gg.curpage - 1] = *s;
+	(*s)->hwire = NULL;
+	(*s)->hwire2 = NULL;
+	(*s)->vwire = NULL;
+	(*s)->vwire2 = NULL;
+	(*s)->temp = (na_long)0;
+}
+
+
+#define rtn             "DISPSOLDER"
+
+
+/*================  DISPSOLDER  ==================*/
+/*=                                              =*/
+/*=  Dispose of a solder point.                  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void dispsolder(log_srec **s)
+{
+	log_srec *s1;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Dispose solder %ld\n", (long)(*s));
+	if (*s == NULL)
+		return;
+	s1 = gg.sbase[gg.curpage - 1];
+	if (*s == s1)
+	{
+		gg.sbase[gg.curpage - 1] = (*s)->next;
+	}
+	else
+	{
+		while (s1 != NULL && s1->next != *s)
+			s1 = s1->next;
+		if (s1 == NULL)
+			report(10, rtn);
+		else
+			s1->next = (*s)->next;
+	}
+	chpageplace((int)gg.curpage, (*s)->x, (*s)->y, (*s)->x, (*s)->y);
+	Free(*s);
+}
+
+#undef rtn
+
+/*================  CLOSERWIRE  ==================*/
+/*=                                              =*/
+/*=  Find which wire(s) are under the cursor,    =*/
+/*=     if any.                                  =*/
+/*=                                              =*/
+/*================================================*/
+
+static void closerwire(short x, short y)
+{
+	if (gg.invisible || gg.showconflicts)
+	{
+		gg.nearhw = NULL;
+		gg.nearvw = NULL;
+		return;
+	}
+	gg.nearhw = gg.hwbase[gg.curpage - 1];
+	while (gg.nearhw != NULL &&
+			(gg.nearhw->y != y || gg.nearhw->x1 > x || gg.nearhw->x2 < x))
+		gg.nearhw = gg.nearhw->next;
+	gg.nearvw = gg.vwbase[gg.curpage - 1];
+	while (gg.nearvw != NULL &&
+			(gg.nearvw->x != x || gg.nearvw->y1 > y || gg.nearvw->y2 < y))
+		gg.nearvw = gg.nearvw->next;
+}
+
+/*assumes hw <> nil if hw2 <> nil*/
+
+#define rtn             "ADDSOLDER"
+
+
+/*=================  ADDSOLDER  ==================*/
+/*=                                              =*/
+/*=  Add a solder point between two wires.       =*/
+/*=                                              =*/
+/*================================================*/
+
+static void addsolder(short x, short y, log_hwrec *hw, log_hwrec *hw2, log_vwrec *vw, log_vwrec *vw2)
+{
+	log_srec *s;
+	log_nrec *n;
+
+	s = gg.sbase[gg.curpage - 1];
+	while (s != NULL && (s->x != x || s->y != y))
+		s = s->next;
+	if (s == NULL) {
+		newsolder(&s);
+		s->x = x;
+		s->y = y;
+		chpageplace((int)gg.curpage, x, y, x, y);
+		s->hwire = NULL;
+		s->hwire2 = NULL;
+		s->vwire = NULL;
+		s->vwire2 = NULL;
+		n = NULL;
+		if (hw != NULL)
+			n = hw->node;
+		if (vw != NULL && n == NULL)
+			n = vw->node;
+		hidecursor();
+		if (gg.glowmode && n != NULL)
+			drawsolderc(x, y, (int)glowcol(n, (long)gg.color.solder));
+		else
+			drawsolderc(x, y, gg.color.solder);
+		hidecursor();
+	}
+	if (hw != NULL && hw != s->hwire && hw != s->hwire2)
+	{
+		if (s->hwire == NULL)
+			s->hwire = hw;
+		else if (s->hwire2 == NULL)
+			s->hwire2 = hw2;
+		else
+			report(1, rtn);
+	}
+	if (hw2 != NULL && hw2 != s->hwire && hw2 != s->hwire2)
+	{
+		if (s->hwire2 == NULL)
+			s->hwire2 = hw2;
+		else
+			report(2, rtn);
+	}
+	if (vw != NULL && vw != s->vwire && vw != s->vwire2)
+	{
+		if (s->vwire == NULL)
+			s->vwire = vw;
+		else if (s->vwire2 == NULL)
+			s->vwire2 = vw;
+		else
+			report(3, rtn);
+	}
+	if (vw2 != NULL && vw2 != s->vwire && vw2 != s->vwire2)
+	{
+		if (s->vwire2 == NULL)
+			s->vwire2 = vw2;
+		else
+			report(4, rtn);
+	}
+	if (gg.traceflag)
+		fprintf(tracefile, "Add solder %ld\n", (long)s);
+}
+
+#undef rtn
+
+
+/*=================  FINDSOLDER  =================*/
+/*=                                              =*/
+/*=  Find a solder point at specified position.  =*/
+/*=                                              =*/
+/*================================================*/
+
+static log_srec *findsolder(short x, short y)
+{
+	log_srec *s;
+
+	s = gg.sbase[gg.curpage - 1];
+	while (s != NULL && (s->x != x || s->y != y))
+		s = s->next;
+	return s;
+}
+
+
+/*=================  ADDSOLDERT  =================*/
+/*=                                              =*/
+/*=  Add a solder point at a T-intersection of   =*/
+/*=     two wires.                               =*/
+/*=                                              =*/
+/*================================================*/
+
+static void addsoldert(log_hwrec *hw, log_vwrec *vw)
+{
+	if (hw->x1 == vw->x && hw->y != vw->y1 && hw->y != vw->y2)
+	{
+		addsolder(hw->x1, hw->y, hw, NULL, vw, NULL);
+		return;
+	}
+	if (hw->x2 == vw->x && hw->y != vw->y1 && hw->y != vw->y2)
+	{
+		addsolder(hw->x2, hw->y, hw, NULL, vw, NULL);
+		return;
+	}
+	if (hw->y == vw->y1 && hw->x1 != vw->x && hw->x2 != vw->x)
+		addsolder(vw->x, vw->y1, hw, NULL, vw, NULL);
+	else if (hw->y == vw->y2 && hw->x1 != vw->x && hw->x2 != vw->x)
+		addsolder(vw->x, vw->y2, hw, NULL, vw, NULL);
+}
+
+
+/*==================  CHGHW/VW  ==================*/
+/*=                                              =*/
+/*=  Used for deleting wires (see DELHWIRE).     =*/
+/*=                                              =*/
+/*================================================*/
+
+static void chggate (log_grec *g, int i, log_nrec *oldnode, log_nrec *n);
+
+static void chgvw (log_vwrec *vw, log_nrec *oldnode, log_nrec *n);
+
+
+#define rtn             "CHGHW"
+
+
+static void chghw(log_hwrec *hw, log_nrec *oldnode, log_nrec *n)
+{
+	log_vwrec *vw;
+	log_hwrec *hw1;
+	log_grec *g;
+	log_srec *s;
+	short i, px, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Change hwire %ld to node %ld\n", (long)hw, (long)n);
+	switchnode(&hw->node, n);
+	g = gg.gbase[gg.curpage - 1];
+	while (g != NULL)
+	{
+		if (abs(g->y - hw->y) <= g->kind->bbmax &&
+				P_ibetweenm((long)hw->x1, (long)g->x, (long)hw->x2,
+					(long)g->kind->bbmax))
+		{
+			FORLIM = g->kind->numpins;
+			for (i = 1; i <= FORLIM; i++)
+			{
+				px = g->pinpos[i - 1].x;
+				if (hw->x1 <= px && px <= hw->x2 && g->pinpos[i - 1].y == hw->y &&
+						g->pin[i - 1] == oldnode)
+					chggate(g, i, oldnode, n);
+			}
+		}
+		g = g->next;
+	}
+	vw = gg.vwbase[gg.curpage - 1];
+	while (vw != NULL)
+	{
+		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
+				hw->y <= vw->y2 && vw->node == oldnode)
+		{
+			if ((hw->x1 == vw->x || hw->x2 == vw->x || vw->y1 == hw->y ||
+						vw->y2 == hw->y) &&
+					(hw->wcolr == vw->wcolr || hw->wcolr == log_wcol_blue ||
+					 vw->wcolr == log_wcol_blue))
+				chgvw(vw, oldnode, n);
+			else
+			{  /*vlsi only*/
+				s = gg.sbase[gg.curpage - 1];
+				while (s != NULL && (s->x != vw->x || s->y != hw->y))
+					s = s->next;
+				if (s != NULL)
+					chgvw(vw, oldnode, n);
+			}
+		}
+		vw = vw->next;
+	}
+	hw1 = gg.hwbase[gg.curpage - 1];
+	while (hw1 != NULL && vlsi)
+	{
+		if (hw->y == hw1->y && (hw->x1 == hw1->x2 || hw->x2 == hw1->x1) &&
+				(hw->wcolr == log_wcol_blue || hw1->wcolr == log_wcol_blue) &&
+				hw1->node == oldnode)
+			chghw(hw1, oldnode, n);
+		hw1 = hw1->next;
+	}
+}
+
+#undef rtn
+
+
+#define rtn             "CHGVW"
+
+
+static void chgvw(log_vwrec *vw, log_nrec *oldnode, log_nrec *n)
+{
+	log_hwrec *hw;
+	log_vwrec *vw1;
+	log_grec *g;
+	log_srec *s;
+	short i, py, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Change vwire %ld to node %ld\n", (long)vw, (long)n);
+	switchnode(&vw->node, n);
+	g = gg.gbase[gg.curpage - 1];
+	while (g != NULL)
+	{
+		if (abs(g->x - vw->x) <= g->kind->bbmax &&
+				P_ibetweenm((long)vw->y1, (long)g->y, (long)vw->y2,
+					(long)g->kind->bbmax))
+		{
+			FORLIM = g->kind->numpins;
+			for (i = 1; i <= FORLIM; i++)
+			{
+				py = g->pinpos[i - 1].y;
+				if (vw->y1 <= py && py <= vw->y2 && g->pinpos[i - 1].x == vw->x &&
+						g->pin[i - 1] == oldnode)
+					chggate(g, i, oldnode, n);
+			}
+		}
+		g = g->next;
+	}
+	hw = gg.hwbase[gg.curpage - 1];
+	while (hw != NULL)
+	{
+		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
+				hw->y <= vw->y2 && hw->node == oldnode) {
+			if (hw->x1 == vw->x || hw->x2 == vw->x || vw->y1 == hw->y ||
+					vw->y2 == hw->y)
+				chghw(hw, oldnode, n);
+			else
+			{
+				s = gg.sbase[gg.curpage - 1];
+				while (s != NULL && (s->x != vw->x || s->y != hw->y))
+					s = s->next;
+				if (s != NULL)
+					chghw(hw, oldnode, n);
+			}
+		}
+		hw = hw->next;
+	}
+	vw1 = gg.vwbase[gg.curpage - 1];
+	while (vw1 != NULL && vlsi)
+	{
+		if (vw->x == vw1->x && (vw->y1 == vw1->y2 || vw->y2 == vw1->y1) &&
+				(vw->wcolr == log_wcol_blue || vw1->wcolr == log_wcol_blue) &&
+				vw1->node == oldnode)
+			chgvw(vw1, oldnode, n);
+		vw1 = vw1->next;
+	}
+}
+
+#undef rtn
+
+/*=================  DELVWIRE  ===================*/
+/*=                                              =*/
+/*=  Delete a horizontal or vertical wire.       =*/
+/*=                                              =*/
+/*================================================*/
+
+static int wantsolder(log_srec *s)
+{
+	struct LOC_wantsolder V;
+
+	V.hasred = false;
+	V.hasgreen = false;
+	V.hasyellow = false;
+	V.hasblue = false;
+	markcolor(&s->hwire, &V);
+	markcolor(&s->hwire2, &V);
+	markcolor((log_hwrec **)(&s->vwire), &V);
+	markcolor((log_hwrec **)(&s->vwire2), &V);
+	return (V.hasblue && (V.hasgreen || V.hasyellow || V.hasred));
+}
+
+static void delhwire(log_hwrec *hw)
+{
+	log_vwrec *vw;
+	log_hwrec *hw1;
+	log_srec *s, *s1;
+	log_nrec *oldnode, *n, *savenode;
+	log_grec *g;
+	short i, x, y, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Delete hwire %ld\n", (long)hw);
+	working();
+	clipon();
+	m_color((long)gg.color.backgr);
+	hline(hw->x1, hw->x2, hw->y);
+	oldnode = hw->node;
+	stamp(&oldnode->simtype->netstamp);
+	switchnode(&hw->node, NULL);
+	savenode = oldnode;
+	s = gg.sbase[gg.curpage - 1];
+	while (s != NULL)
+	{
+		s1 = s->next;
+		if (s->hwire == hw || s->hwire2 == hw)
+		{
+			if (s->hwire == hw)
+				s->hwire = s->hwire2;
+			s->hwire2 = NULL;
+			if (!wantsolder(s))
+			{
+				drawsolderc(s->x, s->y, gg.color.backgr);
+				dispsolder(&s);
+			}
+			else
+			{
+				if (gg.traceflag)
+					fprintf(tracefile, "DELHW keeping solder %ld\n", (long)s);
+			}
+		}
+		s = s1;
+	}
+	vw = gg.vwbase[gg.curpage - 1];
+	while (vw != NULL)
+	{
+		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
+				hw->y <= vw->y2 && vw->node == oldnode)
+		{
+			delgetnode(&savenode, &oldnode, &n);
+			if (n != oldnode)
+				chgvw(vw, oldnode, n);
+		}
+		vw = vw->next;
+	}
+	hw1 = gg.hwbase[gg.curpage - 1];
+	while (hw1 != NULL && vlsi)
+	{
+		if (hw->y == hw1->y && (hw1->x1 == hw->x2 || hw1->x2 == hw->x1) &&
+				hw1->node == oldnode) {
+			delgetnode(&savenode, &oldnode, &n);
+			if (n != oldnode)
+				chghw(hw1, oldnode, n);
+		}
+		hw1 = hw1->next;
+	}
+	g = gg.gbase[gg.curpage - 1];
+	while (g != NULL)
+	{
+		if (abs(g->y - hw->y) <= g->kind->bbmax &&
+				P_ibetweenm((long)hw->x1, (long)g->x, (long)hw->x2,
+					(long)g->kind->bbmax))
+		{
+			FORLIM = g->kind->numpins;
+			for (i = 1; i <= FORLIM; i++)
+			{
+				if (g->pin[i - 1] == oldnode)
+				{
+					x = g->pinpos[i - 1].x;
+					y = g->pinpos[i - 1].y;
+					if (hw->x1 <= x && x <= hw->x2 && y == hw->y)
+					{
+						delgetnode(&savenode, &oldnode, &n);
+						if (n != oldnode)
+							chggate(g, i, oldnode, n);
+					}
+				}
+			}
+		}
+		g = g->next;
+	}
+	disphw(&hw);
+	clipoff();
+}
+
+
+static void delvwire(log_vwrec *vw)
+{
+	log_hwrec *hw;
+	log_vwrec *vw1;
+	log_srec *s, *s1;
+	log_nrec *oldnode, *n, *savenode;
+	log_grec *g;
+	short i, x, y, FORLIM;
+
+	if (gg.traceflag)
+		fprintf(tracefile, "Delete vwire %ld\n", (long)vw);
+	working();
+	clipon();
+	m_color((long)gg.color.backgr);
+	vline(vw->x, vw->y1, vw->y2);
+	oldnode = vw->node;
+	stamp(&oldnode->simtype->netstamp);
+	switchnode(&vw->node, NULL);
+	savenode = oldnode;
+	s = gg.sbase[gg.curpage - 1];
+	while (s != NULL)
+	{
+		s1 = s->next;
+		if (s->vwire == vw || s->vwire2 == vw)
+		{
+			if (s->vwire == vw)
+				s->vwire = s->vwire2;
+			s->vwire2 = NULL;
+			if (!wantsolder(s)) {
+				drawsolderc(s->x, s->y, gg.color.backgr);
+				dispsolder(&s);
+			}
+			else
+			{
+				if (gg.traceflag)
+					fprintf(tracefile, "DELVW keeping solder %ld\n", (long)s);
+			}
+		}
+		s = s1;
+	}
+	hw = gg.hwbase[gg.curpage - 1];
+	while (hw != NULL)
+	{
+		if (hw->x1 <= vw->x && vw->x <= hw->x2 && vw->y1 <= hw->y &&
+				hw->y <= vw->y2 && hw->node == oldnode)
+		{
+			delgetnode(&savenode, &oldnode, &n);
+			if (n != oldnode)
+				chghw(hw, oldnode, n);
+		}
+		hw = hw->next;
+	}
+	vw1 = gg.vwbase[gg.curpage - 1];
+	while (vw1 != NULL && vlsi)
+	{
+		if (vw->x == vw1->x && (vw1->y1 == vw->y2 || vw1->y2 == vw->y1) &&
+				vw1->node == oldnode)
+		{
+			delgetnode(&savenode, &oldnode, &n);
+			if (n != oldnode)
+				chgvw(vw1, oldnode, n);
+		}
+		vw1 = vw1->next;
+	}
+	g = gg.gbase[gg.curpage - 1];
+	while (g != NULL)
+	{
+		if (abs(g->x - vw->x) <= g->kind->bbmax &&
+				P_ibetweenm((long)vw->y1, (long)g->y, (long)vw->y2,
+					(long)g->kind->bbmax))
+		{
+			FORLIM = g->kind->numpins;
+			for (i = 1; i <= FORLIM; i++)
+			{
+				if (g->pin[i - 1] == oldnode)
+				{
+					x = g->pinpos[i - 1].x;
+					y = g->pinpos[i - 1].y;
+					if (vw->y1 <= y && y <= vw->y2 && x == vw->x)
+					{
+						delgetnode(&savenode, &oldnode, &n);
+						if (n != oldnode)
+							chggate(g, i, oldnode, n);
+					}
+				}
+			}
+		}
+		g = g->next;
+	}
+	vw1 = vw;
+	dispvw(&vw);
+	clipoff();
+}
+
-- 
GitLab