summaryrefslogtreecommitdiffstats
path: root/src/libs/libgroff/nametoindex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/libgroff/nametoindex.cpp')
-rw-r--r--src/libs/libgroff/nametoindex.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/libs/libgroff/nametoindex.cpp b/src/libs/libgroff/nametoindex.cpp
new file mode 100644
index 0000000..095a432
--- /dev/null
+++ b/src/libs/libgroff/nametoindex.cpp
@@ -0,0 +1,167 @@
+/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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, either version 3 of the License, or
+(at your option) any later version.
+
+groff 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. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "lib.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "errarg.h"
+#include "error.h"
+#include "font.h"
+#include "ptable.h"
+#include "itable.h"
+
+// Every glyphinfo is actually a charinfo.
+class charinfo : glyph {
+public:
+ const char *name; // The glyph name, or a null pointer.
+ friend class character_indexer;
+};
+
+// PTABLE(charinfo) is a hash table mapping 'const char *' to 'charinfo *'.
+declare_ptable(charinfo)
+implement_ptable(charinfo)
+
+// ITABLE(charinfo) is a hash table mapping 'int >= 0' to 'charinfo *'.
+declare_itable(charinfo)
+implement_itable(charinfo)
+
+// This class is as a registry storing all named and numbered glyphs known
+// so far, and assigns a unique index to each glyph.
+class character_indexer {
+public:
+ character_indexer();
+ ~character_indexer();
+ // --------------------- Lookup or creation of a glyph.
+ glyph *ascii_char_glyph(unsigned char);
+ glyph *named_char_glyph(const char *);
+ glyph *numbered_char_glyph(int);
+private:
+ int next_index; // Number of glyphs already allocated.
+ PTABLE(charinfo) table; // Table mapping name to glyph.
+ glyph *ascii_glyph[256]; // Shorthand table for looking up "charNNN"
+ // glyphs.
+ ITABLE(charinfo) ntable; // Table mapping number to glyph.
+ enum { NSMALL = 256 };
+ glyph *small_number_glyph[NSMALL]; // Shorthand table for looking up
+ // numbered glyphs with small numbers.
+};
+
+character_indexer::character_indexer()
+: next_index(0)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ ascii_glyph[i] = UNDEFINED_GLYPH;
+ for (i = 0; i < NSMALL; i++)
+ small_number_glyph[i] = UNDEFINED_GLYPH;
+}
+
+character_indexer::~character_indexer()
+{
+}
+
+glyph *character_indexer::ascii_char_glyph(unsigned char c)
+{
+ if (ascii_glyph[c] == UNDEFINED_GLYPH) {
+ char buf[4+3+1];
+ memcpy(buf, "char", 4);
+ strcpy(buf + 4, i_to_a(c));
+ charinfo *ci = new charinfo;
+ ci->index = next_index++;
+ ci->number = -1;
+ ci->name = strsave(buf);
+ ascii_glyph[c] = ci;
+ }
+ return ascii_glyph[c];
+}
+
+inline glyph *character_indexer::named_char_glyph(const char *s)
+{
+ // Glyphs with name 'charNNN' are only stored in ascii_glyph[], not
+ // in the table. Therefore treat them specially here.
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ char *val;
+ long n = strtol(s + 4, &val, 10);
+ if (val != s + 4 && *val == '\0' && n >= 0 && n < 256)
+ return ascii_char_glyph((unsigned char)n);
+ }
+ charinfo *ci = table.lookupassoc(&s);
+ if (0 == ci) {
+ ci = new charinfo[1];
+ ci->index = next_index++;
+ ci->number = -1;
+ ci->name = table.define(s, ci);
+ }
+ return ci;
+}
+
+inline glyph *character_indexer::numbered_char_glyph(int n)
+{
+ if (n >= 0 && n < NSMALL) {
+ if (small_number_glyph[n] == UNDEFINED_GLYPH) {
+ charinfo *ci = new charinfo;
+ ci->index = next_index++;
+ ci->number = n;
+ ci->name = 0;
+ small_number_glyph[n] = ci;
+ }
+ return small_number_glyph[n];
+ }
+ charinfo *ci = ntable.lookup(n);
+ if (0 == ci) {
+ ci = new charinfo[1];
+ ci->index = next_index++;
+ ci->number = n;
+ ci->name = 0;
+ ntable.define(n, ci);
+ }
+ return ci;
+}
+
+static character_indexer indexer;
+
+glyph *number_to_glyph(int n)
+{
+ return indexer.numbered_char_glyph(n);
+}
+
+// troff overrides this function with its own version.
+
+glyph *name_to_glyph(const char *s)
+{
+ assert(s != 0 && s[0] != '\0' && s[0] != ' ');
+ if (s[1] == '\0')
+ // \200 and char128 are synonyms
+ return indexer.ascii_char_glyph(s[0]);
+ return indexer.named_char_glyph(s);
+}
+
+const char *glyph_to_name(glyph *g)
+{
+ charinfo *ci = (charinfo *)g; // Every glyph is actually a charinfo.
+ return ci->name;
+}
+
+// Local Variables:
+// fill-column: 72
+// mode: C++
+// End:
+// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: