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	*
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
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