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