150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32184989Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * tputs.c 3750276Speter * delay_output() 3850276Speter * _nc_outch() 3950276Speter * tputs() 4050276Speter * 4150276Speter */ 4250276Speter 4350276Speter#include <curses.priv.h> 4450276Speter#include <ctype.h> 4562449Speter#include <term.h> /* padding_baud_rate, xon_xoff */ 4662449Speter#include <termcap.h> /* ospeed */ 4750276Speter#include <tic.h> 4850276Speter 49184989SrafanMODULE_ID("$Id: lib_tputs.c,v 1.66 2008/06/28 13:12:15 tom Exp $") 5050276Speter 51174993SrafanNCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */ 52174993SrafanNCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ 5350276Speter 54174993SrafanNCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */ 5550276Speter 56184989Srafan#if NCURSES_NO_PADDING 57184989SrafanNCURSES_EXPORT(void) 58184989Srafan_nc_set_no_padding(SCREEN *sp) 59184989Srafan{ 60184989Srafan bool no_padding = (getenv("NCURSES_NO_PADDING") != 0); 61184989Srafan 62184989Srafan if (sp) 63184989Srafan sp->_no_padding = no_padding; 64184989Srafan else 65184989Srafan _nc_prescreen._no_padding = no_padding; 66184989Srafan 67184989Srafan TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used", 68184989Srafan GetNoPadding(sp) ? " not" : "")); 69184989Srafan} 70184989Srafan#endif 71184989Srafan 72166124Srafanstatic int (*my_outch) (int c) = _nc_outch; 7350276Speter 7476726SpeterNCURSES_EXPORT(int) 7562449Speterdelay_output(int ms) 7650276Speter{ 7762449Speter T((T_CALLED("delay_output(%d)"), ms)); 7850276Speter 7962449Speter if (no_pad_char) { 8062449Speter _nc_flush(); 8162449Speter napms(ms); 8262449Speter } else { 8362449Speter register int nullcount; 8450276Speter 85166124Srafan nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000); 8662449Speter for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) 8762449Speter my_outch(PC); 8862449Speter if (my_outch == _nc_outch) 8962449Speter _nc_flush(); 9062449Speter } 9150276Speter 9262449Speter returnCode(OK); 9350276Speter} 9450276Speter 9576726SpeterNCURSES_EXPORT(void) 9662449Speter_nc_flush(void) 9750276Speter{ 9866963Speter (void) fflush(NC_OUTPUT); 9962449Speter} 10062449Speter 10176726SpeterNCURSES_EXPORT(int) 10262449Speter_nc_outch(int ch) 10362449Speter{ 104174993Srafan COUNT_OUTCHARS(1); 10550276Speter 10662449Speter if (SP != 0 10762449Speter && SP->_cleanup) { 10862449Speter char tmp = ch; 10962449Speter /* 11062449Speter * POSIX says write() is safe in a signal handler, but the 11162449Speter * buffered I/O is not. 11262449Speter */ 11362449Speter write(fileno(NC_OUTPUT), &tmp, 1); 11462449Speter } else { 11562449Speter putc(ch, NC_OUTPUT); 11662449Speter } 11762449Speter return OK; 11850276Speter} 11950276Speter 12076726SpeterNCURSES_EXPORT(int) 12162449Speterputp(const char *string) 12250276Speter{ 12362449Speter return tputs(string, 1, _nc_outch); 12462449Speter} 12562449Speter 12676726SpeterNCURSES_EXPORT(int) 127166124Srafantputs(const char *string, int affcnt, int (*outc) (int)) 12862449Speter{ 12962449Speter bool always_delay; 13062449Speter bool normal_delay; 13162449Speter int number; 13266963Speter#if BSD_TPUTS 13362449Speter int trailpad; 13450276Speter#endif /* BSD_TPUTS */ 13550276Speter 13650276Speter#ifdef TRACE 13762449Speter char addrbuf[32]; 13850276Speter 139174993Srafan if (USE_TRACEF(TRACE_TPUTS)) { 14062449Speter if (outc == _nc_outch) 14162449Speter (void) strcpy(addrbuf, "_nc_outch"); 14262449Speter else 14362449Speter (void) sprintf(addrbuf, "%p", outc); 14462449Speter if (_nc_tputs_trace) { 14562449Speter _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, 14666963Speter _nc_visbuf(string), affcnt, addrbuf); 14762449Speter } else { 14862449Speter _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); 14950276Speter } 150174993Srafan TPUTS_TRACE(NULL); 151174993Srafan _nc_unlock_global(tracef); 15262449Speter } 15350276Speter#endif /* TRACE */ 15450276Speter 15562449Speter if (!VALID_STRING(string)) 15662449Speter return ERR; 15762449Speter 15862449Speter if (cur_term == 0) { 15962449Speter always_delay = FALSE; 16062449Speter normal_delay = TRUE; 16162449Speter } else { 16262449Speter always_delay = (string == bell) || (string == flash_screen); 16362449Speter normal_delay = 16462449Speter !xon_xoff 16562449Speter && padding_baud_rate 16666963Speter#if NCURSES_NO_PADDING 167184989Srafan && !GetNoPadding(SP) 16850276Speter#endif 16962449Speter && (_nc_baudrate(ospeed) >= padding_baud_rate); 17062449Speter } 17162449Speter 17266963Speter#if BSD_TPUTS 17362449Speter /* 17462449Speter * This ugly kluge deals with the fact that some ancient BSD programs 17562449Speter * (like nethack) actually do the likes of tputs("50") to get delays. 17662449Speter */ 17762449Speter trailpad = 0; 17897049Speter if (isdigit(UChar(*string))) { 17997049Speter while (isdigit(UChar(*string))) { 18062449Speter trailpad = trailpad * 10 + (*string - '0'); 18162449Speter string++; 18250276Speter } 18362449Speter trailpad *= 10; 18462449Speter if (*string == '.') { 18562449Speter string++; 18697049Speter if (isdigit(UChar(*string))) { 18762449Speter trailpad += (*string - '0'); 18862449Speter string++; 18962449Speter } 19097049Speter while (isdigit(UChar(*string))) 19162449Speter string++; 19262449Speter } 19350276Speter 19462449Speter if (*string == '*') { 19562449Speter trailpad *= affcnt; 19662449Speter string++; 19762449Speter } 19862449Speter } 19962449Speter#endif /* BSD_TPUTS */ 20062449Speter 20162449Speter my_outch = outc; /* redirect delay_output() */ 20262449Speter while (*string) { 20362449Speter if (*string != '$') 20462449Speter (*outc) (*string); 20562449Speter else { 20662449Speter string++; 20762449Speter if (*string != '<') { 20862449Speter (*outc) ('$'); 20962449Speter if (*string) 21062449Speter (*outc) (*string); 21162449Speter } else { 21262449Speter bool mandatory; 21362449Speter 21462449Speter string++; 21597049Speter if ((!isdigit(UChar(*string)) && *string != '.') 21676726Speter || !strchr(string, '>')) { 21762449Speter (*outc) ('$'); 21862449Speter (*outc) ('<'); 21962449Speter continue; 22062449Speter } 22162449Speter 22262449Speter number = 0; 22397049Speter while (isdigit(UChar(*string))) { 22462449Speter number = number * 10 + (*string - '0'); 22562449Speter string++; 22650276Speter } 22762449Speter number *= 10; 22850276Speter if (*string == '.') { 22962449Speter string++; 23097049Speter if (isdigit(UChar(*string))) { 23162449Speter number += (*string - '0'); 23250276Speter string++; 23362449Speter } 23497049Speter while (isdigit(UChar(*string))) 23562449Speter string++; 23650276Speter } 23750276Speter 23862449Speter mandatory = FALSE; 23962449Speter while (*string == '*' || *string == '/') { 24062449Speter if (*string == '*') { 24162449Speter number *= affcnt; 24250276Speter string++; 24362449Speter } else { /* if (*string == '/') */ 24462449Speter mandatory = TRUE; 24562449Speter string++; 24662449Speter } 24750276Speter } 24850276Speter 24962449Speter if (number > 0 25062449Speter && (always_delay 25162449Speter || normal_delay 25262449Speter || mandatory)) 25362449Speter delay_output(number / 10); 25450276Speter 25562449Speter } /* endelse (*string == '<') */ 25662449Speter } /* endelse (*string == '$') */ 25750276Speter 25862449Speter if (*string == '\0') 25962449Speter break; 26050276Speter 26162449Speter string++; 26262449Speter } 26350276Speter 26466963Speter#if BSD_TPUTS 26562449Speter /* 26662449Speter * Emit any BSD-style prefix padding that we've accumulated now. 26762449Speter */ 26862449Speter if (trailpad > 0 26962449Speter && (always_delay || normal_delay)) 27062449Speter delay_output(trailpad / 10); 27150276Speter#endif /* BSD_TPUTS */ 27250276Speter 27362449Speter my_outch = _nc_outch; 27462449Speter return OK; 27550276Speter} 276