home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gle / gle / tex.c < prev    next >
C/C++ Source or Header  |  1992-11-29  |  37KB  |  1,590 lines

  1. #include <stdlib.h>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #ifndef unix
  7. #include <stdarg.h>
  8. #endif
  9. #include "glepro.h"
  10. #define false 0
  11. #define true (!false)
  12. #include "mygraph.h"
  13. #include <math.h>
  14. double emtof(char *s);
  15. int font_reset_parskip(void);
  16. int set_parskip(double v);
  17. int set_lineskip(double v);
  18. int ncat(char *a,char *b,int n);
  19. int pp_fntchar(int f, int c,long *out, int *lout);
  20. int polish_eval(char *s, double *x);
  21. int cmd_token(uchar **in,char *cmdstr);
  22. int set_base_size(void);
  23. int find_primcmd(char *cmd);
  24. int text_box(uchar *s,double width,long *tbuff, long *rplen);
  25. int cmd_param(uchar **inp,uchar *pm[],int pmlen[],int npm);
  26. int text_tomacro(uchar *in, uchar *out);
  27. int texint(char *s, int *i);
  28. int tex_presave(void);
  29. int tex_preload(void);
  30. int fsendstr(char *s, FILE *fout);
  31. int text_gprint(long *in,int ilen);
  32. int fftext_block(uchar *s,double width,int justify);
  33. int font_load(void);
  34. int tex_init(void);
  35. int g_get_font(int *i);
  36. int do_prim(uchar **in,long *out,int *lout);  /*  \frac{text}{text} */
  37. #define dbg if ((gle_debug & 1024)>0)
  38. extern int gle_debug;
  39. double text_endx,text_endy;
  40. /*----------------------------------------------------------------------*/
  41. /*         TeX Emulation routines                     */
  42. /*----------------------------------------------------------------------*/
  43. #define FONTDEF extern
  44. #include "font.h"
  45. #include "tex.h"
  46. double linegap;
  47. /*----------------------------------------------------------------------*/
  48. struct def_table_struct {
  49.     struct def_table_struct *next;
  50.     char *name;
  51.     char *defn;
  52.     int npm;
  53. };
  54. typedef struct def_table_struct deftable;
  55.  
  56. /*----------------------------------------------------------------------*/
  57. int tex_def(char *name, char *defn,int npm);
  58. int tex_mathdef(char *name, int defn);
  59. int *tex_findmathdef(char *s);
  60. int tex_chardef(int c, char *defn);
  61. char *tex_findchardef(int c);
  62. deftable *tex_finddef(char *s) ;
  63. /*----------------------------------------------------------------------*/
  64. /*        Global variables for TEX emulation */
  65.  
  66. int fontfam[16][4];
  67. double fontfamsz[16][4];    /* 1=text,  2=script, 3=scriptscript */
  68. int famdef = -1;    /* dont use unless/until it is defined */
  69.  
  70. char *cdeftable[256];    /* Character macro's */
  71. uchar chr_code[256];    /* Character codes 1..9  */
  72. int chr_mathcode[256];    /* Character codes 1..9  */
  73. int chr_val[256];    /* Character values, or macro numbers */
  74. int chr_init;        /* Flag to initialize chr variables */
  75.  
  76. #define dp if (dont_print==false)
  77. int dont_print=0;
  78. long gt_pbuff[5000];
  79. int gt_plen;
  80. double gt_l,gt_r,gt_u,gt_d;
  81.  
  82. int tofont[9] = {0,2,2,1,1,0,0,0,0};
  83.  
  84. int p_fnt;
  85. double p_hei;
  86. double grphei[10];
  87. int grpfnt[10];
  88. int p_ngrp;
  89.  
  90. double base_size;
  91. int curstyle=6;
  92.  
  93. double stretch_factor=1;
  94. /*----------------------------------------------------------------------*/
  95.  
  96. union both {float f;long l;} bth;
  97. #define outlong(v) *(out+((*lout)++)) = v
  98. #define outfloat(v) bth.f = v; *(out+((*lout)++)) = bth.l
  99. #define chrwidth(d) ((*(fnt[p_fnt].chr))[d].wx)
  100. #define tofloat(fff) ((bth.l = fff),bth.f )
  101. #define tolong(fff) ((bth.f = fff),bth.l )
  102. #define checkfont if (fnt[p_fnt].chr==NULL) font_load_metric(p_fnt)
  103.  
  104. int set_stretch(double v);
  105. set_stretch(double v)
  106. {
  107.     stretch_factor = v;
  108. }
  109. set_base_size()
  110. {
  111.     g_get_hei(&base_size);
  112. }
  113. text_topcode(uchar *in, long *out, int *lout)      /*  passed a paragraph  */
  114. {
  115.     int skip_space;
  116.     float w;
  117.     uchar c,d,c2,d2;
  118.  
  119.     outlong(8);    /* set font size */
  120.     outfloat(p_hei);
  121.  
  122.  
  123.     while (c = *(in++)) {
  124.   dbg /* if (chr_code[c]>2) */ gprint("uchar %d, code %d  value %d \n",c,chr_code[c],chr_val[c]);
  125.       switch (chr_code[c]) {
  126.          case 10:
  127.         case 1: /* Normal character */
  128.         d = chr_val[c];
  129.         /* if next char is normal, then check for ligature and kern */
  130. norm_again:
  131.         w=0;
  132.         checkfont;
  133.         if (chr_code[*in]==1 || chr_code[*in]==10) {
  134.             if (char_lig(p_fnt,&d,chr_val[*in])) {
  135.                 in++;
  136.                 goto norm_again;
  137.             }
  138.             char_kern(p_fnt,d,chr_val[*in],&w);
  139.         }
  140.         outlong(1);
  141.         outlong(d | p_fnt*256);
  142.         dbg gprint("==char width %d %f %f \n",d,chrwidth(d),w);
  143.         if (fnt[p_fnt].chr==NULL) font_load_metric(p_fnt);        outfloat((chrwidth(d)+w)*p_hei);
  144.         skip_space = false;
  145.         break;
  146.         case 2: /* Single space */
  147.         if (skip_space) break;
  148.         skip_space = true;
  149.         outlong(2);
  150.         checkfont;
  151.         outfloat(fnt[p_fnt].space*p_hei);
  152.         outfloat(fnt[p_fnt].space_stretch*p_hei*10*stretch_factor);
  153.         outfloat(fnt[p_fnt].space_shrink*p_hei*10);
  154.         break;
  155.         case 3: /* Tab (for tabular) */
  156.         break;
  157.         case 4: /* 8Tab (verbatim) */
  158.         break;
  159.         case 5: /* \\ End of line */
  160.         skip_space = false;
  161.         outlong(5);
  162.         outlong(0);        /* space for x,y to be put */
  163.         outlong(0);
  164.         break;
  165.         case 6: /* \ Primitive Command (macro's already done) */
  166.         skip_space = false;
  167.         do_prim(&in,out,lout);
  168.         break;
  169.         case 7: /* { begin group */
  170.         skip_space = false;
  171.         grphei[++p_ngrp] = p_hei;
  172.         grpfnt[p_ngrp] = p_fnt;
  173.         break;
  174.         case 8: /* } end group */
  175.         skip_space = false;
  176.         if (p_ngrp<1) {
  177.             gprint("%s\n",in);
  178.             gprint("Too many end group brackets \n");
  179.             return;
  180.         }
  181.         p_hei = grphei[p_ngrp];
  182.         p_fnt = grpfnt[p_ngrp--];
  183.         font_load_metric(p_fnt);
  184.  
  185.         outlong(8); outfloat(p_hei);
  186.         break;
  187.         case 9: /* $^_ Macro (Done in macro expansion) */
  188.         skip_space = false;
  189.         break;
  190.         case 11: /* flag for end of paragraph */
  191.             skip_space = false;
  192.         outlong(10);
  193.         outlong(0);    /* space for x,y to be put */
  194.         outlong(0);
  195.         break;
  196.         default:
  197.         gprint("error, not valid character \n");
  198.       }
  199.     }
  200. }
  201. /* cmd_param(uchar **inp,char *(*pm)[],int (*pmlen)[],int npm) */
  202. int cmd_param(uchar **inp,uchar *pm[],int pmlen[],int npm)
  203. {
  204.     int gcnt=0,i;
  205.     uchar *in = *inp;
  206.     gcnt = 0;
  207.     for (i=0;i<npm;i++) {
  208.      pm[i] = in;
  209.      pmlen[i] = 0;
  210.       if (chr_code[*in]==7) { /* begin group */
  211.         pm[i] = ++in;
  212.         for (;*in!=0;in++) {
  213.             if (chr_code[*in]==7) gcnt++;
  214.             if (chr_code[*in]==8) {
  215.                 if (gcnt==0) break;
  216.                 gcnt--;
  217.             }
  218.         }
  219.         pmlen[i] = in - pm[i];
  220.         in++;
  221.       } else {
  222.           if (chr_code[*in]==6) { /* backslash look for non-alpha */
  223.             pm[i] = ++in;
  224.             if (isalpha(*pm[i])) {
  225.                 for (;*in!=0;in++) {
  226.                     if (!isalpha(*in)) {
  227.                         break;
  228.                     }
  229.                 }
  230.                 pmlen[i] = in - pm[i];
  231.             } else {
  232.                 pm[i] = in;
  233.                 pmlen[i] = 1;
  234.                 in++;
  235.             }
  236.         } else {
  237.             pm[i] = in;
  238.             pmlen[i] = 1;
  239.             in++;
  240.         }
  241.       }
  242.     }
  243.     *inp = in;
  244. }
  245. text_box(uchar *s,double width,long *tbuff, long *rplen)
  246. {
  247.     uchar *t,*r,*m,*p;
  248.     int i;
  249.     int plen=0;
  250.     char *workbuff;
  251.  
  252.     workbuff = myalloc(1000);
  253.     if (s==NULL) return;
  254.     if (*s==0) return;
  255.     if (chr_init==false) tex_init();
  256.     text_tomacro(s,workbuff);
  257.     plen = 0;
  258.     if (width==0) width = 400;
  259.     text_topcode(workbuff,tbuff,&plen);
  260.     text_wrapcode(tbuff,plen,width);
  261.     *rplen = plen;
  262.     myfree(workbuff);
  263. }
  264. topcode(char *s, int slen, double width, long **pbuff, long *plen, double *l,double *r,double *u,double *d)
  265. {
  266.     char schar;
  267.  
  268.     *pbuff = myalloc(1000);
  269.     g_init_bounds();
  270.     schar = s[slen];
  271.     s[slen] = 0;
  272.     text_box(s,width,*pbuff,plen);
  273.     s[slen] = schar;
  274.     g_get_bounds(l,d,r,u);
  275.     if (*l > *r) {*l=0; *r=0; *u=0; *d=0;}
  276.  
  277. }
  278.  
  279. #define p_sethei(hh) pp_sethei(hh,out,lout)
  280. #define p_hfill(hh) pp_hfill(hh,out,lout)
  281. #define p_move(x,y) pp_move(x,y,out,lout)
  282. #define p_fntchar(ff,cc) pp_fntchar(ff,cc,out,lout)
  283. #define p_mathchar(m) pp_mathchar(m,out,lout)
  284. #define p_pcode(pbuff,plen) pp_pcode(pbuff,plen,out,lout)
  285.  
  286. pp_move(double x, double y, long *out,int *lout)
  287. {
  288.     outlong(4);
  289.     outfloat(x);
  290.     outfloat(y);
  291. }
  292. pp_sethei(double h, long *out,int *lout)
  293. {
  294.     outlong(8);
  295.     outfloat(h);
  296.     p_hei = h;
  297. }
  298. pp_hfill(double h, long *out,int *lout)
  299. {
  300.     outlong(2);
  301.     outfloat(0.0);
  302.     outfloat(h*p_hei);
  303.     outfloat(h*p_hei);
  304. }
  305. int char_bbox_user(int p_fnt,int ix, double *x1,double *y1,double *x2,double *y2);
  306. char_bbox_user(int p_fnt,int ix, double *x1,double *y1,double *x2,double *y2)
  307. {
  308.     char_bbox(p_fnt,ix,x1,y1,x2,y2);
  309.     *x1 *= p_hei;
  310.     *x2 *= p_hei;
  311.     *y1 *= p_hei;
  312.     *y2 *= p_hei;
  313. }
  314. pp_mathchar(int m, long *out, int *lout)
  315. {
  316.     int mchar,mfam,mtyp;
  317.     int ix;
  318.     double x1,y1,x2,y2,reqhi,yc;
  319.     double oldhei;
  320.     oldhei = p_hei;
  321.     mchar = m & 0xff;
  322.     mfam = (m & 0xf00) / 0x100;
  323.     mtyp = (m & 0xf000) / 0x1000;
  324.     if (mtyp == 7  && famdef>=0) mfam = famdef;
  325.     if (mtyp == 7) mtyp = 0;
  326.     ix = 'b'; /* center on letter b */
  327.     char_bbox_user(p_fnt,ix,&x1,&y1,&x2,&y2);
  328.     reqhi = y2/2;
  329.     p_sethei(fontfamsz[mfam][tofont[curstyle]] * base_size);
  330.     char_bbox_user(fontfam[mfam][tofont[curstyle]],mchar,&x1,&y1,&x2,&y2);
  331.     yc = (y2-y1)/2;
  332.     if (mtyp==1) pp_move(0,reqhi+yc-y2,out,lout);
  333.     p_fntchar(fontfam[mfam][tofont[curstyle]],mchar);
  334.     if (mtyp==1) pp_move(0,-(reqhi+yc-y2),out,lout);
  335.     p_sethei(oldhei);
  336. }
  337. #define mchrwidth(ddd) ((*(fnt[ff].chr))[ddd].wx)
  338. pp_fntchar(int ff, int ch, long *out,int *lout)
  339. {
  340.     if (fnt[ff].chr==NULL) font_load_metric(ff);
  341.     outlong(1);
  342.     outlong(ch | ff*256);
  343.     outfloat((mchrwidth(ch))*p_hei);
  344. }
  345. pp_pcode(long *pbuff, int plen, long *out,int *lout)
  346. {
  347.     int i;
  348.     out += *lout;
  349.     for (i=0;i<plen;i++) *out++ = *pbuff++;
  350.     *lout = *lout + plen;
  351. }
  352. cmd_param1(uchar **in,char *str1)
  353. {
  354.     union {char *s[4]; uchar *u[4];} pm;
  355.     int pmlen[4];
  356.     cmd_param(in,pm.u,pmlen,1);
  357.     ncpy(str1,pm.s[0],pmlen[0]);
  358. }
  359. cmd_param2(uchar **in,char *str1,char *str2)
  360. {
  361.     union {char *s[4]; uchar *u[4];} pm;
  362.     int pmlen[4];
  363.     cmd_param(in,pm.u,pmlen,(int) 2);
  364.     ncpy(str1,pm.s[0],pmlen[0]);
  365.     ncpy(str2,pm.s[1],pmlen[1]);
  366. }
  367. cmd_param3(uchar **in,char *str1,char *str2,char *str3)
  368. {
  369.     union {char *s[5]; uchar *u[5];} pm;
  370.     int pmlen[5];
  371.     cmd_param(in,pm.u,pmlen,3);
  372.     ncpy(str1,pm.s[0],pmlen[0]);
  373.     ncpy(str2,pm.s[1],pmlen[1]);
  374.     ncpy(str3,pm.s[2],pmlen[2]);
  375. }
  376.  
  377. do_prim(uchar **in,long *out,int *lout)  /*  \frac{text}{text} */
  378. {
  379.     int ci;
  380.     int ix,savefnt,newfnt;
  381.     static char cmdstr[20];
  382.     char str1[100],str2[100],str3[100];
  383.     double lef,wid,hei,dep,savehei,x;
  384.     long *pbuff=0;
  385.     long plen;
  386.     union {char *s[10]; uchar *u[10];} pm;
  387.     int pmlen[10];
  388.     int *m,i,k,j,n,npm;
  389.  
  390.     k = 0;
  391.  
  392.     cmd_token(in,cmdstr);    /* finds command name and parameters */
  393.     ci = find_primcmd(cmdstr);
  394.     if (ci==0) { /* then maybe its a mathchar */
  395.         m = tex_findmathdef(cmdstr);
  396.         if (m!=0) {
  397.             p_mathchar(*m);
  398.         } else {
  399.             gprint("Unrecognised control sequence {%s} \n",cmdstr);
  400.         }
  401.         return;
  402.     }
  403.     switch (ci) {
  404.       case tp_sup: /* \superscript{exp} */
  405.         cmd_param(in,pm.u,pmlen,1);
  406.         savehei = p_hei;
  407.         p_hei = p_hei * .7;
  408.         topcode(pm.s[0],pmlen[0],0.0,&pbuff,&plen,&lef,&wid,&hei,&dep);
  409.         p_move(0,0.8*p_hei);
  410.         p_pcode(pbuff,plen);
  411.         p_move(0,-0.8*p_hei);
  412.         myfree(pbuff);
  413.         p_sethei(savehei);
  414.         break;
  415.       case tp_sub:
  416.         cmd_param(in,pm.u,pmlen,1);
  417.         savehei = p_hei;
  418.         p_hei = p_hei * .7;
  419.         topcode(pm.s[0],pmlen[0],0.0,&pbuff,&plen,&lef,&wid,&hei,&dep);
  420.         p_move(0,-0.3*p_hei);
  421.         p_pcode(pbuff,plen);
  422.         p_move(0,0.3*p_hei);
  423.         myfree(pbuff);
  424.         p_sethei(savehei);
  425.         break;
  426.       case tp_sethei: /* \sethei{exp} */
  427.         cmd_param1(in,str1);
  428.         p_sethei(emtof(str1));
  429.         break;
  430.       case tp_hfill: /* \sethei{exp} */
  431.         p_hfill(10.0);
  432.         break;
  433.       case tp_char:
  434.         cmd_param1(in,str1);
  435.         texint(str1,&ix);
  436.         p_fntchar(p_fnt,ix);
  437.         break;
  438.       case tp_chardef:  /* /chardef{a}{xxxxx} */
  439.         cmd_param2(in,str1,str2);
  440.         tex_chardef(str1[0],str2);
  441.         break;
  442.       case tp_ssfont:
  443.         k++;
  444.       case tp_sfont:
  445.         k++;
  446.       case tp_tfont:  /* \tfont{0}{cmr10}{.5}  */
  447.         cmd_param3(in,str1,str2,str3);
  448.         i = atoi(str1);  if (i>15) i = 1;
  449.         fontfam[i][k] = pass_font(str2);
  450.         fontfamsz[i][k] = emtof(str3);
  451.         break;
  452.       case tp_accent:  /* accent{texcmr}{123}{a} */
  453.         {
  454.         double wid2,hei2,lef2,dep2,ww,hh,h=0,cwid,cwid2;
  455.         int ix2;
  456.  
  457.         cmd_param3(in,str1,str2,str3);
  458.         savefnt = p_fnt;
  459.         newfnt = pass_font(str1);
  460.         texint(str2,&ix);
  461.         ix2 = str3[0];
  462.         char_bbox(newfnt,ix,&lef,&dep,&wid,&hei);
  463.         cwid = p_hei * ((*(fnt[newfnt].chr))[ix].wx);
  464.         char_bbox(p_fnt,ix2,&lef2,&dep2,&wid2,&hei2);
  465.         cwid2 = p_hei * ((*(fnt[p_fnt].chr))[ix2].wx);
  466.  
  467.         wid *= p_hei;  wid2 *= p_hei; hei *= p_hei; hei2 *= p_hei;
  468.         lef *= p_hei;  dep *= p_hei;
  469.         lef2 *= p_hei;  dep2 *= p_hei;
  470.         if (hei2>p_hei*(3.6/8.0)) h = hei2-p_hei*(3.6/8.0);
  471.  
  472.         ww = lef2+wid2;
  473.         p_fntchar(p_fnt,ix2);
  474.         p_move(-cwid2 + lef2 + wid2/2 -wid/2,h);  /* cwid2/2 - cwid/2 */
  475.         p_fntchar(newfnt,ix);          /* cwid2/2 + cwid/2 */
  476.         p_move(-cwid + cwid2 - lef2 - wid2/2 + wid/2,-h);
  477.         p_fnt = savefnt;
  478.         font_load_metric(p_fnt);
  479.         break;
  480.         }
  481.       case tp_def:
  482.         cmd_param1(in,str1); /* finds everything up to the #1#2 */
  483.         npm = 0;
  484.         while (**in == '#') {
  485.             (*in)++;
  486.             n = (*(*in)++) - '0';
  487.             if (n>0 && n<9) if (npm<n) npm=n;
  488.         }
  489.         cmd_param1(in,str2);
  490.         tex_def(str1,str2,npm);
  491.         break;
  492.       case tp_mathchardef:    /* /mathchardef */
  493.         cmd_param2(in,str1,str2);
  494.         texint(str2,&ix);
  495.         tex_mathdef(str1+1,ix);
  496.         break;
  497.       case tp_movexy:
  498.         cmd_param2(in,str1,str2);
  499.         p_move(emtof(str1),emtof(str2));
  500.         break;
  501.       case tp_rule:
  502.         cmd_param2(in,str1,str2);
  503.         outlong(6);
  504.         outfloat(emtof(str1));
  505.         outfloat(emtof(str2));
  506.         break;
  507.       case tp_mathchar:
  508.         cmd_param1(in,str1);
  509.         texint(str1,&ix);
  510.         p_mathchar(ix);
  511.         break;
  512.       case tp_mathcode:
  513.         cmd_param2(in,str1,str2);
  514.         texint(str2,&ix);
  515.         chr_mathcode[*str1] = ix;
  516.         break;
  517.       case tp_delcode:
  518.         cmd_param2(in,str1,str2);
  519.         texint(str2,&ix);
  520.         chr_mathcode[*str1] = ix;
  521.         break;
  522.       case tp_setfont:
  523.         cmd_param1(in,str1);
  524.         p_fnt = pass_font(str1);
  525.         font_load_metric(p_fnt);
  526.  
  527.         if (fnt[p_fnt].chr==NULL) font_load_metric(p_fnt);
  528.         break;
  529.       case tp_presave:
  530.         gprint("Saving definitions\n");
  531.         tex_presave();
  532.         break;
  533.         case tp_newline:
  534.         outlong(5);
  535.         outlong(0);        /* space for x,y to be put */
  536.         outlong(0);
  537.         break;
  538.        case tp_parskip:
  539.         cmd_param1(in,str1);
  540.         set_parskip(emtof(str1));
  541.         break;
  542.        case tp_setstretch:
  543.         cmd_param1(in,str1);
  544.         set_stretch(emtof(str1));
  545.         break;
  546.       case tp_lineskip:
  547.         cmd_param1(in,str1);
  548.         set_lineskip(emtof(str1));
  549.         break;
  550.       case tp_linegap:
  551.         cmd_param1(in,str1);
  552.         linegap = emtof(str1);
  553.         break;
  554.       case tp_frac:
  555.       case tp_delimiter:
  556.       case tp_left:
  557.       case tp_right:
  558.       case tp_defbegin:
  559.       case tp_nolimits:
  560.  
  561.       case tp_overbrace:
  562.       case tp_overline:
  563.       case tp_underbrace:
  564.       case tp_underline:
  565.         gprint("A valid GLE-TEX primitive which isn't implemented yet %d \n",ci);
  566.         break;
  567.       default:
  568.         gprint("An invalid GLE-TEX primitive %d \n",ci);
  569.         break;
  570.     }
  571. }
  572. double emtof(char *s)
  573. {    /* same as ATOF but if it sees EM then it multiplies by FONT HEI */
  574.     if (strstr(s,"sp")!=NULL) {
  575.         return atof(s)*fnt[p_fnt].space*p_hei;
  576.     }
  577.     if (strstr(s,"em")!=NULL) {
  578.         return atof(s)*p_hei*.75;
  579.     }
  580.     return atof(s);
  581. }
  582. texint(char *s, int *i)    /* Reads an integer, or hex string (if $) */
  583. {
  584.     long j;
  585.     if (*s=='$') {
  586.         sscanf(s+1,"%lx",&j);
  587.         *i = j;
  588.     } else *i = atoi(s);
  589. }
  590. /*
  591.     Character Codes
  592.  
  593.     a..z        1    normal character
  594.     space        2    single space
  595.     <TAB>,&        3    Tab (as in tabular)
  596.     <8TAB>        4    TAB (as in verbatim)
  597.     <LF>,\\        5    End of line
  598.     \        6    Macro or command
  599.     {        7    Begin group
  600.     }        8     end group
  601.     $_^        9    Macro call
  602.             10    null
  603.     255        11    end of paragraph (crcr)
  604.     end of command, = first non alpha character
  605. */
  606.  
  607.  
  608.  
  609.  
  610. /*    Bounding Box ??
  611.  
  612.      1=char  font+char,x
  613.       2=move  x,stret,shrink            throw away after cr
  614.       3=MOVE  x,0,0                glue which has been set
  615.     4=MOVE    x,y                solid move
  616.     5=newline,x,y
  617.     6=rule    x,y
  618.     10=color color
  619.     8=fontsz   fontsz
  620.     9=font     i
  621.     15=null
  622. */
  623. #define infloat(fff) ((bth.l = fff),bth.f)
  624.  
  625.  
  626. text_wrapcode(long *in,int ilen,double width)
  627. {
  628.     double cx=0,cy=0,p_hei,ax=0,x,y,cdep=0,chei=0;
  629.     int i,j,eat_glue,c,p_fnt,si,skline,saveii;
  630.     double totstretch=0,totshrink=0,ls=0,gap=0
  631.         ,last_y,last_x,lastdep,last_stret,last_shrink;
  632.     long *pcr=0,last_space=0;
  633.     double setlen;
  634.     dbg text_gprint(in,ilen);
  635.     ls = 0;
  636.     last_x = 0;
  637.     gap = 0;
  638.     last_y = 0;
  639.     lastdep = 0;
  640.     last_stret = 0;
  641.     last_shrink = 0;
  642.     dbg gprint("==wrap pcode, ilen = %d \n",ilen);
  643.  
  644.     dbg gprint("wrap pcode ilen=%d \n",ilen);
  645.     p_hei = 1;
  646.     si = 0;
  647.     for (i=0;i<ilen;i++) {
  648.       switch (*(in+i)) {
  649.         case 1: /* char    font+char,wx      */
  650.         eat_glue = false;
  651.         p_fnt = (*(in+ ++i) & 0xff00) / 0x100;
  652.                 font_load_metric(p_fnt);
  653.  
  654.         c = *(in+i) & 0x00ff;
  655.         if (cdep>cy+p_hei*((*(fnt[p_fnt].chr))[c].y1))
  656.             cdep=cy+p_hei*((*(fnt[p_fnt].chr))[c].y1);
  657.         if (chei<cy+p_hei*((*(fnt[p_fnt].chr))[c].y2))
  658.             chei=cy+p_hei*((*(fnt[p_fnt].chr))[c].y2);
  659. /*        gprint("chei=%f, cdep=%f \n",chei,cdep);   */
  660.  
  661.         cx += tofloat(*(in+ ++i));
  662.         ax = cx;
  663.         if (cx>width) {
  664.           if (last_space>si) {
  665.             dbg gprint("Call SET_GLUE  from %d, to %d \n",si,last_space);
  666.             set_glue(in+si,last_space-si,last_x,width,last_stret,last_shrink,&setlen);
  667.             i = last_space;
  668.             *(in+i++) = 4;
  669.             *(in+i++) = tolong(-setlen);
  670.             if (pcr!=NULL) { /* put in last line feed now */
  671.                 y = last_y-ls;
  672.                 if ((y+chei+gap)>lastdep)
  673.                     y = lastdep-chei-gap;
  674.                 cy = y;
  675.                 *pcr = tolong(y);
  676.             }
  677.             font_get_lineskip(&ls,&gap);
  678.             pcr = (in+i++);   /* place to put line feed */
  679.             *(in+i) = 20;        /* null */
  680.             last_stret = 0;
  681.             last_shrink = 0;
  682.             totstretch = 0;
  683.             totshrink = 0;
  684.             lastdep = cdep;
  685.             last_y = cy;
  686.             cx = 0;
  687.             cy = 0;
  688.             si = i;
  689.             eat_glue = true;
  690.           }
  691.         }
  692.         break;
  693.         case 2: /* move    x,stretch,shrink */
  694.         last_space = i;
  695.         last_x = ax;
  696.         last_y = cy;
  697.         last_stret = totstretch;
  698.         last_shrink = totshrink;
  699.         if (eat_glue) {*(in+i)=3; *(in+ ++i)=tolong(0);i+=2;break;}
  700.         cx += tofloat(*(in+ ++i));
  701.         totstretch += tofloat(*(in+ ++i));
  702.         totshrink += tofloat(*(in+ ++i));
  703.         dbg gprint("total stretch %f, shrink %f \n",totstretch,totshrink);
  704.         break;
  705.         case 3: /* move    x,0,0   SOLID     */
  706.         cx += tofloat(*(in+ ++i));
  707.         i += 2;
  708.         ax = cx;
  709.         eat_glue = false;
  710.         break;
  711.         case 4: /* move     x,y     SOLID     */
  712.         eat_glue = false;
  713.         cx += tofloat(*(in+ ++i));
  714.         cy += tofloat(*(in+ ++i));
  715.         ax = cx;
  716.         break;
  717.         case 5: /* Newline  x,y    (0,0 at moment) */
  718.         case 10:
  719.         if (*(in+i)==5) skline = true; else skline = false;
  720.         *(in+i) = 0;
  721. /*        last_space = i;
  722.         last_x = ax;
  723.         last_y = cy;
  724.         last_stret = totstretch;
  725.         last_shrink = totshrink;
  726. */
  727.           if (last_space<=si || ax==cx) {
  728.             last_x = ax;
  729.             last_y = cy;
  730.             last_stret = totstretch;
  731.             last_shrink = totshrink;
  732.             last_space = i;
  733.           }
  734.             dbg gprint("Call SET_GLUE  from %d, to %d \n",si,last_space);
  735.             set_glue(in+si,last_space-si,last_x,width,last_stret,last_shrink,&setlen);
  736.             saveii = i;
  737.             i = last_space;
  738.             while (i < saveii) *(in+i++) = 20; /* nop */
  739.             *(in+i++) = 4;
  740.             *(in+i++) = tolong(-setlen);
  741.             if (pcr!=NULL) { /* put in last line feed now */
  742.                 y = last_y-ls;
  743.                 if ((y+chei+gap)>lastdep)
  744.                     y = lastdep-chei-gap;
  745.                 cy = y;
  746.                 *pcr = tolong(y);
  747.             }
  748.             if (skline)
  749.                 font_get_lineskip(&ls,&gap);
  750.             else    font_get_parskip(&ls,&gap);
  751.             pcr = (in+i);   /* place to put line feed */
  752.             last_stret = 0;
  753.             last_shrink = 0;
  754.             totstretch = 0;
  755.             totshrink = 0;
  756.             lastdep = cdep;
  757.             last_y = cy;
  758.             cx = 0;
  759.             cy = 0;
  760.             si = i+1;
  761.             eat_glue = true;
  762.             break;
  763. /*        eat_glue = true;
  764.         i += 2;
  765.         break; */
  766.         case 6: /* rule     x,y         */
  767.         i += 2;
  768.         eat_glue = false;
  769.         break;
  770.         case 7: /* color    color         */
  771.         g_set_color(tofloat(*(in+ ++i)));
  772.         break;
  773.         case 8: /* fontsz     sz        */
  774.         p_hei = tofloat(*(in+ ++i));
  775.         g_set_hei(p_hei);
  776.         break;
  777.         case 9: /* font    p_fnt    */
  778.         p_fnt = *(in+ ++i);
  779.                 font_load_metric(p_fnt);
  780.  
  781.         break;
  782.         case 20: /*  nop  */
  783.         break;
  784.         default:
  785.         gprint("dud pcode in wrap pcode %d   i=%d \n",*(in+i),i);
  786.         break;
  787.       }
  788.     }
  789.  
  790.     if (last_space==0) last_space = ilen;
  791.     dbg gprint("Exiting call to SET_GLUE  from %d, to %d \n",si,last_space);
  792.     set_glue(in+si,last_space-si,last_x,width,last_stret,last_shrink,&setlen);
  793.     if (pcr!=NULL) { /* put in last line feed now */
  794.         y = last_y-ls;
  795.         if ((y+chei+gap)>lastdep)
  796.             y = lastdep-chei-gap;
  797.         cy = y;
  798.         *pcr = tolong(y);
  799.     }
  800.     dbg text_gprint(in,ilen);
  801. }
  802. set_glue(long *in,int ilen,double actual,double width,double stretch,double
  803.     shrink,double *setlen)
  804. {
  805.     double mst=0,msh=0;
  806.     float s1,s2,x,y;
  807.     int i=0;
  808.  
  809.     dbg gprint("===set glue \n");
  810.     dbg text_gprint(in,ilen);
  811.     dbg gprint("set glue ilen=%d actual=%f, width=%f, stretch=%f shrink=%f \n"
  812.             ,ilen,actual,width,stretch,shrink);
  813. /*    if (actual<0) get_natural(in,ilen,&actual); */
  814.     if (actual<width) {
  815.         if (stretch>0.0000001) mst = (width-actual)/stretch;
  816.         msh = 0;
  817.         if (mst>1) mst=0;
  818.     } else {
  819.         mst = 0;
  820.         if (shrink>0) msh = (actual-width)/shrink;
  821.         if (msh>1) msh=0;
  822.     }
  823.     *setlen = actual+stretch*mst+shrink*msh;
  824.     dbg gprint("SETTing glue to  %f  %f  actual %f, setto %f\n",mst,msh,actual,*setlen);
  825.  
  826.     for (i=0;i<ilen;i++) {
  827.       switch (*(in+i)) {
  828.         case 1: /* char    font+char,wx      */
  829.         i += 2;
  830.         break;
  831.         case 2: /* move    x,stretch,shrink */
  832.         x = tofloat(*(in+i+1));
  833.         s1 = tofloat(*(in+i+2));
  834.         s2 = tofloat(*(in+i+3));
  835.         *(in+i) = 3;
  836.         *(in+i+1) = tolong(x + s1*mst+s2*msh);
  837.         i += 3;
  838.         break;
  839.         case 3: /* move    x,0,0   SOLID     */
  840.         i += 3;
  841.         break;
  842.         case 4: /* move     x,y     SOLID     */
  843.         i += 2;
  844.         break;
  845.         case 5: /* Newline  x,y    (0,0 at moment) */
  846.         i += 2;
  847.         break;
  848.         case 6: /* rule     x,y         */
  849.         i += 2;
  850.         break;
  851.         case 7: /* color    color         */
  852.         i += 1;
  853.         break;
  854.         case 8: /* fontsz     sz        */
  855.         i += 1;
  856.         break;
  857.         case 9: /* font    p_fnt    */
  858.         i += 1;
  859.         break;
  860.         case 10: /* Newparagraph x,y    (0,0 at moment) */
  861.         i += 2;
  862.         break;
  863.         case 20: /*  nop  */
  864.         break;
  865.         default:
  866.         gprint("dud (in set glue) pcode in text pcode %d i=%d\n",*(in+i),i);
  867.         break;
  868.       }
  869.     }
  870.     dbg printf("=== Result after setting \n");
  871.     dbg text_gprint(in,ilen);
  872.     dbg printf("===+++++ END OF SET GLUE  =============== \n");
  873. }
  874.  
  875. text_draw(long *in,int ilen)
  876. {
  877.     double cx,cy,p_hei,x,y;
  878.     int i,c,p_fnt;
  879.  
  880.     dbg gprint("---TEXT DRAW, ilen = %d \n",ilen);
  881.     dbg text_gprint(in,ilen);
  882.     cx = 0;
  883.     cy = 0;
  884.     dp g_get_xy(&cx,&cy);
  885.     dbg printf("Current x y, %g %g \n",cx,cy);
  886.     p_hei = 1;
  887.  
  888.     for (i=0;i<ilen;i++) {
  889.       switch (*(in+i)) {
  890.         case 1: /* char    font+char,wx      */
  891.         p_fnt = (*(in+ ++i) & 0xff00) / 0x100;
  892.                 font_load_metric(p_fnt);
  893.  
  894.         c = *(in+i) & 0x00ff;
  895.         g_set_bounds(cx+p_hei*((*(fnt[p_fnt].chr))[c].x1),cy+p_hei*((*(fnt[p_fnt].chr))[c].y1));
  896.         g_set_bounds(cx+p_hei*((*(fnt[p_fnt].chr))[c].x2),cy+p_hei*((*(fnt[p_fnt].chr))[c].y2));
  897.         dp {
  898.             g_move(cx,cy);
  899.             g_char(p_fnt,c);
  900.         }
  901.         cx += tofloat(*(in+ ++i));
  902.         break;
  903.         case 2: /* move    x,stretch,shrink */
  904.         cx += tofloat(*(in+ ++i));
  905.         i += 2;        /* glue is already set */
  906.         break;
  907.         case 3: /* move    x,0,0   SOLID     */
  908.         cx += tofloat(*(in+ ++i));
  909.         i += 2;
  910.         break;
  911.         case 4: /* move     x,y     SOLID     */
  912.         cx += tofloat(*(in+ ++i));
  913.         cy += tofloat(*(in+ ++i));
  914.         break;
  915.         case 5: /* Newline  x,y    (turned into a move) */
  916.         i += 2;
  917.         break;
  918.         case 6: /* rule     x,y         */
  919.         x = tofloat(*(in+ ++i));
  920.         y = tofloat(*(in+ ++i));
  921.         g_set_bounds(cx,cy);
  922.         g_set_bounds(cx+x,cy+y);
  923.         if (x>0) g_box_fill(cx,cy,cx+x,cy+y);
  924.         break;
  925.         case 7: /* color    color         */
  926. /*        dp g_set_color(tofloat(*(in+ ++i)));*/
  927.         break;
  928.         case 8: /* fontsz     sz        */
  929.         p_hei = tofloat(*(in+ ++i));
  930.         g_set_hei(p_hei);
  931.         break;
  932.         case 9: /* font    p_fnt    */
  933.         p_fnt = *(in+ ++i);
  934.                 font_load_metric(p_fnt);
  935.  
  936.         break;
  937.         case 10: /* Newline  x,y    (turned into a move) */
  938.         i += 2;
  939.         break;
  940.         case 20: /*  nop  */
  941.         break;
  942.         case 0:
  943.         dbg gprint("zero");
  944.         break;
  945.         default:
  946.         gprint("dud3 pcode in text pcode %d %d \n",*(in+i),i);
  947.         break;
  948.       }
  949.     }
  950.     text_endx = cx;
  951.     text_endy = cy;
  952.     dbg gprint("---TEXT DRAW, DONE. %g %g \n",cx,cy);
  953. }
  954. double tex_xend(void)
  955. {
  956.     return text_endx;
  957. }
  958. double tex_yend(void)
  959. {
  960.     return text_endy;
  961. }
  962. text_gprint(long *in,int ilen)
  963. {
  964.     double cx,cy,p_hei,x,y;
  965.     int i,c,p_fnt,z;
  966.  
  967.      for (i=0;i<ilen;i++) printf("%lx ",*(in+i));
  968.     printf("\n");
  969.     z=0;
  970.     printf("# ");
  971.     for (i=0;i<ilen;i++) {
  972.       switch (*(in+i)) {
  973.         case 1: /* char    font+char,wx      */
  974.         p_fnt = (*(in+ ++i) & 0xff00) / 0x100;
  975.                 font_load_metric(p_fnt);
  976.  
  977.         c = *(in+i) & 0x00ff;
  978.         x = tofloat(*(in+ ++i));
  979.         printf("%c[%3.3g]",c,x);
  980.     /*    printf("%c{%d %3.3f} ",c,p_fnt,tofloat(*(in+ ++i)));  */
  981.         break;
  982.         case 2: /* move    x,stretch,shrink */
  983.         printf("[sp %3.3f %3.3f %3.3f] \n# ",tofloat(*(in+1+i))
  984.                 ,tofloat(*(in+2+i)),tofloat(*(in+3+i)));
  985.         i += 3;
  986.         break;
  987.         case 3: /* move    x,0,0   SOLID     */
  988.         printf("(3 %3.3f %3.3f %3.3f) \n# ",tofloat(*(in+1+i))
  989.                 ,tofloat(*(in+2+i)),tofloat(*(in+3+i)));
  990.         i += 3;
  991.         break;
  992.         case 4: /* move     x,y     SOLID     */
  993.         printf("(4 %3.3f %3.3f) \n# ",tofloat(*(in+1+i))
  994.                 ,tofloat(*(in+2+i)));
  995.         i += 2;
  996.         break;
  997.         case 5: /* Newline  x,y    (turned into a move) */
  998.         i += 2;
  999.         printf("5 \n# ");
  1000.         break;
  1001.         case 6: /* rule     x,y         */
  1002.         printf("(rule %3.3f %3.3f) \n# ",tofloat(*(in+1+i))
  1003.                 ,tofloat(*(in+2+i)));
  1004.         i += 2;
  1005.         break;
  1006.         case 7: /* color    color         */
  1007.         printf("(color %x) \n# ",(*(in+ ++i)));
  1008.         break;
  1009.         case 8: /* fontsz     sz        */
  1010.         printf("(p_hei %3.3f) \n# ",tofloat(*(in+ ++i)));
  1011.         break;
  1012.         case 9: /* font    p_fnt    */
  1013.         printf("(font %d) \n",(*(in+ ++i)));
  1014.         break;
  1015.         case 10: /* Newline  x,y    (turned into a move) */
  1016.         i += 2;
  1017.         printf("\n10(paragraph)\n# ");
  1018.         break;
  1019.         case 20: /*  nop  */
  1020.         printf("NOP ");
  1021.         break;
  1022.         default:
  1023.         printf("(err=%4x pos=%d)\n ",*(in+i),i);
  1024.         break;
  1025.       }
  1026.     }
  1027.     printf("\n");
  1028. }
  1029. double lineskip1,parskip1;
  1030. font_reset_parskip()
  1031. {
  1032.     lineskip1 = 1.0;
  1033.     parskip1 = 2.5;
  1034. }
  1035. set_parskip(double v)
  1036. {
  1037.     parskip1 = v;
  1038. }
  1039. set_lineskip(double v)
  1040. {
  1041.     lineskip1 = v;
  1042. }
  1043. font_get_lineskip(double *ls,double *gap)
  1044. {
  1045.     *ls = p_hei * lineskip1;
  1046.     *gap = *ls * .1 + linegap;
  1047. }
  1048. font_get_parskip(double *ls,double *gap)
  1049. {
  1050.     *ls = p_hei * parskip1;
  1051.     *gap = *ls * .1;
  1052. }
  1053.  
  1054. int pass_font(char *p)
  1055. {
  1056.     int i,f=0,etype=1;
  1057.     long j;
  1058.     char u[90];
  1059.     char vv[80],*s;
  1060.     double xx;
  1061.  
  1062.     s = &u[0];
  1063.     strncpy(u,p,90);
  1064.     strupr(u);
  1065.     if ( (*s=='"')  || (strchr(s,'$') != NULL)) {
  1066.         strcpy(vv,"cvtfont(");
  1067.         strcat(vv,s); strcat(vv,")");
  1068.         polish_eval(vv,&xx);
  1069.         memcpy(&j,&xx,sizeof(long));
  1070.         return j;  /* actyally is an int */
  1071.     } else {
  1072.         if (nfnt==0) font_load();
  1073.         for (i=1; i<=nfnt; i++) {
  1074.             if (fnt[i].name!=NULL) if (strcmp(fnt[i].name,u)==0) {
  1075.               return i;
  1076.             }
  1077.         }
  1078.         gprint("Invalid font name {%s}, NFNT %d expecting one of: \n    ",u,nfnt);
  1079.         for (i=1;i<=nfnt; i++) {
  1080.             if (fnt[i].name!=NULL)
  1081.                 gprint("  {%s} ",fnt[i++].name);
  1082.             if (fnt[i].name!=NULL)
  1083.                 gprint("  {%s} ",fnt[i++].name);
  1084.             if (fnt[i].name!=NULL)
  1085.                 gprint("  {%s} ",fnt[i++].name);
  1086.             if (fnt[i].name!=NULL)
  1087.                 gprint("  {%s} \n",fnt[i].name);
  1088.         }
  1089.         return 1;     /* default font number */
  1090.     }
  1091. }
  1092. #define get_exps(ss) polish(ss,(char *) pcode,plen,&etype)
  1093. #define tok(n)  (*tk)[n]
  1094. get_font(char (*(*tk)[500]),int *ntok,int *curtok,long *pcode,int *plen)
  1095. {
  1096.     int i,f=0,etype=1;
  1097.     char vv[80];
  1098.     char *p;
  1099.     if (nfnt==0) font_load();
  1100.  
  1101.     if ( (*tok(*curtok)=='"') ||  (strchr(tok(*curtok),'$') != NULL) ) {
  1102.         strcpy(vv,"cvtfont(");
  1103.         strcat(vv,tok(*curtok)); strcat(vv,")");
  1104.         get_exps(vv);
  1105.         (*curtok)++;
  1106.         return;
  1107.     }
  1108.  
  1109.     p = (*tk)[*curtok];
  1110.     (*curtok)++;
  1111.     *(pcode+(*plen)++) = 8;
  1112.     for (i=1; i<=nfnt; i++) {
  1113.         if (fnt[i].name!=NULL) if (strcmp(fnt[i].name,p)==0) {
  1114.           *(pcode+(*plen)++) = i;     /* font number */
  1115.           return;
  1116.         }
  1117.     }
  1118.     gprint("Invalid font name {%s}, expecting one of: \n    ",p);
  1119.     for (i=1;i<=nfnt; i++) {
  1120.         if (fnt[i].name!=NULL)
  1121.             gprint("  {%s} ",fnt[i++].name);
  1122.         if (fnt[i].name!=NULL)
  1123.             gprint("  {%s} ",fnt[i++].name);
  1124.         if (fnt[i].name!=NULL)
  1125.             gprint("  {%s} ",fnt[i++].name);
  1126.         if (fnt[i].name!=NULL)
  1127.             gprint("  {%s} \n",fnt[i].name);
  1128.     }
  1129.     *(pcode+(*plen)++) = 1;     /* default font number */
  1130. }
  1131. text_block(uchar *s,double width,int justify)
  1132. {
  1133.     double ox,oy,x,y,ll,rr,uu,dd;
  1134.     double a,b,c,d;
  1135.  
  1136.     set_base_size();
  1137.     g_get_bounds(&a,&b,&c,&d);
  1138.     g_init_bounds();
  1139.     dont_print = true;
  1140.     fftext_block(s,width,justify);
  1141.     dont_print = false;
  1142.     g_get_bounds(&ll,&dd,&rr,&uu);
  1143.     if (ll > rr) {ll=0; rr=0; uu=0; dd=0;}
  1144.     g_get_xy(&ox,&oy);
  1145.     x = ox; y = oy;
  1146.     g_dotjust(&x,&y,ll,rr,uu,dd,justify);
  1147.     g_move(x,y);
  1148.     g_init_bounds();
  1149.     if (a<=c) {
  1150.         g_set_bounds(a,b);
  1151.         g_set_bounds(c,d);
  1152.     }
  1153.     g_get_bounds(&a,&b,&c,&d);
  1154.     text_draw(gt_pbuff,gt_plen);
  1155.     g_get_bounds(&a,&b,&c,&d);
  1156.     g_move(ox,oy);
  1157. }
  1158. /*----------------------------------------------------------------------*/
  1159. /* Searches CMD and replaces #n's with parameters */
  1160. char *tex_replace(char *cmd,char *pm[],int pmlen[],int npm)
  1161. {
  1162.     char *r,*s,*o;
  1163.     int n;
  1164.  
  1165.     if (strchr(cmd,'#')==0) return sdup(cmd);
  1166.     r = myalloc(1000);
  1167.     o = r;
  1168.     for (s=cmd; *s!=0; s++) {
  1169.         if (*s=='#') {
  1170.             n = *(++s) - '0';
  1171.             if (n>0 && n<=npm) {
  1172.                 ncat(o,pm[n-1],pmlen[n-1]);
  1173.                 o += pmlen[n-1];
  1174.             }
  1175.         } else *o++ = *s;
  1176.     }
  1177.     return r;
  1178. }
  1179.  
  1180. /*----------------------------------------------------------------------*/
  1181. /*         tex_chardef                        */
  1182. /*----------------------------------------------------------------------*/
  1183. tex_chardef(int c, char *defn)    /* Defines single char as string */
  1184. {
  1185.     if (c<0 || c>255) return;
  1186.     if (cdeftable[c]!=NULL) myfree(cdeftable[c]);
  1187.     cdeftable[c] = sdup(defn);
  1188. }
  1189. char *tex_findchardef(int c)
  1190. {
  1191.     return cdeftable[c];
  1192. }
  1193.  
  1194. /*----------------------------------------------------------------------*/
  1195. /*         Hashing table code for \def                 */
  1196. /*----------------------------------------------------------------------*/
  1197. #define HASHSIZE 101
  1198.  
  1199. static deftable  *def_hashtab[HASHSIZE];
  1200.  
  1201. unsigned hash_str(char *s);
  1202. unsigned hash_str(char *s)
  1203. {
  1204.     unsigned hashval;
  1205.  
  1206.     for (hashval=0; *s != 0; s++)
  1207.         hashval = *s + 31*hashval;
  1208.     return hashval % HASHSIZE ;
  1209. }
  1210.  
  1211. deftable *tex_finddef(char *s)
  1212. {
  1213.     deftable  *np;
  1214.  
  1215.     for (np = def_hashtab[hash_str(s)]; np != NULL; np = np->next)
  1216.         if (strcmp(s, np->name) == 0) {
  1217.             return np;
  1218.         }
  1219.     return NULL;
  1220. }
  1221.  
  1222. tex_def(char *name, char *defn,int npm)
  1223. {
  1224.     deftable  *np;
  1225.     char **s;
  1226.     unsigned hashval;
  1227.  
  1228.     if ((np = tex_finddef(name)) == NULL) { /* not found */
  1229.         np = (deftable  *) myalloc(sizeof(*np));
  1230.         if ((np == NULL) || (np->name = sdup(name)) == NULL)
  1231.             return NULL;
  1232.         hashval = hash_str(name);
  1233.         np->next = def_hashtab[hashval];
  1234.         def_hashtab[hashval] = np;
  1235.         np->npm = npm;
  1236.         if ((np->defn = sdup(defn)) == NULL) return NULL;
  1237.     } else {
  1238.         myfree(np->defn);
  1239.         if ((np->defn = sdup(defn)) == NULL) return NULL;
  1240.     }
  1241.     return true;
  1242. }
  1243. /*----------------------------------------------------------------------*/
  1244. /*         Hashing table code for \mathchardef            */
  1245. /*----------------------------------------------------------------------*/
  1246. struct mdef_table_struct {
  1247.     struct mdef_table_struct  *next;
  1248.     char *name;
  1249.     int defn;
  1250. };
  1251. typedef struct mdef_table_struct mdeftable;
  1252.  
  1253. static mdeftable  *mdef_hashtab[HASHSIZE];
  1254.  
  1255. int *tex_findmathdef(char *s)
  1256. {
  1257.     mdeftable  *np;
  1258.  
  1259.     for (np = mdef_hashtab[hash_str(s)]; np != NULL; np = np->next)
  1260.         if (strcmp(s, np->name) == 0) {
  1261.             return &np->defn;
  1262.         }
  1263.     return NULL;
  1264. }
  1265.  
  1266. tex_mathdef(char *name, int defn)
  1267. {
  1268.     mdeftable  *np;
  1269.     int *d;
  1270.     unsigned hashval;
  1271.  
  1272.     if ((d = tex_findmathdef(name)) == NULL ) { /* not found */
  1273.         np = (mdeftable  *) myalloc(sizeof(*np));
  1274.         if ((np == NULL) || (np->name = sdup(name)) == NULL)
  1275.             return NULL;
  1276.         hashval = hash_str(name);
  1277.         np->next = mdef_hashtab[hashval];
  1278.         mdef_hashtab[hashval] = np;
  1279.         np->defn = defn;
  1280.     } else {
  1281.         *d = defn;
  1282.     }
  1283.     return true;
  1284. }
  1285. tex_init()
  1286. {
  1287.     int i;
  1288.     for (i=0;i<256;i++) chr_val[i]=i;
  1289.     for (i=0;i<256;i++) chr_code[i]=10;    /* other */
  1290.     for (i=65;i<91;i++) chr_code[i]=1;    /* alpha */
  1291.     for (i=97;i<123;i++) chr_code[i]=1;
  1292.     chr_code[0] = 2; /* maybe should be 0,  this is only tested in lig*/
  1293.     chr_code[' '] = 2;
  1294.     chr_code[9] = 2;
  1295.     chr_code['\n'] = 2;
  1296.     chr_code['\\'] = 6;
  1297.     chr_code['{'] = 7;
  1298.     chr_code['}'] = 8;
  1299.     chr_code[255] = 11;    /* flag for end of paragraph, unless verbatim */
  1300.     chr_init = true;
  1301.     tex_preload();
  1302.     tex_def(" ","\\movexy{1sp}{}",0);
  1303.     tex_def("\\","\\newline",0);
  1304.     tex_def("{","\\char{123}",0);
  1305.     tex_def("}","\\char{125}",0);
  1306.     tex_def("_","\\char{95}",0);
  1307.     /* tex_def("^","\\char{94}",0); */
  1308.     tex_def("$","\\char{36}",0);
  1309. }
  1310. tex_clear()
  1311. {
  1312.     /* clear CHARDEF table before each redraw */
  1313.  
  1314.     int c;
  1315.     for (c=1;c<255;c++) {
  1316.         if (cdeftable[c]!=NULL) {
  1317.             myfree(cdeftable[c]);
  1318.             cdeftable[c] = NULL;
  1319.         }
  1320.     }
  1321.     tex_chardef('^',"\\sup ");
  1322.     tex_chardef('_',"\\sub ");
  1323. }
  1324. g_measure(char *s, double *l, double *r, double *u, double *d)
  1325. {
  1326.     double sa,sb,sc,sd;
  1327.     g_get_bounds(&sa,&sb,&sc,&sd);
  1328.     set_base_size();
  1329.     g_init_bounds();
  1330.     dont_print = true;
  1331.     fftext_block(s,0.0,0);
  1332.     dont_print = false;
  1333.     g_get_bounds(l,d,r,u);
  1334.     if (*l > *r) {*l=0; *r=0; *u=0; *d=0;}
  1335.     gt_l = *l;
  1336.     gt_r = *r;
  1337.     gt_u = *u;
  1338.     gt_d = *d;
  1339.     g_init_bounds();
  1340.     if (sa>sc) return;
  1341.     g_set_bounds(sa,sb);
  1342.     g_set_bounds(sc,sd);
  1343. }
  1344. g_textfindend(char *s, double *cx, double *cy)
  1345. {
  1346.     double sa,sb,sc,sd;
  1347.     set_base_size();
  1348.     g_get_bounds(&sa,&sb,&sc,&sd);
  1349.     dont_print = true;
  1350.     fftext_block(s,0.0,0);
  1351.     *cx = text_endx;
  1352.     *cy = text_endy;
  1353.     dont_print = false;
  1354.     g_init_bounds();
  1355.     if (sa>sc) return;
  1356.     g_set_bounds(sa,sb);
  1357.     g_set_bounds(sc,sd);
  1358. }
  1359. g_jtext(int just)
  1360. {
  1361.     double ox,oy,x,y;
  1362.     g_get_xy(&ox,&oy);
  1363.     x = ox; y = oy;
  1364.     g_dotjust(&x,&y,gt_l,gt_r,gt_u,gt_d,just);
  1365.     g_move(x,y);
  1366.     text_draw(gt_pbuff,gt_plen);
  1367.     g_move(ox,oy);
  1368. }
  1369. static uchar tbuff[8000];
  1370. text_def(uchar *s)
  1371. {
  1372.     gt_plen = 0;
  1373.     if (chr_init==false) tex_init();
  1374.     text_topcode(s,gt_pbuff,>_plen);
  1375. }
  1376. fftext_block(uchar *s,double width,int justify)
  1377. {
  1378.     uchar *t,*r,*m,*p;
  1379.     int i;
  1380.  
  1381.     g_get_font(&p_fnt);
  1382.     font_load_metric(p_fnt);
  1383.  
  1384.     g_get_hei(&p_hei);
  1385.     font_reset_parskip();
  1386.     gt_plen = 0;
  1387.     if (s==NULL) {
  1388.         dbg gprint("TEXT_BLOCK, Passed NULL pointer \n");
  1389.         return;
  1390.     }
  1391.     if (*s==0) {
  1392.         /* gprint("TEXT_BLOCK, Passed empty string \n"); */
  1393.         return;
  1394.     }
  1395.     if (chr_init==false) tex_init();
  1396. lp:
  1397.  
  1398.     t = strstr(s,"\n\n");    /* search for cr,cr              */
  1399.     if (t!=NULL) {
  1400.         *(t+1) = 255;     /* flag end of paragraph */
  1401.         goto lp;
  1402.     }
  1403.     text_tomacro(s,tbuff);
  1404.     gt_plen = 0;
  1405.     if (width==0) {
  1406.         width = 400;
  1407.         chr_code['\n'] = 5;
  1408.     } else chr_code['\n'] = 2;
  1409.     text_topcode(tbuff,gt_pbuff,>_plen);
  1410.     text_wrapcode(gt_pbuff,gt_plen,width);
  1411.     text_draw(gt_pbuff,gt_plen);
  1412.  
  1413.  
  1414.     g_set_font(p_fnt);
  1415.     g_set_hei(p_hei);
  1416.  
  1417.  
  1418. /*    dbg gprint("text to macro {%s} {%s} \n",s,tbuff);
  1419.     dbg gprint("============topcode \n");
  1420.     dbg gprint("P: ");
  1421.     for (i=0;i<plen;i++) {
  1422.         dbg gprint("%4x ",pbuff[i]);
  1423.         if ((i+1)/10==(i+1)/10.0) dbg gprint("\nP: ");
  1424.     }
  1425.     dbg gprint("\n");
  1426.     dbg text_gprint(pbuff,plen);
  1427.     dbg gprint("\n");
  1428.     dbg gprint("==== ====       ==== ==== wrapcode \n");
  1429.     dbg gprint("\n");
  1430.     dbg gprint("==== ====       ==== ==== draw \n");
  1431. */
  1432. }
  1433. cmd_token(uchar **in,char *cmdstr)
  1434. {
  1435.     int gcnt,i;
  1436.     char *s;
  1437.     s = cmdstr;
  1438.     i=0;
  1439.     if ( (!isalpha(**in)) && (**in != 0)) {
  1440.         *cmdstr++ = *(*in)++;
  1441.     } else {
  1442.         for (; chr_code[**in]==1 && **in != 0 && i<20;(*in)++,i++)  {
  1443.             *cmdstr++ = **in;
  1444.         }
  1445.     }
  1446.     *cmdstr = 0;
  1447.     cmdstr -= 1;
  1448.     if (chr_code[*cmdstr]==1) {
  1449.         for (;(**in != 0) && (chr_code[**in]==2);) (*in)++;
  1450.     }
  1451. }
  1452. text_tomacro(uchar *in, uchar *out)
  1453. {
  1454.     /* find /cmdname  or defined characters */
  1455.     static char macroname[30];
  1456.     uchar *s,*dfn,*r,*saves;
  1457.     int changed,dlen;
  1458.     int nrep,j;
  1459.     deftable  *np;
  1460.     static union {char *s[10]; uchar *u[10];} pm;
  1461.     static int pmlen[10];
  1462.  
  1463.     nrep = 0;
  1464.     strcpy(out,in);
  1465.     for (s=out; *s != 0;s++)  {
  1466.       if (nrep>300) gle_abort("Loop in text macros\n");
  1467.       if (chr_code[*s]==6) {    /* backslash, begining of macro? */
  1468.         saves = s;
  1469.         s++;
  1470.         cmd_token(&s,macroname);
  1471.         np = tex_finddef(macroname);
  1472.         if (np != NULL) {
  1473.             nrep++;
  1474.             dfn = np->defn;
  1475.             dbg printf("Found macro {%s} \n",macroname);
  1476.             cmd_param(&s,pm.u,pmlen,np->npm);
  1477.             dlen = s-saves;
  1478.             r = tex_replace(dfn,pm.s,pmlen,np->npm);
  1479.             /* printf("Replace text {%s} dlen %d \n",r,dlen); */
  1480.             s = saves;
  1481.             memmove(s+strlen(r),s+dlen,strlen(s)+1);
  1482.             strncpy(s,r,strlen(r));
  1483.             myfree(r);
  1484.             s--;
  1485.         }
  1486.         s = saves;
  1487.       }
  1488.       if (cdeftable[*s]!=0) {
  1489.         dbg printf("Found char definition %d  {%s} \n",*s,s);
  1490.         nrep++;
  1491.         dfn = tex_findchardef(*s);
  1492.         memmove(s+strlen(dfn)-1,s,strlen(s)+1);
  1493.         strncpy(s,dfn,strlen(dfn));
  1494.         s--;
  1495.       }
  1496.     }
  1497.     dbg printf("MACOR IN {%s} \n",in);
  1498.     dbg printf("MACOR CODE {%s} \n",out);
  1499. }
  1500. tex_presave()
  1501. {
  1502.     int i;
  1503.     deftable *dt;
  1504.     FILE *fout;
  1505.     mdeftable *mdt;
  1506.     char *workarea;
  1507.     /* Save all defined features possible */
  1508.     fout = fopen(gledir("inittex.ini"),WRITE_BIN);
  1509.     if (fout==NULL) gprint("Could not open inittex.ini file \n");
  1510.     fwrite(fontfam,sizeof(int),16*4,fout);
  1511.     fwrite(fontfamsz,sizeof(double),16*4,fout);
  1512.     fwrite(chr_mathcode,sizeof(char),256,fout);
  1513.  
  1514.     for (i=0;i<HASHSIZE;i++) {
  1515.       for (dt = def_hashtab[i]; dt != NULL; dt = dt->next) {
  1516.         fwrite(&i,sizeof(i),1,fout);
  1517.         fwrite(&dt->npm,sizeof(i),1,fout);
  1518.         fsendstr(dt->name,fout);
  1519.         fsendstr(dt->defn,fout);
  1520.       }
  1521.     }
  1522.     i = 0x0fff; fwrite(&i,sizeof(i),1,fout);
  1523.     for (i=0;i<HASHSIZE;i++) {
  1524.       for (mdt = mdef_hashtab[i]; mdt != NULL; mdt = mdt->next) {
  1525.         fwrite(&i,sizeof(i),1,fout);
  1526.         fwrite(&mdt->defn,sizeof(i),1,fout);
  1527.         fsendstr(mdt->name,fout);
  1528.       }
  1529.     }
  1530.     i = 0x0fff; fwrite(&i,sizeof(i),1,fout);
  1531.     for (i=0;i<256;i++)  fsendstr(cdeftable[i],fout);
  1532.     fclose(fout);
  1533. }
  1534. /*----------------------------------------------------------------------*/
  1535. fgetvstr(char **s,FILE *fmt)
  1536. {
  1537.     int i;
  1538.     i = fgetc(fmt);
  1539.     if (i==0) return;
  1540.     *s = myalloc(i+1);
  1541.     fread(*s,1,i,fmt);
  1542.     *(*s+i) = 0;
  1543. }
  1544. fgetcstr(char s[],FILE *fmt)
  1545. {
  1546.     int i;
  1547.     i = fgetc(fmt);
  1548.     if (i==0) return;
  1549.     fread(s,1,i,fmt);
  1550.     s[i] = 0;
  1551. }
  1552. fsendstr(char *s,FILE *fout)
  1553. {
  1554.     if (s==NULL) {
  1555.         fputc(0,fout);
  1556.         return;
  1557.     }
  1558.     fputc(strlen(s),fout);
  1559.     fwrite(s,1,strlen(s),fout);
  1560. }
  1561. tex_preload()
  1562. {
  1563.     int i,j;
  1564.     deftable *dt;
  1565.     FILE *fout;
  1566.     mdeftable *mdt;
  1567.     char *workarea;
  1568.     char str1[80],str2[80];
  1569.     /* reload all defined features */
  1570.     fout = fopen(gledir("inittex.ini"),READ_BIN);
  1571.     if (fout==NULL) {gprint("Could not open inittex.ini file \n"); return;}
  1572.     fread(fontfam,sizeof(int),16*4,fout);
  1573.     fread(fontfamsz,sizeof(double),16*4,fout);
  1574.     fread(chr_mathcode,sizeof(char),256,fout);
  1575.  
  1576.     for (;    (fread(&i,sizeof(i),1,fout)), i != 0x0fff;) {
  1577.         fread(&j,sizeof(j),1,fout);
  1578.         fgetcstr(str1,fout); fgetcstr(str2,fout);
  1579.         tex_def(str1,str2,j);
  1580.     }
  1581.     for (;    (fread(&i,sizeof(i),1,fout)), i != 0x0fff;) {
  1582.         fread(&j,sizeof(j),1,fout);
  1583.         fgetcstr(str1,fout);
  1584.         tex_mathdef(str1,j);
  1585.     }
  1586.  
  1587.     for (i=0;i<256;i++)  fgetvstr(&cdeftable[i],fout);
  1588.     fclose(fout);
  1589. }
  1590.