Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  BasicLyX.pm   Sprache: unbekannt

 
# This file is part of reLyX
# Copyright (c) 1998-9 Amir Karger karger@post.harvard.edu
# You are free to use and modify this code under the terms of
# the GNU General Public Licence version 2 or later.

package BasicLyX;
# This package includes subroutines to translate "clean" LaTeX to LyX.
# It translates only "basic" stuff, which means it doesn't do class-specific
#     things. (It uses the TeX parser Text::TeX)
use strict;

use RelyxTable; # Handle LaTeX tables
use Verbatim;   # Copy stuff verbatim

use vars qw($bibstyle_insert_string $bibstyle_file $Begin_Inset_Include);
$bibstyle_insert_string = "%%%%%Insert bibliographystyle file here!";
$bibstyle_file = "";
$Begin_Inset_Include = "\\begin_inset Include";

#################### PACKAGE-WIDE VARIABLES ###########################
my $debug_on; # is debugging on?

######
#Next text starts a new paragraph?
# $INP = 0 for plain text not starting a new paragraph
# $INP = 1 for text starting a new paragraph, so that we write a new
#    \layout command and renew any font changes for the new paragraph
# Starts as 1 cuz if the first text in the document is plain text
#    (not, e.g., in a \title command) it will start a new paragraph
my $IsNewParagraph = 1;
my $OldINP; #Save $IsNewParagraph during footnotes

# HACK to protect spaces within optional argument to \item
my $protect_spaces = 0;

# $MBD = 1 if we're in a list, but haven't seen an '\item' command
#    In that case, we may need to start a nested "Standard" paragraph
my $MayBeDeeper = 0;
my $OldMBD; #Save $MBD during footnotes -- this should very rarely be necessary!

# Stack to take care of environments like Enumerate, Quote
# We need a separate stack for footnotes, which have separate layouts etc.
# Therefore we use a reference to an array, not just an array
my @LayoutStack = ("Standard"); #default if everything else pops off
my $CurrentLayoutStack = \@LayoutStack;

# Status of various font commands
# Every font characteristic (family, series, etc.) needs a stack, because
#    there may be nested font commands, like \textsf{blah \texttt{blah} blah}
# CurrentFontStatus usually points to the main %FontStatus hash, but
#     when we're in a footnote, it will point to a temporary hash
my %FontStatus = (
    '\emph' => ["default"],
    '\family' => ["default"],
    '\series' => ["default"],
    '\shape' => ["default"],
    '\bar' => ["default"],
    '\size' => ["default"],
    '\noun' => ["default"],
);
my $CurrentFontStatus = \%FontStatus;

# Currently aligning paragraphs right, left, or center?
my $CurrentAlignment = "";
my $OldAlignment; # Save $AS during footnotes

# Global variables for copying tex stuff
my $tex_mode_string; # string we accumulate tex mode stuff in
my @tex_mode_tokens; # stack of tokens which required calling copy_latex_known

# LyX strings to start and end TeX mode
my $start_tex_mode = "\n\\latex latex \n";
my $end_tex_mode = "\n\\latex default \n";

# String to write before each item
my $item_preface = "";

#############  INFORMATION ABOUT LATEX AND LYX   #############################
# LyX translations of LaTeX font commands
my %FontTransTable = (
   # Font commands
   '\emph' => "\n\\emph on \n",
   '\underline' => "\n\\bar under \n",
   '\underbar' => "\n\\bar under \n", # plain tex equivalent of underline?
   '\textbf' => "\n\\series bold \n",
   '\textmd' => "\n\\series medium \n",
   '\textsf' => "\n\\family sans \n",
   '\texttt' => "\n\\family typewriter \n",
   '\textrm' => "\n\\family roman \n",
   '\textsc' => "\n\\shape smallcaps \n",
   '\textsl' => "\n\\shape slanted \n",
   '\textit' => "\n\\shape italic \n",
   '\textup' => "\n\\shape up \n",
   '\noun' => "\n\\noun on \n", # LyX abstraction of smallcaps

# Font size commands
   '\tiny' => "\n\\size tiny \n",
   '\scriptsize' => "\n\\size scriptsize \n",
   '\footnotesize' => "\n\\size footnotesize \n",
   '\small' => "\n\\size small \n",
   '\normalsize' => "\n\\size default \n",
   '\large' => "\n\\size large \n",
   '\Large' => "\n\\size Large \n",
   '\LARGE' => "\n\\size LARGE \n",
   '\huge' => "\n\\size huge \n",
   '\Huge' => "\n\\size Huge \n",
   # This doesn't work yet!
   #'\textnormal' => "\n\\series medium \n\\family roman \n\\shape up \n",
);

# Things LyX implements as "Floats"
my %FloatTransTable = (
   # Footnote, Margin note
   '\footnote' => "\n\\begin_float footnote \n",
   '\thanks' => "\n\\begin_float footnote \n", # thanks is same as footnote
   '\marginpar' => "\n\\begin_float margin \n",
);
# Environments that LyX implements as "floats"
my %FloatEnvTransTable = (
    "table" => "\n\\begin_float tab \n",
    "table*" => "\n\\begin_float wide-tab \n",
    "figure" => "\n\\begin_float fig \n",
    "figure*" => "\n\\begin_float wide-fig \n",
);

# Simple LaTeX tokens which are turned into small pieces of LyX text
my %TextTokenTransTable = (
    # LaTeX escaped characters
    '\_' => '_',
    '\%' => '%',
    '\$' => '$',
    '\&' => '&',
    '\{' => '{',
    '\}' => '}',
    '\#' => '#',
    '\~' => '~',
    '\^' => '^',
    # \i and \j are used in accents. LyX doesn't recognize them in plain
    #    text. Hopefully, this isn't a problem.
    '\i' => '\i',
    '\j' => '\j',

    # Misc simple LaTeX tokens
    '~'      => "\n\\protected_separator \n",
    '@'      => "@", # TeX.pm considers this a token, but it's not really
    '\@'     => "\\SpecialChar \\@",
    '\ldots' => "\n\\SpecialChar \\ldots\{\}\n",
    '\-'     => "\\SpecialChar \\-\n",
    '\LaTeX' => "LaTeX",
    '\LaTeXe' => "LaTeX2e",
    '\TeX'    => "TeX",
    '\LyX'    => "LyX",
    '\hfill'  => "\n\\hfill \n",
    '\noindent'        => "\n\\noindent \n",
    '\textbackslash'   => "\n\\backslash \n",
    '\textgreater'     => ">",
    '\textless'        => "<",
    '\textbar'         => "|",
);

# LyX translations of some plain LaTeX text (TeX parser won't recognize it
#     as a Token, so we need to translate the Text::TeX::Text token.)
my %TextTransTable = (
    # Double quotes
    "``" => "\n\\begin_inset Quotes eld\n\\end_inset \n\n",
    "''" => "\n\\begin_inset Quotes erd\n\\end_inset \n\n",

    # Tokens that don't start with a backslash, so parser won't recognize them
    # (LyX doesn't support them, so we just print them in TeX mode)
    '?`' => "$start_tex_mode?`$end_tex_mode",
    '!`' => "$start_tex_mode!`$end_tex_mode",
);

