ncurses 4.1
[ncurses.git] / ncurses / lib_tputs.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22
23 /*
24  *      tputs.c
25  *              delay_output()
26  *              _nc_outch()
27  *              tputs()
28  *
29  */
30
31 #include <curses.priv.h>
32 #include <ctype.h>
33 #include <term.h>       /* padding_baud_rate, xon_xoff */
34 #include <tic.h>
35
36 MODULE_ID("$Id: lib_tputs.c,v 1.18 1997/02/02 01:52:39 tom Exp $")
37
38 int delay_output(int ms)
39 {
40         T((T_CALLED("delay_output(%d)"), ms));
41
42         if (SP == 0 || SP->_baudrate <= 0)
43                 returnCode(ERR);
44 #ifdef no_pad_char
45         else if (no_pad_char)
46                 napms(ms);
47 #endif /* no_pad_char */
48         else {
49                 register int    nullcount;
50                 char    null = '\0';
51
52 #ifdef pad_char
53                 if (pad_char)
54                         null = pad_char[0];
55 #endif /* pad_char */
56
57                 for (nullcount = ms * 1000 / SP->_baudrate; nullcount > 0; nullcount--)
58                         putc(null, SP->_ofp);
59                 (void) fflush(SP->_ofp);
60         }
61
62         returnCode(OK);
63 }
64
65 int _nc_outch(int ch)
66 {
67 #ifdef TRACE
68         _nc_outchars++;
69 #endif /* TRACE */
70
71         if (SP != NULL)
72                 putc(ch, SP->_ofp);
73         else
74                 putc(ch, stdout);
75         return OK;
76 }
77
78 int putp(const char *string)
79 {
80         return tputs(string, 1, _nc_outch);
81 }
82
83 int tputs(const char *string, int affcnt, int (*outc)(int))
84 {
85 float   number;
86 #ifdef BSD_TPUTS
87 float   trailpad;
88 #endif /* BSD_TPUTS */
89
90 #ifdef TRACE
91 char    addrbuf[17];
92
93         if (_nc_tracing & TRACE_TPUTS)
94         {
95                 if (outc == _nc_outch)
96                         (void) strcpy(addrbuf, "_nc_outch");
97                 else
98                         (void) sprintf(addrbuf, "%p", outc);
99                 if (_nc_tputs_trace)
100                         TR(TRACE_MAXIMUM, ("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, _nc_visbuf(string), affcnt, addrbuf));
101                 else
102                         TR(TRACE_MAXIMUM, ("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf));
103                 _nc_tputs_trace = (char *)NULL;
104         }
105 #endif /* TRACE */
106
107         if (string == ABSENT_STRING || string == CANCELLED_STRING)
108                 return ERR;
109
110 #ifdef BSD_TPUTS
111         /*
112          * This ugly kluge deals with the fact that some ancient BSD programs
113          * (like nethack) actually do the likes of tputs("50") to get delays.
114          */
115         trailpad = 0;
116         number = 0;
117
118         while (isdigit(*string)) {
119                 trailpad = trailpad * 10 + *string - '0';
120                 string++;
121         }
122
123         if (*string == '.') {
124                 string++;
125                 if (isdigit(*string)) {
126                         trailpad += (float) (*string - '0') / 10.;
127                         string++;
128                 }
129                 while (isdigit(*string))
130                         string++;
131         }
132
133         if (*string == '*') {
134                 trailpad *= affcnt;
135                 string++;
136         }
137 #endif /* BSD_TPUTS */
138
139         while (*string) {
140                 if (*string != '$')
141                         (*outc)(*string);
142                 else {
143                         string++;
144                         if (*string != '<') {
145                                 (*outc)('$');
146                                 if (*string)
147                                     (*outc)(*string);
148                         } else {
149                                 bool mandatory;
150
151                                 number = 0;
152                                 string++;
153
154                                 if ((!isdigit(*string) && *string != '.') || !strchr(string, '>')) {
155                                         (*outc)('$');
156                                         (*outc)('<');
157                                         continue;
158                                 }
159                                 while (isdigit(*string)) {
160                                         number = number * 10 + *string - '0';
161                                         string++;
162                                 }
163
164                                 if (*string == '.') {
165                                         string++;
166                                         if (isdigit(*string)) {
167                                                 number += (float) (*string - '0') / 10.;
168                                                 string++;
169                                         }
170                                         while (isdigit(*string))
171                                                 string++;
172                                 }
173
174                                 mandatory = !xon_xoff;
175                                 while (*string == '*' || *string == '/')
176                                 {
177                                         if (*string == '*') {
178                                                 number *= affcnt;
179                                                 string++;
180                                         }
181                                         else /* if (*string == '/') */ {
182                                                 mandatory = TRUE;
183                                                 string++;
184                                         }
185                                 }
186
187 #ifdef padding_baud_rate
188                                 if (mandatory && number > 0 && padding_baud_rate && (!SP || SP->_baudrate >= padding_baud_rate))
189                                         delay_output(number);
190 #endif /* padding_baud_rate */
191                                 number = 0;
192
193                         } /* endelse (*string == '<') */
194                 } /* endelse (*string == '$') */
195
196                 if (*string == '\0')
197                         break;
198
199                 string++;
200         }
201
202 #ifdef BSD_TPUTS
203         /*
204          * Emit any BSD-style prefix padding that we've accumulated now.
205          */
206 #ifdef padding_baud_rate
207         if (trailpad > 0 && !xon_xoff && padding_baud_rate && (!SP || SP->_baudrate >= padding_baud_rate))
208                 delay_output(number);
209 #endif /* padding_baud_rate */
210 #endif /* BSD_TPUTS */
211
212         return OK;
213 }