Mercurial > ~dholland > hg > ag > index.cgi
comparison examples/dsl/screen.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children | aab9ff6af791 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /***** | |
2 | |
3 AnaGram Programming Examples | |
4 | |
5 A Dos Script Language | |
6 Screen Display Module | |
7 | |
8 Copyright 1993 Parsifal Software. All Rights Reserved. | |
9 | |
10 This software is provided 'as-is', without any express or implied | |
11 warranty. In no event will the authors be held liable for any damages | |
12 arising from the use of this software. | |
13 | |
14 Permission is granted to anyone to use this software for any purpose, | |
15 including commercial applications, and to alter it and redistribute it | |
16 freely, subject to the following restrictions: | |
17 | |
18 1. The origin of this software must not be misrepresented; you must not | |
19 claim that you wrote the original software. If you use this software | |
20 in a product, an acknowledgment in the product documentation would be | |
21 appreciated but is not required. | |
22 2. Altered source versions must be plainly marked as such, and must not be | |
23 misrepresented as being the original software. | |
24 3. This notice may not be removed or altered from any source distribution. | |
25 | |
26 *****/ | |
27 | |
28 | |
29 #include "screen.h" | |
30 #include "pair.h" | |
31 #include <assert.h> | |
32 #include "util.h" | |
33 | |
34 #ifdef __MSDOS__ | |
35 #include <dos.h> | |
36 #else | |
37 | |
38 /* This is only meant to compile, not run. (Unix, Windows) */ | |
39 #define far | |
40 union REGS { struct { unsigned short ah, bh, dl, dh; } h; }; | |
41 void INT(unsigned long, union REGS *, union REGS *) {} | |
42 #endif | |
43 | |
44 /***** | |
45 | |
46 Video display class | |
47 | |
48 This class is defined to provide screen initialization and access to the | |
49 screen. It is not used outside this module. | |
50 | |
51 *****/ | |
52 | |
53 class video_display_class { | |
54 public: | |
55 char_cell far *base; | |
56 pair <int> size; | |
57 video_display_class() | |
58 : base((char_cell *)(COLOR_ADAPTER_ADDRESS)) | |
59 , size(80,25) | |
60 {} | |
61 | |
62 // Access a particular char_cell in the display | |
63 | |
64 char_cell &operator[] (pair<int> p) { | |
65 assert(p < size); | |
66 return base[p.x + size.x * p.y]; | |
67 } | |
68 | |
69 pair<int> get_cursor(void) { | |
70 union REGS regs; | |
71 regs.h.ah = 3; | |
72 regs.h.bh = 0; | |
73 INT(0x10, ®s, ®s); | |
74 return pair<int>(regs.h.dl, regs.h.dh); | |
75 } | |
76 | |
77 void set_cursor(pair<int> cp) { | |
78 union REGS regs; | |
79 regs.h.ah = 2; | |
80 regs.h.bh = 0; | |
81 regs.h.dl = (char) cp.x; | |
82 regs.h.dh = (char) cp.y; | |
83 INT(0x10, ®s, ®s); | |
84 } | |
85 }; | |
86 | |
87 // This should be the only instance of a video display class | |
88 | |
89 static video_display_class display; | |
90 | |
91 | |
92 // Protect display class exists to save and restore screen | |
93 | |
94 protect_display::protect_display() { | |
95 n = display.size.x * display.size.y; | |
96 p = new char_cell[n]; | |
97 copy(p,display.base,n); | |
98 cursor_position = display.get_cursor(); | |
99 } | |
100 | |
101 protect_display::~protect_display() { | |
102 copy(display.base, p, n); | |
103 delete [] p; | |
104 display.set_cursor(cursor_position); | |
105 } | |
106 | |
107 | |
108 // Screen Rectangle class | |
109 | |
110 | |
111 // Set cursor in a screen rectangle | |
112 | |
113 screen_rect &screen_rect::set_cursor(const int x, const int y) { | |
114 assert (x < size.x && y < size.y); | |
115 pair<int> where(pos.x + x, pos.y + y); | |
116 display.set_cursor(where); | |
117 return *this; | |
118 } | |
119 | |
120 /***** | |
121 | |
122 Create a screen rectangle at a particular location in the display | |
123 Rectangle consists of entire screen below and to the right of the | |
124 specified coordinates. | |
125 | |
126 *****/ | |
127 | |
128 screen_rect at(int x, int y, int jm) { | |
129 screen_rect r; | |
130 r.pos = pair<int>(x,y); | |
131 assert(r.pos < display.size); | |
132 r.size = display.size - r.pos; | |
133 r.jm.x = (jm/10) & 3; | |
134 r.jm.y = (jm%10) & 3; | |
135 return r; | |
136 } | |
137 | |
138 screen_rect screen_rect::at(int x, int y, int jm) { | |
139 screen_rect r = *this; | |
140 r.pos = pos + pair<int>(x,y); | |
141 assert(r.pos < pos + size); | |
142 r.size = size - pair<int>(x,y); | |
143 r.jm.x = (jm/10) & 3; | |
144 r.jm.y = (jm%10) & 3; | |
145 return r; | |
146 } | |
147 | |
148 screen_rect screen_rect::rect(int w, int d, int jm) { | |
149 screen_rect b = *this; | |
150 pair <int> p = b.pos; | |
151 pair <int> q = b.pos; | |
152 int jmy = (jm % 10) & 3; | |
153 int jmx = (jm / 10) & 3; | |
154 | |
155 if (w < b.size.x) b.size.x = w; | |
156 if (d < b.size.y) b.size.y = d; | |
157 b.pos.x += (size.x - b.size.x)*jmx/2; | |
158 b.pos.y += (size.y - b.size.y)*jmy/2; | |
159 return b; | |
160 } | |
161 | |
162 screen_rect box(screen_rect r){ | |
163 screen_rect b = r; | |
164 pair <int> p = b.pos; | |
165 pair <int> q = b.pos; | |
166 | |
167 q.y += b.size.y - 1; | |
168 display[p] = 218; | |
169 display[q] = 192; | |
170 q.x++; | |
171 p.x++; | |
172 while (p.x < b.pos.x + b.size.x - 1) { | |
173 display[p] = 196; | |
174 display[q] = 196; | |
175 p.x++; | |
176 q.x++; | |
177 } | |
178 display[p] = 191; | |
179 display[q] = 217; | |
180 p = b.pos; | |
181 p.y++; | |
182 q = p; | |
183 q.x += b.size.x - 1; | |
184 while (p.y < b.pos.y + b.size.y - 1) { | |
185 display[p] = 179; | |
186 display[q] = 179; | |
187 p.y++; | |
188 q.y++; | |
189 } | |
190 b.size.x -= 4; | |
191 b.size.y -= 2; | |
192 b.pos.x += 2; | |
193 b.pos.y++; | |
194 return b; | |
195 } | |
196 | |
197 | |
198 screen_rect line(int x, int y, int w, int jm) { | |
199 screen_rect r; | |
200 char_cell p; | |
201 | |
202 if (w + x > display.size.x) w = display.size.x - x; | |
203 r.pos = pair<int>(x,y); | |
204 r.size = pair<int>(w,1); | |
205 r.jm.x = (jm/10) & 3; | |
206 r.jm.y = (jm%10) & 3; | |
207 assert(r.pos + r.size <= display.size); | |
208 return r; | |
209 } | |
210 | |
211 screen_rect screen_rect::line(int x, int y, int w, int jm) const { | |
212 screen_rect r; | |
213 char_cell p; | |
214 | |
215 if (w + x > size.x) w = size.x - x; | |
216 r.pos = pos + pair<int>(x,y); | |
217 r.size = pair<int>(w,1); | |
218 r.jm.x = (jm/10) & 3; | |
219 r.jm.y = (jm%10) & 3; | |
220 assert(r.pos + r.size <= display.size); | |
221 return r; | |
222 } | |
223 | |
224 /***** | |
225 | |
226 Set all char_cells in a rectangle to a given value | |
227 | |
228 *****/ | |
229 | |
230 screen_rect &screen_rect:: operator << (const char_cell &p) { | |
231 pair<int> limit = pos + size; | |
232 pair<int> i = pos; | |
233 pair<int> j = pos; | |
234 while (i.y < limit.y) { | |
235 j = i; | |
236 while (j.x < limit.x) display[j] = p, j.x++; | |
237 i.y++; | |
238 } | |
239 return *this; | |
240 } | |
241 | |
242 /***** | |
243 | |
244 Set all char_cells in a rectangle to a given color | |
245 | |
246 *****/ | |
247 | |
248 screen_rect &screen_rect::tint(int color) { | |
249 pair<int> limit = pos + size; | |
250 pair<int> i = pos; | |
251 pair<int> j = pos; | |
252 while (i.y < limit.y) { | |
253 j = i; | |
254 while (j.x < limit.x) display[j].color = (char) color, j.x++; | |
255 i.y++; | |
256 } | |
257 return *this; | |
258 } | |
259 | |
260 screen_rect &screen_rect::tint(int fg, int bg) { | |
261 tint(COLOR(fg,bg)); | |
262 return *this; | |
263 } | |
264 | |
265 | |
266 /***** | |
267 | |
268 Set all display characters within a rectangle to a given value | |
269 | |
270 *****/ | |
271 | |
272 screen_rect &screen_rect::operator << (const int c) { | |
273 pair<int> limit = pos + size; | |
274 pair<int> i = pos; | |
275 pair<int> j = pos; | |
276 while (i.y < limit.y) { | |
277 j = i; | |
278 while (j.x < limit.x) display[j].data = (char) c, j.x++; | |
279 i.y++; | |
280 } | |
281 return *this; | |
282 } | |
283 | |
284 /***** | |
285 | |
286 Write a string into a screen rectangle, taking account of desired | |
287 justification mode. | |
288 | |
289 string_size returns the size (width x height) of the string. | |
290 str_size adjusts this down, if necesary, to the size of the rectangle | |
291 white is the amount of white space, horizontal and vertical to be | |
292 distributed. | |
293 loc is the position where the string display should begin | |
294 limit is the location where the string should be clipped | |
295 | |
296 | |
297 *****/ | |
298 | |
299 static int n_lines(const char *s) { | |
300 int n = 0; | |
301 if (s == NULL) return 0; | |
302 while (*s) { | |
303 while (*s && *s != '\n') s++; | |
304 if (*s == '\n') s++; | |
305 n++; | |
306 } | |
307 return n; | |
308 } | |
309 | |
310 static int line_width(const char *s) { | |
311 int n = 0; | |
312 while (*s && *s != '\n') n++, s++; | |
313 return n; | |
314 } | |
315 | |
316 screen_rect &screen_rect ::operator << (const char *s) { | |
317 pair<int> loc = pos; | |
318 pair<int> limit = pos + size; | |
319 int string_height = n_lines(s); | |
320 int blank_lines = size.y > string_height ? size.y - string_height : 0; | |
321 screen_rect r = *this; | |
322 | |
323 // Blank lines at top of rectangle | |
324 r.size.y = blank_lines*jm.y/2; | |
325 r << ' '; | |
326 | |
327 | |
328 // Text segment | |
329 loc.y += r.size.y; | |
330 if (s != NULL) while (*s && loc.y < limit.y) { | |
331 pair<int> p = loc; | |
332 int width = line_width(s); | |
333 int n = (size.x > width ? size.x - width : 0) * jm.x / 2; | |
334 | |
335 // Leading blanks | |
336 while (n--) { | |
337 display[p].data = ' '; | |
338 p.x++; | |
339 } | |
340 // Text | |
341 while ( *s && *s != '\n' && p.x < limit.x) { | |
342 display[p].data = *s++; | |
343 p.x++; | |
344 } | |
345 | |
346 // Trailing blanks | |
347 while (p.x < limit.x) { | |
348 display[p].data = ' '; | |
349 p.x++; | |
350 } | |
351 | |
352 // Skip to end of line in string | |
353 while (*s && *s != '\n') s++; | |
354 if (*s == '\n') s++; | |
355 loc.y++; | |
356 } | |
357 | |
358 // Blank lines at bottom of rectangle | |
359 r.pos = loc; | |
360 r.size = limit - r.pos; | |
361 r << ' '; | |
362 | |
363 return *this; | |
364 } | |
365 | |
366 | |
367 char_cell *contents(const screen_rect &r) { | |
368 char_cell *c = new char_cell[r.size.x*r.size.y]; | |
369 pair<int> pos = r.pos; | |
370 pair<int> limit = r.pos + r.size; | |
371 int k = 0; | |
372 while (pos.y < limit.y) { | |
373 pair<int> p = pos; | |
374 while (p.x < limit.x) { | |
375 c[k++] = display[p]; | |
376 p.x++; | |
377 } | |
378 pos.y++; | |
379 } | |
380 return c; | |
381 } | |
382 | |
383 screen_rect &screen_rect::operator << (const char_cell *c) { | |
384 pair<int> rpos = pos; | |
385 pair<int> limit = pos + size; | |
386 int k = 0; | |
387 while (rpos.y < limit.y) { | |
388 pair<int> p = rpos; | |
389 while (p.x < limit.x) { | |
390 display[p] = c[k++]; | |
391 p.x++; | |
392 } | |
393 rpos.y++; | |
394 } | |
395 return *this; | |
396 } |