Mercurial > ~dholland > hg > ag > index.cgi
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/dsl/screen.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,396 @@ +/***** + + AnaGram Programming Examples + + A Dos Script Language + Screen Display Module + + Copyright 1993 Parsifal Software. All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*****/ + + +#include "screen.h" +#include "pair.h" +#include <assert.h> +#include "util.h" + +#ifdef __MSDOS__ +#include <dos.h> +#else + +/* This is only meant to compile, not run. (Unix, Windows) */ +#define far +union REGS { struct { unsigned short ah, bh, dl, dh; } h; }; +void INT(unsigned long, union REGS *, union REGS *) {} +#endif + +/***** + + Video display class + + This class is defined to provide screen initialization and access to the + screen. It is not used outside this module. + +*****/ + +class video_display_class { +public: + char_cell far *base; + pair <int> size; + video_display_class() + : base((char_cell *)(COLOR_ADAPTER_ADDRESS)) + , size(80,25) + {} + +// Access a particular char_cell in the display + + char_cell &operator[] (pair<int> p) { + assert(p < size); + return base[p.x + size.x * p.y]; + } + + pair<int> get_cursor(void) { + union REGS regs; + regs.h.ah = 3; + regs.h.bh = 0; + INT(0x10, ®s, ®s); + return pair<int>(regs.h.dl, regs.h.dh); + } + + void set_cursor(pair<int> cp) { + union REGS regs; + regs.h.ah = 2; + regs.h.bh = 0; + regs.h.dl = (char) cp.x; + regs.h.dh = (char) cp.y; + INT(0x10, ®s, ®s); + } +}; + +// This should be the only instance of a video display class + +static video_display_class display; + + +// Protect display class exists to save and restore screen + +protect_display::protect_display() { + n = display.size.x * display.size.y; + p = new char_cell[n]; + copy(p,display.base,n); + cursor_position = display.get_cursor(); +} + +protect_display::~protect_display() { + copy(display.base, p, n); + delete [] p; + display.set_cursor(cursor_position); +} + + +// Screen Rectangle class + + +// Set cursor in a screen rectangle + +screen_rect &screen_rect::set_cursor(const int x, const int y) { + assert (x < size.x && y < size.y); + pair<int> where(pos.x + x, pos.y + y); + display.set_cursor(where); + return *this; +} + +/***** + + Create a screen rectangle at a particular location in the display + Rectangle consists of entire screen below and to the right of the + specified coordinates. + +*****/ + +screen_rect at(int x, int y, int jm) { + screen_rect r; + r.pos = pair<int>(x,y); + assert(r.pos < display.size); + r.size = display.size - r.pos; + r.jm.x = (jm/10) & 3; + r.jm.y = (jm%10) & 3; + return r; +} + +screen_rect screen_rect::at(int x, int y, int jm) { + screen_rect r = *this; + r.pos = pos + pair<int>(x,y); + assert(r.pos < pos + size); + r.size = size - pair<int>(x,y); + r.jm.x = (jm/10) & 3; + r.jm.y = (jm%10) & 3; + return r; +} + +screen_rect screen_rect::rect(int w, int d, int jm) { + screen_rect b = *this; + pair <int> p = b.pos; + pair <int> q = b.pos; + int jmy = (jm % 10) & 3; + int jmx = (jm / 10) & 3; + + if (w < b.size.x) b.size.x = w; + if (d < b.size.y) b.size.y = d; + b.pos.x += (size.x - b.size.x)*jmx/2; + b.pos.y += (size.y - b.size.y)*jmy/2; + return b; +} + +screen_rect box(screen_rect r){ + screen_rect b = r; + pair <int> p = b.pos; + pair <int> q = b.pos; + + q.y += b.size.y - 1; + display[p] = 218; + display[q] = 192; + q.x++; + p.x++; + while (p.x < b.pos.x + b.size.x - 1) { + display[p] = 196; + display[q] = 196; + p.x++; + q.x++; + } + display[p] = 191; + display[q] = 217; + p = b.pos; + p.y++; + q = p; + q.x += b.size.x - 1; + while (p.y < b.pos.y + b.size.y - 1) { + display[p] = 179; + display[q] = 179; + p.y++; + q.y++; + } + b.size.x -= 4; + b.size.y -= 2; + b.pos.x += 2; + b.pos.y++; + return b; +} + + +screen_rect line(int x, int y, int w, int jm) { + screen_rect r; + char_cell p; + + if (w + x > display.size.x) w = display.size.x - x; + r.pos = pair<int>(x,y); + r.size = pair<int>(w,1); + r.jm.x = (jm/10) & 3; + r.jm.y = (jm%10) & 3; + assert(r.pos + r.size <= display.size); + return r; +} + +screen_rect screen_rect::line(int x, int y, int w, int jm) const { + screen_rect r; + char_cell p; + + if (w + x > size.x) w = size.x - x; + r.pos = pos + pair<int>(x,y); + r.size = pair<int>(w,1); + r.jm.x = (jm/10) & 3; + r.jm.y = (jm%10) & 3; + assert(r.pos + r.size <= display.size); + return r; +} + +/***** + + Set all char_cells in a rectangle to a given value + +*****/ + +screen_rect &screen_rect:: operator << (const char_cell &p) { + pair<int> limit = pos + size; + pair<int> i = pos; + pair<int> j = pos; + while (i.y < limit.y) { + j = i; + while (j.x < limit.x) display[j] = p, j.x++; + i.y++; + } + return *this; +} + +/***** + + Set all char_cells in a rectangle to a given color + +*****/ + +screen_rect &screen_rect::tint(int color) { + pair<int> limit = pos + size; + pair<int> i = pos; + pair<int> j = pos; + while (i.y < limit.y) { + j = i; + while (j.x < limit.x) display[j].color = (char) color, j.x++; + i.y++; + } + return *this; +} + +screen_rect &screen_rect::tint(int fg, int bg) { + tint(COLOR(fg,bg)); + return *this; +} + + +/***** + + Set all display characters within a rectangle to a given value + +*****/ + +screen_rect &screen_rect::operator << (const int c) { + pair<int> limit = pos + size; + pair<int> i = pos; + pair<int> j = pos; + while (i.y < limit.y) { + j = i; + while (j.x < limit.x) display[j].data = (char) c, j.x++; + i.y++; + } + return *this; +} + +/***** + + Write a string into a screen rectangle, taking account of desired + justification mode. + + string_size returns the size (width x height) of the string. + str_size adjusts this down, if necesary, to the size of the rectangle + white is the amount of white space, horizontal and vertical to be + distributed. + loc is the position where the string display should begin + limit is the location where the string should be clipped + + +*****/ + +static int n_lines(const char *s) { + int n = 0; + if (s == NULL) return 0; + while (*s) { + while (*s && *s != '\n') s++; + if (*s == '\n') s++; + n++; + } + return n; +} + +static int line_width(const char *s) { + int n = 0; + while (*s && *s != '\n') n++, s++; + return n; +} + +screen_rect &screen_rect ::operator << (const char *s) { + pair<int> loc = pos; + pair<int> limit = pos + size; + int string_height = n_lines(s); + int blank_lines = size.y > string_height ? size.y - string_height : 0; + screen_rect r = *this; + +// Blank lines at top of rectangle + r.size.y = blank_lines*jm.y/2; + r << ' '; + + +// Text segment + loc.y += r.size.y; + if (s != NULL) while (*s && loc.y < limit.y) { + pair<int> p = loc; + int width = line_width(s); + int n = (size.x > width ? size.x - width : 0) * jm.x / 2; + +// Leading blanks + while (n--) { + display[p].data = ' '; + p.x++; + } +// Text + while ( *s && *s != '\n' && p.x < limit.x) { + display[p].data = *s++; + p.x++; + } + +// Trailing blanks + while (p.x < limit.x) { + display[p].data = ' '; + p.x++; + } + +// Skip to end of line in string + while (*s && *s != '\n') s++; + if (*s == '\n') s++; + loc.y++; + } + +// Blank lines at bottom of rectangle + r.pos = loc; + r.size = limit - r.pos; + r << ' '; + + return *this; +} + + +char_cell *contents(const screen_rect &r) { + char_cell *c = new char_cell[r.size.x*r.size.y]; + pair<int> pos = r.pos; + pair<int> limit = r.pos + r.size; + int k = 0; + while (pos.y < limit.y) { + pair<int> p = pos; + while (p.x < limit.x) { + c[k++] = display[p]; + p.x++; + } + pos.y++; + } + return c; +} + +screen_rect &screen_rect::operator << (const char_cell *c) { + pair<int> rpos = pos; + pair<int> limit = pos + size; + int k = 0; + while (rpos.y < limit.y) { + pair<int> p = rpos; + while (p.x < limit.x) { + display[p] = c[k++]; + p.x++; + } + rpos.y++; + } + return *this; +}