432 lines
7.5 KiB
C++
432 lines
7.5 KiB
C++
#include "stdafx.h"
|
|
#include "defs.h"
|
|
|
|
// total_h sum of the heights of all the items in the display queue
|
|
//
|
|
// display_y the display queue y coordinate that maps to the screen
|
|
//
|
|
// maxy_y the maximum value that display_y can have
|
|
//
|
|
// total_w the maximum width including right and left margins
|
|
|
|
extern int line_height;
|
|
extern int left_margin;
|
|
extern int right_margin;
|
|
extern int display_x;
|
|
extern int display_y;
|
|
extern int display_height;
|
|
extern int display_width;
|
|
extern int max_x;
|
|
extern int max_y;
|
|
extern int total_w;
|
|
extern int total_h;
|
|
extern int update_display_request;
|
|
|
|
extern int text_width(int, char *);
|
|
|
|
#define SMALL_FONT 1
|
|
#define DEFAULT_FONT 2
|
|
|
|
#define DRAW_HRULE 20
|
|
#define DRAW_LEFT_BRACKET 21
|
|
#define DRAW_RIGHT_BRACKET 22
|
|
#define DRAW_LINE 23
|
|
#define DRAW_POINT 24
|
|
#define DRAW_BOX 25
|
|
#define DRAW_LABEL 26
|
|
|
|
#define MAXHIST 10001
|
|
|
|
extern int test_flag;
|
|
int term_flag;
|
|
|
|
// type
|
|
//
|
|
// 0 print string
|
|
//
|
|
// 1 display
|
|
|
|
struct {
|
|
unsigned char type, attr;
|
|
int w, h;
|
|
union {
|
|
char *s;
|
|
unsigned char *d;
|
|
} u;
|
|
} term[MAXHIST];
|
|
|
|
static int head, tail, len;
|
|
static char buf[1000];
|
|
|
|
#define OUTBUFLEN 10000
|
|
char out_buf[OUTBUFLEN + 1];
|
|
int out_count;
|
|
|
|
static void printcharf(int);
|
|
static void advance(void);
|
|
|
|
void
|
|
printchar_nowrap(int c)
|
|
{
|
|
if (c == '\n' || len < 80)
|
|
printchar(c);
|
|
}
|
|
|
|
static int
|
|
breaking_char(int c)
|
|
{
|
|
switch (c) {
|
|
case ' ':
|
|
case '+':
|
|
case '-':
|
|
case '*':
|
|
case '/':
|
|
case ',':
|
|
case '(':
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
printchar(int c)
|
|
{
|
|
if (test_flag && out_count < OUTBUFLEN)
|
|
out_buf[out_count++] = c;
|
|
printcharf(c);
|
|
// try not to break tokens but must break at 80 in case it's a huge number
|
|
if (len >= 60 && breaking_char(c) || len >= 80)
|
|
printcharf('\n');
|
|
}
|
|
|
|
static void
|
|
printcharf(int c)
|
|
{
|
|
char *s;
|
|
|
|
if (c == '\n') {
|
|
s = (char *) malloc(len + 1);
|
|
if (s == NULL)
|
|
return;
|
|
buf[len] = 0;
|
|
strcpy(s, buf);
|
|
len = 0;
|
|
term[tail].type = 0;
|
|
term[tail].attr = term_flag;
|
|
term[tail].u.s = s;
|
|
term[tail].w = text_width(DEFAULT_FONT, s);
|
|
term[tail].h = line_height;
|
|
total_h += line_height;
|
|
if (total_h - max_y > display_height)
|
|
max_y = total_h - display_height;
|
|
display_y = max_y;
|
|
advance();
|
|
return;
|
|
}
|
|
|
|
if (len < (int) sizeof buf)
|
|
buf[len++] = c;
|
|
}
|
|
|
|
void
|
|
printstr(char *s)
|
|
{
|
|
while (*s)
|
|
printchar(*s++);
|
|
}
|
|
|
|
void
|
|
clear_term(void)
|
|
{
|
|
while (head != tail) {
|
|
free(term[head].u.s);
|
|
head = (head + 1) % MAXHIST;
|
|
}
|
|
head = 0;
|
|
tail = 0;
|
|
display_x = 0;
|
|
display_y = 0;
|
|
max_x = 0;
|
|
max_y = 0;
|
|
total_w = 0;
|
|
total_h = 0;
|
|
update_display_request = 1;
|
|
}
|
|
|
|
void
|
|
shipout(unsigned char *d, int w, int h)
|
|
{
|
|
term[tail].type = 1;
|
|
term[tail].attr = 0;
|
|
term[tail].u.d = d;
|
|
term[tail].w = w;
|
|
term[tail].h = h + line_height;
|
|
total_h += h + line_height;
|
|
if (total_h - max_y > display_height)
|
|
max_y = total_h - display_height;
|
|
display_y = max_y;
|
|
advance();
|
|
}
|
|
|
|
static void
|
|
advance(void)
|
|
{
|
|
int h;
|
|
tail = (tail + 1) % MAXHIST;
|
|
if (tail == head) {
|
|
h = term[head].h;
|
|
free(term[head].u.s);
|
|
head = (head + 1) % MAXHIST;
|
|
total_h -= h;
|
|
max_y -= h;
|
|
display_y -= h;
|
|
if (max_y < 0)
|
|
max_y = 0;
|
|
if (display_y < 0)
|
|
display_y = 0;
|
|
}
|
|
update_display_request = 1;
|
|
}
|
|
|
|
extern void drawstring(int, int, char *, int);
|
|
extern void drawpixel(int, int, int, int);
|
|
extern void draw_left_bracket(int, int, int, int);
|
|
extern void draw_right_bracket(int, int, int, int);
|
|
extern void draw_line(int, int, int, int);
|
|
|
|
static int find_start_index(void);
|
|
static void draw(int);
|
|
static int yy;
|
|
|
|
void
|
|
draw_display(void)
|
|
{
|
|
int i;
|
|
update_display_request = 0;
|
|
i = find_start_index();
|
|
total_w = 0;
|
|
while (i != tail && yy < display_height) {
|
|
draw(i);
|
|
i = (i + 1) % MAXHIST;
|
|
}
|
|
max_x = total_w - display_width;
|
|
if (max_x < display_x)
|
|
max_x = display_x;
|
|
}
|
|
|
|
// find the top of the term
|
|
|
|
static int
|
|
find_start_index(void)
|
|
{
|
|
int indx, y;
|
|
|
|
indx = tail;
|
|
|
|
// back up until y <= display_y
|
|
|
|
y = total_h;
|
|
|
|
while (1) {
|
|
|
|
if (y <= display_y)
|
|
break;
|
|
|
|
if (indx == head)
|
|
break;
|
|
|
|
indx = (indx + MAXHIST - 1) % MAXHIST;
|
|
|
|
y -= term[indx].h;
|
|
}
|
|
|
|
// if too tall then negative start_y
|
|
|
|
if (y - display_y < 0)
|
|
yy = y - display_y;
|
|
else
|
|
yy = 0;
|
|
|
|
return indx;
|
|
}
|
|
|
|
extern void draw_text(int, int, int, char *, int);
|
|
extern void draw_hrule(int, int, int);
|
|
extern void draw_point(int, int);
|
|
extern void draw_box(int, int, int, int);
|
|
extern void use_graph_pen(void);
|
|
extern void use_normal_pen(void);
|
|
|
|
#define N(x) (((int) d[k + x] << 24) | ((int) d[k + x + 1] << 16) | ((int) d[k + x + 2]) << 8 | ((int) d[k + x + 3]))
|
|
|
|
static void
|
|
draw(int i)
|
|
{
|
|
int cmd, h, k, len, w, xx, x, x1, x2, y, y1, y2;
|
|
unsigned char *d;
|
|
|
|
w = term[i].w;
|
|
|
|
switch (term[i].type) {
|
|
|
|
case 0:
|
|
if (term[i].u.s[0]) {
|
|
xx = left_margin;
|
|
if (xx + w + right_margin > total_w)
|
|
total_w = xx + w + right_margin;
|
|
xx -= display_x;
|
|
len = (int) strlen(term[i].u.s);
|
|
draw_text(DEFAULT_FONT, xx, yy, term[i].u.s, len);
|
|
}
|
|
yy += line_height;
|
|
break;
|
|
|
|
case 1:
|
|
yy += line_height / 2;
|
|
d = term[i].u.d;
|
|
xx = (display_width - w) / 2; // center it
|
|
if (xx < left_margin)
|
|
xx = left_margin;
|
|
if (xx + w + right_margin > total_w)
|
|
total_w = xx + w + right_margin;
|
|
xx -= display_x;
|
|
k = 0;
|
|
while (1) {
|
|
cmd = d[k];
|
|
if (cmd == 0)
|
|
break;
|
|
switch (cmd) {
|
|
case 1:
|
|
use_normal_pen();
|
|
x = 256 * d[k + 1] + d[k + 2];
|
|
y = 256 * d[k + 3] + d[k + 4];
|
|
if (x > 32767)
|
|
x -= 65536;
|
|
if (y > 32767)
|
|
y -= 65536;
|
|
len = d[k + 5];
|
|
draw_text(SMALL_FONT, xx + x, yy + y, (char *) d + k + 6, len); // small font
|
|
k = k + 6 + len;
|
|
break;
|
|
case 2: // default font
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
use_normal_pen();
|
|
x = N(1);
|
|
y = N(5);
|
|
len = N(9);
|
|
draw_text(cmd, xx + x, yy + y, (char *) d + k + 13, len);
|
|
k = k + 13 + len;
|
|
break;
|
|
case DRAW_HRULE:
|
|
use_normal_pen();
|
|
x = N(1);
|
|
y = N(5);
|
|
w = N(9);
|
|
h = N(13);
|
|
draw_hrule(xx + x, yy + y, w);
|
|
k += 17;
|
|
break;
|
|
case DRAW_LEFT_BRACKET:
|
|
use_normal_pen();
|
|
x = N(1);
|
|
y = N(5);
|
|
w = N(9);
|
|
h = N(13);
|
|
draw_left_bracket(xx + x, yy + y, w, h);
|
|
k += 17;
|
|
break;
|
|
case DRAW_RIGHT_BRACKET:
|
|
use_normal_pen();
|
|
x = N(1);
|
|
y = N(5);
|
|
w = N(9);
|
|
h = N(13);
|
|
draw_right_bracket(xx + x, yy + y, w, h);
|
|
k += 17;
|
|
break;
|
|
case DRAW_LINE:
|
|
use_normal_pen();
|
|
x1 = 256 * d[k + 1] + d[k + 2];
|
|
y1 = 256 * d[k + 3] + d[k + 4];
|
|
x2 = 256 * d[k + 5] + d[k + 6];
|
|
y2 = 256 * d[k + 7] + d[k + 8];
|
|
draw_line(xx + x1, yy + y1, xx + x2, yy + y2);
|
|
k += 9;
|
|
break;
|
|
case DRAW_POINT:
|
|
use_graph_pen();
|
|
x = 256 * d[k + 1] + d[k + 2];
|
|
y = 256 * d[k + 3] + d[k + 4];
|
|
draw_point(xx + x, yy + y);
|
|
k += 5;
|
|
break;
|
|
case DRAW_BOX:
|
|
x1 = 256 * d[k + 1] + d[k + 2];
|
|
y1 = 256 * d[k + 3] + d[k + 4];
|
|
x2 = 256 * d[k + 5] + d[k + 6];
|
|
y2 = 256 * d[k + 7] + d[k + 8];
|
|
draw_box(xx + x1, yy + y1, xx + x2, yy + y2);
|
|
k += 9;
|
|
break;
|
|
default:
|
|
d[4] = 0; // error, force stop
|
|
k = 4;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 1/2 line_height above and below display
|
|
|
|
yy -= line_height / 2;
|
|
yy += term[i].h;
|
|
|
|
use_normal_pen();
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
char *
|
|
get_tty_buf(void)
|
|
{
|
|
int i, j, n;
|
|
char *s;
|
|
|
|
i = head;
|
|
n = 0;
|
|
|
|
while (i != tail) {
|
|
if (term[i].type == 0)
|
|
n += (int) strlen(term[i].u.s) + 1;
|
|
i = (i + 1) % MAXHIST;
|
|
}
|
|
|
|
s = (char *) malloc(n + 1);
|
|
|
|
if (s == NULL)
|
|
return s;
|
|
|
|
i = head;
|
|
j = 0;
|
|
|
|
while (i != tail) {
|
|
if (term[i].type == 0) {
|
|
strcpy(s + j, term[i].u.s);
|
|
j += (int) strlen(term[i].u.s);
|
|
s[j++] = '\n';
|
|
}
|
|
i = (i + 1) % MAXHIST;
|
|
}
|
|
|
|
s[j] = 0;
|
|
|
|
return s;
|
|
}
|