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