1 /* vertical.c - routines that handle vertical space issues
2 
3 Copyright (C) 2002 The Free Software Foundation
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19 This file is available from http://sourceforge.net/projects/latex2rtf/
20 
21 **************************************************************************
22 
23 The tricky part is that latex2rtf is a one-pass converter.  The right thing
24 must be done with each character.  Consider the sequence
25 
26            \vspace{1cm}\noindent New paragraph.
27 
28 When latex2rtf reaches the 'N', then a new paragraph should be started.  We
29 know it is a new paragraph because \vspace should have put the converter
30 into a MODE_VERTICAL and characters are only emitted in MODE_HORIZONTAL.
31 
32 RTF needs to set up the entire paragraph at one time and the
33 
34     * text alignment
35     * line spacing
36     * vertical space above
37     * left margin
38     * right margin
39     * paragraph indentation
40 
41 must all be emitted at this time.  This file contains routines
42 that affect these quantities
43 ******************************************************************************/
44 
45 #include <string.h>
46 #include <stdlib.h>
47 #include <errno.h>
48 #include <ctype.h>
49 #include "main.h"
50 #include "funct1.h"
51 #include "cfg.h"
52 #include "utils.h"
53 #include "parser.h"
54 #include "lengths.h"
55 #include "vertical.h"
56 #include "convert.h"
57 #include "commands.h"
58 #include "styles.h"
59 #include "fonts.h"
60 #include "stack.h"
61 #include "xrefs.h"
62 #include "counters.h"
63 #include "fields.h"
64 #include "acronyms.h"
65 
66 static int g_TeX_mode = MODE_VERTICAL;
67 static int g_line_spacing = 240;
68 static int g_paragraph_no_indent = FALSE;
69 static int g_paragraph_inhibit_indent = FALSE;
70 static int g_vertical_space_to_add = 0;
71 static int g_right_margin_indent;
72 static int g_left_margin_indent;
73 static int g_page_new = FALSE;
74 static int g_column_new = FALSE;
75 static int g_alignment = JUSTIFIED;
76 static int g_par_brace = 0;
77 
78 char TexModeName[7][25] = { "bad", "internal vertical", "horizontal",
79     "restricted horizontal", "math", "displaymath", "vertical"
80 };
81 
82 char ParOptionName[8][13] = { "bad", "FIRST", "GENERIC", "SECTION",
83                               "EQUATION", "SLASHSLASH", "LIST", "ENVIRONMENT"};
84 
85 /******************************************************************************
86      left and right margin accessor functions
87  ******************************************************************************/
setLeftMarginIndent(int indent)88 void setLeftMarginIndent(int indent)
89 {
90     g_left_margin_indent = indent;
91 }
92 
setRightMarginIndent(int indent)93 void setRightMarginIndent(int indent)
94 {
95     g_right_margin_indent = indent;
96 }
97 
getLeftMarginIndent(void)98 int getLeftMarginIndent(void)
99 {
100     return g_left_margin_indent;
101 }
102 
getRightMarginIndent(void)103 int getRightMarginIndent(void)
104 {
105     return g_right_margin_indent;
106 }
107 
108 /******************************************************************************
109      paragraph alignment accessor functions
110  ******************************************************************************/
setAlignment(int align)111 void setAlignment(int align)
112 {
113     g_alignment = align;
114 }
115 
getAlignment(void)116 int getAlignment(void)
117 {
118     return g_alignment;
119 }
120 
121 /******************************************************************************
122      vertical space between paragraph accessor functions
123  ******************************************************************************/
setVspace(int space)124 void setVspace(int space)
125 {
126     g_vertical_space_to_add = space;
127 }
128 
getVspace(void)129 int getVspace(void)
130 {
131     return g_vertical_space_to_add;
132 }
133 
134 /******************************************************************************
135      line spacing accessor functions
136  ******************************************************************************/
setLineSpacing(int spacing)137 static void setLineSpacing(int spacing)
138 {
139     g_line_spacing = spacing;
140 }
141 
getLineSpacing(void)142 static int getLineSpacing(void)
143 {
144     return g_line_spacing;
145 }
146 
147 
148 /******************************************************************************
149 TeX has six modes:
150 
151     MODE_VERTICAL              Building the main vertical list, from which the
152                                pages of output are derived
153 
154     MODE_INTERNAL_VERTICAL     Building a vertical list from a vbox
155 
156     MODE_HORIZONTAL            Building a horizontal list for a paragraph
157 
158     MODE_RESTICTED_HORIZONTAL  Building a horizontal list for an hbox
159 
160     MODE_MATH                  Building a mathematical formula to be placed in a
161                                horizontal list
162 
163     MODE_DISPLAYMATH           Building a mathematical formula to be placed on a
164                                line by itself, temporarily interrupting the current paragraph
165 
166 LaTeX has three modes: paragraph mode, math mode, or left-to-right mode.
167 This is not a particularly useful, since paragraph mode is a combination of
168 vertical and horizontal modes.
169 
170 Why bother keeping track of modes?  Mostly so that paragraph indentation gets handled
171 correctly, as well as vertical and horizontal space.  The mode is also the primary
172 way that the end of a paragraph is signalled.
173  ******************************************************************************/
setTexMode(int mode)174 void setTexMode(int mode)
175 {
176     diagnostics(6, "TeX mode setting from [%s] -> [%s]", TexModeName[g_TeX_mode], TexModeName[mode]);
177     g_TeX_mode = mode;
178 }
179 
getTexMode(void)180 int getTexMode(void)
181 {
182     return g_TeX_mode;
183 }
184 
changeTexMode(int mode)185 void changeTexMode(int mode)
186 {
187     diagnostics(6, "TeX mode changing from [%s] -> [%s]", TexModeName[g_TeX_mode], TexModeName[mode]);
188 
189     if (g_TeX_mode == MODE_VERTICAL && mode == MODE_HORIZONTAL)
190         startParagraph("Normal", PARAGRAPH_GENERIC);
191 
192     if (g_TeX_mode == MODE_HORIZONTAL && mode == MODE_VERTICAL)
193         CmdEndParagraph(0);
194 
195     g_TeX_mode = mode;
196 }
197 
198 /******************************************************************************
199     RTF codes to create a new paragraph.  If the paragraph should
200     not be indented then emit \fi0 otherwise use the current value
201     of \parindent as the indentation of the first line.
202 
203     style describes the type of paragraph ...
204       "Normal"
205       "caption"
206       "author"
207       "bibitem"
208       "section"
209       etc.
210 
211     indenting describes how this paragraph and (perhaps) the following
212     paragraph should be indented
213 
214       PARAGRAPH_SECTION_TITLE  (do not indent this paragraph or the next)
215       PARAGRAPH_FIRST  (do not indent this paragraph but indent the next)
216       PARAGRAPH_GENERIC        (indent as needed)
217       PARAGRAPH_LIST           (the first paragraph of a list item)
218       PARAGRAPH_SLASHSLASH
219       PARAGRAPH_ENVIRONMENT    (include topsep before and after final --- not impl.)
220 
221     Sometimes it is necessary to influence the next paragraph will
222     be before it has been parsed.  For example, a section command
223     should create a paragraph for the section title and then the
224     next paragraph encountered should be handled like as a first
225     paragraph.
226 
227     The problem arises because "\n\n" means different things in different
228     contexts.  After \section{aaa} "\n\n" does not indicate that the next
229     paragraph should be indented.  However after \end{itemize} "\n\n"
230     means that the next paragraph should be indented.  Now CmdEndParagraph()
231     will set g_paragraph_inhibit_indent to FALSE so that the common case
232     of starting new paragraphs is handled appropriately.
233 
234     For PARAGRAPH_FIRST, then it is the first paragraph in a section.
235     Usually the first paragraph is not indented.  However, when the
236     document is being typeset in french it should have normal indentation.
237     Another special case occurs when the paragraph being typeset is
238     in a list environment.  In this case, we need to indent according
239     to the current parindent to obtain the proper hanging indentation
240 
241     The default is to indent according to
242     the current parindent.  However, if the g_paragraph_inhibit_indent
243     flag or the g_paragraph_no_indent flag is TRUE, then do not indent
244     the next line.  Typically these flags are set just after a figure
245     or equation or table.
246  ******************************************************************************/
startParagraph(const char * style,int indenting)247 void startParagraph(const char *style, int indenting)
248 {
249     int width, a, b, c;
250     int parindent,parskip;
251     static char last_style[50] = "Normal";
252     static char the_style[50] = "Normal";
253     static int last_indent = 0;
254     static int next_paragraph_after_section = TRUE;
255 
256     int orig_font_family = CurrentFontFamily();
257     int orig_font_size = CurrentFontSize();
258     int orig_font_series = CurrentFontSeries();
259     int orig_font_shape = CurrentFontShape();
260 
261     /* special style "last" will just repeat previous */
262     if (strcmp(style,"last")==0) {
263         diagnostics(4,"using last style = '%s'",last_style);
264         if (indenting != PARAGRAPH_SLASHSLASH)
265         	indenting = last_indent;
266         strcpy(the_style,last_style);
267     } else {
268         diagnostics(4,"using style = '%s'",style);
269         last_indent = indenting;
270         strcpy(last_style,style);
271         strcpy(the_style,style);
272     }
273 
274     parindent = getLength("parindent");
275     parskip   = getLength("parskip");
276 
277     if (g_par_brace !=0 )
278         diagnostics(5,"******************* starting %s paragraph with braces = %d", style, g_par_brace);
279 
280     if (g_par_brace == 1)
281         CmdEndParagraph(0);
282 
283     width = getLength("textwidth");
284     a = (int) (0.45 * width);
285     b = (int) (0.50 * width);
286     c = (int) (0.55 * width);
287 
288     switch(indenting) {
289 
290         case PARAGRAPH_SECTION_TITLE:         /* titles are never indented */
291             diagnostics(5, "PARAGRAPH_SECTION_TITLE");
292             parindent = 0;
293             break;
294 
295         case PARAGRAPH_FIRST:                 /* French indents first paragraph */
296             diagnostics(5, "PARAGRAPH_FIRST");
297             if (!FrenchMode)
298                 parindent = 0;
299             break;
300 
301         case PARAGRAPH_EQUATION:              /* typically centered with no indent */
302             diagnostics(5, "PARAGRAPH_EQUATION");
303             parindent = 0;
304             break;
305 
306         case PARAGRAPH_SLASHSLASH:            /* \\ is a line break, don't indent */
307             diagnostics(5, "PARAGRAPH_SLASHSLASH");
308             parindent = 0;
309             break;
310 
311         case PARAGRAPH_LIST:                  /* first paragraph in a list, don't monkey */
312             diagnostics(5, "PARAGRAPH_LIST"); /* with indenting */
313             break;
314 
315         default:                              /* Worry about not indenting */
316             diagnostics(5, "PARAGRAPH_GENERIC");
317             if (next_paragraph_after_section || g_paragraph_no_indent ||
318                 g_paragraph_inhibit_indent   || g_processing_list_environment)
319                 parindent = 0;
320             break;
321     }
322 
323     if (g_processing_preamble) {
324         diagnostics(5,"Encountered StartParagraph() in preamble");
325         return;
326     }
327 
328     if (g_par_brace != 0)
329         diagnostics(5,"starting paragraph with braces = %d", g_par_brace);
330     g_par_brace++;
331 
332     diagnostics(5, "Paragraph mode    %s", TexModeName[getTexMode()]);
333     diagnostics(5, "Paragraph option  %s", ParOptionName[indenting]);
334     diagnostics(5, "Noindent is       %s", (g_paragraph_no_indent) ? "TRUE" : "FALSE");
335     diagnostics(5, "Inhibit is        %s", (g_paragraph_inhibit_indent) ? "TRUE" : "FALSE");
336     diagnostics(5, "left indent is    %d", g_left_margin_indent);
337     diagnostics(5, "right indent is   %d", g_right_margin_indent);
338     diagnostics(5, "current parindent %d", getLength("parindent"));
339     diagnostics(5, "this parindent    %d", parindent);
340     diagnostics(5, "current style is    %s", the_style);
341     diagnostics(6, "current family      %d", CurrentFontFamily());
342     diagnostics(6, "current font size   %d", CurrentFontSize());
343     diagnostics(6, "current font series %d", CurrentFontSeries());
344     diagnostics(6, "current font shape  %d", CurrentFontShape());
345 
346     if (g_page_new) {
347         fprintRTF("\\page\n");   /* causes new page */
348         g_page_new = FALSE;
349         g_column_new = FALSE;
350     }
351 
352     if (g_column_new) {
353         fprintRTF("\\column\n"); /* causes new column */
354         g_column_new = FALSE;
355     }
356 
357     fprintRTF("\\pard\\plain");
358     InsertStyle(the_style);
359     if (strcmp(the_style,"equation")==0)
360         fprintRTF("\\tqc\\tx%d", b);
361     if (strcmp(the_style,"equationNum")==0)
362         fprintRTF("\\tqc\\tx%d\\tqr\\tx%d", b, width);
363     if (strcmp(the_style,"equationAlign")==0)
364         fprintRTF("\\tqr\\tx%d\\tql\\tx%d", a, b);
365     if (strcmp(the_style,"equationAlignNum")==0)
366         fprintRTF("\\tqr\\tx%d\\tql\\tx%d\\tqr\\tx%d", a, b, width);
367     if (strcmp(the_style,"equationArray")==0)
368         fprintRTF("\\tqr\\tx%d\\tqc\\tx%d\\tql\\tx%d", a, b, c);
369     if (strcmp(the_style,"equationArrayNum")==0)
370         fprintRTF("\\tqr\\tx%d\\tqc\\tx%d\\tql\\tx%d\\tqr\\tx%d", a, b, c, width);
371 
372     if (strcmp(the_style,"bitmapCenter")==0)
373         fprintRTF("\\tqc\\tx%d\\tqr\\tx%d", b, width);
374 
375     /* TODO change width/6 with hint */
376     if (strcmp(the_style,"acronym")==0)
377         fprintRTF("\\tx%d\\tqr\\tldot\\tx%d", acronymHint(width), width);
378 
379     fprintRTF("\\sl%i\\slmult1 ", getLineSpacing());
380 
381     if (getVspace() > 0)
382         fprintRTF("\\sb%d ", getVspace());
383     setVspace(parskip);
384 
385     if (g_left_margin_indent != 0)
386         fprintRTF("\\li%d", g_left_margin_indent);
387 
388     if (g_right_margin_indent != 0)
389         fprintRTF("\\ri%d", g_right_margin_indent);
390 
391     fprintRTF("\\fi%d ", parindent);
392 
393     /* these are strstr because might end in 0 */
394     if (strstr("part",the_style)    == NULL &&
395         strstr("title",the_style)   == NULL &&
396         strstr("chapter",the_style) == NULL &&
397         strstr("section",the_style) == NULL ) {
398 
399         if (CurrentFontFamily() != orig_font_family)
400             fprintRTF("\\f%d ", orig_font_family);
401 
402         if (CurrentFontSize() != orig_font_size)
403             fprintRTF("\\fs%d ", orig_font_size);
404 
405         if (CurrentFontSeries() != orig_font_series)
406             CmdFontSeries(orig_font_series);
407 
408         if (CurrentFontShape() != orig_font_shape)
409             CmdFontShape(orig_font_shape);
410     }
411 
412     setTexMode(MODE_HORIZONTAL);
413 
414     if (!g_processing_list_environment) {
415         g_paragraph_no_indent = FALSE;
416         if (indenting == PARAGRAPH_SECTION_TITLE)
417             g_paragraph_inhibit_indent = TRUE;
418         else
419             g_paragraph_inhibit_indent = FALSE;
420     }
421 
422     if (indenting == PARAGRAPH_SECTION_TITLE && !FrenchMode)
423     	next_paragraph_after_section = TRUE;
424     else
425     	next_paragraph_after_section = FALSE;
426 
427 }
428 
CmdEndParagraph(int code)429 void CmdEndParagraph(int code)
430 
431 /******************************************************************************
432      purpose : ends the current paragraph and return to MODE_VERTICAL.
433  ******************************************************************************/
434 {
435     int mode = getTexMode();
436     diagnostics(5, "CmdEndParagraph mode = %s, braces=%d", TexModeName[mode], g_par_brace);
437 
438     if (g_par_brace == 1) {
439         endAllFields();
440         fprintRTF("\\par\n");
441         setTexMode(MODE_VERTICAL);
442         g_par_brace=0;
443         g_paragraph_inhibit_indent = FALSE;
444     } else {
445         if (getTexMode() != MODE_VERTICAL)
446             diagnostics(5,"*********************** ending paragraph with braces = %d", g_par_brace);
447         g_paragraph_inhibit_indent = FALSE;
448     }
449 
450 }
451 
CmdHfill(int code)452 void CmdHfill(int code)
453 
454 /******************************************************************************
455      purpose : should do something about the paragraph style but
456      for now, just make sure that we are in horizontal mode.
457  ******************************************************************************/
458 {
459 	if (getTexMode()==MODE_VERTICAL)
460 		changeTexMode(MODE_HORIZONTAL);
461 }
462 
CmdVspace(int code)463 void CmdVspace(int code)
464 
465 /******************************************************************************
466      purpose : vspace, vspace*, and vskip
467 
468      note that \vskip3mm will end a paragraph, but \vspace{1cm} will not.
469  ******************************************************************************/
470 {
471     int vspace=0;
472     char *s;
473 
474     switch (code) {
475         case VSPACE_VSPACE:
476             s = getBraceParam();
477             vspace = getStringDimension(s);
478             free(s);
479             break;
480 
481         case VSPACE_VSKIP:
482             vspace = getDimension();
483     		if (getTexMode() != MODE_VERTICAL) {
484             	CmdEndParagraph(0);
485             	CmdIndent(INDENT_INHIBIT);
486             }
487             break;
488 
489         case VSPACE_SMALL_SKIP:
490             vspace = getLength("smallskipamount");
491     		if (getTexMode() != MODE_VERTICAL) {
492             	CmdEndParagraph(0);
493             	CmdIndent(INDENT_INHIBIT);
494             }
495             break;
496 
497         case VSPACE_MEDIUM_SKIP:
498             vspace = getLength("medskipamount");
499     		if (getTexMode() != MODE_VERTICAL) {
500             	CmdEndParagraph(0);
501             	CmdIndent(INDENT_INHIBIT);
502             }
503             break;
504 
505         case VSPACE_BIG_SKIP:
506             vspace = getLength("bigskipamount");
507     		if (getTexMode() != MODE_VERTICAL) {
508             	CmdEndParagraph(0);
509             	CmdIndent(INDENT_INHIBIT);
510             }
511             break;
512     }
513 
514     if (getTexMode() == MODE_VERTICAL)
515         setVspace(getVspace()+vspace);
516 }
517 
CmdIndent(int code)518 void CmdIndent(int code)
519 
520 /******************************************************************************
521  purpose : set flags so that startParagraph() does the right thing
522 
523            INDENT_INHIBIT allows the next paragraph to be indented if
524            a paragraph break occurs before startParagraph() is called
525 
526            INDENT_NONE tells startParagraph() to not indent the next paragraph
527 
528            INDENT_USUAL has startParagraph() use the value of \parindent
529  ******************************************************************************/
530 {
531     diagnostics(5, "CmdIndent TeX Mode = %s", TexModeName[getTexMode()]);
532     if (code == INDENT_NONE)
533         g_paragraph_no_indent = TRUE;
534 
535     else if (code == INDENT_INHIBIT)
536         g_paragraph_inhibit_indent = TRUE;
537 
538     else if (code == INDENT_USUAL) {
539         g_paragraph_no_indent = FALSE;
540         g_paragraph_inhibit_indent = FALSE;
541     }
542     diagnostics(5, "Noindent is %d", (int) g_paragraph_no_indent);
543     diagnostics(5, "Inhibit  is %d", (int) g_paragraph_inhibit_indent);
544 }
545 
CmdNewPage(int code)546 void CmdNewPage(int code)
547 
548 /******************************************************************************
549   purpose: starts a new page
550 parameter: code: newpage or newcolumn-option
551  ******************************************************************************/
552 {
553     diagnostics(5, "CmdNewPage mode = %d", getTexMode());
554     switch (code) {
555         case NewPage:
556             g_page_new = TRUE;
557             break;
558 
559         case NewColumn:
560             g_column_new = TRUE;
561             break;
562     }
563 }
564 
565 /******************************************************************************
566   purpose: support for \singlespacing, \onehalfspacing, and \doublespacing
567  ******************************************************************************/
CmdLineSpacing(int code)568 void CmdLineSpacing(int code)
569 {
570     setLineSpacing(code);
571 }
572 
573 /******************************************************************************
574   purpose: support \begin{spacing}{xx} ... \end{spacing}
575  ******************************************************************************/
CmdSpacingEnviron(int code)576 void CmdSpacingEnviron(int code)
577 {
578 	char *sizeParam;
579 	static int originalSpacing=240;
580 	float spacing;
581     int true_code = code & ~ON;
582 
583     if (code & ON) {
584 		originalSpacing = getLineSpacing();
585 		if (true_code==2)
586 			setLineSpacing(480);
587 		else {
588 			sizeParam = getBraceParam();
589 			if (*sizeParam) {
590 				sscanf(sizeParam, "%f", &spacing);
591 				setLineSpacing((int)240*spacing);
592 				free(sizeParam);
593 			}
594 		}
595 		PushEnvironment(SPACING_MODE);
596 		return;
597 	}
598 
599 	CmdEndParagraph(0);
600 	PopEnvironment();
601 	setLineSpacing(originalSpacing);
602 }
603 
CmdAlign(int code)604 void CmdAlign(int code)
605 
606 /*****************************************************************************
607     purpose : sets the alignment for a paragraph
608   parameter : code: alignment centered, justified, left or right
609  ********************************************************************************/
610 {
611     char *s;
612     static char old_alignment_before_center = JUSTIFIED;
613     static char old_alignment_before_right = JUSTIFIED;
614     static char old_alignment_before_left = JUSTIFIED;
615     static char old_alignment_before_centerline = JUSTIFIED;
616 
617     if (code == PAR_VCENTER) {
618         int restart_field=0;
619 
620         if (EQ_field_active()) {
621             diagnostics(4,"ending field due to \\vcenter");
622             restart_field = 1;
623             endCurrentField();
624         }
625 
626         s = getBraceParam();
627         ConvertString(s);
628         free(s);
629 
630         if (restart_field)
631             startField(FIELD_EQ);
632         return;
633     }
634 
635     CmdEndParagraph(0);
636     switch (code) {
637         case (PAR_CENTERLINE):
638             old_alignment_before_centerline = getAlignment();
639             setAlignment(CENTERED);
640             fprintRTF("{");
641             diagnostics(4, "Entering Convert from CmdAlign (centerline)");
642             Convert();
643             diagnostics(4, "Exiting Convert from CmdAlign (centerline)");
644             setAlignment(old_alignment_before_centerline);
645             CmdEndParagraph(0);
646             fprintRTF("}");
647             break;
648 
649         case (PAR_RAGGEDRIGHT):
650             old_alignment_before_centerline = getAlignment();
651             setAlignment(LEFT);
652 
653             diagnostics(4, "Entering Convert from CmdAlign (raggedright)");
654             Convert();
655             diagnostics(4, "Exiting Convert from CmdAlign (raggedright)");
656             setAlignment(old_alignment_before_centerline);
657             CmdEndParagraph(0);
658 
659             break;
660 
661         case (PAR_CENTER | ON):
662             CmdIndent(INDENT_NONE);
663             old_alignment_before_center = getAlignment();
664             setAlignment(CENTERED);
665             break;
666         case (PAR_CENTER | OFF):
667             setAlignment(old_alignment_before_center);
668             CmdEndParagraph(0);
669             CmdIndent(INDENT_INHIBIT);
670             break;
671 
672         case (PAR_RIGHT | ON):
673             old_alignment_before_right = getAlignment();
674             setAlignment(RIGHT);
675             CmdIndent(INDENT_NONE);
676             break;
677         case (PAR_RIGHT | OFF):
678             setAlignment(old_alignment_before_right);
679             CmdIndent(INDENT_INHIBIT);
680             break;
681 
682         case (PAR_LEFT | ON):
683             old_alignment_before_left = getAlignment();
684             setAlignment(LEFT);
685             CmdIndent(INDENT_NONE);
686             break;
687         case (PAR_LEFT | OFF):
688             setAlignment(old_alignment_before_left);
689             CmdIndent(INDENT_INHIBIT);
690             break;
691         case (PAR_CENTERING):
692             CmdIndent(INDENT_NONE);
693             old_alignment_before_center = getAlignment();
694             setAlignment(CENTERED);
695             break;
696     }
697 }
698 
699