# Things that LyX translates as "LatexCommand"s
# E.g., \ref{foo} ->'\begin_inset LatexCommand \ref{foo}\n\n\end_inset \n'
# (Some take arguments, others don't)
my @LatexCommands = map {"\\$_"} qw(ref pageref label cite bibliography
                          index printindex tableofcontents
                                 listofalgorithms listoftables listoffigures);
my @IncludeCommands = map {"\\$_"} qw(input include);

# Accents. Most of these take an argument -- the thing to accent
# (\l and \L are handled as InsetLatexAccents, so they go here too)
my $AccentTokens = "\\\\[`'^#~=.uvHtcdblL\"]";

# Environments which describe justifying (converted to LyX \align commands)
#    and the corresponding LyX commands
my %AlignEnvironments = (
    "center" => "\n\\align center \n",
    "flushright" => "\n\\align right \n",
    "flushleft" => "\n\\align left \n",
);

# Some environments' begin commands take an extra argument
# Print string followed by arg for each item in the list, or ignore the arg ("")
my %ExtraArgEnvironments = (
    "thebibliography" => "",
    "lyxlist" =>'\labelwidthstring ',
    "labeling" =>'\labelwidthstring ', # koma script list
);

# Math environments are copied verbatim
my $MathEnvironments = "(math|equation|displaymath|eqnarray(\\*)?)";
# ListLayouts may have standard paragraphs nested inside them.
my $ListLayouts = "Itemize|Enumerate|Description";

#####################   PARSER INVOCATION   ##################################
sub call_parser {
# This subroutine calls the TeX parser & translator
# Before it does that, it does lots of setup work to get ready for parsing.
# Arg0 is the file to read (clean) LaTeX from
# Arg1 is the file to write LyX to
# Arg2 is the file to read layouts from (e.g., in LYX_DIR/layouts/foo.layout)

    my ($InFileName, $OutFileName) = (shift,shift);

# Before anything else, set the package-wide variables based on the
#    user-given flags
    # opt_d is set to 1 if '-d' option given, else (probably) undefined
    $debug_on = (defined($main::opt_d) && $main::opt_d);

    # Hash of tokens passed to the TeX parser
    # Many values are $Text::TeX::Tokens{'\operatorname'}, which has
    #    Type=>report_args and count=>1
    # Note that we don't have to bother putting in tokens which will be simply
    #    translated (e.g., from %TextTokenTransTable).
    my %MyTokens = ( 
 '{' => $Text::TeX::Tokens{'{'},
 '}' => $Text::TeX::Tokens{'}'},
 '\begin' => $Text::TeX::Tokens{'\begin'},
 '\end' => $Text::TeX::Tokens{'\end'},

 # Lots of other commands will be made by ReadCommands:Merge
 # by reading the LaTeX syntax file

 # Font sizing commands (local)
 '\tiny' => {Type => 'local'},
 '\small' => {Type => 'local'},
 '\scriptsize' => {Type => 'local'},
 '\footnotesize' => {Type => 'local'},
 '\small' => {Type => 'local'},
 '\normalsize' => {Type => 'local'},
 '\large' => {Type => 'local'},
 '\Large' => {Type => 'local'},
 '\LARGE' => {Type => 'local'},
 '\huge' => {Type => 'local'},
 '\Huge' => {Type => 'local'},

 # Tokens to ignore (which make a new paragraph)
 # Just pretend they actually ARE new paragraph markers!
 '\maketitle' => {'class' => 'Text::TeX::Paragraph'},
    );
    
    # Now add to MyTokens all of the commands that were read from the
    #    commands file by package ReadCommands
    &ReadCommands::Merge(\%MyTokens);

# Here's the actual subroutine. The above is all preparation
    # Output LyX file
    my $zzz = $debug_on ? " ($InFileName --> $OutFileName)\n" : "... ";
    print STDERR "Translating$zzz";
    open (OUTFILE,">$OutFileName");

    # Open the file to turn into LyX.
    my $infile = new Text::TeX::OpenFile $InFileName,
 'defaultact' => \&basic_lyx,
 'tokens' => \%MyTokens;

    # Process what's left of the file (everything from \begin{document})
    $infile->process;

    # Last line of the LyX file
    print OUTFILE "\n\\the_end\n";
    close OUTFILE;
    #warn "Done with basic translation\n";
    return;
} # end subroutine call_parser

