blob: a8b7276895a503a9e3bb2037bdc5e2eeef88836d [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
2 * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29/****************************************************************************
30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
31 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
32 * and: Thomas E. Dickey 1996-on *
33 ****************************************************************************/
34
35/*
36 * tputs.c
37 * delay_output()
38 * _nc_outch()
39 * tputs()
40 *
41 */
42
43#include <curses.priv.h>
44#include <ctype.h>
45#include <term.h> /* padding_baud_rate, xon_xoff */
46#include <termcap.h> /* ospeed */
47#include <tic.h>
48
49MODULE_ID("$Id: lib_tputs.c,v 1.66 2008/06/28 13:12:15 tom Exp $")
50
51NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */
52NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */
53
54NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */
55
56#if NCURSES_NO_PADDING
57NCURSES_EXPORT(void)
58_nc_set_no_padding(SCREEN *sp)
59{
60 bool no_padding = (getenv("NCURSES_NO_PADDING") != 0);
61
62 if (sp)
63 sp->_no_padding = no_padding;
64 else
65 _nc_prescreen._no_padding = no_padding;
66
67 TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used",
68 GetNoPadding(sp) ? " not" : ""));
69}
70#endif
71
72static int (*my_outch) (int c) = _nc_outch;
73
74NCURSES_EXPORT(int)
75delay_output(int ms)
76{
77 T((T_CALLED("delay_output(%d)"), ms));
78
79 if (no_pad_char) {
80 _nc_flush();
81 napms(ms);
82 } else {
83 register int nullcount;
84
85 nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000);
86 for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--)
87 my_outch(PC);
88 if (my_outch == _nc_outch)
89 _nc_flush();
90 }
91
92 returnCode(OK);
93}
94
95NCURSES_EXPORT(void)
96_nc_flush(void)
97{
98 (void) fflush(NC_OUTPUT);
99}
100
101NCURSES_EXPORT(int)
102_nc_outch(int ch)
103{
104 COUNT_OUTCHARS(1);
105
106 if (SP != 0
107 && SP->_cleanup) {
108 char tmp = ch;
109 /*
110 * POSIX says write() is safe in a signal handler, but the
111 * buffered I/O is not.
112 */
113 write(fileno(NC_OUTPUT), &tmp, 1);
114 } else {
115 putc(ch, NC_OUTPUT);
116 }
117 return OK;
118}
119
120NCURSES_EXPORT(int)
121putp(const char *string)
122{
123 return tputs(string, 1, _nc_outch);
124}
125
126NCURSES_EXPORT(int)
127tputs(const char *string, int affcnt, int (*outc) (int))
128{
129 bool always_delay;
130 bool normal_delay;
131 int number;
132#if BSD_TPUTS
133 int trailpad;
134#endif /* BSD_TPUTS */
135
136#ifdef TRACE
137 char addrbuf[32];
138
139 if (USE_TRACEF(TRACE_TPUTS)) {
140 if (outc == _nc_outch)
141 (void) strcpy(addrbuf, "_nc_outch");
142 else
143 (void) sprintf(addrbuf, "%p", outc);
144 if (_nc_tputs_trace) {
145 _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace,
146 _nc_visbuf(string), affcnt, addrbuf);
147 } else {
148 _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf);
149 }
150 TPUTS_TRACE(NULL);
151 _nc_unlock_global(tracef);
152 }
153#endif /* TRACE */
154
155 if (!VALID_STRING(string))
156 return ERR;
157
158 if (cur_term == 0) {
159 always_delay = FALSE;
160 normal_delay = TRUE;
161 } else {
162 always_delay = (string == bell) || (string == flash_screen);
163 normal_delay =
164 !xon_xoff
165 && padding_baud_rate
166#if NCURSES_NO_PADDING
167 && !GetNoPadding(SP)
168#endif
169 && (_nc_baudrate(ospeed) >= padding_baud_rate);
170 }
171
172#if BSD_TPUTS
173 /*
174 * This ugly kluge deals with the fact that some ancient BSD programs
175 * (like nethack) actually do the likes of tputs("50") to get delays.
176 */
177 trailpad = 0;
178 if (isdigit(UChar(*string))) {
179 while (isdigit(UChar(*string))) {
180 trailpad = trailpad * 10 + (*string - '0');
181 string++;
182 }
183 trailpad *= 10;
184 if (*string == '.') {
185 string++;
186 if (isdigit(UChar(*string))) {
187 trailpad += (*string - '0');
188 string++;
189 }
190 while (isdigit(UChar(*string)))
191 string++;
192 }
193
194 if (*string == '*') {
195 trailpad *= affcnt;
196 string++;
197 }
198 }
199#endif /* BSD_TPUTS */
200
201 my_outch = outc; /* redirect delay_output() */
202 while (*string) {
203 if (*string != '$')
204 (*outc) (*string);
205 else {
206 string++;
207 if (*string != '<') {
208 (*outc) ('$');
209 if (*string)
210 (*outc) (*string);
211 } else {
212 bool mandatory;
213
214 string++;
215 if ((!isdigit(UChar(*string)) && *string != '.')
216 || !strchr(string, '>')) {
217 (*outc) ('$');
218 (*outc) ('<');
219 continue;
220 }
221
222 number = 0;
223 while (isdigit(UChar(*string))) {
224 number = number * 10 + (*string - '0');
225 string++;
226 }
227 number *= 10;
228 if (*string == '.') {
229 string++;
230 if (isdigit(UChar(*string))) {
231 number += (*string - '0');
232 string++;
233 }
234 while (isdigit(UChar(*string)))
235 string++;
236 }
237
238 mandatory = FALSE;
239 while (*string == '*' || *string == '/') {
240 if (*string == '*') {
241 number *= affcnt;
242 string++;
243 } else { /* if (*string == '/') */
244 mandatory = TRUE;
245 string++;
246 }
247 }
248
249 if (number > 0
250 && (always_delay
251 || normal_delay
252 || mandatory))
253 delay_output(number / 10);
254
255 } /* endelse (*string == '<') */
256 } /* endelse (*string == '$') */
257
258 if (*string == '\0')
259 break;
260
261 string++;
262 }
263
264#if BSD_TPUTS
265 /*
266 * Emit any BSD-style prefix padding that we've accumulated now.
267 */
268 if (trailpad > 0
269 && (always_delay || normal_delay))
270 delay_output(trailpad / 10);
271#endif /* BSD_TPUTS */
272
273 my_outch = _nc_outch;
274 return OK;
275}