home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume17 / xdvi / part03 < prev    next >
Encoding:
Text File  |  1992-03-22  |  43.1 KB  |  1,717 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!usc!zaphod.mps.ohio-state.edu!mips!msi!dcmartin
  3. From: vojta@powdermilk.berkeley.edu (Paul Vojta)
  4. Subject: v17i025: xdvi, dvi previewer, Part03/05
  5. Message-ID: <1992Mar23.173114.15281@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. References: <csx-17i023-xdvi@uunet.UU.NET>
  10. Date: Mon, 23 Mar 1992 17:31:14 GMT
  11. Approved: dcmartin@msi.com
  12. Lines: 1703
  13.  
  14. Submitted-by: vojta@powdermilk.berkeley.edu (Paul Vojta)
  15. Posting-number: Volume 17, Issue 25
  16. Archive-name: xdvi/part03
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of shell archive."
  25. # Contents:  font_open.c fontfmts.c gf.c pk.c pxl.c vf.c
  26. # Wrapped by vojta@powdermilk.berkeley.edu on Tue Mar 17 17:49:02 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'font_open.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'font_open.c'\"
  30. else
  31. echo shar: Extracting \"'font_open.c'\" \(16991 characters\)
  32. sed "s/^X//" >'font_open.c' <<'END_OF_FILE'
  33. X/*
  34. X *    font_open.c(font, font_ret, mag, mag_ret, name)
  35. X *    Find and open gf, pk, or pxl files in the given path, having the given
  36. X *    name and magnification.  It tries gf files first, followed by pk and pxl
  37. X *    files.  The path variable should be of the form path1:path2:...:pathn,
  38. X *    and each of the paths will be tried successively.  Strings in pathi of
  39. X *    the form %f, %p, and %d will be replaced by the font name, "gf" or "pk"
  40. X *    or "pxl", and the magnification, respectively.  If no %f appears in a
  41. X *    path specifier, then the string "/%f.%d%p" is added on the end.  This
  42. X *    procedure is repeated for each of the possible magnifications allowed,
  43. X *    and if it fails then the procedure will try changing the point size
  44. X *    as well.  If all of the above fails, then alt_font will be tried.
  45. X *
  46. X *    If the variable SEARCH_SUBDIRECTORIES is set, then the environment
  47. X *    variable TEXFONTS_SUBDIR and the #define variable DEFAULT_SUBDIR_PATH
  48. X *    will be enabled, as well as ``*'' and ``**'' specifiers.  The
  49. X *    SUBDIR_PATH things will be appended to the end of the usual path, with
  50. X *    a `*' at the end of each component.  The `*' means that subdirectories
  51. X *    will be searched up to one level; `**' means that subdirectories
  52. X *    will be recursively searched to any level.  Neither specifier may be
  53. X *    preceded by a `%' specifier (after the most recent colon).
  54. X *
  55. X *    If the file is found, then a file pointer is returned, and the following
  56. X *    values are set:
  57. X *        *font_ret  a pointer to a string containing the font name (if
  58. X *            different from the font requested).
  59. X *        *mag_ret  the actual magnification found.
  60. X *        *name    a pointer to a string containing the file name
  61. X *
  62. X *    If the file is not found, then the return value is NULL.
  63. X *
  64. X *    Often there are so many fonts that we need to manage the number of
  65. X *    simultaneously open files.  For that reason, these routines call
  66. X *    xfopen() instead of fopen(), which should manage the number of open
  67. X *    font files.
  68. X *
  69. X */
  70. X
  71. X#include "xdvi.h"
  72. X#include <errno.h>
  73. X
  74. X#ifndef    X_NOT_STDC_ENV
  75. X#include <stdlib.h>
  76. X#endif
  77. X
  78. X/*
  79. X *    If you think you have to change DEFAULT_TAIL, then you haven't read the
  80. X *    documentation closely enough.
  81. X */
  82. X#ifndef    VMS
  83. X#define    PATH_SEP    ':'
  84. X#define    DEFAULT_TAIL    "/%f.%d%p"
  85. X#define    DEFAULT_VF_TAIL    "/%f.vf"
  86. X#else    /* VMS */
  87. X#define    PATH_SEP    '/'
  88. X#define    DEFAULT_TAIL    ":%f.%d%p"
  89. X#define    DEFAULT_VF_TAIL    ":%f.vf"
  90. X#endif    /* VMS */
  91. X
  92. Xstatic    _Xconst char    *font_path;
  93. Xstatic    _Xconst char    *default_font_path    = DEFAULT_FONT_PATH;
  94. Xstatic    _Xconst char    *vf_path;
  95. Xstatic    _Xconst char    *default_vf_path    = DEFAULT_VF_PATH;
  96. X#ifdef    SEARCH_SUBDIRECTORIES
  97. Xstatic    char    default_subdir_path[]    = DEFAULT_SUBDIR_PATH;
  98. X#endif
  99. Xstatic    int    *sizes, *sizend;
  100. Xstatic    char    default_size_list[]    = DEFAULT_FONT_SIZES;
  101. X
  102. X#define    FILENAMESIZE 512
  103. X
  104. X#ifdef    sun
  105. Xchar    *sprintf();
  106. X#endif
  107. X
  108. Xchar    *xmalloc(), *getenv();
  109. Xdouble    atof();
  110. Xvolatile void    exit();
  111. X
  112. X#ifdef    SEARCH_SUBDIRECTORIES
  113. X/* We will need some system include files to deal with directories.  */
  114. X/* <sys/types.h> was included by xdvi.h.  */
  115. X
  116. X#include <sys/stat.h>
  117. X
  118. Xstatic    int    is_dir ();
  119. X
  120. X#if    defined(SYSV) || defined(_POSIX_SOURCE)
  121. X#include <dirent.h>
  122. Xtypedef    struct dirent    *directory_entry_type;
  123. X#else
  124. X#include <sys/dir.h>
  125. Xtypedef    struct direct    *directory_entry_type;
  126. X#endif
  127. X
  128. X/* Declare the routine to get the current working directory.  */
  129. X
  130. X#ifdef    HAVE_GETWD
  131. Xextern    char    *getwd ();
  132. X#define    getcwd(b, len)    ((b) ? getwd (b) : getwd (xmalloc (len, "getwd")))
  133. X#else
  134. X#ifdef    ANSI
  135. Xextern    char    *getcwd (char *, int);
  136. X#else
  137. Xextern    char    *getcwd ();
  138. X#endif    /* not ANSI */
  139. X#endif    /* not HAVE_GETWD */
  140. X
  141. Xstatic    char    *cwd;
  142. X
  143. X/* The following is a data structure containing the precomputed names of
  144. X   subdirectories to be recursively searched. */
  145. X
  146. Xstatic    struct subdir_entry {
  147. X    char    *name;        /* partial string */
  148. X    _Xconst char    *index;    /* reference point in {,default_}font_path */
  149. X    struct subdir_entry *next;    /* link in list */
  150. X}
  151. X    *subdir_head    = NULL,
  152. X    *next_subdir;
  153. X
  154. X#ifndef    S_ISDIR
  155. X#define    S_ISDIR(m)    ((m & S_IFMT) == S_IFDIR)
  156. X#endif
  157. X
  158. X/* Return true if FN is a directory or a symlink to a directory,
  159. X   false if not. */
  160. X
  161. Xstatic    int
  162. Xis_dir (fn)
  163. X    char    *fn;
  164. X{
  165. X    struct stat    stats;
  166. X
  167. X    return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
  168. X}
  169. X
  170. X/*
  171. X *    Compute extra length of subdirectory entries, including a star for each.
  172. X */
  173. X
  174. Xstatic    int
  175. Xextra_len(str1, str2)
  176. X    char    *str1, *str2;
  177. X{
  178. X    int    bias    = 0;
  179. X    char    *p    = str1;
  180. X    char    *q;
  181. X
  182. X    do {
  183. X        q = index(p, PATH_SEP);
  184. X        if (q == NULL) q = p + strlen(p);
  185. X        if (q == p) {
  186. X        if (str2 != NULL) {
  187. X            bias += extra_len(str2, (char *) NULL);
  188. X            str2 = NULL;
  189. X        }
  190. X        }
  191. X        else ++bias;    /* don't forget the star */
  192. X        p = q + 1;
  193. X    }
  194. X    while (p[-1] != '\0');
  195. X    return bias + p - str1;
  196. X}
  197. X
  198. X/*
  199. X *    Add the specifiers (and double stars) for the given strings (user
  200. X *    string, plus default string) to the destination string.
  201. X */
  202. X
  203. Xstatic    void
  204. Xadd_subdir_paths(dst, dst_first, src, src_default)
  205. X    char    *dst, *dst_first, *src, *src_default;
  206. X{
  207. X    char    *q;
  208. X
  209. X    do {
  210. X        q = index(src, PATH_SEP);
  211. X        if (q == NULL) q = src + strlen(src);
  212. X        if (q == src) {
  213. X        if (src_default != NULL) {
  214. X            add_subdir_paths(dst, dst_first, src_default, (char *)NULL);
  215. X            dst += strlen(dst);
  216. X            src_default = NULL;
  217. X        }
  218. X        }
  219. X        else {
  220. X        if (dst != dst_first) *dst++ = PATH_SEP;
  221. X        bcopy(src, dst, q - src);
  222. X        dst += q - src;
  223. X        *dst++ = '*';
  224. X        }
  225. X        src = q + 1;
  226. X    }
  227. X    while (src[-1] != '\0');
  228. X    *dst = '\0';
  229. X}
  230. X
  231. X/*
  232. X *    Make a subdirectory entry.
  233. X */
  234. X
  235. Xstatic    struct subdir_entry *
  236. Xmake_subdir_entry(index, name)
  237. X    char    *index, *name;
  238. X{
  239. X    struct subdir_entry        *new_entry;
  240. X    static    struct subdir_entry    **subdir_tail = &subdir_head;
  241. X
  242. X    *subdir_tail = new_entry = (struct subdir_entry *)
  243. X        xmalloc(sizeof(struct subdir_entry), "subdirectory list entry");
  244. X    subdir_tail = &(new_entry->next);
  245. X    new_entry->name = strcpy(xmalloc(strlen(name) + 1,
  246. X        "subdirectory entry string"), name);
  247. X    new_entry->index = index;
  248. X    new_entry->next = NULL;
  249. X    return new_entry;
  250. X}
  251. X
  252. X/*
  253. X *    Create the subdirectory linked list for the given initial string
  254. X */
  255. X
  256. Xstatic    void
  257. Xadd_subdirs(str, len, recurs)
  258. X    char    *str;
  259. X    int    len;
  260. X    Boolean    recurs;
  261. X{
  262. X    int    len1 = len;
  263. X    char    temp[FILENAMESIZE];
  264. X    struct subdir_entry *next_subdir;
  265. X    DIR    *dir;
  266. X    directory_entry_type    e;
  267. X
  268. X    bcopy(str, temp, len);
  269. X    if (len > 0 && temp[len - 1] != '/') temp[len1++] = '/';
  270. X    temp[len1] = '\0';
  271. X    next_subdir = make_subdir_entry(str, temp + len);
  272. X    do {
  273. X        /* By changing directories, we save a bunch of string
  274. X           concatenations (and make the pathnames the kernel looks up
  275. X           shorter).  */
  276. X        Strcpy(temp + len, next_subdir->name);
  277. X        if (chdir (temp) != 0) continue;
  278. X
  279. X        dir = opendir (".");
  280. X        if (dir == NULL) continue;
  281. X
  282. X        len1 = strlen(temp);
  283. X        if (len1 == 0 || temp[len1 - 1] != '/') temp[len1++] = '/';
  284. X        while ((e = readdir (dir)) != NULL) {
  285. X        if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
  286. X            && strcmp (e->d_name, "..") != 0) {
  287. X            Strcpy(temp + len1, e->d_name);
  288. X            (void) make_subdir_entry(str, temp + len);
  289. X        }
  290. X        }
  291. X        (void) closedir (dir);
  292. X
  293. X
  294. X        /* Change back to the current directory, in case the path
  295. X           contains relative directory names.  */
  296. X        if (chdir (cwd) != 0) {
  297. X        perror (cwd);
  298. X        exit (errno);
  299. X        }
  300. X    }
  301. X    while (recurs && (next_subdir = next_subdir->next) != NULL);
  302. X}
  303. X
  304. X/*
  305. X *    Recursively figure out the subdirectory tree and precompute the
  306. X *    list of subdirectories to search.
  307. X */
  308. X
  309. Xstatic    void
  310. Xcompute_subdir_paths(fp, fp_default)
  311. X    char    *fp, *fp_default;
  312. X{
  313. X    char    *star_loc = NULL;
  314. X    char    *endp;
  315. X
  316. X    do {
  317. X        if (star_loc == NULL) {
  318. X        star_loc = index(fp, '*');
  319. X        if (star_loc == NULL) star_loc = fp + strlen(fp);
  320. X        }
  321. X        endp = index(fp, PATH_SEP);
  322. X        if (endp == NULL) endp = fp + strlen(fp);
  323. X        if (endp == fp) {
  324. X        if (fp_default != NULL) {
  325. X            compute_subdir_paths(fp_default, (char *) NULL);
  326. X            fp_default = NULL;
  327. X        }
  328. X        }
  329. X        else if (star_loc < endp) {
  330. X        add_subdirs(fp, star_loc - fp, star_loc[1] == '*');
  331. X        star_loc = NULL;
  332. X        }
  333. X        fp = endp + 1;
  334. X    }
  335. X    while (fp[-1] != '\0');
  336. X}
  337. X#endif    /* SEARCH_SUBDIRECTORIES */
  338. X
  339. Xstatic    void
  340. Xget_sizes(size_list, spp)
  341. X    char    *size_list;
  342. X    int    **spp;
  343. X{
  344. X    if (*size_list == PATH_SEP) ++size_list;
  345. X    for (;;) {
  346. X        *(*spp)++ = atof(size_list) * 5 + 0.5;
  347. X        size_list = index(size_list, PATH_SEP);
  348. X        if (size_list == NULL) return;
  349. X        ++size_list;
  350. X    }
  351. X}
  352. X
  353. Xvoid
  354. Xinit_font_open()
  355. X{
  356. X    char    *size_list;
  357. X    int    *sp, *sp1, *sp2;
  358. X    unsigned int n;
  359. X    char    *p;
  360. X#ifdef    SEARCH_SUBDIRECTORIES
  361. X    char    *q;
  362. X#endif
  363. X
  364. X    if ((font_path = getenv("XDVIFONTS")) == NULL
  365. X#ifndef    XDVIFONTS_ONLY
  366. X        && (font_path = getenv("TEXFONTS")) == NULL
  367. X#endif
  368. X        ) {
  369. X        font_path = default_font_path;
  370. X        default_font_path = NULL;
  371. X    }
  372. X
  373. X#ifdef    SEARCH_SUBDIRECTORIES
  374. X    p = getenv ("TEXFONTS_SUBDIR");
  375. X    if (p == NULL) p = "";
  376. X    q = xmalloc((unsigned) strlen(font_path)
  377. X        + extra_len(p, default_subdir_path) + 1,
  378. X        "initializing font searching");
  379. X    Strcpy(q, font_path);
  380. X    add_subdir_paths(q + strlen(q), q, p, default_subdir_path);
  381. X    font_path = q;
  382. X
  383. X    /* Unfortunately, we can't look in the environment for the current
  384. X       directory, because if we are running under a program (let's say
  385. X       Emacs), the PWD variable might have been set by Emacs' parent
  386. X       to the current directory at the time Emacs was invoked.  This
  387. X       is not necessarily the same directory the user expects to be
  388. X       in.  So, we must always call getcwd(3) or getwd(3), even though
  389. X       they are slow and prone to hang in networked installations.  */
  390. X    cwd = getcwd ((char *) NULL, FILENAMESIZE + 2);
  391. X    if (cwd == NULL) {
  392. X        perror ("getcwd");
  393. X        exit (errno);
  394. X    }
  395. X    compute_subdir_paths(font_path, default_font_path);
  396. X#endif
  397. X
  398. X    if ((vf_path = getenv("XDVIVFS")) == NULL) {
  399. X        vf_path = default_vf_path;
  400. X        default_vf_path = NULL;
  401. X    }
  402. X
  403. X    size_list = getenv("XDVISIZES");
  404. X    n = 1;    /* count number of sizes */
  405. X    if (size_list == NULL || *size_list == PATH_SEP)
  406. X        for (p = default_size_list; (p = index(p, PATH_SEP)) != NULL; ++p)
  407. X        ++n;
  408. X    if (size_list != NULL)
  409. X        for (p = size_list; (p = index(p, PATH_SEP)) != NULL; ++p) ++n;
  410. X    sizes = (int *) xmalloc(n * sizeof(int), "size list");
  411. X    sizend = sizes + n;
  412. X    sp = sizes;    /* get the actual sizes */
  413. X    if (size_list == NULL || *size_list == PATH_SEP)
  414. X        get_sizes(default_size_list, &sp);
  415. X    if (size_list != NULL) get_sizes(size_list, &sp);
  416. X
  417. X    /* bubble sort the sizes */
  418. X    sp1 = sizend - 1;    /* extent of this pass */
  419. X    do {
  420. X        sp2 = NULL;
  421. X        for (sp = sizes; sp < sp1; ++sp)
  422. X        if (*sp > sp[1]) {
  423. X            int i = *sp;
  424. X            *sp = sp[1];
  425. X            sp[1] = i;
  426. X            sp2 = sp;
  427. X        }
  428. X    }
  429. X    while ((sp1 = sp2) != NULL);
  430. X}
  431. X
  432. Xstatic    FILE *
  433. Xformatted_open(path, font, gforpk, mag, name, count, tail)
  434. X    _Xconst char    *path;
  435. X    _Xconst char    *font;
  436. X    _Xconst char    *gforpk;
  437. X    int    mag;
  438. X    char    **name;
  439. X    int    count;
  440. X    _Xconst    char    *tail;
  441. X{
  442. X    _Xconst char    *p = path;
  443. X    char    nm[FILENAMESIZE];
  444. X    char    *n = nm;
  445. X    char    c;
  446. X    Boolean    f_used = False;
  447. X    Boolean    p_used = False;
  448. X    FILE    *f;
  449. X
  450. X#ifdef    SEARCH_SUBDIRECTORIES
  451. X    if (next_subdir != NULL && next_subdir->index == p) {
  452. X        int len = index(p, '*') - p;
  453. X
  454. X        bcopy(p, n, len);
  455. X        p += len;
  456. X        n += len;
  457. X        Strcpy(n, next_subdir->name);
  458. X        n += strlen(n);
  459. X        ++p;
  460. X        if (*p == '*') ++p;
  461. X        if (*p != '/') *n++ = '/';
  462. X    }
  463. X#endif
  464. X    for (;;) {
  465. X        c = *p++;
  466. X        if (c==PATH_SEP || c=='\0') {
  467. X        if (f_used) break;
  468. X        p = tail;
  469. X        continue;
  470. X        }
  471. X        if (c=='%') {
  472. X        c = *p++;
  473. X        switch (c) {
  474. X            case 'f':
  475. X            f_used = True;
  476. X            Strcpy(n, font);
  477. X            break;
  478. X            case 'p':
  479. X            p_used = True;
  480. X            Strcpy(n, gforpk);
  481. X            break;
  482. X            case 'd':
  483. X            Sprintf(n, "%d", mag);
  484. X            break;
  485. X            default:
  486. X            *n++ = c;
  487. X            *n = '\0';
  488. X        }
  489. X        n += strlen(n);
  490. X        }
  491. X        else *n++ = c;
  492. X    }
  493. X    if (!p_used && count > 0) return NULL;
  494. X    *n = '\0';
  495. X    if (debug & DBG_OPEN) Printf("Trying font file %s\n", nm);
  496. X    f = xfopen(nm);
  497. X    if (f != NULL) {
  498. X        *name = xmalloc((unsigned) (n - nm + 1), "font file name");
  499. X        Strcpy(*name, nm);
  500. X    }
  501. X    return f;
  502. X}
  503. X
  504. X/*
  505. X *    Try a given size
  506. X */
  507. X
  508. Xstatic    FILE *
  509. Xtry_size(font, pxlmag, name, x_font_path, x_default_font_path)
  510. X    _Xconst char    *font;
  511. X    int    pxlmag;
  512. X    char    **name;
  513. X    _Xconst char    *x_font_path;
  514. X    _Xconst char    *x_default_font_path;
  515. X{
  516. X    _Xconst char    *p    = x_font_path;
  517. X    FILE    *f;
  518. X    int    pkmag    = (pxlmag + 2) / 5;
  519. X
  520. X    /*
  521. X     * loop over paths
  522. X     */
  523. X#ifdef    SEARCH_SUBDIRECTORIES
  524. X    next_subdir = subdir_head;
  525. X#endif
  526. X    for (;;) {
  527. X        int count = 0;
  528. X
  529. X        if (*p == PATH_SEP || *p == '\0') {
  530. X        if (x_default_font_path != NULL &&
  531. X            (f = try_size(font, pxlmag, name, x_default_font_path,
  532. X            (_Xconst char *) NULL)) != NULL)
  533. X            return f;
  534. X        if (*p == '\0') break;
  535. X        }
  536. X        else {
  537. X#ifdef    USE_PK
  538. X        if ((f = formatted_open(p, font, "pk", pkmag, name, count++,
  539. X            DEFAULT_TAIL)) != NULL)
  540. X            return f;
  541. X#endif
  542. X#ifdef    USE_GF
  543. X        if ((f = formatted_open(p, font, "gf", pkmag, name, count++,
  544. X            DEFAULT_TAIL)) != NULL)
  545. X            return f;
  546. X#endif
  547. X#ifdef    USE_PXL
  548. X        if ((f = formatted_open(p, font, "pxl", pxlmag, name, count++,
  549. X            DEFAULT_TAIL)) != NULL)
  550. X            return f;
  551. X#endif
  552. X#ifdef    SEARCH_SUBDIRECTORIES
  553. X        if (next_subdir != NULL && next_subdir->index == p) {
  554. X            next_subdir = next_subdir->next;
  555. X            if (next_subdir != NULL && next_subdir->index == p)
  556. X            continue;
  557. X        }
  558. X#endif
  559. X        p = index(p, PATH_SEP);
  560. X        if (p == NULL) break;
  561. X        }
  562. X        ++p;
  563. X    }
  564. X    return NULL;
  565. X}
  566. X
  567. X/*
  568. X *    Try a virtual font
  569. X */
  570. X
  571. Xstatic    FILE *
  572. Xtry_vf(font, name, x_vf_path, x_default_vf_path)
  573. X    _Xconst char    *font;
  574. X    char    **name;
  575. X    _Xconst char    *x_vf_path;
  576. X    _Xconst char    *x_default_vf_path;
  577. X{
  578. X    _Xconst char    *p    = x_vf_path;
  579. X    FILE    *f;
  580. X
  581. X    /*
  582. X     * loop over paths
  583. X     */
  584. X    for (;;) {
  585. X        if (*p == PATH_SEP || *p == '\0') {
  586. X        if (x_default_vf_path != NULL &&
  587. X            (f = try_vf(font, name, x_default_vf_path,
  588. X            (_Xconst char *) NULL)) != NULL)
  589. X            return f;
  590. X        if (*p == '\0') break;
  591. X        }
  592. X        else {
  593. X        if ((f = formatted_open(p, font, "vf", 0, name, 0,
  594. X            DEFAULT_VF_TAIL)) != NULL)
  595. X            return f;
  596. X        p = index(p, PATH_SEP);
  597. X        if (p == NULL) break;
  598. X        }
  599. X        ++p;
  600. X    }
  601. X    return NULL;
  602. X}
  603. X
  604. X/*
  605. X *    Try a given font name
  606. X */
  607. X
  608. Xstatic    FILE *
  609. Xpre_font_open(font, mag, mag_ret, name)
  610. X    _Xconst char    *font;
  611. X    float    mag;
  612. X    int    *mag_ret;
  613. X    char    **name;
  614. X{
  615. X    FILE    *f;
  616. X    int    *p1, *p2;
  617. X    int    imag    = mag + 0.5;
  618. X    int    pxlmag    = 5 * mag + 0.5;
  619. X#ifndef    VMS
  620. X    _Xconst char    *path_to_use;
  621. X    _Xconst char    *vf_path_to_use;
  622. X#endif
  623. X
  624. X    /*
  625. X     * Loop over sizes.  Try actual size first, then closest sizes.
  626. X       If the pathname is absolutely or explicitly relative, don't
  627. X       use the usual paths to search for it; just look for it in the
  628. X       directory specified.
  629. X     */
  630. X
  631. X#ifndef    VMS
  632. X    path_to_use = (_Xconst char *) NULL;
  633. X    if (*font == '/') path_to_use = "/";
  634. X    else if (*font == '.' && (*(font + 1) == '/'
  635. X        || (*(font + 1) == '.' && *(font + 2) == '/')))
  636. X        path_to_use = ".";
  637. X    vf_path_to_use = path_to_use;
  638. X    if (path_to_use == NULL) {
  639. X        path_to_use = font_path;
  640. X        vf_path_to_use = vf_path;
  641. X    }
  642. X#else    /* VMS */
  643. X#define    path_to_use    font_path
  644. X#define    vf_path_to_use    vf_path
  645. X#endif    /* VMS */
  646. X
  647. X    if ((f = try_size(font, *mag_ret = pxlmag, name, path_to_use,
  648. X        default_font_path)) != NULL)
  649. X        return f;
  650. X
  651. X    /* Try at one away from the size we just tried, to account
  652. X       for rounding error.  */
  653. X    if (pxlmag < 5 * mag) ++pxlmag; else --pxlmag;
  654. X    if ((f = try_size(font, *mag_ret = pxlmag, name, path_to_use,
  655. X        default_font_path)) != NULL)
  656. X        return f;
  657. X
  658. X    /* Try a virtual font. */
  659. X    if ((f = try_vf(font, name, vf_path_to_use, default_vf_path)) != NULL)
  660. X        return f;
  661. X
  662. X    /* Now try at all the sizes. */
  663. X    for (p2 = sizes; p2 < sizend; ++p2) if (*p2 >= imag) break;
  664. X    p1 = p2;
  665. X    for (;;) {
  666. X        /* find another magnification */
  667. X        if (p1 <= sizes)
  668. X        if (p2 >= sizend) return NULL;
  669. X        else pxlmag = *p2++;
  670. X        else if (p2 >= sizend || imag * imag <= p1[-1] * *p2)
  671. X            pxlmag = *--p1;
  672. X        else pxlmag = *p2++;
  673. X        if ((f = try_size(font, *mag_ret = pxlmag, name, path_to_use,
  674. X            default_font_path)) != NULL)
  675. X        return f;
  676. X    }
  677. X}
  678. X
  679. XFILE *
  680. Xfont_open(font, font_ret, mag, mag_ret, name)
  681. X    _Xconst char    *font;
  682. X    char    **font_ret;
  683. X    WIDEARG(float,double) mag;
  684. X    int    *mag_ret;
  685. X    char    **name;
  686. X{
  687. X    FILE    *f;
  688. X    int    actual_pt, low_pt, high_pt, trial_pt;
  689. X    char    fn[50], *fnend;
  690. X
  691. X    f = pre_font_open(font, mag, mag_ret, name);
  692. X    if (f != NULL) {
  693. X        *font_ret = NULL;
  694. X        return f;
  695. X    }
  696. X    Strcpy(fn, font);
  697. X    fnend = fn + strlen(fn);
  698. X    while (fnend > fn && fnend[-1] >= '0' && fnend[-1] <= '9') --fnend;
  699. X    actual_pt = low_pt = high_pt = atoi(fnend);
  700. X    if (actual_pt) {
  701. X        low_pt = actual_pt - 1;
  702. X        high_pt = actual_pt + 1;
  703. X        for (;;) {
  704. X        if (2 * low_pt >= actual_pt &&
  705. X            (low_pt * high_pt > actual_pt * actual_pt ||
  706. X            high_pt > actual_pt + 5))
  707. X            trial_pt = low_pt--;
  708. X        else if (high_pt > actual_pt + 5) break;
  709. X        else trial_pt = high_pt++;
  710. X        Sprintf(fnend, "%d", trial_pt);
  711. X        f = pre_font_open(fn, mag * actual_pt / trial_pt, mag_ret,
  712. X            name);
  713. X        if (f != NULL) {
  714. X            *font_ret = strcpy(xmalloc((unsigned) strlen(fn) + 1,
  715. X            "name of font used"), fn);
  716. X            return f;
  717. X        }
  718. X        }
  719. X    }
  720. X    if (alt_font != NULL) {
  721. X        f = pre_font_open(alt_font, mag, mag_ret, name);
  722. X        if (f != NULL)
  723. X        *font_ret = strcpy(xmalloc((unsigned) strlen(alt_font) + 1,
  724. X            "name of font used"), alt_font);
  725. X    }
  726. X    return f;
  727. X}
  728. END_OF_FILE
  729. if test 16991 -ne `wc -c <'font_open.c'`; then
  730.     echo shar: \"'font_open.c'\" unpacked with wrong size!
  731. fi
  732. # end of 'font_open.c'
  733. fi
  734. if test -f 'fontfmts.c' -a "${1}" != "-c" ; then 
  735.   echo shar: Will not clobber existing file \"'fontfmts.c'\"
  736. else
  737. echo shar: Extracting \"'fontfmts.c'\" \(249 characters\)
  738. sed "s/^X//" >'fontfmts.c' <<'END_OF_FILE'
  739. X#include "xdvi.h"
  740. X
  741. X#ifndef    X_NOT_STDC_ENV
  742. X#include <stdlib.h>
  743. X#endif
  744. X
  745. X/***
  746. X ***    Font reading routines are read into this file.
  747. X ***/
  748. X
  749. X#ifdef    USE_PK
  750. X#include "pk.c"
  751. X#endif
  752. X
  753. X#ifdef    USE_GF
  754. X#include "gf.c"
  755. X#endif
  756. X
  757. X#ifdef    USE_PXL
  758. X#include "pxl.c"
  759. X#endif
  760. END_OF_FILE
  761. if test 249 -ne `wc -c <'fontfmts.c'`; then
  762.     echo shar: \"'fontfmts.c'\" unpacked with wrong size!
  763. fi
  764. # end of 'fontfmts.c'
  765. fi
  766. if test -f 'gf.c' -a "${1}" != "-c" ; then 
  767.   echo shar: Will not clobber existing file \"'gf.c'\"
  768. else
  769. echo shar: Extracting \"'gf.c'\" \(6757 characters\)
  770. sed "s/^X//" >'gf.c' <<'END_OF_FILE'
  771. X/***
  772. X ***    GF font reading routines.
  773. X ***    Public routines are read_GF_index and read_GF_char.
  774. X ***/
  775. X
  776. X#define    PAINT_0        0
  777. X#define    PAINT1        64
  778. X#define    PAINT2        65
  779. X#define    PAINT3        66
  780. X#define    BOC        67
  781. X#define    BOC1        68
  782. X#define    EOC        69
  783. X#define    SKIP0        70
  784. X#define    SKIP1        71
  785. X#define    SKIP2        72
  786. X#define    SKIP3        73
  787. X#define    NEW_ROW_0    74
  788. X#define    NEW_ROW_MAX    238
  789. X#define    XXX1        239
  790. X#define    XXX2        240
  791. X#define    XXX3        241
  792. X#define    XXX4        242
  793. X#define    YYY        243
  794. X#define    NO_OP        244
  795. X#define    CHAR_LOC    245
  796. X#define    CHAR_LOC0    246
  797. X#define    PRE        247
  798. X#define    POST        248
  799. X#define    POST_POST    249
  800. X
  801. X#define    GF_ID_BYTE    131
  802. X#define    TRAILER        223        /* Trailing bytes at end of file */
  803. X
  804. Xstatic    FILE    *GF_file;
  805. X
  806. Xstatic    void
  807. Xexpect(ch)
  808. X    ubyte ch;
  809. X{
  810. X    ubyte ch1 = one(GF_file);
  811. X
  812. X    if (ch1 != ch)
  813. X        oops("Bad GF file:  %d expected, %d received.", ch, ch1);
  814. X}
  815. X
  816. Xstatic    void
  817. Xtoo_many_bits(ch)
  818. X    ubyte ch;
  819. X{
  820. X    oops("Too many bits found when loading character %d", ch);
  821. X}
  822. X
  823. X/*
  824. X *    Public routines
  825. X */
  826. X
  827. X
  828. Xstatic    void
  829. Xread_GF_char(fontp, ch)
  830. X    register struct font *fontp;
  831. X    ubyte ch;
  832. X{
  833. X    register struct glyph *g;
  834. X    ubyte    cmnd;
  835. X    int    min_m, max_m, min_n, max_n;
  836. X    BMUNIT    *cp, *basep, *maxp;
  837. X    int    bytes_wide;
  838. X    Boolean    paint_switch;
  839. X#define    White    False
  840. X#define    Black    True
  841. X    Boolean    new_row;
  842. X    int    count;
  843. X    int    word_weight;
  844. X
  845. X    g = &fontp->glyph[ch];
  846. X    GF_file = fontp->file;
  847. X
  848. X    if(debug & DBG_PK)
  849. X        Printf("Loading gf char %d", ch);
  850. X
  851. X    for (;;) {
  852. X        switch (cmnd = one(GF_file)) {
  853. X        case XXX1:
  854. X        case XXX2:
  855. X        case XXX3:
  856. X        case XXX4:
  857. X            Fseek(GF_file, (long) num(GF_file, cmnd - XXX1 + 1), 1);
  858. X            continue;
  859. X        case YYY:
  860. X            (void) four(GF_file);
  861. X            continue;
  862. X        case BOC:
  863. X            (void) four(GF_file);    /* skip character code */
  864. X            (void) four(GF_file);    /* skip pointer to prev char */
  865. X            min_m = sfour(GF_file);
  866. X            max_m = sfour(GF_file);
  867. X            g->x = -min_m;
  868. X            min_n = sfour(GF_file);
  869. X            g->y = max_n = sfour(GF_file);
  870. X            g->bitmap.w = max_m - min_m + 1;
  871. X            g->bitmap.h = max_n - min_n + 1;
  872. X            break;
  873. X        case BOC1:
  874. X            (void) one(GF_file);    /* skip character code */
  875. X            g->bitmap.w = one(GF_file);    /* max_m - min_m */
  876. X            g->x = g->bitmap.w - one(GF_file);    /* ditto - max_m */
  877. X            ++g->bitmap.w;
  878. X            g->bitmap.h = one(GF_file) + 1;
  879. X            g->y = one(GF_file);
  880. X            break;
  881. X        default:
  882. X            oops("Bad BOC code:  %d", cmnd);
  883. X        }
  884. X        break;
  885. X    }
  886. X    paint_switch = White;
  887. X
  888. X    if (debug & DBG_PK)
  889. X        Printf(", size=%dx%d, dvi_adv=%d\n", g->bitmap.w, g->bitmap.h,
  890. X        g->dvi_adv);
  891. X
  892. X    alloc_bitmap(&g->bitmap);
  893. X    cp = basep = (BMUNIT *) g->bitmap.bits;
  894. X/*
  895. X *    Read character data into *basep
  896. X */
  897. X    bytes_wide = ROUNDUP(g->bitmap.w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
  898. X    maxp = ADD(basep, g->bitmap.h * bytes_wide);
  899. X    bzero(g->bitmap.bits, g->bitmap.h * bytes_wide);
  900. X    new_row = False;
  901. X    word_weight = BITS_PER_BMUNIT;
  902. X    for (;;) {
  903. X        count = -1;
  904. X        cmnd = one(GF_file);
  905. X        if (cmnd < 64) count = cmnd;
  906. X        else if (cmnd >= NEW_ROW_0 && cmnd <= NEW_ROW_MAX) {
  907. X        count = cmnd - NEW_ROW_0;
  908. X        paint_switch = White;    /* it'll be complemented later */
  909. X        new_row = True;
  910. X        }
  911. X        else switch (cmnd) {
  912. X        case PAINT1:
  913. X        case PAINT2:
  914. X        case PAINT3:
  915. X            count = num(GF_file, cmnd - PAINT1 + 1);
  916. X            break;
  917. X        case EOC:
  918. X            if (cp >= ADD(basep, bytes_wide)) too_many_bits(ch);
  919. X            return;
  920. X        case SKIP1:
  921. X        case SKIP2:
  922. X        case SKIP3:
  923. X            *((char **) &basep) +=
  924. X            num(GF_file, cmnd - SKIP0) * bytes_wide;
  925. X        case SKIP0:
  926. X            new_row = True;
  927. X            paint_switch = White;
  928. X            break;
  929. X        case XXX1:
  930. X        case XXX2:
  931. X        case XXX3:
  932. X        case XXX4:
  933. X            Fseek(GF_file, (long) num(GF_file, cmnd - XXX1 + 1), 1);
  934. X            break;
  935. X        case YYY:
  936. X            (void) four(GF_file);
  937. X            break;
  938. X        case NO_OP:
  939. X            break;
  940. X        default:
  941. X            oops("Bad command in GF file:  %d", cmnd);
  942. X        } /* end switch */
  943. X        if (new_row) {
  944. X        *((char **) &basep) += bytes_wide;
  945. X        if (basep >= maxp || cp >= basep) too_many_bits(ch);
  946. X        cp = basep;
  947. X        word_weight = BITS_PER_BMUNIT;
  948. X        new_row = False;
  949. X        }
  950. X        if (count >= 0) {
  951. X        while (count)
  952. X            if (count <= word_weight) {
  953. X#ifndef    MSBITFIRST
  954. X            if (paint_switch)
  955. X                *cp |= bit_masks[count] <<
  956. X                (BITS_PER_BMUNIT - word_weight);
  957. X#endif
  958. X            word_weight -= count;
  959. X#ifdef    MSBITFIRST
  960. X            if (paint_switch)
  961. X                *cp |= bit_masks[count] << word_weight;
  962. X#endif
  963. X            break;
  964. X            }
  965. X            else {
  966. X            if (paint_switch)
  967. X#ifndef    MSBITFIRST
  968. X                *cp |= bit_masks[word_weight] <<
  969. X                (BITS_PER_BMUNIT - word_weight);
  970. X#else
  971. X                *cp |= bit_masks[word_weight];
  972. X#endif
  973. X            cp++;
  974. X            count -= word_weight;
  975. X            word_weight = BITS_PER_BMUNIT;
  976. X            }
  977. X        paint_switch = 1 - paint_switch;
  978. X        }
  979. X    } /* end for */
  980. X}
  981. X
  982. X
  983. Xvoid
  984. Xread_GF_index(fontp)
  985. X    register struct font *fontp;
  986. X{
  987. X    int    hppp, vppp;
  988. X    ubyte    ch, cmnd;
  989. X    register struct glyph *g;
  990. X
  991. X    fontp->read_char = read_GF_char;
  992. X    GF_file = fontp->file;
  993. X    if (debug & DBG_PK)
  994. X        Printf("Reading GF pixel file %s\n", fontp->filename);
  995. X/*
  996. X *    Find postamble.
  997. X */
  998. X    Fseek(GF_file, (long) -4, 2);
  999. X    while (four(GF_file) !=
  1000. X        ((long) TRAILER << 24 | TRAILER << 16 | TRAILER << 8 | TRAILER))
  1001. X        Fseek(GF_file, (long) -5, 1);
  1002. X    Fseek(GF_file, (long) -5, 1);
  1003. X    for (;;) {
  1004. X        ch = one(GF_file);
  1005. X        if (ch != TRAILER) break;
  1006. X        Fseek(GF_file, (long) -2, 1);
  1007. X    }
  1008. X    if (ch != GF_ID_BYTE) oops("Bad end of font file %s", fontp->fontname);
  1009. X    Fseek(GF_file, (long) -6, 1);
  1010. X    expect(POST_POST);
  1011. X    Fseek(GF_file, sfour(GF_file), 0);    /* move to postamble */
  1012. X/*
  1013. X *    Read postamble.
  1014. X */
  1015. X    expect(POST);
  1016. X    (void) four(GF_file);        /* pointer to last eoc + 1 */
  1017. X    (void) four(GF_file);        /* skip design size */
  1018. X    (void) four(GF_file);        /* skip checksum */
  1019. X    hppp = sfour(GF_file);
  1020. X    vppp = sfour(GF_file);
  1021. X    if (hppp != vppp && (debug & DBG_PK))
  1022. X        Printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
  1023. X    (void) four(GF_file);        /* skip min_m */
  1024. X    (void) four(GF_file);        /* skip max_m */
  1025. X    (void) four(GF_file);        /* skip min_n */
  1026. X    (void) four(GF_file);        /* skip max_n */
  1027. X/*
  1028. X *    Prepare glyph array.
  1029. X */
  1030. X    fontp->glyph = (struct glyph *) xmalloc(256 * sizeof(struct glyph),
  1031. X        "glyph array");
  1032. X    bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
  1033. X/*
  1034. X *    Read glyph directory.
  1035. X */
  1036. X    while ((cmnd = one(GF_file)) != POST_POST) {
  1037. X        int addr;
  1038. X
  1039. X        ch = one(GF_file);            /* character code */
  1040. X        g = &fontp->glyph[ch];
  1041. X        switch (cmnd) {
  1042. X        case CHAR_LOC:
  1043. X            /* g->pxl_adv = sfour(GF_file); */
  1044. X            (void) four(GF_file);
  1045. X            (void) four(GF_file);    /* skip dy */
  1046. X            break;
  1047. X        case CHAR_LOC0:
  1048. X            /* g->pxl_adv = one(GF_file) << 16; */
  1049. X            (void) one(GF_file);
  1050. X            break;
  1051. X        default:
  1052. X            oops("Non-char_loc command found in GF preamble:  %d",
  1053. X            cmnd);
  1054. X        }
  1055. X        g->dvi_adv = fontp->dimconv * sfour(GF_file);
  1056. X        addr = four(GF_file);
  1057. X        if (addr != -1) g->addr = addr;
  1058. X        if (debug & DBG_PK)
  1059. X        Printf("Read GF glyph for character %d; dy = %d, addr = %d\n",
  1060. X            ch, g->dvi_adv, addr);
  1061. X    }
  1062. X}
  1063. END_OF_FILE
  1064. if test 6757 -ne `wc -c <'gf.c'`; then
  1065.     echo shar: \"'gf.c'\" unpacked with wrong size!
  1066. fi
  1067. # end of 'gf.c'
  1068. fi
  1069. if test -f 'pk.c' -a "${1}" != "-c" ; then 
  1070.   echo shar: Will not clobber existing file \"'pk.c'\"
  1071. else
  1072. echo shar: Extracting \"'pk.c'\" \(7379 characters\)
  1073. sed "s/^X//" >'pk.c' <<'END_OF_FILE'
  1074. X/***
  1075. X ***    PK font reading routines.
  1076. X ***    Public routines are read_PK_index and read_PK_char.
  1077. X ***/
  1078. X
  1079. X#define PK_ID      89
  1080. X#define PK_CMD_START 240
  1081. X#define PK_X1     240
  1082. X#define PK_X2     241
  1083. X#define PK_X3     242
  1084. X#define PK_X4     243
  1085. X#define PK_Y      244
  1086. X#define PK_POST   245
  1087. X#define PK_NOOP   246
  1088. X#define PK_PRE    247
  1089. X
  1090. Xstatic    int    PK_flag_byte;
  1091. Xstatic    unsigned PK_input_byte;
  1092. Xstatic    int    PK_bitpos;
  1093. Xstatic    int    PK_dyn_f;
  1094. Xstatic    int    PK_repeat_count;
  1095. X
  1096. Xstatic    int
  1097. XPK_get_nyb(fp)
  1098. X    register FILE *fp;
  1099. X{
  1100. X    unsigned temp;
  1101. X    if (PK_bitpos < 0) {
  1102. X        PK_input_byte = one(fp);
  1103. X        PK_bitpos = 4;
  1104. X    }
  1105. X    temp = PK_input_byte >> PK_bitpos;
  1106. X    PK_bitpos -= 4;
  1107. X    return (temp & 0xf);
  1108. X}
  1109. X
  1110. X
  1111. Xstatic    int
  1112. XPK_packed_num(fp)
  1113. X    register FILE *fp;
  1114. X{
  1115. X    int    i,j;
  1116. X
  1117. X    if ((i = PK_get_nyb(fp)) == 0) {
  1118. X        do {
  1119. X        j = PK_get_nyb(fp);
  1120. X        ++i;
  1121. X        }
  1122. X        while (j == 0);
  1123. X        while (i > 0) {
  1124. X        j = (j << 4) | PK_get_nyb(fp);
  1125. X        --i;
  1126. X        }
  1127. X        return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
  1128. X    }
  1129. X    else {
  1130. X        if (i <= PK_dyn_f) return i;
  1131. X        if (i < 14)
  1132. X        return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
  1133. X            + PK_dyn_f + 1);
  1134. X        if (i == 14) PK_repeat_count = PK_packed_num(fp);
  1135. X        else PK_repeat_count = 1;
  1136. X        return PK_packed_num(fp);
  1137. X    }
  1138. X}
  1139. X
  1140. X
  1141. Xstatic    void
  1142. XPK_skip_specials(fontp)
  1143. X    register struct font *fontp;
  1144. X{
  1145. X    int i,j;
  1146. X    register FILE *fp = fontp->file;
  1147. X
  1148. X    do {
  1149. X        PK_flag_byte = one(fp);
  1150. X        if (PK_flag_byte >= PK_CMD_START) {
  1151. X        switch (PK_flag_byte) {
  1152. X            case PK_X1 :
  1153. X            case PK_X2 :
  1154. X            case PK_X3 :
  1155. X            case PK_X4 :
  1156. X            i = 0;
  1157. X            for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
  1158. X                i = (i << 8) | one(fp);
  1159. X            while (i--) (void) one(fp);
  1160. X            break;
  1161. X            case PK_Y :
  1162. X            (void) four(fp);
  1163. X            case PK_POST :
  1164. X            case PK_NOOP :
  1165. X            break;
  1166. X            default :
  1167. X            oops("Unexpected %d in PK file %s", PK_flag_byte,
  1168. X                fontp->filename);
  1169. X            break;
  1170. X        }
  1171. X        }
  1172. X    }
  1173. X    while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
  1174. X}
  1175. X
  1176. X/*
  1177. X *    Public routines
  1178. X */
  1179. X
  1180. Xstatic    void
  1181. Xread_PK_char(fontp, ch)
  1182. X    register struct font *fontp;
  1183. X    ubyte    ch;
  1184. X{
  1185. X    int    i, j;
  1186. X    ubyte    n;
  1187. X    int    row_bit_pos;
  1188. X    Boolean    paint_switch;
  1189. X    BMUNIT    *cp;
  1190. X    register struct glyph *g;
  1191. X    register FILE *fp = fontp->file;
  1192. X    long    fpwidth;
  1193. X    BMUNIT    word;
  1194. X    int    word_weight, bytes_wide;
  1195. X    int    rows_left, h_bit, count;
  1196. X
  1197. X    g = &fontp->glyph[ch];
  1198. X    PK_flag_byte = g->x2;
  1199. X    PK_dyn_f = PK_flag_byte >> 4;
  1200. X    paint_switch = ((PK_flag_byte & 8) != 0);
  1201. X    PK_flag_byte &= 0x7;
  1202. X    if (PK_flag_byte == 7) n = 4;
  1203. X    else if (PK_flag_byte > 3) n = 2;
  1204. X    else n = 1;
  1205. X
  1206. X    if (debug & DBG_PK) Printf("loading pk char %d, char type %d ", ch, n);
  1207. X
  1208. X    /*
  1209. X     * now read rest of character preamble
  1210. X     */
  1211. X    if (n != 4) fpwidth = snum(fp, 3);
  1212. X    else {
  1213. X        fpwidth = sfour(fp);
  1214. X        (void) four(fp);    /* horizontal escapement */
  1215. X    }
  1216. X    (void) num(fp, n);    /* vertical escapement */
  1217. X    {
  1218. X        unsigned long w, h;
  1219. X
  1220. X        w = num(fp, n);
  1221. X        h = num(fp, n);
  1222. X        if (w > 0x7fff || h > 0x7fff)
  1223. X        oops("Character %d too large in file %s", ch, fontp->fontname);
  1224. X        g->bitmap.w = w;
  1225. X        g->bitmap.h = h;
  1226. X    }
  1227. X    g->x = snum(fp, n);
  1228. X    g->y = snum(fp, n);
  1229. X
  1230. X    g->dvi_adv = fontp->dimconv * fpwidth;
  1231. X
  1232. X    if (debug & DBG_PK) {
  1233. X        if (g->bitmap.w != 0)
  1234. X        Printf(", size=%dx%d, dvi_adv=%d", g->bitmap.w, g->bitmap.h,
  1235. X            g->dvi_adv);
  1236. X        Putchar('\n');
  1237. X    }
  1238. X
  1239. X    alloc_bitmap(&g->bitmap);
  1240. X    cp = (BMUNIT *) g->bitmap.bits;
  1241. X
  1242. X    /*
  1243. X     * read character data into *cp
  1244. X     */
  1245. X    bytes_wide = ROUNDUP(g->bitmap.w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
  1246. X    PK_bitpos = -1;
  1247. X    if (PK_dyn_f == 14) {    /* get raster by bits */
  1248. X        bzero(g->bitmap.bits, g->bitmap.h * bytes_wide);
  1249. X        for (i = 0; i < g->bitmap.h; i++) {    /* get all rows */
  1250. X        cp = ADD(g->bitmap.bits, i * bytes_wide);
  1251. X#ifndef    MSBITFIRST
  1252. X        row_bit_pos = -1;
  1253. X#else
  1254. X        row_bit_pos = BITS_PER_BMUNIT;
  1255. X#endif
  1256. X        for (j = 0; j < g->bitmap.w; j++) {    /* get one row */
  1257. X            if (--PK_bitpos < 0) {
  1258. X            word = one(fp);
  1259. X            PK_bitpos = 7;
  1260. X            }
  1261. X#ifndef    MSBITFIRST
  1262. X            if (++row_bit_pos >= BITS_PER_BMUNIT) {
  1263. X            cp++;
  1264. X            row_bit_pos = 0;
  1265. X            }
  1266. X#else
  1267. X            if (--row_bit_pos < 0) {
  1268. X            cp++;
  1269. X            row_bit_pos = BITS_PER_BMUNIT - 1;
  1270. X            }
  1271. X#endif
  1272. X            if (word & (1 << PK_bitpos)) *cp |= 1 << row_bit_pos;
  1273. X        }
  1274. X        }
  1275. X    }
  1276. X    else {        /* get packed raster */
  1277. X        rows_left = g->bitmap.h;
  1278. X        h_bit = g->bitmap.w;
  1279. X        PK_repeat_count = 0;
  1280. X        word_weight = BITS_PER_BMUNIT;
  1281. X        word = 0;
  1282. X        while (rows_left > 0) {
  1283. X        count = PK_packed_num(fp);
  1284. X        while (count > 0) {
  1285. X            if (count < word_weight && count < h_bit) {
  1286. X#ifndef    MSBITFIRST
  1287. X            if (paint_switch)
  1288. X                word |= bit_masks[count] <<
  1289. X                (BITS_PER_BMUNIT - word_weight);
  1290. X#endif
  1291. X            h_bit -= count;
  1292. X            word_weight -= count;
  1293. X#ifdef    MSBITFIRST
  1294. X            if (paint_switch)
  1295. X                word |= bit_masks[count] << word_weight;
  1296. X#endif
  1297. X            count = 0;
  1298. X            }
  1299. X            else if (count >= h_bit && h_bit <= word_weight) {
  1300. X            if (paint_switch)
  1301. X                word |= bit_masks[h_bit] <<
  1302. X#ifndef    MSBITFIRST
  1303. X                (BITS_PER_BMUNIT - word_weight);
  1304. X#else
  1305. X                (word_weight - h_bit);
  1306. X#endif
  1307. X            *cp++ = word;
  1308. X            /* "output" row(s) */
  1309. X            for (i = PK_repeat_count * bytes_wide /
  1310. X                BYTES_PER_BMUNIT; i > 0; --i) {
  1311. X                *cp = *SUB(cp, bytes_wide);
  1312. X                ++cp;
  1313. X            }
  1314. X            rows_left -= PK_repeat_count + 1;
  1315. X            PK_repeat_count = 0;
  1316. X            word = 0;
  1317. X            word_weight = BITS_PER_BMUNIT;
  1318. X            count -= h_bit;
  1319. X            h_bit = g->bitmap.w;
  1320. X            }
  1321. X            else {
  1322. X            if (paint_switch)
  1323. X#ifndef    MSBITFIRST
  1324. X                word |= bit_masks[word_weight] <<
  1325. X                (BITS_PER_BMUNIT - word_weight);
  1326. X#else
  1327. X                word |= bit_masks[word_weight];
  1328. X#endif
  1329. X            *cp++ = word;
  1330. X            word = 0;
  1331. X            count -= word_weight;
  1332. X            h_bit -= word_weight;
  1333. X            word_weight = BITS_PER_BMUNIT;
  1334. X            }
  1335. X        }
  1336. X        paint_switch = 1 - paint_switch;
  1337. X        }
  1338. X        if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
  1339. X        oops("Wrong number of bits stored:  char. %d, font %s", ch,
  1340. X            fontp->fontname);
  1341. X        if (rows_left != 0 || h_bit != g->bitmap.w)
  1342. X        oops("Bad pk file (%s), too many bits", fontp->fontname);
  1343. X    }
  1344. X}
  1345. X
  1346. Xvoid
  1347. Xread_PK_index(fontp)
  1348. X    register struct font *fontp;
  1349. X{
  1350. X    int    hppp, vppp;
  1351. X
  1352. X    fontp->read_char = read_PK_char;
  1353. X    if (debug & DBG_PK)
  1354. X        Printf("Reading PK pixel file %s\n", fontp->filename);
  1355. X
  1356. X    Fseek(fontp->file, (long) one(fontp->file), 1);    /* skip comment */
  1357. X
  1358. X    (void) four(fontp->file);        /* skip design size */
  1359. X    (void) four(fontp->file);        /* skip checksum */
  1360. X    hppp = sfour(fontp->file);
  1361. X    vppp = sfour(fontp->file);
  1362. X    if (hppp != vppp && (debug & DBG_PK))
  1363. X        Printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
  1364. X    /*
  1365. X     * Prepare glyph array.
  1366. X     */
  1367. X    fontp->glyph = (struct glyph *) xmalloc(256 * sizeof(struct glyph),
  1368. X        "glyph array");
  1369. X    bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
  1370. X    /*
  1371. X     * Read glyph directory (really a whole pass over the file).
  1372. X     */
  1373. X    for (;;) {
  1374. X        int bytes_left, flag_low_bits;
  1375. X        unsigned int ch;
  1376. X
  1377. X        PK_skip_specials(fontp);
  1378. X        if (PK_flag_byte == PK_POST) break;
  1379. X        flag_low_bits = PK_flag_byte & 0x7;
  1380. X        if (flag_low_bits == 7) {
  1381. X        bytes_left = four(fontp->file);
  1382. X        ch = four(fontp->file);
  1383. X        } else if (flag_low_bits > 3) {
  1384. X        bytes_left = ((flag_low_bits - 4) << 16) + two(fontp->file);
  1385. X        ch = one(fontp->file);
  1386. X        } else {
  1387. X        bytes_left = (flag_low_bits << 8) + one(fontp->file);
  1388. X        ch = one(fontp->file);
  1389. X        }
  1390. X        fontp->glyph[ch].addr = ftell(fontp->file);
  1391. X        fontp->glyph[ch].x2 = PK_flag_byte;
  1392. X        Fseek(fontp->file, (long) bytes_left, 1);
  1393. X        if (debug & DBG_PK)
  1394. X        Printf("Scanning pk char %d, at %d.\n", ch,
  1395. X            fontp->glyph[ch].addr);
  1396. X    }
  1397. X}
  1398. END_OF_FILE
  1399. if test 7379 -ne `wc -c <'pk.c'`; then
  1400.     echo shar: \"'pk.c'\" unpacked with wrong size!
  1401. fi
  1402. # end of 'pk.c'
  1403. fi
  1404. if test -f 'pxl.c' -a "${1}" != "-c" ; then 
  1405.   echo shar: Will not clobber existing file \"'pxl.c'\"
  1406. else
  1407. echo shar: Extracting \"'pxl.c'\" \(4849 characters\)
  1408. sed "s/^X//" >'pxl.c' <<'END_OF_FILE'
  1409. X/***
  1410. X ***    PXL font reading routines.
  1411. X ***    Public routines are read_PXL_index and read_PXL_char.
  1412. X ***/
  1413. X
  1414. X#ifndef    MSBITFIRST
  1415. Xstatic    unsigned char    _reverse_byte[0x100] = {
  1416. X    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  1417. X    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  1418. X    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  1419. X    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  1420. X    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  1421. X    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  1422. X    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  1423. X    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  1424. X    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  1425. X    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  1426. X    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  1427. X    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  1428. X    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  1429. X    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  1430. X    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  1431. X    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  1432. X    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  1433. X    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  1434. X    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  1435. X    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  1436. X    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  1437. X    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  1438. X    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  1439. X    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  1440. X    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  1441. X    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  1442. X    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  1443. X    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  1444. X    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  1445. X    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  1446. X    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  1447. X    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
  1448. X};
  1449. X#endif    /* MSBITFIRST */
  1450. X
  1451. Xstatic    void
  1452. Xread_PXL_char(fontp, ch)
  1453. X    register struct font *fontp;
  1454. X    ubyte    ch;
  1455. X{
  1456. X    register struct bitmap *bitmap;
  1457. X    register BMUNIT *ptr;
  1458. X    register FILE *fp = fontp->file;
  1459. X    register int i, j;
  1460. X#ifndef    BMLONG
  1461. X    register int padding_length;
  1462. X#endif
  1463. X
  1464. X    bitmap = &fontp->glyph[ch].bitmap;
  1465. X        /* in file, bitmap rows are multiples of 32 bits wide */
  1466. X    alloc_bitmap(bitmap);
  1467. X    ptr = (BMUNIT *) bitmap->bits;
  1468. X#ifndef    BMLONG
  1469. X    padding_length = 3 - (bitmap->bytes_wide + 3) % 4;
  1470. X#endif
  1471. X    for (i = bitmap->h; i > 0; --i) {
  1472. X        for (j = bitmap->bytes_wide; j > 0; j -= BYTES_PER_BMUNIT) {
  1473. X#ifndef    MSBITFIRST
  1474. X        *ptr = _reverse_byte[one(fp)];
  1475. X#if    BYTES_PER_BMUNIT > 1
  1476. X        *ptr |= _reverse_byte[one(fp)] << 8;
  1477. X#endif
  1478. X#ifdef    BMLONG
  1479. X        *ptr |= _reverse_byte[one(fp)] << 16;
  1480. X        *ptr |= _reverse_byte[one(fp)] << 24;
  1481. X#endif
  1482. X#else    /* MSBITFIRST */
  1483. X        *ptr = 0;
  1484. X#ifdef    BMLONG
  1485. X        *ptr |= one(fp) << 24;
  1486. X        *ptr |= one(fp) << 16;
  1487. X#endif
  1488. X#if    BYTES_PER_BMUNIT > 1
  1489. X        *ptr |= one(fp) << 8;
  1490. X#endif
  1491. X        *ptr |= one(fp);
  1492. X#endif    /* MSBITFIRST */
  1493. X        ++ptr;
  1494. X        }
  1495. X#ifndef    BMLONG
  1496. X        for (j = padding_length; j > 0; --j) (void) one(fp);
  1497. X#endif
  1498. X    }
  1499. X}
  1500. X
  1501. Xvoid
  1502. Xread_PXL_index(fontp)
  1503. X    register struct font *fontp;
  1504. X{
  1505. X    register FILE *fp    = fontp->file;
  1506. X    register struct glyph *g;
  1507. X    long font_dir_ptr;
  1508. X
  1509. X    if (debug & DBG_PK)
  1510. X        Printf("Reading PXL file %s\n", fontp->filename);
  1511. X    fontp->read_char = read_PXL_char;
  1512. X    /* seek to trailer info */
  1513. X    Fseek(fp, (long) -4, 2);
  1514. X    while (four(fp) != 1001)
  1515. X        Fseek(fp, (long) -5, 1);
  1516. X    Fseek(fp, (long) -5 * 4, 1);
  1517. X    (void) four(fp);    /* checksum */
  1518. X    (void) four(fp);    /* magnify */
  1519. X    (void) four(fp);    /* design size */
  1520. X    font_dir_ptr = sfour(fp) * 4;
  1521. X    (void) four(fp);    /* pxl id word */
  1522. X    /* seek to font directory */
  1523. X    Fseek(fp, font_dir_ptr, 0);
  1524. X    maxchar = 127;
  1525. X    fontp->glyph = (struct glyph *) xmalloc(128 * sizeof(struct glyph),
  1526. X        "glyph array");
  1527. X    for (g = fontp->glyph; g < fontp->glyph + 128; ++g) {
  1528. X        g->bitmap.bits = NULL;
  1529. X        g->bitmap2.bits = NULL;
  1530. X        g->bitmap.w = two(fp);
  1531. X        g->bitmap.h = two(fp);
  1532. X        g->x = stwo(fp);
  1533. X        g->y = stwo(fp);
  1534. X        g->addr = four(fp) * 4;
  1535. X        /*
  1536. X        **  The TFM-width word is kind of funny in the units
  1537. X        **  it is expressed in.  It works this way:
  1538. X        **
  1539. X        **  If a glyph has width 'w' in a font with design-size
  1540. X        **  'd' (both in same units), the TFM-width word is
  1541. X        **
  1542. X        **                t = (w/d) * 2^20
  1543. X        **
  1544. X        **  Therefore, in order to find the glyph width in
  1545. X        **  DVI units (1 / 2^16 points), we take the design-size
  1546. X        **  'd' (in DVI's), the magnification 'm' of the PXL file
  1547. X        **  and the TFM-width word 't' to the width (in DVI's)
  1548. X        **  as follows:
  1549. X        **
  1550. X        **                     dmt
  1551. X        **                w = -----
  1552. X        **                    2^20
  1553. X        **
  1554. X        **  But the magnification of the PXL file is just the
  1555. X        **  scaled size 's' over the design size, so the final
  1556. X        **  expression for the width is
  1557. X        **
  1558. X        **                     st
  1559. X        **                w = ----
  1560. X        **                    2^20
  1561. X        **
  1562. X        */
  1563. X
  1564. X        g->dvi_adv = fontp->dimconv * four(fp);
  1565. X        if (debug & DBG_PK)
  1566. X        Printf("size=%dx%d, dvi_adv=%d\n", g->bitmap.w, g->bitmap.h,
  1567. X            g->dvi_adv);
  1568. X    }
  1569. X}
  1570. END_OF_FILE
  1571. if test 4849 -ne `wc -c <'pxl.c'`; then
  1572.     echo shar: \"'pxl.c'\" unpacked with wrong size!
  1573. fi
  1574. # end of 'pxl.c'
  1575. fi
  1576. if test -f 'vf.c' -a "${1}" != "-c" ; then 
  1577.   echo shar: Will not clobber existing file \"'vf.c'\"
  1578. else
  1579. echo shar: Extracting \"'vf.c'\" \(2944 characters\)
  1580. sed "s/^X//" >'vf.c' <<'END_OF_FILE'
  1581. X#include "xdvi.h"
  1582. X#include "dvi.h"
  1583. X
  1584. X#ifndef    X_NOT_STDC_ENV
  1585. X#include <stdlib.h>
  1586. X#endif
  1587. X
  1588. X/***
  1589. X ***    VF font reading routines.
  1590. X ***    Public routine is read_index---because virtual characters are presumed
  1591. X ***    to be short, we read the whole virtual font in at once, instead of
  1592. X ***    faulting in characters as needed.
  1593. X ***/
  1594. X
  1595. X#define    LONG_CHAR    242
  1596. X
  1597. X/*
  1598. X *    These are parameters which determine whether macros are combined for
  1599. X *    storage allocation purposes.  Small macros ( <= VF_PARM_1 bytes) are
  1600. X *    combined into chunks of size VF_PARM_2.
  1601. X */
  1602. X
  1603. X#ifndef    VF_PARM_1
  1604. X#define    VF_PARM_1    20
  1605. X#endif
  1606. X#ifndef    VF_PARM_2
  1607. X#define    VF_PARM_2    256
  1608. X#endif
  1609. X
  1610. X/*
  1611. X *    The main routine
  1612. X */
  1613. X
  1614. Xvoid
  1615. Xread_VF_index(fontp)
  1616. X    register struct font *fontp;
  1617. X{
  1618. X    FILE    *VF_file = fontp->file;
  1619. X    ubyte    cmnd;
  1620. X    ubyte    *avail, *availend;    /* available space for macros */
  1621. X
  1622. X    fontp->read_char = NULL;
  1623. X    fontp->flags |= FONT_VIRTUAL;
  1624. X    fontp->set_char_p = set_vf_char;
  1625. X    VF_file = fontp->file;
  1626. X    if (debug & DBG_PK)
  1627. X        Printf("Reading VF pixel file %s\n", fontp->filename);
  1628. X/*
  1629. X *    Read preamble.
  1630. X */
  1631. X    Fseek(VF_file, (long) one(VF_file), 1);    /* skip comment */
  1632. X    (void) four(VF_file);        /* skip checksum */
  1633. X    (void) four(VF_file);        /* skip design size */
  1634. X/*
  1635. X *    Read the fonts.
  1636. X */
  1637. X    fontp->first_font = NULL;
  1638. X    while ((cmnd = one(VF_file)) >= FNTDEF1 && cmnd <= FNTDEF4) {
  1639. X        define_font(VF_file, cmnd, fontp, &fontp->vf_chain);
  1640. X        if (fontp->first_font == NULL)
  1641. X        fontp->first_font = fontp->vf_chain->fontp;
  1642. X    }
  1643. X/*
  1644. X *    Prepare macro array.
  1645. X */
  1646. X    fontp->macro = (struct macro *) xmalloc(256 * sizeof(struct macro),
  1647. X        "macro array");
  1648. X    bzero((char *) fontp->macro, 256 * sizeof(struct macro));
  1649. X/*
  1650. X *    Read macros.
  1651. X */
  1652. X    avail = availend = NULL;
  1653. X    for (; cmnd <= LONG_CHAR; cmnd = one(VF_file)) {
  1654. X        register struct macro *m;
  1655. X        int len;
  1656. X        unsigned long cc;
  1657. X        long width;
  1658. X
  1659. X        if (cmnd == LONG_CHAR) {    /* long form packet */
  1660. X        len = four(VF_file);
  1661. X        cc = four(VF_file);
  1662. X        width = four(VF_file);
  1663. X        if (cc >= 256) {
  1664. X            Fprintf(stderr,
  1665. X            "Virtual character %d in font %s ignored.\n",
  1666. X            cc, fontp->fontname);
  1667. X            Fseek(VF_file, (long) len, 1);
  1668. X            continue;
  1669. X        }
  1670. X        }
  1671. X        else {    /* short form packet */
  1672. X        len = cmnd;
  1673. X        cc = one(VF_file);
  1674. X        width = num(VF_file, 3);
  1675. X        }
  1676. X        m = &fontp->macro[cc];
  1677. X        m->dvi_adv = width * fontp->dimconv;
  1678. X        if (len > 0) {
  1679. X        if (len <= availend - avail) {
  1680. X            m->pos = avail;
  1681. X            avail += len;
  1682. X        }
  1683. X        else {
  1684. X            m->free_me = True;
  1685. X            if (len <= VF_PARM_1) {
  1686. X            m->pos = avail = (ubyte *) xmalloc(VF_PARM_2,
  1687. X                "macro array");
  1688. X            availend = avail + VF_PARM_2;
  1689. X            avail += len;
  1690. X            }
  1691. X            else m->pos = (ubyte *) xmalloc((unsigned) len,
  1692. X            "macro array");
  1693. X        }
  1694. X        Fread((char *) m->pos, 1, len, VF_file);
  1695. X        m->end = m->pos + len;
  1696. X        }
  1697. X        if (debug & DBG_PK)
  1698. X        Printf("Read VF macro for character %d; dy = %d, length = %d\n",
  1699. X            cc, m->dvi_adv, len);
  1700. X    }
  1701. X    if (cmnd != POST)
  1702. X        oops("Wrong command byte found in VF macro list:  %d", cmnd);
  1703. X}
  1704. END_OF_FILE
  1705. if test 2944 -ne `wc -c <'vf.c'`; then
  1706.     echo shar: \"'vf.c'\" unpacked with wrong size!
  1707. fi
  1708. # end of 'vf.c'
  1709. fi
  1710. echo shar: End of shell archive.
  1711. exit 0
  1712. -- 
  1713. --
  1714. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1715. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1716. Sunnyvale, California 94086            at&t: 408/522-9236
  1717.