xref: /illumos-gate/usr/src/lib/libcurses/screen/tputs.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2016 by Delphix. All rights reserved.
26  */
27 
28 /*	Copyright (c) 1988 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 /* Copyright (c) 1979 Regents of the University of California */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 /*LINTLIBRARY*/
36 
37 #include	<sys/types.h>
38 #include	<ctype.h>
39 #include	"curses_inc.h"
40 
41 /*
42  * Put the character string cp out, with padding.
43  * The number of affected lines is affcnt, and the routine
44  * used to output one character is outc.
45  */
46 static	char	*ocp;
47 
48 static	char	*
49 _tpad(char *, int, int (*)(char));
50 
51 static	char	*
52 _tpad(char *cp, int affcnt, int (*outc)(char x))
53 {
54 	int	delay = 0;
55 	char	*icp = cp;
56 	int	ignorexon = 0, doaffcnt = 0;
57 
58 #ifdef	_VR2_COMPAT_CODE
59 	/*
60 	 * Why is this here?
61 	 * Because mandatory padding must be used for flash_screen
62 	 * and bell. We cannot force users to code mandatory padding
63 	 * in their terminfo entries, as that would break compatibility.
64 	 * We therefore, do it here.
65 	 *
66 	 * When compatibility is to be broken, it will go away
67 	 * and users will be informed that they MUST use mandatory
68 	 * padding for flash and bell.
69 	 */
70 	if (ocp == bell || ocp == flash_screen)
71 		ignorexon = TRUE;
72 #endif	/* _VR2_COMPAT_CODE */
73 
74 	/* Eat initial $< */
75 	cp += 2;
76 
77 	/* Convert the number representing the delay. */
78 	if (isdigit(*cp)) {
79 		do
80 			delay = delay * 10 + *cp++ - '0';
81 		while (isdigit(*cp));
82 	}
83 	delay *= 10;
84 	if (*cp == '.') {
85 		cp++;
86 		if (isdigit(*cp))
87 			delay += *cp - '0';
88 	/* Only one digit to the right of the decimal point. */
89 		while (isdigit(*cp))
90 			cp++;
91 	}
92 
93 	/*
94 	 * If the delay is followed by a `*', then
95 	 * multiply by the affected lines count.
96 	 * If the delay is followed by a '/', then
97 	 * the delay is done irregardless of xon/xoff.
98 	 */
99 	/*CONSTCOND*/
100 	while (TRUE) {
101 		if (*cp == '/')
102 			ignorexon = TRUE;
103 		else
104 			if (*cp == '*')
105 				doaffcnt = TRUE;
106 			else
107 				break;
108 		cp++;
109 	}
110 	if (doaffcnt)
111 		delay *= affcnt;
112 	if (*cp == '>')
113 		cp++;	/* Eat trailing '>' */
114 	else {
115 	/*
116 	 * We got a "$<" with no ">".  This is usually caused by
117 	 * a cursor addressing sequence that happened to generate
118 	 * $ < .  To avoid an infinite loop, we output the $ here
119 	 * and pass back the rest.
120 	 */
121 		(*outc)(*icp++);
122 		return (icp);
123 	}
124 
125 	/*
126 	 * If no delay needed, or output speed is
127 	 * not comprehensible, then don't try to delay.
128 	 */
129 	if (delay == 0)
130 		return (cp);
131 	/*
132 	 * Let handshaking take care of it - no extra cpu load from pads.
133 	 * Also, this will be more optimal since the pad info is usually
134 	 * worst case.  We only use padding info for such terminals to
135 	 * estimate the cost of a capability in choosing the cheapest one.
136 	 * Some capabilities, such as flash_screen, really want the
137 	 * padding irregardless.
138 	 */
139 	if (xon_xoff && !ignorexon)
140 		return (cp);
141 	(void) _delay(delay, outc);
142 	return (cp);
143 }
144 
145 int
146 tputs(char *cp, int affcnt, int (*outc)(char))
147 {
148 	if (cp != 0) {
149 		ocp = cp;
150 
151 		/* The guts of the string. */
152 		while (*cp)
153 			if (*cp == '$' && cp[1] == '<')
154 				cp = _tpad(cp, affcnt, outc);
155 			else
156 				(*outc)(*cp++);
157 	}
158 	return (OK);
159 }
160