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