home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / driver / util / new_font.c < prev    next >
C/C++ Source or Header  |  1994-07-10  |  99KB  |  3,614 lines

  1. /*
  2. **    This file generated by localize 2.9 (AmigaDOS 2.1) from util/new_font.c
  3. */
  4. /*
  5.  ************************************************************************
  6.  *                                    *
  7.  *    new_font.c                    04. Mar. 90    *
  8.  *                                    *
  9.  *    A replacement for the old fontstructure-handling.    (hes)    *
  10.  *                                    *
  11.  ************************************************************************
  12.  */
  13.  
  14. /*
  15.  *    Zu tun:
  16.  *
  17.  *    o common ueberpruefen. Wird common nicht zuviel/staendig neu angelegt?
  18.  *      (-)
  19.  *    o Arrays (z.B. Path) ueberpruefen, ob man es nicht per Pointer
  20.  *      (strdup, stringpool? (Liste von Strings??)) machen koennte.
  21.  *      (!)
  22.  *    o Ueberall wo mit Arrays gearbeitet wird muss strncat strncpy ...
  23.  *      verwendet werden.
  24.  *      (!)
  25.  *    o Fontstruktur umstellen. Es soll eine strikte Trennung zwischen DVI-File
  26.  *      Daten und Fontdaten eingefuehrt werden. Dazu noch eine Struktur
  27.  *      vorschalten. Alle Flags umschalten. Alles sollen Bitflags werden.
  28.  *      (!!!)
  29.  *    o pk Substitutionsmoeglichkeit: Es muesste moeglich sein, zu sagen
  30.  *      dass falls ein 143dpi Font nicht gefunden wird, moege doch der 144dpi
  31.  *      Font gesucht werden.
  32.  *      (-)
  33.  *    o TFM File lesen (optional), falls ein Font nicht gefunden wurde.
  34.  *      (!!)
  35.  *    o Die Fontsubstitutionsidee von Bernd implementieren. Falls pkdir oder
  36.  *      flib definiert, dann die der Reihe nach absuchen.
  37.  *      (!)
  38.  *    o Per Option auswaehlbar was/nach welcher Reihenfolge die einzelnen
  39.  *      Ersetzungen gemacht werden sollen:
  40.  *      - Substitution durch andere Groesse
  41.  *      - Black Box durch TFM File
  42.  *      - cmr10 Font einsetzen
  43.  *      (!)
  44.  *    o Virtuelle Fonts! (der zweite Punkt sollte das schon vorbereiten)
  45.  *      (!!!)
  46.  *    o Zukunftsidee:
  47.  *      Die Struktur so umstellen, dass mit mehreren DVI-Files *gleichzeitig*
  48.  *      gearbeitet werden kann.
  49.  *      Vielleicht mal die Fontverwaltung als eigenen Task implementieren
  50.  *      so dass ShowDVI/DVIprint gleichzeitig darauf zugreifen koennen.
  51.  *      (Oder auch andere zu portierende Treiber (Beeble, dvips, ...))
  52.  *      (-)
  53.  *
  54.  */
  55.  
  56. #include "defines.h"
  57.  
  58. #define OLDARGS        /* !!!!! */
  59.  
  60. #include <stdio.h>
  61.  
  62. #ifdef AMIGA
  63. #  include <exec/types.h>
  64. #  include <dos/dos.h>
  65. #endif
  66.  
  67. #include "globals.h"
  68. #include "textypes.h"
  69. #include "flmt.h"
  70. #include "new_font.h"
  71.  
  72. #ifdef ANSI
  73. #  include <string.h>
  74. #  include <stdlib.h>
  75. #  include <stddef.h>
  76. #endif
  77. #include <ctype.h>
  78.  
  79.  
  80. #ifdef LATTICE
  81. #  include <clib/exec_protos.h>
  82. #  include <clib/dos_protos.h>
  83. #  include <pragmas/exec_pragmas.h>
  84. #  include <pragmas/dos_pragmas.h>
  85.    extern struct DosLibrary    *DOSBase;
  86. #endif
  87.  
  88. #include "globals.i"
  89. #include "new_font.i"
  90. #include "loadfont.i"
  91. #include "dvihand.i"
  92.  
  93. #ifdef SLOW
  94. #  include "bitmap.i"
  95. #endif
  96. #ifndef OLDARGS
  97. #  include "parsef.h"
  98. #  include "parsef.i"
  99. #endif
  100.  
  101. #ifdef ATARI
  102. # include <ext.h>
  103. # include <aes.h>   /* for shel_find */
  104. # define abs(a)        labs(a)
  105. # ifdef __TURBOC__
  106.    extern int access(char *, int);
  107. #  if (__TURBOC__ < 0x200)
  108. #   define setup_lru_flib slruflib 
  109. #   define setup_lru_font slrufont 
  110. #   define what_lru_flib wlruflib 
  111. #   define what_lru_font wlrufont
  112. #   define search_font_location sfloc
  113. #   define search_font_group sfgrp
  114. #   define is_font_in_font_list isifolist
  115. #   define is_font_in_lib_list isililist
  116. #   define is_font_in_pk_dirs isipkdirs
  117. #   define search_in_defined_libs sindelibs
  118. #   define search_in_rest_pathes sinrepathes
  119. #   define define_font def_font
  120. #   define define_flib def_flib
  121. #  endif
  122. # endif
  123. #endif
  124.  
  125.  
  126.  
  127. #ifdef AMIGA
  128. #  ifdef FONTS_IN_CHIPMEM
  129. #    include <exec/memory.h>
  130. #    include <libraries/dos.h>
  131. char *AllocRemember();
  132. extern struct Remember *Rem_Key;    /* Memory-Management */
  133. extern int fontmem_in_chipmem;        /* soll oder soll nicht? */
  134. #  endif
  135. #endif
  136.  
  137.  
  138.  
  139. #ifndef ATARI
  140. # ifndef abs
  141. #  define abs(a)    (((a) < 0) ? -(a) : (a))
  142. # endif
  143. #endif
  144.  
  145. #ifdef AMIGA
  146. #  define ACC_READ        4
  147. #  define B_OPEN_READ        "r"
  148. #else
  149. #  ifdef ATARI
  150. #    define ACC_READ        S_IREAD
  151. #    define B_OPEN_READ        "rb"
  152. #  endif
  153. #endif
  154.  
  155.  
  156.  
  157.  
  158. /*
  159.  * Fuer die locale-Library:
  160.  *
  161.  * Hier duerfen *nur* die MSG_#? Nummern eingebunden werden!
  162.  * Achtung:
  163.  * Es muss/sollte 'multiple-include' erlaubt sein!
  164.  */
  165. #include "local.i"
  166.  
  167. #undef  CATCOMP_ARRAY
  168. #undef  CATCOMP_BLOCK
  169. #undef  CATCOMP_STRINGS
  170. #define CATCOMP_NUMBERS
  171. #include "localstr.h"
  172.  
  173.  
  174.  
  175. /*
  176.  ************************************************************************
  177.  *                                    *
  178.  ************************************************************************
  179.  */
  180.  
  181. /*
  182.  ************************************************************************
  183.  *    external variables                        *
  184.  ************************************************************************
  185.  */
  186.  
  187. #ifdef AMIGA
  188. extern struct ArpBase    *ArpBase;
  189. #endif
  190.  
  191. extern long        resolution;    /* actual base resolution    */
  192.        struct Font    *cfontptr;    /* pointer to the actual font    */
  193.  
  194.        struct FontMan    *FontRoot = NULL;    /* root structure    */
  195.  
  196.  
  197. /*
  198.  ************************************************************************
  199.  *    global variables for this module                *
  200.  ************************************************************************
  201.  */
  202.  
  203. static char        *lowmem, *charmap, *start_mem, *end_mem;
  204.  
  205.     /*  lowmem    pointer to the first free memory cell        */
  206.     /*  charmap    pointer to the current character        */
  207.     /*  start_mem    pointer to the start of the fontmem        */
  208.     /*  end_mem    pointer to the end of the fontmem        */
  209.  
  210.  
  211. static short mags[NRMAGS] = { 1000, 1095, 1200, 1315, 1440, 1577,
  212.             1728, 2074, 2488, 2986, 3583, 4300, 5160 };
  213.  
  214.     /* mag(0) mag(0.5) mag(1) mag(1.5) mag(2) mag(2.5)
  215.        mag(3) mag(4)   mag(5) mag(6)   mag(7) mag(8)   mag(9) */
  216.  
  217.  
  218.  
  219.  
  220. #ifndef OLDARGS
  221. /**=============================================================**/
  222.  
  223. struct FontMan *globarg_fnt_root;
  224.  
  225. static void __stdargs    fkw_conc_dirs
  226.         Args((struct string_parse *p, char *line));
  227. static void __stdargs    fkw_parse_string
  228.         Args((struct string_parse *p, char *line, char *string));
  229. static void __stdargs    fkw_dir
  230.         Args((struct string_parse *p, char *line,
  231.             long *res, char *where));
  232. static void __stdargs    fkw_define_flib
  233.         Args((struct string_parse *p, char *line,
  234.             long *res, char *path));
  235. static void __stdargs    fkw_define_font
  236.         Args((struct string_parse *p, char *line,
  237.             char *name, long *res, char *path));
  238.  
  239. /* There should be better ways to do this, but I don't want to refer
  240. to absolute array indices. */
  241. #define ARG_CONC_FLIB    1
  242. #define ARG_CONC_PK    2
  243. #define ARG_STR_FLIB    1
  244. #define ARG_STR_PK    2
  245. #define ARG_STR_BASEPKD    3
  246. #define ARG_STR_PKDIR    4
  247. #define ARG_STR_FLIBFNT    5
  248. #define ARG_PKDIR    1    /*don't you dare change this (see func)!*/
  249. #define ARG_BASEPKDIR    2    /*don't you dare change this (see func)!*/
  250.  
  251. static struct string_parse font_config[] = {
  252.     {
  253.     "flibenv",
  254.     NULL,
  255.     (string_parse_function) fkw_conc_dirs,
  256.     PAF_ARGS,
  257.     ARG_CONC_FLIB
  258.     },
  259.     {
  260.     "pkenv",
  261.     NULL,
  262.     (string_parse_function) fkw_conc_dirs,
  263.     PAF_ARGS,
  264.     ARG_CONC_PK
  265.     },
  266.     {
  267.     "flib_str",
  268.     "%s",
  269.     (string_parse_function) fkw_parse_string,
  270.     PAF_1_ARG,
  271.     ARG_STR_FLIB
  272.     },
  273.     {
  274.     "pk_str",
  275.     "%s",
  276.     (string_parse_function) fkw_parse_string,
  277.     PAF_1_ARG,
  278.     ARG_STR_PK
  279.     },
  280.     {
  281.     "basepkdir_str",
  282.     "%s",
  283.     (string_parse_function) fkw_parse_string,
  284.     PAF_1_ARG,
  285.     ARG_STR_BASEPKD
  286.     },
  287.     {
  288.     "pkdir_str",
  289.     "%s",
  290.     (string_parse_function) fkw_parse_string,
  291.     PAF_1_ARG,
  292.     ARG_STR_PKDIR
  293.     },
  294.     {
  295.     "flib_fnt_str",
  296.     "%s",
  297.     (string_parse_function) fkw_parse_string,
  298.     PAF_1_ARG,
  299.     ARG_STR_FLIBFNT
  300.     },
  301.     {
  302.     "flib",
  303.     "%d %s",
  304.     (string_parse_function) fkw_define_flib,
  305.     PAF_2_ARGS
  306.     },
  307.     {
  308.     "pkdir",
  309.     "%ld %s",
  310.     (string_parse_function) fkw_dir,
  311.     PAF_2_ARGS,
  312.     ARG_PKDIR
  313.     },
  314.     {
  315.     "basepkdir",
  316.     "%ld %s",
  317.     (string_parse_function) fkw_dir,
  318.     PAF_2_ARGS,
  319.     ARG_BASEPKDIR
  320.     },
  321.     {
  322.     "font",
  323.     "%s %d %s",
  324.     (string_parse_function) fkw_define_font,
  325.     PAF_3_ARGS
  326.     },
  327.     {
  328.     NULL
  329.     }
  330. };
  331. #endif
  332.  
  333. /*
  334.  ************************************************************************
  335.  *    external functions                        *
  336.  ************************************************************************
  337.  *
  338.  * void resetfont    Args((void));
  339.  * void setup_ctfmw    Args((struct Font *font));
  340.  * void SetFntNum    Args((long fntnum));
  341.  * int  HasBeenRead    Args((long fntnum));
  342.  * void LoadFont    Args((int  action,          0: define only
  343.  *                  long fntnum,         1: load only
  344.  *                  char *fntname,         2: define & load
  345.  *                  long chksum,
  346.  *                  long d,
  347.  *                  long s,
  348.  *                  long fontmag,
  349.  *                  long fontmag5));
  350.  * int  init_fontmt    Args((char show));         0: dviprint, 1: showdvi
  351.  * long alloc_char    Args((ulong size));         ret = -1 -> no memory
  352.  *
  353.  *
  354.  */
  355.  
  356.  
  357. /*
  358.  ************************************************************************
  359.  *    local functions                            *
  360.  ************************************************************************
  361.  */
  362.  
  363. static void         MarkFile        Args((char * full_name));
  364. #ifdef PASEIT
  365. static int parsit                Args((char *line,
  366.                               char ***array));
  367. #endif
  368. static void setup_sealst            Args((struct FontMan *fnt_root));
  369. static int split_env_string            Args((struct SeaLst *sl,
  370.                               char *env_var,
  371.                               char *def_value));
  372. static long compute_vert            Args((long hdpi));
  373. static void my_sprintf                Args((char buffer[],
  374.                               int length,
  375.                               char fmt[],
  376.                               char fntname[],
  377.                               long dpi,
  378.                               long dpi5));
  379. static void        InitFontMan        Args((char is_show));
  380. static long        test_pk_file        Args((char *pk_name));
  381. static void        setup_lru_flib        Args((struct LibLst *list,
  382.                               struct Fnt_Lib *lib));
  383. static void        setup_lru_font        Args((struct FontLst *list,
  384.                               struct Font *font));
  385. static struct Fnt_Lib    *what_lru_flib        Args((struct LibLst *list));
  386. static struct Font    *what_lru_font        Args((struct FontLst *list));
  387. static void        close_flibs        Args((struct FontMan *fnt_root));
  388. static struct CommonFontGroups
  389.             *search_font_group    Args((char *fntname,
  390.                               struct FontMan *fnt_root));
  391. static struct Font    *search_font        Args((char *fntname,
  392.                               long magnification,
  393.                               long magnification5,
  394.                               struct FontMan *fnt_root));
  395. static struct Font    *search_font_location    Args((char *fntname,
  396.                               long dpi,
  397.                               long dpi5,
  398.                               struct FontMan *fnt_root));
  399. static struct Font     *is_font_in_font_list    Args((char *fntname,
  400.                               long dpi,
  401.                               long dpi5,
  402.                               struct FontLst *fnt_list,
  403.                               struct FontMan *fnt_root));
  404. static struct Font    *is_font_in_lib_list    Args((char *fntname,
  405.                               long dpi,
  406.                               long dpi5,
  407.                               struct FontMan *fnt_root));
  408. static struct Font     *is_font_in_pk_dirs    Args((char * fntname,
  409.                               long dpi,
  410.                               long dpi5,
  411.                               struct FontMan *fnt_root));
  412. static struct Font     *is_font_in_pred_pk_dirs Args((char * fntname,
  413.                               long dpi,
  414.                               long dpi5,
  415.                               struct FontMan *fnt_root,
  416.                               short base));
  417. static struct Font    *define_test_pk_font    Args((char *path,
  418.                               char *fntname,
  419.                               long dpi,
  420.                               long dpi5,
  421.                               char *format_str,
  422.                               struct FontMan *fnt_root));
  423. static struct Font    *search_in_defined_libs    Args((char *fntname,
  424.                               long dpi,
  425.                               long dpi5,
  426.                               struct FontMan *fnt_root));
  427. static struct Font    *search_in_rest_pathes    Args((char *fntname,
  428.                               long dpi,
  429.                               long dpi5,
  430.                               struct FontMan *fnt_root));
  431. static struct Font    *find_font_in_flib    Args((char *fntname,
  432.                               long dpi,
  433.                               long dpi5,
  434.                               struct Fnt_Lib *flib,
  435.                               struct FontMan *fnt_root));
  436. static void        read_font_def_file    Args((struct FontMan *fnt_root,
  437.                               char *file_name));
  438. static void        parse_line        Args((struct FontMan *fnt_root,
  439.                               char *line));
  440. static void        conc_dirs        Args((char *str,
  441.                               struct SeaLst *sl));
  442. static void        define_flib        Args((struct FontMan *fnt_root,
  443.                               long dpi,
  444.                               char *path));
  445. static void        define_font        Args((struct FontMan *fnt_root,
  446.                               long dpi,
  447.                               char *path,
  448.                               char *name));
  449.  
  450. struct Font        *mag_substitution    Args((char *fntname,
  451.                               long dpi,
  452.                               struct FontMan *fnt_root));
  453. struct Font        *dpi_substitution    Args((char *fntname,
  454.                               long magnification,
  455.                               struct FontMan *fnt_root));
  456.  
  457. static void         init_mem        Args((ulong size));
  458. static long         *open_charmap        Args((void));
  459. static long         close_charmap        Args((void));
  460. static void        adjust_mem        Args((long *start,
  461.                               long size));
  462. static int        do_garcol        Args((void));
  463.  
  464. #ifdef AMIGA
  465. static struct Font    *read_atex_file        Args((char *fntname,
  466.                               long dpi,
  467.                               long dpi5,
  468.                               struct FontMan *fnt_root));
  469. static int        copy_file        Args((char *source,
  470.                               char *drain));
  471. static int        create_path        Args((char *path));
  472. #endif
  473.  
  474.  
  475.  
  476.  
  477.  
  478. /*
  479.  ************************************************************************
  480.  *    mark the file full_name                        *
  481.  ************************************************************************
  482.  */
  483.  
  484. static void MarkFile(char * full_name)
  485. {
  486.   if (mark_fonts) {
  487.     __aligned struct FileInfoBlock fib;
  488.     char comment[80];
  489.     struct DateStamp ds;
  490.     long old;
  491.     BPTR lck = Lock(full_name, ACCESS_READ);
  492.     if (lck) {
  493.       (void)DateStamp(&ds);
  494.       Examine(lck, &fib);
  495.       if (fib.fib_Comment[0] == '\0' || sscanf(fib.fib_Comment+10, "%d", &old) != 1) {
  496.         old = 0;
  497.       }
  498.       sprintf(comment, "FontUsed: %d (%d %d %d)", old+1, ds.ds_Days, ds.ds_Minute, ds.ds_Tick);
  499.       UnLock(lck);
  500.       if (!SetComment(full_name, comment)) {
  501.         ; //printf("SetComment %d fehlgeschlagen!\n", comment);
  502.       }
  503.     }
  504.   }
  505. }
  506.  
  507.  
  508.  
  509. /*
  510.  ************************************************************************
  511.  *    release all unpacked chars                    *
  512.  ************************************************************************
  513.  */
  514.  
  515. void release_mem(void)
  516. {
  517.   struct FontLst *flist;
  518.   long i,j;
  519.  
  520.   if (FontRoot != NULL) {
  521.     /* release chars */
  522.     if (FontRoot->unpacked_mem > 0) {
  523.       j=0L;
  524.       for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font) {
  525.         for (i=0; i<NPXLCHARS; i++) {
  526.           if (flist->font.common->ch[i].unpacked != NULL) {
  527.             xfree(flist->font.common->ch[i].unpacked);
  528.             flist->font.common->ch[i].unpacked = NULL;
  529.             j++;
  530.           }
  531.         }
  532.       }
  533.       Logging(MSG_RELEASE_CHARS,FontRoot->unpacked_mem, j);
  534.       FontRoot->unpacked_mem = 0L;
  535.     }
  536.   }
  537. }
  538.  
  539.  
  540.  
  541.  
  542. /*
  543.  ************************************************************************
  544.  *    parse a line and returns int argc, char *argv[]            *
  545.  ************************************************************************
  546.  */
  547.  
  548. #ifdef PASEIT
  549. static int parsit(char *line,char ***array)
  550. {
  551.   char **argv;
  552.   char *word;
  553.   char *linecp;
  554.   int  i,j, num_words, longest_word;
  555.  
  556.   argv = *array;
  557.   if (argv != (char **)NULL) {
  558.     for (i=0; argv[i] != (char*) NULL; i++) {
  559.       xfree(argv[i]);        /* free the old array */
  560.     }
  561.     xfree((char *)argv);        /* and then free the ptr itself */
  562.   }
  563.   
  564.   linecp = line;
  565.   num_words = longest_word = 0;
  566.   while (1) {
  567.     for (; *linecp == ' ' || *linecp == '\t'; ++linecp) ;
  568.     if (*linecp == '\0') {
  569.       break;
  570.     }
  571.     word = linecp;
  572.     for (; *linecp != ' ' && *linecp != '\t' && *linecp != '\0'; ++linecp) ;
  573.     num_words++;
  574.     if ((i = linecp-word) > longest_word) {
  575.       longest_word = i;
  576.     }
  577.     if (*linecp == '\0') {
  578.       break;
  579.     }
  580.   }
  581.   
  582.   if ((argv = (char **)xmalloc((size_t)(num_words +1) * 4)) == (char **)NULL) {
  583.     Warning(MSG_NO_MEM);
  584.     return (0);
  585.   }
  586.   
  587.   if ((word = (char *)xmalloc((size_t)(longest_word+2))) == (char *)NULL) {
  588.     Warning(MSG_NO_MEM);
  589.     return (0);
  590.   }
  591.   
  592.   j = i = 0;
  593.   while (1) {
  594.     for (; *line == ' ' || *line == '\t'; line++) ;
  595.     if (*line == '\0') {
  596.       break;
  597.     }
  598.     i = 0;
  599.     for (; *line != ' ' && *line != '\t' && *line != '\0'; line++) {
  600.       word[i++] = *line;
  601.     }
  602.     word[i] = '\0';
  603.     argv[j] = xmalloc((size_t)strlen(word+1));
  604.     if (argv[j] == (char *)NULL) {
  605.       xfree(word);
  606.       Warning(MSG_NO_MEM);
  607.       return (0);
  608.     }
  609.     (void)strcpy(argv[j], word);
  610.     j++;
  611.     if (*line == '\0') {
  612.       break;
  613.     }
  614.   }
  615.   argv[j] = (char *)NULL;    /* NULL at end of list */
  616.   *array = argv;
  617.   xfree(word);
  618.   return (j);
  619. }
  620. #endif
  621.  
  622.  
  623. /*
  624.  ************************************************************************
  625.  *    compute the vertical resolution                    *
  626.  ************************************************************************
  627.  */
  628.  
  629. static long compute_vert(long hdpi)
  630. {
  631.   return ((hdpi * vconvresolution + hconvresolution/2) / hconvresolution);
  632. }
  633.  
  634.  
  635.  
  636. /*
  637.  ************************************************************************
  638.  *    make in path a complete path-string                *
  639.  ************************************************************************
  640.  */
  641.  
  642. void mk_correct_path(char *path)
  643. {
  644.     int length = strlen(path);
  645. #if defined(HARDDEB)
  646.     if (NULL == path) printf("mk_correct_path == NULL!\n");
  647. #endif
  648.     if ('\n' == path[length-1]) path[--length] = '\0';
  649. #  ifdef ATARI
  650.     if (path[length-1] != ':' && path[length-1] != '\\') {
  651.       path[length] = '\\';
  652.       path[length+1] = '\0';
  653.     }
  654. #  else
  655.     if (0 < length && path[length-1] != ':' && path[length-1] != '/') {
  656.       path[length] = '/';
  657.       path[length+1] = '\0';
  658.     }
  659. #  endif
  660. }
  661.  
  662.  
  663. /*
  664.  ************************************************************************
  665.  *    insert dpi and fontname in fmt string                *
  666.  ************************************************************************
  667.  */
  668.  
  669. static void my_sprintf(char *buffer, int buf_length, char *fmt,
  670.             char *fntname, long dpi, long dpi5)
  671. {
  672.   char c, *t, work[16], hbuf[128];
  673.  
  674.   if (buffer == NULL || fmt == NULL || fntname == NULL) {
  675.     Fatal(20, MSG_INTERNAL_ERROR_SPRINTF);
  676.   }
  677.  
  678.   --buf_length;        /* there has to be a '\0' char at the end ! */
  679.  
  680.   while( *fmt != '\0' && buf_length > 0 ) {
  681.     if( *fmt != '%' ) {        /* copy all chars up to a '%' sign */
  682.       *buffer++ = *fmt++;
  683.       --buf_length;
  684.       continue;
  685.     }
  686.  
  687.     /* we have found a '%' */
  688.     fmt++;
  689.     if( *fmt == '%' ) {        /* for '%%' insert one '%' */
  690.       *buffer++ = *fmt++;
  691.       --buf_length;
  692.       continue;
  693.     }
  694.  
  695.     /* copy '%...X' part from `fmt' into work[] */
  696.     t = work;
  697.     *t++ = '%';
  698.  
  699.     /* Zwischen % und Zeichen sind nur Zahlen+Punkt erlaubt */
  700.     while( (c = *fmt) != '\0' && strchr(".0123456789", c) != NULL
  701.         && t < &work[16-2] )
  702.     *t++ = *fmt++;
  703.  
  704.     *t = 'd';        /* 'd' is most common case, orig char is in `c' */
  705.     *(t+1) = '\0';
  706.     /* weitere Fehlerabfrage wird im default-case des switch erledigt */
  707.  
  708.     if (c != '\0')
  709.       fmt++;
  710.  
  711.     switch (c) {
  712.     case 'h' :
  713.     case 'd' :    sprintf(hbuf, work, (int)dpi);    /* insert dpi        */
  714.         break;
  715.     case 'v' :    sprintf(hbuf, work, (int)compute_vert(dpi));
  716.         break;
  717. #ifdef FONT_MAG
  718.     case 'x' :    { int pxl = (dpi5 * resolution * 5 + 500)/1000;
  719.           sprintf(hbuf, work, pxl);    /* insert dpi*5        */
  720.         }
  721.         break;
  722.     case 'y' :    { int pxl = (dpi5 * resolution * 5 + 500)/1000;
  723.           sprintf(hbuf, work, (int)compute_vert(pxl));
  724.         }
  725.         break;
  726.     case 'M' :    sprintf(hbuf, work, dpi5);    /* insert font mag */
  727.         break;
  728.     case 'm' :    *t = 'f';            /* insert font mag/1000 */
  729.         sprintf(hbuf, work, (float)dpi5/1000.0);
  730.         break;
  731. #else
  732.     case 'x' :    sprintf(hbuf, work, (int)dpi5);    /* insert dpi*5 */
  733.         break;
  734.     case 'y' :    sprintf(hbuf, work, (int)compute_vert(dpi5));
  735.         break;
  736. #endif
  737.     case 's' :  *t = 's';
  738.         sprintf(hbuf, work, fntname);    /* insert font name */
  739.         break;
  740.     default  :    Fatal(5, MSG_UNKNOWN_FORMAT_SPRINTF);
  741.         return;
  742.     }
  743.  
  744.     if (strlen(hbuf) > 100) {
  745.       Fatal(20, MSG_STRING_OVERFLOW_SPRINTF);
  746.       /* NOT REACHED */
  747.     }
  748.  
  749.     if (strlen(hbuf) >= buf_length)
  750.       hbuf[buf_length] = '\0';    /* Cut rest of hbuf (with warning?) */
  751.  
  752.     strcpy(buffer, hbuf);
  753.     buffer += strlen(hbuf);
  754.     buf_length -= strlen(hbuf);
  755.   }
  756.  
  757.   *buffer = '\0';    /* null-terminate string */
  758. }
  759.  
  760.  
  761. /* string only for logging ! */
  762. void get_full_name(char *str, struct Font *fnt)
  763. {
  764.    char fontname[PK_NAME_SIZE], name[PATH_SIZE+PK_NAME_SIZE];
  765.  
  766.    if (fnt->common->where_is_font == WHERE_LIB) {
  767.      /* font in lib: fontname == Lib-name, name == full name of Lib */
  768.      my_sprintf(fontname, PK_NAME_SIZE,
  769.         fnt->common->location.fnt_library->format_str,
  770.                 fnt->common->fnt_group->fnt_name,
  771.                 fnt->common->resolution,
  772.                 fnt->common->resolution5);
  773.      strcpy(name,fnt->common->location.fnt_library->path);
  774.      mk_correct_path(name);
  775.      strcat(name,fontname);
  776.      strcat(name," [");
  777.      strcat(name,fnt->common->fnt_group->fnt_name);
  778.      strcat(name,"]");
  779.    }
  780.    else {
  781.      /* font as pk-file: fontname: full pk-name (without path) */
  782.      strcpy(name,fnt->common->location.pk_directory->path);
  783.      mk_correct_path(name);
  784.      my_sprintf(fontname, PK_NAME_SIZE,
  785.         fnt->common->location.pk_directory->format_str,
  786.         fnt->common->fnt_group->fnt_name,
  787.         fnt->common->resolution,
  788.         fnt->common->resolution5);
  789.      strcat(name, fontname);
  790.    }
  791.  
  792.    strcpy(str, name);
  793. }
  794.  
  795.  
  796.  
  797. /*
  798.  ************************************************************************
  799.  *    split a env-string and saves it in a search-list        *
  800.  ************************************************************************
  801.  */
  802.  
  803. static int split_env_string(struct SeaLst *sl, char *env_var, char *def_value)
  804. {
  805.   char *tmp, *ptr, save[300];
  806.   int i;
  807.   char *string;
  808.   struct SeaEle *ele, *ele2;
  809.  
  810.  
  811.   save[0] = '\0';    /* init for strcat() */
  812.  
  813.   tmp = getenv(env_var);
  814.   if (tmp != NULL) {
  815.     strcpy(save, tmp);
  816.     for (ptr = save; *ptr != '\0'; ptr++) {
  817.       if (*ptr == '!' || *ptr == ',') {        /* env-seperators */
  818.         *ptr = ' ';
  819.       }        /* !! no spaces in pathes of environmentstring !! */
  820.     }
  821.     strcat(save, " ");
  822.   }
  823.  
  824.   if (PXLpath != NULL) {    /* -a option given */
  825.     strcat(save, PXLpath);
  826.     strcat(save, " ");
  827.   }
  828.  
  829. #ifdef ALWAYS_DEFAULT
  830.   strcat(save, def_value);
  831. #else
  832.   if (strlen(save) == 0)
  833.     strcat(save, def_value);
  834. #endif
  835.  
  836.   i = 1;
  837.   string = xmalloc(strlen(save)+1);
  838.   strcpy(string,save);
  839.  
  840.   ele = xmalloc(sizeof(struct SeaEle));
  841.   sl->first_ele = ele;
  842.   ele->path = string;
  843.   ele->next_ele = NULL;
  844.  
  845.   while (*string != '\0' && isspace(*string)) { string++; }
  846.  
  847.   while (*string != '\0') {
  848.     while (*string != '\0' && !isspace(*string)) { string++; }
  849.     if (*string != '\0') {
  850.       *string = '\0';
  851.       string++;
  852.       while (*string != '\0' && isspace(*string)) { string++; }
  853.       if (*string != '\0') {
  854.         ele2 = xmalloc(sizeof(struct SeaEle));
  855.         ele2->path = string;
  856.         ele2->next_ele = NULL;
  857.         ele->next_ele = ele2;
  858.         ele = ele2;
  859.         i++;
  860.       }
  861.     }
  862.   }
  863.  
  864.   sl->number = i;
  865.  
  866.   return 0;
  867. }
  868.  
  869.  
  870. /*
  871.  ************************************************************************
  872.  *    setup the search list for flibs/pk-dirs                *
  873.  ************************************************************************
  874.  */
  875.  
  876. static void setup_sealst(struct FontMan *fnt_root)
  877. {
  878.   if (split_env_string(&(fnt_root->s_list_flib),ENV_FLIB_DIRS,FLIB_AREA) != 0) {
  879.     Warning(MSG_ERROR_SEARCH_LIST_LIB);
  880.   }
  881.   if (split_env_string(&(fnt_root->s_list_pkdirs),ENV_PK_DIRS,PK_AREA) != 0) {
  882.     Warning(MSG_ERROR_SEARCH_LIST_PK);
  883.   }
  884. }
  885.  
  886.  
  887. /*
  888.  ************************************************************************
  889.  *    is the file a pk-file, returns size of pk-file or 0 if not    *
  890.  ************************************************************************
  891.  */
  892. static long test_pk_file(char *pk_name)
  893. {
  894.   long size;
  895.  
  896. #undef SAVETY_PK
  897. #ifdef SAVETY_PK
  898.   char ptr[2];
  899.   FILE *fp;
  900.  
  901.   fp = BINARYOPEN(pk_name);
  902.   if (fp != NULL) {
  903.     if (fread(ptr,1,2,fp) != 2) {
  904.       fclose(fp);
  905.       return 0L;
  906.     }
  907.     if (*((unsigned short *)ptr) != PK_MAGIC) {
  908.       fclose(fp);
  909.       return 0L;
  910.     }
  911.     fclose(fp);
  912. #endif
  913.  
  914. #ifdef ATARI
  915.   {
  916.    struct stat pkstat;
  917.    
  918.    if (stat(pk_name, &pkstat) == -1)
  919.     {
  920.      return(0L);
  921.     }
  922.    return(pkstat.st_size);
  923.   }
  924. #endif
  925. #ifdef AMIGA
  926.     {
  927.       struct FileInfoBlock *fib;
  928. #    ifdef LATTICE
  929.       BPTR lock;
  930. #    else
  931.       struct FileLock *lock;
  932. #    endif
  933.  
  934.       lock = Lock(pk_name,ACCESS_READ);
  935.       if (lock == NULL) {
  936.         return 0L;
  937.       }
  938.       fib = (struct FileInfoBlock *)xmalloc(sizeof(struct FileInfoBlock));
  939.       if (Examine(lock,fib)==0) {
  940.         xfree(fib);
  941.         UnLock((BPTR)lock);
  942.         return 0L;
  943.       }
  944.       size = fib->fib_Size;
  945.       xfree(fib);
  946.       UnLock((BPTR)lock);
  947.     }
  948. #endif
  949. #ifdef SAVETY_PK
  950.   }
  951. #endif
  952.  
  953.   return size;
  954. }
  955.  
  956.  
  957.  
  958. /*
  959.  ************************************************************************
  960.  *    advance the lru-count of all lib's expect lib            *
  961.  ************************************************************************
  962.  */
  963.  
  964. static void setup_lru_flib (struct LibLst *list, struct Fnt_Lib *lib)
  965. {
  966.   struct LibLst *temp;
  967.  
  968. #if 0
  969.   for (temp = list; temp != NULL; temp = temp->next_lib) {
  970.     if (&(temp->flib) == lib) {
  971.       temp->flib.lru_count = 0;
  972.     }
  973.     else {
  974.       temp->flib.lru_count++;
  975.     }
  976.   }
  977. #else
  978.   /* (br) so sollte es klappen... und es ist schneller ;-) */
  979.   for (temp = list; temp != NULL; temp = temp->next_lib) {
  980.     temp->flib.lru_count++;
  981.   }
  982.   lib->lru_count = 0;
  983. #endif
  984. }
  985.  
  986. /*
  987.  ************************************************************************
  988.  *    advance the lru-count of all font's expect font            *
  989.  ************************************************************************
  990.  */
  991.  
  992. static void setup_lru_font (struct FontLst *list, struct Font *font)
  993. {
  994.   register struct FontLst *temp;
  995.  
  996.   /* (br) dto. */
  997.   for (temp = list; temp != NULL; temp = temp->next_font) {
  998.     temp->font.common->lru_count++;
  999.   }
  1000.   font->common->lru_count = 0L;
  1001. }
  1002.  
  1003.  
  1004. /*
  1005.  ************************************************************************
  1006.  *    search the lib with the highest lru-count and fileptr != NULL    *
  1007.  ************************************************************************
  1008.  */
  1009.  
  1010. static struct Fnt_Lib *what_lru_flib (struct LibLst *list)
  1011. {
  1012.   register struct LibLst *temp, *res = NULL;
  1013.   long s = 0;
  1014.  
  1015.   /*** used for closing older flibs ***/
  1016.   for (temp = list; temp != NULL; temp = temp->next_lib) {
  1017.     if (temp->flib.lru_count > s && temp->flib.lib_status == LIB_OPEND) {
  1018.       s = temp->flib.lru_count;
  1019.       res = temp;
  1020.     }
  1021.   }
  1022.   if (res == NULL) {
  1023.     res = list;
  1024.   }
  1025.   return &(res->flib);
  1026. }
  1027.  
  1028. /*
  1029.  ************************************************************************
  1030.  *    search the font with the highest lru-count            *
  1031.  ************************************************************************
  1032.  */
  1033.  
  1034. static struct Font *what_lru_font (struct FontLst *list)
  1035. {
  1036.   struct FontLst *temp, *res;
  1037.   long s;
  1038.  
  1039.   s = 0;
  1040.   res = NULL;
  1041.  
  1042.   /*** used for deleting font from the ram ***/
  1043.   for (temp = list; temp != NULL; temp = temp->next_font) {
  1044.     if ((temp->font.common->lru_count >= s && temp->font.common->fnt_status == FNT_OLD_LOADED) ||
  1045.         (temp->font.common->lru_count >= s && temp->font.common->fnt_status == FNT_DEFINED_OLOADED) ||
  1046.         (temp->font.common->lru_count > s && temp->font.common->fnt_status == FNT_LOADED)) {
  1047.       s = temp->font.common->lru_count;
  1048.       res = temp;
  1049.     }
  1050.   }
  1051.   if (res == NULL) {
  1052.     return NULL;
  1053.   }
  1054.   else {
  1055.     return &(res->font);
  1056.   }
  1057. }
  1058.  
  1059.  
  1060. /*
  1061.  ************************************************************************
  1062.  *    close the flibs whith highest lru-count                *
  1063.  ************************************************************************
  1064.  */
  1065.  
  1066. static void close_flibs(struct FontMan *fnt_root)
  1067. {
  1068.   /* close files */
  1069.   short to_close = abs(fnt_root->files_left);
  1070.   short cl, res=0;
  1071.   struct Fnt_Lib *lib;
  1072.  
  1073.   if (fnt_root->files_left > 0) {
  1074.     return;
  1075.   }
  1076.  
  1077.   for (cl=0; cl <= to_close; cl++) {
  1078.     lib = what_lru_flib(fnt_root->flib_list);
  1079.     if (lib->file_ptr != NULL) {
  1080.       fclose(lib->file_ptr);
  1081.       lib->file_ptr = NULL;
  1082.       lib->lib_status = LIB_READ_CLOSED;
  1083.       res++;
  1084.     }
  1085.   }
  1086.   fnt_root->files_left += res;
  1087. }
  1088.  
  1089.  
  1090. /*
  1091.  ************************************************************************ *
  1092.  *    setup the global fontmanagement-structure            * *
  1093.  ************************************************************************ *
  1094.  */
  1095.  
  1096. static void InitFontMan(char is_show)
  1097. {
  1098.   register struct FontMan *fr;
  1099.  
  1100.   /* (br) Why not a static & initialized FontRoot ??? */
  1101.  
  1102.   fr = (struct FontMan *)xmalloc((size_t)sizeof(struct FontMan));
  1103.   
  1104.   FontRoot = fr;
  1105.  
  1106. #ifdef OLD_NOFONT
  1107.   fr->noFontList            = NULL;
  1108. #endif
  1109.   fr->s_list_flib.number        = 0L;
  1110.   fr->s_list_flib.first_ele        = NULL;
  1111.   fr->s_list_pkdirs.number        = 0L;
  1112.   fr->s_list_pkdirs.first_ele        = NULL;
  1113.   fr->s_list_pkdpi.number        = 0L;
  1114.   fr->s_list_pkdpi.first_ele        = NULL;
  1115.   fr->s_list_base_pkdpi.number        = 0L;
  1116.   fr->s_list_base_pkdpi.first_ele    = NULL;
  1117.   fr->font_list                = NULL;
  1118.   fr->flib_list                = NULL;
  1119.   fr->group_list            = NULL;
  1120.   fr->files_left            = MAXOPEN;
  1121.   fr->unpacked_mem            = 0L;
  1122.  
  1123.   if (is_show) {
  1124.     fr->driver_type        = (char)DRIVER_TYPE_SHOWDVI;
  1125.   }
  1126.   else {
  1127.     fr->driver_type        = (char)DRIVER_TYPE_DVIPRINT;
  1128.   }
  1129.  
  1130.   fr->flib_fmt      = strdup(FLIB_STRING);
  1131.   fr->pk_fmt        = strdup(PK_STRING);
  1132.   fr->pkdir_fmt     = strdup(PKDIR_STRING);
  1133.   fr->basepkdir_fmt = strdup(BASE_PK_STRING);
  1134.   fr->flib_fnt_fmt  = strdup(FLIB_FNT_STRING);
  1135.  
  1136.   if (fr->flib_fmt == NULL || fr->pk_fmt == NULL ||
  1137.     fr->pkdir_fmt == NULL || fr->flib_fnt_fmt == NULL) {
  1138.     Fatal(10, MSG_NO_MEM);
  1139.   }
  1140.  
  1141.   setup_sealst(fr);
  1142.   
  1143.   read_font_def_file(fr, is_show ? SFONT_DEF_FILE : DFONT_DEF_FILE);
  1144. }
  1145.  
  1146.  
  1147. /*
  1148.  *    ********    global functions    *******
  1149.  */
  1150.  
  1151.  
  1152. /*
  1153.  ************************************************************************ *
  1154.  *    initialize all                            * *
  1155.  ************************************************************************ *
  1156.  */
  1157.  
  1158. void init_fontmt(char show)
  1159. {
  1160.   init_mem(fontmemsize);
  1161.   InitFontMan(show);        /* showdvi OR dviprint    */
  1162. }
  1163.  
  1164.  
  1165.  
  1166. /*
  1167.  ************************************************************************ *
  1168.  *    reset the status of all fonts                    * *
  1169.  ************************************************************************ *
  1170.  */
  1171.  
  1172. void resetfont(void)
  1173. {
  1174.   struct FontLst *fntlst;
  1175.  
  1176.   for (fntlst = FontRoot->font_list; fntlst != NULL; fntlst = fntlst->next_font) {
  1177.     if (fntlst->font.common->fnt_status == FNT_DEFINED) {
  1178.       fntlst->font.common->fnt_status = FNT_FOUND;
  1179.     } else if (fntlst->font.common->fnt_status == FNT_LOADED
  1180.         || fntlst->font.common->fnt_status == FNT_DEFINED_OLOADED) {
  1181.       fntlst->font.common->fnt_status = FNT_OLD_LOADED;
  1182.     }
  1183.     fntlst->font.fnt_number = -1L;
  1184.     fntlst->font.ctfmw_valid = (char)FALSE;
  1185.   }
  1186. }
  1187.  
  1188.  
  1189. /*
  1190.  ************************************************************************ *
  1191.  *    setup the ctfmw[] array of the font                * *
  1192.  ************************************************************************ *
  1193.  */
  1194.  
  1195. void setup_ctfmw(struct Font *font)        /* dies wird auch in fast_cp.c gebraucht */
  1196. {
  1197.   int i, maxchar;
  1198.  
  1199.   maxchar = font->common->maxchars;
  1200.  
  1201.   /* printf("setup_ctfmw(%s, %d): maxchar = %d\n", font->common->fnt_group->fnt_name, font->fnt_number, maxchar);*/
  1202.  
  1203.   for (i = 0; i < maxchar; i++) {
  1204.     font->ctfmw[i] =
  1205.     scalewidth(font->common->fnt_group->tfmw[i], font->space_faktor);
  1206.   }
  1207.   for (; i < NPXLCHARS; i++) {
  1208.     font->ctfmw[i] = 0L;
  1209.   }
  1210.  
  1211.   font->ctfmw_valid = (char)TRUE;
  1212. }
  1213.  
  1214.  
  1215.  
  1216. /*
  1217.  ************************************************************************ *
  1218.  *    load the font fntnum                        * *
  1219.  ************************************************************************ *
  1220.  */
  1221.  
  1222. void SetFntNum (long fntnum)
  1223.   struct FontLst *fntlst;
  1224.  
  1225.   for (fntlst = FontRoot->font_list;
  1226.        fntlst != NULL && fntlst->font.fnt_number != fntnum;
  1227.        fntlst = fntlst->next_font);
  1228.  
  1229.   if (fntlst == NULL) {
  1230.      Fatal(5, MSG_FONT_UNDEFINED, fntnum);
  1231.   }
  1232.  
  1233.   cfontptr = &(fntlst->font);        /* this is the actual font now */
  1234.  
  1235.   if (cfontptr->common->fnt_status == FNT_DEFINED ||
  1236.       cfontptr->common->fnt_status == FNT_DEFINED_OLOADED) {
  1237.     LoadFont(1,fntnum,(char *)NULL,0L,0L,0L,0L,0L);    /* load font */
  1238.   }
  1239.   else {
  1240.     setup_lru_font (FontRoot->font_list, cfontptr);
  1241.     if (!cfontptr->ctfmw_valid)
  1242.     setup_ctfmw(cfontptr);
  1243.   }
  1244.  
  1245.   /* nachfolgendes sollte man besser als zusaetzliche Information zum
  1246.    * Font ablegen (z.B. tenquadpxl = 10 * size of font in pt als Naeherung
  1247.    * fuer 1 quad; siehe Level0-Draft)
  1248.    */
  1249.   { double tenquad;
  1250.     unsigned long tenquadpxl;
  1251.     extern double alpha;
  1252.     extern long mag;
  1253.     extern int thinspace, backspace, vertsmallspace;
  1254.  
  1255.     tenquad = ((((double)(mag * cfontptr->space_faktor))/
  1256.         ((double)0x100000 * 100.0)) / alpha);
  1257.     tenquadpxl = (unsigned long)
  1258.         (tenquad * (100 * resolution) / 7227.0 + 0.5);
  1259. #if 0
  1260.     Logging("Font #%d >%s< at %ld = %ld  (ss: %lx  ds: %lx)",
  1261.     cfontptr->fnt_number, cfontptr->common->fnt_group->fnt_name,
  1262.     (long)floor(tenquad),
  1263.     tenquadpxl, cfontptr->space_faktor, cfontptr->design_faktor);
  1264. #endif
  1265.     vertsmallspace = 8 * tenquadpxl / 100;
  1266.     thinspace = 2 * tenquadpxl / 100;
  1267.     backspace = -(9 * tenquadpxl / 100);
  1268.   }
  1269. }
  1270.  
  1271.  
  1272. /*
  1273.  ************************************************************************ *
  1274.  *    is this font already defined?                    * *
  1275.  ************************************************************************ *
  1276.  */
  1277.  
  1278. int HasBeenRead(long fntnum)
  1279. {
  1280.   register struct FontLst *fntlst;
  1281.  
  1282.   for(fntlst = FontRoot->font_list; fntlst != NULL; fntlst = fntlst->next_font)
  1283.     if( fntlst->font.fnt_number == fntnum )
  1284.     return TRUE;
  1285.  
  1286.   return FALSE;
  1287. }
  1288.  
  1289.  
  1290.  
  1291. /*
  1292.  ************************************************************************
  1293.  *    search a font-group                        *
  1294.  ************************************************************************
  1295.  */
  1296.  
  1297. /*
  1298.  *  Search font `fntname' in group_list, if not found, make new group and
  1299.  *  insert it in group_list.
  1300.  */
  1301.  
  1302.   static struct CommonFontGroups *
  1303. search_font_group(char *fntname, struct FontMan *fnt_root)
  1304. {
  1305.   struct GroupLst *glst;
  1306.  
  1307.   for (glst = fnt_root->group_list; glst != NULL; glst = glst->next_group) {
  1308.     if( 0 == stricmp(fntname, glst->fnt_group.fnt_name) )
  1309.     return &(glst->fnt_group);
  1310.   }
  1311.  
  1312.   /* group not found: make a new one */
  1313.  
  1314.   /* Dirty Trick (but supported by all C-Compiler):
  1315.    * struct includes "char fnt_name[1]" declaration as last(!) part,
  1316.    * we have to allocate the struct and the string mem
  1317.    */
  1318.   glst = (struct GroupLst *) xmalloc(sizeof(struct GroupLst) + strlen(fntname));
  1319.  
  1320.   /**** Initialize structure: ****/
  1321.   { struct CommonFontGroups *gp;
  1322.     int i;
  1323.  
  1324.     gp = &(glst->fnt_group);
  1325.     strcpy(gp->fnt_name, fntname);
  1326.  
  1327.     /* set TFM width of all chars to ZERO */
  1328.     for( i = 0; i < NPXLCHARS; i++ ) {
  1329.     gp->tfmw[i] = 0L;
  1330.     }
  1331.   }
  1332.  
  1333.   /* and insert new group node at the beginning of group_list */
  1334.   glst->next_group = fnt_root->group_list;
  1335.   fnt_root->group_list = glst;
  1336.  
  1337.   return &(glst->fnt_group);
  1338. }
  1339.  
  1340.  
  1341. /*
  1342.  ************************************************************************ *
  1343.  *    make new fontlist and commonelement nodes for the font        * *
  1344.  ************************************************************************ *
  1345.  */
  1346.  
  1347. /*
  1348.  *  Make new font description for `fntname' and insert it in font_list.
  1349.  */
  1350.  
  1351.   static struct Font *
  1352. make_new_fontdesc(char *fntname, struct FontMan *fnt_root)
  1353. {
  1354.   struct Font *fnt;
  1355.   struct FontLst *fontlst;
  1356.     
  1357.   fontlst = (struct FontLst *)xmalloc((size_t)sizeof(struct FontLst));
  1358.   fnt = &(fontlst->font);
  1359.  
  1360.   fnt->common = (struct CommonFontElems *)
  1361.             xmalloc((size_t)sizeof(struct CommonFontElems));
  1362.  
  1363.   /* Search for the group of this font, if none found, make a new group */
  1364.   fnt->common->fnt_group        = search_font_group(fntname, FontRoot);
  1365.  
  1366.   /* Initialize... */
  1367.   fnt->common->fnt_length        = 0L;
  1368.   fnt->common->lru_count        = 0L;
  1369.   fnt->common->ch_start_bm        = NULL;
  1370.   fnt->common->ch_len            = 0L;
  1371.   fnt->common->location.pk_directory    = NULL;
  1372.   /* search_font_group initialize the TFM width info to 0L for new group
  1373.    * => it's save to set maxchars to NPXLCHARS
  1374.    * (=> if this font doesn't exist, it uses the whole tfmw array)
  1375.    */
  1376.   fnt->common->maxchars            = NPXLCHARS;
  1377.  
  1378.   fnt->space_faktor        = 0L;
  1379.   fnt->design_faktor        = 0L;
  1380.   fnt->chksum            = 0L;
  1381.   fnt->ctfmw_valid        = (char)FALSE;
  1382.  
  1383.   /* insert font at the beginning of the font-list */
  1384.   fontlst->next_font  = fnt_root->font_list;
  1385.   fnt_root->font_list = fontlst;
  1386.  
  1387.   return fnt;
  1388. }
  1389.  
  1390.  
  1391. /*
  1392.  ************************************************************************ *
  1393.  *    load / define a font                        * *
  1394.  *    where we must search the font?                    * *
  1395.  *        - user defs / pk-dirs / flib-dirs or            * *
  1396.  *        - user defs / flib-dirs / pk-dirs or ...?        * *
  1397.  ************************************************************************ *
  1398.  */
  1399.  
  1400. void LoadFont(int  action, long fntnum, char *fntname,
  1401.           long chksum, long d, long s, long fontmag, long fontmag5)
  1402.     /*
  1403.      * 0: define only    \
  1404.      * 1: load only         => action
  1405.      * 2: define & load    /
  1406.      */
  1407. {
  1408.   struct FontLst *fntlst;
  1409.   struct Font *fnt;
  1410.   char full_name[PATH_SIZE+FLIB_NAME_SIZE];
  1411.   int i, is_subst = FALSE;
  1412.  
  1413.  
  1414.   /* search font with the correct fntnum */
  1415.   for (fntlst = FontRoot->font_list;
  1416.        fntlst != NULL && fntlst->font.fnt_number != fntnum;
  1417.        fntlst = fntlst->next_font);
  1418.  
  1419.   if (fntlst != NULL)        /* font with fntnum found -> font defined */
  1420.    {
  1421.     if (action != 1)        /* define font, but font already defined?? */
  1422.      {
  1423.        Fatal(5, MSG_FONT_ALREADY_DEFINED, fntname, fntnum);
  1424.      }
  1425.     fnt = &(fntlst->font);
  1426.    }
  1427.   else                /* no font with fntnum found -> font undefined */
  1428.    {
  1429.     if (action == 1) {        /* load only, but font not defined?? */
  1430.       Fatal(5, MSG_FONT_STR_UNDEFINED, fntname, fntnum);
  1431.     }
  1432.  
  1433.     /****    and now -> search the font    ****/
  1434.     fnt = search_font(fntname, fontmag, fontmag5, FontRoot);
  1435.    }
  1436.  
  1437.  
  1438.   if (fnt == NULL) {
  1439.     /* Oh no, NO font */
  1440.     /* Warning already printed */
  1441.  
  1442.     fnt = make_new_fontdesc(fntname, FontRoot);
  1443.  
  1444.     fnt->fnt_number            = fntnum;
  1445.     fnt->common->fnt_status    = FNT_NOT_EXISTS;
  1446.     fnt->common->resolution    = fontmag;
  1447.     fnt->common->resolution5   = fontmag5;
  1448.     fnt->orig_dpi              = fontmag;
  1449.     fnt->space_faktor          = s;
  1450.     fnt->design_faktor         = d;
  1451.     fnt->chksum                = chksum;
  1452.     
  1453.     for (i=0; i < NPXLCHARS; i++)     /* mark the chars */
  1454.      {
  1455.       fnt->common->ch[i].packed_data = -1L;
  1456.      }
  1457.  
  1458.     /*
  1459.      * Here we can read the tfm-file of this font (if it exists).
  1460.      * Currently we use the tfmw info of another font in the same font
  1461.      * group for the char width info.
  1462.      */
  1463.     return;                /* =========>>>>> and return */
  1464.   }
  1465.  
  1466.   /* ======================================== */
  1467.   /* ===   We know, that fnt != NULL      === */
  1468.   /* ======================================== */
  1469.  
  1470.   /* here it is */
  1471.  
  1472.   if (action != 1) {            /* not ONLY load the font */
  1473.       /* define the font */
  1474.  
  1475.       /* is this font a substituted font ?? */
  1476.       if (fnt->fnt_number != fntnum &&
  1477.       (fnt->common->fnt_status == FNT_DEFINED || 
  1478.        fnt->common->fnt_status == FNT_DEFINED_OLOADED || 
  1479.        fnt->common->fnt_status == FNT_LOADED)) {
  1480.  
  1481.         /* problem with substituted fonts -> same font with different fntnum */
  1482.         struct FontLst *fontlst;
  1483.  
  1484.     is_subst = TRUE;
  1485.         fontlst = (struct FontLst *)xmalloc((size_t)sizeof(struct FontLst));
  1486.         fontlst->font.common        = fnt->common;
  1487.         fontlst->font.orig_dpi      = fontmag;
  1488.  
  1489.         /* sort font into font-list */
  1490.         fontlst->next_font = FontRoot->font_list;
  1491.         FontRoot->font_list = fontlst;
  1492.  
  1493.         fnt = &(fontlst->font);        /* this is now the current font */
  1494.       }
  1495.  
  1496.       fnt->fnt_number    = fntnum;    /* define the font */
  1497.       fnt->space_faktor  = s;
  1498.       fnt->design_faktor = d;
  1499.       fnt->chksum        = chksum;
  1500.       fnt->ctfmw_valid   = (char)FALSE;
  1501.       
  1502. #if 0    /* bin mir nicht sicher, ob das gemacht werden muss */
  1503.       /* Bei den substituierten Fonts muss das ctfmw Feld wieder aufgefrischt werden! */
  1504.       if (is_subst && (fnt->common->fnt_status == FNT_DEFINED_OLOADED || 
  1505.                   fnt->common->fnt_status == FNT_LOADED)) {
  1506.         fnt->common->fnt_status = FNT_LOADED;
  1507.         setup_ctfmw(fnt);
  1508.       }
  1509. #endif
  1510.  
  1511.   }    /* if (action != 1) */
  1512.  
  1513.   /* exist's the font ?? */
  1514.   if (fnt->common->fnt_status == FNT_NOT_EXISTS) {
  1515.       return;                /* =========>>>>> and return */
  1516.   }
  1517.  
  1518.   if (action == 0) {            /* only define the font */
  1519.       /* FNT_LOADET ist auch moeglich (wb. Substituierung..) */
  1520.       if (fnt->common->fnt_status != FNT_OLD_LOADED && 
  1521.       fnt->common->fnt_status != FNT_LOADED) {
  1522.         fnt->common->fnt_status = FNT_DEFINED;
  1523.       } else {
  1524.         fnt->common->fnt_status = FNT_DEFINED_OLOADED;
  1525. #if 0    /* bin mir nicht sicher, ob das gemacht werden muss */
  1526.         setup_ctfmw(fnt);
  1527. #endif
  1528.       }
  1529.       return;                /* =========>>>>> and return */
  1530.   }
  1531.  
  1532.   /* ================================================================= */
  1533.   /* === The font is defined, it exists ... and now: load the font === */
  1534.   /* ================================================================= */
  1535.  
  1536.   if (fnt->common->fnt_status == FNT_OLD_LOADED
  1537.     || fnt->common->fnt_status == FNT_DEFINED_OLOADED
  1538.     || (is_subst && fnt->common->fnt_status == FNT_LOADED)) {
  1539.     /* pk-file already loaded */
  1540.     if (!is_subst) {
  1541.       sprintf(m_string,GetTeXString(MSG_RELOAD_FONT),
  1542.         fnt->common->fnt_group->fnt_name, fnt->common->resolution);
  1543.       /** Message(m_string); reload ist auf'n Bildschirm nicht so interessant **/
  1544.       sprintf(full_name,GetTeXString(MSG_FONTMEM_USED),
  1545.             (long)(100L-(end_mem-lowmem)*100L/fontmemsize));
  1546.       strcat(m_string,full_name);
  1547.       LoggingStr(m_string);
  1548.     }
  1549.  
  1550.     setup_lru_font (FontRoot->font_list, fnt);
  1551.     fnt->common->fnt_status = FNT_LOADED;
  1552.  
  1553.     setup_ctfmw(fnt);
  1554.     return;                /* =========>>>>> and return */
  1555.   }
  1556.  
  1557.   /* ======================= */
  1558.   /* === Load a new font === */
  1559.   /* ======================= */
  1560.   
  1561.   /* So nun sollte eigentlich der Font ins Fontmemory geladen werden.    */
  1562.   /* Alles ist bestens vorbereitet, ein Aufruf Load_really(fnt) taets.    */
  1563.   /* Aber es wird nicht gemacht! Es wird verzoegert, bis wirklich ein    */
  1564.   /* Zeichen aus dem Font benoetigt wird. Sprich erst wenn ein Zeichen    */
  1565.   /* in SetChar nicht gefunden wird. Falls der Font nur definiert ist,    */
  1566.   /* so wird ein Load_really() probiert.                */
  1567.   /* Das hat den Vorteil, wenn ein Font 'removed' wurde, die        */
  1568.   /* benoetigten Chars aber schon im Speicher sind, muss der Font nicht    */
  1569.   /* gleich wieder geladen werden, sonder eben erst, wenn ein Char    */
  1570.   /* auszupacken ist.                        (hes)    */
  1571.  
  1572.   /* printf("Load new font %s %d (was loaded %d, status %d, valid %d)\n", fnt->common->fnt_group->fnt_name, */
  1573.   /*    fnt->fnt_number, fnt->common->was_loadet, fnt->common->fnt_status, fnt->ctfmw_valid);*/
  1574.  
  1575.   if (!fnt->common->was_loadet) {
  1576.     /* dieser Font ist noch nie geladen worden... */
  1577.     /* also lade ihn zum ersten Mal. Dabei werden */
  1578.     /* auch die Chars Strukturen initialisiert.   */
  1579.     struct Chars *cd;
  1580.  
  1581.     fnt->common->was_loadet = TRUE;
  1582.  
  1583.     /* Initialisiere das ganze nur *einmal* pro Font! */
  1584.     cd = fnt->common->ch;
  1585.     for (i=0; i<NPXLCHARS; i++) {
  1586.       cd->pixelwidth  = 0;
  1587.       cd->packed_data = -1;    /* NIL pointer in internal memory */
  1588.       cd->unpacked    = NULL;
  1589.       cd++;
  1590.     }
  1591.  
  1592.     Load_really(fnt);    /* beim ersten Mal wird's gleich geladen! */
  1593.   }
  1594.   else {
  1595.     setup_ctfmw(fnt);    /* der Font war zwar schon mal geladen, aber ctfmw muss wieder geupdated werden */
  1596.   }
  1597. }
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603. /*
  1604.  ************************************************************************ *
  1605.  *    macht nun den letzten Schritt: Laed den Font in das fontmem    * *
  1606.  ************************************************************************ *
  1607.  */
  1608.  
  1609.  
  1610. void Load_really(struct Font *fnt)    
  1611.                     /* fnt_root wird *global* genommen */
  1612. {
  1613.   FILE *pkfile;
  1614.   char libname[FLIB_NAME_SIZE];
  1615.   char full_name[PATH_SIZE+FLIB_NAME_SIZE];
  1616.   long fntnum;
  1617.   char *fntname;
  1618.  
  1619.   fntnum = fnt->fnt_number;
  1620.   fntname = &(fnt->common->fnt_group->fnt_name[0]);
  1621.  
  1622.   if (fnt->common->fnt_status == FNT_LOADED) {
  1623.     Fatal(5,MSG_LOAD_LOADED_FONT,fntname,fntnum);
  1624.   }
  1625.  
  1626.   Message(MSG_LOAD_FONT,fnt->common->fnt_group->fnt_name,fnt->common->resolution);
  1627.  
  1628.   if (fnt->common->where_is_font == WHERE_LIB) {
  1629.     setup_lru_flib(FontRoot->flib_list, fnt->common->location.fnt_library);
  1630.     pkfile = fnt->common->location.fnt_library->file_ptr;
  1631.     if (pkfile == NULL) {
  1632.        if (fnt->common->location.fnt_library->lib_status == LIB_READ_CLOSED) {
  1633.  
  1634.       my_sprintf(libname,FLIB_NAME_SIZE,fnt->common->location.fnt_library->format_str /*FontRoot->flib_fmt*/,
  1635.             fnt->common->fnt_group->fnt_name,
  1636.             fnt->common->resolution,
  1637.             fnt->common->resolution5);
  1638.       strcpy(full_name,fnt->common->location.fnt_library->path);
  1639.       mk_correct_path(full_name);
  1640.       strcat(full_name,libname);
  1641.  
  1642.       pkfile = BINARYOPEN(full_name);
  1643.       if (pkfile != NULL) {
  1644.         FontRoot->files_left--;
  1645.         fnt->common->location.fnt_library->lib_status = LIB_OPEND;
  1646.         fnt->common->location.fnt_library->file_ptr   = pkfile;
  1647.         MarkFile(full_name);
  1648.       }
  1649.       else {
  1650.                 Fatal(5,MSG_CANT_OPEN,full_name);
  1651.       }
  1652.        }
  1653.        else {
  1654.       Fatal(20,MSG_INTERNAL_ERROR_LIB_MISMATCH);
  1655.        }
  1656.     }
  1657.     fseek(pkfile,fnt->common->where_in_lib,0);
  1658.   }
  1659.   else {
  1660.     /* load pk-file */
  1661.     strcpy(full_name,fnt->common->location.pk_directory->path);
  1662.     mk_correct_path(full_name);
  1663.     my_sprintf(libname,FLIB_NAME_SIZE,
  1664.         fnt->common->location.pk_directory->format_str,
  1665.         fnt->common->fnt_group->fnt_name,
  1666.         fnt->common->resolution, fnt->common->resolution5);
  1667.  
  1668. #ifdef UNNOETIG
  1669.     if (fnt->common->where_is_font == WHERE_PKDIR) {
  1670.       my_sprintf(libname,FLIB_NAME_SIZE,
  1671.         fnt->common->location.pk_directory->format_str /*FontRoot->pkdir_fmt*/,
  1672.         fnt->common->fnt_group->fnt_name,
  1673.         fnt->common->resolution, fnt->common->resolution5);
  1674.     }
  1675.     else {
  1676.       my_sprintf(libname,FLIB_NAME_SIZE,
  1677.         fnt->common->location.pk_directory->format_str /*FontRoot->pk_fmt*/,
  1678.         fnt->common->fnt_group->fnt_name,
  1679.         fnt->common->resolution, fnt->common->resolution5);
  1680.     }
  1681. #endif
  1682.     strcat(full_name,libname);
  1683.     if (fnt->common->fnt_status == FNT_PATH_DEFINED) {    /* shouldn't occur */
  1684.       fnt->common->fnt_length = test_pk_file(full_name);    /* check size */
  1685.       if (fnt->common->fnt_length == 0L) {
  1686.         Fatal(5,MSG_CANT_OPEN,full_name);
  1687.       }
  1688.     }
  1689.     pkfile = BINARYOPEN(full_name);
  1690.     if (pkfile == NULL) {
  1691.       Fatal(5,MSG_CANT_OPEN,full_name);
  1692.     }
  1693.     MarkFile(full_name);
  1694.   }
  1695.  
  1696.   if (pkfile == NULL) {        /* unnoetig, da schon abgefragt */
  1697.     FatalStr(20,"pkfile == NULL");
  1698.   }
  1699.  
  1700.   setup_lru_font(FontRoot->font_list, fnt);
  1701.  
  1702.   fnt->common->copied = (char)FALSE;
  1703.   fnt->common->ch_start_bm = open_charmap ();
  1704.  
  1705.   loadfont(fnt, pkfile);    /* NEW (laed nur pk-file, packt _nicht_ aus) */
  1706.  
  1707.   fnt->common->ch_len = close_charmap ();
  1708.   fnt->common->fnt_status  = FNT_LOADED;
  1709.   setup_ctfmw(fnt);
  1710.  
  1711.   if (fnt->common->where_is_font != WHERE_LIB) {
  1712.     fclose(pkfile);
  1713.   }
  1714.  
  1715.   Logging(MSG_LOAD_FONT_MEM_USED,
  1716.     fnt->common->fnt_group->fnt_name,
  1717.     fnt->common->resolution,
  1718.     100L-(end_mem-lowmem)*100L/fontmemsize);
  1719.  
  1720.   if (Stats) {
  1721.     if (fnt->common->where_is_font == WHERE_LIB) {
  1722.       my_sprintf(full_name, PATH_SIZE+FLIB_NAME_SIZE, fnt->common->location.fnt_library->format_str,
  1723.         fnt->common->fnt_group->fnt_name,
  1724.         fnt->common->resolution, fnt->common->resolution5);
  1725.       Logging(MSG_FOUND_IN_LIB,
  1726.         fnt->common->location.fnt_library->path, full_name);
  1727.     }
  1728.     else {
  1729.       my_sprintf(full_name, PATH_SIZE+FLIB_NAME_SIZE, fnt->common->location.pk_directory->format_str,
  1730.         fnt->common->fnt_group->fnt_name,
  1731.         fnt->common->resolution, fnt->common->resolution5);
  1732.       Logging(MSG_FOUND_AS_PK,
  1733.         fnt->common->location.pk_directory->path, full_name);
  1734.     }
  1735.   }
  1736. }
  1737.  
  1738.  
  1739.  
  1740. /*
  1741.  ************************************************************************ *
  1742.  *    alloc the memory for a character                * *
  1743.  ************************************************************************ *
  1744.  */
  1745.  
  1746. long alloc_char (size)
  1747.   ulong size;
  1748.   char *memstart;
  1749.  
  1750. #if 0
  1751.   size += (4 - (size % 4));    /* if size%4 == 0, add 4 ???? */
  1752. #else
  1753.   size = (size + 3) & ~3L;    /* long alignment */
  1754. #endif
  1755.  
  1756.   while (size > (long)(end_mem - lowmem)) {
  1757.      if( do_garcol() != 0 )
  1758.     return (-1L);    /* no memory */
  1759.   }
  1760.  
  1761.   memstart = lowmem;
  1762. #if 0
  1763.   lowmem = (char *)((ulong)lowmem + size);
  1764. #else
  1765.   lowmem += size;
  1766. #endif
  1767.  
  1768.   if (lowmem  < start_mem || charmap < start_mem ||
  1769.       lowmem  > end_mem   || charmap > end_mem ) {
  1770.     Fatal(10,MSG_MEMORY_ERROR);
  1771.   }
  1772.  
  1773.   return (long)((memstart - charmap)/sizeof(long));    /* / bytesperlong */
  1774. }
  1775.  
  1776.  
  1777. /* (br)
  1778.  * Substitution von Fonts sollte man noch verbessern, z.B. ist es
  1779.  * manchmal im Previewer wuenschenswert, wenn man kurz auf eine hoehere
  1780.  * Magnification gehen kann und trotzdem noch die meisten Fonts gefunden
  1781.  * werden (wenn man Fonts komplett in allen maghalf-Steps hat).
  1782.  *
  1783.  * Nachfolgend ist ein Ansatz, wie man dies machen kann.
  1784.  *
  1785.  * Um nicht zu grosse Rundungsfehler zu haben, sollte die Resolution, DPI
  1786.  * bzw. DPI5 (oder Magnification bzgl. DPI) eines Fonts besser mit einem
  1787.  * Faktor zwischen 2^8 und 2^16 multipliziert im Font-Struct abgelegt werden.
  1788.  * (Danach muss man jedoch auf Overflows achten !)
  1789.  */
  1790.  
  1791. /*
  1792.  ************************************************************************
  1793.  *    try to substitute a font within magscale list            *
  1794.  ************************************************************************
  1795.  */
  1796.  
  1797. struct Font *mag_substitution(fntname, dpi, fnt_root)
  1798.   char          *fntname;
  1799.   long          dpi;
  1800.   struct FontMan  *fnt_root;
  1801. {
  1802.   struct Font *fnt;
  1803.   int i, nr;
  1804.   long diff, temp, new_dpi, new_dpi5;
  1805.  
  1806.   diff = 1L<<30;            /* max diff */
  1807.   nr = 0;
  1808.  
  1809.   for ( i = 0; i < NRMAGS; i++ ) {
  1810.     /** new_dpi  = ((long)resolution * mags[nr] + 500L) / 1000L; **/
  1811.     new_dpi  = ((long)resolution * mags[i] + 500L) / 1000L;
  1812.     temp = abs(dpi - new_dpi);
  1813.     /* subst. Font sollte nicht groesser als 5% ueber tatsaechlichem sein */
  1814.     /* (Heuristik) */
  1815.     if (temp < diff && (new_dpi <= dpi || temp <= (resolution * 5)/100) ) {
  1816.         nr = i;
  1817.         diff = temp;
  1818.     }
  1819.   }
  1820.  
  1821.   fnt = NULL;
  1822.  
  1823.   while (nr >= 0 && fnt == NULL) {
  1824.       new_dpi  = ((long)resolution * mags[nr] + 500L) / 1000L;
  1825. #ifdef FONT_MAG
  1826.       new_dpi5 = mags[nr];
  1827. #else
  1828.       new_dpi5 = ((long)resolution * 5 * mags[nr] + 500L) / 1000L;
  1829. #endif
  1830.       if (new_dpi != dpi) {
  1831.         fnt = search_font_location(fntname, new_dpi, new_dpi5, fnt_root);
  1832.       }
  1833.       if (fnt == NULL) {
  1834.         nr--;
  1835.         if (fnt_root->files_left <= 0) {
  1836.           close_flibs(fnt_root);
  1837.         }
  1838.       }
  1839.   }
  1840.  
  1841.   if (nr >= 0) {
  1842.       /* substitute font */
  1843.       Logging(MSG_SUBSTITUTE_FONT,fntname,dpi,new_dpi);
  1844.       Message(MSG_SUBSTITUTE_FONT,fntname,dpi,new_dpi);
  1845.   }
  1846.   else {
  1847. #ifdef OLD_NOFONT
  1848.     /* no font found */
  1849.     struct noFont *nf;
  1850.   
  1851.     /* Dirty Trick (string alloc) */
  1852.     nf = (struct noFont *)xmalloc(sizeof(struct noFont) + strlen(fntname));
  1853.  
  1854.     strcpy(nf->fnt_name, fntname);
  1855.     nf->resolution = dpi;
  1856.  
  1857.     nf->next = fnt_root->noFontList;
  1858.     fnt_root->noFontList = nf;
  1859. #endif
  1860.     if (hconvresolution == vconvresolution) {
  1861.       Warning(MSG_FONT_NOT_FOUND, fntname, dpi);
  1862.     }
  1863.     else {
  1864.       Warning(MSG_FONT_XY_NOT_FOUND, fntname, dpi, compute_vert(dpi));
  1865.     }
  1866.   }
  1867.  
  1868.   return fnt;
  1869. }
  1870.  
  1871. /*
  1872.  ************************************************************************
  1873.  *    try to substitute a font with defined fonts/flibs        *
  1874.  ************************************************************************
  1875.  */
  1876.  
  1877. #if 0    /* dass muss ich mir erst mal spaeter in Ruhe ansehen (hes) */
  1878.  
  1879. struct Font *dpi_substitution(fntname, magnification, fnt_root)
  1880.   char          *fntname;
  1881.   long          magnification;
  1882.   struct FontMan  *fnt_root;
  1883. {
  1884.   struct Font *fnt;
  1885.   struct LibLst *lp;
  1886.   long diff, ndiff, dpi, best_dpi = 0L;
  1887.  
  1888.   diff = 1L << 30;
  1889.  
  1890.   for(lp = fnt_root->flib_list; lp != NULL; lp = lp->next_lib) {
  1891.     if( lp->flib.lib_status == LIB_NONE
  1892.     || lp->flib.lib_status == LIB_NOT_EXISTS )
  1893.       continue;
  1894.     dpi = lp->flib.resolution;
  1895.     ndiff = abs(magnification - dpi);
  1896.     /* subst. Font sollte nicht groesser als 5% ueber tatsaechlichem sein */
  1897.     if( ndiff < diff && (dpi <= magnification || ndiff <= 5*resolution/100) ) {
  1898.     diff = ndiff;
  1899.     best_dpi = dpi;
  1900.     }
  1901.   }
  1902.  
  1903.   Logging(MSG_TRY_SUBSTITUTE,fntname, magnification, best_dpi);
  1904.  
  1905.   fnt = NULL;
  1906.  
  1907.   if( best_dpi > 0L ) {        /* wir haben was gefunden */
  1908.     long dpi5;
  1909.  
  1910.     /* Oouch, this could be totally buggy! */
  1911. #ifdef FONT_MAG
  1912.     dpi5 = (best_dpi * 1000 + resolution/2) / resolution;
  1913. #else
  1914.     dpi5 = best_dpi * 5;
  1915. #endif
  1916.  
  1917.     fnt = search_font_location(fntname, best_dpi, dpi5, fnt_root);
  1918.   }
  1919.  
  1920.   if( fnt != NULL ) {
  1921.       /* substitute font */
  1922.       Logging(MSG_SUBSTITUTE_FONT,fntname, magnification, best_dpi);
  1923.       Message(MSG_SUBSTITUTE_FONT,fntname, magnification, best_dpi);
  1924.   }
  1925.  
  1926.   return fnt;
  1927. }
  1928.  
  1929. #endif
  1930.  
  1931.  
  1932. /*
  1933.  ************************************************************************
  1934.  *    search a font, substitute fonts if necessary            *
  1935.  ************************************************************************
  1936.  */
  1937.  
  1938. static struct Font *search_font(fntname, magnification, magnification5, fnt_root)
  1939.   char          *fntname;
  1940.   long          magnification;
  1941.   long          magnification5;
  1942.   struct FontMan  *fnt_root;
  1943. {
  1944.   struct Font *fnt;
  1945.  
  1946.   fnt = search_font_location(fntname, magnification, magnification5, fnt_root);
  1947.  
  1948. #ifdef AMIGA
  1949.   if (fnt == NULL) {
  1950.     char pkname[PK_NAME_SIZE];
  1951.     char pkdir[PATH_SIZE];
  1952.     char *format;
  1953.     struct SeaEleDpi *dele;
  1954.     short found;
  1955.  
  1956.     found = FALSE;
  1957.     for (dele = FontRoot->s_list_base_pkdpi.first_ele; dele != NULL && !found; dele = dele->next_ele) {
  1958.       if (dele->hdpi == hconvresolution && dele->vdpi == vconvresolution) {
  1959.         strcpy(pkdir, dele->path);
  1960.         mk_correct_path(pkdir);
  1961.         format = dele->format_str;
  1962.         found = TRUE;
  1963.       }
  1964.     }
  1965.     if (!found) {
  1966.       strcpy(pkdir, "TeX:pk/");
  1967.       format = fnt_root->pk_fmt;
  1968.     }
  1969.  
  1970.     my_sprintf(pkname, PK_NAME_SIZE, format, fntname, magnification, magnification5);
  1971.  
  1972.     if (call_mf(fntname, magnification, hconvresolution, vconvresolution,
  1973.         (long)fnt_root->driver_type, pkname, pkdir)) {    /* call metafont */
  1974.       fnt = search_font_location(fntname, magnification, magnification5,
  1975.                       fnt_root);
  1976.     }
  1977.   }
  1978. #endif /* AMIGA */
  1979.  
  1980.   if (fnt == NULL) {
  1981.     /* not found => try to substitute, find first matching magstep */
  1982.     fnt = mag_substitution(fntname, magnification, fnt_root);
  1983.   }
  1984.  
  1985. #if 0    /* das geh ich erst spaeter an... (hes) */
  1986.   if (fnt == NULL) {
  1987.     /* search dpi-list of defined flibs, pk's etc. for a possible subst */
  1988.     fnt = dpi_substitution(fntname, magnification, fnt_root);
  1989.   }
  1990. #endif
  1991.  
  1992.   if (fnt != NULL) {
  1993.     /* font found => set lru counter */
  1994.     setup_lru_font(fnt_root->font_list, fnt);
  1995.   }
  1996.   
  1997.   if (fnt_root->files_left <= 0) {
  1998.     /* close files */
  1999.     close_flibs(fnt_root);
  2000.   }
  2001.  
  2002.   return (fnt);
  2003. }
  2004.  
  2005.  
  2006. /*
  2007.  ************************************************************************
  2008.  *    where is the font?                        *
  2009.  ************************************************************************
  2010.  */
  2011.  
  2012. static struct Font *search_font_location(fntname, dpi, dpi5, fnt_root)
  2013.   char          *fntname;
  2014.   long          dpi, dpi5;
  2015.   struct FontMan  *fnt_root;
  2016. {
  2017.   /* search only for the location of the font.                */
  2018.   /* Returns NULL if the font cannot be found.                */
  2019.   /* return:                                */
  2020.   /*    font structure with fnt_name/fnt_status/where_is_font/resol.    */
  2021.  
  2022.   struct Font *fnt;
  2023.  
  2024.   /* Ist der Font einzeln definiert?                 --------------------*/
  2025.   fnt = is_font_in_font_list(fntname, dpi, dpi5, fnt_root->font_list, fnt_root);
  2026.  
  2027.   if (fnt == NULL) {
  2028.     /* Ist eine passende Library einzeln oder per ENV definiert? -------------------*/
  2029.     fnt = is_font_in_lib_list(fntname, dpi, dpi5, fnt_root);
  2030.  
  2031.     if (fnt == NULL) {
  2032.       /* Ist der Font in einem vordefinierten Base-DPI Verzeichnis? ----------------*/
  2033.       fnt = is_font_in_pred_pk_dirs(fntname, dpi, dpi5, fnt_root, (short)1);
  2034.  
  2035.       if (fnt == NULL) {
  2036.         /* Ist der Font in einem PK-Dir, definiert in der ENV Variable? ------------*/
  2037.         fnt = is_font_in_pk_dirs(fntname, dpi, dpi5, fnt_root);
  2038.  
  2039.         if (fnt == NULL) {
  2040.           /* Ist der Font in einem fuer eine bestimmte DPI ausgelegten Directory? --*/
  2041.           /* Diese Moeglichkeit ist mehr zum Fontsubstituieren gedacht,            */
  2042.           /* deshalb wird dies erst nach dem Durchsuchen der ENV Pfade gemacht.        */
  2043.           fnt = is_font_in_pred_pk_dirs(fntname, dpi, dpi5, fnt_root, (short)0);
  2044.  
  2045. #ifdef AMIGA
  2046.           if (fnt == NULL) {
  2047.             /* Ist der Font ueber das TeX:pk/fontvols File zu finden? --------------*/
  2048.             fnt = read_atex_file(fntname, dpi, dpi5, fnt_root);
  2049.           }
  2050. #endif
  2051.         }
  2052.       }
  2053.     }
  2054.   }
  2055.  
  2056.   return (fnt);
  2057. }
  2058.  
  2059.  
  2060. /*
  2061.  ************************************************************************
  2062.  *    is the font in the font list                    *
  2063.  ************************************************************************
  2064.  */
  2065.  
  2066. static struct Font *is_font_in_font_list(fntname, dpi, dpi5, fnt_list, fnt_root)
  2067.   char *fntname;
  2068.   long dpi, dpi5;
  2069.   struct FontLst *fnt_list;
  2070.   struct FontMan *fnt_root;
  2071. {
  2072.   /* easy function. Looks only in the list of the defined fonts    */
  2073.   /* ^^^^ naja (rbs)                        */
  2074.   /* this function doesn't define a NEW font!            */
  2075.   /* only changes the status of a font                */
  2076.  
  2077.   struct FontLst *lst;
  2078.   char pkname[PK_NAME_SIZE], full_name[PATH_SIZE+FLIB_NAME_SIZE];
  2079.   long size;
  2080.  
  2081.   lst = fnt_list;
  2082.   if (lst == NULL)
  2083.     return NULL;
  2084.  
  2085.   do {
  2086.     if (lst->font.common->resolution == dpi
  2087.     && stricmp(lst->font.common->fnt_group->fnt_name, fntname) == 0) {
  2088.       if (lst->font.common->fnt_status == FNT_FOUND
  2089.       || lst->font.common->fnt_status == FNT_DEFINED
  2090.       || lst->font.common->fnt_status == FNT_LOADED
  2091.       || lst->font.common->fnt_status == FNT_DEFINED_OLOADED
  2092.       || lst->font.common->fnt_status == FNT_OLD_LOADED) {
  2093.         return &(lst->font);
  2094.       }
  2095.       if (lst->font.common->fnt_status == FNT_PATH_DEFINED) {
  2096.         if (lst->font.common->where_is_font == WHERE_LIB) {
  2097.           Fatal(10,MSG_PREDEF_FONT_IN_LIB);
  2098.       /* NOT REACHED */
  2099.     }
  2100.         my_sprintf(pkname, PK_NAME_SIZE,
  2101.         lst->font.common->location.pk_directory->format_str /*fnt_root->pk_fmt*/,
  2102.         fntname, dpi, dpi5);
  2103.         strcpy(full_name, lst->font.common->location.pk_directory->path);
  2104.         mk_correct_path(full_name);
  2105.         strcat(full_name,pkname);
  2106.         size = test_pk_file(full_name);
  2107.         if (size != 0L) {
  2108.           lst->font.common->fnt_status = FNT_FOUND;
  2109.           lst->font.common->fnt_length = size;
  2110.           return &(lst->font);
  2111.     }
  2112.     /* (size == 0L) */
  2113.         lst->font.common->fnt_status = FNT_NOT_EXISTS;
  2114.         Logging(MSG_PREDEF_FONT_NOT_FOUND,fntname,dpi);
  2115.       }
  2116.     }
  2117.   } while( (lst = lst->next_font) != NULL );
  2118.  
  2119.   return NULL;
  2120. }
  2121.  
  2122.  
  2123. /*
  2124.  ************************************************************************
  2125.  *    is the font in a fontlibrary                    *
  2126.  ************************************************************************
  2127.  */
  2128.  
  2129. static struct Font *is_font_in_lib_list(fntname, dpi, dpi5, fnt_root)
  2130.   char *fntname;
  2131.   long dpi, dpi5;
  2132.   struct FontMan *fnt_root;
  2133. {
  2134.   /* this function looks in all directories for the fontlibraries    */
  2135.   /* then it looks if the fontlib in this directory is already opened    */
  2136.   /* if this is successful, then define a new font and a new fontlibrary */
  2137.  
  2138.   struct Font *font;
  2139.  
  2140.   /**** search in the list of predefined libs ****/
  2141.   font = search_in_defined_libs(fntname, dpi, dpi5, fnt_root);
  2142.  
  2143.   if (font == NULL) {
  2144.     /**** font not in a predefined lib => search in the rest of the pathes ****/
  2145.     font = search_in_rest_pathes(fntname, dpi, dpi5, fnt_root);
  2146.   }
  2147.  
  2148.   return (font);
  2149. }
  2150.  
  2151.  
  2152. /*
  2153.  ************************************************************************
  2154.  *    is the font in a pk-directory (not predefined)            *
  2155.  ************************************************************************
  2156.  */
  2157.  
  2158. static struct Font *is_font_in_pk_dirs(fntname, dpi, dpi5, fnt_root)
  2159.   char *fntname;
  2160.   long dpi, dpi5;
  2161.   struct FontMan *fnt_root;
  2162. {
  2163.   struct Font    *font;
  2164.   struct SeaEle    *ele;
  2165.  
  2166.   ele = fnt_root->s_list_pkdirs.first_ele;
  2167.   font = NULL;
  2168.  
  2169.   while (font == NULL && ele != NULL) {
  2170.     font = define_test_pk_font(ele->path, fntname, dpi, dpi5,
  2171.                 fnt_root->pk_fmt, fnt_root);
  2172.     ele = ele->next_ele;
  2173.   }
  2174.   return (font);
  2175. }
  2176.  
  2177.  
  2178. /*
  2179.  ************************************************************************
  2180.  *    is the font in a pk-directory (defined in *.fnt)        *
  2181.  ************************************************************************
  2182.  */
  2183.  
  2184. static struct Font *is_font_in_pred_pk_dirs(fntname, dpi, dpi5, fnt_root, base)
  2185.   char *fntname;
  2186.   long dpi, dpi5;
  2187.   struct FontMan *fnt_root;
  2188.   short base;    /* search in base pk-dirs or in normal pk-dirs? */
  2189. {
  2190.   struct Font        *font;
  2191.   struct SeaEleDpi    *ele;
  2192.  
  2193.   if (base) {
  2194.     ele = fnt_root->s_list_base_pkdpi.first_ele;
  2195.   }
  2196.   else {
  2197.     ele = fnt_root->s_list_pkdpi.first_ele;
  2198.   }
  2199.   font = NULL;
  2200.  
  2201.   while (font == NULL && ele != NULL) {
  2202.     /* printf("base: %ld, ele->dpi: %ld, dpi: %ld, hc: %ld\n", base, ele->dpi, dpi, hconvresolution); */
  2203.     /* stimmt die Base-Dpi? */
  2204.     if ((base && ele->hdpi == hconvresolution && ele->vdpi == vconvresolution) ||
  2205.         (!base && ele->hdpi == dpi && ele->vdpi == compute_vert(dpi))) {
  2206.       font = define_test_pk_font(ele->path, fntname, dpi, dpi5,
  2207.                 ele->format_str, fnt_root);
  2208.       if (font != NULL) {
  2209.         font->common->where_is_font = WHERE_PKDIR;
  2210.       }
  2211.     }
  2212.     ele = ele->next_ele;
  2213.   }
  2214.   return (font);
  2215. }
  2216.  
  2217. /*
  2218.  ************************************************************************
  2219.  *    test a pk-file and define the font if the pk-file exists    *
  2220.  ************************************************************************
  2221.  */
  2222.  
  2223. static struct Font *define_test_pk_font(path, fntname, dpi, dpi5, format_str, fnt_root)
  2224.   char *path;
  2225.   char *fntname;
  2226.   long dpi, dpi5;
  2227.   char *format_str;
  2228.   struct FontMan *fnt_root;
  2229. {
  2230.   char whole_name[PATH_SIZE+FONT_NAME_SIZE];
  2231.   char pkname[PK_NAME_SIZE];
  2232.   struct Font     *font;
  2233.   long size;            /* size in bytes of pk-file */
  2234.   BPTR lck;
  2235.  
  2236.   if (format_str == NULL) Fatal(20, MSG_INTERNAL_ERROR_FMT_STR);
  2237.  
  2238.   my_sprintf(pkname, PK_NAME_SIZE, format_str, fntname, dpi, dpi5);
  2239.  
  2240.   strcpy(whole_name,path);
  2241.   mk_correct_path(whole_name);
  2242.   strcat(whole_name,pkname);
  2243.  
  2244.   lck = Lock(whole_name, ACCESS_READ);    /* read access ? */
  2245.   if (!lck) return NULL;
  2246.   
  2247.   UnLock(lck); 
  2248.   lck = NULL;
  2249.  
  2250.  
  2251.   /* font is found, now define the font-structure */
  2252.   size = test_pk_file(whole_name);
  2253.   if (size == 0L)
  2254.     return (struct Font *)NULL;
  2255.  
  2256.  
  2257.   font = make_new_fontdesc(fntname, fnt_root);
  2258.  
  2259.   font->fnt_number            = -1L;
  2260.   font->common->fnt_status    = FNT_FOUND;
  2261.   font->common->where_is_font = WHERE_PK;
  2262.   font->common->where_in_lib  = 0L;
  2263.   font->common->fnt_length    = size;
  2264.   font->common->resolution    = dpi;
  2265.   font->common->resolution5   = dpi5;
  2266.   font->orig_dpi          = dpi;
  2267.  
  2268.   font->common->location.pk_directory = 
  2269.     (struct PK_Dir *)xmalloc((size_t)sizeof(struct PK_Dir));
  2270.   strcpy(font->common->location.pk_directory->path, path);
  2271.   font->common->location.pk_directory->format_str = format_str;
  2272.  
  2273.   return font;
  2274. }
  2275.  
  2276.  
  2277. /*
  2278.  ************************************************************************
  2279.  *    search a font in the list of fontlibraries            *
  2280.  ************************************************************************
  2281.  */
  2282.  
  2283. static struct Font *search_in_defined_libs(fntname, dpi, dpi5, fnt_root)
  2284.   char *fntname;
  2285.   long dpi, dpi5;
  2286.   struct FontMan *fnt_root;
  2287. {
  2288.   int ret;
  2289.   struct LibLst  *liblist;
  2290.   FILE         *file;
  2291.   struct Font     *font;
  2292.   char libname[FLIB_NAME_SIZE];
  2293.   char full_name[PATH_SIZE+FLIB_NAME_SIZE];
  2294.   int version;
  2295.  
  2296.   /**** search in the list of predefined libs ****/
  2297.  
  2298.   for(liblist = fnt_root->flib_list; liblist != NULL;
  2299.                     liblist = liblist->next_lib) {
  2300.     if (liblist->flib.resolution == dpi) {
  2301.       /* here is already a lib defined */
  2302.       if (liblist->flib.lib_status == LIB_PATH_DEFINED) {
  2303.         /* open the lib and read the directory */
  2304.     my_sprintf(libname, FLIB_NAME_SIZE, liblist->flib.format_str, fntname, dpi, dpi5);
  2305.     strcpy(full_name,liblist->flib.path);
  2306.     mk_correct_path(full_name);
  2307.     strcat(full_name,libname);
  2308.         file = open_flib(full_name, B_OPEN_READ, &version, (short)0);
  2309.         liblist->flib.directory.version = version;
  2310.         if (file != NULL) {
  2311.           /* here is really a flib */
  2312.           ret = read_dir(file,&(liblist->flib.directory));
  2313.           if (ret) {        /* all ok */
  2314.             fnt_root->files_left--;
  2315.             liblist->flib.lib_status = LIB_OPEND;
  2316.             liblist->flib.file_ptr   = file;
  2317.             setup_lru_flib(fnt_root->flib_list,&(liblist->flib));
  2318.           }
  2319.           else {        /* corrupted file ? */
  2320.             fclose(file);
  2321.             liblist->flib.lib_status = LIB_NOT_EXISTS;
  2322.           }
  2323.         }
  2324.         else {            /* can't open the file */
  2325.           liblist->flib.lib_status = LIB_NOT_EXISTS;
  2326.         }
  2327.       }
  2328.       if (liblist->flib.lib_status == LIB_OPEND || 
  2329.         liblist->flib.lib_status == LIB_READ_CLOSED) {
  2330.         /* the directoy of the lib is already in the ram */
  2331.         font = find_font_in_flib(fntname, dpi, dpi5, &(liblist->flib), fnt_root);
  2332.         if (font != NULL)
  2333.       return font;        /* ======>>>>> found it */
  2334.       }
  2335.     }
  2336.   }
  2337.  
  2338.   return (struct Font *)NULL;
  2339. }
  2340.  
  2341. /*
  2342.  ************************************************************************
  2343.  *    search in this places, where no lib is found            *
  2344.  ************************************************************************
  2345.  */
  2346.  
  2347. static struct Font *search_in_rest_pathes(fntname, dpi, dpi5, fnt_root)
  2348.   char *fntname;
  2349.   long dpi, dpi5;
  2350.   struct FontMan *fnt_root;
  2351. {
  2352.   int ret;
  2353.   char *path, libname[FLIB_NAME_SIZE];
  2354.   char full_name[PATH_SIZE+FLIB_NAME_SIZE];
  2355.   struct LibLst  *liblist;
  2356.   FILE         *file;
  2357.   struct Font     *font;
  2358.   struct SeaEle     *ele;
  2359.   int version;
  2360.  
  2361.   /**** font not in a predefined lib => search in the rest of the pathes ****/
  2362.  
  2363.   my_sprintf(libname, FLIB_NAME_SIZE, fnt_root->flib_fmt, fntname, dpi, dpi5);
  2364.   ele = fnt_root->s_list_flib.first_ele;
  2365.  
  2366.   while (ele != NULL) {
  2367.     path = ele->path;
  2368.     ele = ele->next_ele;
  2369.  
  2370.     /* is this flib (whith this path) already defined?? */
  2371.     for (liblist = fnt_root->flib_list;
  2372.      liblist != NULL && (liblist->flib.resolution != dpi ||
  2373.         (stricmp(liblist->flib.path,path) != 0));
  2374.      liblist = liblist->next_lib);
  2375.  
  2376.     if (liblist == NULL) {        /* no, nix defined */
  2377.       /* this path is a new path */
  2378.       liblist = (struct LibLst *)xmalloc((size_t)sizeof(struct LibLst));
  2379.       strcpy(full_name,path);
  2380.       mk_correct_path(full_name);
  2381.       strcat(full_name,libname);
  2382.       file = open_flib(full_name, B_OPEN_READ, &version, (short)0);
  2383.       liblist->flib.directory.version = version;
  2384.  
  2385.       /* and now, sort the flib into the flib-list */
  2386.       liblist->next_lib = fnt_root->flib_list;
  2387.       fnt_root->flib_list = liblist;
  2388.  
  2389.       liblist->flib.resolution  = dpi;
  2390.       liblist->flib.lru_count   = 0;
  2391.       liblist->flib.format_str  = fnt_root->flib_fmt;
  2392.       strcpy(liblist->flib.path, path);
  2393.  
  2394.       if (file != NULL) {
  2395.         /* here is really a flib */
  2396.         ret = read_dir(file,&(liblist->flib.directory));
  2397.         if (ret) {
  2398.           /* define a new fontlibrary */
  2399.           fnt_root->files_left--;
  2400.           liblist->flib.file_ptr    = file;
  2401.           liblist->flib.lib_status  = LIB_OPEND;
  2402.           setup_lru_flib(fnt_root->flib_list,&(liblist->flib));
  2403.  
  2404.           font = find_font_in_flib(fntname, dpi, dpi5, &(liblist->flib), fnt_root);
  2405.           if (font != NULL)
  2406.         return font;
  2407.         }
  2408.         else {
  2409.           fclose(file);
  2410.           liblist->flib.file_ptr    = NULL;
  2411.           liblist->flib.lib_status  = LIB_NOT_EXISTS;
  2412.         }
  2413.       }
  2414.       else {    /* can't open flib */
  2415.         liblist->flib.file_ptr    = NULL;
  2416.         liblist->flib.lib_status  = LIB_NOT_EXISTS;
  2417.       }
  2418.     }
  2419.   }
  2420.  
  2421.   return (struct Font *)NULL;
  2422. }
  2423.  
  2424.  
  2425. /*
  2426.  ************************************************************************
  2427.  *    search-define a font in a fontlibrary                *
  2428.  ************************************************************************
  2429.  */
  2430.  
  2431. static struct Font *find_font_in_flib(fntname, dpi, dpi5, flib, fnt_root)
  2432.   char *fntname;
  2433.   long dpi, dpi5;
  2434.   struct Fnt_Lib *flib;
  2435.   struct FontMan *fnt_root;
  2436. {
  2437.   /* this function search in a flib a font and if it is found, the font    */
  2438.   /* would be defined and in the font-list inserted.            */
  2439.  
  2440.   char name[FONT_NAME_SIZE];
  2441.   struct dirlist *dirlist;
  2442.   struct Font     *font;
  2443.  
  2444.   my_sprintf(name, FONT_NAME_SIZE, fnt_root->flib_fnt_fmt, fntname, dpi, dpi5);
  2445.  
  2446.   dirlist = findmod(&(flib->directory),name);
  2447.  
  2448.   if (dirlist == NULL)
  2449.     return (struct Font *)NULL;
  2450.  
  2451.   /* font found, now define the font-structure */
  2452.  
  2453.   font = make_new_fontdesc(fntname, fnt_root);
  2454.  
  2455.   font->fnt_number                   = -1L;
  2456.   font->common->fnt_status           = FNT_FOUND;
  2457.   font->common->where_is_font        = WHERE_LIB;
  2458.   font->common->where_in_lib         = dirlist->dirent.where;
  2459.   font->common->fnt_length           = dirlist->dirent.size;
  2460.   font->common->resolution           = dpi;
  2461.   font->common->resolution5          = dpi5;
  2462.   font->orig_dpi             = dpi;
  2463.   font->common->location.fnt_library = flib;
  2464.  
  2465.   return (font);
  2466. }
  2467.  
  2468.  
  2469. /*
  2470.  * writes font definitions into log (!) file    (by AbortRun if Stats)
  2471.  */
  2472. void write_font_def_file(void)
  2473. {
  2474.  struct LibLst      *llist;
  2475.  struct FontLst     *flist;
  2476.  struct SeaEle        *ele;
  2477.  struct SeaEleDpi    *dele;
  2478.  long            i, j;
  2479.  char            *last_format;
  2480.  
  2481.  if (FontRoot != NULL)
  2482.   {
  2483.    j=0L;
  2484.    for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font) {
  2485.      for (i=0; i<NPXLCHARS; i++) {
  2486.        if (flist->font.common->ch[i].unpacked != NULL) {
  2487.      j++;
  2488.        }
  2489.      }
  2490.    }
  2491.  
  2492.    LoggingStr("");
  2493.    Logging(MSG_BYTES_USED_FOR_CHARS,FontRoot->unpacked_mem,j);
  2494.  
  2495.    LoggingStr("");
  2496.    Logging(MSG_SEARCHPATH_LIB_ENTRIES_NR,FontRoot->s_list_flib.number);
  2497.    strcpy(m_string,"\t");
  2498.    for (ele = FontRoot->s_list_flib.first_ele; ele != NULL; ele = ele->next_ele) {
  2499.      strcat(m_string,ele->path);
  2500.      if (ele->next_ele != NULL) {
  2501.        strcat(m_string,", ");
  2502.      }
  2503.    }
  2504.    LoggingStr(m_string);
  2505.  
  2506.    LoggingStr("");
  2507.    Logging(MSG_SEARCHPATH_PK_ENTRIES_NR,FontRoot->s_list_pkdirs.number);
  2508.    strcpy(m_string,"\t");
  2509.    for (ele = FontRoot->s_list_pkdirs.first_ele; ele != NULL; ele = ele->next_ele) {
  2510.      strcat(m_string,ele->path);
  2511.      if (ele->next_ele != NULL) {
  2512.        strcat(m_string,", ");
  2513.      }
  2514.    }
  2515.    LoggingStr(m_string);
  2516.  
  2517.  
  2518.  
  2519.    last_format = FontRoot->flib_fmt;
  2520.  
  2521.    LoggingStr("");
  2522.    LoggingStr("");
  2523.    Logging(MSG_LOG_FONTDEF_START);
  2524.    for (llist=FontRoot->flib_list; llist != NULL; llist = llist->next_lib)
  2525.     {
  2526.      if (stricmp(llist->flib.format_str, last_format) != 0) {
  2527.        last_format = llist->flib.format_str;
  2528.        LoggingStr("flib_str\t%s", last_format);
  2529.      }
  2530.      switch (llist->flib.lib_status)
  2531.       {
  2532.        case LIB_READ_CLOSED:
  2533.        case LIB_OPEND:
  2534.         Logging(MSG_LOG_FONTDEF_LIB_FOUND,
  2535.             llist->flib.resolution,
  2536.             llist->flib.path);
  2537.         break;
  2538.        case LIB_PATH_DEFINED:
  2539.         Logging(MSG_LOG_FONTDEF_LIB_DEF,
  2540.             llist->flib.resolution,
  2541.             llist->flib.path);
  2542.         break;
  2543.        case LIB_NOT_EXISTS:
  2544.         Logging(MSG_LOG_FONTDEF_LIB_NOT_FOUND,
  2545.             llist->flib.resolution,
  2546.             llist->flib.path);
  2547.         break;
  2548.        default:
  2549.         break;
  2550.       }
  2551.     }
  2552.    if (stricmp(FontRoot->flib_fmt, last_format) != 0) {
  2553.      LoggingStr("flib_str\t%s", FontRoot->flib_fmt);
  2554.    }
  2555.  
  2556.    for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font) {
  2557.      flist->font.common->copied = (char)FALSE;
  2558.    }
  2559.  
  2560.  
  2561.    last_format = FontRoot->pk_fmt;
  2562.  
  2563.    for (flist=FontRoot->font_list; flist != NULL; flist = flist->next_font)
  2564.     {
  2565.      if (flist->font.common->copied == (char)FALSE)
  2566.       {
  2567.        flist->font.common->copied = (char)TRUE;
  2568.        if (flist->font.common->where_is_font != WHERE_LIB)
  2569.         {
  2570.          if (flist->font.common->location.pk_directory != NULL)
  2571.           {
  2572.            if (stricmp(flist->font.common->location.pk_directory->format_str,
  2573.             last_format) != 0) {
  2574.              last_format = flist->font.common->location.pk_directory->format_str;
  2575.              LoggingStr("pk_str\t\t%s", last_format);
  2576.            }
  2577.           }
  2578.          switch (flist->font.common->fnt_status)
  2579.           {
  2580.            case FNT_FOUND:
  2581.            case FNT_LOADED:
  2582.            case FNT_OLD_LOADED:
  2583.              Logging(MSG_LOG_FONTDEF_PK_FOUND,
  2584.                      flist->font.common->fnt_group->fnt_name,
  2585.                      flist->font.common->resolution,
  2586.                      flist->font.common->location.pk_directory->path);
  2587.              break;
  2588.            case FNT_PATH_DEFINED:
  2589.              Logging(MSG_LOG_FONTDEF_PK_PREDEF,
  2590.                      flist->font.common->fnt_group->fnt_name,
  2591.                      flist->font.common->resolution,
  2592.                      flist->font.common->location.pk_directory->path);
  2593.              break;
  2594.            case FNT_NOT_EXISTS:
  2595.             {
  2596.              struct PK_Dir *dir;
  2597.              
  2598.              dir = flist->font.common->location.pk_directory;
  2599.              if (dir != NULL)
  2600.               {
  2601.                Logging(MSG_LOG_FONTDEF_PK_PREDEF_NOT_FOUND,
  2602.                      flist->font.common->fnt_group->fnt_name,
  2603.                      flist->font.common->resolution,
  2604.                      flist->font.common->location.pk_directory->path);
  2605.               }
  2606.              break;
  2607.             }
  2608.            default:
  2609.              break;
  2610.           }
  2611.         }
  2612.       }
  2613.     }
  2614.    for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font)
  2615.     {
  2616.      flist->font.common->copied = (char)FALSE;
  2617.     }
  2618.    if (stricmp(FontRoot->pk_fmt, last_format) != 0) {
  2619.      LoggingStr("pk_str\t\t%s", FontRoot->pk_fmt);
  2620.    }
  2621.  
  2622.  
  2623.    /**** logge die base-pk-directories zu einer bestimmten Grundaufloesung***/
  2624.  
  2625.    last_format = FontRoot->basepkdir_fmt;
  2626.  
  2627.    if (FontRoot->s_list_base_pkdpi.number > 0) {
  2628.      LoggingStr("");
  2629.      Logging(MSG_LOG_FONTDEF_NR_BASE_PK_DIRS_PREDEF, FontRoot->s_list_base_pkdpi.number);
  2630.      for (dele = FontRoot->s_list_base_pkdpi.first_ele; dele != NULL; dele = dele->next_ele) {
  2631.        if (stricmp(dele->format_str, last_format) != 0) {
  2632.          last_format = dele->format_str;
  2633.          LoggingStr("basepkdir_str\t%s", last_format);
  2634.        }
  2635.        LoggingStr("basepkdir\t%ld\t%ld\t%s", dele->hdpi, dele->vdpi, dele->path);
  2636.      }
  2637.      /** das wird hier nicht benoetigt, da ja keine Eintraege dynamisch hinzukommen!
  2638.      if (stricmp(FontRoot->basepkdir_fmt, last_format) != 0) {
  2639.        LoggingStr("basepkdir_str\t%s", FontRoot->basepkdir_fmt);
  2640.      }
  2641.      **/
  2642.    }
  2643.  
  2644.  
  2645.    /**** logge die pk-directories zu einer bestimmten Aufloesung***/
  2646.  
  2647.    last_format = FontRoot->pkdir_fmt;
  2648.  
  2649.    if (FontRoot->s_list_pkdpi.number > 0) {
  2650.      LoggingStr("");
  2651.      Logging(MSG_LOG_FONTDEF_NO_PK_DIRS_PREDEF, FontRoot->s_list_pkdpi.number);
  2652.      for (dele = FontRoot->s_list_pkdpi.first_ele; dele != NULL; dele = dele->next_ele) {
  2653.        if (stricmp(dele->format_str, last_format) != 0) {
  2654.          last_format = dele->format_str;
  2655.          LoggingStr("pkdir_str\t%s", last_format);
  2656.        }
  2657.        LoggingStr("pkdir\t\t%ld\t%ld\t%s", dele->hdpi, dele->vdpi, dele->path);
  2658.      }
  2659.      /** das wird hier nicht benoetigt, da ja keine Eintraege dynamisch hinzukommen!
  2660.      if (stricmp(FontRoot->pkdir_fmt, last_format) != 0) {
  2661.        LoggingStr("pkdir_str\t%s", FontRoot->pkdir_fmt);
  2662.      }
  2663.      **/
  2664.    }
  2665.  
  2666.    Logging(MSG_LOG_FONTDEF_END);
  2667.    LoggingStr("");
  2668.   }
  2669. }
  2670.  
  2671. /*
  2672.  ************************************************************************
  2673.  *    read font definition file                    *
  2674.  ************************************************************************
  2675.  */
  2676. static void read_font_def_file(fnt_root, file_name)
  2677.   struct FontMan *fnt_root;
  2678.   char *file_name;
  2679. {
  2680.   FILE *f;
  2681. #ifndef AMIGA
  2682.   char def_file[PATH_SIZE], *d;
  2683. #endif
  2684.  
  2685. #ifdef AMIGA
  2686.   f = OpenConfigFile(file_name, MODE_READ);
  2687. #else
  2688.   d = getenv(ENV_DEFAULT_PATH);
  2689.   if (d == NULL) {        /** no environment var defined **/
  2690.     strcpy(def_file,DEFAULT_PATH);
  2691.   }
  2692.   else {            /** take the defined path **/
  2693.     strcpy(def_file,d);
  2694.   }
  2695.   mk_correct_path(def_file);
  2696.   strcat(def_file,file_name);
  2697.   f = fopen(def_file,"r");
  2698. #endif
  2699.  
  2700.   if (f == NULL)
  2701.    {
  2702. #ifdef ATARI
  2703.     strcpy(def_file, file_name);
  2704.     if (shel_find(def_file)==0)
  2705.      {
  2706.       char *shenv;
  2707.  
  2708.       Logging("*** Can't open font/flib configuration file \"%s\"!",file_name);
  2709.       Logging("    Font/flib configuration file has been searched in following pathes:");
  2710.       if (d != NULL)
  2711.        {
  2712.         Logging("     - via environment variable \"%s\" ('%s')",
  2713.             ENV_DEFAULT_PATH, d);
  2714.        }
  2715.       else
  2716.        {
  2717.         Logging("     - via default path ('%s')",
  2718.             DEFAULT_PATH);
  2719.        }
  2720.       shel_envrn(&shenv,"PATH=");
  2721.       strcpy(def_file, (shenv==NULL) ? "" : shenv);
  2722.       Logging("     - via system environment variable \"PATH=\" ('%s')", def_file);
  2723.       return;
  2724.      }
  2725.     f = fopen(def_file,"r");
  2726.     if (f == NULL)
  2727.      {
  2728.       Logging("*** Can't open font/flib configuration file \"%s\"!",def_file);
  2729.       return;
  2730.      }
  2731. #else
  2732.     Logging(MSG_CANT_OPEN_FONT_CONFIG,file_name);
  2733.     return;
  2734. #endif
  2735.    }
  2736.   Logging(MSG_LOAD_FONT_CONFIG,file_name);
  2737. #ifdef OLDARGS
  2738.   { char line[256], *s;
  2739.    line[255] = '\0';
  2740.    while(fgets(line,255,f) != NULL) {
  2741.     s = strrchr(line,'\n');
  2742.     if (s != NULL) *s = '\0';
  2743.  
  2744.     s = strchr(line,';');
  2745.     if (s != NULL) *s = '\0';        /* skip comment */
  2746.  
  2747.     parse_line(fnt_root,line);
  2748.    }
  2749.   }
  2750. #else
  2751.   globarg_fnt_root = fnt_root;
  2752.   parse_file(font_config,f, 0); /* ignore unknown keywords */
  2753. #endif
  2754.  
  2755.   fclose(f);
  2756. }
  2757.  
  2758.  
  2759. #ifdef OLDARGS
  2760. /*
  2761.  ************************************************************************
  2762.  *    read a line of a font-def-file                    *
  2763.  ************************************************************************
  2764.  */
  2765.  
  2766. static void parse_line(fnt_root,line)
  2767.   struct FontMan *fnt_root;
  2768.   char *line;
  2769. {
  2770.   char key[20], arg1[100], arg2[100], arg3[100];
  2771.   long number_dpi;
  2772.   short mark;
  2773.   
  2774.   for (; (*line == ' ' || *line == '\t') && *line != '\0'; line++);
  2775.   if (*line == '\0') {        /* empty line */
  2776.     return;
  2777.   }
  2778.  
  2779. #ifndef ATARI
  2780.   if (sscanf(line,"%19s %99s %99s %99s",key,arg1,arg2,arg3) < 2) {
  2781.     Warning(MSG_CANT_PARSE_FONT_CONFIG_LINE,line);
  2782.   }
  2783. #else
  2784.   if (sscanf(line,"%20s %100s",key,arg1) < 2) {
  2785.     Warning("Can't parse line \"%s\"!",line);
  2786.   }
  2787. #endif
  2788.  
  2789.  /***      FLIBENV    *******************************************************/
  2790.  if (stricmp("flibenv",key) == 0) {
  2791.    if (*arg1 == '\0') {
  2792.      Warning(MSG_TOO_FEW_ARGS, "flibenv");
  2793.    }
  2794.    else {
  2795.      conc_dirs(line, &(fnt_root->s_list_flib));
  2796.    }
  2797.    return;
  2798.  }
  2799.  
  2800.  /***    PKENV     *******************************************************/
  2801.  if (stricmp("pkenv",key) == 0) {
  2802.    if (*arg1 == '\0') {
  2803.      Warning(MSG_TOO_FEW_ARGS, "pkenv");
  2804.    }
  2805.    else {
  2806.      conc_dirs(line, &(fnt_root->s_list_pkdirs));
  2807.    }
  2808.    return;
  2809.  }
  2810.  
  2811.  /***    FLIB_STR  *******************************************************/
  2812.  if (stricmp("flib_str",key) == 0) {
  2813.         if (*arg1 == '\0') {
  2814.           Warning(MSG_TOO_FEW_ARGS, "flib_str");
  2815.         }
  2816.         else {
  2817.           if ((fnt_root->flib_fmt = strdup(arg1)) == NULL) {
  2818.             Fatal(10, MSG_NO_MEM);
  2819.           }
  2820.         }
  2821.    return;
  2822.   }
  2823.  
  2824.  /***    PK_STR    *******************************************************/
  2825.  if (stricmp("pk_str",key) == 0) {
  2826.           if (*arg1 == '\0') {
  2827.             Warning(MSG_TOO_FEW_ARGS, "pk_str");
  2828.           }
  2829.           else {
  2830.             if ((fnt_root->pk_fmt = strdup(arg1)) == NULL) {
  2831.               Fatal(10, MSG_NO_MEM);
  2832.             }
  2833.           }
  2834.     return;
  2835.   }
  2836.  
  2837.  /*** BASEPKDIR_STR   *******************************************************/
  2838.  if (stricmp("basepkdir_str",key) == 0) {
  2839.           if (*arg1 == '\0') {
  2840.             Warning(MSG_TOO_FEW_ARGS, "basepkdir_str");
  2841.           }
  2842.           else {
  2843.             if ((fnt_root->basepkdir_fmt = strdup(arg1)) == NULL) {
  2844.               Fatal(10, MSG_NO_MEM);
  2845.             }
  2846.           }
  2847.     return;
  2848.   }
  2849.  
  2850.  /***    PKDIR_STR   *******************************************************/
  2851.  if (stricmp("pkdir_str",key) == 0) {
  2852.           if (*arg1 == '\0') {
  2853.             Warning(MSG_TOO_FEW_ARGS, "pkdir_str");
  2854.           }
  2855.           else {
  2856.             if ((fnt_root->pkdir_fmt = strdup(arg1)) == NULL) {
  2857.               Fatal(10, MSG_NO_MEM);
  2858.             }
  2859.           }
  2860.     return;
  2861.   }
  2862.  
  2863.  /***    FLIB_FNT_STR  *******************************************************/
  2864.  if (stricmp("flib_fnt_str",key) == 0) {
  2865.           if (*arg1 == '\0') {
  2866.             Warning(MSG_TOO_FEW_ARGS, "flib_fnt_str");
  2867.           }
  2868.           else {
  2869.             if ((fnt_root->flib_fnt_fmt = strdup(arg1)) == NULL) {
  2870.               Fatal(10, MSG_NO_MEM);
  2871.             }
  2872.           }
  2873.     return;
  2874.   }
  2875.  
  2876. #ifdef ATARI
  2877.   if (sscanf(line,"%20s %100s %100s",key,arg1,arg2) < 3) {
  2878.     Warning("Can't parse line \"%s\"!",line);
  2879.   }
  2880. #endif
  2881.  
  2882.  /***    FLIB    *******************************************************/
  2883.  if (stricmp("flib",key) == 0) {
  2884.     if (*arg2 == '\0' || *arg1 == '\0') {
  2885.         Warning(MSG_TOO_FEW_ARGS, "flib");
  2886.       }
  2887.       else {
  2888.     long dpi;
  2889.     sscanf(arg1,"%ld",&dpi);
  2890.         define_flib(fnt_root,dpi,arg2);
  2891.       }
  2892.     return;
  2893.   }
  2894.  
  2895.  /*** PKDIR -- BASEPKDIR *********************************************/
  2896.   mark = 0;
  2897.   if (stricmp("pkdir",key) == 0) {
  2898.     mark = 1;
  2899.   }
  2900.   if (stricmp("basepkdir",key) == 0) {
  2901.     mark = 2;
  2902.   }
  2903.  
  2904.   if (mark != 0) {
  2905.     struct SeaEleDpi *ele, *new;
  2906.     char *larg;
  2907.  
  2908.     if (*arg2 == '\0' || *arg1 == '\0') {
  2909.       Warning(MSG_TOO_FEW_ARGS, (mark == 1) ? "pkdir" : "basepkdir");
  2910.       return;
  2911.     }
  2912.  
  2913.     /* arg1 == dpi, arg2 == vdpi, arg2/3 (larg) == path */
  2914.     new = xmalloc(sizeof(struct SeaEleDpi));
  2915.     if (sscanf(arg1, "%ld",&(new->hdpi)) != 1) {
  2916.           xfree(new);
  2917.           Warning(MSG_NOT_A_VALID_INT,arg1);
  2918.           return;    /* ** weg ** */
  2919.     }
  2920.     if (isdigit(*arg2)) {
  2921.       if (sscanf(arg2, "%ld",&(new->vdpi)) != 1) {
  2922.             xfree(new);
  2923.             Warning(MSG_NOT_A_VALID_INT,arg1);
  2924.             return;    /* ** weg ** */
  2925.       }
  2926.       larg = &(arg3[0]);
  2927.       if (*larg == '\0') {
  2928.             xfree(new);
  2929.         Warning(MSG_TOO_FEW_ARGS, (mark == 1) ? "pkdir" : "basepkdir");
  2930.         return;    /* ** weg ** */
  2931.       }
  2932.     }
  2933.     else {
  2934.       new->vdpi = new->hdpi;
  2935.       larg = &(arg2[0]);
  2936.     }
  2937.     new->path = strdup(larg);
  2938.     if (new->path == NULL) {
  2939.       xfree(new);
  2940.       return;    /* ** weg ** */
  2941.     }
  2942.     if (mark == 1) {
  2943.         new->format_str = strdup(fnt_root->pkdir_fmt);
  2944.     }
  2945.     else {
  2946.         new->format_str = strdup(fnt_root->basepkdir_fmt);
  2947.     }
  2948.         if (new->format_str == NULL) {
  2949.           xfree(new->path);
  2950.           xfree(new);
  2951.           return;    /* ** weg ** */
  2952.         }
  2953.         new->next_ele = NULL;
  2954.         if (mark == 1) {
  2955.           fnt_root->s_list_pkdpi.number++;
  2956.           ele = fnt_root->s_list_pkdpi.first_ele;
  2957.           if (ele == NULL) {
  2958.             fnt_root->s_list_pkdpi.first_ele = new;
  2959.           }
  2960.           else {
  2961.             for (; ele->next_ele != NULL; ele = ele->next_ele);
  2962.             ele->next_ele = new;
  2963.           }
  2964.         }
  2965.         else {
  2966.           fnt_root->s_list_base_pkdpi.number++;
  2967.           ele = fnt_root->s_list_base_pkdpi.first_ele;
  2968.           if (ele == NULL) {
  2969.             fnt_root->s_list_base_pkdpi.first_ele = new;
  2970.           }
  2971.           else {
  2972.             for (; ele->next_ele != NULL; ele = ele->next_ele);
  2973.             ele->next_ele = new;
  2974.           }
  2975.         }
  2976.     return;
  2977.   }
  2978.  
  2979. #ifdef ATARI
  2980.   if (sscanf(line,"%20s %100s %100s %100s",key,arg1,arg2,arg3) < 4) {
  2981.     Warning("Can't parse line \"%s\"!",line);
  2982.   }
  2983. #endif
  2984.  
  2985.   /***    FONT   *******************************************************/
  2986.   if (stricmp("font",key) == 0) {
  2987.     if (*arg3 == '\0' || *arg2 == '\0' || *arg1 == '\0') {
  2988.       Warning(MSG_TOO_FEW_ARGS, "font");
  2989.     }
  2990.     else {
  2991.       if (sscanf(arg2,"%ld",&number_dpi) == 1) {
  2992.         define_font(fnt_root,number_dpi,arg3,arg1);
  2993.       }
  2994.       else {
  2995.         Warning(MSG_CANT_READ_DPI_FONT_COMM);
  2996.       }
  2997.     }
  2998.     return;
  2999.   }
  3000.  Warning(MSG_UNKNOWN_KEYWORD_IN_CONFIG,key);
  3001. }
  3002.  
  3003. #else /* OLDARGS */
  3004.  
  3005. /*    fkw_conc_dirs
  3006.  *
  3007.  * Called when a list of directories needs to be parsed.
  3008.  */
  3009. static void __stdargs fkw_conc_dirs
  3010.     (struct string_parse *p, char *line)
  3011. {
  3012.   struct SeaLst *sl;
  3013.   switch (p->paf_userdata) {
  3014.     case ARG_CONC_FLIB:
  3015.       sl = &globarg_fnt_root->s_list_flib;
  3016.       break;
  3017.     case ARG_CONC_PK:
  3018.       sl = &globarg_fnt_root->s_list_pkdirs;
  3019.       break;
  3020. #if defined(HARDDEB)
  3021.     default: Fatal(20,"fkw_conc_dirs() : illegal switch!");
  3022. #endif
  3023.   }
  3024.   conc_dirs(line, sl);
  3025. }
  3026.  
  3027. /*    fkw_parse_string
  3028.  *
  3029.  * Called when a full string needs to be parsed.
  3030.  */
  3031. static void __stdargs fkw_parse_string
  3032.     (struct string_parse *p, char *line, char *string)
  3033. {
  3034.   char **s;
  3035.   switch(p->paf_userdata) {
  3036.     case ARG_STR_FLIB:
  3037.       s=&globarg_fnt_root->flib_fmt;
  3038.       break;
  3039.     case ARG_STR_PK:
  3040.       s=&globarg_fnt_root->pk_fmt;
  3041.       break;
  3042.     case ARG_STR_BASEPKD:
  3043.       s=&globarg_fnt_root->basepkdir_fmt;
  3044.       break;
  3045.     case ARG_STR_PKDIR:
  3046.       s=&globarg_fnt_root->pkdir_fmt;
  3047.       break;
  3048.     case ARG_STR_FLIBFNT:
  3049.       s=&globarg_fnt_root->flib_fnt_fmt;
  3050.       break;
  3051. #if defined(HARDDEB)
  3052.     default: Fatal(20,"fkw_parse_string(): Illegal switch!");
  3053. #endif
  3054.   }
  3055.   if (NULL == (*s = strdup(string)))
  3056.     Fatal(10,"Not enough memory!");
  3057. }
  3058.  
  3059. /*    fkw_dir
  3060.  *
  3061.  * Called through 'pkdir'and 'basepkdir' keywords
  3062.  */
  3063. static void __stdargs fkw_dir
  3064.     (struct string_parse *p, char *line, long *dpi, char *path)
  3065. {
  3066.   int mark = p->paf_userdata;
  3067.     struct SeaEleDpi *ele, *new;
  3068.  
  3069.     new = xmalloc(sizeof(struct SeaEleDpi));
  3070.     new->dpi = *dpi;
  3071.  
  3072.         new->path = xmalloc(strlen(path)+1);
  3073.         if (mark == 1) {    /*    pkdir        */
  3074.             new->format_str = strdup(globarg_fnt_root->pkdir_fmt);
  3075.         }
  3076.         else {        /*    basepkdir    */
  3077.             new->format_str = strdup(globarg_fnt_root->basepkdir_fmt);
  3078.         }
  3079.             if (new->format_str == NULL) {
  3080.               xfree(new);
  3081.             }
  3082.             else {
  3083.               strcpy(new->path, path);
  3084.               new->next_ele = NULL;
  3085.               if (mark == 1) {
  3086.                   globarg_fnt_root->s_list_pkdpi.number++;
  3087.                   ele = globarg_fnt_root->s_list_pkdpi.first_ele;
  3088.                   if (ele == NULL) {
  3089.                     globarg_fnt_root->s_list_pkdpi.first_ele = new;
  3090.                   }
  3091.                   else {
  3092.                     for (; ele->next_ele != NULL; ele = ele->next_ele);
  3093.                     ele->next_ele = new;
  3094.                   }
  3095.               }
  3096.               else {
  3097.                   globarg_fnt_root->s_list_base_pkdpi.number++;
  3098.                   ele = globarg_fnt_root->s_list_base_pkdpi.first_ele;
  3099.                   if (ele == NULL) {
  3100.                     globarg_fnt_root->s_list_base_pkdpi.first_ele = new;
  3101.                   }
  3102.                   else {
  3103.                     for (; ele->next_ele != NULL; ele = ele->next_ele);
  3104.                     ele->next_ele = new;
  3105.                   }
  3106.               }
  3107.             }
  3108. }
  3109.  
  3110. static void __stdargs fkw_define_flib
  3111.     (struct string_parse *p, char *line, long *dpi, char *path)
  3112. {
  3113.   define_flib(globarg_fnt_root, *dpi, path);
  3114. }
  3115.  
  3116. static void __stdargs fkw_define_font
  3117.     (struct string_parse *p, char *line, char *name, long *dpi, char *where)
  3118. {
  3119.   define_font(globarg_fnt_root, *dpi, where, name);
  3120. }
  3121.  
  3122. #endif /* OLDARGS */
  3123.  
  3124.  
  3125. /*
  3126.  ************************************************************************
  3127.  *    parse string and append the entries to the search list        *
  3128.  ************************************************************************
  3129.  */
  3130.  
  3131. static void conc_dirs(char *str, struct SeaLst *sl)
  3132. {
  3133.   short nr = 0;
  3134.   char *token;
  3135.   struct SeaEle *se, *nse, *lse;
  3136.  
  3137.   for (se = sl->first_ele;
  3138.     se != NULL && se->next_ele != NULL && se->next_ele->next_ele != NULL;
  3139.     se = se->next_ele);
  3140.   /* last ele should be last ele */
  3141.   if (se != NULL) {            /* no ele ? */
  3142.     if (se->next_ele == NULL) {        /* only one ele ? */
  3143.      lse = se;
  3144.      se = NULL;
  3145.     }
  3146.     else {
  3147.       lse = se->next_ele;
  3148.     }
  3149.   }
  3150.  
  3151.   (void) strtok(str, " ,\t");    /* skip key word */
  3152.   do {
  3153.     token = strtok(NULL, " ,\t");
  3154.     if (token != NULL) {
  3155.       if ((nse = xmalloc(sizeof(struct SeaEle))) == NULL) {
  3156.         sl->number += nr;
  3157.         return;
  3158.       }
  3159.       if ((nse->path = strdup(token)) == NULL) {
  3160.         xfree(nse);
  3161.         sl->number += nr;
  3162.         return;
  3163.       }
  3164.       nse->next_ele = lse;    /* next ele is every time the last ele */
  3165.       if (se == NULL) {
  3166.        sl->first_ele = nse;
  3167.       }
  3168.       else {
  3169.         se->next_ele = nse;
  3170.       }
  3171.       nr++;
  3172.       se = nse;
  3173.     }
  3174.   } while (token != NULL);
  3175.   sl->number += nr;
  3176. }
  3177.  
  3178.  
  3179. /*
  3180.  ************************************************************************
  3181.  *    define a flib                            *
  3182.  ************************************************************************
  3183.  */
  3184.  
  3185. static void define_flib (fnt_root, dpi, path)
  3186.   struct FontMan *fnt_root;
  3187.   long dpi;
  3188.   char *path;
  3189. {
  3190.   struct LibLst *entry;
  3191.  
  3192.   entry = (struct LibLst *)xmalloc((size_t)sizeof(struct LibLst));
  3193.  
  3194.   entry->flib.lib_status = LIB_PATH_DEFINED;
  3195.   strcpy(entry->flib.path,path);
  3196.   entry->flib.resolution = dpi;
  3197.   entry->flib.format_str = fnt_root->flib_fmt;
  3198.   entry->flib.lru_count = 0;
  3199.  
  3200.   entry->next_lib = fnt_root->flib_list;
  3201.   fnt_root->flib_list = entry;
  3202. }
  3203.  
  3204.  
  3205. /*
  3206.  ************************************************************************
  3207.  *    define a pk-font                        *
  3208.  ************************************************************************
  3209.  */
  3210.  
  3211. static void define_font (fnt_root, dpi, path, name)
  3212.   struct FontMan *fnt_root;
  3213.   long dpi;
  3214.   char *path;
  3215.   char *name;
  3216. {
  3217.   struct Font *entry;
  3218.   struct PK_Dir *p;
  3219.  
  3220.   /* Huch.... warum wird hier eigentlich auf jeden Fall ein neues font-common angelegt ??? */
  3221.   /* (br) soll es oder soll es nicht ??? */
  3222.   /* (hes) wuesste nicht warum ? */
  3223.  
  3224.   entry = make_new_fontdesc(name, fnt_root);
  3225.  
  3226.   p = (struct PK_Dir *)xmalloc(sizeof(struct PK_Dir));
  3227.  
  3228.   strcpy(p->path, path);
  3229.   p->format_str = fnt_root->pk_fmt;
  3230.  
  3231.   entry->fnt_number                    = -1L;
  3232.   entry->common->fnt_status            = FNT_PATH_DEFINED;
  3233.   entry->common->location.pk_directory = p;
  3234.   entry->common->resolution            = dpi;
  3235.   entry->common->resolution5           = dpi * 5;    /* not exactely */
  3236.   entry->common->where_is_font         = WHERE_PK;
  3237.   entry->orig_dpi               = dpi;
  3238. }
  3239.  
  3240.  
  3241. /*---------------------------------------------*/
  3242.  
  3243. /*
  3244.  ************************************************************************
  3245.  *    initialize the memory-pool for the fonts            *
  3246.  ************************************************************************
  3247.  */
  3248.  
  3249. static void init_mem (ulong size)
  3250. {
  3251.   if (size % 2) size++;        /* byte alignment */
  3252.  
  3253.   lowmem = xmalloc((unsigned)size);
  3254.  
  3255.   start_mem = lowmem;
  3256. #if 0
  3257.   /* wrong !! compiler/machine-dependent   (unsigned long) != (char *) */
  3258.   end_mem = (char *)((unsigned long)lowmem + (unsigned long)size);
  3259. #else
  3260.   end_mem = lowmem + size;
  3261. #endif
  3262.  
  3263. }
  3264.  
  3265.  
  3266. static long *open_charmap (void)
  3267. {
  3268.   charmap = lowmem;
  3269.   return ((long *)charmap);
  3270. }
  3271.  
  3272. static long close_charmap (void)
  3273. {
  3274. #if 0
  3275.   return (((long)lowmem - (long)charmap) >> 2);    /* length in long's */
  3276. #else
  3277.   return (long)((lowmem - charmap)/sizeof(long));    /* length in long's */
  3278. #endif
  3279. }
  3280.  
  3281.  
  3282. /*  verschiebe Bereich von (start + size*4  ...  lowmem)
  3283.  *                    nach (start  ...  lowmem - size*4)
  3284.  *  d.h. Bereich (start  ...  start + size*4 - 1) wird "geloescht"
  3285.  */
  3286.  
  3287. static void adjust_mem (long *start,long size)
  3288.   long len;
  3289.   long *copy;
  3290.  
  3291.   copy = start + size;        /* first source-adr */
  3292.   len = (long)((lowmem - (char *)copy) / sizeof(long));    /* len in byte's */
  3293. #if 0
  3294.   lowmem = (char *) ((long *)lowmem - size);
  3295. #else
  3296.   lowmem = lowmem - (size * sizeof(long));
  3297. #endif
  3298.  
  3299.   while (len-- > 0)
  3300.     *start++ = *copy++;
  3301.  
  3302. #ifdef MYDEBUG
  3303.   /* After copying: start == lowmem !! */
  3304.   if( (char *)start != lowmem ) {
  3305.     LoggingStr("ERROR: adjust_mem() start: 0x%x lowmem: 0x%x size: 0x%x",
  3306.     start, lowmem, size);
  3307.   }
  3308. #endif
  3309. }
  3310.  
  3311.  
  3312. static int do_garcol(void)
  3313.   struct Font *rmFont;
  3314.   struct FontLst *flist;
  3315.   long size;            /* size of deleted font in long's */
  3316.  
  3317.   /* find font to remove */
  3318.   rmFont = what_lru_font(FontRoot->font_list);
  3319.  
  3320.   if (rmFont == NULL) return (TRUE);
  3321.  
  3322.   /* remove font `rmFont' */
  3323.   size = rmFont->common->ch_len;        /* len in long's */
  3324.   adjust_mem(rmFont->common->ch_start_bm, size);
  3325.  
  3326.   /* don't forget to change bm_pointer of fonts in moved area */
  3327.   for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font) {
  3328.     flist->font.common->copied = (char)FALSE;
  3329.   }
  3330.   for (flist = FontRoot->font_list; flist != NULL; flist = flist->next_font) {
  3331.     if (flist->font.common->ch_start_bm != NULL
  3332.     && flist->font.common->ch_start_bm > rmFont->common->ch_start_bm
  3333.     && flist->font.common->copied == (char)FALSE) {
  3334.       flist->font.common->ch_start_bm -= size;
  3335.       flist->font.common->copied       = (char)TRUE;
  3336.     }
  3337.   }
  3338.  
  3339.   charmap = charmap - size * sizeof(long);
  3340.  
  3341.   rmFont->common->ch_start_bm = NULL;
  3342.   rmFont->common->ch_len      = 0;
  3343.  
  3344.   if (rmFont->common->fnt_status == FNT_LOADED ||
  3345.       rmFont->common->fnt_status == FNT_DEFINED_OLOADED) {
  3346.     rmFont->common->fnt_status = FNT_DEFINED;
  3347.   }
  3348.   else {
  3349.     rmFont->common->fnt_status = FNT_FOUND;
  3350.   }
  3351.  
  3352.   Message(MSG_FONT_REMOVED,
  3353.     rmFont->common->fnt_group->fnt_name, rmFont->common->resolution);
  3354.   Logging(MSG_FONT_REMOVED_USED,
  3355.     rmFont->common->fnt_group->fnt_name, rmFont->common->resolution,
  3356.     100L-(end_mem-lowmem)*100L/fontmemsize);
  3357.  
  3358.   return (FALSE);
  3359. }
  3360.  
  3361.  
  3362. #ifdef AMIGA
  3363. /*
  3364.  ************************************************************************
  3365.  *    read the AmigaTeX "fontvols" file and search a pk-font        *
  3366.  ************************************************************************
  3367.  */
  3368.  
  3369. static struct Font *read_atex_file(char *fntname,
  3370.                    long dpi, long dpi5,
  3371.                    struct FontMan *fnt_root)
  3372. {
  3373.   FILE *fontvols;
  3374.   struct Font *fnt = NULL;
  3375.   char *s, *t, *ptr, c;
  3376.   long d_entry, d_v_entry, read_dpi, read_v_dpi;
  3377.   int end, linenr;
  3378.   char *memory, *line, *path, *pkname, *source_name, *dest_name;
  3379.  
  3380.   /**  
  3381.   Allociere die Arrays per malloc, damit 4kB Stack ausreichen!!
  3382.   char line[256], path[PATH_SIZE], pkname[PK_NAME_SIZE];
  3383.   char source_name[PATH_SIZE+FONT_NAME_SIZE], dest_name[PATH_SIZE+FONT_NAME_SIZE],
  3384.   **/
  3385.   memory = xmalloc(256+PATH_SIZE+PK_NAME_SIZE+2*(PATH_SIZE+FONT_NAME_SIZE));
  3386.   line = memory;
  3387.   path = line+256;
  3388.   pkname = path+PATH_SIZE;
  3389.   source_name = pkname+PK_NAME_SIZE;
  3390.   dest_name = source_name+PATH_SIZE+FONT_NAME_SIZE;
  3391.  
  3392.   /* suche erst im TEXCONFIG Pfad */
  3393.   fontvols = OpenConfigFile("fontvols", MODE_READ);
  3394.   if (fontvols == NULL) {
  3395.     fontvols = fopen("TeX:pk/fontvols", "r");
  3396.   }
  3397.  
  3398.   if (fontvols != NULL) {
  3399.     line[255] = '\0';
  3400.     linenr = 0;
  3401.     while(fnt == NULL && fgets(line,255,fontvols) != NULL) {
  3402.       d_entry = d_v_entry = 0;
  3403.       linenr++;
  3404.       
  3405.       t = strrchr(&(line[0]), '\n');        /* skip trailing Return */
  3406.       if (t != NULL) *t = '\0';
  3407.       t = strchr(&(line[0]), ';');        /* skip trailing comment */
  3408.       if (t != NULL) *t = '\0';
  3409.  
  3410.       t = &(line[0]);                /* skip leading blanks */
  3411.       while (*t != '\0' && isspace(*t)) t++;
  3412.       
  3413.       if (*t == '\0') continue;            /* skip blank line */
  3414.  
  3415.       s = strchr(line,'=');
  3416.       if (s == NULL) {
  3417.     Warning(MSG_ERROR_IN_FONTVOLS, "`='", linenr);
  3418.       }
  3419.       else {
  3420.         *s++ = '\0';
  3421.         t = strchr(s, 'd');
  3422.         if (t != NULL) {
  3423.           if (sscanf(s, "%ldx%ld", &d_entry, &d_v_entry) != 2) {
  3424.             d_v_entry = d_entry;    /* kein ddxdd entry */
  3425.           }
  3426.           s = t+1;    /* setze s auf eins nach 'd', sollte ein '.' sein */
  3427.         }
  3428.  
  3429.     end = FALSE;
  3430.     if (t == NULL || *s != '.') {
  3431.           Warning(MSG_ERROR_IN_FONTVOLS, 
  3432.         (t == NULL) ? "`d' key" : GetTeXString(MSG_FONTVOLS_FIRST_DOT), linenr);
  3433.       end = TRUE;
  3434.     }
  3435.         /* hier wird noch getestet, ob die Zeile auch zur richtigen Aufloesung gehoert */
  3436.     end = end || (d_entry != 0 && d_entry != hconvresolution && d_v_entry != vconvresolution);
  3437.  
  3438.     /**
  3439.         printf("d: %ld, vd: %ld, hc: %ld, vc: %ld, end: %ld, &t: %x, *s: %c\n", 
  3440.             d_entry, d_v_entry, hconvresolution, vconvresolution, end, t, *s);
  3441.     **/
  3442.  
  3443.     s++;            /* skip point */
  3444.     while (fnt == NULL && !end) {
  3445.       /* now read entry */
  3446.           for (t=s; *t != '\0' && *t != '.' && *t != '\n'; t++);
  3447.           if (*t == '\n' || *t == '\0') { end = TRUE; }
  3448.           *t = c = '\0';
  3449.           if (sscanf(s,"%ld%c", &read_dpi, &c) > 0) {
  3450.             if (c == 'x') {
  3451.               ptr = strchr(s, c);    /* da sollte nun wirklich nie NULL rauskommen */
  3452.               if (ptr == NULL || sscanf(ptr+1, "%ld", &read_v_dpi) != 1) {
  3453.                 read_v_dpi = read_dpi; /* da nehmen wir quadratisch an... */
  3454.               }
  3455.             }
  3456.             else {
  3457.               read_v_dpi = read_dpi;
  3458.             }
  3459.             /* teste auf x und y resolution */
  3460.             if (read_dpi == dpi && read_v_dpi == compute_vert(dpi)) {
  3461.           char *dest_path;
  3462.           struct SeaEleDpi    *ele;
  3463.  
  3464.               strcpy(path,line);
  3465.               strcat(path,":");
  3466.  
  3467.           /* falls basepkdir definiert wird dieses als Ziel verwendet */
  3468.           ele = fnt_root->s_list_base_pkdpi.first_ele;
  3469.           /* suche passendes Dir... */
  3470.           while (ele != NULL && (ele->hdpi != hconvresolution || ele->vdpi != vconvresolution)) {
  3471.             ele = ele->next_ele;
  3472.           }
  3473.           /* wenn ein basepkdir gefunden, nimm den Formatstring davon */
  3474.               fnt = define_test_pk_font(path, fntname, dpi, dpi5,
  3475.             (ele == NULL) ? fnt_root->pk_fmt : ele->format_str, fnt_root);
  3476.  
  3477.               if (fnt != NULL) {
  3478.  
  3479.         my_sprintf(pkname, PK_NAME_SIZE, fnt->common->location.pk_directory->format_str, fntname, dpi, dpi5);
  3480.         strcpy(source_name,path);
  3481.         mk_correct_path(source_name);
  3482.         strcat(source_name,pkname);
  3483.         
  3484.         /* hier wird nun path[] zu dem Zielpfad */
  3485.  
  3486.         if (ele != NULL) {
  3487.           /* BasePKDir gefunden */
  3488.           my_sprintf(pkname, PK_NAME_SIZE, ele->format_str, fntname, dpi, dpi5);
  3489.           strncpy(dest_name, ele->path, PATH_SIZE);
  3490.           strncpy(path, ele->path, PATH_SIZE);
  3491.           mk_correct_path(dest_name);
  3492.           strncat(dest_name, pkname, PATH_SIZE+FONT_NAME_SIZE);
  3493.           dest_path = ele->path;
  3494.         }
  3495.         else {
  3496.           /* ansonsten nimm default 'TeX:pk' */
  3497.           my_sprintf(pkname, PK_NAME_SIZE, fnt_root->pk_fmt, fntname, dpi, dpi5);
  3498.           strcpy(dest_name, PK_AREA);    /* keine Ueberpruefung noetig! */
  3499.           strcpy(path, PK_AREA);
  3500.           mk_correct_path(dest_name);
  3501.           strncat(dest_name, pkname, PATH_SIZE+FONT_NAME_SIZE);
  3502.           dest_path = PK_AREA;
  3503.         }
  3504.  
  3505.  
  3506.         Logging(MSG_COPY_FONT_TO_CACHE,fntname,dpi,dest_path);
  3507.         Message(MSG_COPY_FONT_TO_CACHE,fntname,dpi,dest_path);
  3508.  
  3509.         /** fnt_root->files_left =-2;     CRASH **/
  3510.         /** close_flibs(fnt_root);     CRASH **/
  3511.         if (!copy_file(source_name,dest_name)) {
  3512.           Warning(MSG_CANT_COPY_FONT_TO_CACHE);
  3513.         }
  3514.         else {
  3515.           /* Wenn der Font kopiert...dann setze den Pfad auf die Kopie    */
  3516.           /* damit die Diskette nicht mehr benoetigt wird!        */
  3517.           strncpy(fnt->common->location.pk_directory->path, path, PK_NAME_SIZE);
  3518.         }
  3519.         /** fnt_root->files_left =+2;    CRASH **/
  3520.               }
  3521.             }
  3522.           }
  3523.           s = t+1;
  3524.     }    /* end while */
  3525.       }
  3526.     }
  3527.     fclose(fontvols);
  3528.   }
  3529.  
  3530.   xfree(memory);  
  3531.   return fnt;
  3532. }
  3533.  
  3534.  
  3535. /*
  3536.  ************************************************************************
  3537.  *    copy the file source to the file drain (make directory)        *
  3538.  ************************************************************************
  3539.  */
  3540.  
  3541. static int copy_file(char *source, char *drain)
  3542. {
  3543.   FILE *sf, *df;
  3544.   long len;
  3545.   char *buffer;
  3546.  
  3547.   /* erzeuge alle noetigen Unterdirectories */
  3548.   if (!create_path(drain)) {
  3549.     return FALSE;
  3550.   }
  3551.  
  3552.   /* xmalloc() liefert nie NULL */
  3553.   buffer = xmalloc(CPBUFSIZE*sizeof(char));
  3554.   if ((sf = fopen(source,"r")) == NULL) {
  3555.     xfree(buffer);
  3556.     return FALSE;
  3557.   }
  3558.   if ((df = fopen(drain,"w")) == NULL) {
  3559.     fclose(sf);
  3560.     xfree(buffer);
  3561.     return FALSE;
  3562.   }
  3563.   while ((len = fread(buffer,sizeof(char),CPBUFSIZE,sf)) == CPBUFSIZE) {
  3564.     if (fwrite(buffer,sizeof(char),CPBUFSIZE,df) != CPBUFSIZE) {
  3565.         fclose(sf);
  3566.         fclose(df);
  3567.         xfree(buffer);
  3568.         return FALSE;
  3569.     }
  3570.   }
  3571.   if (len > 0) {
  3572.     if (fwrite(buffer,sizeof(char),len,df) != len) {
  3573.         fclose(sf);
  3574.         fclose(df);
  3575.         xfree(buffer);
  3576.         return FALSE;
  3577.     }
  3578.   }
  3579.   fclose(sf);
  3580.   fclose(df);
  3581.   xfree(buffer);
  3582.   
  3583.   return TRUE;
  3584. }
  3585.  
  3586.  
  3587. static int create_path(char *path)
  3588. {
  3589.   char *dir, *ptr;
  3590.   BPTR lock;
  3591.  
  3592.   ptr = path;
  3593.   while ((dir = strchr(ptr,'/')) != NULL) {
  3594.     *dir = '\0';
  3595.     lock = Lock(path,ACCESS_READ);
  3596.     if (lock == NULL) {
  3597.       lock = CreateDir(path);
  3598.       if (lock == NULL) {
  3599.         return FALSE;
  3600.       }
  3601.     }
  3602.     UnLock((BPTR)lock);
  3603.     *dir = '/';
  3604.     ptr = dir+1;
  3605.   }
  3606.   return TRUE;
  3607. }
  3608.  
  3609. #endif
  3610.