10e3d5408SPeter Wemm /**************************************************************************** 206bfebdeSXin LI * Copyright (c) 1998-2009,2010 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> * 325d08fb1fSRong-En Fan * and: Thomas E. Dickey 1996-on * 3306bfebdeSXin LI * and: Juergen Pfeifer 2009 * 340e3d5408SPeter Wemm ****************************************************************************/ 350e3d5408SPeter Wemm 360e3d5408SPeter Wemm /* 370e3d5408SPeter Wemm * tputs.c 380e3d5408SPeter Wemm * delay_output() 390e3d5408SPeter Wemm * _nc_outch() 400e3d5408SPeter Wemm * tputs() 410e3d5408SPeter Wemm * 420e3d5408SPeter Wemm */ 430e3d5408SPeter Wemm 440e3d5408SPeter Wemm #include <curses.priv.h> 4506bfebdeSXin LI 4606bfebdeSXin LI #ifndef CUR 4706bfebdeSXin LI #define CUR SP_TERMTYPE 4806bfebdeSXin LI #endif 4906bfebdeSXin LI 500e3d5408SPeter Wemm #include <ctype.h> 510e3d5408SPeter Wemm #include <termcap.h> /* ospeed */ 520e3d5408SPeter Wemm #include <tic.h> 530e3d5408SPeter Wemm 5406bfebdeSXin LI MODULE_ID("$Id: lib_tputs.c,v 1.81 2010/12/20 00:42:50 tom Exp $") 550e3d5408SPeter Wemm 564a1a9510SRong-En Fan NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */ 577a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ 580e3d5408SPeter Wemm 594a1a9510SRong-En Fan NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */ 600e3d5408SPeter Wemm 615d08fb1fSRong-En Fan #if NCURSES_NO_PADDING 625d08fb1fSRong-En Fan NCURSES_EXPORT(void) 635d08fb1fSRong-En Fan _nc_set_no_padding(SCREEN *sp) 645d08fb1fSRong-En Fan { 655d08fb1fSRong-En Fan bool no_padding = (getenv("NCURSES_NO_PADDING") != 0); 665d08fb1fSRong-En Fan 675d08fb1fSRong-En Fan if (sp) 685d08fb1fSRong-En Fan sp->_no_padding = no_padding; 695d08fb1fSRong-En Fan else 705d08fb1fSRong-En Fan _nc_prescreen._no_padding = no_padding; 715d08fb1fSRong-En Fan 725d08fb1fSRong-En Fan TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used", 735d08fb1fSRong-En Fan GetNoPadding(sp) ? " not" : "")); 745d08fb1fSRong-En Fan } 755d08fb1fSRong-En Fan #endif 765d08fb1fSRong-En Fan 7706bfebdeSXin LI #if NCURSES_SP_FUNCS 7806bfebdeSXin LI #define SetOutCh(func) if (SP_PARM) SP_PARM->_outch = func; else _nc_prescreen._outch = func 7906bfebdeSXin LI #define GetOutCh() (SP_PARM ? SP_PARM->_outch : _nc_prescreen._outch) 8006bfebdeSXin LI #else 8106bfebdeSXin LI #define SetOutCh(func) static_outch = func 8206bfebdeSXin LI #define GetOutCh() static_outch 8306bfebdeSXin LI static NCURSES_SP_OUTC static_outch = NCURSES_SP_NAME(_nc_outch); 8406bfebdeSXin LI #endif 850e3d5408SPeter Wemm 867a69bbfbSPeter Wemm NCURSES_EXPORT(int) 8706bfebdeSXin LI NCURSES_SP_NAME(delay_output) (NCURSES_SP_DCLx int ms) 880e3d5408SPeter Wemm { 8906bfebdeSXin LI T((T_CALLED("delay_output(%p,%d)"), (void *) SP_PARM, ms)); 9006bfebdeSXin LI 9106bfebdeSXin LI if (!HasTInfoTerminal(SP_PARM)) 9206bfebdeSXin LI returnCode(ERR); 930e3d5408SPeter Wemm 9415589c42SPeter Wemm if (no_pad_char) { 9506bfebdeSXin LI NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); 960e3d5408SPeter Wemm napms(ms); 9715589c42SPeter Wemm } else { 9806bfebdeSXin LI NCURSES_SP_OUTC my_outch = GetOutCh(); 990e3d5408SPeter Wemm register int nullcount; 1000e3d5408SPeter Wemm 1014a1a9510SRong-En Fan nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000); 1020e3d5408SPeter Wemm for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) 10306bfebdeSXin LI my_outch(NCURSES_SP_ARGx PC); 10406bfebdeSXin LI if (my_outch == NCURSES_SP_NAME(_nc_outch)) 10506bfebdeSXin LI NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); 1060e3d5408SPeter Wemm } 1070e3d5408SPeter Wemm 1080e3d5408SPeter Wemm returnCode(OK); 1090e3d5408SPeter Wemm } 1100e3d5408SPeter Wemm 11106bfebdeSXin LI #if NCURSES_SP_FUNCS 11206bfebdeSXin LI NCURSES_EXPORT(int) 11306bfebdeSXin LI delay_output(int ms) 11406bfebdeSXin LI { 11506bfebdeSXin LI return NCURSES_SP_NAME(delay_output) (CURRENT_SCREEN, ms); 11606bfebdeSXin LI } 11706bfebdeSXin LI #endif 11806bfebdeSXin LI 11906bfebdeSXin LI NCURSES_EXPORT(void) 12006bfebdeSXin LI NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_DCL0) 12106bfebdeSXin LI { 12206bfebdeSXin LI (void) fflush(NC_OUTPUT(SP_PARM)); 12306bfebdeSXin LI } 12406bfebdeSXin LI 12506bfebdeSXin LI #if NCURSES_SP_FUNCS 1267a69bbfbSPeter Wemm NCURSES_EXPORT(void) 12715589c42SPeter Wemm _nc_flush(void) 12815589c42SPeter Wemm { 12906bfebdeSXin LI NCURSES_SP_NAME(_nc_flush) (CURRENT_SCREEN); 13015589c42SPeter Wemm } 13106bfebdeSXin LI #endif 13215589c42SPeter Wemm 1337a69bbfbSPeter Wemm NCURSES_EXPORT(int) 13406bfebdeSXin LI NCURSES_SP_NAME(_nc_outch) (NCURSES_SP_DCLx int ch) 1350e3d5408SPeter Wemm { 13606bfebdeSXin LI int rc = OK; 13706bfebdeSXin LI 1385ca44d1cSRong-En Fan COUNT_OUTCHARS(1); 1390e3d5408SPeter Wemm 14006bfebdeSXin LI if (HasTInfoTerminal(SP_PARM) 14106bfebdeSXin LI && SP_PARM != 0 14206bfebdeSXin LI && SP_PARM->_cleanup) { 14306bfebdeSXin LI char tmp = (char) ch; 1441759abf3SPeter Wemm /* 1451759abf3SPeter Wemm * POSIX says write() is safe in a signal handler, but the 1461759abf3SPeter Wemm * buffered I/O is not. 1471759abf3SPeter Wemm */ 14806bfebdeSXin LI if (write(fileno(NC_OUTPUT(SP_PARM)), &tmp, 1) == -1) 14906bfebdeSXin LI rc = ERR; 1501759abf3SPeter Wemm } else { 15106bfebdeSXin LI if (putc(ch, NC_OUTPUT(SP_PARM)) == EOF) 15206bfebdeSXin LI rc = ERR; 1531759abf3SPeter Wemm } 15406bfebdeSXin LI return rc; 1550e3d5408SPeter Wemm } 1560e3d5408SPeter Wemm 15706bfebdeSXin LI #if NCURSES_SP_FUNCS 15806bfebdeSXin LI NCURSES_EXPORT(int) 15906bfebdeSXin LI _nc_outch(int ch) 16006bfebdeSXin LI { 16106bfebdeSXin LI return NCURSES_SP_NAME(_nc_outch) (CURRENT_SCREEN, ch); 16206bfebdeSXin LI } 16306bfebdeSXin LI #endif 16406bfebdeSXin LI 16506bfebdeSXin LI NCURSES_EXPORT(int) 16606bfebdeSXin LI NCURSES_SP_NAME(putp) (NCURSES_SP_DCLx const char *string) 16706bfebdeSXin LI { 16806bfebdeSXin LI return NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx 16906bfebdeSXin LI string, 1, NCURSES_SP_NAME(_nc_outch)); 17006bfebdeSXin LI } 17106bfebdeSXin LI 17206bfebdeSXin LI NCURSES_EXPORT(int) 17306bfebdeSXin LI NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_DCLx 17406bfebdeSXin LI const char *name GCC_UNUSED, 17506bfebdeSXin LI const char *string) 17606bfebdeSXin LI { 17706bfebdeSXin LI int rc = ERR; 17806bfebdeSXin LI 17906bfebdeSXin LI if (string != 0) { 18006bfebdeSXin LI TPUTS_TRACE(name); 18106bfebdeSXin LI rc = NCURSES_SP_NAME(putp) (NCURSES_SP_ARGx string); 18206bfebdeSXin LI } 18306bfebdeSXin LI return rc; 18406bfebdeSXin LI } 18506bfebdeSXin LI 18606bfebdeSXin LI #if NCURSES_SP_FUNCS 1877a69bbfbSPeter Wemm NCURSES_EXPORT(int) 18815589c42SPeter Wemm putp(const char *string) 1890e3d5408SPeter Wemm { 19006bfebdeSXin LI return NCURSES_SP_NAME(putp) (CURRENT_SCREEN, string); 1910e3d5408SPeter Wemm } 1920e3d5408SPeter Wemm 1937a69bbfbSPeter Wemm NCURSES_EXPORT(int) 19406bfebdeSXin LI _nc_putp(const char *name, const char *string) 1950e3d5408SPeter Wemm { 19606bfebdeSXin LI return NCURSES_SP_NAME(_nc_putp) (CURRENT_SCREEN, name, string); 19706bfebdeSXin LI } 19806bfebdeSXin LI #endif 19906bfebdeSXin LI 20006bfebdeSXin LI NCURSES_EXPORT(int) 20106bfebdeSXin LI NCURSES_SP_NAME(tputs) (NCURSES_SP_DCLx 20206bfebdeSXin LI const char *string, 20306bfebdeSXin LI int affcnt, 20406bfebdeSXin LI NCURSES_SP_OUTC outc) 20506bfebdeSXin LI { 20606bfebdeSXin LI NCURSES_SP_OUTC my_outch = GetOutCh(); 2070e3d5408SPeter Wemm bool always_delay; 2080e3d5408SPeter Wemm bool normal_delay; 2090e3d5408SPeter Wemm int number; 21018259542SPeter Wemm #if BSD_TPUTS 2110e3d5408SPeter Wemm int trailpad; 2120e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 2130e3d5408SPeter Wemm 2140e3d5408SPeter Wemm #ifdef TRACE 2150e3d5408SPeter Wemm char addrbuf[32]; 2160e3d5408SPeter Wemm 2175ca44d1cSRong-En Fan if (USE_TRACEF(TRACE_TPUTS)) { 21806bfebdeSXin LI if (outc == NCURSES_SP_NAME(_nc_outch)) 2190e3d5408SPeter Wemm (void) strcpy(addrbuf, "_nc_outch"); 2200e3d5408SPeter Wemm else 2210e3d5408SPeter Wemm (void) sprintf(addrbuf, "%p", outc); 2220e3d5408SPeter Wemm if (_nc_tputs_trace) { 22315589c42SPeter Wemm _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, 22415589c42SPeter Wemm _nc_visbuf(string), affcnt, addrbuf); 22515589c42SPeter Wemm } else { 22615589c42SPeter Wemm _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); 2270e3d5408SPeter Wemm } 2285ca44d1cSRong-En Fan TPUTS_TRACE(NULL); 2295ca44d1cSRong-En Fan _nc_unlock_global(tracef); 2300e3d5408SPeter Wemm } 2310e3d5408SPeter Wemm #endif /* TRACE */ 2320e3d5408SPeter Wemm 23306bfebdeSXin LI if (SP_PARM != 0 && !HasTInfoTerminal(SP_PARM)) 23406bfebdeSXin LI return ERR; 23506bfebdeSXin LI 2360e3d5408SPeter Wemm if (!VALID_STRING(string)) 2370e3d5408SPeter Wemm return ERR; 2380e3d5408SPeter Wemm 23906bfebdeSXin LI if ( 24006bfebdeSXin LI #if NCURSES_SP_FUNCS 24106bfebdeSXin LI (SP_PARM != 0 && SP_PARM->_term == 0) 24206bfebdeSXin LI #else 24306bfebdeSXin LI cur_term == 0 24406bfebdeSXin LI #endif 24506bfebdeSXin LI ) { 2460e3d5408SPeter Wemm always_delay = FALSE; 2470e3d5408SPeter Wemm normal_delay = TRUE; 2480e3d5408SPeter Wemm } else { 2490e3d5408SPeter Wemm always_delay = (string == bell) || (string == flash_screen); 2500e3d5408SPeter Wemm normal_delay = 2510e3d5408SPeter Wemm !xon_xoff 2520e3d5408SPeter Wemm && padding_baud_rate 25318259542SPeter Wemm #if NCURSES_NO_PADDING 25406bfebdeSXin LI && !GetNoPadding(SP_PARM) 2550e3d5408SPeter Wemm #endif 2560e3d5408SPeter Wemm && (_nc_baudrate(ospeed) >= padding_baud_rate); 2570e3d5408SPeter Wemm } 2580e3d5408SPeter Wemm 25918259542SPeter Wemm #if BSD_TPUTS 2600e3d5408SPeter Wemm /* 2610e3d5408SPeter Wemm * This ugly kluge deals with the fact that some ancient BSD programs 2620e3d5408SPeter Wemm * (like nethack) actually do the likes of tputs("50") to get delays. 2630e3d5408SPeter Wemm */ 2640e3d5408SPeter Wemm trailpad = 0; 26539f2269fSPeter Wemm if (isdigit(UChar(*string))) { 26639f2269fSPeter Wemm while (isdigit(UChar(*string))) { 2670e3d5408SPeter Wemm trailpad = trailpad * 10 + (*string - '0'); 2680e3d5408SPeter Wemm string++; 2690e3d5408SPeter Wemm } 2700e3d5408SPeter Wemm trailpad *= 10; 2710e3d5408SPeter Wemm if (*string == '.') { 2720e3d5408SPeter Wemm string++; 27339f2269fSPeter Wemm if (isdigit(UChar(*string))) { 2740e3d5408SPeter Wemm trailpad += (*string - '0'); 2750e3d5408SPeter Wemm string++; 2760e3d5408SPeter Wemm } 27739f2269fSPeter Wemm while (isdigit(UChar(*string))) 2780e3d5408SPeter Wemm string++; 2790e3d5408SPeter Wemm } 2800e3d5408SPeter Wemm 2810e3d5408SPeter Wemm if (*string == '*') { 2820e3d5408SPeter Wemm trailpad *= affcnt; 2830e3d5408SPeter Wemm string++; 2840e3d5408SPeter Wemm } 2850e3d5408SPeter Wemm } 2860e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 2870e3d5408SPeter Wemm 28806bfebdeSXin LI SetOutCh(outc); /* redirect delay_output() */ 2890e3d5408SPeter Wemm while (*string) { 2900e3d5408SPeter Wemm if (*string != '$') 29106bfebdeSXin LI (*outc) (NCURSES_SP_ARGx *string); 2920e3d5408SPeter Wemm else { 2930e3d5408SPeter Wemm string++; 2940e3d5408SPeter Wemm if (*string != '<') { 29506bfebdeSXin LI (*outc) (NCURSES_SP_ARGx '$'); 2960e3d5408SPeter Wemm if (*string) 29706bfebdeSXin LI (*outc) (NCURSES_SP_ARGx *string); 2980e3d5408SPeter Wemm } else { 2990e3d5408SPeter Wemm bool mandatory; 3000e3d5408SPeter Wemm 3010e3d5408SPeter Wemm string++; 30239f2269fSPeter Wemm if ((!isdigit(UChar(*string)) && *string != '.') 3037a69bbfbSPeter Wemm || !strchr(string, '>')) { 30406bfebdeSXin LI (*outc) (NCURSES_SP_ARGx '$'); 30506bfebdeSXin LI (*outc) (NCURSES_SP_ARGx '<'); 3060e3d5408SPeter Wemm continue; 3070e3d5408SPeter Wemm } 3080e3d5408SPeter Wemm 3090e3d5408SPeter Wemm number = 0; 31039f2269fSPeter Wemm while (isdigit(UChar(*string))) { 3110e3d5408SPeter Wemm number = number * 10 + (*string - '0'); 3120e3d5408SPeter Wemm string++; 3130e3d5408SPeter Wemm } 3140e3d5408SPeter Wemm number *= 10; 3150e3d5408SPeter Wemm if (*string == '.') { 3160e3d5408SPeter Wemm string++; 31739f2269fSPeter Wemm if (isdigit(UChar(*string))) { 3180e3d5408SPeter Wemm number += (*string - '0'); 3190e3d5408SPeter Wemm string++; 3200e3d5408SPeter Wemm } 32139f2269fSPeter Wemm while (isdigit(UChar(*string))) 3220e3d5408SPeter Wemm string++; 3230e3d5408SPeter Wemm } 3240e3d5408SPeter Wemm 3250e3d5408SPeter Wemm mandatory = FALSE; 32615589c42SPeter Wemm while (*string == '*' || *string == '/') { 3270e3d5408SPeter Wemm if (*string == '*') { 3280e3d5408SPeter Wemm number *= affcnt; 3290e3d5408SPeter Wemm string++; 33015589c42SPeter Wemm } else { /* if (*string == '/') */ 3310e3d5408SPeter Wemm mandatory = TRUE; 3320e3d5408SPeter Wemm string++; 3330e3d5408SPeter Wemm } 3340e3d5408SPeter Wemm } 3350e3d5408SPeter Wemm 3360e3d5408SPeter Wemm if (number > 0 3370e3d5408SPeter Wemm && (always_delay 3380e3d5408SPeter Wemm || normal_delay 3390e3d5408SPeter Wemm || mandatory)) 34006bfebdeSXin LI NCURSES_SP_NAME(delay_output) (NCURSES_SP_ARGx number / 10); 3410e3d5408SPeter Wemm 3420e3d5408SPeter Wemm } /* endelse (*string == '<') */ 3430e3d5408SPeter Wemm } /* endelse (*string == '$') */ 3440e3d5408SPeter Wemm 3450e3d5408SPeter Wemm if (*string == '\0') 3460e3d5408SPeter Wemm break; 3470e3d5408SPeter Wemm 3480e3d5408SPeter Wemm string++; 3490e3d5408SPeter Wemm } 3500e3d5408SPeter Wemm 35118259542SPeter Wemm #if BSD_TPUTS 3520e3d5408SPeter Wemm /* 3530e3d5408SPeter Wemm * Emit any BSD-style prefix padding that we've accumulated now. 3540e3d5408SPeter Wemm */ 3550e3d5408SPeter Wemm if (trailpad > 0 3560e3d5408SPeter Wemm && (always_delay || normal_delay)) 3570e3d5408SPeter Wemm delay_output(trailpad / 10); 3580e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 3590e3d5408SPeter Wemm 36006bfebdeSXin LI SetOutCh(my_outch); 3610e3d5408SPeter Wemm return OK; 3620e3d5408SPeter Wemm } 36306bfebdeSXin LI 36406bfebdeSXin LI #if NCURSES_SP_FUNCS 36506bfebdeSXin LI NCURSES_EXPORT(int) 36606bfebdeSXin LI _nc_outc_wrapper(SCREEN *sp, int c) 36706bfebdeSXin LI { 36806bfebdeSXin LI if (0 == sp) { 36906bfebdeSXin LI return (ERR); 37006bfebdeSXin LI } else { 37106bfebdeSXin LI return sp->jump(c); 37206bfebdeSXin LI } 37306bfebdeSXin LI } 37406bfebdeSXin LI 37506bfebdeSXin LI NCURSES_EXPORT(int) 37606bfebdeSXin LI tputs(const char *string, int affcnt, int (*outc) (int)) 37706bfebdeSXin LI { 37806bfebdeSXin LI SetSafeOutcWrapper(outc); 37906bfebdeSXin LI return NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx string, affcnt, _nc_outc_wrapper); 38006bfebdeSXin LI } 38106bfebdeSXin LI #endif 382