2 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
31 // Every glyphinfo is actually a charinfo.
32 class charinfo : glyph {
34 const char *name; // The glyph name, or NULL.
35 friend class character_indexer;
38 // PTABLE(charinfo) is a hash table mapping `const char *' to `charinfo *'.
39 declare_ptable(charinfo)
40 implement_ptable(charinfo)
42 // ITABLE(charinfo) is a hash table mapping `int >= 0' to `charinfo *'.
43 declare_itable(charinfo)
44 implement_itable(charinfo)
46 // This class is as a registry storing all named and numbered glyphs known
47 // so far, and assigns a unique index to each glyph.
48 class character_indexer {
52 // --------------------- Lookup or creation of a glyph.
53 glyph *ascii_char_glyph(unsigned char);
54 glyph *named_char_glyph(const char *);
55 glyph *numbered_char_glyph(int);
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"
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.
67 character_indexer::character_indexer()
71 for (i = 0; i < 256; i++)
72 ascii_glyph[i] = UNDEFINED_GLYPH;
73 for (i = 0; i < NSMALL; i++)
74 small_number_glyph[i] = UNDEFINED_GLYPH;
77 character_indexer::~character_indexer()
81 glyph *character_indexer::ascii_char_glyph(unsigned char c)
83 if (ascii_glyph[c] == UNDEFINED_GLYPH) {
85 memcpy(buf, "char", 4);
86 strcpy(buf + 4, i_to_a(c));
87 charinfo *ci = new charinfo;
88 ci->index = next_index++;
90 ci->name = strsave(buf);
93 return ascii_glyph[c];
96 inline glyph *character_indexer::named_char_glyph(const char *s)
98 // Glyphs with name `charNNN' are only stored in ascii_glyph[], not
99 // in the table. Therefore treat them specially here.
100 if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
102 long n = strtol(s + 4, &val, 10);
103 if (val != s + 4 && *val == '\0' && n >= 0 && n < 256)
104 return ascii_char_glyph((unsigned char)n);
106 charinfo *ci = table.lookupassoc(&s);
108 ci = new charinfo[1];
109 ci->index = next_index++;
111 ci->name = table.define(s, ci);
116 inline glyph *character_indexer::numbered_char_glyph(int n)
118 if (n >= 0 && n < NSMALL) {
119 if (small_number_glyph[n] == UNDEFINED_GLYPH) {
120 charinfo *ci = new charinfo;
121 ci->index = next_index++;
124 small_number_glyph[n] = ci;
126 return small_number_glyph[n];
128 charinfo *ci = ntable.lookup(n);
130 ci = new charinfo[1];
131 ci->index = next_index++;
134 ntable.define(n, ci);
139 static character_indexer indexer;
141 glyph *number_to_glyph(int n)
143 return indexer.numbered_char_glyph(n);
146 // troff overrides this function with its own version.
148 glyph *name_to_glyph(const char *s)
150 assert(s != 0 && s[0] != '\0' && s[0] != ' ');
152 // \200 and char128 are synonyms
153 return indexer.ascii_char_glyph(s[0]);
154 return indexer.named_char_glyph(s);
157 const char *glyph_to_name(glyph *g)
159 charinfo *ci = (charinfo *)g; // Every glyph is actually a charinfo.