10e3d5408SPeter Wemm /**************************************************************************** 25ca44d1cSRong-En Fan * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 320e3d5408SPeter Wemm ****************************************************************************/ 330e3d5408SPeter Wemm 340e3d5408SPeter Wemm /* 350e3d5408SPeter Wemm * tputs.c 360e3d5408SPeter Wemm * delay_output() 370e3d5408SPeter Wemm * _nc_outch() 380e3d5408SPeter Wemm * tputs() 390e3d5408SPeter Wemm * 400e3d5408SPeter Wemm */ 410e3d5408SPeter Wemm 420e3d5408SPeter Wemm #include <curses.priv.h> 430e3d5408SPeter Wemm #include <ctype.h> 440e3d5408SPeter Wemm #include <term.h> /* padding_baud_rate, xon_xoff */ 450e3d5408SPeter Wemm #include <termcap.h> /* ospeed */ 460e3d5408SPeter Wemm #include <tic.h> 470e3d5408SPeter Wemm 485ca44d1cSRong-En Fan MODULE_ID("$Id: lib_tputs.c,v 1.64 2007/09/29 20:37:13 tom Exp $") 490e3d5408SPeter Wemm 504a1a9510SRong-En Fan NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */ 517a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ 520e3d5408SPeter Wemm 534a1a9510SRong-En Fan NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */ 540e3d5408SPeter Wemm 550e3d5408SPeter Wemm static int (*my_outch) (int c) = _nc_outch; 560e3d5408SPeter Wemm 577a69bbfbSPeter Wemm NCURSES_EXPORT(int) 5815589c42SPeter Wemm delay_output(int ms) 590e3d5408SPeter Wemm { 600e3d5408SPeter Wemm T((T_CALLED("delay_output(%d)"), ms)); 610e3d5408SPeter Wemm 6215589c42SPeter Wemm if (no_pad_char) { 6315589c42SPeter Wemm _nc_flush(); 640e3d5408SPeter Wemm napms(ms); 6515589c42SPeter Wemm } else { 660e3d5408SPeter Wemm register int nullcount; 670e3d5408SPeter Wemm 684a1a9510SRong-En Fan nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000); 690e3d5408SPeter Wemm for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) 700e3d5408SPeter Wemm my_outch(PC); 710e3d5408SPeter Wemm if (my_outch == _nc_outch) 721759abf3SPeter Wemm _nc_flush(); 730e3d5408SPeter Wemm } 740e3d5408SPeter Wemm 750e3d5408SPeter Wemm returnCode(OK); 760e3d5408SPeter Wemm } 770e3d5408SPeter Wemm 787a69bbfbSPeter Wemm NCURSES_EXPORT(void) 7915589c42SPeter Wemm _nc_flush(void) 8015589c42SPeter Wemm { 8115589c42SPeter Wemm (void) fflush(NC_OUTPUT); 8215589c42SPeter Wemm } 8315589c42SPeter Wemm 847a69bbfbSPeter Wemm NCURSES_EXPORT(int) 8515589c42SPeter Wemm _nc_outch(int ch) 860e3d5408SPeter Wemm { 875ca44d1cSRong-En Fan COUNT_OUTCHARS(1); 880e3d5408SPeter Wemm 891759abf3SPeter Wemm if (SP != 0 901759abf3SPeter Wemm && SP->_cleanup) { 911759abf3SPeter Wemm char tmp = ch; 921759abf3SPeter Wemm /* 931759abf3SPeter Wemm * POSIX says write() is safe in a signal handler, but the 941759abf3SPeter Wemm * buffered I/O is not. 951759abf3SPeter Wemm */ 961759abf3SPeter Wemm write(fileno(NC_OUTPUT), &tmp, 1); 971759abf3SPeter Wemm } else { 981759abf3SPeter Wemm putc(ch, NC_OUTPUT); 991759abf3SPeter Wemm } 1000e3d5408SPeter Wemm return OK; 1010e3d5408SPeter Wemm } 1020e3d5408SPeter Wemm 1037a69bbfbSPeter Wemm NCURSES_EXPORT(int) 10415589c42SPeter Wemm putp(const char *string) 1050e3d5408SPeter Wemm { 1060e3d5408SPeter Wemm return tputs(string, 1, _nc_outch); 1070e3d5408SPeter Wemm } 1080e3d5408SPeter Wemm 1097a69bbfbSPeter Wemm NCURSES_EXPORT(int) 1104a1a9510SRong-En Fan tputs(const char *string, int affcnt, int (*outc) (int)) 1110e3d5408SPeter Wemm { 1120e3d5408SPeter Wemm bool always_delay; 1130e3d5408SPeter Wemm bool normal_delay; 1140e3d5408SPeter Wemm int number; 11518259542SPeter Wemm #if BSD_TPUTS 1160e3d5408SPeter Wemm int trailpad; 1170e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 1180e3d5408SPeter Wemm 1190e3d5408SPeter Wemm #ifdef TRACE 1200e3d5408SPeter Wemm char addrbuf[32]; 1210e3d5408SPeter Wemm 1225ca44d1cSRong-En Fan if (USE_TRACEF(TRACE_TPUTS)) { 1230e3d5408SPeter Wemm if (outc == _nc_outch) 1240e3d5408SPeter Wemm (void) strcpy(addrbuf, "_nc_outch"); 1250e3d5408SPeter Wemm else 1260e3d5408SPeter Wemm (void) sprintf(addrbuf, "%p", outc); 1270e3d5408SPeter Wemm if (_nc_tputs_trace) { 12815589c42SPeter Wemm _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, 12915589c42SPeter Wemm _nc_visbuf(string), affcnt, addrbuf); 13015589c42SPeter Wemm } else { 13115589c42SPeter Wemm _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); 1320e3d5408SPeter Wemm } 1335ca44d1cSRong-En Fan TPUTS_TRACE(NULL); 1345ca44d1cSRong-En Fan _nc_unlock_global(tracef); 1350e3d5408SPeter Wemm } 1360e3d5408SPeter Wemm #endif /* TRACE */ 1370e3d5408SPeter Wemm 1380e3d5408SPeter Wemm if (!VALID_STRING(string)) 1390e3d5408SPeter Wemm return ERR; 1400e3d5408SPeter Wemm 1410e3d5408SPeter Wemm if (cur_term == 0) { 1420e3d5408SPeter Wemm always_delay = FALSE; 1430e3d5408SPeter Wemm normal_delay = TRUE; 1440e3d5408SPeter Wemm } else { 1450e3d5408SPeter Wemm always_delay = (string == bell) || (string == flash_screen); 1460e3d5408SPeter Wemm normal_delay = 1470e3d5408SPeter Wemm !xon_xoff 1480e3d5408SPeter Wemm && padding_baud_rate 14918259542SPeter Wemm #if NCURSES_NO_PADDING 1500e3d5408SPeter Wemm && (SP == 0 || !(SP->_no_padding)) 1510e3d5408SPeter Wemm #endif 1520e3d5408SPeter Wemm && (_nc_baudrate(ospeed) >= padding_baud_rate); 1530e3d5408SPeter Wemm } 1540e3d5408SPeter Wemm 15518259542SPeter Wemm #if BSD_TPUTS 1560e3d5408SPeter Wemm /* 1570e3d5408SPeter Wemm * This ugly kluge deals with the fact that some ancient BSD programs 1580e3d5408SPeter Wemm * (like nethack) actually do the likes of tputs("50") to get delays. 1590e3d5408SPeter Wemm */ 1600e3d5408SPeter Wemm trailpad = 0; 16139f2269fSPeter Wemm if (isdigit(UChar(*string))) { 16239f2269fSPeter Wemm while (isdigit(UChar(*string))) { 1630e3d5408SPeter Wemm trailpad = trailpad * 10 + (*string - '0'); 1640e3d5408SPeter Wemm string++; 1650e3d5408SPeter Wemm } 1660e3d5408SPeter Wemm trailpad *= 10; 1670e3d5408SPeter Wemm if (*string == '.') { 1680e3d5408SPeter Wemm string++; 16939f2269fSPeter Wemm if (isdigit(UChar(*string))) { 1700e3d5408SPeter Wemm trailpad += (*string - '0'); 1710e3d5408SPeter Wemm string++; 1720e3d5408SPeter Wemm } 17339f2269fSPeter Wemm while (isdigit(UChar(*string))) 1740e3d5408SPeter Wemm string++; 1750e3d5408SPeter Wemm } 1760e3d5408SPeter Wemm 1770e3d5408SPeter Wemm if (*string == '*') { 1780e3d5408SPeter Wemm trailpad *= affcnt; 1790e3d5408SPeter Wemm string++; 1800e3d5408SPeter Wemm } 1810e3d5408SPeter Wemm } 1820e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 1830e3d5408SPeter Wemm 1840e3d5408SPeter Wemm my_outch = outc; /* redirect delay_output() */ 1850e3d5408SPeter Wemm while (*string) { 1860e3d5408SPeter Wemm if (*string != '$') 1870e3d5408SPeter Wemm (*outc) (*string); 1880e3d5408SPeter Wemm else { 1890e3d5408SPeter Wemm string++; 1900e3d5408SPeter Wemm if (*string != '<') { 1910e3d5408SPeter Wemm (*outc) ('$'); 1920e3d5408SPeter Wemm if (*string) 1930e3d5408SPeter Wemm (*outc) (*string); 1940e3d5408SPeter Wemm } else { 1950e3d5408SPeter Wemm bool mandatory; 1960e3d5408SPeter Wemm 1970e3d5408SPeter Wemm string++; 19839f2269fSPeter Wemm if ((!isdigit(UChar(*string)) && *string != '.') 1997a69bbfbSPeter Wemm || !strchr(string, '>')) { 2000e3d5408SPeter Wemm (*outc) ('$'); 2010e3d5408SPeter Wemm (*outc) ('<'); 2020e3d5408SPeter Wemm continue; 2030e3d5408SPeter Wemm } 2040e3d5408SPeter Wemm 2050e3d5408SPeter Wemm number = 0; 20639f2269fSPeter Wemm while (isdigit(UChar(*string))) { 2070e3d5408SPeter Wemm number = number * 10 + (*string - '0'); 2080e3d5408SPeter Wemm string++; 2090e3d5408SPeter Wemm } 2100e3d5408SPeter Wemm number *= 10; 2110e3d5408SPeter Wemm if (*string == '.') { 2120e3d5408SPeter Wemm string++; 21339f2269fSPeter Wemm if (isdigit(UChar(*string))) { 2140e3d5408SPeter Wemm number += (*string - '0'); 2150e3d5408SPeter Wemm string++; 2160e3d5408SPeter Wemm } 21739f2269fSPeter Wemm while (isdigit(UChar(*string))) 2180e3d5408SPeter Wemm string++; 2190e3d5408SPeter Wemm } 2200e3d5408SPeter Wemm 2210e3d5408SPeter Wemm mandatory = FALSE; 22215589c42SPeter Wemm while (*string == '*' || *string == '/') { 2230e3d5408SPeter Wemm if (*string == '*') { 2240e3d5408SPeter Wemm number *= affcnt; 2250e3d5408SPeter Wemm string++; 22615589c42SPeter Wemm } else { /* if (*string == '/') */ 2270e3d5408SPeter Wemm mandatory = TRUE; 2280e3d5408SPeter Wemm string++; 2290e3d5408SPeter Wemm } 2300e3d5408SPeter Wemm } 2310e3d5408SPeter Wemm 2320e3d5408SPeter Wemm if (number > 0 2330e3d5408SPeter Wemm && (always_delay 2340e3d5408SPeter Wemm || normal_delay 2350e3d5408SPeter Wemm || mandatory)) 2360e3d5408SPeter Wemm delay_output(number / 10); 2370e3d5408SPeter Wemm 2380e3d5408SPeter Wemm } /* endelse (*string == '<') */ 2390e3d5408SPeter Wemm } /* endelse (*string == '$') */ 2400e3d5408SPeter Wemm 2410e3d5408SPeter Wemm if (*string == '\0') 2420e3d5408SPeter Wemm break; 2430e3d5408SPeter Wemm 2440e3d5408SPeter Wemm string++; 2450e3d5408SPeter Wemm } 2460e3d5408SPeter Wemm 24718259542SPeter Wemm #if BSD_TPUTS 2480e3d5408SPeter Wemm /* 2490e3d5408SPeter Wemm * Emit any BSD-style prefix padding that we've accumulated now. 2500e3d5408SPeter Wemm */ 2510e3d5408SPeter Wemm if (trailpad > 0 2520e3d5408SPeter Wemm && (always_delay || normal_delay)) 2530e3d5408SPeter Wemm delay_output(trailpad / 10); 2540e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 2550e3d5408SPeter Wemm 2560e3d5408SPeter Wemm my_outch = _nc_outch; 2570e3d5408SPeter Wemm return OK; 2580e3d5408SPeter Wemm } 259