1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* Copyright (c) 1979 Regents of the University of California */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 /*LINTLIBRARY*/ 35 36 #include <sys/types.h> 37 #include <ctype.h> 38 #include "curses_inc.h" 39 40 /* 41 * Put the character string cp out, with padding. 42 * The number of affected lines is affcnt, and the routine 43 * used to output one character is outc. 44 */ 45 static char *ocp; 46 47 static char * 48 _tpad(char *, int, int (*)(char)); 49 50 static char * 51 _tpad(char *cp, int affcnt, int (*outc)(char x)) 52 { 53 int delay = 0; 54 char *icp = cp; 55 int ignorexon = 0, doaffcnt = 0; 56 57 #ifdef _VR2_COMPAT_CODE 58 /* 59 * Why is this here? 60 * Because mandatory padding must be used for flash_screen 61 * and bell. We cannot force users to code mandatory padding 62 * in their terminfo entries, as that would break compatibility. 63 * We therefore, do it here. 64 * 65 * When compatibility is to be broken, his will go away 66 * and users will be informed that they MUST use mandatory 67 * padding for flash and bell. 68 */ 69 if (ocp == bell || ocp == flash_screen) 70 ignorexon = TRUE; 71 #endif /* _VR2_COMPAT_CODE */ 72 73 /* Eat initial $< */ 74 cp += 2; 75 76 /* Convert the number representing the delay. */ 77 if (isdigit(*cp)) { 78 do 79 delay = delay * 10 + *cp++ - '0'; 80 while (isdigit(*cp)); 81 } 82 delay *= 10; 83 if (*cp == '.') { 84 cp++; 85 if (isdigit(*cp)) 86 delay += *cp - '0'; 87 /* Only one digit to the right of the decimal point. */ 88 while (isdigit(*cp)) 89 cp++; 90 } 91 92 /* 93 * If the delay is followed by a `*', then 94 * multiply by the affected lines count. 95 * If the delay is followed by a '/', then 96 * the delay is done irregardless of xon/xoff. 97 */ 98 /*CONSTCOND*/ 99 while (TRUE) { 100 if (*cp == '/') 101 ignorexon = TRUE; 102 else 103 if (*cp == '*') 104 doaffcnt = TRUE; 105 else 106 break; 107 cp++; 108 } 109 if (doaffcnt) 110 delay *= affcnt; 111 if (*cp == '>') 112 cp++; /* Eat trailing '>' */ 113 else { 114 /* 115 * We got a "$<" with no ">". This is usually caused by 116 * a cursor addressing sequence that happened to generate 117 * $ < . To avoid an infinite loop, we output the $ here 118 * and pass back the rest. 119 */ 120 (*outc)(*icp++); 121 return (icp); 122 } 123 124 /* 125 * If no delay needed, or output speed is 126 * not comprehensible, then don't try to delay. 127 */ 128 if (delay == 0) 129 return (cp); 130 /* 131 * Let handshaking take care of it - no extra cpu load from pads. 132 * Also, this will be more optimal since the pad info is usually 133 * worst case. We only use padding info for such terminals to 134 * estimate the cost of a capability in choosing the cheapest one. 135 * Some capabilities, such as flash_screen, really want the 136 * padding irregardless. 137 */ 138 if (xon_xoff && !ignorexon) 139 return (cp); 140 (void) _delay(delay, outc); 141 return (cp); 142 } 143 144 int 145 tputs(char *cp, int affcnt, int (*outc)(char)) 146 { 147 if (cp != 0) { 148 ocp = cp; 149 150 /* The guts of the string. */ 151 while (*cp) 152 if (*cp == '$' && cp[1] == '<') 153 cp = _tpad(cp, affcnt, outc); 154 else 155 (*outc)(*cp++); 156 } 157 return (OK); 158 } 159