2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
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
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
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.
36 // Every glyphinfo is actually a charinfo.
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"
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.
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()
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
) {
93 memcpy(buf
, "char", 4);
94 strcpy(buf
+ 4, i_to_a(c
));
95 charinfo
*ci
= new charinfo
;
96 ci
->index
= next_index
++;
98 ci
->name
= strsave(buf
);
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') {
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
);
116 ci
= new charinfo
[1];
117 ci
->index
= next_index
++;
119 ci
->name
= table
.define(s
, 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
++;
132 small_number_glyph
[n
] = ci
;
134 return small_number_glyph
[n
];
136 charinfo
*ci
= ntable
.lookup(n
);
138 ci
= new charinfo
[1];
139 ci
->index
= next_index
++;
142 ntable
.define(n
, 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] != ' ');
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.