Commit | Line | Data |
---|---|---|
6468808a DF |
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 | ||
760ebb08 | 7 | #ifndef lint |
6468808a DF |
8 | static char sccsid[] = "@(#)tgoto.c 5.1 (Berkeley) %G%"; |
9 | #endif not lint | |
760ebb08 | 10 | |
760ebb08 SL |
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 | } |