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, &regs, &regs);
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, &regs, &regs);
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 }