xref: /illumos-gate/usr/src/cmd/lp/lib/lp/set_size.c (revision 55fea89d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.13	*/
27 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
28 
29 #include "string.h"
30 #include "stdlib.h"
31 
32 #include "lp.h"
33 #include "lp.set.h"
34 
35 #if	defined(__STDC__)
36 
37 char *			tparm ( char * , ... );
38 int			putp ( char * );
39 int			tidbit ( char * , char * , ... );
40 
41 #else
42 
43 extern char		*tparm();
44 int			putp();
45 int			tidbit();
46 
47 #endif
48 
49 extern short		output_res_char,
50 			output_res_line,
51 			output_res_horz_inch,
52 			output_res_vert_inch;
53 
54 /**
55  ** set_size()
56  **/
57 
58 int
59 #if	defined(__STDC__)
set_size(char * str,int which,int putout)60 set_size (
61 	char *			str,
62 	int			which,
63 	int			putout
64 )
65 #else
66 set_size (str, which, putout)
67 	char			*str;
68 	int			which,
69 				putout;
70 #endif
71 {
72 	static int		cleared_margins_already	= 0;
73 
74 	double			size;
75 
76 	int			i,
77 				isize,
78 				ret;
79 
80 	short			curval,
81 				output_res,
82 				output_res_inch;
83 
84 	char			*rest,
85 				*set_margin1,
86 				*set_margin2,
87 				*set_margin1_parm,
88 				*set_margin2_parm,
89 				*set_both_margins	= 0,
90 				*move1,
91 				*move2,
92 				*step2,
93 				*p1,
94 				*p2,
95 				*sp1,
96 				*sp2,
97 				*carriage_return,
98 				*parm_right_cursor,
99 				*column_address,
100 				*repeat_char,
101 				*cursor_right,
102 				*parm_down_cursor,
103 				*row_address,
104 				*cursor_down,
105 				*clear_margins,
106 				*finale,
107 				*slines;
108 
109 
110 	if (which == 'W') {
111 
112 		tidbit ((char *)0, "cols", &curval);
113 
114 		if (output_res_char == -1)
115 			tidbit ((char *)0, "orc", &output_res_char);
116 		output_res = output_res_char;
117 
118 		if (output_res_horz_inch == -1)
119 			tidbit ((char *)0, "orhi", &output_res_horz_inch);
120 		output_res_inch = output_res_horz_inch;
121 
122 	} else {
123 
124 		tidbit ((char *)0, "lines", &curval);
125 
126 		if (output_res_line == -1)
127 			tidbit ((char *)0, "orl", &output_res_line);
128 		output_res = output_res_line;
129 
130 		if (output_res_vert_inch == -1)
131 			tidbit ((char *)0, "orvi", &output_res_vert_inch);
132 		output_res_inch = output_res_vert_inch;
133 
134 	}
135 
136 	size = strtod(str, &rest);
137 	if (size <= 0)
138 		return (E_BAD_ARGS);
139 
140 	switch (*rest) {
141 	case ' ':
142 	case 0:
143 		break;
144 	case 'c':
145 		/*
146 		 * Convert to inches.
147 		 */
148 		size /= 2.54;
149 		/* fall through */
150 	case 'i':
151 		/*
152 		 * Convert to lines/columns.
153 		 */
154 		if (output_res == -1 || output_res_inch == -1)
155 			return (E_FAILURE);
156 		size *= output_res_inch / output_res;
157 		break;
158 	default:
159 		return (E_BAD_ARGS);
160 	}
161 
162 
163 	if ((isize = R(size)) == curval)
164 		return (E_SUCCESS);
165 
166 	/*
167 	 * We number things 0 through N (e.g. an 80 column
168 	 * page is numbered 0 to 79). Thus if we are asked
169 	 * to set a width of 132, we set the left margin at
170 	 * 0 and the right at 131.
171 	 * Of course, if we're using the "slines" string,
172 	 * we give the length as N+1.
173 	 */
174 	isize--;
175 
176 	/*
177 	 * When the width or length is set using the set-margin-at-
178 	 * current-position caps (e.g. smgl and smgr, smgt, smgb):
179 	 * If a parameterized motion capability exists, then we'll try
180 	 * to use it. However, if the instantiation of the capability
181  	 * (through tparm()) gives nothing, assume this means the motion
182 	 * is not allowed--don't try the next choice. This is the only
183 	 * way we have of checking for a width or length beyond the
184 	 * limits of the printer. If a parameterized motion capability
185 	 * doesn't exist, we have no way to check out-of-bounds width
186 	 * and length, sorry.
187 	 *
188 	 * When the width or length is set using parameterized caps
189 	 * (e.g. smglp and smgrp, or slines for length), the above is not
190 	 * a problem, of course.
191 	 */
192 	if (which == 'W') {
193 
194 		tidbit ((char *)0, "smgl", &set_margin1);
195 		tidbit ((char *)0, "smgr", &set_margin2);
196 		tidbit ((char *)0, "smglp", &set_margin1_parm);
197 		tidbit ((char *)0, "smgrp", &set_margin2_parm);
198 		tidbit ((char *)0, "smglr", &set_both_margins);
199 
200 		tidbit ((char *)0, "cr", &carriage_return);
201 		tidbit ((char *)0, "cuf", &parm_right_cursor);
202 		tidbit ((char *)0, "hpa", &column_address);
203 		tidbit ((char *)0, "rep", &repeat_char);
204 		tidbit ((char *)0, "cuf1", &cursor_right);
205 
206 		if (OKAY(carriage_return))
207 			move1 = carriage_return;
208 		else
209 			move1 = "\r";
210 
211 		if (OKAY(parm_right_cursor)) {
212 			move2 = tparm(parm_right_cursor, isize);
213 			step2 = 0;
214 
215 		} else if (OKAY(column_address)) {
216 			move2 = tparm(column_address, isize);
217 			step2 = 0;
218 
219 		} else if (OKAY(repeat_char)) {
220 			move2 = tparm(repeat_char, ' ', isize);
221 			step2 = 0;
222 
223 		} else if (OKAY(cursor_right)) {
224 			move2 = 0;
225 			step2 = cursor_right;
226 
227 		} else {
228 			move2 = 0;
229 			step2 = " ";
230 		}
231 
232 		finale = move1;		/* i.e. carriage return */
233 
234 	} else {
235 
236 		tidbit ((char *)0, "smgt", &set_margin1);
237 		tidbit ((char *)0, "smgb", &set_margin2);
238 		tidbit ((char *)0, "smgtp", &set_margin1_parm);
239 		tidbit ((char *)0, "smgbp", &set_margin2_parm);
240 		tidbit ((char *)0, "smgtb", &set_both_margins);
241 
242 		/*
243 		 * For compatibility with SVR3.2 era Terminfo files,
244 		 * we check "u9" as an alias for "slines" IF a check
245 		 * of "slines" comes up empty.
246 		 */
247 		slines = 0; /* (in case compiled with old tidbit) */
248 		tidbit ((char *)0, "slines", &slines);
249 		if (!OKAY(slines))
250 			tidbit ((char *)0, "u9", &slines);
251 
252 		tidbit ((char *)0, "cud", &parm_down_cursor);
253 		tidbit ((char *)0, "vpa", &row_address);
254 		tidbit ((char *)0, "cud1", &cursor_down);
255 
256 		move1 = "";	/* Assume we're already at top-of-page */
257 
258 		if (OKAY(parm_down_cursor)) {
259 			move2 = tparm(parm_down_cursor, isize);
260 			step2 = 0;
261 
262 		} else if (OKAY(row_address)) {
263 			move2 = tparm(row_address, isize);
264 			step2 = 0;
265 
266 		} else if (OKAY(cursor_down)) {
267 			move2 = 0;
268 			step2 = cursor_down;
269 
270 		} else {
271 			move2 = 0;
272 			step2 = "\n";
273 		}
274 
275 		/*
276 		 * This has to be smarter, but we don't have the
277 		 * smarts ourselves, yet; i.e. what do we do if
278 		 * there is no "ff"?
279 		 */
280 		tidbit ((char *)0, "ff", &finale);
281 
282 	}
283 
284 	/*
285 	 * For a short while we needed a kludge in Terminfo
286 	 * whereby if only one of the left/right or top/bottom
287 	 * parameterized margin setters was defined, it was
288 	 * a parm-string that could set BOTH margins. We now have
289 	 * separate strings for setting both margins, but we still
290 	 * allow the kludge.
291 	 */
292 	if (!OKAY(set_both_margins)) {
293 		if (OKAY(set_margin1_parm) && !OKAY(set_margin2_parm))
294 			set_both_margins = set_margin1_parm;
295 		else if (OKAY(set_margin2_parm) && !OKAY(set_margin1_parm))
296 			set_both_margins = set_margin2_parm;
297 	}
298 
299 	sp1 = sp2 = 0;
300 
301 	if (
302 		which == 'L'
303 	     && OKAY(slines)
304 	     && (p1 = tparm(slines, isize + 1))
305 	) {
306 		if (putout)
307 			putp (p1);
308 		finale = 0;
309 		ret = E_SUCCESS;
310 
311 	} else if (
312 		OKAY(set_both_margins)
313 	     && (p1 = tparm(set_both_margins, 0, isize))
314 	     && *p1
315 	     && (sp1 = Strdup(p1))
316 	) {
317 
318 		if (putout) {
319 
320 			if (!cleared_margins_already) {
321 				tidbit ((char *)0, "mgc", &clear_margins);
322 				if (OKAY(clear_margins)) {
323 					cleared_margins_already = 1;
324 					putp (clear_margins);
325 				}
326 			}
327 
328 			putp (sp1);
329 
330 		}
331 		ret = E_SUCCESS;
332 
333 	/*
334 	 * The "smgbp" string takes two parameters; each defines the
335 	 * position of the margin, the first counting lines from the top
336 	 * of the page, the second counting lines from the bottom of the
337 	 * page. This shows the flaw in using the set-margin commands
338 	 * for setting the page length, because BY DEFINITION the second
339 	 * parameter must be 0 for us. But giving 0 won't cause a change
340 	 * in the page length, will it!
341 	 *
342 	 * Anyway, the "smgrp" expects just one parameter (thus will
343 	 * ignore a second parameter) so we can safely give the second
344 	 * parameter without caring which of width or length we're
345 	 * setting.
346 	 */
347 	} else if (
348 		OKAY(set_margin1_parm)
349 	     && (p1 = tparm(set_margin1_parm, 0))
350 	     && *p1
351 	     && (sp1 = Strdup(p1))
352 	     && OKAY(set_margin2_parm)
353 	     && (p2 = tparm(set_margin2_parm, isize, 0))
354 	     && *p2
355 	     && (sp2 = Strdup(p2))
356 	) {
357 
358 		if (putout) {
359 
360 			if (!cleared_margins_already) {
361 				tidbit ((char *)0, "mgc", &clear_margins);
362 				if (OKAY(clear_margins)) {
363 					cleared_margins_already = 1;
364 					putp (clear_margins);
365 				}
366 			}
367 
368 			putp (sp1);
369 			putp (sp2);
370 
371 		}
372 		ret = E_SUCCESS;
373 
374 	} else if (
375 		OKAY(set_margin1)
376 	     && OKAY(set_margin2)
377 	     && (OKAY(move2) || OKAY(step2))
378 	) {
379 
380 		register char		*p,
381 					*q;
382 
383 		register int		free_it = 0;
384 
385 		if (putout) {
386 
387 			if (!cleared_margins_already) {
388 				tidbit ((char *)0, "mgc", &clear_margins);
389 				if (OKAY(clear_margins)) {
390 					cleared_margins_already = 1;
391 					putp (clear_margins);
392 				}
393 			}
394 
395 			putp (move1);
396 			putp (set_margin1);
397 
398 			if (!move2) {
399 				move2 = Malloc(isize * strlen(step2) + 1);
400 				if (!move2)
401 					return (E_MALLOC);
402 				for (p = move2, i = 0; i < isize; i++)
403 					for (q = step2; *q; )
404 						*p++ = *q++;
405 				*p = 0;
406 				free_it = 1;
407 			}
408 
409 			putp (move2);
410 			putp (set_margin2);
411 
412 			if (free_it)
413 				Free (move2);
414 		}
415 		ret = E_SUCCESS;
416 
417 	} else
418 		ret = E_FAILURE;
419 
420 	if (putout && OKAY(finale))
421 		putp (finale);
422 
423 	if (sp1)
424 		Free (sp1);
425 	if (sp2)
426 		Free (sp2);
427 	return (ret);
428 }
429