1 1.6 blymn /* $NetBSD: tputs.c,v 1.6 2021/12/15 21:07:12 blymn Exp $ */ 2 1.1 roy 3 1.1 roy /* 4 1.1 roy * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 1.1 roy * 6 1.1 roy * This code is derived from software contributed to The NetBSD Foundation 7 1.1 roy * by Roy Marples. 8 1.1 roy * 9 1.1 roy * Redistribution and use in source and binary forms, with or without 10 1.1 roy * modification, are permitted provided that the following conditions 11 1.1 roy * are met: 12 1.1 roy * 1. Redistributions of source code must retain the above copyright 13 1.1 roy * notice, this list of conditions and the following disclaimer. 14 1.1 roy * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 roy * notice, this list of conditions and the following disclaimer in the 16 1.1 roy * documentation and/or other materials provided with the distribution. 17 1.1 roy * 18 1.1 roy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 roy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 roy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 roy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 roy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 roy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 roy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 roy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 roy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 roy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 roy */ 29 1.1 roy 30 1.1 roy #include <sys/cdefs.h> 31 1.6 blymn __RCSID("$NetBSD: tputs.c,v 1.6 2021/12/15 21:07:12 blymn Exp $"); 32 1.1 roy 33 1.1 roy #include <assert.h> 34 1.1 roy #include <ctype.h> 35 1.1 roy #include <stdio.h> 36 1.1 roy #include <string.h> 37 1.1 roy #include <term_private.h> 38 1.1 roy #include <term.h> 39 1.1 roy 40 1.2 martin /* 41 1.2 martin * The following array gives the number of tens of milliseconds per 42 1.2 martin * character for each speed as returned by gtty. Thus since 300 43 1.2 martin * baud returns a 7, there are 33.3 milliseconds per char at 300 baud. 44 1.2 martin */ 45 1.1 roy static const short tmspc10[] = { 46 1.1 roy 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5 47 1.1 roy }; 48 1.1 roy 49 1.1 roy short ospeed; 50 1.1 roy char PC; 51 1.1 roy 52 1.1 roy static int 53 1.1 roy _ti_calcdelay(const char **str, int affcnt, int *mand) 54 1.1 roy { 55 1.1 roy int i; 56 1.3 roy 57 1.3 roy i = 0; 58 1.1 roy /* Convert the delay */ 59 1.1 roy while (isdigit(*(const unsigned char *)*str)) 60 1.1 roy i = i * 10 + *(*str)++ - '0'; 61 1.1 roy i *= 10; 62 1.1 roy if (*(*str) == '.') { 63 1.1 roy (*str)++; 64 1.1 roy if (isdigit(*(const unsigned char *)*str)) 65 1.1 roy i += *(*str) - '0'; 66 1.1 roy while (isdigit(*(const unsigned char *)*str)) 67 1.1 roy (*str)++; 68 1.1 roy } 69 1.1 roy if (*(*str) == '*') { 70 1.1 roy (*str)++; 71 1.1 roy i *= affcnt; 72 1.1 roy } else if (*(*str) == '/') { 73 1.1 roy (*str)++; 74 1.1 roy if (mand != NULL) 75 1.1 roy *mand = 1; 76 1.1 roy } 77 1.1 roy return i; 78 1.1 roy } 79 1.1 roy 80 1.1 roy static void 81 1.1 roy _ti_outputdelay(int delay, short os, char pc, 82 1.1 roy int (*outc)(int, void *), void *args) 83 1.1 roy { 84 1.1 roy int mspc10; 85 1.1 roy 86 1.2 martin if (delay < 1 || os < 1 || (size_t)os >= __arraycount(tmspc10)) 87 1.1 roy return; 88 1.3 roy 89 1.1 roy mspc10 = tmspc10[os]; 90 1.1 roy delay += mspc10 / 2; 91 1.1 roy for (delay /= mspc10; delay > 0; delay--) 92 1.1 roy outc(pc, args); 93 1.1 roy } 94 1.1 roy 95 1.1 roy static int 96 1.4 roy _ti_puts(int dodelay, short os, char pc, 97 1.1 roy const char *str, int affcnt, int (*outc)(int, void *), void *args) 98 1.1 roy { 99 1.1 roy int taildelay, delay, mand; 100 1.1 roy 101 1.1 roy if (str == NULL) 102 1.1 roy return OK; 103 1.1 roy 104 1.1 roy taildelay = _ti_calcdelay(&str, affcnt, NULL); 105 1.1 roy 106 1.1 roy /* Output the string with embedded delays */ 107 1.1 roy for (; *str != '\0'; str++) { 108 1.1 roy if (str[0] != '$' || 109 1.1 roy str[1] != '<' || 110 1.1 roy !(isdigit((const unsigned char)str[2]) || str[2] == '.') || 111 1.1 roy strchr(str + 3, '>') == NULL) 112 1.1 roy { 113 1.1 roy outc(*str, args); 114 1.1 roy } else { 115 1.1 roy str += 2; 116 1.1 roy mand = 0; 117 1.1 roy delay = _ti_calcdelay(&str, affcnt, &mand); 118 1.1 roy if (dodelay != 0 || mand != 0) 119 1.1 roy _ti_outputdelay(delay, os, pc, outc, args); 120 1.1 roy } 121 1.1 roy } 122 1.1 roy 123 1.1 roy /* Delay if needed */ 124 1.1 roy if (dodelay) 125 1.1 roy _ti_outputdelay(taildelay, os, pc, outc, args); 126 1.1 roy 127 1.1 roy return OK; 128 1.1 roy } 129 1.1 roy 130 1.1 roy int 131 1.1 roy ti_puts(const TERMINAL *term, const char *str, int affcnt, 132 1.1 roy int (*outc)(int, void *), void *args) 133 1.1 roy { 134 1.1 roy int dodelay; 135 1.1 roy char pc; 136 1.1 roy 137 1.1 roy _DIAGASSERT(term != NULL); 138 1.1 roy _DIAGASSERT(outc != NULL); 139 1.3 roy 140 1.6 blymn if (str == NULL) 141 1.6 blymn return OK; 142 1.6 blymn 143 1.1 roy dodelay = (str == t_bell(term) || 144 1.1 roy str == t_flash_screen(term) || 145 1.1 roy (t_xon_xoff(term) == 0 && t_padding_baud_rate(term) != 0)); 146 1.1 roy 147 1.1 roy if (t_pad_char(term) == NULL) 148 1.1 roy pc = '\0'; 149 1.1 roy else 150 1.1 roy pc = *t_pad_char(term); 151 1.1 roy return _ti_puts(dodelay, term->_ospeed, pc, 152 1.1 roy str, affcnt, outc, args); 153 1.1 roy } 154 1.1 roy 155 1.1 roy int 156 1.1 roy ti_putp(const TERMINAL *term, const char *str) 157 1.1 roy { 158 1.1 roy 159 1.1 roy _DIAGASSERT(term != NULL); 160 1.5 christos return ti_puts(term, str, 1, 161 1.5 christos (int (*)(int, void *))(void *)putchar, NULL); 162 1.1 roy } 163 1.1 roy 164 1.1 roy int 165 1.1 roy tputs(const char *str, int affcnt, int (*outc)(int)) 166 1.1 roy { 167 1.1 roy 168 1.1 roy _DIAGASSERT(outc != NULL); 169 1.1 roy return _ti_puts(1, ospeed, PC, str, affcnt, 170 1.5 christos (int (*)(int, void *))(void *)outc, NULL); 171 1.1 roy } 172 1.3 roy 173 1.1 roy int 174 1.1 roy putp(const char *str) 175 1.1 roy { 176 1.1 roy 177 1.1 roy return tputs(str, 1, putchar); 178 1.1 roy } 179