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