1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)tgoto.c 5.1 (Berkeley) 06/05/85"; 9 #endif not lint 10 11 #define CTRL(c) ('c' & 037) 12 13 #define MAXRETURNSIZE 64 14 15 char *UP; 16 char *BC; 17 18 /* 19 * Routine to perform cursor addressing. 20 * CM is a string containing printf type escapes to allow 21 * cursor addressing. We start out ready to print the destination 22 * line, and switch each time we print row or column. 23 * The following escapes are defined for substituting row/column: 24 * 25 * %d as in printf 26 * %2 like %2d 27 * %3 like %3d 28 * %. gives %c hacking special case characters 29 * %+x like %c but adding x first 30 * 31 * The codes below affect the state but don't use up a value. 32 * 33 * %>xy if value > x add y 34 * %r reverses row/column 35 * %i increments row/column (for one origin indexing) 36 * %% gives % 37 * %B BCD (2 decimal digits encoded in one byte) 38 * %D Delta Data (backwards bcd) 39 * 40 * all other characters are ``self-inserting''. 41 */ 42 char * 43 tgoto(CM, destcol, destline) 44 char *CM; 45 int destcol, destline; 46 { 47 static char result[MAXRETURNSIZE]; 48 static char added[10]; 49 char *cp = CM; 50 register char *dp = result; 51 register int c; 52 int oncol = 0; 53 register int which = destline; 54 55 if (cp == 0) { 56 toohard: 57 /* 58 * ``We don't do that under BOZO's big top'' 59 */ 60 return ("OOPS"); 61 } 62 added[0] = 0; 63 while (c = *cp++) { 64 if (c != '%') { 65 *dp++ = c; 66 continue; 67 } 68 switch (c = *cp++) { 69 70 #ifdef CM_N 71 case 'n': 72 destcol ^= 0140; 73 destline ^= 0140; 74 goto setwhich; 75 #endif 76 77 case 'd': 78 if (which < 10) 79 goto one; 80 if (which < 100) 81 goto two; 82 /* fall into... */ 83 84 case '3': 85 *dp++ = (which / 100) | '0'; 86 which %= 100; 87 /* fall into... */ 88 89 case '2': 90 two: 91 *dp++ = which / 10 | '0'; 92 one: 93 *dp++ = which % 10 | '0'; 94 swap: 95 oncol = 1 - oncol; 96 setwhich: 97 which = oncol ? destcol : destline; 98 continue; 99 100 #ifdef CM_GT 101 case '>': 102 if (which > *cp++) 103 which += *cp++; 104 else 105 cp++; 106 continue; 107 #endif 108 109 case '+': 110 which += *cp++; 111 /* fall into... */ 112 113 case '.': 114 casedot: 115 /* 116 * This code is worth scratching your head at for a 117 * while. The idea is that various weird things can 118 * happen to nulls, EOT's, tabs, and newlines by the 119 * tty driver, arpanet, and so on, so we don't send 120 * them if we can help it. 121 * 122 * Tab is taken out to get Ann Arbors to work, otherwise 123 * when they go to column 9 we increment which is wrong 124 * because bcd isn't continuous. We should take out 125 * the rest too, or run the thing through more than 126 * once until it doesn't make any of these, but that 127 * would make termlib (and hence pdp-11 ex) bigger, 128 * and also somewhat slower. This requires all 129 * programs which use termlib to stty tabs so they 130 * don't get expanded. They should do this anyway 131 * because some terminals use ^I for other things, 132 * like nondestructive space. 133 */ 134 if (which == 0 || which == CTRL(d) || /* which == '\t' || */ which == '\n') { 135 if (oncol || UP) /* Assumption: backspace works */ 136 /* 137 * Loop needed because newline happens 138 * to be the successor of tab. 139 */ 140 do { 141 strcat(added, oncol ? (BC ? BC : "\b") : UP); 142 which++; 143 } while (which == '\n'); 144 } 145 *dp++ = which; 146 goto swap; 147 148 case 'r': 149 oncol = 1; 150 goto setwhich; 151 152 case 'i': 153 destcol++; 154 destline++; 155 which++; 156 continue; 157 158 case '%': 159 *dp++ = c; 160 continue; 161 162 #ifdef CM_B 163 case 'B': 164 which = (which/10 << 4) + which%10; 165 continue; 166 #endif 167 168 #ifdef CM_D 169 case 'D': 170 which = which - 2 * (which%16); 171 continue; 172 #endif 173 174 default: 175 goto toohard; 176 } 177 } 178 strcpy(dp, added); 179 return (result); 180 } 181