1 /* $OpenBSD: tgoto.c,v 1.2 2015/11/15 07:12:50 deraadt Exp $ */ 2 /* $NetBSD: tgoto.c,v 1.5 1995/06/05 19:45:54 pk Exp $ */ 3 4 /* 5 * Copyright (c) 1980, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <string.h> 34 #include <curses.h> 35 36 #define CTRL(c) ((c) & 037) 37 38 #define MAXRETURNSIZE 64 39 40 char *UP; 41 char *BC; 42 43 /* 44 * Routine to perform cursor addressing. 45 * CM is a string containing printf type escapes to allow 46 * cursor addressing. We start out ready to print the destination 47 * line, and switch each time we print row or column. 48 * The following escapes are defined for substituting row/column: 49 * 50 * %d as in printf 51 * %2 like %2d 52 * %3 like %3d 53 * %. gives %c hacking special case characters 54 * %+x like %c but adding x first 55 * 56 * The codes below affect the state but don't use up a value. 57 * 58 * %>xy if value > x add y 59 * %r reverses row/column 60 * %i increments row/column (for one origin indexing) 61 * %% gives % 62 * %B BCD (2 decimal digits encoded in one byte) 63 * %D Delta Data (backwards bcd) 64 * 65 * all other characters are ``self-inserting''. 66 */ 67 char * 68 tgoto(char *CM, int destcol, int destline) 69 { 70 static char result[MAXRETURNSIZE]; 71 static char added[10]; 72 char *cp = CM; 73 char *dp = result; 74 int c; 75 int oncol = 0; 76 int which = destline; 77 78 if (cp == 0) { 79 toohard: 80 /* 81 * ``We don't do that under BOZO's big top'' 82 */ 83 return ("OOPS"); 84 } 85 added[0] = 0; 86 while ((c = *cp++) != '\0') { 87 if (c != '%') { 88 if (dp >= &result[MAXRETURNSIZE]) 89 goto toohard; 90 *dp++ = c; 91 continue; 92 } 93 switch (c = *cp++) { 94 95 #ifdef CM_N 96 case 'n': 97 destcol ^= 0140; 98 destline ^= 0140; 99 goto setwhich; 100 #endif 101 102 case 'd': 103 if (which < 10) 104 goto one; 105 if (which < 100) 106 goto two; 107 /* fall into... */ 108 109 case '3': 110 if (dp >= &result[MAXRETURNSIZE]) 111 goto toohard; 112 *dp++ = (which / 100) | '0'; 113 which %= 100; 114 /* fall into... */ 115 116 case '2': 117 two: 118 if (dp >= &result[MAXRETURNSIZE]) 119 goto toohard; 120 *dp++ = which / 10 | '0'; 121 one: 122 if (dp >= &result[MAXRETURNSIZE]) 123 goto toohard; 124 *dp++ = which % 10 | '0'; 125 swap: 126 oncol = 1 - oncol; 127 setwhich: 128 which = oncol ? destcol : destline; 129 continue; 130 131 #ifdef CM_GT 132 case '>': 133 if (which > *cp++) 134 which += *cp++; 135 else 136 cp++; 137 continue; 138 #endif 139 140 case '+': 141 which += *cp++; 142 /* fall into... */ 143 144 case '.': 145 /* 146 * This code is worth scratching your head at for a 147 * while. The idea is that various weird things can 148 * happen to nulls, EOT's, tabs, and newlines by the 149 * tty driver, arpanet, and so on, so we don't send 150 * them if we can help it. 151 * 152 * Tab is taken out to get Ann Arbors to work, otherwise 153 * when they go to column 9 we increment which is wrong 154 * because bcd isn't continuous. We should take out 155 * the rest too, or run the thing through more than 156 * once until it doesn't make any of these, but that 157 * would make termlib (and hence pdp-11 ex) bigger, 158 * and also somewhat slower. This requires all 159 * programs which use termlib to stty tabs so they 160 * don't get expanded. They should do this anyway 161 * because some terminals use ^I for other things, 162 * like nondestructive space. 163 */ 164 if ((which == 0 || which == CTRL('d') || which == '\n') 165 && (oncol || UP)) /* Assumption: backspace works */ 166 /* 167 * Loop needed because newline happens 168 * to be the successor of tab. 169 */ 170 do { 171 if (strlcat(added, oncol ? 172 (BC ? BC : "\b") : UP, 173 sizeof(added)) >= sizeof(added)) 174 goto toohard; 175 which++; 176 } while (which == '\n'); 177 if (dp >= &result[MAXRETURNSIZE]) 178 goto toohard; 179 *dp++ = which; 180 goto swap; 181 182 case 'r': 183 oncol = 1; 184 goto setwhich; 185 186 case 'i': 187 destcol++; 188 destline++; 189 which++; 190 continue; 191 192 case '%': 193 if (dp >= &result[MAXRETURNSIZE]) 194 goto toohard; 195 *dp++ = c; 196 continue; 197 198 #ifdef CM_B 199 case 'B': 200 which = (which/10 << 4) + which%10; 201 continue; 202 #endif 203 204 #ifdef CM_D 205 case 'D': 206 which = which - 2 * (which%16); 207 continue; 208 #endif 209 210 default: 211 goto toohard; 212 } 213 } 214 if (strlcpy(dp, added, sizeof(result) - (dp - result)) 215 >= sizeof(result) - (dp - result)) 216 goto toohard; 217 return (result); 218 } 219