/*@z11.c:Style Service:EchoStyle()@*******************************************/ /* */ /* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.35) */ /* COPYRIGHT (C) 1991, 2007 Jeffrey H. Kingston */ /* */ /* Jeffrey H. Kingston (jeff@it.usyd.edu.au) */ /* School of Information Technologies */ /* The University of Sydney 2006 */ /* AUSTRALIA */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either Version 2, or (at your option) */ /* any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */ /* */ /* FILE: z11.c */ /* MODULE: Style Service */ /* EXTERNS: EchoStyle(), SpaceChange(), BreakChange() */ /* */ /*****************************************************************************/ #include "externs.h" #if DEBUG_ON /*****************************************************************************/ /* */ /* FULL_CHAR *EchoStyle(style) */ /* */ /* Returns a string showing the value of the style. */ /* */ /*****************************************************************************/ FULL_CHAR *EchoStyle(STYLE *style) { static FULL_CHAR res[100]; static char buff[100]; static char *hyphwords[] = { "hyph_undef", "hyph_off", "hyph_on" }; static char *fillwords[] = { "fill_undef", "fill_off", "fill_on" }; static char *spacewords[] = { "lout", "comp", "troff", "tex" }; static char *displaywords[] = { "undef", "adjust", "outdent", "oragged", "left", "centre", "right", "do" }; StringCopy(res, AsciiToFull("[")); StringCat(res, EchoCatOp(VCAT,mark(line_gap(*style)),join(line_gap(*style)))); StringCat(res, EchoGap(&line_gap(*style))); StringCat(res, AsciiToFull(", ")); if( font(*style) == 0 ) StringCat(res, AsciiToFull("nofont")); else { StringCat(res, FontFamilyAndFace(font(*style))); StringCat(res, AsciiToFull(" ")); StringCat(res, EchoLength(FontSize(font(*style), nilobj))); } StringCat(res, AsciiToFull(" (")); StringCat(res, AsciiToFull(spacewords[space_style(*style)])); StringCat(res, AsciiToFull(" ")); StringCat(res, EchoGap(&space_gap(*style))); StringCat(res, AsciiToFull("), ")); StringCat(res, AsciiToFull(hyph_style(*style) < 3 ? hyphwords[hyph_style(*style)] : "?")); StringCat(res, AsciiToFull(":")); StringCat(res, AsciiToFull(fill_style(*style) < 3 ? fillwords[fill_style(*style)] : "?")); StringCat(res, AsciiToFull(":")); StringCat(res, AsciiToFull(display_style(*style) < 7 ? displaywords[display_style(*style)] : "?")); if( small_caps(*style) > 0 ) StringCat(res, AsciiToFull(":smallcaps")); if( vadjust(*style) ) StringCat(res, AsciiToFull(":vadjust")); if( hadjust(*style) ) StringCat(res, AsciiToFull(":hadjust")); if( padjust(*style) ) StringCat(res, AsciiToFull(":padjust")); if( yunit(*style) != 0 ) { StringCat(res, AsciiToFull(":y=")); StringCat(res, EchoLength(yunit(*style))); } if( zunit(*style) != 0 ) { StringCat(res, AsciiToFull(":z=")); StringCat(res, EchoLength(zunit(*style))); } if( nobreakfirst(*style) ) StringCat(res, AsciiToFull(":NBF")); if( nobreaklast(*style) ) StringCat(res, AsciiToFull(":NBL")); if( marginkerning(*style) ) StringCat(res, AsciiToFull(":MK")); sprintf(buff, ":C%d:P%d", colour(*style), texture(*style)); StringCat(res, AsciiToFull(buff)); StringCat(res, AsciiToFull("]")); return res; } /* end EchoStyle */ #endif /*@::SpaceChange()@***********************************************************/ /* */ /* SpaceChange(style, x) */ /* */ /* Change the current space style as indicated by object x. */ /* */ /*****************************************************************************/ static void changespace(STYLE *style, OBJECT x) { GAP res_gap; unsigned gap_inc; assert( is_word(type(x)), "changespace: type(x)!" ); if( beginsbreakstyle(string(x)[0]) ) { /* should be a new space style option */ if( StringEqual(string(x), STR_SPACE_LOUT) ) space_style(*style) = SPACE_LOUT; else if( StringEqual(string(x), STR_SPACE_COMPRESS) ) space_style(*style) = SPACE_COMPRESS; else if( StringEqual(string(x), STR_SPACE_SEPARATE) ) space_style(*style) = SPACE_SEPARATE; else if( StringEqual(string(x), STR_SPACE_TROFF) ) space_style(*style) = SPACE_TROFF; else if( StringEqual(string(x), STR_SPACE_TEX) ) space_style(*style) = SPACE_TEX; else Error(11, 1, "unknown option to %s symbol (%s)", WARN, &fpos(x), KW_SPACE, string(x)); } else /* should be a new space gap */ { GetGap(x, style, &res_gap, &gap_inc); if( gap_inc != GAP_ABS && units(res_gap) != units(space_gap(*style)) ) { Error(11, 2, "spacing %s is not compatible with current spacing", WARN, &fpos(x), string(x)); } else { units(space_gap(*style)) = units(res_gap); mode(space_gap(*style)) = mode(res_gap); width(space_gap(*style)) = gap_inc == GAP_ABS ? width(res_gap) : gap_inc == GAP_INC ? width(space_gap(*style)) + width(res_gap) : find_max(width(space_gap(*style)) - width(res_gap), 0); } } debug1(DSS, D, "SpaceChange returning %s", EchoStyle(style)); } /* end SpaceChange */ void SpaceChange(STYLE *style, OBJECT x) { OBJECT link, y; debug2(DSS, D, "SpaceChange(%s, %s)", EchoStyle(style), EchoObject(x)); switch( type(x) ) { case NULL_CLOS: break; case WORD: case QWORD: if( !StringEqual(string(x), STR_EMPTY) ) changespace(style, x); break; case ACAT: for( link = Down(x); link != x; link = NextDown(link) ) { Child(y, link); if( type(y) == GAP_OBJ || type(y) == NULL_CLOS ) continue; else if( is_word(type(y)) ) { if( !StringEqual(string(y), STR_EMPTY) ) changespace(style, y); } else Error(11, 3, "invalid left parameter of %s", WARN, &fpos(x), KW_SPACE); } break; default: Error(11, 4, "invalid left parameter of %s", WARN, &fpos(x), KW_SPACE); break; } debug1(DSS, D, "SpaceChange returning %s", EchoStyle(style)); } /* end SpaceChange */ /*@::BreakChange()@***********************************************************/ /* */ /* BreakChange(style, x) */ /* */ /* Change the current break style as indicated by object x. */ /* */ /*****************************************************************************/ static void changebreak(STYLE *style, OBJECT x) { GAP res_gap; unsigned gap_inc; debug0(DSS, D, "[ changebreak"); if( beginsbreakstyle(string(x)[0]) ) { /* should be a new break style option */ if( StringEqual(string(x), STR_BREAK_HYPHEN) ) hyph_style(*style) = HYPH_ON; else if( StringEqual(string(x), STR_BREAK_NOHYPHEN) ) hyph_style(*style) = HYPH_OFF; else if( StringEqual(string(x), STR_BREAK_ADJUST) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_ADJUST; else if( StringEqual(string(x), STR_BREAK_OUTDENT) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_OUTDENT; else if( StringEqual(string(x), STR_BREAK_RAGGED) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_LEFT; else if( StringEqual(string(x), STR_BREAK_CRAGGED) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_CENTRE; else if( StringEqual(string(x), STR_BREAK_RRAGGED) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_RIGHT; else if( StringEqual(string(x), STR_BREAK_ORAGGED) ) fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_ORAGGED; else if( StringEqual(string(x), STR_BREAK_LINES) ) fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_LEFT; else if( StringEqual(string(x), STR_BREAK_CLINES) ) fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_CENTRE; else if( StringEqual(string(x), STR_BREAK_RLINES) ) fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_RIGHT; else if( StringEqual(string(x), STR_BREAK_OLINES) ) fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_ORAGGED; else if( StringEqual(string(x), STR_BREAK_NOFIRST) ) nobreakfirst(*style) = TRUE; else if( StringEqual(string(x), STR_BREAK_FIRST) ) nobreakfirst(*style) = FALSE; else if( StringEqual(string(x), STR_BREAK_NOLAST) ) nobreaklast(*style) = TRUE; else if( StringEqual(string(x), STR_BREAK_LAST) ) nobreaklast(*style) = FALSE; else if( StringEqual(string(x), STR_BREAK_MARGINKERNING) ) marginkerning(*style) = TRUE; else if( StringEqual(string(x), STR_BREAK_NOMARGINKERNING) ) marginkerning(*style) = FALSE; else Error(11, 5, "found unknown option to %s symbol (%s)", WARN, &fpos(x), KW_BREAK, string(x)); } else /* should be a new inter-line gap */ { GetGap(x, style, &res_gap, &gap_inc); if( gap_inc != GAP_ABS && units(res_gap) != units(line_gap(*style)) ) Error(11, 6, "line spacing %s is not compatible with current spacing", WARN, &fpos(x), string(x)); else { units(line_gap(*style)) = units(res_gap); mode(line_gap(*style)) = mode(res_gap); width(line_gap(*style)) = gap_inc == GAP_ABS ? width(res_gap) : gap_inc == GAP_INC ? width(line_gap(*style)) + width(res_gap) : find_max(width(line_gap(*style)) - width(res_gap), 0); } } debug0(DSS, D, "] changebreak"); } /* end changebreak */ void BreakChange(STYLE *style, OBJECT x) { OBJECT link, y; GAP res_gap; unsigned gap_inc; debug3(DSS, D, "BreakChange(%s, %s at %s)", EchoStyle(style), EchoObject(x), EchoFilePos(&fpos(x))); switch( type(x) ) { case NULL_CLOS: break; case WORD: case QWORD: if( !StringEqual(string(x), STR_EMPTY) ) { debug1(DSS, D, "BreakChange WORD examining %s", (string(x))); if( StringEqual(string(x), STR_BREAK_SETOUTDENT) ) { debug1(DSS, D, " found %s", STR_BREAK_SETOUTDENT); Error(11, 11, "width missing after %s in %s", WARN, &fpos(x), STR_BREAK_SETOUTDENT, KW_BREAK); } else { debug1(DSS, D, " not found %s", STR_BREAK_SETOUTDENT); changebreak(style, x); } } break; case ACAT: for( link = Down(x); link != x; link = NextDown(link) ) { Child(y, link); if( type(y) == GAP_OBJ || type(y) == NULL_CLOS ) continue; else if( is_word(type(y)) ) { if( !StringEqual(string(y), STR_EMPTY) ) { debug1(DSS, D, "BreakChange examining %s", (string(y))); if( StringEqual(string(y), STR_BREAK_SETOUTDENT) ) { debug1(DSS, D, " found %s", STR_BREAK_SETOUTDENT); if( NextDown(link)==x || NextDown(NextDown(link))==x ) { Error(11, 11, "width missing after %s in %s", WARN, &fpos(x), STR_BREAK_SETOUTDENT, KW_BREAK); } else { link = NextDown(NextDown(link)); Child(y, link); GetGap(y, style, &res_gap, &gap_inc); outdent_len(*style) = gap_inc == GAP_ABS ? width(res_gap) : gap_inc == GAP_INC ? outdent_len(*style) + width(res_gap) : find_max(outdent_len(*style) - width(res_gap), 0); } } else if( StringEqual(string(y), STR_BREAK_SCALE) ) { debug1(DSS, D, " found %s", STR_BREAK_SCALE); if( NextDown(link)==x || NextDown(NextDown(link))==x ) { Error(11, 12, "scale factor missing after %s in %s", WARN, &fpos(x), STR_BREAK_SCALE, KW_BREAK); } else { float val; link = NextDown(NextDown(link)); Child(y, link); val = GetScaleFactor(y); blanklinescale(*style) = (int) (val * SF); } } else { debug1(DSS, D, " not found %s", STR_BREAK_SETOUTDENT); changebreak(style, y); } } } else Error(11, 7, "invalid left parameter of %s", WARN, &fpos(x), KW_BREAK); } break; default: Error(11, 8, "invalid left parameter of %s", WARN, &fpos(x), KW_BREAK); break; } debug1(DSS, D, "BreakChange returning %s", EchoStyle(style)); } /* end BreakChange */ /*@::YUnitChange(), ZUnitChange()@********************************************/ /* */ /* YUnitChange(style, x) */ /* */ /* Change the current value of the y unit as indicated by object x. */ /* */ /*****************************************************************************/ void YUnitChange(STYLE *style, OBJECT x) { GAP res_gap; unsigned gap_inc; GetGap(x, style, &res_gap, &gap_inc); if( units(res_gap) != FIXED_UNIT ) Error(11, 9, "this unit not allowed with %s symbol", WARN, &fpos(x), KW_YUNIT); else { if( gap_inc == GAP_ABS ) yunit(*style) = width(res_gap); else if( gap_inc == GAP_INC ) yunit(*style) += width(res_gap); else yunit(*style) = find_max(yunit(*style) - width(res_gap), 0); } } /* end YUnitChange */ /*****************************************************************************/ /* */ /* ZUnitChange(style, x) */ /* */ /* Change the current value of the z unit as indicated by object x. */ /* */ /*****************************************************************************/ void ZUnitChange(STYLE *style, OBJECT x) { GAP res_gap; unsigned gap_inc; GetGap(x, style, &res_gap, &gap_inc); if( units(res_gap) != FIXED_UNIT ) Error(11, 10, "this unit not allowed with %s symbol", WARN, &fpos(x), KW_ZUNIT); else { if( gap_inc == GAP_ABS ) zunit(*style) = width(res_gap); else if( gap_inc == GAP_INC ) zunit(*style) += width(res_gap); else zunit(*style) = find_max(zunit(*style) - width(res_gap), 0); } } /* end ZUnitChange */