##########################   MAIN TRANSLATOR SUBROUTINE   #####################
sub basic_lyx {
# This subroutine is called by Text::TeX::process each time subroutine
#     eat returns a value.
# Argument 0 is the return value from subroutine eat
# Argument 1 is the Text::TeX::OpenFile (namely, $TeXfile)
    my $eaten = shift;
    my $fileobject = shift;

    # This handles most but maybe not all comments
    # THere shouldn't be any if we've run CleanTeX.pl
    print "Comment: ",$eaten->comment if defined $eaten->comment && $debug_on;

    my $type = ref($eaten);
    print "$type " if $debug_on;

    # This loop is basically just a switch. However, making it a for
    #    (1) makes $_ = $type (convenient)
    #    (2) allows us to use things like next and last
    TYPESW: for ($type) {

        # some pre-case work
        s/^Text::TeX:://o or die "unknown token?!";
 my ($dummy, $tok);
 my ($thistable);

 # The parser puts whitespace before certain kinds of tokens along
 # with that token. If that happens, save a space
 my $pre_space = ""; # whitespace before a token
 if (/BegArgsToken|^Token|::Group$/) {
     $dummy = $eaten->exact_print;
     # Only set prespace if we match something
     #    We wouldn't want it to be more than one space, since that's
     # illegal in LyX. Also, replace \t or \n with ' ' since they are
     # ignored in LyX. Hopefully, this won't lead to anything worse
     # than some lines with >80 chars
     #    Finally, don't put a space at the beginning of a new paragraph
     if (($dummy =~ /^\s+/) && !$IsNewParagraph) {
  $pre_space = " ";
     }
 }

        # Handle blank lines.
        if (m/^Paragraph$/o) {
     # $INP <>0 means We will need a new layout command
     $IsNewParagraph = 1;

     # $MBD means start a begin_deeper within list environments
     #    unless there's an \item command
     $MayBeDeeper = 1;

            last TYPESW;
        }

 # If, e.g., there's just a comment in this token, don't do anything
 # This actually shouldn't happen if CleanTeX has already removed them
 last TYPESW if !defined $eaten->print;
        
        # Handle LaTeX tokens
        if (/^Token$/o) {

     my $name = $eaten->token_name; # name of the token, e.g., "\large"
     print "'$name' " if $debug_on;

     # Tokens which turn into a bit of LyX text
     if (exists $TextTokenTransTable{$name}) {
         &CheckForNewParagraph; #Start new paragraph if necessary

  my $to_print = $TextTokenTransTable{$name};

  # \@ has to be specially handled, because it depends on
  # the character AFTER the \@
  if ($name eq '\@') {
      my $next = $fileobject->eatGroup(1);
      my $ch="";
      $ch = $next->print or warn "\@ confused me!\n";
      if ($ch eq '.') {
   # Note: \@ CAN'T have pre_space before it
   print OUTFILE "$to_print$ch\n";
   print "followed by $ch" if $debug_on;
      } else {
         warn "LyX (or LaTeX) can't handle '$ch' after $name\n";
   print OUTFILE $ch;
      }

  } else { # it's not \@
      # Print the translated text (include preceding whitespace)
      print OUTFILE "$pre_space$to_print";
  } # end special handling for \@

     # Handle tokens that LyX translates as a "LatexCommand" inset
     } elsif (grep {$_ eq $name} @LatexCommands) {
  &CheckForNewParagraph; #Start new paragraph if necessary
         print OUTFILE "$pre_space\n\\begin_inset LatexCommand ",
                 $name,
         "\n\n\\end_inset \n\n";

     # Math -- copy verbatim until you're done
     } elsif ($name eq '\(' || $name eq '\[') {
  print "\nCopying math beginning with '$name'\n" if $debug_on;
  # copy everything until end text
  $dummy = &Verbatim::copy_verbatim($fileobject, $eaten);
  $dummy = &fixmath($dummy); # convert '\sp' to '^', etc.

  &CheckForNewParagraph; # math could be first thing in a par
  print OUTFILE "$pre_space\n\\begin_inset Formula $name ";
  print $dummy if $debug_on;
  print OUTFILE $dummy;

     } elsif ($name eq '\)' || $name eq '\]') {
         # end math
  print OUTFILE "$name\n\\end_inset \n\n";
  print "\nDone copying math ending with '$name'" if $debug_on;

     # Items in list environments
     } elsif ($name eq '\item') {
  
  # What if we had a nested "Standard" paragraph?
  # Then write \end_deeper to finish the standard layout
  #     before we write the new \layout ListEnv command
  if ($$CurrentLayoutStack[-1] eq "Standard") {
      pop (@$CurrentLayoutStack); # take "Standard" off the stack
      print OUTFILE "\n\\end_deeper ";
      print "\nCurrent Layout Stack: @$CurrentLayoutStack"
            if $debug_on;
  } # end deeper if

  # Upcoming text (the item) will be a new paragraph, 
  #    requiring a new layout command based on whichever
  #    kind of list environment we're in
  $IsNewParagraph = 1;

  # But since we had an \item command, DON'T nest a
  #    deeper "Standard" paragraph in the list
  $MayBeDeeper = 0;

  # Check for an optional argument to \item
  # If so, within the [] we need to protect spaces
  # TODO: In fact, for description, if there's no [] or
  # there's an empty [], then we need to write a ~, since LyX
  # will otherwise make the next word the label
  # If it's NOT a description & has a [] then we're stuck!
  # They need to fix the bullets w/in lyx!
  if (($dummy = $fileobject->lookAheadToken) &&
      ($dummy =~ /\s*\[/)) {
      $fileobject->eatFixedString('\['); # eat the [
      $protect_spaces = 1;
  }

  # Special lists (e.g. List layout) have to print something
  # before each item. In that case, CFNP and print it
  if ($item_preface) {
      &CheckForNewParagraph;
      print OUTFILE $item_preface;
  }

     # Font sizing commands
     # (Other font commands are TT::BegArgsTokens because they take
     #     arguments. Font sizing commands are 'local' TT::Tokens)
     } elsif (exists $FontTransTable{$name}) {
  my $command = $FontTransTable{$name}; #e.g., '\size large'

  if (! $IsNewParagraph) {
      print OUTFILE "$pre_space$command";
  } #otherwise, wait until we've printed the new paragraph command

  # Store the current font change
  ($dummy = $command) =~ s/\s*(\S+)\s+(\w+)\s*/$1/;
  die "Font command error" if !exists $$CurrentFontStatus{$dummy};
  push (@{$CurrentFontStatus->{$dummy}}, $2);
  print "\nCurrent $dummy Stack: @{$CurrentFontStatus->{$dummy}}"
        if $debug_on;

     # Table stuff
     } elsif ($name eq '&') {
  if ($thistable = &RelyxTable::in_table) {
      print OUTFILE "\n\\newline \n";
      $thistable->nextcol;
  } else {warn "& is illegal outside a table!"}

     } elsif ($name eq '\\\\' || $name eq '\\newline') {
  &CheckForNewParagraph; # could be at beginning of par?
                print OUTFILE "\n\\newline \n";

  # If we're in a table, \\ means add a row to the table
  # Note: if we're on the last row of the table, this extra
  # row will get deleted later. This hack is necessary, because
  # we don't know while reading when the last row is!
  if ($thistable = &RelyxTable::in_table) {
      $thistable->addrow;
  }

     } elsif ($name eq '\hline') {
  if ($thistable = &RelyxTable::in_table) {
      # hcline does hline if no arg is given
      $thistable->hcline;
  } else {warn "\\hline is illegal outside a table!"}

     } elsif ($name =~ /\\verb.*?/) {
         my $dummy = &Verbatim::copy_verb($fileobject, $eaten);
  print "\nCopying $name in TeX mode: " if $debug_on;
  &print_tex_mode ($dummy);

     # Otherwise it's an unknown token, which must be copied
     #     in TeX mode, along with its arguments, if any
     } else {
  if (defined($eaten->relyx_args($fileobject))) {
     ©_latex_known($eaten, $fileobject);
  } else { # it's not in MyTokens
      ©_latex_unknown($eaten, $fileobject);
  }
     }

            last TYPESW;
        }
        
 # Handle tokens that take arguments, like \section{},\section*{}
 if (/^BegArgsToken$/) {
     my $name = $eaten->token_name;
     print "$name" if $debug_on;

     # Handle things that LyX translates as a "LatexCommand" inset
     if (grep {$_ eq $name} @LatexCommands) {
  &CheckForNewParagraph; #Start new paragraph if necessary

         print OUTFILE "$pre_space\n\\begin_inset LatexCommand ";

  #    \bibliography gets handled as a LatexCommand inset, but
  # it's a special case, cuz LyX syntax expects "\BibTeX"
  # instead of "\bibliography" (I have no idea why), and because
  # we have to print extra stuff
  #    Because we might not have encountered the
  # \bibliographystyle command yet, we write
  # "insert bibstyle here", and replace that string
  # with the actual bibliographystyle argument in
  # LastLyX (i.e., the next pass through the file)
  if ($name eq "\\bibliography") {
      print OUTFILE "\\BibTeX[", $bibstyle_insert_string, "]";
  } else {
      print OUTFILE "$name";
  }

  # \cite takes an optional argument, e.g.
  my $args = $eaten->relyx_args ($fileobject);
  while ($args =~ s/^o//) {
      my $tok = $fileobject->eatOptionalArgument;
      my $dummy = $tok->exact_print;
      print OUTFILE $dummy;
  }

  print OUTFILE "\{";
         last TYPESW; # skip to the end of the switch
     }

     if (grep {$_ eq $name} @IncludeCommands) {
  &CheckForNewParagraph; #Start new paragraph if necessary
         print OUTFILE "$pre_space\n$Begin_Inset_Include $name\{";
         last TYPESW; # skip to the end of the switch
     }

     # This is to handle cases where _ is used, say, in a filename.
     # When _ is used in math mode, it'll be copied by the math mode
     # copying subs. Here we handle cases where it's used in non-math.
     # Examples are filenames for \includegraphics & citation labels.
     # (It's illegal to use it in regular LaTeX text.)
     if ($name eq "_") {
        print OUTFILE $eaten->exact_print;
        last TYPESW;
     }

     # Sectioning and Title environments (using a LyX \layout command)
     if (exists $ReadCommands::ToLayout->{$name}) {
  &ConvertToLayout($name);
  last TYPESW; #done translating

     # Font characteristics
     } elsif (exists $FontTransTable{$name}) {
  my $dum2;
         my $command = $FontTransTable{$name};
         ($dummy, $dum2) = ($command =~ /(\S+)\s+(\w+)/);

  # HACK so that "\emph{hi \emph{bye}}" yields unemph'ed "bye"
  if ( ($dummy eq "\\emph") && 
       ($CurrentFontStatus->{$dummy}->[-1] eq "on")) {
         $dum2 = "default"; # "on" instead of default?
         $command =~ s/on/default/;
  }

  # If we're about to start a new paragraph, save writing
  #    this command until *after* we write '\layout Standard'
  if (! $IsNewParagraph) {
      print OUTFILE "$pre_space$command";
  }

  # Store the current font change
  die "Font command error" if !exists $$CurrentFontStatus{$dummy};
  push (@{$CurrentFontStatus->{$dummy}}, $dum2);


     # Handle footnotes and margin notes
     # Make a new font table & layout stack which will be local to the 
     #    footnote or marginpar
     } elsif (exists $FloatTransTable{$name}) {
         my $command = $FloatTransTable{$name};

  # Open the footnote
  print OUTFILE "$pre_space$command";

  # Make $CurrentFontStatus point to a new (anonymous) font table
         $CurrentFontStatus =  {
      '\emph' => ["default"],
      '\family' => ["default"],
      '\series' => ["default"],
      '\shape' => ["default"],
      '\bar' => ["default"],
      '\size' => ["default"],
      '\noun' => ["default"],
  };

  # And make $CurrentLayoutStack point to a new (anon.) stack
  $CurrentLayoutStack = ["Standard"];

  # Store whether we're at the end of a paragraph or not
  #    for when we get to end of footnote AND 
  # Note that the footnote text will be starting a new paragraph
  # Also store the current alignment (justification)
  $OldINP = $IsNewParagraph; $OldMBD = $MayBeDeeper;
  $OldAlignment = $CurrentAlignment;
  $IsNewParagraph = 1;
  $MayBeDeeper = 0; #can't be deeper at beginning of footnote
  $CurrentAlignment = "";

     # Accents
     } elsif ($name =~ m/^$AccentTokens$/) {
  &CheckForNewParagraph; # may be at the beginning of a par

  print OUTFILE "$pre_space\n",'\i ',$name,'{'
     
     # Miscellaneous commands

     } elsif ($name eq "\\multicolumn") {
  if ($thistable = &RelyxTable::in_table) {
      # the (simple text) first arg.
      $dummy = $fileobject->eatRequiredArgument->contents->print;
      my $group = $fileobject->eatRequiredArgument;
      $thistable->multicolumn($dummy, $group);
  } else {warn "\\multicolumn is illegal outside a table!"}

     } elsif ($name eq '\cline') {
  if ($thistable = &RelyxTable::in_table) {
      # the (simple text) first arg.
      $dummy = $fileobject->eatRequiredArgument->contents->print;
      # sub hcline does cline if an arg is given
      $thistable->hcline($dummy);
  } else {warn "\\cline is illegal outside a table!"}

     } elsif ($name eq '\bibliographystyle') {
  $tok = $fileobject->eatRequiredArgument;
  $bibstyle_file = "";
  # There may be >1 token in the {}, e.g. "{a_b}" -> 3 tokens
  my @toks = $tok->contents;
  foreach $tok (@toks) {
      # kludge: CleanTeX adds {} after _
      $tok = $tok->contents if ref($tok) eq "Text::TeX::Group";
      $bibstyle_file .= $tok->print;
  }
  print "\nBibliography style file is $bibstyle_file"if $debug_on;

     # LyX \bibitem actually looks just like LaTeX bibitem, except
     # it's in a Bibliography par & there must be a space after the
     # bibitem command. Note we need to explicitly print the braces...
     } elsif ($name eq "\\bibitem") {
  $IsNewParagraph=1; # \bibitem always starts new par. in LyX
  &CheckForNewParagraph;

  $tok = $fileobject->eatOptionalArgument;
         print OUTFILE "$name ", $tok->exact_print, "{";

     # ensuremath -- copy verbatim until you're done
     # but add \( and \)
     # Note that we'll only get here if the command is NOT in math mode
     } elsif ($name eq '\ensuremath') {
  print "\nCopying math beginning with '$name'\n" if $debug_on;
  my $tok = $fileobject->eatGroup; # eat math expression
  my $dummy = $tok->exact_print;
  $dummy =~ s/\{(.*)\}/$1/;
  $dummy = &fixmath($dummy); # convert '\sp' to '^', etc.

  &CheckForNewParagraph; # math could be first thing in a par
  print OUTFILE "$pre_space\n\\begin_inset Formula \\( ";
  print $dummy if $debug_on;
  print OUTFILE $dummy;

         # end math
  print OUTFILE "\\)\n\\end_inset \n\n";
  print "\nDone copying math" if $debug_on;

     # Token in the ReadCommands command list that basic_lyx doesn't
     #    know how to handle
     } else {
  ©_latex_known($eaten,$fileobject);
     } # end big if

     # Exit the switch
     last TYPESW;
 }

 # ArgTokens appear when we've used eatRequiredArgument
 if (/^ArgToken$/) {
     # If we're copying a recognized but untranslatable token in tex mode
     my $tok = $tex_mode_tokens[-1] || 0;
     if ($eaten->base_token == $tok) {
  ©_latex_known($eaten,$fileobject);
     }
        
     last TYPESW;
 }

 if (/^EndArgsToken$/) {
     # If we're copying a recognized but untranslatable token in tex mode
     my $tok = $tex_mode_tokens[-1] || 0;
     if ($eaten->base_token eq $tok) {
  ©_latex_known($eaten,$fileobject);
         last TYPESW;
     }

     my $name = $eaten->token_name;
     print "$name" if $debug_on;

     # Handle things that LyX translates as a "LatexCommand" inset
     # or "Include" insets
     if (grep {$_ eq $name} @LatexCommands, @IncludeCommands) {
         print OUTFILE "\}\n\n\\end_inset \n\n";

     } elsif (exists $ReadCommands::ToLayout->{$name}) {
  &EndLayout($name);

     # Font characteristics
     # Pop the current FontStatus stack for a given characteristic
     #    and give the new command (e.g., \emph default)
     } elsif (exists $FontTransTable{$name}) {
         my $command = $FontTransTable{$name};
         ($dummy) = ($command =~ /(\S+)\s+\w+/);
  pop @{$CurrentFontStatus->{$dummy}};
  $command = "\n$dummy $CurrentFontStatus->{$dummy}->[-1] \n";
  print OUTFILE "$command";

     # Footnotes and marginpars
     } elsif (exists $FloatTransTable{$name}) {
         print OUTFILE "\n\\end_float \n\n";

  # Reset the layout stack and font status table pointers to
  #    point to the global stack/table again, instead of the
  #    footnote-specific stack/table
  $CurrentFontStatus = \%FontStatus;
  $CurrentLayoutStack = \@LayoutStack;

  # We need to reissue any font commands (but not layouts)
  foreach $dummy (keys %$CurrentFontStatus) {
      if ($CurrentFontStatus->{$dummy}->[-1] ne "default") {
   print OUTFILE $FontTransTable{$dummy};
      }
  }

  # Same paragraph status as we had before the footnote started
  $IsNewParagraph = $OldINP; $MayBeDeeper = $OldMBD;
  $CurrentAlignment = $OldAlignment;

     } elsif ($name =~ m/^$AccentTokens$/) {
  print OUTFILE "}\n";
     
     } elsif ($name eq "\\bibitem") {
         print OUTFILE "}\n";
     } # End if on $name

     # Exit main switch
     last TYPESW;
 } # end if EndArgsToken

 # Handle END of scope of local commands like \large
 if (/^EndLocal$/) {
     my $name = $eaten->token_name; #cmd we're ending, e.g.,\large
     print $name if $debug_on;

     if (exists $FontTransTable{$name}) {
  my $command = $FontTransTable{$name};
  ($dummy = $command) =~ s/\s*(\S*)\s+(\w+)\s*/$1/; #e.g., '\size'
  die "Font command error" if !exists $$CurrentFontStatus{$dummy};
  # TT::OF->check_presynthetic returns local commands FIFO!
  # So pop font stack, but warn if we pop the wrong thing
  warn " font confusion?" if
      pop @{$CurrentFontStatus->{$dummy}} ne $2;
  print "\nCurrent $dummy Stack: @{$CurrentFontStatus->{$dummy}}"
        if $debug_on;
  my $newfont = $CurrentFontStatus->{$dummy}->[-1];
  $command = "\n$dummy $newfont\n";
  print OUTFILE "$command";

     } else {
         warn "Unknown EndLocal token!\n";
     }

     last TYPESW;
 }

 # We don't print { or }, but we make sure that the spacing is correct
 # Handle '{'
 if (/^Begin::Group$/) {
     print OUTFILE "$pre_space";
     last TYPESW;
 }

 # Handle '{'
 if (/^End::Group$/) {
     print OUTFILE "$pre_space";
     last TYPESW;
 }

        # Handle \begin{foo}
        if (/^Begin::Group::Args$/) {
     print $eaten->print," " if $debug_on; # the string "\begin{foo}"
     my $env = $eaten->environment;
     
     # Any environment found in the layouts files
     if (exists $ReadCommands::ToLayout->{$env}) {
         &ConvertToLayout($env);

  # Some environments have an extra argument. In that case,
  # print the \layout command (cuz these environments always
  # start new pars). Then either print the extra arg or
  # ignore it (depending on the environment).
  if (exists $ExtraArgEnvironments{$env}) {
      if ($ExtraArgEnvironments{$env}) { #print it
   # Should be just one token in the arg.
   my $arg = $fileobject->eatBalanced->contents->print;
   print "\nArgument $arg to $env environment"
        if $debug_on;
   $item_preface = $ExtraArgEnvironments{$env} . $arg."\n";

      } else { #ignore it
   print "\nIgnoring argument to $env environment"
        if $debug_on;
      }
  } # end if for reading extra args to \begin command

     # Math environments
     } elsif ($env =~ /^$MathEnvironments$/o) {
  &CheckForNewParagraph; # may be beginning of paragraph
  my $begin_text = $eaten->print;
  print "\nCopying math beginning with '$begin_text'\n"
                                                if $debug_on;
  print OUTFILE "\n\\begin_inset Formula $begin_text ";
  $dummy = &Verbatim::copy_verbatim($fileobject, $eaten);
  $dummy = &fixmath($dummy); # convert '\sp' to '^', etc.
  print $dummy if $debug_on;
  print OUTFILE $dummy;

     # Alignment environments
     } elsif (exists $AlignEnvironments{$env}) {
  # Set it to the command which creates this alignment
         $CurrentAlignment = $AlignEnvironments{$env};
  ($dummy) = ($CurrentAlignment =~ /\S+\s+(\w+)/);
  print "\nNow $dummy-aligning text " if $debug_on;

  # alignment environments automatically start a new paragraph
  $IsNewParagraph = 1;

     # Environments lyx translates to floats
     } elsif (exists $FloatEnvTransTable{$env}) {
  $tok = $fileobject->eatOptionalArgument;
  if ($tok && defined ($dummy = $tok->print) && $dummy) {
      print "\nIgnoring float placement '$dummy'" if $debug_on;
  }
         my $command = $FloatEnvTransTable{$env};

  # Open the footnote
  print OUTFILE "$command";

     # table
     } elsif ($env =~ /^tabular$/) { # don't allow tabular* or ctabular
  # Table must start a new paragraph
  $IsNewParagraph = 1; $MayBeDeeper = 1;
  # We want to print table stuff *after* a \layout Standard
  &CheckForNewParagraph;

  # Since table info needs to come *before* the table content,
  #    put a line in the output file saying that the *next*
  #    reLyX pass needs to put the table info there
  print OUTFILE "\n$RelyxTable::TableBeginString\n";

  # Read and ignore an optional argument [t] or [b]
  $tok = $fileobject->eatOptionalArgument;
  if ($tok && defined ($dummy = $tok->print) && $dummy) {
      print "\nIgnoring positioning arg '$dummy'" if $debug_on;
  }

         # Read the argument into a TT::Group
  #   (that group may contain groups, e.g. for {clp{10cm}}
  $tok = $fileobject->eatGroup;
  new RelyxTable::Table $tok;

     # \begin document
     } elsif ($env eq "document") {
  # do nothing
         #print "\nStarting to translate actual document" if $debug_on;

     # Special environments to copy as regular text (-r option).
     # Do this by copying the \begin & \end command in TeX mode
     # (\Q\E around $env allows *'s in environment names!)
     } elsif (grep /^\Q$env\E$/, @ReadCommands::regular_env) {
  print "\nCopying $env environment as regular text\n"
                                                if $debug_on;
  $dummy = $eaten->print; # \begin{env}, ignore initial whitespace
  &print_tex_mode($dummy);

     # otherwise, it's an unknown environment
     # In that case, copy everything up to the \end{env}
     #    Save stuff in global tex_mode_string so we can print it
     # when we read & handle the \end{env}
     } else {

  print "\nUnknown environment $env" if $debug_on;
  $tex_mode_string = "";
  # print "\begin{env}
  # For reLyXskip env, don't print the \begin & \end commands!
  $tex_mode_string .= $eaten->exact_print 
                  unless $env eq "reLyXskip";
  $tex_mode_string .=&Verbatim::copy_verbatim($fileobject,$eaten);
     }

            last TYPESW;
        }
        
        # Handle \end{foo}
        if (/^End::Group::Args$/) {
     print $eaten->print," " if $debug_on; # the string "\end{foo}"
     my $env = $eaten->environment;

     # End of list or quote/verse environment
     # OR special environment given with -t option
     if (exists $ReadCommands::ToLayout->{$env}) {
         &EndLayout($env);
  $item_preface = ""; # reset when at end of List env.

     # End of math environments
     } elsif ($env =~ /^$MathEnvironments$/o) {
  print OUTFILE "\\end{$env}\n\\end_inset \n\n";
  print "\nDone copying math environment '$env'" if $debug_on;

     } elsif (exists $AlignEnvironments{$env}) {
  # Back to block alignment
         $CurrentAlignment = "";
  print "\nBack to block alignment" if $debug_on;

  # assume that \end should end a paragraph
  # This isn't correct LaTeX, but LyX can't align part of a par
  $IsNewParagraph = 1;

     # Environments lyx translates to floats
     } elsif (exists $FloatEnvTransTable{$env}) {
         print OUTFILE "\n\\end_float \n\n";

     # table
     } elsif ($env =~ /tabular$/) { # don't allow tabular*
         if ($thistable = &RelyxTable::in_table) {
      $thistable->done_reading;
      print OUTFILE "\n$RelyxTable::TableEndString\n";
  } else {warn "found \\end{tabular} when not in table!"}

  # Anything after a table will be a new paragraph
  $IsNewParagraph = 1; $MayBeDeeper = 1;

     } elsif ($env eq "document") {
         print "\nDone with document!" if $debug_on;

     # "regular" environment given with -r option
     } elsif (grep /^\Q$env\E$/, @ReadCommands::regular_env) {
  $dummy = $eaten->print; # \end{env}, ignore initial whitespace
  &print_tex_mode($dummy);

  # Next stuff will be new env.
  $IsNewParagraph = 1;

     # End of unknown environments. We're already in TeX mode
     } else {
  # Add \end{env} (including initial whitespace) to string
  # For reLyXskip environment, don't print \begin & \end commands!
  $tex_mode_string .= $eaten->exact_print
                         unless $env eq "reLyXskip";
  # Now print it
  &print_tex_mode($tex_mode_string);
  print "Done copying unknown environment '$env'" if $debug_on;
     }

            last TYPESW;

        }

 # Note for text handling: we have to do lots of stuff to handle
 # spaces in (as close as possible to) the same way that LaTeX does
 #    LaTeX considers all whitespace to be the same, so basically, we
 # convert each clump of whitespace to one space. Unfortunately, there
 # are special cases, like whitespace at the beginning/end of a par,
 # which we have to get rid of to avoid extra spaces in the LyX display.
 #    \n at the end of a paragraph must be considered like a space,
 # because the next line might begin with a token like \LyX. But
 # if the next line starts with \begin, say, then an extra space will be
 # generated in the LyX file. Oh well. It doesn't affect the dvi file.
 if (/^Text$/) {
     my $outstr = $eaten->print; # the actual text

     # don't bother printing whitespace
     #    Note: this avoids the problem of extra whitespace generating
     # extra Text::TeX::Paragraphs, which would generate extra
     # \layout commands
     last TYPESW if $outstr =~ /^\s+$/;

     # whitespace at beginning of a paragraph is meaningless
     # e.g. \begin{foo}\n hello \end{foo} shouldn't print the \n
     # (Note: check IsNewParagraph BEFORE calling &CFNP, which zeros it)
     my $replace = $IsNewParagraph ? "" : " ";
     $outstr =~ s/^\s+/$replace/;

     # Only write '\layout Standard' once per paragraph
     &CheckForNewParagraph;

     # \n\n signals end of paragraph, so get rid of it (and any space
     # before it)
     $outstr =~ s/\s*\n\n$//;

     # Print the LaTeX text to STDOUT
     print "'$outstr'" if $debug_on;

     # LyX *ignores* \n and \t, whereas LaTeX considers them just
     # like a space.
     #    Also, many spaces are equivalent to one space in LaTeX
     # (But LyX misleadingly displays them on screen, so get rid of them)
     $outstr =~ s/\s+/ /g;

     # protect spaces in an optional argument if necessary
     # Put a SPACE after the argument for List, Description layouts
     if ($protect_spaces) {
  $dummy = $TextTokenTransTable{'~'};

  # This will not handle brackets in braces!
  if ($outstr =~ /\]/) { # protect spaces only *until* the bracket
      my $tempstr = $`;
      my $tempstr2 = $';
      # Note that any \t's have been changed to space already
      $tempstr =~ s/ /$dummy/g;

      # Print 1 space after the argument (which finished with ])
      # Don't print 2 (i.e. remove leading space from $tempstr2)
      # don't print the bracket
      $tempstr2 =~ s/^ //;
      $outstr = "$tempstr $tempstr2";
      $protect_spaces = 0; # Done with optional argument
  } else { # protect all spaces, since we're inside brackets
      $outstr =~ s/ /$dummy/g;
  }
     } # end special stuff for protected spaces

     # Translate any LaTeX text that requires special LyX handling
     foreach $dummy (keys %TextTransTable) {
  $outstr =~ s/\Q$dummy\E/$TextTransTable{$dummy}/g;
     }

     # "pretty-print" the string. It's not perfect, since there may
     # be text in the OUTFILE before $outstr, but it will keep from
     # having REALLY long lines.
     # Try to use approximately the same word-wrapping as LyX does:
     # - before space after a period, except at end of string
     # - before first space after column seventy-one
     # - after 80'th column
     while (1) {
         $outstr =~ s/\. (?!$)/.\n /      or
  $outstr =~ s/(.{71,79}?) /$1\n / or
  $outstr =~ s/(.{80})(.)/$1\n$2/ or
  last; # exit loop if string is < 79 characters
     }

     # Actually print the text
     print OUTFILE "$outstr";
     last TYPESW;
 } # end TT::Text handling

 # The default action - this should never happen!
 print("I don't know ",$eaten->print) if $debug_on;

    } # end for ($type)

    print "\n" if $debug_on;

} #end sub basic_lyx

#########################  TEX MODE  SUBROUTINES  #########################

# This subroutine copies and prints a latex token and its arguments if any.
# This sub is only needed if the command was not found in the syntax file
# Use exact_print to preserve, e.g., whitespace after macros
sub copy_latex_unknown {
    my $eaten = shift;
    my $fileobject = shift;
    my $outstr = $eaten->exact_print;
    my ($dummy, $tok, $count);

# Copy the actual word. Copy while you've still got
#     arguments. Assume all args must be in the same paragraph
#     (There could be new paragraphs *within* args)
    #    We can't use copy_verbatim (unless we make it smarter) because
    # it would choke on nested braces
    print "\nUnknown token: '",$eaten->print,"': Copying in TeX mode\n"
                                                         if $debug_on;
    my $dum2;
    while (($dum2 = $fileobject->lookAheadToken) &&
    ($dum2 =~ /^[[{]$/)) {
 if ($dum2 eq '[') { #copy optional argument - assume it's simple
     $tok = $fileobject->eatOptionalArgument;
     $outstr .= $tok->exact_print; # also print brackets & whitespace
 } else {
     $count = 0;
     EAT: { #copied from eatBalanced, but allow paragraphs
         die unless defined ($tok = $fileobject->eatMultiToken);
  $outstr.="\n",redo EAT if ref($tok) eq "Text::TeX::Paragraph";
  $dummy = $tok->exact_print;
  $outstr .= $dummy;
  # Sometimes, token will be '\n{', e.g.
  $count++ if $dummy =~ /^\s*\{$/; # add a layer of nesting
  $count-- if $dummy =~ /^\s*\}$/; # end one layer of nesting
  redo EAT if $count; #don't dump out until all done nesting
     } #end EAT block
 } # end if $dummy = [{

    } #end while
    # Add {} after macro if it's followed by '}'. Otherwise, {\foo}bar
    #     will yield \foobar when LyX creates LaTeX files
    $outstr.="{}" if $outstr=~/\\[a-zA-Z]+$/ && $dum2 eq '}';

    # Print it out in TeX mode
    &print_tex_mode($outstr);

    print "\nDone copying unknown token" if $debug_on;
} # end sub copy_latex_unknown

# Copy an untranslatable latex command whose syntax we know, along with its
# arguments
#    The command itself, optional arguments, and untranslatable
# arguments get copied in TeX mode. However, arguments which contain regular
# LaTeX will get translated by reLyX. Do that by printing what you have so
# far in TeX mode, leaving this subroutine, continuing with regular reLyX
# translating, and then returning here when you reach the ArgToken or
# EndArgsToken at the end of the translatable argument.
#    We need to keep a stack of the tokens that brought us here, because
# you might have nested commands (e.g., \mbox{hello \fbox{there} how are you}
sub copy_latex_known {
    my ($eaten, $fileobject) = (shift,shift);
    my $type = ref($eaten);
    $type =~ s/^Text::TeX::// or die "unknown token?!";

    # token itself for TT::Token, TT::BegArgsToken,
    # Corresponding BegArgsToken for ArgToken,EndArgsToken
    my $temp_start = $eaten->base_token;

# Initialize tex mode copying
    if ($type eq "BegArgsToken" or $type eq "Token") {
 print "\nCopying untranslatable token '",$eaten->print,
                               "' in TeX mode" if $debug_on;
 push @tex_mode_tokens, $temp_start;

 # initialize the string of stuff we're copying
 $tex_mode_string = $eaten->exact_print;
    } # Start tex copying?

# Handle arguments
    # This token's next arguments -- returns a string matching /o*[rR]?/
    my $curr_args = $eaten->next_args($fileobject);

    if ($type eq "EndArgsToken" or $type eq "ArgToken") {
 # Print ending '}' for the group we just finished reading
 $tex_mode_string .= '}';
    }

    # If there could be optional arguments next, copy them
    while ($curr_args =~ s/^o// && $fileobject->lookAheadToken eq '[') {
 my $opt = $fileobject->eatOptionalArgument;
 $tex_mode_string .= $opt->exact_print;
    }
    $curr_args =~ s/^o*//; # Some OptArgs may not have appeared

    if ($type eq "BegArgsToken" or $type eq "ArgToken") {
 # Print beginning '{' for the group we're about to read
 $tex_mode_string .= '{';
    }

    # Now copy the next required argument, if any
    # Copy it verbatim (r), or translate it as regular LaTeX (R)?
    if ($curr_args =~ s/^r//) {
 my $group = $fileobject->eatRequiredArgument;
 my $temp = $group->exact_print;
 # Remove braces. They're put in explicitly
 $temp =~ s/\{(.*)\}/$1/; # .* is greedy
 $tex_mode_string .= $temp;

    } elsif ($curr_args =~ s/^R//) {
 print "\n" if $debug_on;
 &print_tex_mode($tex_mode_string);
 $tex_mode_string = "";
 print "\nTranslating this argument for ",$temp_start->print,
       " as regular LaTeX" if $debug_on;

    } else { # anything but '' is weird
 warn "weird arg $curr_args to ",$temp_start->print,"\n" if $curr_args;
    }

# Finished tex mode copying
    if ($type eq "Token" or $type eq "EndArgsToken") {

 # Add {} to plain tokens followed by { or }. Otherwise {\foo}bar
 # and \foo{bar} yield \foobar in the LaTeX files created by LyX
 my $dummy;
 if ($type eq "Token" and
         $dummy=$fileobject->lookAheadToken and
         $dummy =~ /[{}]/)
 {
     $tex_mode_string .= '{}';
 }

 # Print out the string
 print "\n" if $debug_on;
 &print_tex_mode($tex_mode_string);
 $tex_mode_string = "";

        # We're done with this token
 pop(@tex_mode_tokens);

 my $i = $type eq "Token" ? "" : " and its arguments";
 my $j = $temp_start->print;
 print "\nDone copying untranslatable token '$j'$i in TeX mode"
                                                   if $debug_on;
    } # end tex copying?
} # end sub copy_latex_known

# Print a string in LyX "TeX mode"
#    The goal of this subroutine is to create a block of LyX which will be
# translated exactly back to the original when LyX creates its temporary LaTeX
# file prior to creating a dvi file.
#    Don't print \n\n at the end of the string... instead just set the
# new paragraph flag. Also, don't print \n at the beginning of the string.
# Print nothing if it's the beginning of a paragraph, or space otherwise.
# These two things avoid extra C-Enter's in the LyX file
sub print_tex_mode {
    my $outstr = shift;

    print "'$outstr'" if $debug_on;

    # Handle extra \n's
    my $str_ends_par = ($outstr =~ s/\n{2,}$//);
    if ($IsNewParagraph) {
        $outstr =~ s/\n//;  # .e.g, $outstr follows '\begin{quote}\n'
    } else {
        $outstr =~ s/\n/ /; # e.g. $outstr follows '\LaTeX{}\n'
    }

    # Check whether string came right at the beginning of a new paragraph
    # This *might* not be necessary. Probably can't hurt.
    &CheckForNewParagraph;

    # Get into TeX mode
    print OUTFILE "$start_tex_mode";

    # Do TeX mode translation;
    $outstr =~ s/\\/\n\\backslash /g;
    # don't translate \n in '\n\backslash' that we just made!
    $outstr =~ s/\n(?!\\backslash)/\n\\newline \n/g;

    # Print the actual token + arguments if any
    print OUTFILE $outstr;

    # Get OUT of LaTeX mode (and end nesting if nec.)
    print OUTFILE "$end_tex_mode";
    $IsNewParagraph = $str_ends_par;

    return;
} # end sub print_tex_mode

############################  LAYOUT  SUBROUTINES  ###########################

sub CheckForNewParagraph {
# This subroutine makes sure we only write \layout command once per paragraph
#    It's mostly necessary cuz 'Standard' layout is the default in LaTeX;
#    there is no command which officially starts a standard environment
# If we're in a table, new layouts aren't allowed, so just return
# If $IsNewParagraph is 0, it does nothing
# If $INP==1, It starts a new paragraph
# If $CurrentAlignment is set, it prints the alignment command for this par.
# If $MayBeDeeper==1 and we're currently within a list environment,
#    it starts a "deeper" Standard paragraph
    my $dummy; 
    my $layout = $$CurrentLayoutStack[-1];

    return if &RelyxTable::in_table;

    if ($IsNewParagraph) {
 # Handle standard text within a list environment specially
 if ($MayBeDeeper) {
     if ($layout =~ /^$ListLayouts$/o) {
  push (@$CurrentLayoutStack, "Standard");
  print "\nCurrent Layout Stack: @$CurrentLayoutStack\n"
                                       if $debug_on;
  print OUTFILE "\n\\begin_deeper ";
  $layout = "Standard";
     }
     $MayBeDeeper = 0; # Don't test again until new paragraph
 }

 # Print layout command itself
 print OUTFILE "\n\\layout $layout\n\n";
 print OUTFILE $CurrentAlignment if $CurrentAlignment;

 # Now that we've written the command, it's no longer a new paragraph
 $IsNewParagraph = 0;

 # When you write a new paragraph, reprint any font commands
 foreach $dummy (keys %$CurrentFontStatus) {
     my $currf = $CurrentFontStatus->{$dummy}->[-1];
     if ($currf ne "default") {
  print OUTFILE "\n$dummy $currf \n";
     }
 }
    } # end if $INP
} # end sub CheckForNewParagraph

sub ConvertToLayout {
# This subroutine begins a new layout, pushing onto the layout stack, nesting
# if necessary. It doesn't actually write the \layout command -- that's
# done by CheckForNewParagraph.
#    The subroutine assumes that it's being passed an environment name or macro
# which is known and which creates a known layout
#    It uses the ToLayout hash (created by the ReadCommands module) which
# gives the LyX layout for a given LaTeX command or environment
# Arg0 is the environment or macro
    my $name = shift;

    my $layoutref = $ReadCommands::ToLayout->{$name};
    my $layout = $layoutref->{'layout'};
    my $dummy = ($name =~ /^\\/ ? "macro" : "environment");
    print "\nChanging $dummy $name to layout $layout" if $debug_on;

    # Nest if the layout stack has more than just "Standard" in it
    if ($#{$CurrentLayoutStack} > 0) {
 # Die here for sections & things that can't be nested!
 print " Nesting!" if $debug_on;
 print OUTFILE "\n\\begin_deeper ";
    }

    # Put the new layout onto the layout stack
    push @$CurrentLayoutStack, $layout;
    print "\nCurrent Layout Stack: @$CurrentLayoutStack" if $debug_on;

    # Upcoming text will be new paragraph, needing a new layout cmd
    $IsNewParagraph = 1;

    # Test for nested "Standard" paragraph in upcoming text?
    # Some environments can nest. Sections & Title commands can't
    $MayBeDeeper = $layoutref->{"nestable"};

} # end sub ConvertToLayout

sub EndLayout {
# This subroutine ends a layout, popping the layout stack, etc.
#    The subroutine assumes that it's being passed an environment name or macro
# which is known and which creates a known layout
#    It uses the ToLayout hash (created by the ReadCommands module) which
# gives the LyX layout for a given LaTeX command or environment
# Arg0 is the environment or macro
    my $name = shift;

    my $layoutref = $ReadCommands::ToLayout->{$name};
    my $layout = $layoutref->{'layout'};
    my $dummy = ($name =~ /^\\/ ? "macro" : "environment");
    print "\nEnding $dummy $name (layout $layout)" if $debug_on;

    my $mylayout = pop (@$CurrentLayoutStack);

    # If a standard paragraph was the last thing in a list, then
    #     we need to end_deeper and then pop the actual list layout
    # This should only happen if the Standard layout was nested
    #    in a nestable layout. We don't check.
    if ($mylayout eq "Standard") {
 print OUTFILE "\n\\end_deeper ";
 print " End Standard Nesting!" if $debug_on;
 $mylayout = pop (@$CurrentLayoutStack);
    }

    # The layout we popped off the stack had better match the
    #    environment (or macro) we're ending!
    if ($mylayout ne $layout) { die "Problem with Layout Stack!\n"};
    print "\nCurrent Layout Stack: @$CurrentLayoutStack" if $debug_on;

    # If we're finishing a nested layout, we need to end_deeper
    # This should only happen if the layout was nested
    #    in a nestable layout. We don't check.
    # Note that if we're nested in a list environment and the
    #     NEXT paragraph is Standard, then we'll have an extra
    #     \end_deeper \begin_deeper in the LyX file. It's sloppy
    #     but it works, and LyX will get rid of it when it
    #     resaves the file.
    if ($#{$CurrentLayoutStack} > 0) {
 print " End Nesting!" if $debug_on;
 print OUTFILE "\n\\end_deeper ";
    }

    # Upcoming text will be new paragraph, needing a new layout cmd
    $IsNewParagraph = 1;

    # Test for nested "Standard" paragraph in upcoming text?
    # Some environments can nest. Sections & Title commands can't
    $MayBeDeeper = $layoutref->{"nestable"};
} # end sub EndLayout

#######################  MISCELLANEOUS SUBROUTINES  ###########################
sub fixmath {
# Translate math commands LyX doesn't support into commands it does support
    my $input = shift;
    my $output = "";

    while ($input =~ s/
     (.*?)    # non-token matter ($1)
     (\\      # token ($2) is a backslash followed by ...
         ( ([^A-Za-z] \*?) |    # non-letter (and *) ($4) OR
    ([A-Za-z]+ \*?)   )  # letters (and *) ($5)
     )//xs) # /x to allow whitespace/comments, /s to copy \n's
    { 
 $output .= $1;
 my $tok = $2;
 if (exists $ReadCommands::math_trans{$tok}) {
     $tok = $ReadCommands::math_trans{$tok};
     # add ' ' in case we had, e.g., \|a, which would become \Verta
     # Only need to do it in those special cases
     $tok .= ' ' if
             defined $4 && $tok =~ /[A-Za-z]$/ && $input =~ /^[A-Za-z]/;
 }
 $output .= $tok;
    }
    $output .= $input; # copy what's left in $input

    return $output;
}

1; # return true to calling subroutine


[ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge