diff --git a/Makefile b/Makefile
index 4b26dafcd803c741ec448c466cf55177038aa346..293244f3a2c7b71b34d20a90b291a17143d330d3 100644
--- a/Makefile
+++ b/Makefile
@@ -120,7 +120,7 @@ TOOLOBJ = $(SIMOBJ) \
 	  $(TARGET_DIR)/pagewriter.o $(TARGET_DIR)/pagereader.o	\
 	  $(TARGET_DIR)/configreader.o $(TARGET_DIR)/attrs.o \
 	  $(TARGET_DIR)/keyboard.o $(TARGET_DIR)/box.o \
-	  $(TARGET_DIR)/pen.o
+	  $(TARGET_DIR)/pen.o $(TARGET_DIR)/libraryreader.o
 
 
 $(TARGET_DIR)/ana/%.o: $(SRC_DIR)/ana/%.c
diff --git a/include/libraryreader.h b/include/libraryreader.h
new file mode 100644
index 0000000000000000000000000000000000000000..fda6b2cb3691e980be1da099bf21544b8f3470f2
--- /dev/null
+++ b/include/libraryreader.h
@@ -0,0 +1,13 @@
+#ifndef LIBRARY_READER_H
+#define LIBRARY_READER_H
+
+/* Local variables for readlibrary_at: */
+struct LOC_readlibrary_at {
+	short p, f;
+	long dist;
+};
+
+short readlibrary_at(char *n_, short where, int loadit);
+short readlibrary(char *n);
+
+#endif
diff --git a/include/log.h b/include/log.h
index 63cfc18b3ad55d14bf99a1af8ddb3beaa5175493..3edf08992cf582009b59228fc30d540213c5cc1e 100644
--- a/include/log.h
+++ b/include/log.h
@@ -45,7 +45,6 @@ void prealunit2(double r, short p, char *u, char *s);
 void beginerror();
 void enderror();
 void setvlsimode(int flag);
-short readlibrary(char *n);
 void histdelsignals();
 void histaddsignal(log_hnrec **hn, short sig, short y);
 void addboxat(short x1, short y1, short x2, short y2);
