home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / dev / genepic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-10  |  29.8 KB  |  1,214 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation. The authors make no representations about the suitability 
  11.  * of this software for any purpose.  It is provided "as is" without express 
  12.  * or implied warranty.
  13.  *
  14.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  */
  23.  
  24. /*
  25.  * genepic.c: (E)EPIC driver for fig2dev
  26.  *
  27.  * Converted from fig2epic 5/89 by Micah Beck
  28.  */
  29. /*==================================================================*/
  30. /*    fig2epic (Fig to EPIC converter)                 */
  31. /*         Version 1.1d <March 30, 1988>                */
  32. /*                                    */
  33. /*    Written by Conrad Kwok, Division of Computer Science, UCD   */
  34. /*                                    */
  35. /*    Permission is granted for freely distribution of this file  */
  36. /*        provided that this message is included.            */
  37. /*==================================================================*/
  38.  
  39. /*====================================================================
  40.   Changes:
  41.  
  42.   Version 1.0d:<September 18, 1988>
  43.   1. Add the option -P for Page mode. Two more configurable parameter---
  44.      Preamble and Postamble.
  45.  
  46.   Version 1.1a: <January 18, 1989>
  47.   1. Fix the bug in closed control splines. The routine convertCS(p) is being
  48.      called once too often.
  49.  
  50.   2. Add supports to Variable line width
  51.   3. Add supports to black, white or shaded area fill.
  52.  
  53.   Version 1.1b: <Febrary 2, 1989>
  54.   1. Draw outline for area-filled figures when using dvips.
  55.  
  56.   Version 1.1c: <Febrary 7, 1989>
  57.   1. Supports all 5 gray level in area fill.
  58.  
  59.   Version 1.1d: <March 30, 1989>
  60.   1. Add supports for Gould NP1 (Bsd4.3) (Recieve the changes from
  61.         mcvax!presto.irisa.fr!hleroy@uunet.uu.net. Sorry
  62.         I don't have his/her name)
  63.   2. Add exit(0) before exit in the main.
  64. ====================================================================*/
  65.  
  66.   
  67. #include <stdio.h>
  68. #include <math.h>
  69. #include <varargs.h>
  70. #include <ctype.h>
  71. #include "object.h"
  72. #include "fig2dev.h"
  73. #include "texfonts.h"
  74. #include "pi.h"
  75.  
  76. #ifdef MSDOS
  77. #define getopt egetopt
  78. #define M_PI 3.14159265358979324
  79. #endif
  80.  
  81. #define DrawOutLine
  82. #ifdef DrawOutLine
  83. int OutLine=0;
  84. #endif
  85.  
  86. #define TopCoord 840        /* 10.5 in * 80 (DPI)            */
  87.                 /* Actually, it can be any value */
  88. #define PtPerLine 3
  89. #define ThinLines 0
  90. #define ThickLines 1
  91. #define FALSE 0
  92. #define TRUE 1
  93. #define Epic 0
  94. #define EEpic_emu 1
  95. #define EEpic 2
  96. #define None 0
  97. #define SolidLineBox 1
  98. #define DashLineBox 2
  99. #define BothBoxType 3
  100. #define Normal 0
  101. #define Economic 1
  102. #define DottedDash 2
  103.  
  104. void genepic_ctl_spline(), genepic_int_spline(); 
  105. void genepic_open_spline(), genepic_closed_spline(); 
  106.  
  107. /* Structure for Point with "double" values */
  108. struct fp_struct {
  109.     double x,y;
  110. };
  111.  
  112. typedef struct fp_struct FPoint;
  113.  
  114. /* Local to the file only */
  115. static int coord_system;
  116. static int CoordSys = 2;
  117. static double Threshold;
  118. static int DPI;
  119. static int CurWidth = 0;
  120. static int LineStyle = SOLID_LINE;
  121. static int LLX = 0, LLY = 0;
  122. static char *LnCmd;
  123. static int MaxCircleRadius;
  124. static double DashLen;
  125. static int PageMode = FALSE;
  126. static int PatternType=UNFILLED;
  127. static struct {
  128.     double mag;
  129.     int size;
  130. } ScaleTbl[5] = {
  131.     { 0.6667, 8 },
  132.     { 0.75  , 9 },
  133.     { 0.8333, 10 },
  134.     { 0.9167, 11 },
  135.     { 1.0   , 12 }
  136. };
  137.  
  138. /* Definition of Keywords for some of the configurable parameter */
  139. char *Tlangkw[] = { /* The order must match the definition of corr. constants */
  140.     "Epic", "EEpicemu", "EEpic", NULL
  141. };
  142.  
  143. char *EllCmdkw[] = {
  144.     "ellipse", "oval", NULL
  145. };
  146.  
  147. char *EllCmdstr[] = {
  148.     "\\%s%s{%d}{%d}}\n", "\\%s%s(%d,%d)}\n"
  149. };
  150.  
  151. char *FillCommands[] = {
  152.     "", "\\whiten",
  153.     "\\shade", "\\shade", "\\shade",
  154.     "\\shade", "\\shade", "\\shade",
  155.     "\\shade", "\\shade", "\\shade",
  156.     "\\shade", "\\shade", "\\shade",
  157.     "\\shade", "\\shade", "\\shade",
  158.     "\\shade", "\\shade", "\\shade",
  159.     "\\shade", "\\blacken"
  160. };
  161.  
  162. #define TEXT_LINE_SEP '\n'
  163. /* The following two arrays are used to translate characters which
  164.    are special to LaTeX into characters that print as one would expect.
  165.    Note that the <> characters aren't really special LaTeX characters
  166.    but they will not print as themselves unless one is using a font
  167.    like tt. */
  168. char latex_text_specials[] = "\\{}><^~$&#_%";
  169. char *latex_text_mappings[] = {
  170.   "$\\backslash$",
  171.   "$\\{$",
  172.   "$\\}$",
  173.   "$>$",
  174.   "$<$",
  175.   "\\^{}",
  176.   "\\~{}",
  177.   "\\$",
  178.   "\\&",
  179.   "\\#",
  180.   "\\_",
  181.   "\\%"};
  182.  
  183.  
  184. /* Configurable parameters */
  185. int LowerLeftX=0, LowerLeftY=0;
  186. double SegLen = 0.0625; /* inch */
  187. int Verbose = FALSE;
  188. int TopMargin = 5;
  189. int BottomMargin = 10;
  190. int DotDist = 5;
  191. int LineThick = 2;
  192. int TeXLang = EEpic;
  193. double DashScale=1;
  194. int EllipseCmd=0;
  195. int UseBox=None;
  196. int DashType=Normal;
  197. char *Preamble="\\documentstyle[epic,eepic]{article}\n\\begin{document}\n\\begin{center}\n";
  198. char *Postamble="\\end{center}\n\\end{document}\n";
  199. int VarWidth=FALSE;
  200.  
  201. void genepic_option(opt, optarg)
  202. char opt, *optarg;
  203. {
  204.       int loop, i;
  205.  
  206.         switch (opt) {
  207.     case 'a':
  208.         fprintf(stderr, "warning: genepic option -a obsolete");
  209.         break;
  210.  
  211.     case 'f':
  212.         for ( i = 1; i <= MAX_FONT; i++ )
  213.         if ( !strcmp(optarg, texfontnames[i]) ) break;
  214.  
  215.         if ( i > MAX_FONT)
  216.         fprintf(stderr,
  217.             "warning: non-standard font name %s\n", optarg);
  218.     
  219.             texfontnames[0] = texfontnames[1] = optarg;
  220.         break;
  221.  
  222.         case 'l':
  223.             LineThick = atoi(optarg);
  224.             break;
  225.  
  226.     case 'L':
  227.         for (loop=0; loop < 3; loop++) {
  228.             if (stricmp(optarg, Tlangkw[loop]) == 0) break;
  229.         }
  230.         TeXLang = loop;
  231.         break;
  232.  
  233.  
  234.     case 'm':
  235.         break;
  236.  
  237.     case 'P':
  238.         PageMode = 1;
  239.         break;
  240.  
  241.     case 's':
  242.         font_size = atoi(optarg);
  243.         if (font_size <= 0 || font_size > MAXFONTSIZE) {
  244.         fprintf(stderr,
  245.             "warning: font size %d out of bounds\n", font_size);
  246.         }
  247.         break;
  248.  
  249.         case 'S':
  250.             loop = atoi(optarg);
  251.             if (loop < 8 || loop > 12) {
  252.                 put_msg("Scale must be between 8 and 12 inclusively\n");
  253.                 exit(1);
  254.             }
  255.             loop -= 8;
  256.             mag = ScaleTbl[loop].mag;
  257.             font_size = ScaleTbl[loop].size;
  258.             break;
  259.  
  260.         case 'v':
  261.             Verbose = TRUE;
  262.             break;
  263.  
  264.     case 'w':
  265.     case 'W':
  266.         VarWidth = opt=='W';
  267.         break;
  268.  
  269.     default:
  270.         put_msg(Err_badarg, opt, "epic");
  271.         exit(1);
  272.         break;
  273.         }
  274. }
  275.  
  276. static fconvertCS(fpt)
  277. FPoint *fpt;
  278. {
  279.     if (CoordSys) {
  280.         fpt->y = TopCoord - fpt->y;
  281.     }
  282.     fpt->x -= LLX;
  283.     fpt->y -= LLY;
  284. }
  285.  
  286. convertCS(pt)
  287. F_point *pt;
  288. {
  289.     if (CoordSys) {
  290.         pt->y = TopCoord - pt->y;
  291.     }
  292.     pt->x -= LLX;
  293.     pt->y -= LLY;
  294. }
  295.  
  296. void genepic_start(objects)
  297. F_compound *objects;
  298. {
  299.     int temp;
  300.     F_point pt1, pt2;
  301.     F_arc *arc;
  302.     F_compound *comp;
  303.     F_ellipse *ell;
  304.     F_line *line;
  305.     F_spline *spl;
  306.     F_text *text;
  307.  
  308.     texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size);
  309.  
  310.     switch (TeXLang) {
  311.     case Epic:
  312.         EllipseCmd = 1; /* Oval */
  313.         LnCmd = "drawline";
  314.         break;
  315.     case EEpic_emu:
  316.     case EEpic:
  317.         LnCmd = "path";
  318.         break;
  319.     default:
  320.         put_msg("Program error in main\n");
  321.         break;
  322.     }
  323.     if (PageMode) {
  324.         fputs(Preamble, stdout);
  325.     }
  326.  
  327.     DPI = objects->nwcorner.x;
  328.     if (DPI <= 0) {
  329.         put_msg("Resolution has to be positive. Default to 80!\n");
  330.         DPI = 80;
  331.     }
  332.     coord_system = objects->nwcorner.y;
  333.     switch (coord_system) {
  334.     case 1:
  335.         CoordSys = 0;
  336.         break;
  337.     case 2:
  338.         CoordSys = 1;
  339.         break;
  340.     default:
  341.         put_msg("Unknown Coordinate system -- %d\n", coord_system);
  342.         exit(1);
  343.     }
  344.     pt1.x = llx;
  345.     pt1.y = lly;
  346.     pt2.x = urx;
  347.     pt2.y = ury;
  348.     convertCS(&pt1);
  349.     convertCS(&pt2);
  350.     if (pt1.x > pt2.x) {
  351.         temp = pt1.x;
  352.         pt1.x = pt2.x;
  353.         pt2.x = temp;
  354.     }
  355.     if (pt1.y > pt2.y) {
  356.         temp = pt1.y;
  357.         pt1.y = pt2.y;
  358.         pt2.y = temp;
  359.     }
  360.     LLX = pt1.x - LowerLeftX;
  361.     LLY = pt1.y - LowerLeftY;
  362.     if (Verbose) {
  363.         fprintf(tfp, "%%\n%% Language in use is %s\n%%\n", Tlangkw[TeXLang]);
  364.     }
  365.     Threshold = 1.0 / DPI * mag;
  366.     fprintf(tfp, "\\setlength{\\unitlength}{%.4fin}\n", Threshold);
  367.     MaxCircleRadius = (int) (40 / 72.27 / Threshold);
  368.     Threshold = SegLen / Threshold;
  369.     define_setfigfont(tfp);
  370.     fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
  371.            pt2.x-pt1.x, pt2.y-pt1.y + TopMargin + BottomMargin,
  372.            LowerLeftX, LowerLeftY-BottomMargin);
  373. }
  374.  
  375. void genepic_end()
  376. {
  377.     fprintf(tfp, "\\end{picture}\n");
  378.     if (PageMode)
  379.         fputs(Postamble, stdout);
  380. }
  381.  
  382. static set_linewidth(w)
  383. int w;
  384. {
  385.     int old_width;
  386.  
  387.     if (w < 0) return;
  388.     old_width=CurWidth;
  389.     CurWidth = (w >= LineThick) ? (VarWidth ? w : ThickLines) : ThinLines;
  390.     if (old_width != CurWidth) {
  391.     if (CurWidth==ThinLines) {
  392.         fprintf(tfp, "\\thinlines\n");
  393.     } else if (VarWidth) {
  394.         fprintf(tfp, "\\allinethickness{%d}%%\n",w);
  395.     } else {
  396.         fprintf(tfp, "\\thicklines\n");
  397.     }
  398.     }
  399. }
  400.  
  401. set_pattern(type)
  402. int type;
  403. {
  404.     static unsigned long patterns[3][32] = {
  405.     { 0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
  406.       0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
  407.       0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
  408.       0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0},
  409.     { 0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
  410.       0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
  411.       0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
  412.       0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0},
  413.     { 0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
  414.       0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
  415.       0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
  416.       0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0}};
  417.     int count, loop1, loop2, i;
  418.  
  419.     if (type <= WHITE_FILL || type >= BLACK_FILL) return;
  420.     if (type != PatternType) {
  421.     PatternType=type;
  422.     i = ((int) PatternType - WHITE_FILL - 1) / 6;
  423.     fprintf(tfp, "\\texture{");
  424.     count=0;
  425.     for (loop1=4; loop1>0;) {
  426.         for (loop2=8; loop2>0; loop2--) 
  427.         fprintf(tfp, "%lx ", patterns[i][count++]);
  428.         if (--loop1 > 0)
  429.         fprintf(tfp, "\n\t");
  430.         else
  431.         fprintf(tfp, "}%\n");
  432.     }
  433.     }
  434. }
  435.  
  436. void genepic_line(line)
  437. F_line *line;
  438. {
  439.     F_point *p, *q;
  440.     int pt_count = 0, temp;
  441.     int boxflag = FALSE, llx, lly, urx, ury;
  442.     double dtemp;
  443.  
  444.     set_linewidth(line->thickness);
  445.     set_style(line->style, line->style_val);
  446.     p = line->points;
  447.     q = p->next;
  448.     convertCS(p);
  449.     if (q == NULL) {
  450.     fprintf(tfp, "\\drawline(%d,%d)(%d,%d)\n", p->x, p->y, p->x, p->y);
  451.     return;
  452.     }
  453.     if (line->type == T_ARC_BOX) { /* A box with rounded corners */
  454.       fprintf(stderr, "Arc box not implemented; substituting box.\n");
  455.       line->type = T_BOX;
  456.     }
  457.     if (line->type == T_BOX) {
  458.     if (Verbose) {
  459.         fprintf(tfp, "%%\n%% A box\n%%\n");
  460.     }
  461.     switch (LineStyle) {
  462.     case SOLID_LINE:
  463.         if (UseBox == BothBoxType || UseBox == SolidLineBox) {
  464.             boxflag = TRUE;
  465.         }
  466.         break;
  467.     case DASH_LINE:
  468.         if (UseBox == BothBoxType || UseBox == DashLineBox) {
  469.             boxflag = TRUE;
  470.         }
  471.         break;
  472.     }
  473.     if (boxflag) {
  474.         llx = urx = p->x;
  475.         lly = ury = p->y;
  476.         while (q != NULL) {
  477.             convertCS(q);
  478.             if (q->x < llx) {
  479.                 llx = q->x;
  480.             } else if (q->x > urx) {
  481.                 urx = q->x;
  482.             }
  483.             if (q->y < lly) {
  484.                 lly = q->y;
  485.             } else if (q->y > ury) {
  486.                 ury = q->y;
  487.             }
  488.             q = q->next;
  489.         }
  490.         switch(LineStyle) {
  491.         case SOLID_LINE:
  492.             fprintf(tfp, "\\put(%d,%d){\\framebox(%d,%d){}}\n",
  493.                 llx, lly, urx-llx, ury-lly);
  494.             break;
  495.         case DASH_LINE:
  496.         temp = (int) ((urx-llx) / DashLen);
  497.         dtemp = (double) (urx-llx) / temp;
  498.             fprintf(tfp, "\\put(%d,%d){\\dashbox{%4.3f}(%d,%d){}}\n",
  499.                 llx, lly, dtemp , urx-llx, ury-lly);
  500.             break;
  501.         default:
  502.             put_msg("Program Error! No other line styles allowed.\n");
  503.             break;
  504.         }
  505.         return;
  506.       }
  507.     }
  508.     set_pattern(line->area_fill);
  509.     convertCS(q);
  510.     if (line->back_arrow) {
  511.     draw_arrow_head(q, p, line->back_arrow->ht, line->back_arrow->wid);
  512.         if (Verbose) fprintf(tfp, "%%\n");
  513.     }
  514.     switch (LineStyle) {
  515.     case SOLID_LINE:
  516.     if (q->next != NULL && strcmp(LnCmd,"path")==0) {
  517.         if (line->area_fill < UNFILLED) line->area_fill = UNFILLED;
  518.         fprintf(tfp, "%s", FillCommands[line->area_fill]);
  519.     }
  520.     fprintf(tfp, "\\%s", LnCmd);
  521. #ifdef DrawOutLine
  522.     if (line->area_fill != UNFILLED && OutLine == 0) OutLine=1;
  523. #endif
  524.     break;
  525.     case DASH_LINE:
  526.         if ((TeXLang==Epic || TeXLang ==EEpic_emu) && DashType == Economic) {
  527.             fprintf(tfp, "\\drawline[-50]");
  528.         } else {
  529.         fprintf(tfp, "\\dashline{%4.3f}", DashLen);
  530.     }
  531.     break;
  532.     case DOTTED_LINE:
  533.     fprintf(tfp, "\\dottedline{%d}", DotDist);
  534.     break;
  535.     default:
  536.     fprintf(stderr,"Unknown Style\n");
  537.     exit(1);
  538.     }
  539.     fprintf(tfp, "(%d,%d)", p->x, p->y);
  540.     pt_count++;
  541.     while(q->next != NULL) {
  542.     if (++pt_count > PtPerLine) {
  543.         pt_count=1;
  544.         fprintf(tfp, "\n\t");
  545.     }
  546.     fprintf(tfp, "(%d,%d)", q->x, q->y);
  547.     p=q;
  548.     q = q->next;
  549.     convertCS(q);
  550.     }
  551.     fprintf(tfp, "(%d,%d)\n", q->x, q->y);
  552. #ifdef DrawOutLine
  553.     if (OutLine == 1) {
  554.     OutLine=0;
  555.     fprintf(tfp, "\\%s", LnCmd);
  556.     p=line->points;
  557.     pt_count=0;
  558.     q=p->next;
  559.     fprintf(tfp, "(%d,%d)", p->x, p->y);
  560.     pt_count++;
  561.     while(q->next != NULL) {
  562.         if (++pt_count > PtPerLine) {
  563.         pt_count=1;
  564.         fprintf(tfp, "\n\t");
  565.         }
  566.         fprintf(tfp, "(%d,%d)", q->x, q->y);
  567.         p=q;
  568.         q = q->next;
  569.     }
  570.     fprintf(tfp, "(%d,%d)\n", q->x, q->y);
  571.     }
  572. #endif
  573.     if (line->for_arrow) {
  574.     draw_arrow_head(p, q, line->for_arrow->ht, line->for_arrow->wid);
  575.         if (Verbose) fprintf(tfp, "%%\n");
  576.     }
  577. }
  578.  
  579. set_style(style, dash_len)
  580. int style;
  581. float dash_len;
  582. {
  583.     LineStyle = style;
  584.     if (LineStyle == DASH_LINE) {
  585.         switch (DashType) {
  586.         case DottedDash:
  587.             LineStyle = DOTTED_LINE;
  588.             break;
  589.         default:
  590.             DashLen = dash_len * DashScale;
  591.             break;
  592.         }
  593.     }
  594. }
  595.  
  596.  
  597. void genepic_spline(spl)
  598. F_spline *spl;
  599. {
  600.     set_linewidth(spl->thickness);
  601.     set_style(SOLID_LINE, 0.0);
  602.     if (int_spline(spl)) {
  603.     genepic_itp_spline(spl);
  604.     } else {
  605.     genepic_ctl_spline(spl);
  606.     }
  607. }
  608.  
  609. void genepic_ctl_spline(spl)
  610. F_spline *spl;
  611. {
  612.     if (closed_spline(spl)) {
  613.     genepic_closed_spline(spl);
  614.     } else {
  615.     genepic_open_spline(spl);
  616.     }
  617. }
  618.  
  619. static void genepic_open_spline(spl)
  620. F_spline *spl;
  621. {
  622.     F_point *p, *q, *r;
  623.     FPoint first, mid;
  624.     int pt_count = 0;
  625.  
  626.     p = spl->points;
  627.     q = p->next;
  628.     convertCS(p);
  629.     convertCS(q);
  630.     if (spl->back_arrow) {
  631.     draw_arrow_head(q, p, spl->back_arrow->ht, spl->back_arrow->wid);
  632.         if (Verbose) fprintf(tfp, "%%\n");
  633.     }
  634.     if (q->next == NULL) {
  635.     fprintf(tfp, "\\%s(%d,%d)(%d,%d)\n", LnCmd,
  636.            p->x, p->y, q->x, q->y);
  637.     return;
  638.     }
  639.     if (TeXLang == EEpic || TeXLang == EEpic_emu) {
  640.         fprintf(tfp, "\\spline(%d,%d)\n", p->x, p->y);
  641.         pt_count++;
  642.         while(q->next != NULL) {
  643.              if (++pt_count > PtPerLine) {
  644.                  pt_count=1;
  645.                  fprintf(tfp, "\n\t");
  646.              }
  647.              fprintf(tfp, "(%d,%d)", q->x, q->y);
  648.              p=q;
  649.              q = q->next;
  650.              convertCS(q);
  651.         }
  652.         fprintf(tfp, "(%d,%d)\n", q->x, q->y);
  653.     } else {
  654.         fprintf(tfp, "\\%s(%d,%d)\n", LnCmd, p->x, p->y);
  655.         r = q->next;
  656.         convertCS(r);
  657.         first.x = p->x;
  658.         first.y = p->y;
  659.         while (r->next != NULL) {
  660.             mid.x = (q->x + r->x) / 2.0;
  661.             mid.y = (q->y + r->y) / 2.0;
  662.             chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
  663.                             mid.x, mid.y);
  664.             first = mid;
  665.             q=r;
  666.             r = r->next;
  667.             convertCS(r);
  668.         }
  669.         chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
  670.                         (double) r->x, (double) r->y);
  671.         p=q;
  672.         q=r;
  673.     fprintf(tfp, "\n");
  674.     }
  675.     if (spl->for_arrow) {
  676.     draw_arrow_head(p, q, spl->for_arrow->ht, spl->for_arrow->wid);
  677.         if (Verbose) fprintf(tfp, "%%\n");
  678.     }
  679. }
  680.  
  681. static void genepic_closed_spline(spl)
  682. F_spline *spl;
  683. {
  684.     F_point *p;
  685.     double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  686.     double x1, y1, x2, y2;
  687.  
  688.     p = spl->points;
  689.     convertCS(p);
  690.     x1 = p->x;  y1 = p->y;
  691.     p = p->next;
  692.     convertCS(p);
  693.     x2 = p->x;  y2 = p->y;
  694.     cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
  695.     cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  696.     for (p = p->next; p != NULL; p = p->next) {
  697.     fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
  698.     x1 = x2;  y1 = y2;
  699.     convertCS(p);
  700.     x2 = p->x;  y2 = p->y;
  701.     cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  702.     cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  703.     quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  704.     fprintf(tfp, "\n");
  705.     cx1 = cx4;  cy1 = cy4;
  706.     cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  707.     }
  708.     x1 = x2;  y1 = y2;
  709.     p = spl->points->next;
  710.     x2 = p->x;  y2 = p->y;
  711.     cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  712.     cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  713.     fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
  714.     quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  715.     fprintf(tfp, "\n");
  716. }
  717.  
  718. chaikin_curve(a1, b1, a2, b2, a3, b3)
  719. double a1, b1, a2, b2, a3, b3;
  720. {
  721.     double xm1, xmid, xm2, ym1, ymid, ym2;
  722.  
  723.     if (fabs(a1-a3) < Threshold && fabs(b1-b3) < Threshold) {
  724.         fprintf(tfp, "\t(%.3f,%.3f)\n", a3, b3);
  725.     } else {
  726.         xm1 = (a1 + a2) / 2;
  727.         ym1 = (b1 + b2) / 2;
  728.         xm2 = (a2 + a3) / 2;
  729.         ym2 = (b2 + b3) / 2;
  730.         xmid = (xm1 + xm2) / 2;
  731.         ymid = (ym1 + ym2) / 2;
  732.         chaikin_curve(a1, b1, xm1, ym1, xmid, ymid);
  733.         chaikin_curve(xmid, ymid, xm2, ym2, a3, b3);
  734.     }
  735. }
  736.  
  737. static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  738. double    a1, b1, a2, b2, a3, b3, a4, b4;
  739. {
  740.     double    x1, y1, x4, y4;
  741.     double    xmid, ymid;
  742.  
  743.     x1 = a1; y1 = b1;
  744.     x4 = a4; y4 = b4;
  745.  
  746.     xmid = (a2 + a3) / 2;
  747.     ymid = (b2 + b3) / 2;
  748.     if (fabs(x1 - xmid) < Threshold && fabs(y1 - ymid) < Threshold) {
  749.     fprintf(tfp, "\t(%.3f,%.3f)\n", xmid, ymid);
  750.     } else {
  751.     quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  752.              ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  753.     }
  754.  
  755.     if (fabs(xmid - x4) < Threshold && fabs(ymid - y4) < Threshold) {
  756.     fprintf(tfp, "\t(%.3f,%.3f)\n", x4, y4);
  757.     } else {
  758.     quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  759.              ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  760.     }
  761. }
  762.  
  763. genepic_itp_spline(spl)
  764. F_spline *spl;
  765. {
  766.     F_point *p1, *p2;
  767.     FPoint pt1l, pt1r, pt2l, pt2r, tmpfpt;
  768.     F_control *cp1, *cp2;
  769.  
  770.     p1 = spl->points;
  771.     convertCS(p1);
  772.     cp1 = spl->controls;
  773.     pt1l.x = cp1->lx;
  774.     pt1l.y = cp1->ly;
  775.     pt1r.x = cp1->rx;
  776.     pt1r.y = cp1->ry;
  777.     fconvertCS(&pt1l);
  778.     fconvertCS(&pt1r);
  779.  
  780.     if (spl->back_arrow) {
  781.     tmpfpt.x = p1->x;
  782.     tmpfpt.y = p1->y;
  783.     fdraw_arrow_head(&pt1r, &tmpfpt, 
  784.         spl->back_arrow->ht, spl->back_arrow->wid);
  785.         if (Verbose) fprintf(tfp, "%%\n");
  786.     }
  787.  
  788.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  789.      p1 = p2, pt1r = pt2r, p2 = p2->next, cp2 = cp2->next) {
  790.     fprintf(tfp, "\\%s(%d,%d)", LnCmd, p1->x, p1->y);
  791.     convertCS(p2);
  792.     pt2l.x = cp2->lx;
  793.     pt2l.y = cp2->ly;
  794.     pt2r.x = cp2->rx;
  795.     pt2r.y = cp2->ry;
  796.     fconvertCS(&pt2l);
  797.     fconvertCS(&pt2r);
  798.     bezier_spline((double) p1->x, (double) p1->y,
  799.               pt1r.x, pt1r.y,
  800.               pt2l.x, pt2l.y,
  801.               (double) p2->x, (double) p2->y);
  802.     fprintf(tfp, "\n");
  803.     }
  804.  
  805.     if (spl->for_arrow) {
  806.     tmpfpt.x = p1->x;
  807.     tmpfpt.y = p1->y;
  808.     fdraw_arrow_head(&pt2l, &tmpfpt, 
  809.              spl->for_arrow->ht, spl->for_arrow->wid);
  810.     if (Verbose) fprintf(tfp, "%%\n");
  811.     }
  812. }
  813.  
  814. static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  815. double    a0, b0, a1, b1, a2, b2, a3, b3;
  816. {
  817.     double    x0, y0, x3, y3;
  818.     double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  819.  
  820.     x0 = a0; y0 = b0;
  821.     x3 = a3; y3 = b3;
  822.     if (fabs(x0 - x3) < Threshold && fabs(y0 - y3) < Threshold) {
  823.     fprintf(tfp, "\t(%.3f,%.3f)\n", x3, y3);
  824.     } else {
  825.     tx = (a1 + a2) / 2;        ty = (b1 + b2) / 2;
  826.     sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
  827.     sx2 = (sx1 + tx) / 2;    sy2 = (sy1 + ty) / 2;
  828.     tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
  829.     tx1 = (tx2 + tx) / 2;    ty1 = (ty2 + ty) / 2;
  830.     xmid = (sx2 + tx1) / 2;    ymid = (sy2 + ty1) / 2;
  831.  
  832.     bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  833.     bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  834.     }
  835. }
  836.  
  837. void genepic_ellipse(ell)
  838. F_ellipse *ell;
  839. {
  840.     F_point pt;
  841.  
  842.     set_linewidth(ell->thickness);
  843.     pt.x = ell->center.x;
  844.     pt.y = ell->center.y;
  845.     convertCS(&pt);
  846.     if (TeXLang == EEpic || TeXLang == EEpic_emu ||
  847.       ell->radiuses.x != ell->radiuses.y ||
  848.           ell->radiuses.x > MaxCircleRadius) {
  849.     set_pattern(ell->area_fill);
  850.         fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
  851. #ifndef OLDCODE
  852.         if (EllipseCmd == 0) {
  853.         if (ell->area_fill < UNFILLED) ell->area_fill = UNFILLED;
  854.         fprintf(tfp, "%s", FillCommands[ell->area_fill]);
  855. #  ifdef DrawOutLine
  856.         if (ell->area_fill != UNFILLED && OutLine == 0) OutLine = 1;
  857. #  endif
  858.         }
  859.      fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
  860.            2 * ell->radiuses.x, 2 * ell->radiuses.y);
  861. #  ifdef DrawOutLine
  862.     if (OutLine == 1) {
  863.         OutLine=0;
  864.             fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
  865.         fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
  866.            2 * ell->radiuses.x, 2 * ell->radiuses.y);
  867.     }
  868. #  endif
  869. #else
  870.     fprintf(tfp, EllCmdstr[EllipseCmd], EllCmdkw[EllipseCmd],
  871.            (EllipseCmd==0 && ell->area_fill==BLACK_FILL ? "*" : ""),
  872.            2 * ell->radiuses.x, 2 * ell->radiuses.y);
  873. #endif
  874.     } else {
  875.         fprintf(tfp, "\\put(%d,%d){\\circle", pt.x, pt.y);
  876.         if (ell->area_fill == BLACK_FILL) {
  877.             fputc('*', tfp);
  878.         }
  879.         fprintf(tfp, "{%d}}\n", 2*ell->radiuses.x);
  880.     }
  881. }
  882.  
  883. extern char *ISOtoTeX[];
  884. void genepic_text(text)
  885. F_text *text;
  886. {
  887.     F_point pt;
  888.     char *tpos, *esc_cp, *special_index;
  889.     unsigned char   *cp;
  890.  
  891.     pt.x=text->base_x;
  892.     pt.y=text->base_y;
  893.     convertCS(&pt);
  894.     switch (text->type) {
  895.     case T_LEFT_JUSTIFIED:
  896.     case DEFAULT:
  897.     tpos = "[lb]";
  898.     break;
  899.     case T_CENTER_JUSTIFIED:
  900.     tpos = "[b]";
  901.     break;
  902.     case T_RIGHT_JUSTIFIED:
  903.     tpos = "[rb]";
  904.     break;
  905.     default:
  906.     fprintf(stderr, "unknown text position type\n");
  907.     exit(1);
  908.     }
  909.     fprintf(tfp, "\\put(%d,%d){\\makebox(0,0)%s{\\smash{",
  910.            pt.x, pt.y, tpos);
  911.     /* Output a shortstack in case there are multiple lines. */
  912.     for(cp = (unsigned char*)text->cstring; *cp; cp++) {
  913.       if (*cp == TEXT_LINE_SEP) {
  914.     fprintf(tfp, "\\shortstack" );
  915.     /* Output the justification for the shortstack. */
  916.     switch (text->type) {
  917.     case T_LEFT_JUSTIFIED:
  918.     case DEFAULT:
  919.     fprintf(tfp, "[l]");
  920.     break;
  921.     case T_CENTER_JUSTIFIED:
  922.     break;
  923.     case T_RIGHT_JUSTIFIED:
  924.     fprintf(tfp, "[r]");
  925.     break;
  926.     default:
  927.     fprintf(stderr, "unknown text position type\n");
  928.     exit(1);
  929.     }
  930.     break;
  931.       }
  932.     }
  933.  
  934.     unpsfont(text);
  935.     { int texsize;
  936.       double baselineskip;
  937.  
  938.       texsize = TEXFONTMAG(text);
  939.       baselineskip = (texsize * 1.2);
  940.  
  941.       fprintf(tfp, "{{\\SetFigFont{%d}{%.1f}{%s}",
  942.           texsize, baselineskip, TEXFONT(text->font));
  943.     }
  944.  
  945.     if (!special_text(text))
  946.     /* This loop escapes special LaTeX characters. */
  947.     for(cp = (unsigned char*)text->cstring; *cp; cp++) {
  948.               if (special_index=strchr(latex_text_specials, *cp)) {
  949.           /* Write out the replacement.  Implementation note: we can't
  950.          use puts since that will output an additional newline. */
  951.           esc_cp=latex_text_mappings[special_index-latex_text_specials];
  952.           while (*esc_cp)
  953.         fputc(*esc_cp++, tfp);
  954.         }
  955.         else if (*cp == TEXT_LINE_SEP) {
  956.           /* Handle multi-line text strings. The problem being addressed here
  957.          is a LaTeX bug where LaTeX is unable to handle a font which
  958.          spans multiple lines.  What we are doing here is closing off
  959.          the current font, starting a new line, and then resuming with
  960.          the current font. */
  961.           fprintf(tfp, "} \\\\\n");
  962.  
  963.            { int texsize;
  964.          double baselineskip;
  965.  
  966.          texsize = TEXFONTMAG(text);
  967.          baselineskip = (texsize * 1.2);
  968.          
  969.          fprintf(tfp, "{\\SetFigFont{%d}{%.1f}{%s}",
  970.              texsize, baselineskip, TEXFONT(text->font));
  971.             }
  972.         }
  973.         else
  974.         fputc(*cp, tfp);
  975.           }
  976.     else 
  977.     for(cp = (unsigned char*)text->cstring; *cp; cp++) {
  978.       if (*cp == TEXT_LINE_SEP) {
  979.           /* Handle multi-line text strings. */
  980.           fprintf(tfp, "} \\\\\n");
  981.  
  982.           { int texsize;
  983.         double baselineskip;
  984.  
  985.         texsize = TEXFONTMAG(text);
  986.         baselineskip = (texsize * 1.2);
  987.         
  988.         fprintf(tfp, "{\\SetFigFont{%d}{%.1f}{%s}",
  989.             texsize, baselineskip, TEXFONT(text->font));
  990.           }
  991.         }
  992.         else
  993.             if (*cp >= 0xa0)    /* we escape 8-bit char */
  994.                 fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]);
  995.         else
  996.             fputc(*cp, tfp);
  997.       }
  998.     fprintf(tfp, "}}}}}\n");
  999. }
  1000.  
  1001. void genepic_arc(arc)
  1002. F_arc *arc;
  1003. {
  1004.     FPoint pt1, pt2, ctr, tmp;
  1005.     double r1, r2, th1, th2, theta;
  1006.     double dx1, dy1, dx2, dy2;
  1007.     double arrowfactor;
  1008.  
  1009.     ctr.x = arc->center.x;
  1010.     ctr.y = arc->center.y;
  1011.     pt1.x = arc->point[0].x;
  1012.     pt1.y = arc->point[0].y;
  1013.     pt2.x = arc->point[2].x;
  1014.     pt2.y = arc->point[2].y;
  1015.     fconvertCS(&ctr);
  1016.     fconvertCS(&pt1);
  1017.     fconvertCS(&pt2);
  1018.  
  1019.     dx1 = pt1.x - ctr.x;
  1020.     dy1 = pt1.y - ctr.y;
  1021.     dx2 = pt2.x - ctr.x;
  1022.     dy2 = pt2.y - ctr.y;
  1023.  
  1024.     rtop(dx1, dy1, &r1, &th1);
  1025.     rtop(dx2, dy2, &r2, &th2);
  1026.     arrowfactor = (r1+r2) / 30.0;
  1027.     if (arrowfactor > 1) arrowfactor = 1;
  1028.     set_linewidth(arc->thickness);
  1029.     if (arc->for_arrow) {
  1030.     arc_tangent(&ctr, &pt2, arc->direction, &tmp);
  1031.     fdraw_arrow_head(&tmp, &pt2,
  1032.              arc->for_arrow->ht*arrowfactor,
  1033.              arc->for_arrow->wid*arrowfactor);
  1034.         if (Verbose) fprintf(tfp, "%%\n");
  1035.     }
  1036.     if (arc->back_arrow) {
  1037.     arc_tangent(&ctr, &pt1, !arc->direction, &tmp);
  1038.     fdraw_arrow_head(&tmp, &pt1,
  1039.              arc->back_arrow->ht*arrowfactor,
  1040.              arc->back_arrow->wid*arrowfactor);
  1041.         if (Verbose) fprintf(tfp, "%%\n");
  1042.     }
  1043.     if (TeXLang == EEpic) {
  1044.     set_pattern(arc->area_fill);
  1045.         fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
  1046.     } else {
  1047.     fprintf(tfp, "\\drawline");
  1048.     }
  1049.     if (TeXLang == EEpic) {
  1050.     if (arc->area_fill < UNFILLED) arc->area_fill = UNFILLED;
  1051.     fprintf(tfp, "%s", FillCommands[arc->area_fill]);
  1052. #ifdef DrawOutLine
  1053.     if (arc->area_fill != UNFILLED && OutLine==0) OutLine=1;
  1054. #endif
  1055.     }
  1056.     if (arc->direction) {
  1057.     theta = th2 - th1;
  1058.     if (theta < 0) theta += 2 * M_PI;
  1059.     th2 = 2*M_PI-th2;
  1060.     if (TeXLang == EEpic) {
  1061.         fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
  1062. #ifdef DrawOutLine
  1063.         if (OutLine==1) {
  1064.         OutLine=0;
  1065.             fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
  1066.         fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
  1067.         }
  1068. #endif
  1069.         } else {
  1070.             drawarc(&ctr, r1, 2*M_PI - th2 - theta, theta);
  1071.         }
  1072.     } else {
  1073.     theta = th1 - th2;
  1074.     if (theta < 0) theta += 2 * M_PI;
  1075.     th1 = 2*M_PI-th1;
  1076.     if (TeXLang == EEpic) {
  1077.         fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
  1078. #ifdef DrawOutLine
  1079.         if (OutLine==1) {
  1080.         OutLine=0;
  1081.             fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
  1082.         fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
  1083.         }
  1084. #endif
  1085.     } else {
  1086.             drawarc(&ctr, r2, 2*M_PI - th1 - theta, theta);
  1087.         }
  1088.     }
  1089. }
  1090.  
  1091. drawarc(ctr, r, th1, angle)
  1092. FPoint *ctr;
  1093. double r, th1, angle;
  1094. {
  1095.     double arclength, delta;
  1096.     int division, pt_count = 0;
  1097.  
  1098.  
  1099.     division = angle * r / Threshold;
  1100.     delta = angle / division;
  1101.     division++;
  1102.     while (division-- > 0) {
  1103.         if (++pt_count > PtPerLine) {
  1104.             fprintf(tfp, "\n\t");
  1105.             pt_count = 1;
  1106.         }
  1107.         fprintf(tfp, "(%.3lf,%.3lf)", ctr->x + cos(th1) * r,
  1108.                                 ctr->y + sin(th1) * r);
  1109.         th1 += delta;
  1110.     }
  1111.     fprintf(tfp, "\n");
  1112. }
  1113.  
  1114. static arc_tangent(pt1, pt2, direction, pt3)
  1115. FPoint *pt1, *pt2, *pt3;
  1116. int direction;
  1117. {
  1118.     if (direction) {
  1119.     pt3->x = pt2->x + (pt2->y - pt1->y);
  1120.     pt3->y = pt2->y - (pt2->x - pt1->x);
  1121.     } else {
  1122.     pt3->x = pt2->x - (pt2->y - pt1->y);
  1123.     pt3->y = pt2->y + (pt2->x - pt1->x);
  1124.     }
  1125. }
  1126.  
  1127. rtop(x, y, r, th)
  1128. double x, y, *r, *th;
  1129. {
  1130.     *r = sqrt(x*x+y*y);
  1131.     *th = acos(x/(*r));
  1132.     if (*th < 0) *th = M_PI + *th;
  1133.     if (y < 0) *th = 2*M_PI - *th;
  1134. }
  1135.  
  1136. static draw_arrow_head(pt1, pt2, arrowht, arrowwid)
  1137. F_point *pt1, *pt2;
  1138. double arrowht, arrowwid;
  1139. {
  1140.     FPoint fpt1, fpt2;
  1141.  
  1142.     fpt1.x = pt1->x;
  1143.     fpt1.y = pt1->y;
  1144.     fpt2.x = pt2->x;
  1145.     fpt2.y = pt2->y;
  1146.     fdraw_arrow_head(&fpt1, &fpt2, arrowht, arrowwid);
  1147. }
  1148.  
  1149. fdraw_arrow_head(pt1, pt2, arrowht, arrowwid)
  1150. FPoint *pt1, *pt2;
  1151. double arrowht, arrowwid;
  1152. {
  1153.     double x1, y1, x2, y2;
  1154.     double x,y, xb,yb,dx,dy,l,sina,cosa;
  1155.     double xc, yc, xd, yd;
  1156.  
  1157.     x1 = pt1->x;
  1158.     y1 = pt1->y;
  1159.     x2 = pt2->x;
  1160.     y2 = pt2->y;
  1161.  
  1162.     dx = x2 - x1;  dy = y1 - y2;
  1163.     l = sqrt(dx*dx+dy*dy);
  1164.     if (l == 0) {
  1165.      return;
  1166.     }
  1167.     else {
  1168.      sina = dy / l;  cosa = dx / l;
  1169.     }
  1170.     xb = x2*cosa - y2*sina;
  1171.     yb = x2*sina + y2*cosa;
  1172.     x = xb - arrowht;
  1173.     y = yb - arrowwid / 2;
  1174.     xc = x*cosa + y*sina;
  1175.     yc = -x*sina + y*cosa;
  1176.     y = yb + arrowwid / 2;
  1177.     xd = x*cosa + y*sina;
  1178.     yd = -x*sina + y*cosa;
  1179.  
  1180.     if (Verbose) fprintf(tfp, "%%\n%% arrow head\n%%\n");
  1181.  
  1182.     fprintf(tfp, "\\%s(%4.3f,%4.3f)(%4.3f,%4.3f)(%4.3f,%4.3f)\n", LnCmd,
  1183.         xc, yc, x2, y2, xd, yd);
  1184. }
  1185.  
  1186. #ifndef MSDOS
  1187. stricmp(s, t)
  1188. char *s, *t;
  1189. {
  1190.     char a, b;
  1191.  
  1192.     for (;;) {
  1193.         a= *s++; b= *t++;
  1194.         a = islower(a) ? toupper(a) : a;
  1195.         b = islower(b) ? toupper(b) : b;
  1196.         if (a != b) break;
  1197.         if (a == '\0') return(0);
  1198.     }
  1199.     return(a - b);
  1200. }
  1201. #endif
  1202.  
  1203. struct driver dev_epic = {
  1204.          genepic_option,
  1205.     genepic_start,
  1206.     genepic_arc,
  1207.     genepic_ellipse,
  1208.     genepic_line,
  1209.     genepic_spline,
  1210.     genepic_text,
  1211.     genepic_end,
  1212.     INCLUDE_TEXT
  1213. };
  1214.