Sync-to-go: update copyright for 2015
[s-roff.git] / src / lib-roff / nametoindex.cpp
blob0c5c160c86f0ebe3bb3896ac7dd0c6f44934a6db
1 /*@
2 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2000 - 2004, 2006, 2008
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
24 #include "lib.h"
26 #include <assert.h>
27 #include <ctype.h>
28 #include <stdlib.h>
30 #include "errarg.h"
31 #include "error.h"
32 #include "font.h"
33 #include "itable.h"
34 #include "ptable.h"
36 // Every glyphinfo is actually a charinfo.
37 class charinfo
38 : glyph
40 public:
41 const char *name; // The glyph name, or NULL.
42 friend class character_indexer;
45 // PTABLE(charinfo) is a hash table mapping `const char *' to `charinfo *'.
46 declare_ptable(charinfo)
47 implement_ptable(charinfo)
49 // ITABLE(charinfo) is a hash table mapping `int >= 0' to `charinfo *'.
50 declare_itable(charinfo)
51 implement_itable(charinfo)
53 // This class is as a registry storing all named and numbered glyphs known
54 // so far, and assigns a unique index to each glyph.
55 class character_indexer
57 int next_index; // Number of glyphs already allocated.
58 PTABLE(charinfo) table; // Table mapping name to glyph.
59 glyph *ascii_glyph[256]; // Shorthand table for looking up "charNNN"
60 // glyphs.
61 ITABLE(charinfo) ntable; // Table mapping number to glyph.
62 enum { NSMALL = 256 };
63 glyph *small_number_glyph[NSMALL]; // Shorthand table for looking up
64 // numbered glyphs with small numbers.
66 public:
67 character_indexer();
68 ~character_indexer();
69 // --------------------- Lookup or creation of a glyph.
70 glyph *ascii_char_glyph(unsigned char);
71 glyph *named_char_glyph(const char *);
72 glyph *numbered_char_glyph(int);
75 character_indexer::character_indexer()
76 : next_index(0)
78 int i;
79 for (i = 0; i < 256; i++)
80 ascii_glyph[i] = UNDEFINED_GLYPH;
81 for (i = 0; i < NSMALL; i++)
82 small_number_glyph[i] = UNDEFINED_GLYPH;
85 character_indexer::~character_indexer()
89 glyph *character_indexer::ascii_char_glyph(unsigned char c)
91 if (ascii_glyph[c] == UNDEFINED_GLYPH) {
92 char buf[4+3+1];
93 memcpy(buf, "char", 4);
94 strcpy(buf + 4, i_to_a(c));
95 charinfo *ci = new charinfo;
96 ci->index = next_index++;
97 ci->number = -1;
98 ci->name = strsave(buf);
99 ascii_glyph[c] = ci;
101 return ascii_glyph[c];
104 inline glyph *character_indexer::named_char_glyph(const char *s)
106 // Glyphs with name `charNNN' are only stored in ascii_glyph[], not
107 // in the table. Therefore treat them specially here.
108 if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
109 char *val;
110 long n = strtol(s + 4, &val, 10);
111 if (val != s + 4 && *val == '\0' && n >= 0 && n < 256)
112 return ascii_char_glyph((unsigned char)n);
114 charinfo *ci = table.lookupassoc(&s);
115 if (ci == NULL) {
116 ci = new charinfo[1];
117 ci->index = next_index++;
118 ci->number = -1;
119 ci->name = table.define(s, ci);
121 return ci;
124 inline glyph *character_indexer::numbered_char_glyph(int n)
126 if (n >= 0 && n < NSMALL) {
127 if (small_number_glyph[n] == UNDEFINED_GLYPH) {
128 charinfo *ci = new charinfo;
129 ci->index = next_index++;
130 ci->number = n;
131 ci->name = NULL;
132 small_number_glyph[n] = ci;
134 return small_number_glyph[n];
136 charinfo *ci = ntable.lookup(n);
137 if (ci == NULL) {
138 ci = new charinfo[1];
139 ci->index = next_index++;
140 ci->number = n;
141 ci->name = NULL;
142 ntable.define(n, ci);
144 return ci;
147 static character_indexer indexer;
149 glyph *number_to_glyph(int n)
151 return indexer.numbered_char_glyph(n);
154 // troff overrides this function with its own version.
156 glyph *name_to_glyph(const char *s)
158 assert(s != 0 && s[0] != '\0' && s[0] != ' ');
159 if (s[1] == '\0')
160 // \200 and char128 are synonyms
161 return indexer.ascii_char_glyph(s[0]);
162 return indexer.named_char_glyph(s);
165 const char *glyph_to_name(glyph *g)
167 charinfo *ci = (charinfo *)g; // Every glyph is actually a charinfo.
168 return ci->name;
171 // s-it2-mode