Commit | Line | Data |
---|---|---|
6468808a | 1 | /* |
31a14b65 KB |
2 | * Copyright (c) 1980 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
9c1340a5 | 5 | * %sccs.include.redist.c% |
6468808a DF |
6 | */ |
7 | ||
760ebb08 | 8 | #ifndef lint |
9c1340a5 | 9 | static char sccsid[] = "@(#)tgoto.c 5.4 (Berkeley) %G%"; |
31a14b65 | 10 | #endif /* not lint */ |
760ebb08 | 11 | |
3d5c63f1 | 12 | #define CTRL(c) ((c) & 037) |
760ebb08 SL |
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 | */ | |
3d5c63f1 | 135 | if (which == 0 || which == CTRL('d') || /* which == '\t' || */ which == '\n') { |
760ebb08 SL |
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 | } |