1 /*@z11.c:Style Service:EchoStyle()@*******************************************/
2 /* */
3 /* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39) */
4 /* COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston */
5 /* */
6 /* Jeffrey H. Kingston (jeff@it.usyd.edu.au) */
7 /* School of Information Technologies */
8 /* The University of Sydney 2006 */
9 /* AUSTRALIA */
10 /* */
11 /* This program is free software; you can redistribute it and/or modify */
12 /* it under the terms of the GNU General Public License as published by */
13 /* the Free Software Foundation; either Version 3, or (at your option) */
14 /* any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */
24 /* */
25 /* FILE: z11.c */
26 /* MODULE: Style Service */
27 /* EXTERNS: EchoStyle(), SpaceChange(), BreakChange() */
28 /* */
29 /*****************************************************************************/
30 #include "externs.h"
31
32
33 #if DEBUG_ON
34 /*****************************************************************************/
35 /* */
36 /* FULL_CHAR *EchoStyle(style) */
37 /* */
38 /* Returns a string showing the value of the style. */
39 /* */
40 /*****************************************************************************/
41
EchoStyle(STYLE * style)42 FULL_CHAR *EchoStyle(STYLE *style)
43 { static FULL_CHAR res[100];
44 static char buff[100];
45 static char *hyphwords[] = { "hyph_undef", "hyph_off", "hyph_on" };
46 static char *fillwords[] = { "fill_undef", "fill_off", "fill_on" };
47 static char *spacewords[] = { "lout", "comp", "troff", "tex" };
48 static char *displaywords[] = { "undef", "adjust", "outdent", "oragged",
49 "left", "centre", "right", "do" };
50
51 StringCopy(res, AsciiToFull("["));
52 StringCat(res, EchoCatOp(VCAT,mark(line_gap(*style)),join(line_gap(*style))));
53 StringCat(res, EchoGap(&line_gap(*style)));
54 StringCat(res, AsciiToFull(", "));
55 if( font(*style) == 0 )
56 StringCat(res, AsciiToFull("nofont"));
57 else
58 {
59 StringCat(res, FontFamilyAndFace(font(*style)));
60 StringCat(res, AsciiToFull(" "));
61 StringCat(res, EchoLength(FontSize(font(*style), nilobj)));
62 }
63 StringCat(res, AsciiToFull(" ("));
64 StringCat(res, AsciiToFull(spacewords[space_style(*style)]));
65 StringCat(res, AsciiToFull(" "));
66 StringCat(res, EchoGap(&space_gap(*style)));
67 StringCat(res, AsciiToFull("), "));
68 StringCat(res, AsciiToFull(hyph_style(*style) < 3 ?
69 hyphwords[hyph_style(*style)] : "?"));
70 StringCat(res, AsciiToFull(":"));
71 StringCat(res, AsciiToFull(fill_style(*style) < 3 ?
72 fillwords[fill_style(*style)] : "?"));
73 StringCat(res, AsciiToFull(":"));
74 StringCat(res, AsciiToFull(display_style(*style) < 7 ?
75 displaywords[display_style(*style)] : "?"));
76 if( small_caps(*style) > 0 ) StringCat(res, AsciiToFull(":smallcaps"));
77 if( vadjust(*style) ) StringCat(res, AsciiToFull(":vadjust"));
78 if( hadjust(*style) ) StringCat(res, AsciiToFull(":hadjust"));
79 if( padjust(*style) ) StringCat(res, AsciiToFull(":padjust"));
80 if( yunit(*style) != 0 )
81 { StringCat(res, AsciiToFull(":y="));
82 StringCat(res, EchoLength(yunit(*style)));
83 }
84 if( zunit(*style) != 0 )
85 { StringCat(res, AsciiToFull(":z="));
86 StringCat(res, EchoLength(zunit(*style)));
87 }
88 if( nobreakfirst(*style) ) StringCat(res, AsciiToFull(":NBF"));
89 if( nobreaklast(*style) ) StringCat(res, AsciiToFull(":NBL"));
90 if( marginkerning(*style) ) StringCat(res, AsciiToFull(":MK"));
91 sprintf(buff, ":C%d:P%d", colour(*style), texture(*style));
92 StringCat(res, AsciiToFull(buff));
93 StringCat(res, AsciiToFull("]"));
94 return res;
95 } /* end EchoStyle */
96 #endif
97
98
99 /*@::SpaceChange()@***********************************************************/
100 /* */
101 /* SpaceChange(style, x) */
102 /* */
103 /* Change the current space style as indicated by object x. */
104 /* */
105 /*****************************************************************************/
106
changespace(STYLE * style,OBJECT x)107 static void changespace(STYLE *style, OBJECT x)
108 { GAP res_gap; unsigned gap_inc;
109 assert( is_word(type(x)), "changespace: type(x)!" );
110 if( beginsbreakstyle(string(x)[0]) )
111 {
112 /* should be a new space style option */
113 if( StringEqual(string(x), STR_SPACE_LOUT) )
114 space_style(*style) = SPACE_LOUT;
115 else if( StringEqual(string(x), STR_SPACE_COMPRESS) )
116 space_style(*style) = SPACE_COMPRESS;
117 else if( StringEqual(string(x), STR_SPACE_SEPARATE) )
118 space_style(*style) = SPACE_SEPARATE;
119 else if( StringEqual(string(x), STR_SPACE_TROFF) )
120 space_style(*style) = SPACE_TROFF;
121 else if( StringEqual(string(x), STR_SPACE_TEX) )
122 space_style(*style) = SPACE_TEX;
123 else Error(11, 1, "unknown option to %s symbol (%s)",
124 WARN, &fpos(x), KW_SPACE, string(x));
125 }
126 else /* should be a new space gap */
127 { GetGap(x, style, &res_gap, &gap_inc);
128 if( gap_inc != GAP_ABS && units(res_gap) != units(space_gap(*style)) )
129 { Error(11, 2, "spacing %s is not compatible with current spacing",
130 WARN, &fpos(x), string(x));
131 }
132 else
133 { units(space_gap(*style)) = units(res_gap);
134 mode(space_gap(*style)) = mode(res_gap);
135 width(space_gap(*style)) = gap_inc == GAP_ABS ? width(res_gap) :
136 gap_inc == GAP_INC ? width(space_gap(*style)) + width(res_gap) :
137 find_max(width(space_gap(*style)) - width(res_gap), 0);
138 }
139 }
140 debug1(DSS, D, "SpaceChange returning %s", EchoStyle(style));
141 } /* end SpaceChange */
142
143
SpaceChange(STYLE * style,OBJECT x)144 void SpaceChange(STYLE *style, OBJECT x)
145 { OBJECT link, y;
146 debug2(DSS, D, "SpaceChange(%s, %s)", EchoStyle(style), EchoObject(x));
147 switch( type(x) )
148 {
149 case NULL_CLOS: break;
150
151 case WORD:
152 case QWORD: if( !StringEqual(string(x), STR_EMPTY) )
153 changespace(style, x);
154 break;
155
156
157 case ACAT: for( link = Down(x); link != x; link = NextDown(link) )
158 { Child(y, link);
159 if( type(y) == GAP_OBJ || type(y) == NULL_CLOS ) continue;
160 else if( is_word(type(y)) )
161 { if( !StringEqual(string(y), STR_EMPTY) )
162 changespace(style, y);
163 }
164 else Error(11, 3, "invalid left parameter of %s",
165 WARN, &fpos(x), KW_SPACE);
166 }
167 break;
168
169
170 default: Error(11, 4, "invalid left parameter of %s",
171 WARN, &fpos(x), KW_SPACE);
172 break;
173 }
174 debug1(DSS, D, "SpaceChange returning %s", EchoStyle(style));
175 } /* end SpaceChange */
176
177
178 /*@::BreakChange()@***********************************************************/
179 /* */
180 /* BreakChange(style, x) */
181 /* */
182 /* Change the current break style as indicated by object x. */
183 /* */
184 /*****************************************************************************/
185
changebreak(STYLE * style,OBJECT x)186 static void changebreak(STYLE *style, OBJECT x)
187 { GAP res_gap; unsigned gap_inc;
188 debug0(DSS, D, "[ changebreak");
189 if( beginsbreakstyle(string(x)[0]) )
190 {
191 /* should be a new break style option */
192 if( StringEqual(string(x), STR_BREAK_HYPHEN) )
193 hyph_style(*style) = HYPH_ON;
194 else if( StringEqual(string(x), STR_BREAK_NOHYPHEN) )
195 hyph_style(*style) = HYPH_OFF;
196 else if( StringEqual(string(x), STR_BREAK_ADJUST) )
197 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_ADJUST;
198 else if( StringEqual(string(x), STR_BREAK_OUTDENT) )
199 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_OUTDENT;
200 else if( StringEqual(string(x), STR_BREAK_RAGGED) )
201 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_LEFT;
202 else if( StringEqual(string(x), STR_BREAK_CRAGGED) )
203 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_CENTRE;
204 else if( StringEqual(string(x), STR_BREAK_RRAGGED) )
205 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_RIGHT;
206 else if( StringEqual(string(x), STR_BREAK_ORAGGED) )
207 fill_style(*style) = FILL_ON, display_style(*style) = DISPLAY_ORAGGED;
208 else if( StringEqual(string(x), STR_BREAK_LINES) )
209 fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_LEFT;
210 else if( StringEqual(string(x), STR_BREAK_CLINES) )
211 fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_CENTRE;
212 else if( StringEqual(string(x), STR_BREAK_RLINES) )
213 fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_RIGHT;
214 else if( StringEqual(string(x), STR_BREAK_OLINES) )
215 fill_style(*style) = FILL_OFF, display_style(*style) = DISPLAY_ORAGGED;
216 else if( StringEqual(string(x), STR_BREAK_NOFIRST) )
217 nobreakfirst(*style) = TRUE;
218 else if( StringEqual(string(x), STR_BREAK_FIRST) )
219 nobreakfirst(*style) = FALSE;
220 else if( StringEqual(string(x), STR_BREAK_NOLAST) )
221 nobreaklast(*style) = TRUE;
222 else if( StringEqual(string(x), STR_BREAK_LAST) )
223 nobreaklast(*style) = FALSE;
224 else if( StringEqual(string(x), STR_BREAK_MARGINKERNING) )
225 marginkerning(*style) = TRUE;
226 else if( StringEqual(string(x), STR_BREAK_NOMARGINKERNING) )
227 marginkerning(*style) = FALSE;
228 else Error(11, 5, "found unknown option to %s symbol (%s)",
229 WARN, &fpos(x), KW_BREAK, string(x));
230 }
231 else /* should be a new inter-line gap */
232 { GetGap(x, style, &res_gap, &gap_inc);
233 if( gap_inc != GAP_ABS && units(res_gap) != units(line_gap(*style)) )
234 Error(11, 6, "line spacing %s is not compatible with current spacing",
235 WARN, &fpos(x), string(x));
236 else
237 { units(line_gap(*style)) = units(res_gap);
238 mode(line_gap(*style)) = mode(res_gap);
239 width(line_gap(*style)) = gap_inc == GAP_ABS ? width(res_gap) :
240 gap_inc == GAP_INC ? width(line_gap(*style)) + width(res_gap) :
241 find_max(width(line_gap(*style)) - width(res_gap), 0);
242 }
243 }
244 debug0(DSS, D, "] changebreak");
245 } /* end changebreak */
246
BreakChange(STYLE * style,OBJECT x)247 void BreakChange(STYLE *style, OBJECT x)
248 { OBJECT link, y;
249 GAP res_gap; unsigned gap_inc;
250 debug3(DSS, D, "BreakChange(%s, %s at %s)", EchoStyle(style),
251 EchoObject(x), EchoFilePos(&fpos(x)));
252 switch( type(x) )
253 {
254 case NULL_CLOS: break;
255
256 case WORD:
257 case QWORD: if( !StringEqual(string(x), STR_EMPTY) )
258 {
259 debug1(DSS, D, "BreakChange WORD examining %s", (string(x)));
260 if( StringEqual(string(x), STR_BREAK_SETOUTDENT) )
261 {
262 debug1(DSS, D, " found %s", STR_BREAK_SETOUTDENT);
263 Error(11, 11, "width missing after %s in %s",
264 WARN, &fpos(x), STR_BREAK_SETOUTDENT, KW_BREAK);
265 }
266 else
267 {
268 debug1(DSS, D, " not found %s", STR_BREAK_SETOUTDENT);
269 changebreak(style, x);
270 }
271 }
272 break;
273
274
275 case ACAT: for( link = Down(x); link != x; link = NextDown(link) )
276 { Child(y, link);
277 if( type(y) == GAP_OBJ || type(y) == NULL_CLOS ) continue;
278 else if( is_word(type(y)) )
279 { if( !StringEqual(string(y), STR_EMPTY) )
280 {
281 debug1(DSS, D, "BreakChange examining %s", (string(y)));
282 if( StringEqual(string(y), STR_BREAK_SETOUTDENT) )
283 {
284 debug1(DSS, D, " found %s", STR_BREAK_SETOUTDENT);
285 if( NextDown(link)==x || NextDown(NextDown(link))==x )
286 {
287 Error(11, 11, "width missing after %s in %s",
288 WARN, &fpos(x), STR_BREAK_SETOUTDENT, KW_BREAK);
289 }
290 else
291 {
292 link = NextDown(NextDown(link));
293 Child(y, link);
294 GetGap(y, style, &res_gap, &gap_inc);
295 outdent_len(*style) = gap_inc == GAP_ABS ?
296 width(res_gap) : gap_inc == GAP_INC ?
297 outdent_len(*style) + width(res_gap) :
298 find_max(outdent_len(*style) - width(res_gap), 0);
299 }
300 }
301 else if( StringEqual(string(y), STR_BREAK_SCALE) )
302 {
303 debug1(DSS, D, " found %s", STR_BREAK_SCALE);
304 if( NextDown(link)==x || NextDown(NextDown(link))==x )
305 {
306 Error(11, 12, "scale factor missing after %s in %s",
307 WARN, &fpos(x), STR_BREAK_SCALE, KW_BREAK);
308 }
309 else
310 {
311 float val;
312 link = NextDown(NextDown(link));
313 Child(y, link);
314 val = GetScaleFactor(y);
315 blanklinescale(*style) = (int) (val * SF);
316 }
317 }
318 else
319 {
320 debug1(DSS, D, " not found %s", STR_BREAK_SETOUTDENT);
321 changebreak(style, y);
322 }
323 }
324 }
325 else Error(11, 7, "invalid left parameter of %s",
326 WARN, &fpos(x), KW_BREAK);
327 }
328 break;
329
330
331 default: Error(11, 8, "invalid left parameter of %s",
332 WARN, &fpos(x), KW_BREAK);
333 break;
334 }
335 debug1(DSS, D, "BreakChange returning %s", EchoStyle(style));
336 } /* end BreakChange */
337
338
339 /*@::YUnitChange(), ZUnitChange()@********************************************/
340 /* */
341 /* YUnitChange(style, x) */
342 /* */
343 /* Change the current value of the y unit as indicated by object x. */
344 /* */
345 /*****************************************************************************/
346
YUnitChange(STYLE * style,OBJECT x)347 void YUnitChange(STYLE *style, OBJECT x)
348 { GAP res_gap; unsigned gap_inc;
349 GetGap(x, style, &res_gap, &gap_inc);
350 if( units(res_gap) != FIXED_UNIT )
351 Error(11, 9, "this unit not allowed with %s symbol",
352 WARN, &fpos(x), KW_YUNIT);
353 else
354 { if( gap_inc == GAP_ABS ) yunit(*style) = width(res_gap);
355 else if( gap_inc == GAP_INC ) yunit(*style) += width(res_gap);
356 else yunit(*style) = find_max(yunit(*style) - width(res_gap), 0);
357 }
358 } /* end YUnitChange */
359
360
361 /*****************************************************************************/
362 /* */
363 /* ZUnitChange(style, x) */
364 /* */
365 /* Change the current value of the z unit as indicated by object x. */
366 /* */
367 /*****************************************************************************/
368
ZUnitChange(STYLE * style,OBJECT x)369 void ZUnitChange(STYLE *style, OBJECT x)
370 { GAP res_gap; unsigned gap_inc;
371 GetGap(x, style, &res_gap, &gap_inc);
372 if( units(res_gap) != FIXED_UNIT )
373 Error(11, 10, "this unit not allowed with %s symbol",
374 WARN, &fpos(x), KW_ZUNIT);
375 else
376 { if( gap_inc == GAP_ABS ) zunit(*style) = width(res_gap);
377 else if( gap_inc == GAP_INC ) zunit(*style) += width(res_gap);
378 else zunit(*style) = find_max(zunit(*style) - width(res_gap), 0);
379 }
380 } /* end ZUnitChange */
381