10e3d5408SPeter Wemm /**************************************************************************** 27a69bbfbSPeter Wemm * Copyright (c) 1998,1999,2000,2001 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 487a69bbfbSPeter Wemm MODULE_ID("$Id: lib_tputs.c,v 1.56 2001/04/21 18:53:53 tom Exp $") 490e3d5408SPeter Wemm 507a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(char) 517a69bbfbSPeter Wemm PC = 0; /* used by termcap library */ 527a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ 530e3d5408SPeter Wemm 547a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(int) 557a69bbfbSPeter Wemm _nc_nulls_sent = 0; /* used by 'tack' program */ 560e3d5408SPeter Wemm 570e3d5408SPeter Wemm static int (*my_outch) (int c) = _nc_outch; 580e3d5408SPeter Wemm 597a69bbfbSPeter Wemm NCURSES_EXPORT(int) 6015589c42SPeter Wemm delay_output(int ms) 610e3d5408SPeter Wemm { 620e3d5408SPeter Wemm T((T_CALLED("delay_output(%d)"), ms)); 630e3d5408SPeter Wemm 6415589c42SPeter Wemm if (no_pad_char) { 6515589c42SPeter Wemm _nc_flush(); 660e3d5408SPeter Wemm napms(ms); 6715589c42SPeter Wemm } else { 680e3d5408SPeter Wemm register int nullcount; 690e3d5408SPeter Wemm 700e3d5408SPeter Wemm nullcount = (ms * _nc_baudrate(ospeed)) / 10000; 710e3d5408SPeter Wemm for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) 720e3d5408SPeter Wemm my_outch(PC); 730e3d5408SPeter Wemm if (my_outch == _nc_outch) 741759abf3SPeter Wemm _nc_flush(); 750e3d5408SPeter Wemm } 760e3d5408SPeter Wemm 770e3d5408SPeter Wemm returnCode(OK); 780e3d5408SPeter Wemm } 790e3d5408SPeter Wemm 807a69bbfbSPeter Wemm NCURSES_EXPORT(void) 8115589c42SPeter Wemm _nc_flush(void) 8215589c42SPeter Wemm { 8315589c42SPeter Wemm (void) fflush(NC_OUTPUT); 8415589c42SPeter Wemm } 8515589c42SPeter Wemm 867a69bbfbSPeter Wemm NCURSES_EXPORT(int) 8715589c42SPeter Wemm _nc_outch(int ch) 880e3d5408SPeter Wemm { 890e3d5408SPeter Wemm #ifdef TRACE 900e3d5408SPeter Wemm _nc_outchars++; 910e3d5408SPeter Wemm #endif /* TRACE */ 920e3d5408SPeter Wemm 931759abf3SPeter Wemm if (SP != 0 941759abf3SPeter Wemm && SP->_cleanup) { 951759abf3SPeter Wemm char tmp = ch; 961759abf3SPeter Wemm /* 971759abf3SPeter Wemm * POSIX says write() is safe in a signal handler, but the 981759abf3SPeter Wemm * buffered I/O is not. 991759abf3SPeter Wemm */ 1001759abf3SPeter Wemm write(fileno(NC_OUTPUT), &tmp, 1); 1011759abf3SPeter Wemm } else { 1021759abf3SPeter Wemm putc(ch, NC_OUTPUT); 1031759abf3SPeter Wemm } 1040e3d5408SPeter Wemm return OK; 1050e3d5408SPeter Wemm } 1060e3d5408SPeter Wemm 10718259542SPeter Wemm #if USE_WIDEC_SUPPORT 10815589c42SPeter Wemm /* 10915589c42SPeter Wemm * Reference: The Unicode Standard 2.0 11015589c42SPeter Wemm * 11115589c42SPeter Wemm * No surrogates supported (we're storing only one 16-bit Unicode value per 11215589c42SPeter Wemm * cell). 11315589c42SPeter Wemm */ 1147a69bbfbSPeter Wemm NCURSES_EXPORT(int) 11515589c42SPeter Wemm _nc_utf8_outch(int ch) 11615589c42SPeter Wemm { 11715589c42SPeter Wemm static const unsigned byteMask = 0xBF; 11815589c42SPeter Wemm static const unsigned otherMark = 0x80; 11915589c42SPeter Wemm static const unsigned firstMark[] = 12015589c42SPeter Wemm {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; 12115589c42SPeter Wemm 12215589c42SPeter Wemm int result[7], *ptr; 12315589c42SPeter Wemm int count = 0; 12415589c42SPeter Wemm 12518259542SPeter Wemm if ((unsigned int) ch < 0x80) 12615589c42SPeter Wemm count = 1; 12718259542SPeter Wemm else if ((unsigned int) ch < 0x800) 12815589c42SPeter Wemm count = 2; 12918259542SPeter Wemm else if ((unsigned int) ch < 0x10000) 13015589c42SPeter Wemm count = 3; 13118259542SPeter Wemm else if ((unsigned int) ch < 0x200000) 13215589c42SPeter Wemm count = 4; 13318259542SPeter Wemm else if ((unsigned int) ch < 0x4000000) 13415589c42SPeter Wemm count = 5; 13518259542SPeter Wemm else if ((unsigned int) ch <= 0x7FFFFFFF) 13615589c42SPeter Wemm count = 6; 13715589c42SPeter Wemm else { 13818259542SPeter Wemm count = 3; 13915589c42SPeter Wemm ch = 0xFFFD; 14015589c42SPeter Wemm } 14115589c42SPeter Wemm ptr = result + count; 14215589c42SPeter Wemm switch (count) { 14315589c42SPeter Wemm case 6: 14415589c42SPeter Wemm *--ptr = (ch | otherMark) & byteMask; 14515589c42SPeter Wemm ch >>= 6; 14618259542SPeter Wemm /* FALLTHRU */ 14715589c42SPeter Wemm case 5: 14815589c42SPeter Wemm *--ptr = (ch | otherMark) & byteMask; 14915589c42SPeter Wemm ch >>= 6; 15018259542SPeter Wemm /* FALLTHRU */ 15115589c42SPeter Wemm case 4: 15215589c42SPeter Wemm *--ptr = (ch | otherMark) & byteMask; 15315589c42SPeter Wemm ch >>= 6; 15418259542SPeter Wemm /* FALLTHRU */ 15515589c42SPeter Wemm case 3: 15615589c42SPeter Wemm *--ptr = (ch | otherMark) & byteMask; 15715589c42SPeter Wemm ch >>= 6; 15818259542SPeter Wemm /* FALLTHRU */ 15915589c42SPeter Wemm case 2: 16015589c42SPeter Wemm *--ptr = (ch | otherMark) & byteMask; 16115589c42SPeter Wemm ch >>= 6; 16218259542SPeter Wemm /* FALLTHRU */ 16315589c42SPeter Wemm case 1: 16415589c42SPeter Wemm *--ptr = (ch | firstMark[count]); 16518259542SPeter Wemm break; 16615589c42SPeter Wemm } 16715589c42SPeter Wemm while (count--) 16815589c42SPeter Wemm _nc_outch(*ptr++); 16915589c42SPeter Wemm return OK; 17015589c42SPeter Wemm } 17115589c42SPeter Wemm #endif 17215589c42SPeter Wemm 1737a69bbfbSPeter Wemm NCURSES_EXPORT(int) 17415589c42SPeter Wemm putp(const char *string) 1750e3d5408SPeter Wemm { 1760e3d5408SPeter Wemm return tputs(string, 1, _nc_outch); 1770e3d5408SPeter Wemm } 1780e3d5408SPeter Wemm 1797a69bbfbSPeter Wemm NCURSES_EXPORT(int) 1807a69bbfbSPeter Wemm tputs 1817a69bbfbSPeter Wemm (const char *string, int affcnt, int (*outc) (int)) 1820e3d5408SPeter Wemm { 1830e3d5408SPeter Wemm bool always_delay; 1840e3d5408SPeter Wemm bool normal_delay; 1850e3d5408SPeter Wemm int number; 18618259542SPeter Wemm #if BSD_TPUTS 1870e3d5408SPeter Wemm int trailpad; 1880e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 1890e3d5408SPeter Wemm 1900e3d5408SPeter Wemm #ifdef TRACE 1910e3d5408SPeter Wemm char addrbuf[32]; 1920e3d5408SPeter Wemm 19315589c42SPeter Wemm if (_nc_tracing & TRACE_TPUTS) { 1940e3d5408SPeter Wemm if (outc == _nc_outch) 1950e3d5408SPeter Wemm (void) strcpy(addrbuf, "_nc_outch"); 1960e3d5408SPeter Wemm else 1970e3d5408SPeter Wemm (void) sprintf(addrbuf, "%p", outc); 1980e3d5408SPeter Wemm if (_nc_tputs_trace) { 19915589c42SPeter Wemm _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, 20015589c42SPeter Wemm _nc_visbuf(string), affcnt, addrbuf); 20115589c42SPeter Wemm } else { 20215589c42SPeter Wemm _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); 2030e3d5408SPeter Wemm } 2040e3d5408SPeter Wemm _nc_tputs_trace = (char *) NULL; 2050e3d5408SPeter Wemm } 2060e3d5408SPeter Wemm #endif /* TRACE */ 2070e3d5408SPeter Wemm 2080e3d5408SPeter Wemm if (!VALID_STRING(string)) 2090e3d5408SPeter Wemm return ERR; 2100e3d5408SPeter Wemm 2110e3d5408SPeter Wemm if (cur_term == 0) { 2120e3d5408SPeter Wemm always_delay = FALSE; 2130e3d5408SPeter Wemm normal_delay = TRUE; 2140e3d5408SPeter Wemm } else { 2150e3d5408SPeter Wemm always_delay = (string == bell) || (string == flash_screen); 2160e3d5408SPeter Wemm normal_delay = 2170e3d5408SPeter Wemm !xon_xoff 2180e3d5408SPeter Wemm && padding_baud_rate 21918259542SPeter Wemm #if NCURSES_NO_PADDING 2200e3d5408SPeter Wemm && (SP == 0 || !(SP->_no_padding)) 2210e3d5408SPeter Wemm #endif 2220e3d5408SPeter Wemm && (_nc_baudrate(ospeed) >= padding_baud_rate); 2230e3d5408SPeter Wemm } 2240e3d5408SPeter Wemm 22518259542SPeter Wemm #if BSD_TPUTS 2260e3d5408SPeter Wemm /* 2270e3d5408SPeter Wemm * This ugly kluge deals with the fact that some ancient BSD programs 2280e3d5408SPeter Wemm * (like nethack) actually do the likes of tputs("50") to get delays. 2290e3d5408SPeter Wemm */ 2300e3d5408SPeter Wemm trailpad = 0; 2310e3d5408SPeter Wemm if (isdigit(*string)) { 2320e3d5408SPeter Wemm while (isdigit(*string)) { 2330e3d5408SPeter Wemm trailpad = trailpad * 10 + (*string - '0'); 2340e3d5408SPeter Wemm string++; 2350e3d5408SPeter Wemm } 2360e3d5408SPeter Wemm trailpad *= 10; 2370e3d5408SPeter Wemm if (*string == '.') { 2380e3d5408SPeter Wemm string++; 2390e3d5408SPeter Wemm if (isdigit(*string)) { 2400e3d5408SPeter Wemm trailpad += (*string - '0'); 2410e3d5408SPeter Wemm string++; 2420e3d5408SPeter Wemm } 2430e3d5408SPeter Wemm while (isdigit(*string)) 2440e3d5408SPeter Wemm string++; 2450e3d5408SPeter Wemm } 2460e3d5408SPeter Wemm 2470e3d5408SPeter Wemm if (*string == '*') { 2480e3d5408SPeter Wemm trailpad *= affcnt; 2490e3d5408SPeter Wemm string++; 2500e3d5408SPeter Wemm } 2510e3d5408SPeter Wemm } 2520e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 2530e3d5408SPeter Wemm 2540e3d5408SPeter Wemm my_outch = outc; /* redirect delay_output() */ 2550e3d5408SPeter Wemm while (*string) { 2560e3d5408SPeter Wemm if (*string != '$') 2570e3d5408SPeter Wemm (*outc) (*string); 2580e3d5408SPeter Wemm else { 2590e3d5408SPeter Wemm string++; 2600e3d5408SPeter Wemm if (*string != '<') { 2610e3d5408SPeter Wemm (*outc) ('$'); 2620e3d5408SPeter Wemm if (*string) 2630e3d5408SPeter Wemm (*outc) (*string); 2640e3d5408SPeter Wemm } else { 2650e3d5408SPeter Wemm bool mandatory; 2660e3d5408SPeter Wemm 2670e3d5408SPeter Wemm string++; 2687a69bbfbSPeter Wemm if ((!isdigit(CharOf(*string)) && *string != '.') 2697a69bbfbSPeter Wemm || !strchr(string, '>')) { 2700e3d5408SPeter Wemm (*outc) ('$'); 2710e3d5408SPeter Wemm (*outc) ('<'); 2720e3d5408SPeter Wemm continue; 2730e3d5408SPeter Wemm } 2740e3d5408SPeter Wemm 2750e3d5408SPeter Wemm number = 0; 2767a69bbfbSPeter Wemm while (isdigit(CharOf(*string))) { 2770e3d5408SPeter Wemm number = number * 10 + (*string - '0'); 2780e3d5408SPeter Wemm string++; 2790e3d5408SPeter Wemm } 2800e3d5408SPeter Wemm number *= 10; 2810e3d5408SPeter Wemm if (*string == '.') { 2820e3d5408SPeter Wemm string++; 2837a69bbfbSPeter Wemm if (isdigit(CharOf(*string))) { 2840e3d5408SPeter Wemm number += (*string - '0'); 2850e3d5408SPeter Wemm string++; 2860e3d5408SPeter Wemm } 2877a69bbfbSPeter Wemm while (isdigit(CharOf(*string))) 2880e3d5408SPeter Wemm string++; 2890e3d5408SPeter Wemm } 2900e3d5408SPeter Wemm 2910e3d5408SPeter Wemm mandatory = FALSE; 29215589c42SPeter Wemm while (*string == '*' || *string == '/') { 2930e3d5408SPeter Wemm if (*string == '*') { 2940e3d5408SPeter Wemm number *= affcnt; 2950e3d5408SPeter Wemm string++; 29615589c42SPeter Wemm } else { /* if (*string == '/') */ 2970e3d5408SPeter Wemm mandatory = TRUE; 2980e3d5408SPeter Wemm string++; 2990e3d5408SPeter Wemm } 3000e3d5408SPeter Wemm } 3010e3d5408SPeter Wemm 3020e3d5408SPeter Wemm if (number > 0 3030e3d5408SPeter Wemm && (always_delay 3040e3d5408SPeter Wemm || normal_delay 3050e3d5408SPeter Wemm || mandatory)) 3060e3d5408SPeter Wemm delay_output(number / 10); 3070e3d5408SPeter Wemm 3080e3d5408SPeter Wemm } /* endelse (*string == '<') */ 3090e3d5408SPeter Wemm } /* endelse (*string == '$') */ 3100e3d5408SPeter Wemm 3110e3d5408SPeter Wemm if (*string == '\0') 3120e3d5408SPeter Wemm break; 3130e3d5408SPeter Wemm 3140e3d5408SPeter Wemm string++; 3150e3d5408SPeter Wemm } 3160e3d5408SPeter Wemm 31718259542SPeter Wemm #if BSD_TPUTS 3180e3d5408SPeter Wemm /* 3190e3d5408SPeter Wemm * Emit any BSD-style prefix padding that we've accumulated now. 3200e3d5408SPeter Wemm */ 3210e3d5408SPeter Wemm if (trailpad > 0 3220e3d5408SPeter Wemm && (always_delay || normal_delay)) 3230e3d5408SPeter Wemm delay_output(trailpad / 10); 3240e3d5408SPeter Wemm #endif /* BSD_TPUTS */ 3250e3d5408SPeter Wemm 3260e3d5408SPeter Wemm my_outch = _nc_outch; 3270e3d5408SPeter Wemm return OK; 3280e3d5408SPeter Wemm } 329