diff --git a/src/libraryreader.c b/src/libraryreader.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d8a3d5c2afe480f87272aa432da72f117dbad10
--- /dev/null
+++ b/src/libraryreader.c
@@ -0,0 +1,686 @@
+#include "libraryreader.h"
+
+#include <utils/p2c.h>
+#include <utils/strings.h>
+#include <graphics/newci.h>
+#include <graphics/newcrt.h>
+#include "logdef.h"
+#include "logglobals.h"
+#include "log.h"
+#include "screen.h"
+#include "swap.h"
+
+/** @brief Compare string S with template string T.
+
+	T allows wildcards:
+		- % matches any character in S.
+		- * matches zero or more characters in S.
+		- ? and = are equivalent to *.
+		- ; precedes group number(s).
+*/
+static int comparestr(char *s_, uchar g, char *t_)
+{
+	int Result;
+	char *s, *t;
+	char ch;
+	short i;
+	int match;
+	short FORLIM;
+
+	s = s_;
+	t = t_;
+	if (*t == '\0' || !strcmp(s, t))
+	{
+		return (strcmp(s, t) == 0);
+	}
+	else
+	{
+		ch = t[0];
+		if (ch == '*' || ch == '?' || ch == '=')
+		{
+			t++;
+			do
+			{
+				match = comparestr(s, g, t);
+				if (!match && *s != '\0')
+					s++;
+			} while (!(match || *s == '\0'));
+			return (match || comparestr(s, g, t));
+		}
+		else if (ch == ';')
+		{
+			Result = false;
+			if (*s != '\0')
+				return Result;
+			FORLIM = strlen(t);
+			for (i = 1; i < FORLIM; i++)
+			{
+				if (t[i] == g + 48)
+					Result = true;
+			}
+			return Result;
+		}
+		else if (*s != '\0' && (ch == '%' || ch == s[0]))
+		{
+			s++;
+			t++;
+			return (comparestr(s, g, t));
+		}
+		else
+		{
+			return false;
+		}
+	}
+	return Result;
+}
+
+
+#define maxvars         16
+
+
+static void readint(struct LOC_readlibrary_at *LINK)
+{
+	if (LINK->p >= 64)
+	{
+		GET(libf1[LINK->f - 1]->f, filerec);
+		LINK->p = 0;
+	}
+}
+
+static long readnum(struct LOC_readlibrary_at *LINK)
+{
+	long Result;
+
+	if (LINK->p >= 256)
+	{
+		GET(libf1[LINK->f - 1]->f, filerec);
+		LINK->p = 0;
+	}
+	Result = GETFBUF(libf1[LINK->f - 1]->f, filerec).b[LINK->p];
+	LINK->p++;
+	LINK->dist++;
+	return Result;
+}
+
+static long readcoord(struct LOC_readlibrary_at *LINK)
+{
+	long i;
+
+	i = readnum(LINK);
+	if (i < 128)
+		return i;
+	else if (i == 128)
+		return 0;
+	else
+		return (i - 256);
+}
+
+static void bound(log_krec *k, long x, long y, struct LOC_readlibrary_at *LINK)
+{
+	if (x < k->bbx1)
+		k->bbx1 = x;
+	if (x > k->bbx2)
+		k->bbx2 = x;
+	if (y < k->bby1)
+		k->bby1 = y;
+	if (y > k->bby2)
+		k->bby2 = y;
+}
+
+static long uncompress(long i, struct LOC_readlibrary_at *LINK)
+{
+	if (i < 0)
+		i += 256;
+	if (i == 0)
+		return 0;
+	else
+		return (na_po2(i / 16) * ((i & 15) + 16) * 4);
+}
+
+
+static descrec *readdesc(char *rec)
+{
+	unsigned short i,j1,j2,s1,s2;
+	static descrec d;
+	d.ptr = getintsw(rec);
+	d.numvects = rec[4];
+	d.numpins = rec[5];
+	d.numpnums= rec[6];
+	d.lblsize = rec[7];
+	d.simtype = rec[8];
+	d.procsize= rec[9];
+	d.flag = getshortsw(&(rec[10]));
+
+	if (!bigendian)
+	{
+		/* d.flag.i = reverse(d.flag.i); */
+		d.flag = reverse(d.flag);
+	}
+	d.xx1= rec[12];
+	d.yy1= rec[13];
+	d.xx2= rec[14];
+	d.yy2= rec[15];
+	return &d;
+}
+
+
+static log_pnumrec readpnum(char *rec)
+{
+	static log_pnumrec p;
+
+	p.x = rec[0];
+	p.y = rec[1];
+	p.num = getshortsw(&(rec[2]));
+	return p;
+}
+
+
+/** @brief Read gate(s) named from library and enter into the catalog.
+
+	If catalog is full, attempt to replace a gate-kind which is
+	no longer used.
+*/
+short readlibrary_at(char *n_, short where, int loadit)
+{
+	struct LOC_readlibrary_at V;
+	short Result;
+	char n[9];
+	short i, i0, i00, j, j0, j00, j000, count;
+	long j1;
+	strlist_t *l2;
+	log_grec *g;
+	char buf[256];
+	char ch, ch2, curcol;
+	int found, flag;
+	log_vectorrec *tempvects;
+	char STR1[256];
+	short FORLIM, FORLIM1;
+	long TEMP;
+	log_krec *WITH;
+	descrec *WITH1;
+	log_vectorrec *WITH2;
+	long FORLIM2;
+
+	strcpy(n, n_);
+	strcpy(n, strrtrim(strcpy(STR1, strltrim(n))));
+	found = false;
+	count = 0;
+	FORLIM = idxsize;
+	for (i0 = 1; i0 <= FORLIM; i0++)
+	{
+		if (comparestr(index_[i0 - 1], indexgroup[i0 - 1], n))
+		{
+			found = true;
+			if (P_getbits_UB(loadedgates, i0 - 1, 0, 3))
+			{
+				i = 0;
+				FORLIM1 = maxkinds;
+				for (j = 1; j <= FORLIM1; j++)
+				{
+					if (kind[j - 1] != NULL && kind[j - 1]->code == i0)
+						i = j;
+				}
+				goto _L1;
+			}
+
+			if (!loadit)
+			{
+				count++;
+				goto _L1;
+			}
+			i = where;
+			while (i <= maxkinds && kind[i - 1] != NULL)
+				i++;
+			if (i > maxkinds)
+			{
+				i = 1;
+				while (i <= maxkinds && kind[i - 1] != NULL)
+					i++;
+			}
+
+			/* garbagge collection */
+			if (i > maxkinds)
+			{
+				i = libptr;
+				do
+				{
+					if (i >= maxkinds)
+						i = 0;
+					i++;
+					flag = false;
+					FORLIM1 = gg.numpages;
+					for (j = 0; j < FORLIM1; j++)
+					{
+						g = gg.pages[j]->gbase;
+						while (g != NULL)
+						{
+							flag = (flag || (g->g & (log_kindoffset - 1)) == i);
+							g = g->next;
+						}
+					}
+					FORLIM1 = kindgroupsize;
+					for (j = 0; j < FORLIM1; j++)
+						flag = (flag || (kindgroup[j] & (log_kindoffset - 1)) == i);
+				} while (flag && i != libptr);
+
+				if (flag)
+				{
+					beginerror();
+					nc_printf("Maximum of %d gate types are in use.\n", maxkinds);
+					enderror();
+					i = 0;
+					goto _L1;
+				}
+				libptr = i;
+				clipoff();
+				if (gg.showpage == log_page_cat)
+				{
+					udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
+							(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
+							gg.color.backgr);
+				}
+				TEMP = kind[i - 1]->code - 1;
+				P_clrbits_B(loadedgates, TEMP, 0, 3);
+				WITH = kind[i - 1];
+				calltoolkind(kind[i - 1], act_disposekind);
+				if (WITH->proc != NULL)
+					Free(WITH->proc);
+				if (WITH->lbl != NULL)
+					strlist_empty(&WITH->lbl);
+				if (WITH->attr != NULL)
+					Free(WITH->attr);
+				if (WITH->vector != NULL)
+					Free(WITH->vector);
+				if (WITH->pin != NULL)
+					Free(WITH->pin);
+				if (WITH->pnum != NULL)
+					Free(WITH->pnum);
+				Free(kind[i - 1]);
+				kind[i - 1] = NULL;
+			}
+			V.f = indexfile[i0 - 1];
+			TRY(try15);
+			i00 = indexoffset[i0 - 1];
+			fseek(libf1[V.f - 1]->f,
+					(libfstart[V.f - 1] + (i00 - 1L) / 16 - 1) * sizeof(filerec),
+					0);
+			SETUPBUF(libf1[V.f - 1]->f, filerec);
+			GET(libf1[V.f - 1]->f, filerec);
+			WITH1 = readdesc((char*) &GETFBUF(libf1[V.f - 1]->f, filerec).b[16*((i00 - 1) &
+						15)]);
+			kind[i - 1] = (log_krec *)Malloc(sizeof(log_krec));
+			kind[i - 1]->simtype = findsimtype(WITH1->simtype);
+			kind[i - 1]->numvects = WITH1->numvects;
+			kind[i - 1]->numpins = WITH1->numpins;
+			kind[i - 1]->flag.i = WITH1->flag;
+			if (kind[i - 1]->flag.U3.expanded)
+			{
+				kind[i - 1]->bigprocsize = uncompress((long)WITH1->procsize, &V);
+				kind[i - 1]->biglblsize = uncompress((long)WITH1->lblsize, &V);
+				kind[i - 1]->numpnums = 0;
+				kind[i - 1]->bigvectsize = uncompress((long)WITH1->numpnums, &V);
+			}
+			else
+			{
+				kind[i - 1]->bigprocsize = WITH1->procsize * 4;
+				kind[i - 1]->biglblsize = WITH1->lblsize * 4;
+				kind[i - 1]->numpnums = WITH1->numpnums;
+			}
+			kind[i - 1]->x1 = WITH1->xx1;
+			kind[i - 1]->y1 = WITH1->yy1;
+			kind[i - 1]->x2 = WITH1->xx2;
+			kind[i - 1]->y2 = WITH1->yy2;
+			j1 = WITH1->ptr;
+			fseek(libf1[V.f - 1]->f, j1 / 64 * sizeof(filerec), 0);
+			SETUPBUF(libf1[V.f - 1]->f, filerec);
+			GET(libf1[V.f - 1]->f, filerec);
+			WITH = kind[i - 1];
+			WITH->code = i0;
+			strcpy(WITH->name, index_[i0 - 1]);
+			WITH->proc = NULL;
+			WITH->lbl = NULL;
+			WITH->attr = NULL;
+			WITH->vector = NULL;
+			WITH->pin = NULL;
+			WITH->pinnames = NULL;
+			WITH->pnum = NULL;
+			WITH->info = (na_long)0;
+			V.p = j1 & 63;
+			WITH->bbx1 = -log_scale0;
+			WITH->bby1 = -log_scale0;
+			WITH->bbx2 = log_scale0;
+			WITH->bby2 = log_scale0;
+			bound(kind[i - 1], (long)WITH->x1, (long)WITH->y1, &V);
+			bound(kind[i - 1], (long)WITH->x2, (long)WITH->y2, &V);
+
+			if (WITH->numvects != 0)
+			{
+				if (WITH->flag.U3.expanded)
+				{
+					tempvects = (log_vectorrec *)
+						Malloc(WITH->numvects * sizeof(log_vectorrec) * 2);
+					j = 0;
+					curcol = '1';
+					V.dist = 0;
+					V.p *= 4;
+					FORLIM1 = WITH->numvects;
+					for (j0 = 1; j0 <= FORLIM1; j0++)
+					{
+						ch = (char)readnum(&V);
+						if (ch >= '1' && ch <= '7')
+						{
+							do
+							{
+								ch2 = ch;
+								ch = (char)readnum(&V);
+							} while (ch >= '1' && ch <= '7');
+
+							if (ch2 != curcol)
+							{
+								j++;
+								tempvects[j - 1].vkind = ch2;
+								tempvects[j - 1].numcoords = 0;
+								curcol = ch2;
+							}
+						}
+						j++;
+						WITH2 = &tempvects[j - 1];
+						WITH2->vkind = ch;
+						switch (ch)
+						{
+
+							case 'v':
+							case 'C':
+							case 'e':
+							case 'E':
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->UU.U99.x2 = readcoord(&V);
+								WITH2->UU.U99.y2 = readcoord(&V);
+								WITH2->numcoords = 2;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
+										(long)WITH2->UU.U99.y2, &V);
+								break;
+
+							case 'r':
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->UU.U99.x2 = readcoord(&V);
+								WITH2->UU.U99.y2 = readcoord(&V);
+								WITH2->UU.U98.num = readcoord(&V);
+								WITH2->numcoords = 2;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
+										(long)WITH2->UU.U99.y2, &V);
+								break;
+
+							case 'F':
+							case 'c':
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->UU.U99.x2 = readcoord(&V);
+								WITH2->UU.U99.y2 = readcoord(&V);
+								WITH2->UU.U99.x3 = readcoord(&V);
+								WITH2->UU.U99.y3 = readcoord(&V);
+								WITH2->UU.U99.x4 = readcoord(&V);
+								WITH2->UU.U99.y4 = readcoord(&V);
+								WITH2->numcoords = 4;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
+										(long)WITH2->UU.U99.y2, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x3,
+										(long)WITH2->UU.U99.y3, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x4,
+										(long)WITH2->UU.U99.y4, &V);
+								break;
+
+							case 'p':
+								WITH2->UU.U98.num = readnum(&V);
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->numcoords = 1;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								break;
+
+							case 'b':
+								WITH2->UU.U98.num = readnum(&V);
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->UU.U99.x2 = readcoord(&V);
+								WITH2->UU.U99.y2 = readcoord(&V);
+								WITH2->numcoords = 2;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
+										(long)WITH2->UU.U99.y2, &V);
+								break;
+
+							case 't':
+								WITH2->UU.U116.tsize = readnum(&V);
+								WITH2->UU.U116.torg = readnum(&V) - 1;
+								WITH2->x1 = readcoord(&V);
+								WITH2->y1 = readcoord(&V);
+								WITH2->numcoords = 1;
+								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
+								j000 = readnum(&V);
+								buf[j000] = '\0';
+								for (j00 = 0; j00 < j000; j00++)
+									buf[j00] = (char)readnum(&V);
+								WITH2->UU.U116.sp = strdup(buf);
+								break;
+
+							default:
+								j--;
+								break;
+						}
+					}
+					WITH->numvects = j;
+					WITH->vector = (log_vectorrec *)
+						Malloc(WITH->numvects * sizeof(log_vectorrec));
+					memmove((void *)WITH->vector, (void *)tempvects,
+							WITH->numvects * sizeof(log_vectorrec));
+					while (V.dist < WITH->bigvectsize)
+						j0 = readnum(&V);
+					V.p /= 4;
+					Free(tempvects);
+				}
+				else
+				{
+					WITH->vector = (log_vectorrec *)
+						Malloc(WITH->numvects * sizeof(log_vectorrec));
+					FORLIM1 = WITH->numvects;
+					for (j = 0; j < FORLIM1; j++)
+					{
+						readint(&V);
+						WITH->vector[j].vkind = 'v';
+						WITH->vector[j].numcoords = 2;
+						WITH->vector[j].x1 = GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].x1;
+						WITH->vector[j].y1 = GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].y1;
+						WITH->vector[j].UU.U99.x2 =
+							GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].x2;
+						WITH->vector[j].UU.U99.y2 =
+							GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].y2;
+						bound(kind[i - 1], (long)WITH->vector[j].x1,
+								(long)WITH->vector[j].y1, &V);
+						bound(kind[i - 1], (long)WITH->vector[j].UU.U99.x2,
+								(long)WITH->vector[j].UU.U99.y2, &V);
+						V.p++;
+					}
+				}
+			}
+
+			if (WITH->numpins != 0)
+			{
+				WITH->pin = (log_pinrec *)Malloc(WITH->numpins * sizeof(log_pinrec));
+				WITH->pinnames = (strlist_t **)
+					Malloc(WITH->numpins * sizeof(strlist_t *));
+				FORLIM1 = WITH->numpins;
+				for (j = 0; j < FORLIM1; j++)
+				{
+					readint(&V);
+					WITH->pin[j].x = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].x /
+						log_scale0;
+					WITH->pin[j].y = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].y /
+						log_scale0;
+					WITH->pin[j].s = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].s;
+					WITH->pin[j].c = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].c;
+					bound(kind[i - 1], (long)(WITH->pin[j].x * log_scale0),
+							(long)(WITH->pin[j].y * log_scale0), &V);
+					WITH->pinnames[j] = NULL;
+					V.p++;
+				}
+			}
+
+			if (WITH->numpnums != 0)
+			{
+				WITH->pnum = (log_pnumrec *)Malloc(WITH->numpnums *
+						sizeof(log_pnumrec));
+				FORLIM1 = WITH->numpnums;
+				for (j = 0; j < FORLIM1; j++)
+				{
+					readint(&V);
+					WITH->pnum[j] = readpnum((char *) &GETFBUF(libf1[V.f - 1]->f, filerec).b
+							[4*V.p]);
+					bound(kind[i - 1], (long)WITH->pnum[j].x, (long)WITH->pnum[j].y,
+							&V);
+					V.p++;
+				}
+			}
+			WITH->numattrs = 0;
+			if (WITH->biglblsize != 0)
+			{
+				strlist_init(&WITH->lbl);
+				*buf = '\0';
+				ch = '\001';
+				FORLIM2 = WITH->biglblsize / 4;
+				for (j1 = 1; j1 <= FORLIM2; j1++)
+				{
+					readint(&V);
+					for (j = 0; j <= 3; j++)
+					{
+						if (ch != '\0')
+						{
+							ch = GETFBUF(libf1[V.f - 1]->f, filerec).c4[V.p][j];
+							if (ch == '\001')
+							{
+								if (*buf == '\002')
+								{
+									j0 = 0;
+									while (*buf != '\0')
+									{
+										if (buf[0] == '\002')
+											j0++;
+										strcpy_overlap(buf, buf + 1);
+										j00 = strposc(buf, '\002', 1L);
+										if (j00 == 0)
+											j00 = strlen(buf) + 1;
+										j000 = strposc(buf, '\003', 1L);
+										if (j000 == 0)
+											j000 = strlen(buf) + 1;
+										j00 = P_imin2((long)j00, (long)j000);
+										if (j00 > 1) {
+											if (j0 <= WITH->numpins)
+											{
+												sprintf(STR1, "%.*s", j00 - 1, buf);
+												l2 = strlist_append(&WITH->pinnames[j0 - 1], STR1);
+												l2->value = (na_long)((long)j0);
+											}
+										}
+										strcpy_overlap(buf, buf + j00 - 1);
+									}
+								}
+								else
+								{
+									l2 = strlist_append(&WITH->lbl, buf);
+								}
+								*buf = '\0';
+							}
+							else if (ch != '\0')
+							{
+								sprintf(buf + strlen(buf), "%c", ch);
+							}
+						}
+					}
+					V.p++;
+				}
+				parselabel(&WITH->lbl, &j, &WITH->attr);
+				WITH->numattrs = j;
+			}
+			if (WITH->bigprocsize != 0) {
+				WITH->proc = (uchar *)Malloc(WITH->bigprocsize);
+				FORLIM2 = WITH->bigprocsize / 4;
+				for (j1 = 1; j1 <= FORLIM2; j1++) {
+					readint(&V);
+					for (j0 = 0; j0 <= 3; j0++)
+						WITH->proc[j1 * 4 + j0 - 4] = GETFBUF(libf1[V.f - 1]->f,
+								filerec).c[V.p * 4 + j0];
+					V.p++;
+				}
+			}
+			else
+			{
+				WITH->proc = (uchar *)Malloc(4L);
+				WITH->proc[0] = '\0';
+			}
+			WITH->bbx1 = -((log_scale0 - WITH->bbx1 - 1) / log_scale0);
+			WITH->bby1 = -((log_scale0 - WITH->bby1 - 1) / log_scale0);
+			WITH->bbx2 = (log_scale0 + WITH->bbx2 - 1) / log_scale0;
+			WITH->bby2 = (log_scale0 + WITH->bby2 - 1) / log_scale0;
+			WITH->bbmax = P_imax2(P_imax2((long)(-WITH->bbx1), (long)WITH->bbx2),
+					P_imax2((long)(-WITH->bby1), (long)WITH->bby2));
+			calltoolkind(kind[i - 1], act_newkind);
+			P_putbits_UB(loadedgates, i0 - 1, 1, 0, 3);
+			RECOVER(try15);
+			kind[i - 1] = NULL;
+
+			if (P_escapecode == -20)
+			{
+				_Escape(P_escapecode);
+			}
+			else
+			{
+				if (P_escapecode != 0)
+				{
+					beginerror();
+					nc_printf("%d/%d/%ld: ", P_escapecode, i, EXCP_LINE);
+					nc_printf("Unable to read file \"%s\"\n", gatesname[V.f - 1]);
+					enderror();
+				}
+				i = 0;
+				goto _L1;
+			}
+
+			ENDTRY(try15);
+			clipoff();
+			if (gg.showpage == log_page_cat)
+			{
+				udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
+						(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
+						gg.color.catgate);
+			}
+_L1:
+			Result = i;
+		}
+	}
+
+	if (!loadit)
+		return count;
+	if (found)
+		return Result;
+	beginerror();
+	nc_printf("Can't find gate \"%s\"\n", n);
+	enderror();
+	Result = 0;
+	if (!gg.initdone)
+		_Escape(0);
+	return Result;
+}
+
+#undef maxvars
+
+
+short readlibrary(char *n)
+{
+	return (readlibrary_at(n, 1, true));
+}
+
diff --git a/src/log.c b/src/log.c
index c00505e5a841e84fb4812ce0a05482a542e51db4..5ceba73f1c97c0119737b9c1b4ba7991bfec0653 100644
--- a/src/log.c
+++ b/src/log.c
@@ -81,6 +81,7 @@
 #include "pagereader.h"
 
 #include "configreader.h"
