g_cntrlify.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* _pl_g_controlify() converts a "label" (i.e. a character string), which may
  16. contain troff-like escape sequences, into a string of unsigned shorts.
  17. The possible troff-like escape sequences are listed in g_cntrlify.h.
  18. This conversion is to facilitate rendering. _pl_g_controlify() is
  19. called by alabel(), and the converted label is rendered by
  20. _alabel_standard(), _alabel_stroke(), or _alabel_device(), depending on
  21. what sort of font is currently selected. See g_alabel.c
  22. (_pl_g_controlify() is called by labelwidth() too).
  23. If the currently selected font is a font with ISO-Latin-1 encoding, the
  24. valid escape sequences include escape sequences for the non-ASCII
  25. ISO-Latin-1 characters. Also allowed are such escape sequences as \f0,
  26. \f1, \f2, \f3, \f4, etc., which switch among the various fonts in the
  27. current typeface:
  28. \f1 Switch to font #1, basic
  29. \f2 Switch to font #2, italic
  30. \f3 Switch to font #3, bold
  31. \f4 Switch to font #4, bold italic
  32. \f0 Switch to font #0, symbol (including Greek characters)
  33. \fP switches to the previously used font (there is a depth-1 stack,
  34. i.e. only one previous font is remembered, as in troff).
  35. All typefaces include at least two fonts: fonts #0 and #1. Some may
  36. include more than the above five. Each unsigned short in the converted
  37. string is really an annotated character: the low byte is the character,
  38. and the high byte is the font number.
  39. Besides font annotations, the controlified string may include control
  40. codes (unsigned shorts with particular bit patterns in their high
  41. bytes), which are produced by the escape sequences:
  42. \sp start superscript
  43. \ep end superscript
  44. \sb start subscript
  45. \eb end subscript
  46. \mk mark location
  47. \rt return to mark
  48. [useful e.g. for underlining, and filling square roots]
  49. There are also control codes for horizontal shifts. \r1, \r2, \r4,
  50. \r6, \r8, \r^ will produce control codes that will shift right by 1 em,
  51. 1/2 em, 1/4 em, 1/6 em, 1/8 em, 1/12 em, respectively. \l1, \l2, \l4,
  52. \l6, \l8, \l^ are similar.
  53. The string of unsigned shorts, which is returned, is allocated with
  54. malloc and may be freed later. */
  55. #include "sys-defines.h"
  56. #include "extern.h"
  57. #include "g_control.h"
  58. #include "g_cntrlify.h"
  59. #include "g_jis.h"
  60. /* these two array lengths must agree with values in file g_her_glyph.c */
  61. #define NUM_OCCIDENTAL_HERSHEY_GLYPHS 4400
  62. #define NUM_ORIENTAL_HERSHEY_GLYPHS 5500
  63. unsigned short *
  64. _pl_g_controlify (R___(Plotter *_plotter) const unsigned char *src)
  65. {
  66. unsigned short *dest;
  67. unsigned char c, d;
  68. unsigned char esc[3];
  69. int j = 0; /* index into destination string */
  70. int raw_fontnum, raw_symbol_fontnum;
  71. int previous_raw_fontnum; /* implement depth-1 stack */
  72. unsigned short fontword, symbol_fontword;
  73. /* note: string length can grow by a factor of 6, because a single
  74. printable character can be mapped to a sequence of unsigned shorts, of
  75. length up to 6 (see comment below) */
  76. dest = (unsigned short *)_pl_xmalloc ((6 * strlen ((char *)src) + 1) * sizeof(unsigned short));
  77. /* Determine initial number of font, as index into low-level table in
  78. g_fontdb.c, and the initial value for the shifted `font word' which
  79. we'll OR with each character; also same, for associated symbol font.
  80. May be updated by \f0, \f1, etc. */
  81. switch (_plotter->drawstate->font_type)
  82. {
  83. case PL_F_POSTSCRIPT:
  84. default:
  85. raw_fontnum = _pl_g_ps_typeface_info[_plotter->drawstate->typeface_index].fonts[_plotter->drawstate->font_index];
  86. raw_symbol_fontnum = _pl_g_ps_typeface_info[_plotter->drawstate->typeface_index].fonts[0];
  87. break;
  88. case PL_F_PCL:
  89. raw_fontnum = _pl_g_pcl_typeface_info[_plotter->drawstate->typeface_index].fonts[_plotter->drawstate->font_index];
  90. raw_symbol_fontnum = _pl_g_pcl_typeface_info[_plotter->drawstate->typeface_index].fonts[0];
  91. break;
  92. case PL_F_STICK:
  93. raw_fontnum = _pl_g_stick_typeface_info[_plotter->drawstate->typeface_index].fonts[_plotter->drawstate->font_index];
  94. raw_symbol_fontnum = _pl_g_stick_typeface_info[_plotter->drawstate->typeface_index].fonts[0];
  95. break;
  96. case PL_F_HERSHEY:
  97. raw_fontnum = _pl_g_hershey_typeface_info[_plotter->drawstate->typeface_index].fonts[_plotter->drawstate->font_index];
  98. raw_symbol_fontnum = _pl_g_hershey_typeface_info[_plotter->drawstate->typeface_index].fonts[0];
  99. break;
  100. case PL_F_OTHER:
  101. /* no real font table in this case; by convention font #1 internally
  102. means the current device-specific font and #0 is an associated
  103. symbol font */
  104. raw_fontnum = 1;
  105. raw_symbol_fontnum = 0;
  106. break;
  107. }
  108. /* Of the following two words, `fontword' is updated whenever an escape
  109. sequence like \f0, \f1, \f2 etc. is seen, since raw_fontnum is itself
  110. updated. But `symbol_fontword' is fixed */
  111. fontword = ((unsigned short)raw_fontnum) << FONT_SHIFT;
  112. symbol_fontword = ((unsigned short)raw_symbol_fontnum) << FONT_SHIFT;
  113. /* Implement depth-1 stack of fonts, for use by \fP macro */
  114. previous_raw_fontnum = raw_fontnum;
  115. while (*src != (unsigned char)'\0')
  116. {
  117. /* If EUC, check first for high bit and process two-byte characters
  118. separately. This approach is awkward (we duplicate a lot of code
  119. here, which appears elsewhere below). */
  120. if ((raw_fontnum == PL_HERSHEY_EUC)
  121. && (*src & 0x80) && (*(src + 1) & 0x80))
  122. {
  123. unsigned char jis_row = *src & ~(0x80);
  124. unsigned char jis_col = *(src + 1) & ~(0x80);
  125. if (GOOD_JIS_INDEX(jis_row, jis_col))
  126. {
  127. int jis_glyphindex = 256 * jis_row + jis_col;
  128. if (jis_glyphindex >= BEGINNING_OF_KANJI)
  129. /* in Kanji range, so check if we have it */
  130. {
  131. #ifndef NO_KANJI
  132. const struct kanjipair *kanji = _builtin_kanji_glyphs;
  133. bool matched = false;
  134. while (kanji->jis != 0)
  135. {
  136. if (jis_glyphindex == kanji->jis)
  137. {
  138. matched = true;
  139. break;
  140. }
  141. kanji++;
  142. }
  143. if (matched)
  144. {
  145. dest[j++] = RAW_ORIENTAL_HERSHEY_GLYPH | (kanji->nelson);
  146. src += 2;
  147. continue; /* back to top of while loop */
  148. }
  149. else /* a Kanji we don't have */
  150. {
  151. /* render as standard `undefined character' glyph */
  152. dest[j++] = RAW_HERSHEY_GLYPH | UNDE;
  153. src += 2;
  154. continue; /* back to top of while loop */
  155. }
  156. #endif /* not NO_KANJI */
  157. }
  158. else
  159. /* not in Kanji range, so look for it in char table */
  160. {
  161. const struct jis_entry *char_mapping = _builtin_jis_chars;
  162. bool matched = false;
  163. while (char_mapping->jis != 0)
  164. {
  165. if (jis_glyphindex == char_mapping->jis)
  166. {
  167. matched = true;
  168. break;
  169. }
  170. char_mapping++;
  171. }
  172. if (matched)
  173. /* the entry in the character table maps the JIS
  174. character to a character (in 0..255 range) in
  175. one of the fonts in the master table in g_fontdb.c */
  176. {
  177. int fontnum = char_mapping->font;
  178. unsigned short charnum = char_mapping->charnum;
  179. if (charnum & RAW_HERSHEY_GLYPH)
  180. /* a raw Hershey glyph, not in any font */
  181. dest[j++] = RAW_HERSHEY_GLYPH | charnum;
  182. else
  183. /* a character in one of the fonts in g_fontdb.c */
  184. dest[j++] = (((unsigned short)fontnum) << FONT_SHIFT) | charnum;
  185. src += 2;
  186. continue; /* back to top of while loop */
  187. }
  188. else /* a character we don't have */
  189. {
  190. /* render as standard `undefined character' glyph */
  191. dest[j++] = RAW_HERSHEY_GLYPH | UNDE;
  192. src += 2;
  193. continue; /* back to top of while loop */
  194. }
  195. }
  196. }
  197. else
  198. /* JIS index is OOB */
  199. {
  200. src += 2;
  201. continue; /* back to top of while loop */
  202. }
  203. }
  204. /* if current font is Hershey, first try to match each ligature
  205. pattern (no ligatures supported in non-Hershey fonts) */
  206. if (_plotter->drawstate->font_type == PL_F_HERSHEY)
  207. {
  208. int i;
  209. bool matched = false;
  210. for (i = 0; i < NUM_LIGATURES; i++)
  211. if ((_ligature_tbl[i].font == raw_fontnum)
  212. && (strncmp ((char *)src, _ligature_tbl[i].from,
  213. strlen (_ligature_tbl[i].from)) == 0))
  214. {
  215. matched = true;
  216. break;
  217. }
  218. if (matched)
  219. {
  220. dest[j++] = fontword | (unsigned short)_ligature_tbl[i].byte;
  221. src += strlen (_ligature_tbl[i].from);
  222. continue; /* back to top of while loop */
  223. }
  224. }
  225. c = *(src++); /* no ligature, so get single new char */
  226. if (c != (unsigned char)'\\') /* ordinary char, may pass through */
  227. {
  228. /* if current font is an ISO-Latin-1 Hershey font ... */
  229. if (_plotter->drawstate->font_type == PL_F_HERSHEY
  230. && _pl_g_hershey_font_info[raw_fontnum].iso8859_1)
  231. {
  232. int i;
  233. bool matched = false;
  234. /* check if this is a `raised' ISO-Latin-1 character */
  235. for (i = 0; i < NUM_RAISED_CHARS; i++)
  236. if (c == _raised_char_tbl[i].from)
  237. {
  238. matched = true;
  239. break;
  240. }
  241. if (matched) /* it's a raised character */
  242. {
  243. /* map to string of unsigned shorts, length 3 or 6:
  244. `begin superscript' control code, [`mark'
  245. control code,] replacement char, [`return'
  246. control code, underline,] `end superscript' */
  247. dest[j++] =
  248. (unsigned short) (CONTROL_CODE | C_BEGIN_SUPERSCRIPT);
  249. if (_raised_char_tbl[i].underscored) /* also underline */
  250. {
  251. dest[j++] =
  252. (unsigned short) (CONTROL_CODE | C_PUSH_LOCATION);
  253. dest[j++] =
  254. fontword | (unsigned short)_raised_char_tbl[i].to;
  255. dest[j++] =
  256. (unsigned short) (CONTROL_CODE | C_POP_LOCATION);
  257. /* select appropriate HersheySymbol font */
  258. dest[j++] =
  259. symbol_fontword | (unsigned short)VECTOR_SYMBOL_FONT_UNDERSCORE;
  260. }
  261. else /* just print raised char, no underline */
  262. dest[j++] =
  263. fontword | (unsigned short)_raised_char_tbl[i].to;
  264. dest[j++] =
  265. (unsigned short) (CONTROL_CODE | C_END_SUPERSCRIPT);
  266. continue; /* back to top of while loop */
  267. }
  268. /* since current font is an ISO-Latin-1 Hershey font, also
  269. check if this char should be deligatured */
  270. for (i = 0; i < NUM_DELIGATURED_CHARS; i++)
  271. if (c == _deligature_char_tbl[i].from)
  272. {
  273. matched = true;
  274. break;
  275. }
  276. if (matched)
  277. {
  278. if (_deligature_char_tbl[i].except_font != raw_fontnum)
  279. {
  280. dest[j++] = fontword
  281. | (unsigned short)_deligature_char_tbl[i].to[0];
  282. dest[j++] = fontword
  283. | (unsigned short)_deligature_char_tbl[i].to[1];
  284. continue; /* back to top of while loop */
  285. }
  286. }
  287. }
  288. /* didn't do anything special, so just pass the character thru */
  289. dest[j++] = fontword | (unsigned short)c;
  290. continue; /* back to top of while loop */
  291. }
  292. else /* character is a backslash */
  293. {
  294. c = *(src++); /* grab next character */
  295. if (c == (unsigned char)'\0') /* ASCII NUL ? */
  296. {
  297. dest[j++] = fontword | (unsigned short)'\\';
  298. break; /* string terminated with a backslash */
  299. }
  300. if (c == (unsigned char)'\\')
  301. {
  302. dest[j++] = fontword | (unsigned short)'\\';
  303. dest[j++] = fontword | (unsigned short)'\\';
  304. continue; /* saw \\, leave as is */
  305. }
  306. d = *(src++);
  307. if (d == (unsigned char)'\0')
  308. {
  309. dest[j++] = fontword | (unsigned short)'\\';
  310. dest[j++] = fontword | (unsigned short)c;
  311. break; /* string terminated with \c */
  312. }
  313. esc[0] = c;
  314. esc[1] = d;
  315. esc[2] = (unsigned char)'\0'; /* have an escape sequence */
  316. /* is this an escape seq. (e.g. \#H0001) for a raw Hershey glyph? */
  317. if (_plotter->drawstate->font_type == PL_F_HERSHEY
  318. && esc[0] == '#' && esc[1] == 'H'
  319. && src[0] >= '0' && src[0] <= '9'
  320. && src[1] >= '0' && src[1] <= '9'
  321. && src[2] >= '0' && src[2] <= '9'
  322. && src[3] >= '0' && src[3] <= '9')
  323. {
  324. int glyphindex;
  325. glyphindex = (src[3] - '0') + 10 * (src[2] - '0')
  326. + 100 * (src[1] - '0') + 1000 * (src[0] - '0');
  327. if (glyphindex < NUM_OCCIDENTAL_HERSHEY_GLYPHS)
  328. {
  329. dest[j++] = RAW_HERSHEY_GLYPH | glyphindex;
  330. src += 4;
  331. continue; /* back to top of while loop */
  332. }
  333. }
  334. #ifndef NO_KANJI
  335. /* is this an escape seq. (e.g. \#N0001) for a raw Japanese
  336. Hershey glyph (Kanji), as numbered in Nelson's dictionary? */
  337. if (_plotter->drawstate->font_type == PL_F_HERSHEY
  338. && esc[0] == '#' && esc[1] == 'N'
  339. && src[0] >= '0' && src[0] <= '9'
  340. && src[1] >= '0' && src[1] <= '9'
  341. && src[2] >= '0' && src[2] <= '9'
  342. && src[3] >= '0' && src[3] <= '9')
  343. {
  344. int glyphindex;
  345. glyphindex = (src[3] - '0') + 10 * (src[2] - '0')
  346. + 100 * (src[1] - '0') + 1000 * (src[0] - '0');
  347. if (glyphindex < NUM_ORIENTAL_HERSHEY_GLYPHS)
  348. {
  349. dest[j++] = RAW_ORIENTAL_HERSHEY_GLYPH | glyphindex;
  350. src += 4;
  351. continue; /* back to top of while loop */
  352. }
  353. }
  354. #endif /* not NO_KANJI */
  355. /* is this an escape seq. (e.g. \#J0001) for a raw Japanese
  356. Hershey glyph (JIS numbering, in hex)? */
  357. if (_plotter->drawstate->font_type == PL_F_HERSHEY
  358. && esc[0] == '#' && esc[1] == 'J'
  359. && ((src[0] >= '0' && src[0] <= '9')
  360. || (src[0] >= 'a' && src[0] <= 'f')
  361. || (src[0] >= 'A' && src[0] <= 'F'))
  362. && ((src[1] >= '0' && src[1] <= '9')
  363. || (src[1] >= 'a' && src[1] <= 'f')
  364. || (src[1] >= 'A' && src[1] <= 'F'))
  365. && ((src[2] >= '0' && src[2] <= '9')
  366. || (src[2] >= 'a' && src[2] <= 'f')
  367. || (src[2] >= 'A' && src[2] <= 'F'))
  368. && ((src[3] >= '0' && src[3] <= '9')
  369. || (src[3] >= 'a' && src[3] <= 'f')
  370. || (src[3] >= 'A' && src[3] <= 'F')))
  371. {
  372. int jis_glyphindex;
  373. int i, hexnum[4];
  374. int jis_row, jis_col;
  375. for (i = 0; i < 4; i++)
  376. if (src[i] >= 'a' && src[i] <= 'f')
  377. hexnum[i] = 10 + src[i] - 'a';
  378. else if (src[i] >= 'A' && src[i] <= 'F')
  379. hexnum[i] = 10 + src[i] - 'A';
  380. else /* a decimal digit */
  381. hexnum[i] = src[i] - '0';
  382. jis_glyphindex = (hexnum[3] + 16 * hexnum[2]
  383. + 256 * hexnum[1] + 4096 * hexnum[0]);
  384. jis_row = hexnum[1] + 16 * hexnum[0];
  385. jis_col = hexnum[3] + 16 * hexnum[2];
  386. if (GOOD_JIS_INDEX(jis_row, jis_col))
  387. {
  388. if (jis_glyphindex >= BEGINNING_OF_KANJI)
  389. /* in Kanji range, so check if we have it */
  390. {
  391. #ifndef NO_KANJI
  392. const struct kanjipair *kanji = _builtin_kanji_glyphs;
  393. bool matched = false;
  394. while (kanji->jis != 0)
  395. {
  396. if (jis_glyphindex == kanji->jis)
  397. {
  398. matched = true;
  399. break;
  400. }
  401. kanji++;
  402. }
  403. if (matched)
  404. {
  405. dest[j++] = RAW_ORIENTAL_HERSHEY_GLYPH | (kanji->nelson);
  406. src += 4;
  407. continue; /* back to top of while loop */
  408. }
  409. else /* a Kanji we don't have */
  410. {
  411. /* render as standard `undefined character' glyph */
  412. dest[j++] = RAW_HERSHEY_GLYPH | UNDE;
  413. src += 4;
  414. continue; /* back to top of while loop */
  415. }
  416. #endif /* not NO_KANJI */
  417. }
  418. else
  419. /* not in Kanji range, so look for it in char table */
  420. {
  421. const struct jis_entry *char_mapping = _builtin_jis_chars;
  422. bool matched = false;
  423. while (char_mapping->jis != 0)
  424. {
  425. if (jis_glyphindex == char_mapping->jis)
  426. {
  427. matched = true;
  428. break;
  429. }
  430. char_mapping++;
  431. }
  432. if (matched)
  433. /* the entry in the character table maps the JIS
  434. character to a character (in 0..255 range) in
  435. one of the fonts in the master table in g_fontdb.c*/
  436. {
  437. int fontnum = char_mapping->font;
  438. unsigned short charnum = char_mapping->charnum;
  439. if (charnum & RAW_HERSHEY_GLYPH)
  440. /* a raw Hershey glyph, not in any font */
  441. dest[j++] = RAW_HERSHEY_GLYPH | charnum;
  442. else
  443. /* a character in one of the fonts in g_fontdb.c */
  444. dest[j++] = (((unsigned short)fontnum) << FONT_SHIFT) | charnum;
  445. src += 4;
  446. continue; /* back to top of while loop */
  447. }
  448. else /* a character we don't have */
  449. {
  450. /* render as standard `undefined character' glyph */
  451. dest[j++] = RAW_HERSHEY_GLYPH | UNDE;
  452. src += 4;
  453. continue; /* back to top of while loop */
  454. }
  455. }
  456. }
  457. }
  458. {
  459. int i;
  460. bool matched = false;
  461. /* is this an escape seq. for a control code? */
  462. for (i = 0; i < NUM_CONTROLS; i++)
  463. if (strcmp ((char *)esc, _control_tbl[i]) == 0)
  464. {
  465. matched = true;
  466. break;
  467. }
  468. if (matched) /* it's a control code */
  469. {
  470. dest[j++] = CONTROL_CODE | i;
  471. continue; /* back to top of while loop */
  472. }
  473. }
  474. /* if current font is an ISO-Latin-1 Hershey font, is this an
  475. escape sequence for an 8-bit (non-ASCII) char, which due to
  476. nonexistence should be deligatured? */
  477. if (_plotter->drawstate->font_type == PL_F_HERSHEY
  478. && _pl_g_hershey_font_info[raw_fontnum].iso8859_1)
  479. {
  480. int i;
  481. bool matched = false;
  482. for (i = 0; i < NUM_DELIGATURED_ESCAPES; i++)
  483. if (strcmp ((char *)esc, _deligature_escape_tbl[i].from) == 0)
  484. {
  485. matched = true;
  486. break;
  487. }
  488. if (matched)
  489. {
  490. if (_deligature_escape_tbl[i].except_font != raw_fontnum)
  491. {
  492. dest[j++] = fontword
  493. | (unsigned short)_deligature_escape_tbl[i].to[0];
  494. dest[j++] = fontword
  495. | (unsigned short)_deligature_escape_tbl[i].to[1];
  496. continue; /* back to top of while loop */
  497. }
  498. }
  499. }
  500. /* if the current font is an ISO-Latin-1 font (no matter whether
  501. font is a a Hershey font, a PS or PCL/Stick font, or a
  502. device-specific font for which we have no table entry), is
  503. this an escape seq. for an 8-bit (non-ASCII) ISO8859-1 char? */
  504. if ((_plotter->drawstate->font_type == PL_F_POSTSCRIPT
  505. && _pl_g_ps_font_info[raw_fontnum].iso8859_1)
  506. || (_plotter->drawstate->font_type == PL_F_HERSHEY
  507. && _pl_g_hershey_font_info[raw_fontnum].iso8859_1)
  508. || (_plotter->drawstate->font_type == PL_F_PCL
  509. && _pl_g_pcl_font_info[raw_fontnum].iso8859_1)
  510. || (_plotter->drawstate->font_type == PL_F_STICK
  511. && _pl_g_stick_font_info[raw_fontnum].iso8859_1)
  512. || (_plotter->drawstate->font_type == PL_F_OTHER
  513. && _plotter->drawstate->font_is_iso8859_1
  514. && raw_fontnum == 1))
  515. {
  516. int i;
  517. bool matched = false;
  518. for (i = 0; i < NUM_ISO_ESCAPES; i++)
  519. if (strcmp ((char *)esc, _iso_escape_tbl[i].string) == 0)
  520. {
  521. matched = true;
  522. break;
  523. }
  524. if (matched) /* it's an 8-bit ISO8859-1 character */
  525. {
  526. /* certain such characters are drawn in the Hershey fonts
  527. as superscripts */
  528. if (_plotter->drawstate->font_type == PL_F_HERSHEY)
  529. {
  530. int k;
  531. bool matched2 = false;
  532. /* check if this is a `raised' ISO-Latin-1 character */
  533. for (k = 0; k < NUM_RAISED_CHARS; k++)
  534. if (_iso_escape_tbl[i].byte == _raised_char_tbl[k].from)
  535. {
  536. matched2 = true;
  537. break;
  538. }
  539. if (matched2) /* it's a raised character */
  540. {
  541. /* map to string of unsigned shorts, length 3 or 6:
  542. `begin superscript' control code, [`mark'
  543. control code,] replacement char, [`return'
  544. control code, underline,] `end superscript' */
  545. dest[j++] =
  546. (unsigned short) (CONTROL_CODE | C_BEGIN_SUPERSCRIPT);
  547. if (_raised_char_tbl[k].underscored) /* also underline */
  548. {
  549. dest[j++] =
  550. (unsigned short) (CONTROL_CODE | C_PUSH_LOCATION);
  551. dest[j++] =
  552. fontword | (unsigned short)_raised_char_tbl[k].to;
  553. dest[j++] =
  554. (unsigned short) (CONTROL_CODE | C_POP_LOCATION);
  555. /* select appropriate HersheySymbol font */
  556. dest[j++] =
  557. symbol_fontword | (unsigned short)VECTOR_SYMBOL_FONT_UNDERSCORE;
  558. }
  559. else /* just print raised char, no underline */
  560. {
  561. dest[j++] =
  562. fontword | (unsigned short)_raised_char_tbl[k].to;
  563. }
  564. dest[j++] =
  565. (unsigned short) (CONTROL_CODE | C_END_SUPERSCRIPT);
  566. continue; /* back to top of while loop */
  567. }
  568. }
  569. /* won't draw this char as a superscript; just pass thru */
  570. dest[j++] = fontword | (unsigned short)(_iso_escape_tbl[i].byte);
  571. continue; /* back to top of while loop */
  572. }
  573. }
  574. /* is this an escape seq. for a `special' (non-ISO, non-Symbol)
  575. Hershey glyph? Such glyphs include astronomical signs, and
  576. `final s'. */
  577. if (_plotter->drawstate->font_type == PL_F_HERSHEY)
  578. {
  579. int i;
  580. bool matched = false;
  581. for (i = 0; i < NUM_SPECIAL_ESCAPES; i++)
  582. if (strcmp ((char *)esc, _special_escape_tbl[i].string) == 0)
  583. {
  584. matched = true;
  585. break;
  586. }
  587. if (matched) /* it's a special character */
  588. {
  589. /* "\s-" is special; yields character in current font */
  590. if (_special_escape_tbl[i].byte == FINAL_LOWERCASE_S)
  591. dest[j++] =
  592. fontword | (unsigned short)(_special_escape_tbl[i].byte);
  593. else
  594. /* we select symbol font of typeface, in which we've
  595. stored all other special characters */
  596. dest[j++] = symbol_fontword | (unsigned short)(_special_escape_tbl[i].byte);
  597. continue; /* back to top of while loop */
  598. }
  599. }
  600. {
  601. int i;
  602. bool matched = false;
  603. /* Irrespective of font type, is this an escape seq. for a char
  604. in the font's corresponding symbol font? */
  605. for (i = 0; i < NUM_SYMBOL_ESCAPES; i++)
  606. if (strcmp (_symbol_escape_tbl[i].string, "NO_ABBREV") != 0
  607. && strcmp ((char *)esc, _symbol_escape_tbl[i].string) == 0)
  608. {
  609. matched = true;
  610. break;
  611. }
  612. if (matched) /* it's a character in the symbol font */
  613. {
  614. /* select symbol font by OR'ing in the symbol fontword */
  615. dest[j++] = symbol_fontword | (unsigned short)(_symbol_escape_tbl[i].byte);
  616. continue; /* back to top of while loop */
  617. }
  618. }
  619. /* Gross kludge. In the non-Hershey fonts we handle the "\rn"
  620. control sequence in a painful way. For a PS font we map it
  621. into (1) a left shift, (2) the `radicalex' character in the PS
  622. Symbol font, and (3) a right shift. Shift distances are taken
  623. from the bbox of the radicalex char, and are slightly larger
  624. than 0.5 em. For a PCL font it's similar, but the shifts are
  625. much smaller. The reason it's different for PCL is that the
  626. PCL radicalex character is different from the PS radicalex
  627. character: the overbar is not displaced. Possibly someone at
  628. HP made a mistake while reimplementing the Adobe Symbol font
  629. for PCL 5?
  630. We don't implement \rn for Stick fonts, because they have
  631. no associated symbol font. */
  632. if (strcmp ((char *)esc, "rn") == 0)
  633. {
  634. if (_plotter->drawstate->font_type == PL_F_POSTSCRIPT
  635. || _plotter->drawstate->font_type == PL_F_PCL)
  636. {
  637. dest[j++]
  638. = (unsigned short)(CONTROL_CODE | C_LEFT_RADICAL_SHIFT);
  639. /* take `radicalex' glyph from PS symbol font */
  640. dest[j++]
  641. = symbol_fontword | (unsigned short)RADICALEX;
  642. dest[j++]
  643. = (unsigned short)(CONTROL_CODE | C_RIGHT_RADICAL_SHIFT);
  644. continue; /* back to top of while loop */
  645. }
  646. }
  647. /* Attempt to parse as a font-change command, i.e. as one of the
  648. macros \f0, \f1, \f2, etc., or \fP. \fR, \fI, \fB are the
  649. same as \f1, \f2, \f3 for troff compatibility. */
  650. if (esc[0] == 'f' && ((esc[1] >= '0' && esc[1] <= '9')
  651. || esc[1] == 'P' || esc[1] == 'R'
  652. || esc[1] == 'I' || esc[1] == 'B'))
  653. {
  654. /* If a user-specified, device-specific font [e.g. an X font,
  655. for which we have no internal table listing the other
  656. fonts in its family] is being used, we can't really do
  657. font switching, except via \f0, \f1. These switch to the
  658. X symbol font and the current user-specified font,
  659. respectively. (\fP is also supported.) */
  660. if (_plotter->drawstate->font_type == PL_F_OTHER
  661. && ((esc[1] >= '2' && esc[1] <= '9')
  662. || esc[1] == 'I' || esc[1] == 'B'))
  663. esc[1] = '1'; /* treat as \f1 */
  664. /* troff compatibility */
  665. if (esc[1] == 'R')
  666. esc[1] = '1';
  667. else if (esc[1] == 'I')
  668. esc[1] = '2';
  669. else if (esc[1] == 'B')
  670. esc[1] = '3';
  671. if (esc[1] == 'P') /* \fP seen, so go back to previous font */
  672. raw_fontnum = previous_raw_fontnum;
  673. else /* font specified as index into typeface */
  674. {
  675. int new_font_index = esc[1] - '0';
  676. /* switch to specified font (OOB tests here now obsolete?) */
  677. previous_raw_fontnum = raw_fontnum;
  678. switch (_plotter->drawstate->font_type)
  679. {
  680. case PL_F_HERSHEY:
  681. if ((new_font_index >= _pl_g_hershey_typeface_info[_plotter->drawstate->typeface_index].numfonts)
  682. || new_font_index < 0)
  683. new_font_index = 1; /* OOB -> use default font */
  684. raw_fontnum = _pl_g_hershey_typeface_info[_plotter->drawstate->typeface_index].fonts[new_font_index];
  685. break;
  686. case PL_F_PCL:
  687. if ((new_font_index >= _pl_g_pcl_typeface_info[_plotter->drawstate->typeface_index].numfonts)
  688. || new_font_index < 0)
  689. new_font_index = 1; /* OOB -> use default font */
  690. raw_fontnum = _pl_g_pcl_typeface_info[_plotter->drawstate->typeface_index].fonts[new_font_index];
  691. break;
  692. case PL_F_STICK:
  693. if ((new_font_index >= _pl_g_stick_typeface_info[_plotter->drawstate->typeface_index].numfonts)
  694. || new_font_index < 0)
  695. new_font_index = 1; /* OOB -> use default font */
  696. raw_fontnum = _pl_g_stick_typeface_info[_plotter->drawstate->typeface_index].fonts[new_font_index];
  697. break;
  698. case PL_F_POSTSCRIPT:
  699. default:
  700. if ((new_font_index >= _pl_g_ps_typeface_info[_plotter->drawstate->typeface_index].numfonts)
  701. || new_font_index < 0)
  702. new_font_index = 1; /* OOB -> use default font */
  703. raw_fontnum = _pl_g_ps_typeface_info[_plotter->drawstate->typeface_index].fonts[new_font_index];
  704. break;
  705. case PL_F_OTHER:
  706. if (new_font_index != 0 && new_font_index != 1)
  707. new_font_index = 1; /* OOB -> use default font */
  708. raw_fontnum = new_font_index;
  709. break;
  710. }
  711. }
  712. fontword = ((unsigned short)raw_fontnum) << FONT_SHIFT;
  713. continue; /* back to top of while loop */
  714. }
  715. /* couldn't match; unknown escape seq., so pass through unchanged */
  716. dest[j++] = fontword | (unsigned short)'\\';
  717. dest[j++] = fontword | (unsigned short)c;
  718. dest[j++] = fontword | (unsigned short)d;
  719. }
  720. }
  721. dest[j] = (unsigned short)'\0'; /* terminate string */
  722. return dest;
  723. }
  724. int
  725. _codestring_len (const unsigned short *codestring)
  726. {
  727. int i = 0;
  728. while (*codestring)
  729. {
  730. i++;
  731. codestring++;
  732. }
  733. return i;
  734. }