home *** CD-ROM | disk | FTP | other *** search
/ swCHIP 1991 January / swCHIP_95-1.bin / utility / gsview13 / src / doc2rtf.c < prev    next >
C/C++ Source or Header  |  1995-12-09  |  9KB  |  431 lines

  1. /*
  2.  * doc2rtf.c  -- program to convert Gnuplot .DOC format to MS windows
  3.  * help (.rtf) format.
  4.  *
  5.  * This involves stripping all lines with a leading digit or
  6.  * a leading @, #, or %.
  7.  * Modified by Maurice Castro from doc2gih.c by Thomas Williams 
  8.  *
  9.  * usage:  doc2rtf file.doc file.rtf [-d]
  10.  *
  11.  */
  12.  
  13. /* note that tables must begin in at least the second column to */
  14. /* be formatted correctly and tabs are forbidden */
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20.  
  21. #define MAX_LINE_LEN    1024
  22. #define TRUE 1
  23. #define FALSE 0
  24.  
  25. struct LIST
  26. {
  27.     int level;
  28.     int line;
  29.     char *string;
  30.     struct LIST *next;
  31.     };
  32.  
  33. struct LIST *list = NULL;
  34. struct LIST *head = NULL;
  35.  
  36. struct LIST *keylist = NULL;
  37. struct LIST *keyhead = NULL;
  38.  
  39. int debug = FALSE;
  40.  
  41. void footnote();
  42. void parse();
  43. void refs();
  44. void convert();
  45. void process_line();
  46. int lookup();
  47.  
  48. main(argc,argv)
  49. int argc;
  50. char **argv;
  51. {
  52. FILE * infile;
  53. FILE * outfile;
  54.     if (argc==4 && argv[3][0]=='-' && argv[3][1]=='d')
  55.         debug = TRUE;
  56.  
  57.     if (argc != 3 && !debug) {
  58.         fprintf(stderr,"Usage: %s infile outfile\n", argv[0]);
  59.         return(1);
  60.     }
  61.     if ( (infile = fopen(argv[1],"r")) == (FILE *)NULL) {
  62.         fprintf(stderr,"%s: Can't open %s for reading\n",
  63.             argv[0], argv[1]);
  64.         return(1);
  65.     }
  66.     if ( (outfile = fopen(argv[2],"w")) == (FILE *)NULL) {
  67.         fprintf(stderr,"%s: Can't open %s for writing\n",
  68.             argv[0], argv[2]);
  69.     }
  70.     parse(infile);
  71.     convert(infile,outfile);
  72.     return(0);
  73. }
  74.  
  75. /* scan the file and build a list of line numbers where particular levels are */
  76. void parse(a)
  77. FILE *a;
  78. {
  79.     static char line[MAX_LINE_LEN];
  80.     char *c;
  81.     int lineno=0;
  82.     int lastline=0;
  83.  
  84.     while (fgets(line,MAX_LINE_LEN,a)) 
  85.     {
  86.     lineno++;
  87.     if (isdigit(line[0]))
  88.     {
  89.         if (list == NULL)    
  90.             head = (list = (struct LIST *) malloc(sizeof(struct LIST)));
  91.         else
  92.             list = (list->next = (struct LIST *) malloc(sizeof(struct LIST)));
  93.         list->line = lastline = lineno;
  94.         list->level = line[0] - '0';
  95.         list->string = (char *) malloc (strlen(line)+1);
  96.         c = strtok(&(line[1]),"\n");
  97.         strcpy(list->string, c);
  98.         list->next = NULL;
  99.     }
  100.     if (line[0]=='?')
  101.     {
  102.         if (keylist == NULL)    
  103.             keyhead = (keylist = (struct LIST *) malloc(sizeof(struct LIST)));
  104.         else
  105.             keylist = (keylist->next = (struct LIST *) malloc(sizeof(struct LIST)));
  106.         keylist->line = lastline;
  107.         keylist->level = line[0] - '0';
  108.         keylist->string = (char *) malloc (strlen(line)+1);
  109.         c = strtok(&(line[1]),"\n");
  110.         strcpy(keylist->string, c);
  111.         keylist->next = NULL;
  112.     }
  113.     }
  114.     rewind(a);
  115.     }
  116.  
  117. /* look up an in text reference */
  118. int
  119. lookup(s)
  120. char *s;
  121. {
  122.     char *c;
  123.     char tokstr[MAX_LINE_LEN];
  124.     char *match; 
  125.     int l;
  126.  
  127.     strcpy(tokstr, s);
  128.  
  129.     /* first try the ? keyword entries */
  130.     keylist = keyhead;
  131.     while (keylist != NULL)
  132.     {
  133.         c = keylist->string;
  134.         while (isspace(*c)) c++;
  135.         if (!strcmp(s, c)) return(keylist->line);
  136.         keylist = keylist->next;
  137.         }
  138.  
  139.     /* then try titles */
  140.     match = strtok(tokstr, " \n\t");
  141.     l = 0; /* level */
  142.     
  143.     list = head;
  144.     while (list != NULL)
  145.     {
  146.         c = list->string;
  147.         while (isspace(*c)) c++;
  148.         if (!strcmp(match, c)) 
  149.         {
  150.             l = list->level;
  151.             match = strtok(NULL, "\n\t ");
  152.             if (match == NULL)
  153.             {
  154.                 return(list->line);
  155.                 }
  156.             }
  157.         if (l > list->level)
  158.             break;
  159.         list = list->next;
  160.         }
  161.     return(-1);
  162.     }
  163.  
  164. /* search through the list to find any references */
  165. void
  166. refs(l, f)
  167. int l;
  168. FILE *f;
  169. {
  170.     int curlevel;
  171.     char str[MAX_LINE_LEN];
  172.     char *c;
  173.  
  174.     /* find current line */
  175.     list = head;
  176.     while (list->line != l)
  177.         list = list->next;
  178.     curlevel = list->level;
  179.     list = list->next;        /* look at next element before going on */
  180.     if (list != NULL)
  181.         fprintf(f,"\\par");
  182.     while (list != NULL)
  183.     {
  184.         /* we are onto the next topic so stop */
  185.         if (list->level == curlevel)
  186.             break;
  187.         /* these are the next topics down the list */
  188.         if (list->level == curlevel+1)
  189.         {
  190.             c = list->string;
  191.             while (isspace(*c)) c++;
  192.             fprintf(f,"\\par{\\uldb %s}",c);
  193.             fprintf(f,"{\\v loc%d}\n",list->line);
  194.             }
  195.         list = list->next;
  196.         }
  197.     }
  198.  
  199. /* generate an RTF footnote with reference char c and text s */
  200. void footnote(c, s, b)
  201. char c;
  202. char *s;
  203. FILE *b;
  204. {
  205.     fprintf(b,"%c{\\footnote %c %s}\n",c,c,s);
  206.     }
  207.  
  208. void
  209. convert(a,b)
  210.     FILE *a,*b;
  211. {
  212.     static char line[MAX_LINE_LEN];
  213.     
  214.     /* generate rtf header */
  215.     fprintf(b,"{\\rtf1\\ansi ");        /* vers 1 rtf, ansi char set */
  216.     fprintf(b,"\\deff0");                /* default font font 0 */
  217.     /* font table: font 0 proportional, font 1 fixed */
  218.     fprintf(b,"{\\fonttbl{\\f0\\fswiss Arial;}{\\f1\\fmodern Courier New;}}\n");
  219.  
  220.     /* process each line of the file */
  221.     while (fgets(line,MAX_LINE_LEN,a)) {
  222.        process_line(line, b);
  223.        }
  224.  
  225.     /* close final page and generate trailer */
  226.     fprintf(b,"}{\\plain \\page}\n");
  227.     fprintf(b,"}\n");
  228. }
  229.  
  230. void
  231. process_line(line, b)
  232.     char *line;
  233.     FILE *b;
  234. {
  235.     static int line_count = 0;
  236.     static char line2[MAX_LINE_LEN];
  237.     static int last_line;
  238.     int i;
  239.     int j;
  240.     static int startpage = 1;
  241.     char str[MAX_LINE_LEN];
  242.     char topic[MAX_LINE_LEN];
  243.     int k, l;
  244.     static int tabl=0;
  245.     static int para=0;
  246.     static int llpara=0;
  247.     static int inquote = FALSE;
  248.     static int inref = FALSE;
  249.  
  250.     line_count++;
  251.  
  252.     i = 0;
  253.     j = 0;
  254.     while (line[i] != '\0')
  255.     {
  256.         switch(line[i])
  257.         {
  258.             case '\\':
  259.             case '{':
  260.             case '}':
  261.                 line2[j] = '\\';
  262.                 j++;
  263.                 line2[j] = line[i];
  264.                 break;
  265.             case '\r':
  266.             case '\n':
  267.                 break;
  268.             case '`':    /* backquotes mean boldface or link */
  269.                 if (line[1]==' ')    /* tabular line */
  270.                     line2[j] = line[i];
  271.                 else if ((!inref) && (!inquote))
  272.                 {
  273.                     k=i+1;    /* index into current string */
  274.                     l=0;    /* index into topic string */
  275.                     while ((line[k] != '`') && (line[k] != '\0'))
  276.                     {
  277.                         topic[l] = line[k];
  278.                         k++;
  279.                         l++;
  280.                         }
  281.                     topic[l] = '\0';
  282.                     k = lookup(topic);
  283.                     if ((k > 0) && (k != last_line))
  284.                     {
  285.                         line2[j++] = '{';
  286.                         line2[j++] = '\\';
  287.                         line2[j++] = 'u';
  288.                         line2[j++] = 'l';
  289.                         line2[j++] = 'd';
  290.                         line2[j++] = 'b';
  291.                         line2[j] = ' ';
  292.                         inref = k;
  293.                         }
  294.                     else
  295.                     {
  296.                         if (debug)
  297.                             fprintf(stderr,"Can't make link for \042%s\042 on line %d\n",topic,line_count);
  298.                         line2[j++] = '{';
  299.                         line2[j++] = '\\';
  300.                         line2[j++] = 'b';
  301.                         line2[j] = ' ';
  302.                         inquote = TRUE;
  303.                         }
  304.                     }
  305.                 else
  306.                 {
  307.                     if (inquote && inref)
  308.                         fprintf(stderr, "Warning: Reference Quote conflict line %d\n", line_count);
  309.                     if (inquote)
  310.                     {
  311.                         line2[j] = '}';
  312.                         inquote = FALSE;
  313.                         }
  314.                     if (inref)
  315.                     {
  316.                         /* must be inref */
  317.                         sprintf(topic,"%d",inref);
  318.                         line2[j++] = '}';
  319.                         line2[j++] = '{';
  320.                         line2[j++] = '\\';
  321.                         line2[j++] = 'v';
  322.                         line2[j++] = ' ';
  323.                         line2[j++] = 'l';
  324.                         line2[j++] = 'o';
  325.                         line2[j++] = 'c';
  326.                         k = 0;
  327.                         while (topic[k] != '\0')
  328.                         {
  329.                             line2[j++] = topic[k];
  330.                             k++;
  331.                             }
  332.                         line2[j] = '}';
  333.                         inref = 0;
  334.                         }
  335.                 }
  336.                 break;
  337.             default:
  338.                 line2[j] = line[i];
  339.             }
  340.         i++;
  341.         j++;
  342.         line2[j] = '\0';
  343.         }
  344.  
  345.     i = 1;
  346.  
  347.     switch(line[0]) {        /* control character */
  348.        case '?': {            /* interactive help entry */
  349.         if ((line2[1] != '\0') && (line2[1] != ' '))
  350.             footnote('K',&(line2[1]),b);
  351.           break;
  352.        }
  353.        case '@': {            /* start/end table */
  354.           break;            /* ignore */
  355.        }
  356.        case '#': {            /* latex table entry */
  357.           break;            /* ignore */
  358.        }
  359.        case '%': {            /* troff table entry */
  360.           break;            /* ignore */
  361.        }
  362.        case '\n':            /* empty text line */
  363.             fprintf(b,"\\par\n");
  364.             llpara = para;
  365.             para = 0;
  366.             tabl = 0;
  367.             break;
  368.        case ' ': {            /* normal text line */
  369.           if ((line2[1] == '\0') || (line2[1] == '\n'))
  370.           {
  371.                 fprintf(b,"\\par\n"); 
  372.                 llpara = para;
  373.                 para = 0;
  374.                 tabl = 0;
  375.                 }
  376.           if (line2[1] == ' ') 
  377.           {
  378.                 if (!tabl)
  379.                 {
  380.                     fprintf(b,"\\par\n"); 
  381.                     }
  382.                 fprintf(b,"{\\pard \\plain \\f1\\fs20 ");
  383.                   fprintf(b,"%s",&line2[1]); 
  384.                 fprintf(b,"}\\par\n");
  385.                 llpara = 0;
  386.                 para = 0;
  387.                 tabl = 1;
  388.                 }
  389.           else
  390.           {
  391.                 if (!para)
  392.                 {
  393.                     if (llpara)
  394.                         fprintf(b,"\\par\n"); /* blank line between paragraphs */
  395.                     llpara = 0;
  396.                     para = 1;        /* not in para so start one */
  397.                     tabl = 0;
  398.                     fprintf(b,"\\pard \\plain \\qj \\fs20 \\f0 ");
  399.                     }
  400.                   fprintf(b,"%s \n",&line2[1]); 
  401.                 }
  402.           break;
  403.        }
  404.        default: {
  405.           if (isdigit(line[0])) { /* start of section */
  406.             if (!startpage)
  407.             {
  408.                 refs(last_line,b);
  409.                 fprintf(b,"}{\\plain \\page}\n");
  410.                 }
  411.             para = 0;                    /* not in a paragraph */
  412.             tabl = 0;
  413.             last_line = line_count;
  414.             startpage = 0;
  415.             fprintf(b,"{\n");
  416.             sprintf(str,"browse:%05d", line_count);
  417.             footnote('+',str,b);
  418.             footnote('$',&(line2[1]),b); /* title */
  419.             fprintf(b,"{\\b \\fs24 %s}\\plain\\par\\par\n",&(line2[1]));
  420.             /* output unique ID */
  421.             sprintf(str,"loc%d", line_count);
  422.             footnote('#',str,b);
  423.           } else
  424.             fprintf(stderr, "unknown control code '%c' in column 1, line %d\n",
  425.                 line[0], line_count);
  426.           break;
  427.        }
  428.     }
  429. }
  430.  
  431.