+#include "libraryreader.h"
 
 enum cursors;
 enum cursors cursortype;
@@ -4980,686 +4981,6 @@ static void centercommand()
 	refrfunc();
 }
 
-/** @brief Compare string S with template string T.
-
-	T allows wildcards:
-		- % matches any character in S.
-		- * matches zero or more characters in S.
-		- ? and = are equivalent to *.
-		- ; precedes group number(s).
-*/
-static int comparestr(char *s_, uchar g, char *t_)
-{
-	int Result;
-	char *s, *t;
-	char ch;
-	short i;
-	int match;
-	short FORLIM;
-
-	s = s_;
-	t = t_;
-	if (*t == '\0' || !strcmp(s, t))
-	{
-		return (strcmp(s, t) == 0);
-	}
-	else
-	{
-		ch = t[0];
-		if (ch == '*' || ch == '?' || ch == '=')
-		{
-			t++;
-			do
-			{
-				match = comparestr(s, g, t);
-				if (!match && *s != '\0')
-					s++;
-			} while (!(match || *s == '\0'));
-			return (match || comparestr(s, g, t));
-		}
-		else if (ch == ';')
-		{
-			Result = false;
-			if (*s != '\0')
-				return Result;
-			FORLIM = strlen(t);
-			for (i = 1; i < FORLIM; i++)
-			{
-				if (t[i] == g + 48)
-					Result = true;
-			}
-			return Result;
-		}
-		else if (*s != '\0' && (ch == '%' || ch == s[0]))
-		{
-			s++;
-			t++;
-			return (comparestr(s, g, t));
-		}
-		else
-		{
-			return false;
-		}
-	}
-	return Result;
-}
-
-
-#define maxvars         16
-
-
-/* Local variables for readlibrary_at: */
-struct LOC_readlibrary_at {
-	short p, f;
-	long dist;
-} ;
-
-static void readint(struct LOC_readlibrary_at *LINK)
-{
-	if (LINK->p >= 64)
-	{
-		GET(libf1[LINK->f - 1]->f, filerec);
-		LINK->p = 0;
-	}
-}
-
-static long readnum(struct LOC_readlibrary_at *LINK)
-{
-	long Result;
-
-	if (LINK->p >= 256)
-	{
-		GET(libf1[LINK->f - 1]->f, filerec);
-		LINK->p = 0;
-	}
-	Result = GETFBUF(libf1[LINK->f - 1]->f, filerec).b[LINK->p];
-	LINK->p++;
-	LINK->dist++;
-	return Result;
-}
-
-static long readcoord(struct LOC_readlibrary_at *LINK)
-{
-	long i;
-
-	i = readnum(LINK);
-	if (i < 128)
-		return i;
-	else if (i == 128)
-		return 0;
-	else
-		return (i - 256);
-}
-
-static void bound(log_krec *k, long x, long y, struct LOC_readlibrary_at *LINK)
-{
-	if (x < k->bbx1)
-		k->bbx1 = x;
-	if (x > k->bbx2)
-		k->bbx2 = x;
-	if (y < k->bby1)
-		k->bby1 = y;
-	if (y > k->bby2)
-		k->bby2 = y;
-}
-
-static long uncompress(long i, struct LOC_readlibrary_at *LINK)
-{
-	if (i < 0)
-		i += 256;
-	if (i == 0)
-		return 0;
-	else
-		return (na_po2(i / 16) * ((i & 15) + 16) * 4);
-}
-
-
-static descrec *readdesc(char *rec)
-{
-	unsigned short i,j1,j2,s1,s2;
-	static descrec d;
-	d.ptr = getintsw(rec);
-	d.numvects = rec[4];
-	d.numpins = rec[5];
-	d.numpnums= rec[6];
-	d.lblsize = rec[7];
-	d.simtype = rec[8];
-	d.procsize= rec[9];
-	d.flag = getshortsw(&(rec[10]));
-
-	if (!bigendian)
-	{
-		/* d.flag.i = reverse(d.flag.i); */
-		d.flag = reverse(d.flag);
-	}
-	d.xx1= rec[12];
-	d.yy1= rec[13];
-	d.xx2= rec[14];
-	d.yy2= rec[15];
-	return &d;
-}
-
-
-static log_pnumrec readpnum(char *rec)
-{
-	static log_pnumrec p;
-
-	p.x = rec[0];
-	p.y = rec[1];
-	p.num = getshortsw(&(rec[2]));
-	return p;
-}
-
-
-/** @brief Read gate(s) named from library and enter into the catalog.
-
-	If catalog is full, attempt to replace a gate-kind which is
-	no longer used.
-*/
-static short readlibrary_at(char *n_, short where, int loadit)
-{
-	struct LOC_readlibrary_at V;
-	short Result;
-	char n[9];
-	short i, i0, i00, j, j0, j00, j000, count;
-	long j1;
-	strlist_t *l2;
-	log_grec *g;
-	char buf[256];
-	char ch, ch2, curcol;
-	int found, flag;
-	log_vectorrec *tempvects;
-	char STR1[256];
-	short FORLIM, FORLIM1;
-	long TEMP;
-	log_krec *WITH;
-	descrec *WITH1;
-	log_vectorrec *WITH2;
-	long FORLIM2;
-
-	strcpy(n, n_);
-	strcpy(n, strrtrim(strcpy(STR1, strltrim(n))));
-	found = false;
-	count = 0;
-	FORLIM = idxsize;
-	for (i0 = 1; i0 <= FORLIM; i0++)
-	{
-		if (comparestr(index_[i0 - 1], indexgroup[i0 - 1], n))
-		{
-			found = true;
-			if (P_getbits_UB(loadedgates, i0 - 1, 0, 3))
-			{
-				i = 0;
-				FORLIM1 = maxkinds;
-				for (j = 1; j <= FORLIM1; j++)
-				{
-					if (kind[j - 1] != NULL && kind[j - 1]->code == i0)
-						i = j;
-				}
-				goto _L1;
-			}
-
-			if (!loadit)
-			{
-				count++;
-				goto _L1;
-			}
-			i = where;
-			while (i <= maxkinds && kind[i - 1] != NULL)
-				i++;
-			if (i > maxkinds)
-			{
-				i = 1;
-				while (i <= maxkinds && kind[i - 1] != NULL)
-					i++;
-			}
-
-			/* garbagge collection */
-			if (i > maxkinds)
-			{
-				i = libptr;
-				do
-				{
-					if (i >= maxkinds)
-						i = 0;
-					i++;
-					flag = false;
-					FORLIM1 = gg.numpages;
-					for (j = 0; j < FORLIM1; j++)
-					{
-						g = gg.pages[j]->gbase;
-						while (g != NULL)
-						{
-							flag = (flag || (g->g & (log_kindoffset - 1)) == i);
-							g = g->next;
-						}
-					}
-					FORLIM1 = kindgroupsize;
-					for (j = 0; j < FORLIM1; j++)
-						flag = (flag || (kindgroup[j] & (log_kindoffset - 1)) == i);
-				} while (flag && i != libptr);
-
-				if (flag)
-				{
-					beginerror();
-					nc_printf("Maximum of %d gate types are in use.\n", maxkinds);
-					enderror();
-					i = 0;
-					goto _L1;
-				}
-				libptr = i;
-				clipoff();
-				if (gg.showpage == log_page_cat)
-				{
-					udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
-							(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
-							gg.color.backgr);
-				}
-				TEMP = kind[i - 1]->code - 1;
-				P_clrbits_B(loadedgates, TEMP, 0, 3);
-				WITH = kind[i - 1];
-				calltoolkind(kind[i - 1], act_disposekind);
-				if (WITH->proc != NULL)
-					Free(WITH->proc);
-				if (WITH->lbl != NULL)
-					strlist_empty(&WITH->lbl);
-				if (WITH->attr != NULL)
-					Free(WITH->attr);
-				if (WITH->vector != NULL)
-					Free(WITH->vector);
-				if (WITH->pin != NULL)
-					Free(WITH->pin);
-				if (WITH->pnum != NULL)
-					Free(WITH->pnum);
-				Free(kind[i - 1]);
-				kind[i - 1] = NULL;
-			}
-			V.f = indexfile[i0 - 1];
-			TRY(try15);
-			i00 = indexoffset[i0 - 1];
-			fseek(libf1[V.f - 1]->f,
-					(libfstart[V.f - 1] + (i00 - 1L) / 16 - 1) * sizeof(filerec),
-					0);
-			SETUPBUF(libf1[V.f - 1]->f, filerec);
-			GET(libf1[V.f - 1]->f, filerec);
-			WITH1 = readdesc((char*) &GETFBUF(libf1[V.f - 1]->f, filerec).b[16*((i00 - 1) &
-						15)]);
-			kind[i - 1] = (log_krec *)Malloc(sizeof(log_krec));
-			kind[i - 1]->simtype = findsimtype(WITH1->simtype);
-			kind[i - 1]->numvects = WITH1->numvects;
-			kind[i - 1]->numpins = WITH1->numpins;
-			kind[i - 1]->flag.i = WITH1->flag;
-			if (kind[i - 1]->flag.U3.expanded)
-			{
-				kind[i - 1]->bigprocsize = uncompress((long)WITH1->procsize, &V);
-				kind[i - 1]->biglblsize = uncompress((long)WITH1->lblsize, &V);
-				kind[i - 1]->numpnums = 0;
-				kind[i - 1]->bigvectsize = uncompress((long)WITH1->numpnums, &V);
-			}
-			else
-			{
-				kind[i - 1]->bigprocsize = WITH1->procsize * 4;
-				kind[i - 1]->biglblsize = WITH1->lblsize * 4;
-				kind[i - 1]->numpnums = WITH1->numpnums;
-			}
-			kind[i - 1]->x1 = WITH1->xx1;
-			kind[i - 1]->y1 = WITH1->yy1;
-			kind[i - 1]->x2 = WITH1->xx2;
-			kind[i - 1]->y2 = WITH1->yy2;
-			j1 = WITH1->ptr;
-			fseek(libf1[V.f - 1]->f, j1 / 64 * sizeof(filerec), 0);
-			SETUPBUF(libf1[V.f - 1]->f, filerec);
-			GET(libf1[V.f - 1]->f, filerec);
-			WITH = kind[i - 1];
-			WITH->code = i0;
-			strcpy(WITH->name, index_[i0 - 1]);
-			WITH->proc = NULL;
-			WITH->lbl = NULL;
-			WITH->attr = NULL;
-			WITH->vector = NULL;
-			WITH->pin = NULL;
-			WITH->pinnames = NULL;
-			WITH->pnum = NULL;
-			WITH->info = (na_long)0;
-			V.p = j1 & 63;
-			WITH->bbx1 = -log_scale0;
-			WITH->bby1 = -log_scale0;
-			WITH->bbx2 = log_scale0;
-			WITH->bby2 = log_scale0;
-			bound(kind[i - 1], (long)WITH->x1, (long)WITH->y1, &V);
-			bound(kind[i - 1], (long)WITH->x2, (long)WITH->y2, &V);
-
-			if (WITH->numvects != 0)
-			{
-				if (WITH->flag.U3.expanded)
-				{
-					tempvects = (log_vectorrec *)
-						Malloc(WITH->numvects * sizeof(log_vectorrec) * 2);
-					j = 0;
-					curcol = '1';
-					V.dist = 0;
-					V.p *= 4;
-					FORLIM1 = WITH->numvects;
-					for (j0 = 1; j0 <= FORLIM1; j0++)
-					{
-						ch = (char)readnum(&V);
-						if (ch >= '1' && ch <= '7')
-						{
-							do
-							{
-								ch2 = ch;
-								ch = (char)readnum(&V);
-							} while (ch >= '1' && ch <= '7');
-
-							if (ch2 != curcol)
-							{
-								j++;
-								tempvects[j - 1].vkind = ch2;
-								tempvects[j - 1].numcoords = 0;
-								curcol = ch2;
-							}
-						}
-						j++;
-						WITH2 = &tempvects[j - 1];
-						WITH2->vkind = ch;
-						switch (ch)
-						{
-
-							case 'v':
-							case 'C':
-							case 'e':
-							case 'E':
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->UU.U99.x2 = readcoord(&V);
-								WITH2->UU.U99.y2 = readcoord(&V);
-								WITH2->numcoords = 2;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
-										(long)WITH2->UU.U99.y2, &V);
-								break;
-
-							case 'r':
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->UU.U99.x2 = readcoord(&V);
-								WITH2->UU.U99.y2 = readcoord(&V);
-								WITH2->UU.U98.num = readcoord(&V);
-								WITH2->numcoords = 2;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
-										(long)WITH2->UU.U99.y2, &V);
-								break;
-
-							case 'F':
-							case 'c':
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->UU.U99.x2 = readcoord(&V);
-								WITH2->UU.U99.y2 = readcoord(&V);
-								WITH2->UU.U99.x3 = readcoord(&V);
-								WITH2->UU.U99.y3 = readcoord(&V);
-								WITH2->UU.U99.x4 = readcoord(&V);
-								WITH2->UU.U99.y4 = readcoord(&V);
-								WITH2->numcoords = 4;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
-										(long)WITH2->UU.U99.y2, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x3,
-										(long)WITH2->UU.U99.y3, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x4,
-										(long)WITH2->UU.U99.y4, &V);
-								break;
-
-							case 'p':
-								WITH2->UU.U98.num = readnum(&V);
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->numcoords = 1;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								break;
-
-							case 'b':
-								WITH2->UU.U98.num = readnum(&V);
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->UU.U99.x2 = readcoord(&V);
-								WITH2->UU.U99.y2 = readcoord(&V);
-								WITH2->numcoords = 2;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								bound(kind[i - 1], (long)WITH2->UU.U99.x2,
-										(long)WITH2->UU.U99.y2, &V);
-								break;
-
-							case 't':
-								WITH2->UU.U116.tsize = readnum(&V);
-								WITH2->UU.U116.torg = readnum(&V) - 1;
-								WITH2->x1 = readcoord(&V);
-								WITH2->y1 = readcoord(&V);
-								WITH2->numcoords = 1;
-								bound(kind[i - 1], (long)WITH2->x1, (long)WITH2->y1, &V);
-								j000 = readnum(&V);
-								buf[j000] = '\0';
-								for (j00 = 0; j00 < j000; j00++)
-									buf[j00] = (char)readnum(&V);
-								WITH2->UU.U116.sp = strdup(buf);
-								break;
-
-							default:
-								j--;
-								break;
-						}
-					}
-					WITH->numvects = j;
-					WITH->vector = (log_vectorrec *)
-						Malloc(WITH->numvects * sizeof(log_vectorrec));
-					memmove((void *)WITH->vector, (void *)tempvects,
-							WITH->numvects * sizeof(log_vectorrec));
-					while (V.dist < WITH->bigvectsize)
-						j0 = readnum(&V);
-					V.p /= 4;
-					Free(tempvects);
-				}
-				else
-				{
-					WITH->vector = (log_vectorrec *)
-						Malloc(WITH->numvects * sizeof(log_vectorrec));
-					FORLIM1 = WITH->numvects;
-					for (j = 0; j < FORLIM1; j++)
-					{
-						readint(&V);
-						WITH->vector[j].vkind = 'v';
-						WITH->vector[j].numcoords = 2;
-						WITH->vector[j].x1 = GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].x1;
-						WITH->vector[j].y1 = GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].y1;
-						WITH->vector[j].UU.U99.x2 =
-							GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].x2;
-						WITH->vector[j].UU.U99.y2 =
-							GETFBUF(libf1[V.f - 1]->f, filerec).vec[V.p].y2;
-						bound(kind[i - 1], (long)WITH->vector[j].x1,
-								(long)WITH->vector[j].y1, &V);
-						bound(kind[i - 1], (long)WITH->vector[j].UU.U99.x2,
-								(long)WITH->vector[j].UU.U99.y2, &V);
-						V.p++;
-					}
-				}
-			}
-
-			if (WITH->numpins != 0)
-			{
-				WITH->pin = (log_pinrec *)Malloc(WITH->numpins * sizeof(log_pinrec));
-				WITH->pinnames = (strlist_t **)
-					Malloc(WITH->numpins * sizeof(strlist_t *));
-				FORLIM1 = WITH->numpins;
-				for (j = 0; j < FORLIM1; j++)
-				{
-					readint(&V);
-					WITH->pin[j].x = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].x /
-						log_scale0;
-					WITH->pin[j].y = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].y /
-						log_scale0;
-					WITH->pin[j].s = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].s;
-					WITH->pin[j].c = GETFBUF(libf1[V.f - 1]->f, filerec).pin[V.p].c;
-					bound(kind[i - 1], (long)(WITH->pin[j].x * log_scale0),
-							(long)(WITH->pin[j].y * log_scale0), &V);
-					WITH->pinnames[j] = NULL;
-					V.p++;
-				}
-			}
-
-			if (WITH->numpnums != 0)
-			{
-				WITH->pnum = (log_pnumrec *)Malloc(WITH->numpnums *
-						sizeof(log_pnumrec));
-				FORLIM1 = WITH->numpnums;
-				for (j = 0; j < FORLIM1; j++)
-				{
-					readint(&V);
-					WITH->pnum[j] = readpnum((char *) &GETFBUF(libf1[V.f - 1]->f, filerec).b
-							[4*V.p]);
-					bound(kind[i - 1], (long)WITH->pnum[j].x, (long)WITH->pnum[j].y,
-							&V);
-					V.p++;
-				}
-			}
-			WITH->numattrs = 0;
-			if (WITH->biglblsize != 0)
-			{
-				strlist_init(&WITH->lbl);
-				*buf = '\0';
-				ch = '\001';
-				FORLIM2 = WITH->biglblsize / 4;
-				for (j1 = 1; j1 <= FORLIM2; j1++)
-				{
-					readint(&V);
-					for (j = 0; j <= 3; j++)
-					{
-						if (ch != '\0')
-						{
-							ch = GETFBUF(libf1[V.f - 1]->f, filerec).c4[V.p][j];
-							if (ch == '\001')
-							{
-								if (*buf == '\002')
-								{
-									j0 = 0;
-									while (*buf != '\0')
-									{
-										if (buf[0] == '\002')
-											j0++;
-										strcpy_overlap(buf, buf + 1);
-										j00 = strposc(buf, '\002', 1L);
-										if (j00 == 0)
-											j00 = strlen(buf) + 1;
-										j000 = strposc(buf, '\003', 1L);
-										if (j000 == 0)
-											j000 = strlen(buf) + 1;
-										j00 = P_imin2((long)j00, (long)j000);
-										if (j00 > 1) {
-											if (j0 <= WITH->numpins)
-											{
-												sprintf(STR1, "%.*s", j00 - 1, buf);
-												l2 = strlist_append(&WITH->pinnames[j0 - 1], STR1);
-												l2->value = (na_long)((long)j0);
-											}
-										}
-										strcpy_overlap(buf, buf + j00 - 1);
-									}
-								}
-								else
-								{
-									l2 = strlist_append(&WITH->lbl, buf);
-								}
-								*buf = '\0';
-							}
-							else if (ch != '\0')
-							{
-								sprintf(buf + strlen(buf), "%c", ch);
-							}
-						}
-					}
-					V.p++;
-				}
-				parselabel(&WITH->lbl, &j, &WITH->attr);
-				WITH->numattrs = j;
-			}
-			if (WITH->bigprocsize != 0) {
-				WITH->proc = (uchar *)Malloc(WITH->bigprocsize);
-				FORLIM2 = WITH->bigprocsize / 4;
-				for (j1 = 1; j1 <= FORLIM2; j1++) {
-					readint(&V);
-					for (j0 = 0; j0 <= 3; j0++)
-						WITH->proc[j1 * 4 + j0 - 4] = GETFBUF(libf1[V.f - 1]->f,
-								filerec).c[V.p * 4 + j0];
-					V.p++;
-				}
-			}
-			else
-			{
-				WITH->proc = (uchar *)Malloc(4L);
-				WITH->proc[0] = '\0';
-			}
-			WITH->bbx1 = -((log_scale0 - WITH->bbx1 - 1) / log_scale0);
-			WITH->bby1 = -((log_scale0 - WITH->bby1 - 1) / log_scale0);
-			WITH->bbx2 = (log_scale0 + WITH->bbx2 - 1) / log_scale0;
-			WITH->bby2 = (log_scale0 + WITH->bby2 - 1) / log_scale0;
-			WITH->bbmax = P_imax2(P_imax2((long)(-WITH->bbx1), (long)WITH->bbx2),
-					P_imax2((long)(-WITH->bby1), (long)WITH->bby2));
-			calltoolkind(kind[i - 1], act_newkind);
-			P_putbits_UB(loadedgates, i0 - 1, 1, 0, 3);
-			RECOVER(try15);
-			kind[i - 1] = NULL;
-
-			if (P_escapecode == -20)
-			{
-				_Escape(P_escapecode);
-			}
-			else
-			{
-				if (P_escapecode != 0)
-				{
-					beginerror();
-					nc_printf("%d/%d/%ld: ", P_escapecode, i, EXCP_LINE);
-					nc_printf("Unable to read file \"%s\"\n", gatesname[V.f - 1]);
-					enderror();
-				}
-				i = 0;
-				goto _L1;
-			}
-
-			ENDTRY(try15);
-			clipoff();
-			if (gg.showpage == log_page_cat)
-			{
-				udrawgatec((int)(((i - 1) % catwidth * 2 + 1) * gridcen),
-						(int)(((i - 1) / catwidth * 2 + 1) * gridcen), i,
-						gg.color.catgate);
-			}
-_L1:
-			Result = i;
-		}
-	}
-
-	if (!loadit)
-		return count;
-	if (found)
-		return Result;
-	beginerror();
-	nc_printf("Can't find gate \"%s\"\n", n);
-	enderror();
-	Result = 0;
-	if (!gg.initdone)
-		_Escape(0);
-	return Result;
-}
-
-#undef maxvars
-
-
-short readlibrary(char *n)
-{
-	return (readlibrary_at(n, 1, true));
-}
-
 
 static void getgate(char *name, short *gtype)
 {