home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xtroff / part15 < prev    next >
Encoding:
Internet Message Format  |  1989-07-19  |  31.2 KB

  1. Path: uunet!island!argv
  2. From: argv@island.uu.net (Dan Heller)
  3. Newsgroups: comp.sources.x
  4. Subject: v04i060: xtroff -- troff previewer for X11, Part15/18
  5. Message-ID: <895@island.uu.net>
  6. Date: 19 Jul 89 09:13:17 GMT
  7. Organization: Island Graphics, Marin County, California
  8. Lines: 1052
  9. Approved: island!argv@sun.com
  10.  
  11. Submitted-by: Mark Moraes <moraes@ai.toronto.edu>
  12. Posting-number: Volume 4, Issue 60
  13. Archive-name: xtroff/part15
  14.  
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 15 (of 18)."
  24. # Contents:  xtroff/font.c
  25. # Wrapped by moraes@neat.ai on Thu Jul 13 20:55:22 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'xtroff/font.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'xtroff/font.c'\"
  29. else
  30. echo shar: Extracting \"'xtroff/font.c'\" \(29184 characters\)
  31. sed "s/^X//" >'xtroff/font.c' <<'END_OF_FILE'
  32. X/*
  33. X *    SunTroff -  A program to display the output of Device Independent
  34. X *        Troff as a window on a Sun Workstation.
  35. X *
  36. X *    font.c - All the stuff you will ever need to deal with
  37. X *        troff fonts, versatec fonts for the screen and picking
  38. X *        the best font to use when nothing else is available.  
  39. X *        Tries to be intelligent about the best font to use and
  40. X *        to cache all the information it figures out.
  41. X *
  42. X *    Authors - The original version of this program was written by
  43. X *            Richard L. Hyde (Purdue)
  44. X *            David Slattengren (Berkeley)
  45. X *        It was nearly all rewritten, cleaned up and a more elegant
  46. X *        user interface installed by
  47. X *            Malcolm Slaney (Schlumberger Palo Alto Research)
  48. X *
  49. X *    Legalese -  This command was developed as an independent project
  50. X *        to satisfy a need of the author.  This program may contain
  51. X *        bugs and the user is cautioned to independently verify that
  52. X *        the program is suitable for the user's intended purpose.
  53. X *        The program is made available on an ``as is'' basis with
  54. X *        all faults and without any implied or expressed warranties
  55. X *        or support from either the author, Malcolm Slaney, or
  56. X *        Schlumberger Palo Alto Research Laboratory.
  57. X *
  58. X *        I am putting this program in the public domain.  You are
  59. X *        free to use it as you wish.  In return I ask two things.
  60. X *        First, that you do not remove the names of the authors
  61. X *        from this work.  Secondly, if you make changes or
  62. X *        improvements to this program that you pass these back to
  63. X *        the author so that everybody can benefit from the
  64. X *        improvements.
  65. X *
  66. X *                    Malcolm Slaney  (December 1986)
  67. X *                    Schlumberger Palo Alto Research
  68. X *                    3340 Hillview Avenue
  69. X *                    Palo Alto, CA 94304
  70. X *                    (415) 496-4669
  71. X *                    spar!malcolm@decwrl.dec.com
  72. X *                    malcolm@ecn.purdue.edu
  73. X *                    malcolm@spar.slb.com (Someday)
  74. X */
  75. X
  76. X#include    "suntroff.h"
  77. X#include    <sys/dir.h>
  78. X
  79. X#ifndef SUNTOOLS
  80. Xextern Display *dpy;
  81. Xextern GC gc;
  82. Xextern int SUNRES;
  83. X/*
  84. X *  Maximum number of fonts to list - make it too big and XListFonts
  85. X *  will fail. Make it large enough to list all fonts you have - 1k
  86. X *  should be enough for most installations
  87. X */
  88. X#define MAX_XFONTS    1024
  89. X#endif
  90. X
  91. X#ifdef SUNTOOLS
  92. X/* emalloc - call fatal() if it can't get memory */
  93. Xchar *
  94. Xemalloc(n)
  95. Xint n;
  96. X{
  97. X    char *cp = malloc((unsigned int) n);
  98. X    if (cp == NULL)
  99. X        fatal("Can't allocate memory\n");
  100. X    return(cp);
  101. X}
  102. X#else
  103. Xextern char *XtMalloc();
  104. X#define emalloc(n)    XtMalloc((unsigned int) (n))
  105. X#endif
  106. Xextern char *malloc();
  107. X
  108. X/* rfont () - allocate space and read section of font description
  109. X *
  110. X *    fp - font file
  111. X *     n - number of bytes to read
  112. X *    file - file name
  113. X *    exit - pointer to table section
  114. X */
  115. Xchar *
  116. Xrfont(fp, n, file)
  117. Xint    fp;
  118. Xint    n;
  119. Xchar    *file;
  120. X{
  121. X    char    *p;
  122. X    extern char *malloc();
  123. X
  124. X    if((p = (char *) malloc((unsigned) n)) == NULL)
  125. X        fatal("Can't allocate space for reading %d bytes of typesetter information.\n", n);
  126. X    if (read(fp, p, n) != n)
  127. X        fatal("Can't read font information from %s.\n", file);
  128. X    return(p);
  129. X}
  130. X             
  131. X/*
  132. X    Each typesetter has a DESC.out file that contains information about
  133. X    the capabilities of the device.  The InitFonts function reads this
  134. X    file and puts     the information in a useable format for this program.
  135. X
  136. X    The following information is present in the file:
  137. X    Device            A binary image of the Device structure
  138. X                (see dev.h)
  139. X    
  140. X    PointSizeTable        An array of shorts that map a point size
  141. X                number (used in the output file format) into
  142. X                a real paper point size.
  143. X
  144. X    SpecialCharacterNumber    An array of indexes that can be used to map
  145. X                a special character number (- 128) into the
  146. X                special character name array that follows.
  147. X
  148. X    SpecialCharacterName    Many null terminated strings representing
  149. X                the names of the special characters that are
  150. X                recognized by this device.
  151. X
  152. X    Then for each of the Device.nfonts fonts the following information
  153. X    is present (index by i, the font number).
  154. X    FontInformation[i]:    Lots of miscellaneous information about the
  155. X                font.
  156. X    WidthTable[i]        A pointer to a table of characters indicating
  157. X                the width of each character in the font.  The
  158. X                width listed is that of point size 'unitwidth'
  159. X                (see the Device structure.)
  160. X    Kerning[i]        A pointer to a table of ascender/descender
  161. X                information
  162. X    CodeTable[i]        A pointer to a table giving the code sent to
  163. X                the typesetter to actually produce this
  164. X                character.
  165. X    AsciiTable[i]        A pointer to a table giving the mapping
  166. X                between the ASCII code for a character and
  167. X                    the character number in the device width
  168. X                tables. Note: The first 128-32 entries of this
  169. X                table give the mapping to the printable ascii
  170. X                characters.  Those indices above 128-32 are
  171. X                used for the special characters defined in the
  172. X                SpecialCharacterName[SpecialCharacterNumber]
  173. X                array.
  174. X
  175. XTo look up a character do the following....
  176. XIf the character is a printable ascii simply subtract 32 from its character
  177. Xcode, and look up this number in the AsciiTable.  The number retuned by
  178. Xthe AsciiTable can be used to index into the WidthTable, Kerning and
  179. XCodeTables.
  180. X
  181. XIf the character is a special character then it is necessary to search
  182. Xthrough the names listed in the SpecialCharacterName array until a match
  183. Xis found.  Then add 128-32 to this number and then do the above procedure.
  184. X                
  185. X*/
  186. X
  187. Xstruct Typesetter TypesetterList = {
  188. X    "*********", };
  189. X
  190. Xstruct Typesetter *UserTypesetter = NULL, *OutputTypesetter = NULL,
  191. X          *DefaultTypesetter = NULL;
  192. X
  193. X#ifndef    SUNTOOLS
  194. X#define DEFAULTFONT "r"
  195. X#else    SUNTOOLS
  196. X#define DEFAULTFONT "R"
  197. X#endif    SUNTOOLS
  198. X
  199. Xstatic char *FontName = NULL;
  200. X    
  201. X                        /* The table below is used
  202. X                         * to keep the mapping between
  203. X                         * font positions as used by
  204. X                         * the user and the actual
  205. X                         * font name.
  206. X                         */
  207. Xstatic char FontPosition[NFONTS][MaxFontName+1];
  208. X
  209. X/* LoadDevice - This routine is called by the routine that parses device
  210. X *    control requests in the user's input file.  At this point the
  211. X *    user has specified the desired typesetter.....we first check
  212. X *    check to see if we already know about this one.  If not then we
  213. X *    call the InitFonts() routine to load the description file.
  214. X *
  215. X *    This routine is simply called with the name of the typesetter.
  216. X *    All typesetters are stored in a linked list so we just skip down
  217. X *    the list until we find a match.
  218. X */
  219. Xstruct Typesetter *
  220. XLoadDevice(Device)
  221. Xchar    *Device;
  222. X{
  223. X    struct Typesetter *CurrentTypesetter, *LastTypesetter;
  224. X    extern char *malloc();
  225. X
  226. X    for (CurrentTypesetter = &TypesetterList;
  227. X         CurrentTypesetter;
  228. X         CurrentTypesetter = CurrentTypesetter->NextTypesetter){
  229. X             if (STREQ(Device,CurrentTypesetter->Name)){
  230. X                 return(CurrentTypesetter);
  231. X             }
  232. X             LastTypesetter = CurrentTypesetter;
  233. X         }
  234. X    CurrentTypesetter = (struct Typesetter *)
  235. X                  malloc(sizeof(*CurrentTypesetter));
  236. X    if (!CurrentTypesetter) {
  237. X        fatal("Can't get space for typesetter description.\n");
  238. X    }
  239. X
  240. X    LastTypesetter->NextTypesetter = CurrentTypesetter;
  241. X    CurrentTypesetter->NextTypesetter = NULL;
  242. X    strncpy(CurrentTypesetter->Name,Device,MAXNAME);
  243. X
  244. X    InitFonts(CurrentTypesetter);
  245. X    return(CurrentTypesetter);
  246. X}
  247. X             
  248. X/*
  249. X * InitFonts - Given a typesetter structure (that is empty except for the
  250. X *     name) go out and read the description file (DESC.out) and fill in
  251. X *    all the entries.
  252. X *
  253. X *    This is called by the LoadDevice() routine when a typesetter,
  254. X *    previously unknown to this program, is requested.
  255. X */
  256. XInitFonts(Typesetter)
  257. Xstruct Typesetter *Typesetter;
  258. X{
  259. X    char    temp[BUFSIZ];
  260. X    int    i;
  261. X    int    fp;
  262. X
  263. X    sprintf(temp,"%s/dev%s/DESC.out",FONTDIR,Typesetter->Name);
  264. X    if ((fp = open(temp, O_RDONLY)) == NULL)
  265. X        fatal("Can't open typesetter description %s.\n",temp);
  266. X    
  267. X    if (read(fp, (char *) &Typesetter->Device, sizeof(Typesetter->Device)) 
  268. X                        != sizeof(Typesetter->Device)) {
  269. X        fatal("Can't read header of %s.\n",temp);
  270. X    }
  271. X    
  272. X    Typesetter->PointSizeTable = (short *) rfont(fp,
  273. X        sizeof(short) * (Typesetter->Device.nsizes + 1), temp);
  274. X
  275. X    Typesetter->SpecialCharacterNumber = (short *) rfont(fp,
  276. X        sizeof(short) * Typesetter->Device.nchtab, temp);
  277. X    
  278. X    Typesetter->SpecialCharacterName = (char *) rfont(fp,
  279. X        Typesetter->Device.lchname, temp);
  280. X    
  281. X    Typesetter->WidthTable = (char **)emalloc(NFONTS*sizeof(char *));
  282. X    Typesetter->CodeTable = (char **)emalloc(NFONTS*sizeof(char *));
  283. X    Typesetter->AsciiTable = (char **)emalloc(NFONTS*sizeof(char *));
  284. X
  285. X     for (i=1;i<=Typesetter->Device.nfonts;i++){
  286. X        int    NumberWidths;
  287. X        
  288. X        Typesetter->FontInformation[i] = (struct Font *) rfont(fp,
  289. X            sizeof(struct Font), temp);
  290. X        NumberWidths = Typesetter->FontInformation[i]->nwfont & 0377;
  291. X
  292. X        Typesetter->WidthTable[i] = rfont(fp, 3 * NumberWidths +
  293. X            Typesetter->Device.nchtab + 128 - 32, temp);
  294. X                        /* Skip Kerning Table */
  295. X
  296. X        Typesetter->CodeTable[i] = Typesetter->WidthTable[i] +
  297. X            2 * NumberWidths;
  298. X
  299. X        Typesetter->AsciiTable[i] = Typesetter->WidthTable[i] +
  300. X            3 * NumberWidths;
  301. X
  302. X        SetFontPositionBuffer(i,Typesetter->FontInformation[i]->namefont,
  303. X                Typesetter->FontInformation[i]->intname);
  304. X    }
  305. X
  306. X    close(fp);
  307. X
  308. X                        /* Clear out the rest of the
  309. X                           font table. */
  310. X    for (i=Typesetter->Device.nfonts+1;i<NFONTS;i++){
  311. X        Typesetter->FontInformation[i] = (struct Font *) 0;
  312. X    }
  313. X
  314. X                        /* Set up the default font
  315. X                           position (0) */
  316. X    Typesetter->FontInformation[0] =
  317. X        (struct Font *)emalloc(sizeof (struct Font));
  318. X    Typesetter->WidthTable[0] = (char *)emalloc(3 * 255 +
  319. X        Typesetter->Device.nchtab + 128 - 32);
  320. X    Typesetter->FontInformation[0]->nwfont = 255;
  321. X    Typesetter->CodeTable[0] = Typesetter->WidthTable[0] + 2 * 255;
  322. X    Typesetter->AsciiTable[0] = Typesetter->WidthTable[0] + 3 * 255;
  323. X    Typesetter->FontBitHead.NextFont = NULL;
  324. X    Typesetter->FontBitHead.NextSize = NULL;
  325. X    *(Typesetter->FontBitHead.Name) = NULL;
  326. X
  327. X#ifdef    FONTDEBUG
  328. X    PrintDevice(Typesetter);
  329. X#endif    FONTDEBUG
  330. X}
  331. X
  332. X/* InitTypesetter () - This routine is called in response to the "x i"
  333. X *    device control request in the user's input file.  This routine 
  334. X *    needs to do only two things.  Both of these things could be done
  335. X *    in the LoadDevice routine but we do them here just so we have
  336. X *    something to do in this routine.
  337. X *
  338. X *    First, we use ReadFontDirectory() to figure out which fonts we 
  339. X *    have bits we can use on the screen.
  340. X *
  341. X *    Second, we load the FontPosition table with the default font 
  342. X *    position mapping information.
  343. X */
  344. XInitTypesetter()
  345. X{
  346. X    int    i;
  347. X
  348. X    if (!ReadFontDirectory(UserTypesetter)){
  349. X#ifdef    TYPEDEBUG    
  350. X        printf("Loading the %s DESC.out file\n",DEFAULT_TYPESETTER);
  351. X#endif    TYPEDEBUG        
  352. X        if (!DefaultTypesetter){
  353. X            DefaultTypesetter = LoadDevice(DEFAULT_TYPESETTER);
  354. X            if (!DefaultTypesetter){
  355. X                fatal("Can't read default typesetter DESC\n");
  356. X            }
  357. X        }
  358. X        OutputTypesetter = DefaultTypesetter;
  359. X#ifdef    TYPEDEBUG        
  360. X        printf("Attempting to load bits for %s.\n",
  361. X               OutputTypesetter->Name);
  362. X#endif    TYPEDEBUG        
  363. X        if (!ReadFontDirectory(DefaultTypesetter)){
  364. X            fatal("Can't get font bits for default typesetter.\n");
  365. X        }
  366. X    } else {
  367. X        OutputTypesetter = UserTypesetter;
  368. X    }
  369. X    
  370. X    for (i=0;i<UserTypesetter->Device.nfonts;i++){
  371. X            strncpy(FontPosition[i],
  372. X            UserTypesetter->FontInformation[i]->namefont,
  373. X            MaxFontName);
  374. X    }
  375. X    for (i; i<NFONTS; i++){
  376. X        FontPosition[i][0] = 0;
  377. X    }
  378. X        
  379. X#ifdef    FONTDEBUG
  380. X    PrintFontDirectory(OutputTypesetter);
  381. X#endif    FONTDEBUG
  382. X}    
  383. X
  384. X/* SetFontPosition - Given a font number and a font name (from the "x f"
  385. X *    device request) if the font is not already loaded (in that position)
  386. X *      get the font info and store the name in the FontPostion buffer
  387. X */
  388. XSetFontPosition(FontNumber,FontName,InternalFontName)
  389. Xint    FontNumber;
  390. Xchar    *FontName, *InternalFontName;
  391. X{
  392. X    char    temp[BUFSIZ];
  393. X    int    NumberWidths;
  394. X    FILE    *fp;
  395. X    struct    Typesetter    *Typesetter = OutputTypesetter;
  396. X    int    norig;
  397. X    
  398. X
  399. X    if (FontNumber < 0 || FontNumber > NFONTS)
  400. X        fatal("illegal x font command %d %s", FontNumber, FontName);
  401. X#ifdef FONTDEBUG
  402. X    printf("x font %d %s - FontPosition[%d]= %s\n", FontNumber, FontName,
  403. X        FontNumber, FontPosition[FontNumber]);
  404. X#endif /* FONTDEBUG */
  405. X    if (strncmp(FontPosition[FontNumber], FontName, MaxFontName) == 0)
  406. X        return;
  407. X    if (Typesetter->FontInformation[FontNumber] == 0) {
  408. X#ifdef FONTDEBUG
  409. X        printf("allocating space for %s/dev%s/%s.out\n", FONTDIR,
  410. X            Typesetter->Name, FontName);
  411. X#endif /* FONTDEBUG */
  412. X        Typesetter->FontInformation[FontNumber] =
  413. X            (struct Font *)emalloc(sizeof (struct Font));
  414. X        Typesetter->WidthTable[FontNumber] = (char *)emalloc(3 * 255 +
  415. X            Typesetter->Device.nchtab + 128 - 32);
  416. X        Typesetter->FontInformation[FontNumber]->nwfont = 255;
  417. X        Typesetter->CodeTable[FontNumber] =
  418. X            Typesetter->WidthTable[FontNumber] + 2 * 255;
  419. X        Typesetter->AsciiTable[FontNumber] =
  420. X            Typesetter->WidthTable[FontNumber] + 3 * 255;
  421. X    }
  422. X    SetFontPositionBuffer(FontNumber,FontName,InternalFontName);
  423. X
  424. X    /* open the font file */
  425. X    sprintf(temp,"%s/dev%s/%s.out",FONTDIR,Typesetter->Name,
  426. X        FontName);
  427. X    fp = fopen(temp,"r");
  428. X    if (!fp){
  429. X        warning("Can't open typesetter description %s.\n",temp);
  430. X#ifdef FONTDEBUG
  431. X        printf("Can't open typesetter description %s.\n",temp);
  432. X#endif /* FONTDEBUG */
  433. X        return;
  434. X    }
  435. X    norig = Typesetter->FontInformation[FontNumber]->nwfont & 0xff;
  436. X
  437. X    fread((char *) Typesetter->FontInformation[FontNumber],
  438. X          sizeof(struct Font), 1, fp);
  439. X    NumberWidths = Typesetter->FontInformation[FontNumber]->nwfont & 0377;
  440. X    if (NumberWidths > norig) {
  441. X#ifdef FONTDEBUG
  442. X        printf("allocating space for %s/dev%s/%s.out\n", FONTDIR,
  443. X            Typesetter->Name, FontName);
  444. X#endif /* FONTDEBUG */
  445. X        Typesetter->WidthTable[FontNumber] = (char *)emalloc(3 * 255 +
  446. X            Typesetter->Device.nchtab + 128 - 32);
  447. X        norig = 255;
  448. X    }
  449. X    fread(Typesetter->WidthTable[FontNumber], NumberWidths * 3 +
  450. X        Typesetter->Device.nchtab + 128 - 32, 1, fp);
  451. X    fclose(fp);
  452. X
  453. X    Typesetter->CodeTable[FontNumber] =
  454. X        Typesetter->WidthTable[FontNumber] + 2 * NumberWidths;
  455. X    Typesetter->AsciiTable[FontNumber] =
  456. X        Typesetter->WidthTable[FontNumber] + 3 * NumberWidths;
  457. X    Typesetter->FontInformation[FontNumber]->nwfont = norig;
  458. X}
  459. X
  460. X/* SetFontPositionBuffer - Given a font number and a font name, store the
  461. X * name in the font position table
  462. X */
  463. X/*ARGSUSED*/
  464. XSetFontPositionBuffer(FontNumber,FontName,InternalFontName)
  465. Xint    FontNumber;
  466. Xchar    *FontName, *InternalFontName;
  467. X{
  468. X    int    i;
  469. X    char *cp;
  470. X
  471. X    if (FontNumber >= 0 && FontNumber <= NFONTS){
  472. X            strncpy(FontPosition[FontNumber], FontName, MaxFontName);
  473. X#ifndef SUNTOOLS
  474. X        for(i = 0, cp = FontPosition[FontNumber]; *cp && 
  475. X         i < MaxFontName; i++, cp++)
  476. X             if (isascii(*cp) && islower(*cp))
  477. X                *cp = tolower(*cp);
  478. X#endif
  479. X    }
  480. X}
  481. X
  482. X/* SetFontSize - Given a point size change the current font to this new
  483. X *    font.  Most of the work needed is done by VirtualLoadFont.  But
  484. X *    then VirtualLoadFont doesn't really do any work....it just caches
  485. X *    the information until it is needed later.
  486. X */
  487. XSetFontSize(n)
  488. Xint    n;                    /* Actual Point Size */
  489. X{
  490. X    size = n;
  491. X    ditsiz = (float)(SUNRES * n)/75.;
  492. X#ifdef    FONTDEBUG
  493. X    printf("SetFontSize(%d)\n",n);
  494. X    printf("ditsiz=%g\n",ditsiz);
  495. X#endif    /* FONTDEBUG */
  496. X
  497. X    if (FontName == NULL) {
  498. X        if ((FontName = (char *) malloc(sizeof(DEFAULTFONT))) == NULL)
  499. X            fatal("Can't allocate font name space\n");
  500. X        strcpy(FontName, DEFAULTFONT);
  501. X    }
  502. X    VirtualLoadFont(FontName,size);
  503. X}
  504. X
  505. X/* SetFont - Given a font number this routine looks it up in the FontPosition
  506. X *    mapping table.  All the real work is done by the VirtualLoadFont()
  507. X *    routine.
  508. X */
  509. XSetFont(n)
  510. Xint    n;                    /* Internal Font Number */
  511. X{
  512. X    if (n >= 0 &&
  513. X        n < NFONTS){
  514. X        font = n;
  515. X        FontName = FontPosition[n];
  516. X        VirtualLoadFont(FontName,size);
  517. X    }
  518. X}
  519. X
  520. X#ifdef    FONTDEBUG
  521. X
  522. X/* PrintDevice - Print out an ASCII representation of the DESC.out file
  523. X *    so that the correct operation of the InitFonts routine can be
  524. X *    verified.  This also will verify that the DESC.out file and the
  525. X *    dev.h file used to compile this program are compatible.
  526. X */
  527. XPrintDevice(Typesetter)
  528. Xstruct Typesetter *Typesetter;
  529. X{
  530. X    int    i;
  531. X    struct dev    *Device;
  532. X    short    *SpecialCharacterNumber;
  533. X    char    *SpecialCharacterName;
  534. X
  535. X    Device = &Typesetter->Device;
  536. X
  537. X    printf("# Debugging output for suntroff of main device.\n");
  538. X
  539. X    printf("res %d\n",Device->res);
  540. X    printf("hor %d\n",Device->hor);
  541. X    printf("vert %d\n",Device->vert);
  542. X    printf("unitwidth %d\n",Device->unitwidth);
  543. X    printf("paperwidth %d\n",Device->paperwidth);
  544. X    printf("paperlength %d\n",Device->paperlength);
  545. X
  546. X    printf("sizes");
  547. X    for (i=0;i<Device->nsizes;i++){
  548. X        printf(" %d",Typesetter->PointSizeTable[i]);
  549. X    }
  550. X    printf("\n");
  551. X
  552. X    printf("fonts %d",Device->nfonts);
  553. X    fflush(stdout);
  554. X    for (i=1;i<=Device->nfonts;i++){
  555. X        if (Typesetter->FontInformation[i]){
  556. X            printf(" %s",Typesetter->FontInformation[i]->namefont);
  557. X        } else {
  558. X            printf("FontInformation[i=%d] is null.\n",i);
  559. X        }
  560. X    }
  561. X    printf("\n");
  562. X
  563. X    printf("charset\n");
  564. X    
  565. X    SpecialCharacterName = Typesetter->SpecialCharacterName;
  566. X    SpecialCharacterNumber = Typesetter->SpecialCharacterNumber;
  567. X
  568. X    for (i=0;i<Device->nchtab;i++){
  569. X        printf(" %2s",
  570. X               &SpecialCharacterName[SpecialCharacterNumber[i]]);
  571. X        if (i%10 == 0)
  572. X              printf("\n");
  573. X    }
  574. X           printf("\n");
  575. X
  576. X#if    FONTDEBUG > 1
  577. X    for (i=0;i<=Device->nfonts;i++){
  578. X        PrintFont(Typesetter,i);
  579. X    }
  580. X#endif    FONTDEBUG > 1
  581. X}
  582. X
  583. X/* PrintFont - Print out an ASCII representation for the information in
  584. X *    a font description file.
  585. X */
  586. XPrintFont(Typesetter,i)
  587. Xstruct Typesetter *Typesetter;
  588. Xint    i;
  589. X{
  590. X    int    j;
  591. X    struct Font **FontInformation1;
  592. X    char    **AsciiTable, **CodeTable, **WidthTable;
  593. X    short    *SpecialCharacterNumber;
  594. X    char    *SpecialCharacterName;
  595. X    struct Font **FontInformation;
  596. X
  597. X    FontInformation = Typesetter->FontInformation;
  598. X    AsciiTable = Typesetter->AsciiTable;
  599. X    CodeTable = Typesetter->CodeTable;
  600. X    WidthTable = Typesetter->WidthTable;
  601. X    SpecialCharacterNumber = Typesetter->SpecialCharacterNumber;
  602. X    SpecialCharacterName = Typesetter->SpecialCharacterName;
  603. X
  604. X    if (!FontInformation[i]){
  605. X        printf("There is no font information for font %d.\n",i);
  606. X    }
  607. X    printf("\n#\n");
  608. X    printf("name %s\n",FontInformation[i]->namefont);
  609. X    printf("internalname %s\n",FontInformation[1]->intname);
  610. X    printf("ligatures ");
  611. X    if (FontInformation[i]->ligfont & LFF) printf(" ff");
  612. X    if (FontInformation[i]->ligfont & LFI) printf(" fi");
  613. X    if (FontInformation[i]->ligfont & LFL) printf(" fl");
  614. X    if (FontInformation[i]->ligfont & LFFI) printf(" ffi");
  615. X    if (FontInformation[i]->ligfont & LFFL) printf(" ffl");
  616. X    printf(" 0\ncharset\n");
  617. X    for (j=0;j<FontInformation[i]->nwfont;j++){
  618. X        int    k;
  619. X
  620. X        for (k=0;k<Typesetter->Device.nchtab+128-32;k++){
  621. X            if (AsciiTable[i][k] == j){
  622. X                break;
  623. X            }
  624. X        }
  625. X        if (k < Typesetter->Device.nchtab+128-32){
  626. X            if (k < 128-32){
  627. X                printf("%c\t",k+32);
  628. X            } else {
  629. X                printf("%s\t",
  630. X                       &SpecialCharacterName
  631. X                       [SpecialCharacterNumber[k-(128-32)]]);
  632. X            }
  633. X        } else {
  634. X            printf("Couldn't find %d\t",j);
  635. X        }
  636. X        printf("%d\t%d\t%d\n",
  637. X               WidthTable[i][j],0,CodeTable[i][j]);
  638. X    }
  639. X    fflush(stdout);
  640. X}
  641. X      
  642. X
  643. X#endif    FONTDEBUG
  644. X
  645. X/* ReadFontDirectory - Given a Typesetter go out to the BITDIR directory
  646. X *    and figure out which fonts exist.  This information is important
  647. X *    because it will allow the VirtualLoadFont() routine to search through
  648. X *    memory instead of probing the file system every time it wants to
  649. X *    change fonts.  Reading the entire directory is much more efficient
  650. X *    then trying to do random probes looking for the closest match to
  651. X *    a font.
  652. X */
  653. X/* 
  654. X *  For X Windows, the workstation that your display is on, and the
  655. X *  machine you're running xtroff on may be quite different - and might
  656. X *  have access to completely different fonts as a result. So we use
  657. X *  XListFonts()
  658. X */
  659. XReadFontDirectory(Typesetter)
  660. Xstruct Typesetter *Typesetter;
  661. X{
  662. X#ifdef SUNTOOLS
  663. X    DIR    *dfp;
  664. X    struct direct *DirectoryEntry;
  665. X    char    Directory[BUFSIZ];
  666. X#else
  667. X    int nf;
  668. X    char **fontNames;
  669. X/* MAXDEVICE is the maximum length of the name of the device - (eg) devsun */
  670. X#define MAXDEVICE 32
  671. X    char fontfamily[MAXDEVICE+8];
  672. X    char devname[MAXDEVICE];
  673. X    int devnamelen;
  674. X    char *dpi;
  675. X    int dotsperinch;
  676. X#endif
  677. X    char    *FontName, *FontSize, *p;
  678. X    char *FileName;
  679. X    char    *Device;
  680. X
  681. X    Device = Typesetter->Name;
  682. X    if (Typesetter->FontBitHead.NextFont){
  683. X        return(1);
  684. X    }
  685. X      
  686. X#ifdef SUNTOOLS
  687. X    sprintf(Directory,"%s/dev%s",BITDIR,Device);
  688. X    dfp = opendir(Directory);
  689. X    if (!dfp){
  690. X        return(0);
  691. X    }
  692. X
  693. X    while(DirectoryEntry = readdir(dfp)){
  694. X
  695. X        if (!DirectoryEntry->d_fileno){
  696. X            continue;
  697. X        }
  698. X        FontSize = FontName = DirectoryEntry->d_name;
  699. X#else SUNTOOLS
  700. X    sprintf(devname, "dev%s", Device);
  701. X    devnamelen = strlen(devname);
  702. X    sprintf(fontfamily, "%s.*.*", devname);
  703. X    /*
  704. X     *  Pity we can't give a better pattern - now if they had
  705. X     *  regular expressions......
  706. X     */
  707. X    fontNames = XListFonts(dpy, fontfamily, MAX_XFONTS, &nf);
  708. X    if (nf == 0)
  709. X        return(0);
  710. X    while(--nf >= 0){
  711. X        FontSize = FontName = fontNames[nf] + devnamelen + 1;
  712. X#endif SUNTOOLS
  713. X        while (isalpha(*FontSize)){
  714. X            FontSize++;
  715. X        }
  716. X        if (!*FontSize || FontName == FontSize)
  717. X            continue;            /* No Size */
  718. X        *FontSize = '\0';
  719. X
  720. X        p = ++FontSize;
  721. X        while (isdigit(*p)){
  722. X            p++;
  723. X        }
  724. X#ifdef SUNTOOLS
  725. X        if (p == FontSize || *p != '\0'){
  726. X            continue;
  727. X        }
  728. X        FileName = (char *)malloc(strlen(Directory)+strlen(FontName) 
  729. X                      +strlen(FontSize)+4);
  730. X        if (!FileName){
  731. X            fatal("Can't allocate file name space.\n");
  732. X        }
  733. X        sprintf(FileName,"%s/%s.%s",Directory,FontName,FontSize);
  734. X        InsertFont(Typesetter,FontName,atoi(FontSize),FileName);
  735. X    }
  736. X    closedir(dfp);
  737. X#else SUNTOOLS
  738. X        if (*p == '\0') {
  739. X            dpi = "75";
  740. X            dotsperinch = atoi(dpi);
  741. X            FileName = (char *)emalloc(devnamelen + strlen(FontName) 
  742. X             + strlen(FontSize) + strlen(dpi) + 4);
  743. X            sprintf(FileName, "%s.%s.%s", devname, FontName, FontSize);
  744. X            InsertFont(Typesetter, FontName,
  745. X             (dotsperinch * atoi(FontSize) + (SUNRES / 2))
  746. X              / SUNRES, FileName);
  747. X        } else {
  748. X            if (p == FontSize || *p != '.'){
  749. X                continue;
  750. X            }
  751. X
  752. X            *p++ = '\0';
  753. X            dpi = p;
  754. X            while (isdigit(*p)) {
  755. X                p++;
  756. X            }
  757. X
  758. X            if (p == dpi || *p != '\0') {
  759. X                continue;
  760. X            }
  761. X            dotsperinch = atoi(dpi);
  762. X            FileName = (char *)malloc(devnamelen + strlen(FontName) 
  763. X             + strlen(FontSize) + strlen(dpi) + 4);
  764. X            if (!FileName){
  765. X                fatal("Can't allocate file name space.\n");
  766. X            }
  767. X            (void) sprintf(FileName, "%s.%s.%s.%s", devname,
  768. X             FontName, FontSize, dpi);
  769. X            InsertFont(Typesetter, FontName,
  770. X             (dotsperinch * atoi(FontSize) + (SUNRES / 2))
  771. X              / SUNRES, FileName);
  772. X        }
  773. X    }
  774. X    XFreeFontNames(fontNames);
  775. X#endif SUNTOOLS
  776. X    return(1);
  777. X}
  778. X
  779. X/* PrintFontDirectory - Print out all the fonts found by the ReadFontDirectory
  780. X *    routine.
  781. X */
  782. XPrintFontDirectory(Typesetter)
  783. Xstruct Typesetter *Typesetter;
  784. X{
  785. X    struct FontBitStruct *FontPointer, *SizePointer;
  786. X    char    *Device;
  787. X
  788. X    Device = Typesetter->Name;
  789. X    printf("Found the following fonts for %s.",Device);
  790. X
  791. X    for (FontPointer = &Typesetter->FontBitHead;
  792. X         FontPointer;
  793. X         FontPointer = FontPointer->NextFont){
  794. X             printf("\n%s\t",FontPointer->Name);
  795. X             for (SizePointer = FontPointer;
  796. X              SizePointer;
  797. X              SizePointer = SizePointer -> NextSize){
  798. X                  printf("%d ",SizePointer->Size);
  799. X              }
  800. X         }
  801. X    printf("\n");
  802. X}
  803. X
  804. X/* InsertFont - OK, we've found a file name in the BITDIR that looks like
  805. X *    a proper font name, add it to the font list for the current 
  806. X *    typesetter.  This routine just looks for the proper point in the
  807. X *    two dimensional (name and size) linked list.  AddFont() does
  808. X *    all the real work.
  809. X */
  810. XInsertFont(Typesetter,Name,Size,FileName)
  811. Xstruct Typesetter *Typesetter;
  812. Xchar    *Name, *FileName;
  813. Xint    Size;
  814. X{
  815. X    struct FontBitStruct *FontPointer, *SizePointer, *CurrentFont;
  816. X    struct FontBitStruct *AddFont();
  817. X
  818. X    for (FontPointer = &Typesetter->FontBitHead;
  819. X         FontPointer;
  820. X         FontPointer = FontPointer->NextFont){
  821. X        if (STREQ(Name,FontPointer->Name)){
  822. X            for (SizePointer = FontPointer;
  823. X                 SizePointer;
  824. X                 SizePointer = SizePointer->NextSize){
  825. X                     if (SizePointer->Size == Size){
  826. X                         return;
  827. X                     }
  828. X                     CurrentFont = SizePointer;
  829. X                 }
  830. X            CurrentFont->NextSize = AddFont(Name,Size,FileName);
  831. X            return;
  832. X        }
  833. X        CurrentFont = FontPointer;
  834. X    }
  835. X    CurrentFont->NextFont = AddFont(Name,Size,FileName);
  836. X}
  837. X
  838. X/* AddFont - Add a structure to the list of available fonts indicating that
  839. X *    the font Name and Size are available in the indicated FileName.
  840. X */
  841. Xstruct FontBitStruct *
  842. XAddFont(Name,Size,FileName)
  843. Xchar    *Name, *FileName;
  844. Xint    Size;
  845. X{
  846. X
  847. X    struct FontBitStruct *font;
  848. X
  849. X    font = (struct FontBitStruct *)malloc(sizeof(*font));
  850. X    if (!font){
  851. X        fatal("Can't get storage for font cache.\n");
  852. X    }
  853. X    
  854. X    strncpy(font->Name,Name,MaxFontName);
  855. X    font->Size = Size;
  856. X    font->NextFont = font->NextSize = NULL;
  857. X    font->Bits = NULL;
  858. X    font->FileName = FileName;
  859. X    return(font);
  860. X}
  861. X
  862. X/* VirtualLoadFont - Given a desired FontName and PointSize find the font
  863. X *    that we have screen bits for that is as close as possible.  Close
  864. X *    is defined as being the same name and the largest point size that
  865. X *    is smaller than the desired.
  866. X *
  867. X *    If we don't have the correct font name then go ahead and use the
  868. X *    "R" font.  We don't bother giving the user an error message, but
  869. X *    we probably should.
  870. X *
  871. X *    Once we have the best font name, then look down the list until
  872. X *    we can find the best point size match.  If we can't find an exact
  873. X *    match then use the NextBestFont which is the largest point size
  874. X *    that is smaller than the desired (we try to avoid overlapping the
  875. X *    characters).  If we didn't find the exact match then we install
  876. X *    our best approximation as the correct choice so the user only
  877. X *    sees one point size substitution error message.
  878. X */
  879. Xstruct FontBitStruct *
  880. XVirtualLoadFont(FontName,PointSize)
  881. Xchar     *FontName;                /* Actual Font Name */
  882. Xint    PointSize;                /* Actual Point Size */
  883. X{
  884. X    struct FontBitStruct *NewFont, *NextBestFont, *FindFont(), *LastFont;
  885. X
  886. X    if (!FontName || FontName[0] == 0)
  887. X        fatal("Bad font found in VirtualLoadFont.\n");
  888. X
  889. X#ifndef SUNTOOLS
  890. X    /*
  891. X     *  X11 has this brain dead convention that all font names must
  892. X     *  be lower case! Case independent, forsooth...
  893. X     */
  894. X    {
  895. X    register char *s;
  896. X    for(s = FontName; *s; s++)
  897. X        if (isascii(*s) && isupper(*s)) 
  898. X            *s = tolower(*s);
  899. X    }
  900. X#endif SUNTOOLS
  901. X
  902. X    if (CurrentFont && CurrentFont->Size == PointSize &&
  903. X     STREQ(CurrentFont->Name, FontName)){
  904. X        return CurrentFont;
  905. X    }
  906. X
  907. X    NewFont = FindFont(FontName);
  908. X    if (!NewFont){
  909. X        NewFont = FindFont(DEFAULTFONT);
  910. X    }
  911. X    if (!NewFont){
  912. X        fatal("Couldn't find either the %s or the R font.",FontName);
  913. X    }
  914. X
  915. X    NextBestFont = NewFont;
  916. X
  917. X#ifdef    FONTDEBUG
  918. X    printf("Loading font name %s, point size %d.\n",
  919. X           FontName,PointSize);
  920. X    if (CurrentFont)
  921. X        printf("Current font is %s, point size %d.\n",
  922. X            CurrentFont->Name, CurrentFont->Size);
  923. X#endif
  924. X
  925. X    while (NewFont){
  926. X        if (NewFont->Size == PointSize){
  927. X            CurrentFont = NewFont;
  928. X            return(CurrentFont);
  929. X        }
  930. X
  931. X        if (NextBestFont->Size > PointSize &&
  932. X            NewFont->Size < NextBestFont->Size){
  933. X                NextBestFont = NewFont;
  934. X
  935. X        }
  936. X            
  937. X        if (NewFont->Size < PointSize &&
  938. X            NextBestFont->Size < NewFont->Size){
  939. X                NextBestFont = NewFont;
  940. X        }
  941. X        LastFont = NewFont;
  942. X        NewFont = NewFont->NextSize;
  943. X    }
  944. X    if (abs(PointSize - NextBestFont->Size) > 1){
  945. X        warning("Couldn't find point size %d of the %s font. Using point size %d instead",
  946. X              PointSize,FontName, NextBestFont->Size);
  947. X    }
  948. X    /*
  949. X     * Don't have the correct size....so fake an entry so the user only
  950. X     * gets one error message.
  951. X     */
  952. X    if (PointSize != NextBestFont->Size){
  953. X        if (!LastFont ->NextSize){
  954. X            NewFont = AddFont(FontName, PointSize,
  955. X                             NextBestFont->FileName);
  956. X            NewFont->Bits = NextBestFont->Bits;
  957. X            NextBestFont = LastFont->NextSize = NewFont;
  958. X        }
  959. X    }
  960. X    CurrentFont = NextBestFont;
  961. X    return CurrentFont;
  962. X}
  963. X
  964. X/* Findfont - Given a font name, find it on the list of available output
  965. X *    type styles.  This routine is called by the VirtualLoadFont routine.
  966. X */
  967. Xstruct FontBitStruct *
  968. XFindFont(FontName)
  969. Xchar    *FontName;
  970. X{
  971. X    struct FontBitStruct *NewFont;
  972. X
  973. X    if (!OutputTypesetter){
  974. X        fatal("Program error: No typesetter specified.\n");
  975. X    }
  976. X    for (NewFont= &OutputTypesetter->FontBitHead;
  977. X         NewFont;
  978. X         NewFont=NewFont->NextFont){
  979. X        if (STREQ(NewFont->Name,FontName)){
  980. X            return(NewFont);
  981. X        }
  982. X    }
  983. X    return(0);
  984. X}
  985. X
  986. X/* LoadFontBits - OK, the user has already requested a point size and
  987. X *    typeface.  The VirtualLoadFont() routine has figured out which
  988. X *    of the available output fonts is best to use.
  989. X *
  990. X *    Now this routine actually goes out and loads the correct (Versatec)
  991. X *    font file.  All the real work is done by the SunTools pf_open()
  992. X *    routine.  Thanks, Sun.
  993. X */
  994. X
  995. XLoadFontBits(){
  996. X#ifdef SUNTOOLS
  997. X    struct pixfont *pf_open();
  998. X
  999. X    if (CurrentFont->Bits){
  1000. X        return;                /* Already Loaded */
  1001. X    }
  1002. X#ifdef    FONTDEBUG    
  1003. X    printf("Loading the bits from %s.\n",CurrentFont->FileName);
  1004. X#endif    FONTDEBUG    
  1005. X
  1006. X    CurrentFont->Bits = pf_open(CurrentFont->FileName);
  1007. X
  1008. X    if (!CurrentFont->Bits){
  1009. X        fatal("Can't read fonts from %s.\n",
  1010. X              CurrentFont->FileName);
  1011. X    }
  1012. X#else SUNTOOLS
  1013. X    static Font curxfont = 0;
  1014. X    
  1015. X    if (CurrentFont->Bits){
  1016. X        if (curxfont != CurrentFont->Bits->fid) {
  1017. X#ifdef FONTDEBUG
  1018. X            printf("changing to font %s\n", CurrentFont->FileName);
  1019. X#endif FONTDEBUG
  1020. X            curxfont = CurrentFont->Bits->fid;
  1021. X            XSetFont(dpy, gc, curxfont);
  1022. X        }
  1023. X        return;                /* Already Loaded */
  1024. X    }
  1025. X
  1026. X#ifdef FONTDEBUG
  1027. X    printf("Loading the bits from %s.\n",CurrentFont->FileName);
  1028. X#endif FONTDEBUG
  1029. X
  1030. X    CurrentFont->Bits = XLoadQueryFont(dpy, CurrentFont->FileName);
  1031. X
  1032. X    if (!CurrentFont->Bits){
  1033. X        fatal("Can't read fonts from %s.\n",
  1034. X              CurrentFont->FileName);
  1035. X    }
  1036. X    curxfont = CurrentFont->Bits->fid;
  1037. X    XSetFont(dpy, gc, curxfont);
  1038. X#endif SUNTOOLS
  1039. X}
  1040. END_OF_FILE
  1041. if test 29184 -ne `wc -c <'xtroff/font.c'`; then
  1042.     echo shar: \"'xtroff/font.c'\" unpacked with wrong size!
  1043. fi
  1044. # end of 'xtroff/font.c'
  1045. fi
  1046. echo shar: End of archive 15 \(of 18\).
  1047. cp /dev/null ark15isdone
  1048. MISSING=""
  1049. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1050.     if test ! -f ark${I}isdone ; then
  1051.     MISSING="${MISSING} ${I}"
  1052.     fi
  1053. done
  1054. if test "${MISSING}" = "" ; then
  1055.     echo You have unpacked all 18 archives.
  1056.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1057. else
  1058.     echo You still need to unpack the following archives:
  1059.     echo "        " ${MISSING}
  1060. fi
  1061. ##  End of shell archive.
  1062. exit 0
  1063.