home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-08-18 | 34.8 KB | 1,457 lines |
- Newsgroups: comp.text.frame
- Path: sparky!uunet!europa.asd.contel.com!darwin.sura.net!convex!convex!connolly
- From: connolly@convex.com (Dan Connolly)
- Subject: mif2rtf.pl: here it is.
- Summary: perl script to convert FrameMaker MIF files to MS Word RTF format
- Sender: usenet@news.eng.convex.com (news access account)
- Message-ID: <1992Aug18.202733.21362@news.eng.convex.com>
- Date: Tue, 18 Aug 1992 20:27:33 GMT
- Nntp-Posting-Host: pixel.convex.com
- Organization: Engineering, CONVEX Computer Corp., Richardson, Tx., USA
- Keywords: MIF RTF perl Rich Text Format filter
- X-Disclaimer: This message was written by a user at CONVEX Computer
- Corp. The opinions expressed are those of the user and
- not necessarily those of CONVEX.
- Lines: 1440
-
- I have had a number of requests for this beast over the last
- year or so. I don't use the perl script any more -- the version
- under development uses XLisp in stead.
-
- But a lot of folks have had good luck with it. It converts
- basic character and paragraph formatting. It does pretty
- much what you'd expect for letters and memo's. Somebody
- had good luck with a 90 page document. (Chalk one up
- for perl! It scales well.)
-
- I have one request: would somebody archive this thing on
- an FTP server and let me know where you put it?
-
- Anyway, here it is:
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Wrapped by pixel!connolly on Tue Aug 18 15:21:58 CDT 1992
- # Contents: mif2rtf.pl
-
- echo x - mif2rtf.pl
- sed 's/^@//' > "mif2rtf.pl" <<'@//E*O*F mif2rtf.pl//'
- #!/usr/local/bin/perl
- # $Id$
- #
- # USE
- #
- $Usage = "
- $0 -d [mif_file]... >out.rtf
- -d turn on debugging
- -info TAG GROUP Put all text from TAG paragraphs into info group GROUP
- ";
- #
- # Code marked @@ needs fixing.
- # Code marked @# is an improvisation
- # Code marked HEURISTIC is not exact.
- #
- # COPYRIGHT
- #
- # Copyright 1992 by Convex Computer Corporation, Richardson, Texas.
- #
- # All Rights Reserved
- #
- # Permission to use, copy, modify, and distribute this software and its
- # documentation for any purpose and without fee is hereby granted,
- # provided that the above copyright notice appear in all copies and that
- # both that copyright notice and this permission notice appear in
- # supporting documentation, and that the name Convex not be
- # used in advertising or publicity pertaining to distribution of the
- # software without specific, written prior permission.
- #
- # CONVEX DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- # CONVEX BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- # SOFTWARE.
- #
- # BUGS
- #
- # @#Footnote paragraph formats not right
- # @#should convert page margins (frame BRect->margr etc.)
- # @#No way to make TOC entries
- # @#master pages
- # @# Not all document, section, or table properties are converted.
- # @#Hard problems: reference page items
- # Maybe use command line options for those.
- # @# LineSpacing doesn't translate
- #
- # IDEAS
- # absolute positioned object: frame brect etc.
- #
-
- #########
- #
- # main
- #
-
- local($Debug,
- #
- # %TagGroup maps MIF paragraph tags to RTF info groups
- # %RTFInfo holds the text of the RTF info groups
- # so that after &convert_pages(),
- # $RTFInfo{$TagGroup{pgftag}} contains all text tagged pgftag
- #
- # @@ idea: extend this to character tags
- #
- %TagGroup
- );
- @@ARGV = &parse_args(@ARGV);
-
-
- local(%State,
- #
- # %State maps MIF and RTF codes to their current settings
- #
- %CharacterConversions
- );
- &initialize_state();
-
- local($Document,
- # $Document is the RTF code to get from the default
- # document format to what's in %State
- # NOTE: some MIF document attrs are RTF Section attrs
- # ASSUME: MIF document defaults are RTF defaults
-
- %Typeface, $Typeface,
- # %Typeface maps FFamilys to RTF font numbers
-
- %Tag, $Tag,
- # %Tag maps PgfTags to RTF style numbers
-
- %PgfCatalog, %FontCatalog,
-
- @BodyPage,
- %TextRect, %TextFlow,
- %AFrame,
- %Tbl
- );
-
- $Document = "\\ftnbj "; # This is the default in Frame, but not in Word.
-
- local($PageType, $TextRectID, $ID, $TblID,
- $XRefName, $VaraibleName);
-
- &read_whole_file
- ('DPageSize', '$Document. = &change_dims($data, "paperw", "paperh")',
- 'DStartPage', '$Document .= &change_attr("pgnstarts", $data)',
- 'DPageNumStyle', '$Document .= &select_attr($data, "PageNumStyle",
- "Arabic", "pgndec",
- "UCRoman", "pgnucrm",
- "LCRoman", "pgnlcrm",
- "UCALpha", "pgnucltr",
- "LCAlpha", "pgnlcltr")',
- 'DTwoSides', '$Document .= &change_attr("facingp", 1)',
- 'DFNoteRestart', '$Document .= &select_attr($data, "FNoteRestart",
- "PerPage", "ftnrestart")',
- 'DFNoteStartNum', '$Document .= &change_attr("fntstart", $data)',
- 'DAutoChBars', '$Document .= &change_attr("revisions", 1)',
-
- 'FFamily', '&intern(*Typeface, $data)',
- 'PgfTag', '&intern(*Tag, $data)',
-
- 'PgfCatalog', '&convert_paragraph_catalog($here)',
- 'FontCatalog', '&convert_character_catalog($here)',
-
- 'PageType', '$PageType = $data',
- 'Page', 'push(@BodyPage, $here) if $PageType eq "BodyPage"',
-
- 'TextRectID',
- '$TextRectID ? &debug("Extra TextRect: $data") : ($TextRectID = $data)',
-
- 'TextFlow', '@TextRect{$TextRectID} = $here;
- &debug("flow", %TextRect); $TextRectID = ""',
-
- 'Frame', '$AFrame{&data_search($here, "ID", 1)} = $here',
-
- 'TblID', '$TblID = $data',
- 'Tbl', '$Tbl{$TblID} = $here',
-
- 'XRefName', '$XRefName = &convert_string($data)',
- 'XRefDef', '$Definition{"XRef", $XRefName} = $data',
-
- 'VarialbeName', '$VariableName = &convert_string($data)',
- 'VariableDef', '$Definition{"Variable", $VariableName} = $data'
- );
-
- print STDOUT &rtf_begin_doc;
- print STDOUT &rtf_font_table(%Typeface);
- print STDOUT &rtf_color_table(('0 0 0 Black', # These are Frame's colors
- '1 1 1 White',
- '1 0 0 Red',
- '0 1 0 Green',
- '0 0 1 Blue',
- '0 1 1 Cyan',
- '1 0 1 Magenta',
- '1 1 0 Yellow'));
-
- print STDOUT $Document, "\n";
-
- #&debug("body pages: ", @BodyPage);
-
- local(@Document);
-
- foreach $page (@BodyPage){
- # &debug("converting page:\n", &expand_mif_statement($page));
- push(@Document, &convert_frame($page));
- }
-
- if(!defined($StyleSheet) || $StyleSheet) {
- print STDOUT &rtf_style_sheet(%Tag);
- }
- print STDOUT &rtf_info(%RTFInfo);
- print STDOUT @Document;
- print STDOUT &rtf_end_doc;
-
- print STDERR "\n"; # after all the .....'s
-
- ######
-
- sub parse_args{
- #
- # USE : @ARGV = &parse_args(@ARGV);
- # SETS: $Debug, %TagGroup
- #
- local(@files);
-
- while($_ = shift){
- if(/^-d/){
- $Debug = 'debug';
- }
- elsif(/^-info/){
- $TagGroup{shift} = shift;
- }
- elsif(/^-nostyles/){
- $StyleSheet = 0;
- }else{
- push(@files, $_);
- }
- }
- @files;
- }
-
- #
- #
- ##########
-
-
- ##########
- #
- # Mif Parsing Routines
- #
- # I've finally found a perl representation of a mif file that I'm happy with.
- # It's pretty memory intensive and not real zippy, but that's the nature
- # of the beast with MIF.
- #
- sub read_whole_file{
- local(%Callbacks) = @_;
- # global(@Parts);
- @Parts = (0); # put one element in it so there's no statement 0.
-
- 1 while(&read_mif_statement());
- }
-
-
-
- sub read_mif_statement{
- #
- # Returns an index in @Parts so that
- # $Parts[$index] is the statement type
- # and @Parts[$index+1, $index+2, ...] are the parts of the statement.
- # For compound statement, @Parts[$index, ...] looks like
- # ('<', token, index1, index2, index3, ...)
- # where indexN are the substatements
- #
- # for each statment, $Callbacks{$token} is evaluated
- # with $token, $data, and $here set
- #
-
- local($_, $type, $token, $data, @parts, $here, $line);
- # global(@Parts);
-
- while(<>){
- $line = $.;
- $type = '<>', $token = $1, $data = $2, last
- if /^\s*<(\w+)\s+(.*\S)?\s*>/;
- $type = '<', $token = $1, last
- if /^\s*<(\w+)/;
- return 0 if /^\s*>/;
- $type = '=', $token = $1, $data = &read_mif_inset(), last
- if /^=(\w+)/;
- }
- return 0 unless $type;
-
- local($callback);
- if($type eq '<>' || $type eq '='){
- $here = $#Parts+1;
- push (@Parts, $type, $token, $data);
- eval $callback if $callback = $Callbacks{$token};
- die "$@ $callback" if $@;
- }else{
- while($_ = &read_mif_statement()){
- push(@parts, $_);
- }
- $here = $#Parts+1;
- push(@Parts, '<', $token, @parts);
- eval $callback if $callback = $Callbacks{$token};
- die "$@ $callback" if $@;
- }
-
- $Lines{$here} = $line; # for debugging purposes
- $here;
- }
-
- sub read_mif_inset{
- # Read until a line starts with "=EndInset"
- # and return all the lines concatenated
- local($inset);
- while(<>){
- $inset .= $_;
- last if /^=EndInset/;
- }
- $inset;
- }
-
-
- sub new_statement{
- local($s) = $#Parts + 1;
- push(@Parts, @_);
- return $s;
- }
-
- sub type{
- $Parts[$_[0]];
- }
-
- sub token{
- $Parts[$_[0]+1];
- }
-
- sub data{
- $Parts[$_[0]+2];
- }
-
- sub parts{
- local($i) = @_;
- if(&type($_[0]) eq '<'){
- local($s) = $i+2;
- for(; $Parts[$s] > 0; $s++){
- }
- return @Parts[$i+2 .. $s-1];
- }else{
- return @Parts[$i+2]; #data
- }
- }
-
- sub do_statement{
- # global(@Parts);
- local($__s, %__callbacks) = @_;
- local($here, $__cb);
-
- foreach $here (&parts($__s)){
- local($token) = &token($here);
- local($data) = &data($here);
-
- eval $__cb if $__cb = $__callbacks{$token};
- warn "Error executing: $__cb \n-->$@" if $@;
- warn "IGNORED: $token line:", $Lines{$here}
- if (&type($here) ne '<>') && !$__cb;
-
- &assert('$token =~ /\w+/');
- }
- }
-
-
- sub expand_mif_statement{
- # global(@Parts);
- local($i, $leader) = @_;
- local($_) = &type($i);
-
- if($_ eq '<>'){
- return (sprintf("%s<%s %s>\n", $leader, @Parts[$i+1, $i+2]));
- }elsif($_ eq '='){
- return (sprintf("=%s\n%s", @Parts[$i+1, $i+2]));
- }elsif($_ eq '<'){
- local(@lines);
- @lines = (sprintf("%s<%s\n", $leader, &token($i)));
- foreach (&parts($i)){
- push (@lines, &expand_mif_statement($_, " $leader"));
- }
- push(@lines, "$leader>\n");
- return @lines;
- }
- }
-
-
- sub data_search{
- #
- # use $tag = &data_search($para, 'PgfTag', 2)
- # to search 2 levels of the $para statement,
- # and return the data of the first PgfTag statement found.
- #
- local($s, $t, $levels) = @_;
- foreach (&parts($s)){
- if(&type($_) eq '<'){
- if($levels>1){
- $s = &data_search($_, $t, $levels-1);
- return $s if $s ne '';
- }
- }else{
- return &data($_) if &token($_) eq $t;
- }
- }
- return '';
- }
-
- sub token_search{
- #
- # use &token_search($compound_statement, "token", 3)
- # to search the next three levels of hairy_statement for
- # "token" statements.
- #
- local($s, $t, $levels) = @_;
-
- local(@matches, $_);
-
- foreach (&parts($s)){
- push(@matches, $_) if &token($_) eq $t;
- push(@matches, &token_search($_, $t, $levels-1))
- if &type($_) eq '<' && $levels>1;
- }
- return @matches;
- }
-
-
- #
- #
- ########
-
- ############
- #
- # %State manipulation
- #
-
- sub change_attr{
- local($attr, $val) = @_;
-
- # &debug("change attr: $attr ($State{$attr}) -> [$val]");
- $State{$attr} = $val
- , return "\\$attr$val "
- unless $State{$attr} eq $val;
- '';
- }
-
- sub change_dims{
- local($dims, @attrs) = @_;
- local($_, $r);
-
- foreach (&rtf_dimensions($dims)){
- local($attr) = shift(@attrs);
- last unless $attr;
- $attr =~ s-/(\d+)-- && ($_ = int($_/$1)); #HACK
- $r .= &change_attr($attr, $_);
- }
- $r;
- }
-
- sub select_attr{
- local($key, $s, %attrs) = @_;
-
- if($attrs{$key}){
- # &debug("select attr: '$s=$key' from ", join(",", %attrs)),
- $State{$s} = $attrs{$key}, return "\\$attrs{$key} "
- unless $State{$s} eq $attrs{$key};
- }
- $State{$s} = '';
- }
-
- #############
- #
- # conversions
- #
-
- sub convert_paragraph_catalog{
- local($s) = @_;
- #global(%State, %PgfCatalog);
-
- local($tag);
- &do_statement($s, 'Pgf', '
- $tag = &convert_string(&data_search($here, "PgfTag"));
- $PgfCatalog{"Statement", $tag} = $here;'
- );
- }
-
- sub convert_character_catalog{
- local($s) = @_;
- #global(%State, %FontCatalog);
-
- local($tag);
- &do_statement($s,'Font', '
- $tag = &convert_string(&data_search($here, "FTag"));
- $FontCatalog{"Statement", $tag} = $here;'
- );
- }
-
- sub convert_pgf_format{
- local($s) = @_;
- #
- # Returns RTF to change from what's in %State to what's in $s
- # EXCEPT TABS! use ¤t_tabs() to get them.
- #
-
- local($rtf, $_);
-
- local($lindent) = &data_search($s, 'PgfLIndent');
- local($li);
- if($lindent gt ''){
- ($li) = &rtf_dimensions($lindent);
- $State{'LIndent'}=$lindent;
- }else{
- ($li) = &rtf_dimensions($State{'LIndent'});
- }
-
- local($findent) = &data_search($s, 'PgfFIndent');
- local($fi);
- if($findent gt ''){
- ($fi) = &rtf_dimensions($findent);
- $State{'FIndent'}=$findent;
- }else{
- ($fi) = &rtf_dimensions($State{'FIndent'});
- }
- $rtf .= &change_attr("fi", $fi - $li);
- $rtf .= &change_attr("li", $li);
- &debug("findent: $findent fi: $fi lindent: $findent li: $li");
-
- &do_statement
- ($s,
- 'PgfNumberFont', '$State{"NumberFont"} = &convert_string($data)',
- 'PgfNumFormat', '$State{"NumFormat"} = &convert_string($data)',
- 'PgfNextTag',
- '$rtf .= &change_attr("snext", &intern(*Tag, $data))',
- 'PgfNumTabs', 'undef($State{"TabStops"})',
- 'TabStop', '&TabStop($here)',
- 'PgfAlignment', '$rtf .= &select_attr($data, "Alignment",
- "Left", "ql",
- "Center", "qc",
- "Right", "qr",
- "LeftRight", "qj")',
- # RTF & MIF are different about tabs and first indents
- 'PgfRIndent', '$rtf .= &change_dims($data, "ri")',
-
- 'PgfTopSeparator',
- '$rtf .= &change_attr("brdrt", 1) if $data ne "`\'"', #@#
- 'PgfBotSeparator',
- '$rtf .= &change_attr("brdrb", 1) if $data ne "`\'"', #@#
-
- 'PgfPlacement', '$rtf .= &select_attr($data, "Placement",
- "ColumnTop", "pagebb", #@#
- "PageTop", "pagebb",
- "LPageTop", "pagebb", #@#
- "RPageTop", "pagebb")', #@#
- 'PgfSpBefore', '$rtf .= &change_dims($data, "sb")',
- 'PgfSpAfter', '$rtf .= &change_dims($data, "sa")',
-
- #@# withprev
- 'PgfWithNext', '$rtf .= &select_attr($data, "WithNext",
- "Yes", "keepn", "No", "keepn0")',
- 'PgfBlockSize', '$rtf .= &change_attr("keep", 1) unless $data <2',
- 'PgfLeading', '$rtf .= &change_dims($data, "sl")',
- 'PgfFont', '$rtf .= &convert_char_format($here)'
- );
-
- # &debug("converted $State{'PgfTag'} -> $rtf");
- $rtf;
- }
-
- sub TabStop{
- local($s) = @_;
-
- #@# tab alignment ignored!
- $State{'TabStops'} .= " " . &data_search($s, 'TSX');
- }
-
- sub convert_char_format{
- local($rtf);
- &do_statement
- ($_[0],
- 'FFamily', '$State{"Family"} = &convert_string($data);
- $rtf .= &change_attr("f", &intern(*Typeface, $data))',
- #@# 'FVar', 'warn "IGNORED: Variation $data" unless $data =~ /regular/i',
- 'FWeight', '$rtf .= &select_attr(&convert_string($data),"Weight",
- "Bold", "b", "Regular", "b0")',
- 'FAngle', '$rtf .= &select_attr(&convert_string($data), "Angle",
- "Italic", "i", "Oblique", "i2",
- "Regular", "i0")',
- 'FSize', '$rtf .= &change_dims($data, "fs/10")',
- 'FUnderline', '$rtf .= &select_attr($data, "Underline",
- "Yes", "ul", "No", "ulnone")',
- 'FStrike', '$rtf .= &select_attr($data, "Strike",
- "Yes", "strike", "No", "strike0")',
- 'FSupScript', '$rtf .= &select_attr($data, "SupScript",
- "Yes", "up6", "No", "up0")',
- 'FSubScript', '$rtf .= &select_attr($data, "SubScript",
- "Yes", "dn6", "No", "dn0")',
- 'FChangeBar', '$rtf .= &select_attr($data, "ChangeBar",
- "Yes", "revised", "No", "revised0")',
- 'FOutline', '$rtf .= &select_attr($data, "Outline",
- "Yes", "outl", "No", "outl0")',
- 'FShadow', '$rtf .= &select_attr($data, "Shadow",
- "Yes", "shad", "No", "shad0")',
- 'FSeparation', '$rtf .= &change_attr("cf", $data)'
- );
- # &debug("char format: $rtf");
- $rtf;
- }
-
- ########
-
- sub convert_frame{
- local($s) = @_;
- #@@ local(@BRect) = @BRect;
- local(@ret);
-
- &debug("convert frame: $s");
- &do_statement
- ($s,
- 'TextRect', 'push(@ret, &convert_textrect($here))',
- 'Frame', 'push(@ret, &convert_frame($here))',
- 'ImportObject', 'push(@ret, &convert_picture($here))',
- 'BRect', 'push(@ret, &change_dims($data, "posx", "posy", "absw"))',
- 'FrameType', 'push(@ret, &select_attr($data, "FrameType",
- "Inline", "posyil",
- "Top", "posyt",
- "Bottom", "posyb",
- "Left", "posxl",
- "Right", "posxr",
- "Near", "posxi",
- "Far", "posxo"))'
- );
- @ret;
- }
-
- sub convert_textrect{
- local($tr) = @_;
- local(@ret);
-
- &do_statement
- ($tr,
- 'ID',
- 'local($_) = $TextRect{$data};
- $_ && !$TextFlow{$_}++ ? push(@ret, &convert_flow($_))
- : &debug("no flow or repeated flow:$data line: ",$Lines{$_});'
- );
- @ret;
- }
-
- #
- # this is one alternative...
- #
- sub old_convert_textrect{
- local($tr) = @_;
- local($id, @ret);
-
- &debug("convert textrect $tr");
- for($id = &data_search($tr, 'ID', 1); $id;
- $id = &data_search($tr, 'TRNext', 1)){
- local($s) = $TextRect{$id};
- last if $TextRect[$s]++;
- &debug("TextRectID = $id");
- push(@ret, &convert_flow($s));
- }
- @ret;
- }
-
- sub convert_table{
- local($s) = @_;
- local(@r);
- local($rows) = 'push(@r, &convert_rows($here))';
-
- &do_statement
- ($s,
- 'TblTitleContent', 'push(@r, &convert_flow($here))'
- #@@ for AVS, we need the table title content, but we captured
- # all the rows as bitmaps.
- #@@ 'TblH', $rows,
- #@@ 'TblBody', $rows,
- #@@ 'TblF', $rows
- );
-
- @r;
- }
-
- sub convert_rows{
- local($s) = @_;
- local(@r);
-
- &do_statement
- ($s,
- 'Row', 'push(@r, "\\\\trowd ", &convert_cells($here), "\\\\row\n")'
- );
- @r;
- }
-
- sub convert_cells{
- local($s) = @_;
- local(@r);
-
- &do_statement
- ($s,
- 'Cell', 'push(@r, &convert_cell($here))'
- );
- @r;
- }
-
- sub convert_cell{
- local($s) = @_;
- local(@r);
-
- #@@ cell formatting!
- &do_statement
- ($s,
- 'CellContent',
- 'push(@r, &convert_flow($here, "\\\\intbl "), "\\\\cell")'
- );
- @r;
- }
-
- sub convert_picture{
- local($s) = @_;
-
- local(@r, $color, $unixpath, $dipath, $epsi, $image, $brect);
-
- &do_statement
- ($s,
- 'Separation', '$color = $data',
- 'ImportObFile', '$unixpath = $data',
- 'ImportObFileDI', '$dipath = $data',
- 'EPSI', '$epsi = $data',
- 'FrameImage', 'push(@r, "\\\\frameimage\n", $data)',
- 'BRect', '$brect = $data'
- );
-
- &debug("picture: color($color) file($unixpath,$dipath) brect($brect)");
-
- if($brect){
- local($l, $t, $h, $w) = &rtf_dimensions($brect);
- unshift(@r, "\\picwGoal$w\\pichGoal$h\n");
- }
-
- undef($unixpath) if $unixpath =~ /internal inset/;
-
- local($path);
- if($dipath){
- local($_) = &convert_string($dipath);
- if(/<U>([^<]+)/){
- $path = $1;
- }else{
- if($unixpath){
- $path = &convert_string($unixpath);
- }else { warn "no path in: $dipath"; }
- }
- }
-
- if($path){
- push(@r, "\\xwdfile $path");
- }
- if($epsi){
- $epsi =~ s/.*&%v\s*&//;
- $epsi =~ s/\n&//g;
- push(@r, "\\epsi\n", $epsi);
- }
-
- @r = ("\\qc{\\pict\n", @r, "}\\par\n"); # put it in a centered paragraph @#
- @r = ("{\\cf$color", @r, "}") if $color;
- @r;
- }
-
- sub convert_flow{
- local($s, $Container) = @_;
- local(@r, %Notes);
-
- &do_statement
- ($s,
- 'Notes', '&save_notes($here)',
- 'Para', 'push(@r, &convert_paragraph($here))'
- );
- @r;
- }
-
- sub save_notes{
- local($s) = @_;
- local($_, $n);
-
- foreach (&parts($s)){
- $n = &data_search($_, 'ID', 1);
- # &debug("note: $n is:", &expand_mif_statement($_));
- $Notes{$n} = $_;
- }
- }
-
-
- sub convert_paragraph{
- local($s) = @_;
- local(@fmt, @lines, @pre, @post, $HyperGroup);
- # global($PgfTag);
-
- &do_statement($s,
- 'PgfTag',
- 'push(@fmt, &change_style(&convert_string($data)))',
- 'Pgf',
- 'push(@fmt, &convert_pgf_format($here))',
- 'PgfNumString',
- 'push(@lines, &convert_numstring($data))',
- 'ParaLine',
- 'push(@lines, &convert_paraline($here, *pre, *post), "\n")'
- );
-
- &debug("convert_paragraph: ",$State{'PgfTag'});
- print STDERR '.'; #@# status
-
- push(@lines, $HyperGroup), undef($HyperGroup) if $HyperGroup;
-
- local($group);
- $RTFInfo{$group} .= join('', @lines)."\\par\n" #@#lines is arbitrary
- if $group = $TagGroup{$State{'PgfTag'}};
- &debug(%TagGroup);
- &debug("tag: ", $State{'PgfTag'}, " group: ", $group);
-
- # $Container is, e.g. '\intbl ' (for tables)
- return(@pre, @fmt, $Container, ¤t_tabs(),
- @lines, "\\par ", @post, "\n");
- }
-
- sub current_tabs{
- local($rtf, $_);
-
- local($li) = &rtf_dimensions($State{'LIndent'});
-
- foreach (&rtf_dimensions($State{'TabStops'})){
- $_ -= $li; #@# MIF to RTF mindset
- $rtf .= "\\tx$_ ";
- }
- $rtf;
- }
-
- sub convert_numstring{
- local($string) = @_;
- local(%State) = %State; # don't clobber font
- local($numfont) = $State{'NumberFont'};
- local($font) = $numfont ? &change_char_style($numfont) : '';
- local($form) = $State{'NumFormat'};
-
- $string = &convert_string($string, $State{'Family'} ne 'Symbol');
-
- &debug("numstring($string) [font($numfont): $font form: $form]");
- local($tabs) = ¤t_tabs();
- "{\\field{\\fldinst PgfNumFormat $form}{\\fldrslt $font$tabs$string}}";
- }
-
- sub change_style{
- local($tag) = @_;
-
- local($style, $_);
-
- if($PgfCatalog{"Style", $tag}){
- &set_paragraph_format($tag);
- $style = $PgfCatalog{"Style", $tag};
- }else{
- local($pgf_fmt) = $PgfCatalog{'Statement', $tag};
- if($pgf_fmt){
- &reset_paragraph_format();
- &reset_character_format();
- $style = &convert_pgf_format($pgf_fmt);
- $PgfCatalog{"Style", $tag} = $style;
- &save_paragraph_format($tag);
- }else{
- warn "No catalog entry for '$tag'";
- }
- }
-
- $State{'PgfTag'} = $tag;
-
- join('', "\\pard\\plain\\s", &intern(*Tag, $tag), " ", $style);
- }
-
- sub change_char_style{
- local($tag) = @_;
- local($style, $_);
-
- &reset_character_format();
- $State{'FTag'} = $tag;
-
- local($s) = $FontCatalog{'Statement', $tag};
- $s ? "\\plain" . &convert_char_format($s)
- : '';
- }
-
- sub convert_paraline{
- local($s, *pre, *post) = @_;
- #@# empty_hyper gets around the: <marker><font>hot-text<font> bug.
- local(@text, $empty_hyper);
-
- &do_statement
- ($s,
- 'String',
- 'push(@text, &convert_string($data, $State{"Family"} ne "Symbol"));
- $empty_hyper=0;',
- 'Char',
- 'push(@text, &convert_character($data))',
-
- 'ATbl',
- 'local(%State) = %State;
- local(@tbl) = &convert_table($Tbl{$data});
- $State{"TblPlacement"} =~ /Top|Left|Right|Near|Far/
- ? push(@pre, "{", @tbl, "}") : push(@post, "{", @tbl, "}")',
-
- 'AFrame',
- 'local(%State) = %State;
- &debug("converting AFrame $data");
- local(@af) = &convert_frame($AFrame{$data});
- $State{"FrameType"} =~ /Top|Left|Right|Near|Far/
- ? push(@pre, "{", @af, "}") : push(@post, "{", @af, "}")',
-
- 'FNote',
- 'push(@text, &convert_footnote($Notes{$data}))',
-
- 'XRefEnd',
- 'push(@text, &convert_xref_end($data))',
-
- #@@ there could be a problem with tagged fonts here:
- # convert_char_format ignores tags. Catalog lookup occurs
- # in its caller (e.g. convert_character_catalog).
- # And this is its caller.
- 'Font',
- 'push(@text, $HyperGroup), undef($HyperGroup)
- if $HyperGroup && !$empty_hyper;
- push(@text, &convert_char_format($here))',
-
- 'Marker',
- 'push(@text, &convert_marker($here)); $empty_hyper=1',
-
- 'Variable',
- 'push(@text, &convert_definition("Variable",
- &data_search("VariableName", $here)))',
- 'XRef',
- 'push(@text, &convert_xref($here))'
- );
- @text;
- }
-
- sub convert_string{
- # Change a MIF String datum (without newlines) to a rtf string
- local($_, $do_hex) = @_;
-
- # put backslashes out of band
- s/\\\\/\n\n/g;
-
- # undo MIFisms
- s/^`//;
- s/'.*//;
- s/\\q/'/g;
- s/\\Q/`/g;
- s/\\</</g;
- s/\\>/>/g;
-
- # convert hex stuff
- $do_hex ? s/\\x(\w\w) /$FrameCode[hex($1)]/ge :
- s/\\x(\w\w) /pack('C', hex($1))/ge;
-
- # protect RTFisms
- s/\{/\n\{/;
- s/\}/\n\}/;
- s/\\t/\t/;
- s/\\/\n\n/;
- warn "@@unexpected backslash: $_" if /\\/;
-
- # change backslashes back
- s/\n/\\/g;
- $_;
- }
-
- sub convert_character{
- local($name) = @_;
- $CharacterConversions{$name};
- }
-
- sub convert_footnote{
- return ("\\chftn{\\footnote\n", &convert_flow($_[0]), "}");
- }
-
- sub convert_xref{
- local($s) = @_;
-
- $XRefSrcText = &convert_string(&data_search($s, 'XRefSrcText'));
- $XRefSrcFile = &convert_string(&data_search($s, 'XRefSrcFile'));
-
- return "{\\field{\\fldrslt ";
- }
-
- sub convert_xref_end{
- return "}{\\fldinst XRefSrcFile=$XRefSrcFile XRefSrcText=$XRefSrcText " .
- "XRefFormat=" . $Definition{'XRef', $XRefName} . "}}";
- }
-
- sub convert_definition{
- local($type, $name) = @_;
- #@# converts Frame variables literally to RTF
- return &convert_string($Definition{$type, $name});
- }
-
- sub convert_other{
- local($token, $text, $invisible) = @_;
- local($fldpriv) = $invisible ? '\fldpriv\v' : '';
- "{\\field$fldpriv{\\fldinst $token}{\\fldrslt $text}}";
- }
-
- sub convert_marker{
- local($type) = &data_search($_[0], 'MType', 1);
- local($text) = &convert_string(&data_search($_[0], 'MText', 1));
-
- if($type == 0 || $type == 1){
- #@@ these actually occur in pairs.
- return &convert_other('FrameHeaderFooter ' . ($type+1), $text, 1); #@#
- }elsif($type == 2){
- return "{\\v{\\xe $text}}"; #@# text needs to be interpreted
- }elsif($type == 3){
- $RTFInfo{'comment'} .= "$text\n";
- }elsif($type == 4){
- $RTFInfo{'subject'} .= "$text\n";
- }elsif($type == 5){
- $RTFInfo{'author'} .= "$text\n";
- }elsif($type == 6){
- $RTFInfo{'keywords'} .= "$text\n"; #@# glossary, really
- }elsif($type == 7){
- return '{\|}'; #@# equation marker->formula character
- }elsif($type == 8){
- $HyperGroup = "}{\\fldinst FrameHypertext $text}}";
- return "{\\field{\\fldrslt ";
- }elsif($type == 9){
- return &convert_other('FrameXRefMarker ', $text, 1); #@#
- }
- return &convert_other('FrameMarker ' . ($type+1), $text, 1); #@#
- }
-
- #
- # Output routines
- #
-
- sub debug{
- print STDERR @_, " @$.\n" if $Debug;
- }
-
- ##############
- #
- #
- sub initialize_state{
- @FrameCode =
- ('', '', '', '', '\-', '', '\_', '',
- '\tab', '\line', "\266", "\247", '', '', '', '',
- " ", "\240", " ", " ", " ", "\255", '', '',
- '', '', '', '', '', '', '', '',
- ' ', '!', '"', '#', "\$", '%', '&', "\'",
- '(', ')', '*', '+', ',', '-', '.', '/',
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', ':', ';', '<', '=', '>', '?',
- '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
- 'X', 'Y', 'Z', '[', "\\", ']', '^', '_',
- "\`", 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
- 'x', 'y', 'z', '{', '|', '}', '~', '',
- # 0x80
- "\304", "\305", "\307", "\311", "\321", "\326", "\334", "\341",
- # 0x88
- "\340", "\342", "\344", "\343", "\345", "\347", "\351", "\350",
- # 0x90
- "\352", "\353", "\355", "\354", "\356", "\357", "\361", "\363",
- # 0x98
- "\362", "\364", "\366", "\365", "\372", "\371", "\373", "\374",
- # 0xa0
- "**", "\260", "\242", "\243", "\247", "\267", "\266", "\337",
- # 0xa8
- "\256", "\251", "(tm)", "\264", "\250", "", "\306", "\330",
- # 0xb0
- "", "", "", "", "\225", "", "", "",
- # 0xb8
- "", "", "", "\252", "\272", "", "\346", "\370",
- # 0xc0
- "\277", "\241", "\254", "", "f", "", "", "\253",
- # 0xc8
- "\273", "...", "", "\300", "\303", "\325", "OE", "oe",
- # 0xd0
- "\255", "--", "``", "''", "`", "'", "", "",
- # 0xd8
- "\377", "Y", "/", "\244", "<", ">", "fi", "fl",
- # 0xe0
- "***", "\267", ",", ",,", "%.", "\302", "\312", "\301",
- # 0xe8
- "\313", "\310", "\315", "\316", "\317", "\314", "\323", "\324",
- # 0xf0
- "", "\322", "\332", "\333", "\331", "i", "^", "~",
- # 0xf8
- "\256", "\257", ".", "\260", "\270", "''", ",");
-
- %CharacterConversions =
- ('Tab', '\tab ',
- 'HardSpace', '\~ ',
- 'SoftHypen', '\_ ', #@#
- 'DiscHypen', '\- ',
- 'Cent', "\242", # from ISO8859-1
- 'Pound', "\243",
- 'Yen', "\245",
- 'EnDash', "\255",
- 'EmDash', '-', #@#
- 'Dagger', '**', #@#
- 'DoubleDagger', '***', #@#
- 'Bullet', "\267",
- 'HardReturn', '\line ',
- 'EndOfPara', "\266",
- 'EndOfFlow', "\247",
- 'NumberSpace', ' ', #@#
- 'ThinSpace', ' ', #@#
- 'EnSpace', ' ',
- 'EmSpace', ' '
- );
-
- local(%doc_defaults) =
- ('paperw', 12240,
- 'paperh', 15840,
- 'margl', 1800,
- 'margr', 1800,
- 'margt', 1440,
- 'margb', 1440,
- 'facingp', '',
- 'TwoSides', 'No',
- 'gutter', 0,
- 'deftab', 720,
- 'widowctrl', '',
- 'hyphhotz', '',
- 'fntsep', '',
- 'ftnsepc', '',
- 'ftncn', '',
- 'endnotes', 1,
- 'enddoc', 0,
- 'ftntj', 0,
- 'ftnbj', 1,
- 'ftnstart', 1,
- 'pgnstart', 1,
- 'linestart', 1,
- 'landscape', 0,
- 'fracwidth', 0,
- 'nextfile', '',
- 'template', '',
- 'makeback', '',
- 'defformat', '',
- 'revisions', '',
- 'margmirror', '',
- 'revprop', 3,
- 'revbar', 3);
-
- local(%para_defaults) =
- ('snext', '',
- 'sbasedon', '',
- 'pard', '',
- 's', '',
- 'ql', '',
- 'qr', '',
- 'qj', '',
- 'qc', '',
- 'Alignment', 'ql',
- 'LIndent', '0',
- 'FIndent', '',
- 'NumberFont', '',
- 'fi', 0,
- 'li', 0,
- 'ri', 0,
- 'sb', 0,
- 'sa', 0,
- 'sl', '',
- 'intbl', '',
- 'keep', '',
- 'keepn', '',
- 'WithNext', 'keep0',
- 'sbys', '',
- 'pagebb', '',
- 'Placement', 'Anywhere',
- 'noline', '',
- 'TabStops', '',
- 'tx', '',
- 'tqr', '',
- 'tqc', '',
- 'tqdec', '',
- 'tb', '',
- 'brdrt', '',
- 'brdrl', '',
- 'brdrr', '',
- 'box', '',
- 'brdrs', '',
- 'brdrth', '',
- 'brdrsh', '',
- 'brdrdb', '',
- 'brdrdot', '',
- 'brdrhair', '',
- 'brsp', '',
- 'tldot', 1,
- 'tlhyph', '',
- 'tlul', '',
- 'tlth', '');
-
- local(%char_defaults) =
- ('f', '',
- 'Family', '',
- 'b', '',
- 'Weight', 'b0',
- 'i', '',
- 'Angle', 'i0',
- 'strike', '',
- 'Strike', 'strike0',
- 'outl', '',
- 'Outline', 'outl0',
- 'shad', '',
- 'Shadow', 'shad0',
- 'scaps', '',
- 'caps', '',
- 'v', '',
- 'fn', '',
- 'fs', '24',
- 'expnd', 0,
- 'ul', '',
- 'ulw', '',
- 'uld', '',
- 'uldb', '',
- 'ulnone', '',
- 'Underline', 'ulnone',
- 'up', '',
- 'SupScript', 'up0',
- 'dn', '',
- 'SubScript', 'dn0',
- 'revised', '',
- 'ChangeBar', 'revised0',
- 'cf', 0
- );
-
- local($_);
- @DocumentAttrs = keys(%doc_defaults);
- foreach (@DocumentAttrs){
- push(@DocumentDefaults, $doc_defaults{$_});
- }
- @State{@DocumentAttrs} = @DocumentDefaults;
-
- @ParagraphAttrs = keys(%para_defaults);
- foreach (@ParagraphAttrs){
- push(@ParagraphDefaults, $para_defaults{$_});
- }
- @State{@ParagraphAttrs} = @ParagraphDefaults;
-
- @CharacterAttrs = keys(%char_defaults);
- foreach (@CharacterAttrs){
- push(@CharacterDefaults, $char_defaults{$_});
- }
- @State{@CharacterAttrs} = @CharacterDefaults;
- }
-
- sub reset_paragraph_format{
- @State{@ParagraphAttrs} = @ParagraphDefaults;
- '';
- }
-
- sub set_paragraph_format{
- local($tag) = @_;
- local($_);
- &reset_paragraph_format();
- &reset_character_format();
- grep($State{$_} = $PgfCatalog{$_, $tag},
- @ParagraphAttrs, @CharacterAttrs);
- }
-
- sub save_paragraph_format{
- local($tag) = @_;
- local($_);
- grep($PgfCatalog{$_, $tag} = $State{$_},
- @ParagraphAttrs, @CharacterAttrs);
- }
-
- sub reset_character_format{
- @State{@CharacterAttrs} = @CharacterDefaults;
- '';
- }
-
- ###############
- #
- #
-
- sub rtf_begin_doc{
- return "{\\rtf1\\ansi\n";
- }
-
- sub rtf_end_doc{
- return "}\n";
- }
-
- sub rtf_info{
- local(%groups) = @_;
- local(@r, $_);
-
- push(@r, "{\\info\n");
- foreach (keys %groups){
- push(@r, "{\\$_ ", $groups{$_}, "}\n");
- }
- push(@r, "}\n");
- return @r;
- }
-
- sub intern{
- local(*arr, $_) = @_;
- s/^\`//;
- s/\'.*//;
- $arr{$_} || ($arr{$_} = ++$arr);
- # $_ = $arr{$_} || ($arr{$_} = ++$arr);
- # &debug("intern: $_[1] -> $_");
- # $_;
- }
-
- sub rtf_font_table{
- #
- # HEURISTIC: uses \fnil for unrecognized fonts.
- # recognizes all FrameMaker 2.1 fonts
- #
- local(%fonts) = @_;
- local(@r);
-
- local($n, $family, $_);
- foreach (keys %fonts){
- $family = 'nil';
- $n = $fonts{$_};
- $family = 'roman' if /serif/ || /times/i || /palatino/i
- || /bookman/i || /newcenturysch/;
- $family = 'swiss' if /sans/ || /helvetica/i || /avantgarde/i;
- $family = 'modern' if /courier/i;
- $family = 'script' if /cursive/i;
- $family = 'decor' if /zapfchancery/i;
- $family = 'tech' if /symbol/i;
-
- push(@r, "{\\f$n\\f$family $_;}\n");
- }
- return("{\\fonttbl\n", @r, "}\n");
- }
-
-
- sub rtf_style_sheet{
- local(%styles) = @_;
- local(@r);
-
- local($n, $style, $_);
- foreach (keys %styles){
- $n = &intern(*Tag, $_);
- #@# all styles mentioned in the document will appear in the
- # stylesheet, but only styles used in the document will be defined!
- $style = $PgfCatalog{'Style', $_};
- push(@r, "{\\s$n $style$_;}\n");
- }
- return("{\\stylesheet\n", @r, "}\n");
- }
-
-
- sub rtf_color_table{
- local(@colors) = @_;
-
- local($red, $green, $blue, $_);
- foreach (@colors){
- ($red, $green, $blue) = split(/\s+/, $_);
- $red = 255 * $red;
- $green = 255 * $green;
- $blue = 255 * $blue;
- push(@r, "\\red$red\\green$green\\blue$blue;\n");
- }
- return("{\\colortbl\n", @r, "}\n");
- }
-
- sub rtf_dimensions{
- local($_, $twips) = @_;
- local(@trect);
- #
- # convert all dimensions to twips
- # didot@@ cicero@@
- #
- while($_){
- if( s/\s*(-?\d+(\.\d*)?)\s*//){
- $twips = $1 * 1440;
- }else{
- warn "@@Bad dimensions: $_\n";
- return ();
- }
- s/"//;
- s/in//;
- s/pt// && ($twips = $twips/72);
- s-cm-- && ($twips = $twips/2.54);
- s-mm-- && ($twips = $twips/25.4);
- push (@trect, int($twips));
- }
- @trect;
- }
-
-
- ##############
- #
- # tchrists' assert stuff
- #
-
- sub assert {
- &panic("ASSERTION BOTCHED: $_[0]",$@) unless eval $_[0];
- }
-
- sub panic {
-
- select(STDERR);
-
-
- print "\npanic: @_";
-
- exit 1 if $] <= 4.003; # caller broken
-
- # stack traceback stolen from perl debugger
-
- local($i,$_);
- local($p,$f,$l,$s,$h,$a,@a,@sub);
- for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) {
- @a = @DB'args;
- for (@a) {
- if (/^StB\000/ && length($_) == length($_main{'_main'})) {
- $_ = sprintf("%s",$_);
- }
- else {
- s/'/\\'/g;
- s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/;
- s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
- s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
- }
- }
- $w = $w ? '@ = ' : '$ = ';
- $a = $h ? '(' . join(', ', @a) . ')' : '';
- push(@sub, "$w&$s$a from file $f line $l\n");
- last if $signal;
- }
- for ($i=0; $i <= $#sub; $i++) {
- last if $signal;
- print $sub[$i];
- }
- kill 'TERM', -$Start_Pid;
- exit 1;
- }
- @//E*O*F mif2rtf.pl//
- chmod u=rwx,g=rx,o=rx mif2rtf.pl
-
- exit 0
-
-