/* * An output filter to produce LaTeX using Paul DuBois' RTF reader * WECHTL Erwin * Woerthg. 2/18 * A-2500 Baden * AUSTRIA * * a student of the University in vienna * Technische Universitaet Wien * Institut fuer Technische Informatik * Treitlstr. 3 * A-1040 WIEN * AUSTRIA * * Changed code from: * * Written and copyright (c) 1991 by Robert Lupton (rhl@astro.princeton.edu) * Permission is granted to freely distribute and modify this code, providing: * 1/ This copyright notice is preserved * 2/ You send me a copy of any changes for inclusion in a future release */ #include #include #include #ifdef __STDC__ # include # ifndef THINK_C # include # endif #else /* !__STDC__ */ # ifdef NO_MALLOC_H extern char *malloc (); # else /* NO_MALLOC_H */ # include # endif /* NO_MALLOC_H */ #endif /* !__STDC__ */ #ifndef SEEK_SET # define SEEK_SET 0 #endif #include "fonts.h" #include "r2L_version.h" #include "rtf2LaTeX.h" #include "rtf.h" #ifdef THINK_C #include #include "macintosh.h" static char * RTFDIR; #endif char *progname; /* Used in Error messages */ RTFFuncPtr default_read_font = NULL; /* default func to read style table */ RTFFuncPtr default_read_style = NULL; /* default func to read style table */ /* This forward declaration isn't possible in the header file because * RTFStyle isn't defined there yet. */ static int is_specialWORDstyle A((RTFStyle*,LATEXStyle*)); /*****************************************************************************/ int main(ac,av) int ac; char *av[]; { RTF_STACK rtf_initial; /* initial values of things that on rtf stack */ static char *header_erwinbet[] = { "% Converted from RTF format using rtf2LaTeX", "% Comments and bugs to Erwin Wechtl", "% Woertg. 2/18", "% A-2500 Baden", "%", NULL, }; FILE *fil = NULL; extern int optind; extern char *optarg; int c; char *codefile = "mac", *landfile = "english"; char *str = "12345.67"; char *rtf_filename = NULL; #ifdef THINK_C RTFDIR = get_home_dir(); ac = ccommand(&av); #endif /* THINK_C */ progname = av[0]; while((c = getopt(ac,av,"cC:dhgGHL:npqrstT:uv:V")) != EOF) { switch (c) { case 'g': german_squotes = 1; break; case 'G': german_dquotes = 1; break; case 'q': translate_quotes = 1; break; case 'C': codefile = optarg; break; case 'c': /* don't do character formating */ formatting_char= 0; break; case 'd': /* formate also in specila WORD styles like heading, footer, footnote text, .. (default 0) */ formatting_sWORD = 1; break; case 'h': usage(); exit(0); case 'H': /* use LaTeX default header and footer */ header_on = 0; break; case 'L': landfile = optarg; break; case 'n': other_linebreak = 1; /* use \hfil\break instead of \\ */ break; /* for making a new line */ case 'p': /* don't do paragraph formating */ formatting_para = 0; break; case 'r': /* ignore left and right skip */ rl_skip_on = 0; break; case 's': /* ignore tab stops */ tabstops_on = 0; break; case 't': /* don't do any formating in tables */ formatting_table = 0; break; case 'T': /* decrease cell-width (default 0.7)*/ smaller_cell_factor=atof(optarg); if (!(smaller_cell_factor > 0)) { fprintf(stderr,"\n%s: Argument of the -T flag must be greater than 0,\n but it is %g\n", progname, smaller_cell_factor); fprintf(stderr,"use -h for help\n"); exit(2); } break; case 'u': /* change underline to italic */ noUnderline = 1; break; case 'v': verbose = atoi(optarg); if (verbose!=1 && verbose!=2) { fprintf(stderr,"\n%s: The level of verbose can only be 1 or 2\n", progname); fprintf(stderr,"use -h for help\n"); exit(2); } break; case 'V': fprintf(stderr,"%s: %s\n",progname,version); exit(0); break; case '?': fprintf(stderr,"%s: ", progname); usage(); exit(2); } } if (optind 1 || (verbose && count++ == 0)) { msg_not_yet("sbasedon"); } } break; case rtfNext: if(rtfParam != rtfNoParam) { static int count = 0; if(verbose > 1 || (verbose && count++ == 0)) { msg_not_yet("snext"); } } break; default: fprintf(stderr,"%s: Illegal minor number for StyleAttr: %d\n", progname,rtfMinor); break; } break; case rtfSpecialChar: SpecialChar(); break; case rtfDocAttr: DocAttr(); break; case rtfSectAttr: SectAttr(); break; case rtfTblAttr: TblAttr(); break; case rtfParAttr: ParAttr(); break; case rtfCharAttr: if (Cformatting_char) CharAttr(); break; case rtfPictAttr: fprintf(stderr,"%s: You shouldn't see rtfPictAttr: minor %d\n", progname,rtfMinor); break; case rtfFieldAttr: FieldAttr(); break; case rtfTOCAttr: TOCAttr(); break; case rtfPosAttr: PosAttr(); break; } } /***************************************************************************** * * Control class major number handlers. Each one switches on the * minor numbers that occur within the major number. rtfStyleSheet, * rtfFontTbl, and rtfColorTbl are not in the switch because they're * handled by the reader. rtfPict has its own callback. */ static void CharSet() { switch (rtfMinor) { case rtfAnsiCharSet: break; case rtfMacCharSet: break; case rtfPcCharSet: break; case rtfPcaCharSet: break; } } static void Destination() { switch (rtfMinor) { case rtfFootnote: output_str("%\n",'\0'); output_str("\\footnote{",'\0'); push_LaTeX_stack("}%\n",Footnote,0); break; case rtfHeader: if (!initialised) initialise(); if (header_on) { output_str("\\markright{",'\0'); push_LaTeX_stack(" }\n",Header,0); } else { RTFSkipGroup(); RTFUngetToken(); } break; case rtfHeaderLeft: case rtfHeaderRight: case rtfHeaderFirst: if (verbose) msg_not_supported(rtfTextBuf+1); break; case rtfFooter: if (header_on) { if (verbose) fprintf(stderr,"LaTeX supports only the header\n"); output_str("% LaTeX supports only the header\n",'\0'); } RTFSkipGroup(); RTFUngetToken(); break; case rtfFooterLeft: break; case rtfFooterRight: break; case rtfFooterFirst: break; case rtfFNSep: break; case rtfFNContSep: break; case rtfFNContNotice: break; case rtfInfo: break; case rtfField: break; case rtfFieldInst: { char buf[80]; buf[0]='\0'; (void)RTFGetToken(); while(rtfClass==rtfText) { strcat(buf,rtfTextBuf); (void)RTFGetToken(); } RTFUngetToken(); if (strncmp(buf,"date",4)==0) output_str("\\today",'\0'); else if (verbose) { char msg_buf[80]; strcpy(msg_buf,rtfTextBuf+1); strcat(msg_buf,buf); msg_not_yet(msg_buf); } break; } break; case rtfFieldResult: break; case rtfIndex: break; case rtfIndexBold: break; case rtfIndexItalic: break; case rtfIndexText: break; case rtfIndexRange: break; case rtfTOC: break; case rtfBookmarkStart: break; case rtfBookmarkEnd: break; case rtfITitle: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; case rtfISubject: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; case rtfIAuthor: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; case rtfIOperator: break; case rtfIKeywords: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; case rtfIComment: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; case rtfIVersion: break; case rtfIVerscomm: /* \verscomm is a token, made by Macintosh's WORD. * I don't know the meaning, * because it isn't specified in the RTF-specification. */ RTFSkipGroup(); RTFUngetToken(); break; case rtfIDoccomm: (void) RTFGetToken (); while (rtfClass == rtfText) (void) RTFGetToken (); RTFUngetToken(); break; } } static void SpecialChar() { switch (rtfMinor) { case rtfCurHeadPage: if (verbose && header_on) fprintf(stderr,"LaTeX always puts the page number in right corner\n"); break; case rtfCurFNote: { static int count=0; if (verbose && count++ == 0) msg_not_needed(rtfTextBuf+1); break; } case rtfCurHeadPict: msg_not_supported("chpict"); break; case rtfCurHeadDate: case rtfCurHeadTime: if (verbose) msg_not_supported(rtfTextBuf+1); break; case rtfFormula: msg_not_yet("|"); break; case rtfNoBrkSpace: if(!text_out) start_para(); output_str("~",'\0'); break; case rtfNoReqHyphen: output_str("\\-",'\0'); break; case rtfNoBrkHyphen: if(!text_out) start_para(); output('-',1); break; case rtfPage: end_para(); end_table(); /* if there is a table */ output_str("\n\\newpage\n",'\0'); break; case rtfLine: if (!other_linebreak) output_str("\\\\ \n",'\0'); else output_str(" \\hfill \\break \n",'\0'); break; case rtfPar: if (top_LaTeX_flags(Header)) { if (!other_linebreak) output_str("\\\\ \n",'\0'); else output_str(" \\hfill \\break \n",'\0'); return; } if (top_LaTeX_flags(SpecialWORDstyle)) pop_LaTeX_stack(); if (tab==2 && text_out) { while (!top_LaTeX_flags(Tabstops) ) if (pop_LaTeX_stack()==0) break; rtf_current=rtf_default; output_str("\\\\ \n",'\0'); update_current(); } /* we may want to deal with this elsewhere, so as to pop the stacks before printing the newline */ RTFGetToken(); if(RTFCheckCM(rtfGroup,rtfEndGroup) || RTFCheckCMM(rtfControl,rtfParAttr,rtfParDef)) { end_of_par = 1; /* Don't know if this one is needed anymore * } else if(in_table && RTFCheckCMM(rtfControl,rtfSpecialChar,rtfPar)) { * end_table(); * two \par's in a row * */ } else { end_para(); } RTFUngetToken(); break; case rtfSect: rtfMinor = rtfPar; /* pretend that it's just a para */ RTFUngetToken(); break; case rtfTab: if (top_LaTeX_flags(SpecialWORDstyle)) return; /* no tab stops in header, haeding, ...*/ if(!text_out) start_para(); if (!tabstops_on) break; if (tab) { while (!top_LaTeX_flags(Tabstops) ) if (pop_LaTeX_stack()==0) break; rtf_current=rtf_default; output_str("\\> ",'\0'); update_current(); } else { output(' ',1); if (verbose && tabstops_on) fprintf(stderr,"this tab stop is ignored\n you have to specify the position of the tab stop before\n"); } break; case rtfCell: while (!top_LaTeX_flags(Tabular) ) if (pop_LaTeX_stack()==0) break; rtf_current=rtf_default; cellnr++; if (cellnr 1 || (verbose && count++ == 0)) { msg_not_yet(rtfTextBuf+1); } } break; case rtfFacingPage: if(verbose) msg_not_yet(rtfTextBuf+1); break; case rtfGutterWid: msg_not_yet("gutter"); break; case rtfDefTab: msg_not_yet("deftab"); break; case rtfWidowCtrl: msg_not_yet("widowctrl"); break; case rtfFNoteEndSect: msg_not_yet("endnotes"); break; case rtfFNoteEndDoc: break; case rtfFNoteBottom: break; case rtfFNoteText: msg_not_yet("ftntj"); break; case rtfFNoteStart: if(footnote_num0 != rtfParam) { footnote_num0 = rtfParam; change_headfoot = 1; } break; case rtfFNoteRestart: if(footnotes_restart_each_page != 1) { footnotes_restart_each_page = 1; change_headfoot = 1; } break; case rtfHyphHotZone: break; case rtfPageStart: pageno = rtfParam; break; case rtfLineStart: lineno = rtfParam; break; case rtfLandscape: msg_not_supported("landscape"); break; case rtfFracWidth: break; case rtfNextFile: break; case rtfTemplate: break; case rtfMakeBackup: break; case rtfRTFDefault: break; case rtfRevisions: break; case rtfMirrorMargin: break; case rtfRevDisplay: break; case rtfRevBar: break; } } /*****************************************************************************/ static void SectAttr() { switch (rtfMinor) { case rtfSectDef: set_headfoot_lines(); break; case rtfNoBreak: break; case rtfColBreak: break; case rtfPageBreak: break; case rtfEvenBreak: break; case rtfOddBreak: break; case rtfPageStarts: break; case rtfPageCont: break; case rtfPageRestart: break; case rtfPageDecimal: if(pageno_style != Pageno_Decimal) { pageno_style = Pageno_Decimal; change_headfoot = 1; } break; case rtfPageURoman: if(pageno_style != Pageno_URoman) { pageno_style = Pageno_URoman; change_headfoot = 1; } break; case rtfPageLRoman: if(pageno_style != Pageno_LRoman) { pageno_style = Pageno_LRoman; change_headfoot = 1; } break; case rtfPageULetter: msg_not_yet("pgnucltr"); break; case rtfPageLLetter: msg_not_yet("pgnlcltr"); break; case rtfPageNumLeft: if(pageno_x != rtfParam) { pageno_x = rtfParam; change_headfoot = 1; } break; case rtfPageNumTop: if(pageno_y != rtfParam) { pageno_y = rtfParam; change_headfoot = 1; } break; case rtfLineModulus: if(rtfParam != 0) msg_not_supported("linemod"); break; case rtfLineStarts: break; case rtfLineDist: msg_not_supported("linex"); break; case rtfLineRestart: msg_not_supported("linerestart"); break; case rtfLineRestartPg: msg_not_supported("lineppage"); break; case rtfLineCont: msg_not_supported("linecont"); break; case rtfHeaderY: msg_not_yet("headery"); break; case rtfFooterY: msg_not_yet("footery"); break; case rtfTopVAlign: break; case rtfBottomVAlign: break; case rtfCenterVAlign: break; case rtfJustVAlign: break; case rtfColumns: if(rtfParam != 1) msg_not_yet("cols"); break; case rtfColumnLine: break; case rtfColumnSpace: msg_not_yet("colsx"); break; case rtfENoteHere: msg_not_supported("endnhere"); break; case rtfTitleSpecial: msg_not_supported("titlepg"); break; } } static void TblAttr() { switch (rtfMinor) { case rtfCellBordBottom: case rtfCellBordTop: case rtfCellBordLeft: case rtfCellBordRight: { static int count = 0; if(verbose > 1 || (verbose && count++ == 0)) { msg_not_yet(rtfTextBuf+1); } } break; case rtfRowDef: table_mode=1; push_LaTeX_stack("",TabularInit,1); strcpy(tabinitnew,"\n\\begin{tabular}{"); endOfLastCell=-70; max_cellnr=0; break; case rtfRowLeft: case rtfRowRight: case rtfRowCenter: case rtfRowGapH: case rtfRowHt: case rtfRowLeftEdge: { static int count = 0; if(verbose > 1 || (verbose && count++ == 0)) { msg_not_yet(rtfTextBuf+1); } } break; case rtfCellPos: { unsigned int cell_bright; max_cellnr++; cell_bright=(rtfParam-endOfLastCell)*smaller_cell_factor; sprintf(buff,"p{%gpt}",TW_TO_PT(cell_bright)); strcat(tabinitnew,buff); endOfLastCell=rtfParam; break; } case rtfCellShading: /* \clshdng is a token, made by Macintosh's WORD * I don't know the meaning, * because it isn't specified in the RTF-specification */ break; case rtfMergeRngFirst: break; case rtfMergePrevious: break; } } /*****************************************************************************/ static void ParAttr() { switch (rtfMinor) { case rtfParDef: if(!initialised) { /* it's hard to know where to call it*/ initialise(); } while(top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num) || top_LaTeX_flags(Font_Size) || top_LaTeX_flags(Style) || top_LaTeX_flags(Undefined) || top_LaTeX_flags(Underline) || top_LaTeX_flags(Sub_Super) || top_LaTeX_flags(Paragraph) || top_LaTeX_flags(NormalWORDstyle) || top_LaTeX_flags(LRskip) || top_LaTeX_flags(SpecialWORDstyle)) { (void)pop_LaTeX_stack(); } rtf_current.par_attr.leftskip=rtf_current.par_attr.rightskip=0; if (top_LaTeX_flags(Tabstops)) { (void)pop_LaTeX_stack(); Cformatting_char=formatting_char; Cformatting_para=formatting_para; } if (!table_mode && top_LaTeX_flags(Tabular)) end_table(); /* it's hard to know where to call it*/ if ((table_mode) && /* begin of a table in rtf */ top_LaTeX_flags(TabularInit) ) if (strcmp(tabinitold,tabinitnew)==0) { /*we haven't finished the last */ (void)pop_LaTeX_stack(); /* table in LaTeX and the parameters */ } /* of both the current and last */ /* rtf-table are equal so we needn't */ /* start a new LaTeX-table */ else { end_table(); /* we will have to finish the last table, if there is one */ strcpy(tabinitold,tabinitnew); table_mode=1; output_str(tabinitnew,'\0'); /* and to start a new one */ output_str("}\n",'\0'); push_LaTeX_stack("\\end{tabular}\n",Tabular,0); Cformatting_char=formatting_char&&formatting_table; Cformatting_para=formatting_para&&formatting_table; } if(end_of_par /*&& !table_mode*/) { end_para(); } ntabs = 0; table_mode=0; tab=0; rtf_default.LaTeX_stack = rtf_ptr->LaTeX_stack; rtf_default.prev = rtf_ptr->prev; *rtf_ptr = rtf_default; rtf_current.char_attr = rtf_default.char_attr; (void)RTFSetClassCallback(rtfText, start_para); /* not really start a new pragraph but have a look if there is a table end */ break; case rtfStyleNum: if(inDefineStyle) RTFExpandStyle(rtfParam); else { if(!initialised) { /* it's hard to know where to call it*/ RTFUngetToken(); /* store the Token, because initialise */ initialise(); /* changes it */ RTFGetToken(); } if (!table_mode && top_LaTeX_flags(Tabular)) end_table(); /* it's hard to know where to call it*/ setstylecommand(rtfParam); } break; case rtfQuadLeft: { static int count = 0; if(verbose > 1 || (verbose && count++ == 0)) { msg_map_to("gl","gj"); } rtf_ptr->par_attr.flags |= LeftAlign; } break; case rtfQuadRight: if (text_out) { if (!Cformatting_para) /* no paragraph formatting */ break; output_str("\n\\begin{flushright}",'\0'); push_LaTeX_stack("\n\\end{flushright}",Paragraph,0); } else rtf_ptr->par_attr.flags |= RightAlign; break; case rtfQuadJust: rtf_ptr->par_attr.flags &= ~(LeftAlign | Centred | RightAlign); break; case rtfQuadCenter: if (text_out) { if (!Cformatting_para) /* no paragraph formatting */ break; output_str("\n\\begin{center}",'\0'); push_LaTeX_stack("\n\\end{center}",Paragraph,0); } else rtf_ptr->par_attr.flags |= Centred; break; case rtfFirstIndent: rtf_ptr->par_attr.parindent = rtfParam; break; case rtfLeftIndent: rtf_ptr->par_attr.leftskip = rtfParam; break; case rtfRightIndent: rtf_ptr->par_attr.rightskip = rtfParam; break; case rtfSpaceBefore: rtf_ptr->par_attr.skip_before = rtfParam; break; case rtfSpaceAfter: rtf_ptr->par_attr.skip_after = rtfParam; break; case rtfSpaceBetween: break; case rtfInTable: table_mode=1; break; case rtfKeep: break; case rtfKeepNext: break; case rtfSideBySide: break; case rtfPBBefore: break; case rtfNoLineNum: /* ignored */ break; case rtfBorderTop: break; case rtfBorderBottom: break; case rtfBorderLeft: break; case rtfBorderRight: break; case rtfBorderBar: break; case rtfBorderBox: break; case rtfBorderBetween: break; case rtfBorderSingle: break; case rtfBorderThick: break; case rtfBorderShadow: break; case rtfBorderDouble: break; case rtfBorderDot: break; case rtfBorderHair: break; case rtfBorderSpace: break; case rtfTabPos: if (top_LaTeX_flags(SpecialWORDstyle)) return; /*no tab stops in header, heading, ...*/ if (!tabstops_on) break; if (!table_mode && top_LaTeX_flags(Tabular)) end_table(); if (table_mode) { if (verbose) fprintf(stderr,"can't deal with tab stops in tables"); } else { tab=1; if(ntabs >= NTABS) { if(ntabs == NTABS) fprintf(stderr,"%s: Attempt to set more than %d tabs\n", progname,NTABS); } else { tabstops[ntabs++].pos = rtfParam; tabstops[ntabs].type = TabLeft; } } break; case rtfTabRight: if(ntabs < NTABS) { tabstops[ntabs].type = TabRight; } break; case rtfTabCenter: if(ntabs < NTABS) { tabstops[ntabs].type = TabCentre; } break; case rtfTabDecimal: if(ntabs < NTABS) { tabstops[ntabs].type = TabDecimal; } break; case rtfTabBar: { static int count = 0; if(verbose > 1 || (verbose && count++ == 0)) msg_not_yet("tb"); } break; case rtfLeaderDot: break; case rtfLeaderHyphen: break; case rtfLeaderUnder: break; case rtfLeaderThick: break; } } /*procedure not needed yet*/ static void PictAttr () { switch (rtfMinor) { case rtfMacQD: break; case rtfWinMetafile: break; case rtfWinBitmap: break; case rtfPicWid: break; case rtfPicHt: break; case rtfPicGoalWid: break; case rtfPicGoalHt: break; case rtfPicScaleX: break; case rtfPicScaleY: break; case rtfPicScaled: break; case rtfPicCropTop: break; case rtfPicCropBottom: break; case rtfPicCropLeft: break; case rtfPicCropRight: break; case rtfPixelBits: break; case rtfBitmapPlanes: break; case rtfBitmapWid: break; case rtfPicBinary: break; } } /*****************************************************************************/ static void FieldAttr() { switch (rtfMinor) { case rtfFieldDirty: break; case rtfFieldEdited: break; case rtfFieldLocked: break; case rtfFieldPrivate: break; } } /*****************************************************************************/ static void TOCAttr() { switch (rtfMinor) { case rtfTOCType: break; case rtfTOCLevel: break; } } /*****************************************************************************/ static void PosAttr() { switch (rtfMinor) { case rtfPosX: break; case rtfPosXCenter: break; case rtfPosXInside: break; case rtfPosXLeft: break; case rtfPosXOutSide: break; case rtfPosXRight: break; case rtfPosY: break; case rtfPosYInline: break; case rtfPosYTop: break; case rtfPosYCenter: break; case rtfPosYBottom: break; case rtfAbsWid: break; case rtfTextDist: break; case rtfRPosMargV: break; case rtfRPosPageV: break; case rtfRPosMargH: break; case rtfRPosPageH: break; case rtfRPosColH: break; } } /***************************************************************************** * * Deal with Pict destinations */ static void read_pict() { static int count=0; if (verbose && count++==0) fprintf(stderr,"%s: Don't support any picture-things yet; be patient\n", progname); if (verbose>1) msg_not_yet(rtfTextBuf+1); RTFSkipGroup (); RTFRouteToken (); /* feed "}" back to router */ } /***************************************************************************** * * Deal with things like footnote numbering and page numbers; things * that involve the headline or footline */ static void set_headfoot_lines() { int pageno_top = (pageno_y < paper_height/2 ? 1 : 0); if(!change_headfoot) return; # ifdef notdef /* I think this is left over from rtf2tex */ /* * The headline first * output_str("\\headline={\\tenrm ",'\0'); if(footnotes_restart_each_page) { sprintf(buff,"\\footnum=%d",footnote_num0); output_str(buff,' '); } if(pageno_top) { sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num()); output_str(buff,' '); } output_str("}",'\n'); /* * And now the foot * output_str("\\footline={\\tenrm ",'\0'); if(!pageno_top) { sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num()); output_str(buff,' '); } output_str("}",'\n'); change_headfoot = 0; /* we've done it * */ # endif /* notdef */ } /***************************************************************************** * * Convert the pageno to the desired form */ static char * page_num() { switch (pageno_style) { case Pageno_Decimal: return("\\number\\pageno"); case Pageno_LRoman: return("\\romannumeral\\pageno"); case Pageno_URoman: return("\\uppercase\\expandafter{\\romannumeral\\pageno}"); default: return(""); } } /***************************************************************************** * * This is called when we see the first text token after each \par */ #define CURRENT(WHAT) /* is WHAT up-to-date? */ \ (rtf_current.WHAT == rtf_ptr->WHAT) static void start_para() { if(!initialised) { /* this could be the place */ initialise(); } if(!table_mode && top_LaTeX_flags(Tabular)) end_table(); if (tab==1 && !table_mode) start_tabstops(); update_current(); text_out = 1; (void)RTFSetClassCallback(rtfText, TextClass); if(rtfClass == rtfText) { RTFUngetToken(); /* re-schedule the text */ } } /* * End a paragraph */ static void end_para() { if(in_table) { tab_num = 0; } else { if (top_LaTeX_flags(SpecialWORDstyle) || top_LaTeX_flags(Header)) pop_LaTeX_stack(); output('\n',1); output('\n',1); } text_out = 0; end_of_par = 0; (void)RTFSetClassCallback(rtfText, start_para); } /***************************************************************************** * * Force an update of the current state, only emitting commands * that actually change anything. */ static void update_current() { RTFStyle *style; if (Cformatting_char) { if(!CURRENT(char_attr.FontSize)) set_fontsize(rtf_ptr->char_attr.FontSize); if(!CURRENT(char_attr.sub_super_height)) set_subsuper(rtf_ptr->char_attr.sub_super_height); if(!CURRENT(char_attr.smallcaps)) set_smallcaps(); if(!CURRENT(char_attr.font)) if(rtf_ptr->char_attr.font == Bold) { if (initialised) set_font(Bold,1,"\n{\\bf ","}"); else set_font(Bold,1,"\n\\bf ",""); } if(!CURRENT(char_attr.font)) if(rtf_ptr->char_attr.font == Italic) { if (initialised) set_font(Italic,1,"\n{\\it ","}"); else set_font(Italic,1,"\n\\it ",""); } } if (Cformatting_para) { if(!CURRENT(par_attr.flags)) switch (rtf_ptr->par_attr.flags) { case Centred: output_str("\n\\begin{center}",'\0'); push_LaTeX_stack("\n\\end{center}",Paragraph,0); break; case RightAlign: output_str("\n\\begin{flushright}",'\0'); push_LaTeX_stack("\n\\end{flushright}",Paragraph,0); break; case LeftAlign: output_str("\n\\begin{flushleft}",'\0'); push_LaTeX_stack("\n\\end{flushleft}",Paragraph,0); break; default: /* block modus (LaTeX default)*/ break; } if(!CURRENT(par_attr.parindent)) { if (rtf_ptr->par_attr.parindent==LaTeXdefault) sprintf(buff,"\n\\setlength{\\parindent}{\\defaultparindent}"); else sprintf(buff,"\n\\setlength{\\parindent}{%gpt}", TW_TO_PT(rtf_ptr->par_attr.parindent)); output_str(buff,'\0'); } if (!CURRENT(par_attr.skip_before) || !CURRENT(par_attr.skip_after)) { int skip; skip=rtf_ptr->par_attr.skip_after+rtf_ptr->par_attr.skip_before; sprintf(buff,"\n\\setlength{\\parskip}{%gpt}", TW_TO_PT(skip)); output_str(buff,'\0'); } if((!CURRENT(par_attr.leftskip) || !CURRENT(par_attr.rightskip)) && rl_skip_on) { if ((rtf_ptr->par_attr.leftskip!=0) || (rtf_ptr->par_attr.rightskip!=0) ) { output_str("\n\\begin{list}",'\0'); output_str("{ }{",'\0'); sprintf(buff,"\n\\setlength{\\leftmargin}{%gpt}", TW_TO_PT(rtf_ptr->par_attr.leftskip)); output_str(buff,'\0'); sprintf(buff,"\\setlength{\\rightmargin}{%gpt}", TW_TO_PT(rtf_ptr->par_attr.rightskip)); output_str(buff,'\0'); output_str("\n\\setlength{\\topsep}{0pt}",'\0'); output_str("\\setlength{\\partopsep}{0pt}",'\0'); output_str("}\n\\item ",'\0'); push_LaTeX_stack("\n\\end{list}",LRskip,0); } } } rtf_current = *rtf_ptr; rtf_current.LaTeX_stack = NULL; rtf_current.prev = NULL; } /***************************************************************************** * * ALLDONE */ #define SET_FONT(FONT,START,END) /* set a Font */\ if(text_out && initialised) { \ set_font(FONT,(rtfParam == 0 ? 0 : 1),START,END); \ } \ rtf_ptr->char_attr.font = (rtfParam == 0 ? 0 : FONT); #define SET_FONTSIZE(FONTSIZE) /* set a Fontsize */\ if(text_out && initialised) { \ set_fontsize(FONTSIZE); \ } \ rtf_ptr->char_attr.FontSize = FONTSIZE; static void CharAttr() { switch (rtfMinor) { case rtfPlain: if(text_out) { while(top_LaTeX_flags(Underline) || top_LaTeX_flags(Sub_Super) || top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num)) (void)pop_LaTeX_stack(); } rtf_ptr->char_attr = rtf_default.char_attr; rtf_current.char_attr = rtf_default.char_attr; break; case rtfBold: SET_FONT(Bold,"\n{\\bf ","}"); break; case rtfItalic: SET_FONT(Italic,"\n{\\it ","}"); break; case rtfAllCaps: { static int count; if(verbose > 1 || (verbose && count++ == 0)) { msg_map_to("ac","sc"); } } case rtfSmallCaps: if(text_out && initialised) set_smallcaps(); rtf_ptr->char_attr.smallcaps = 1; break; case rtfStrikeThru: case rtfOutline: case rtfShadow: case rtfInvisible: { static int count = 0; if(verbose > 1 || (verbose && count == 0)) msg_not_supported( rtfMinor == rtfStrikeThru ? "strike" : rtfMinor == rtfOutline ? "outl" : rtfMinor == rtfShadow ? "shad" : rtfMinor == rtfInvisible ? "v" : "Unknown"); count++; } break; case rtfFontNum: break; case rtfFontSize: SET_FONTSIZE(rtfParam/2); break; case rtfDbUnderline: case rtfDUnderline: if (!noUnderline) { if (initialised) { output_str("\n\\underline{\\underline{",'\0'); push_LaTeX_stack("}}",Underline,0); } /* else doesn't work in LaTeX { output_str("\n\\underline \\bgroup \\underline \\bgroup",'\0'); push_LaTeX_stack("\\egroup \\egroup",Underline,0); } */ break; } case rtfUnderline: case rtfWUnderline: { static int count = 0; if (!noUnderline) { if (initialised) { output_str("\n\\underline{",'\0'); push_LaTeX_stack("}",Underline,0); } /* else doesn't work in LaTeX { output_str("\n\\underline \\bgroup",'\0'); push_LaTeX_stack("\\egroup",Underline,0); } */ } else { if(verbose > 1 || (verbose && count++ == 0)) { msg_map_to((rtfMinor == rtfUnderline ? "ul" : "ulw"),"i"); } rtfMinor = rtfItalic; CharAttr(); } } break; case rtfNoUnderline: break; case rtfSubScript: case rtfSuperScript: if(rtf_ptr->char_attr.sub_super_height == rtfParam) break; if(!text_out && initialised) start_para(); if(text_out && initialised) { set_subsuper(rtfParam); } rtf_ptr->char_attr.sub_super_height = rtfParam; break; case rtfForeColor: msg_not_supported("cf"); break; case rtfBackColor: break; case rtfExpand: msg_not_needed("expnd"); break; case rtfRevised: break; } } /***************************************************************************** * * Various ways of refusing to deal with a keyword * * * Treat \from as \to (e.g. treat \ul as \i) */ static void msg_map_to(from,to) char *from, *to; { if(verbose && !writing_defs) { fprintf(stderr,"I'm going to treat \\%s as \\%s\n",from,to); } } /* * Keyword is neither needed by LaTeX or supported by rtf2LaTeX * For example, \expnd to fiddle with inter-character spacing. */ static void msg_not_needed(name) char *name; { if(verbose && !writing_defs) { fprintf(stderr,"\\%s is neither needed nor supported\n",name); } } /* * Keyword isn't supported, and probably can't be * For example, \cf to change colours */ static void msg_not_supported(name) char *name; { static int pointer = 0; for (pointer=0;(name[pointer]!='\0' && isalpha(name[pointer]));pointer++) continue; /* Should fix problem writing to string constants with gcc */ if(name[pointer] != '\0') name[pointer]='\0'; /*No argument will be printed*/ if(verbose && !writing_defs) { fprintf(stderr,"%s: Don't support \\%s; sorry\n",progname,name); } } /* * Keyword will be supported, but I haven't done it yet */ static void msg_not_yet(name) char *name; { if(verbose && !writing_defs) { fprintf(stderr,"%s: Don't support \\%s yet; be patient\n",progname,name); } } /***************************************************************************** * * Convert a string to a form that LaTeX can handle * * Remove spaces and capitalise the following letter, * and converted digits to letters (1 --> A etc., 0 --> O) */ static char * LaTeX_name(str) char *str; { static char temp[50]; char *ptr; for(ptr = temp;*str != '\0';str++) { if(isspace(*str)) { for(str++;isspace(*str);str++) continue; if(*str == '\0') break; *str = islower(*str) ? toupper(*str) : *str; str--; continue; /* reprocess the character */ } else if(isdigit(*str)) { if(*str == '0') *ptr++ = 'O'; else *ptr++ = *str + 'A' - '1'; } else { *ptr++ = *str; } } *ptr = '\0'; return(temp); } /*****************************************************************************/ static void usage() { static char *msg[] = { "Your options are:", " -c No character formatting stuff", " -C file Use another translation-file for characters above 128", " -d Use WORD formates within special WORD styles ", " like heading, footnote text, ...", " -H Use LaTeX header and footer, not as default WORD header", " -h This message", " -L file Use another translation-file for specilal WORD styles", " like heading, footer, footnote text, ...", " -n Use \\hfill instead of \\\\ for making a new line", " -p No paragraph formatting stuff", " -r No left or right skip", " -s No tab stops", " -t No formatting in tables", " -T f Decrease-factor for the cell-width (default:0.7)", " -u Change underline to italic", " -v[#] Turn on verbose messages; the higher #, the more messages", " -V Print the version number", "If you omit the filename rtf2LaTeX will read standard input.", "\nIf there are any LaTeX errors or warnings,", "have a look in the man page section troubleshooting.\n ", NULL, }; fprintf(stderr, "Usage: %s [options] [RTF-file]\n", progname); print_text(msg,stderr); } /***************************************************************************** * * print some text MSG to a stream FIL */ static void print_text(msg,fil) char *msg[]; FILE *fil; { char **line; for(line = msg;*line != NULL;line++) { fprintf(fil,"%s\n",*line); } } /***************************************************************************** * * set a Font */ static void set_font(font,turn_on,start,end) int font; /* flag for font to set (e.g. Bold) */ int turn_on; /* should I start the font or end it?*/ char *end; /* strings to start and */ char *start; /* end the group that sets the font */ { if(turn_on && Cformatting_char) { if(!no_grouping) { push_LaTeX_stack(end,Font,font); } output_str(start,'\0'); } } /***************************************************************************** * * change fontsize */ void set_fontsize(fontsize) int fontsize; /* size of fonts default 10 */ { if (fontsize<0) { p6("set_fontsize\nfontsize<0"); return; } if (fontsize==0) { p6("set_fontsize\nfontsize==0"); return; } if (!Cformatting_char) { return; } if (fontsize==8) { (void)RTFGetToken(); if (strcmp(rtfTextBuf,"\\up6")==0) { RTFUngetToken(); return; /* mostly we are before a footnote here */ } /* so we need no size-command, because */ RTFUngetToken(); /* LaTeX deel in a good way with it */ } fputc('%',stdout); output('\n',1); if (initialised) /* in newenvironment {} not necessary */ { push_LaTeX_stack("}",Font,0); output_str("{",'\0'); } if (fontsize<5) { output_str("\\tiny ",'\0'); return; } if (fontsize<7) { output_str("\\scriptsize ",'\0'); return; } if (fontsize<9) { output_str("\\small ",'\0'); return; } if (fontsize<11) { output_str("\\normalsize ",'\0'); return; } if (fontsize<13) { output_str("\\large ",'\0'); return; } if (fontsize<17) { output_str("\\Large ",'\0'); return; } if (fontsize<21) { output_str("\\LARGE ",'\0'); return; } if (fontsize<25) { output_str("\\huge ",'\0'); return; } output_str("\\Huge ",'\0'); } /***************************************************************************** * * set higher or lower text */ static void set_subsuper(param) int param; { if(param == 0) { /* end of a sub/superscript */ while(!top_LaTeX_flags(Sub_Super)) { if(pop_LaTeX_stack() == 0) { if(verbose) { fprintf(stderr,"%s: Failed to find end of sub/superscript\n", progname); } return; } } pop_LaTeX_stack(); /* pop off the '}' */ if(top_LaTeX_flags(Math)) pop_LaTeX_stack(); /* and pop math too */ return; } if (rtfMinor == rtfSuperScript) { (void)RTFGetToken(); if (strcmp(rtfTextBuf,"\\chftn")==0) return; /* we are before a footnote here */ RTFUngetToken(); /* so we need no command, because */ } /* LaTeX deels with it in a good way */ output_str("$",'\0'); push_LaTeX_stack("$",Sub_Super,1); if (initialised) { output_str(rtfMinor == rtfSuperScript ? "^{" : "_{",'\0'); push_LaTeX_stack("}",Sub_Super,rtfParam); } else { output_str(rtfMinor == rtfSuperScript ? "^" : "_",'\0'); output_str(" \\bgroup",'\0'); push_LaTeX_stack(" \\egroup",Sub_Super,rtfParam); } } /***************************************************************************** * * set smallcaps */ static void set_smallcaps() { fputc('%',stdout); output('\n',1); if (initialised) { output_str("{",'\0'); push_LaTeX_stack("}",Font,0); } output_str("\\sc ",'\0'); } /***************************************************************************** * * Print a string, ensuring that we are in math mode at the time */ static void in_math(str) char *str; { output('$',0); output_str(str,'\0'); output('$',0); } /***************************************************************************** * * Write a character, filling the the output text as we go. Characters * special to LaTeX are treated appropriately. */ #define FILL_COLUMN 60 /* column to fill to */ #define MAX_COLUMN 80 /* max of column*/ static int column=0; /* current column */ static void output(c,quote) int c; /* The char to print */ int quote; /* quote LaTeX's special chars? */ { char temp[25]; c &= '\377'; /* prevent sign extension */ if(isspace(c)) { if(c == '\n') { fputc('\n',stdout); column=0; } else { fputc(' ',stdout); column++; if (column>FILL_COLUMN) { fputc('\n',stdout); column=0; } } return; } if(quote) { switch (rtf_ptr->char_attr.FontType) { case rtfFFTech: /* A technical font */ { char *str; str = (c < 128) ? symbol[c] : symbol8[c & '\177']; if(*str == '\0') { /* if(verbose) { */ fprintf(stderr,"%s: Unknown Tech character: 0x%x\n", progname,c); /* } */ } if(verbose) { fprintf(stderr,"A Tech character: 0x%x\n",c); } in_math(str); } return; default: switch (c) { /* deal with various characters */ case '%': case '$': case '#': case '&': case '_': fputc('\\',stdout); column++; break; case '^': output_str("$^{\\wedge}$",'\0'); return; case '"': if(translate_quotes) c = (quotecount++ % 2) ? '\'' : '`'; else c = '`'; fputc(german_dquotes ? '"' : c, stdout); column++; break; case '<': case '>': case '|': sprintf(temp,"%c",c); in_math(temp); return; case '{': case '}': sprintf(temp,"\\%c",c); in_math(temp); return; case '\\': in_math("\\backslash"); return; case '~': in_math("\\sim"); c = ' '; return; default: if(!isascii(c)) { output_8bit(c); return; } if(!isalnum(c) && !ispunct(c)) { if (verbose) fprintf(stderr,"%s: Unknown 7-bit character: 0x%x\n", progname,c); return; } break; } } } fputc(c,stdout); column++; } /***************************************************************************** * * Output an entire word, without trying to quote any special characters. * The character C is then output using output(), which allows proper page * breaks. */ static void output_str(str,c) char *str; int c; { int len = strlen(str); int zeiger=0; if(c != '\0') { output(c,1); } if (column==0 && str[0]=='\n') str++; if (str[0]=='\n') fputc('%',stdout); fprintf(stdout,"%s",str); column+=len; if (str[0] =='\n') column=len; if (str[len-1] == '\n') column=0; } /***************************************************************************** * * Deal with special characters above \177. */ typedef struct Char8bit { int nr; /* RTF-code */ char *str; /* LaTeX command */ struct Char8bit *next; }char8; char8 *list_8bit; /* begin of the 8bit list */ char8 *help; /***************************************************************************** * * write a 8bit character */ static void output_8bit(c) int c; { char *str; help=list_8bit; while(help->nr!=c && help->next!=NULL) /* search for the character*/ help=help->next; if (help->nr==c) { output_str(help->str,'\0'); /* and write it */ } else { /* character not found */ if(verbose) { static count=0; fprintf(stderr,"%s: Unknown 8-bit character: 0x%x\n",progname,c); if (count++<1||verbose>1) fprintf(stderr," Have a look in the file .cod\n"); } } } /***************************************************************************** * * read the file mac.code (or an other file e.g. ansi.code: use flag -C) * and store the commands for characters with the 8bit set in the list * "list_8bit" */ static void read_code_file(codefile) char *codefile; { char line[line_length]; int pos; open_code_file(codefile); if (fgets(line,line_length,fpcode)==NULL) { fprintf(stderr,"\n%s: Incorrect file a8bit \ \nat first there must be a number of the ascii character with msb set \ \n(between 128 and 255)\n",progname); exit(1); } for (pos=23;line[pos]==' ';pos--); line[pos+1]='\0'; /* cut the comment in the file*/ list_8bit=(struct Char8bit *)malloc((int)sizeof(struct Char8bit)); if (list_8bit==(struct Char8bit *)NULL) { fprintf(stderr,"%s: TCErr - cannot allocate a 8bit-character name\n", progname); exit(1); } sscanf(line,"%d",&(list_8bit->nr)); list_8bit->str=StrSave(line+4); if (list_8bit->nr<128 || list_8bit->nr>255) { fprintf(stderr,"\n%s: Incorrect file a8bit \ \nat first there must be a number of the ascii character with msb set \ \n(between 128 and 255)\n", progname); exit(1); } list_8bit->next=NULL; while (fgets(line,line_length,fpcode)!=NULL) { for (pos=23;line[pos]==' ';pos--); line[pos+1]='\0'; help=(struct Char8bit *)malloc((int)sizeof(struct Char8bit)); if (help==(struct Char8bit *)NULL) { fprintf(stderr,"%s: SSErr - cannot allocate a 8bit-character name\n", progname); exit(1); } help->next=list_8bit; list_8bit=help; sscanf(line,"%d",&(list_8bit->nr)); list_8bit->str=StrSave(line+4); if (list_8bit->nr<128 || list_8bit->nr>255) { fprintf(stderr,"\n%s: Incorrect file a8bit \ \nat first there must be a number of the ascii character with msb set \ \n(between 128 and 255)\n", progname); exit(1); } } if (fpcode!=NULL) fclose(fpcode); } /***************************************************************************** * * write an errormassage to stderr * */ static void p6(proc_name) char *proc_name; /*name of ther procedure where the mistake must be */ { fprintf(stderr," %s: Problem in procedure %s\n",progname,proc_name); fprintf(stderr," please call Erwin Wechtl\n"); fprintf(stderr," W""ortgasse 2/18\n"); fprintf(stderr," A-2500 Baden\n"); fprintf(stderr," Austria\n"); fprintf(stderr," Tel.: 43/2252/44686\n"); } /***************************************************************************** * * set end af table */ static void end_table() { table_mode=0; if (top_LaTeX_flags(Tabular)) { Cformatting_char=formatting_char; Cformatting_para=formatting_para; pop_LaTeX_stack(); tabinitold[0]='\0'; output_str("\n \n",'\0'); } } /***************************************************************************** * * translate each RTF-style into a new LaTeX environment * and look for special WORD styles like heading (tranlated into section) * or footer (ignored) */ LATEXStyle *LaTeXstyleList; /* we can't use the RTFstylelist because we need more variables */ void DefineStyles() { RTFStyle *rtfstyle; /* the style to deel with */ LATEXStyle *LaTeXstyle; /* the style to deel with */ output_str("\n \n",'\0'); LaTeXstyleList=(LATEXStyle *)NULL; for(rtfstyle=RTFGetStyle(-1);rtfstyle!=(RTFStyle *)NULL;rtfstyle=rtfstyle->rtfNextStyle) { LaTeXstyle=(LATEXStyle *)malloc(sizeof(struct LATEXStyle)); if (LaTeXstyle==NULL) { fprintf(stderr,"\n%s: Can't alloc LaTeXstyle\n",progname); exit(1); } LaTeXstyle->stacktype=Undefined; LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0'; LaTeXstyle->special_WinwordStyle=TRUE; if (!is_specialWORDstyle(rtfstyle,LaTeXstyle)) /* looking for special styles */ { char commandbuf[80]; RTF_STACK rtf_save; push_rtf_group(); rtf_save = rtf_current; LaTeXstyle->special_WinwordStyle=FALSE; LaTeX_name(rtfstyle->rtfSName); strcpy(commandbuf,"\n\\"); strcat(commandbuf,"begin{"); strcat(commandbuf,rtfstyle->rtfSName); strcat(commandbuf,"}\n"); strcpy(LaTeXstyle->BeginCommand,commandbuf); strcpy(commandbuf,"\n\\"); strcat(commandbuf,"end{"); strcat(commandbuf,rtfstyle->rtfSName); strcat(commandbuf,"}\n"); strcpy(LaTeXstyle->EndCommand,commandbuf); output_str("\n% definition of ",'\0'); output_str(rtfstyle->rtfSName,'\0'); output_str("\n\\newenvironment{",'\0'); output_str(rtfstyle->rtfSName,'\0'); output_str("}{",'\0'); RTFExpandStyle(rtfstyle->rtfSNum); LaTeXstyle->char_attr=rtf_ptr->char_attr; LaTeXstyle->par_attr=rtf_ptr->par_attr; LaTeXstyle->stacktype=NormalWORDstyle; update_current(); output_str("}{",'\0'); while(pop_LaTeX_stack()) continue; output_str("}\n",'\0'); rtf_current = rtf_save; pop_rtf_group(); } LaTeXstyle->rtfSNum=rtfstyle->rtfSNum; LaTeXstyle->rtfSName=rtfstyle->rtfSName; LaTeXstyle->LaTeXNextStyle=LaTeXstyleList; LaTeXstyleList=LaTeXstyle; } if (fpland!=NULL) fclose(fpland); } /***************************************************************************** * * begin a style environment */ void setstylecommand(n) int n; /* rtfStyleNumber */ { LATEXStyle *LaTeXstyle; RTFStyle *rtfstyle; char buf[80]; if(!table_mode && top_LaTeX_flags(Tabular)) end_table(); LaTeXstyle=LaTeXstyleList; while (LaTeXstyle!=NULL && LaTeXstyle->rtfSNum!=n) LaTeXstyle=LaTeXstyle->LaTeXNextStyle; if (LaTeXstyle==NULL) { static int count=0; rtfstyle=RTFGetStyle(n); if (verbose>1 || (verbose && count++==0)) { fprintf(stderr,"%s: There are some troubles with the style %s with the number %d, \n so this style is ignored\n", progname,rtfstyle->rtfSName,n); } # ifdef notdef /* Don't know if this is needed anymore */ /* sprintf(buf,"\n%% The Style %s with the number %d may begin here\n",rtfstyle->rtfSName,n); output_str(buf,'\0'); output_str("%%But rtf2LaTeX has had some troubles with it",'\0'); sprintf(buf,"\n% The Style %s with the number %d may end here\n",rtfstyle->rtfSName,n); push_LaTeX_stack(buf,NormalWORDstyle,0); */ # endif /* notdef */ return; } if (LaTeXstyle->special_WinwordStyle) /* if heading,footer, ... */ { /* use paragraph(character) formating only if the flag -d is on */ Cformatting_para=formatting_sWORD&&formatting_para; Cformatting_char=formatting_sWORD&&formatting_char; } else { update_current(); /* format */ rtf_current.par_attr=LaTeXstyle->par_attr; rtf_current.char_attr=LaTeXstyle->char_attr; rtf_ptr->par_attr=LaTeXstyle->par_attr; rtf_ptr->char_attr=LaTeXstyle->char_attr; rtf_current.LaTeX_stack = NULL; rtf_current.prev = NULL; } output_str(LaTeXstyle->BeginCommand,'\0'); push_LaTeX_stack(LaTeXstyle->EndCommand,LaTeXstyle->stacktype,0); } /***************************************************************************** * * look in the file english.land (or an other file e.g. german.land: * use flag -L) * if this is a Spezial WORD style like heading, footer, ... */ int is_specialWORDstyle(rtfstyle,LaTeXstyle) RTFStyle *rtfstyle; LATEXStyle *LaTeXstyle; { char line[line_length]; /* the line which is read from the file */ if (formatting_sWORD) /* if flag -d is on */ return(0); /* use WORD formate instead of LaTeX formate within header, ... */ fseek(fpland, 0, SEEK_SET); while (fgets(line,line_length,fpland)!=NULL) { if (strncmp(rtfstyle->rtfSName,line,strlen(rtfstyle->rtfSName))==0) { LaTeXstyle->stacktype=SpecialWORDstyle; if (strncmp(line+20," ",10)!=0) sscanf(line+20,"%20s%20s",LaTeXstyle->BeginCommand,LaTeXstyle->EndCommand); else LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0'; output_str("% ",'\0'); output_str(line+60,'\0'); return(1); } } return(0); } /***************************************************************************** * * malloc for a string */ static char *StrSave (s) char *s; { char *p; if ((p = (char *)malloc (strlen (s) + 1)) == (char *) NULL) fprintf(stderr,"%s: Error in malloc\n",progname); return (strcpy (p, s)); } /***************************************************************************** * * set the position of the Tabstops and output the begin environment */ static void start_tabstops() { int i,j; int width; /* width of table entry (twips) */ char buf[1]; if (top_LaTeX_flags(SpecialWORDstyle)) return; /* no tab stops in header, heading, ...*/ Cformatting_char=formatting_char&&formatting_table; Cformatting_para=formatting_para&&formatting_table; output_str("\n\\begin{tabbing}\n",'\0'); for(i = 0;i < NTABS;i++) { width = tabstops[i].pos; if(i > 0) width -= tabstops[i - 1].pos; width=TW_TO_CA(width); if (width<1) continue; for(j=1;j<=width;j++) { sprintf(buf,"%d",(j % 10)); output_str(buf,'\0'); } output_str("\\=",'\0'); } output_str("\\kill\n",'\0'); push_LaTeX_stack("\\end{tabbing}\n",Tabstops,0); tabstopsInit(); tab=2; } /***************************************************************************** * * initialise the array of the Tabstops-positions */ static void tabstopsInit() { int i; for (i=0;iprev == NULL) { fprintf(stderr,"%s: Attempt to pop an empty stack\n", progname); abort(); } temp = rtf_ptr->prev; rtf_ptr->prev = rtf_free_list; rtf_free_list = rtf_ptr; rtf_ptr = temp; } /* * push the RTF status stack */ static void push_rtf_group() { RTF_STACK *temp; if(rtf_free_list != NULL) { temp = rtf_free_list; rtf_free_list = rtf_free_list->prev; } else { if((temp = (RTF_STACK *)malloc(sizeof(RTF_STACK))) == NULL) { fprintf(stderr,"%s: Can't allocate storage for stack\n",progname); exit(1); } } memcpy((char *)temp,(char *)rtf_ptr,sizeof(RTF_STACK)); temp->prev = rtf_ptr; rtf_ptr = temp; rtf_ptr->LaTeX_stack = NULL; } /***************************************************************************** * * Now the LaTeX stacks. Use the stack in the current rtf_ptr frame */ static LATEX_STACK *myTeX_free_list = NULL; static int pop_LaTeX_stack() { char *str; LATEX_STACK *temp; if(rtf_ptr->LaTeX_stack == NULL) { return(0); } if (rtf_ptr->LaTeX_stack->type == SpecialWORDstyle) { /* reset formatting */ Cformatting_para =formatting_para; /* after heading, footer, .. */ Cformatting_char=formatting_char; } LaTeX_group--; str = rtf_ptr->LaTeX_stack->str; temp = rtf_ptr->LaTeX_stack->prev; rtf_ptr->LaTeX_stack->prev = myTeX_free_list; myTeX_free_list = rtf_ptr->LaTeX_stack; rtf_ptr->LaTeX_stack = temp; output_str(myTeX_free_list->str,'\0'); return(1); } /* * push the string STR onto the LaTeX stack, with attributes TYPE and FLAGS */ static void push_LaTeX_stack(str,type,flags) char *str; /* string to save */ int type; /* type of string */ long flags; /* and corresponding flags */ { LATEX_STACK *temp; LaTeX_group++; if(myTeX_free_list != NULL) { temp = myTeX_free_list; myTeX_free_list = myTeX_free_list->prev; } else { if((temp = (LATEX_STACK *)malloc(sizeof(LATEX_STACK))) == NULL) { fprintf(stderr,"%s: Can't allocate storage for stack\n",progname); exit(1); } } temp->prev = rtf_ptr->LaTeX_stack; rtf_ptr->LaTeX_stack = temp; rtf_ptr->LaTeX_stack->str = str; rtf_ptr->LaTeX_stack->type = type; rtf_ptr->LaTeX_stack->flags = flags; return; } /***************************************************************************** * * Return the flags of the proper type for the top element of the LaTeX stack */ static int top_LaTeX_flags(type) int type; { return((rtf_ptr->LaTeX_stack != NULL && rtf_ptr->LaTeX_stack->type == type) ? 1 : 0); } /*****************************************************************************/ static void open_code_file (codefile) char *codefile; { char *filename; char line[line_length]; char c; if((filename = malloc(strlen(codefile) + strlen(RTFDIR) + 7)) == NULL) { fprintf(stderr,"%s: Error in malloc\n",progname); exit(3); } strcpy(filename,RTFDIR); #if !defined (THINK_C) strcat(filename,"/"); #endif /* !THINK_C */ strcat(filename,codefile); if ((strchr(codefile,'.')) == NULL) strcat(filename,".code"); if((fpcode = fopen(filename,"r")) == NULL) { fprintf(stderr,"%s: Can't open %s\n",progname,filename); exit(1); } free(filename); if (fgets(line,line_length,fpcode)==NULL) { fprintf(stderr,"\n%s: Incorrect file a8bit \ \nthere must be a comment in the first line\n", progname); exit(1); } } static void open_land_file (landfile) char *landfile; { char *filename; if((filename = malloc(strlen(landfile) + strlen(RTFDIR) + 7)) == NULL) { fprintf(stderr,"%s: Error in malloc\n",progname); exit(3); } strcpy(filename,RTFDIR); #if !defined (THINK_C) strcat(filename,"/"); #endif /* !THINK_C */ strcat(filename,landfile); if ((strchr(landfile,'.')) == NULL) strcat(filename,".land"); if((fpland = fopen(filename,"r")) == NULL) { fprintf(stderr,"%s: Can't open %s\n",progname,filename); exit(1); } free(filename); }