home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <bios.h>
- #include <dos.h>
- #include <dpmi.h>
- #include <go32.h>
- #include <keys.h>
- #include <setjmp.h>
- #include "ed.h"
- #include "screen.h"
- void *xmalloc (size_t);
- /* ------------------------------------------------------------------------- */
- static char *colours[] = {
- "black", "blue", "green", "cyan",
- "red", "purple", "brown", "grey",
- "darkgrey", "lightblue", "lightgreen", "lightcyan",
- "lightred", "lightmagenta", "yellow", "white"};
- /* ------------------------------------------------------------------------- */
- /* At position (X,Y) place TXT in the debugger screen. */
-
- inline void
- put (int x, int y, unsigned char *txt)
- {
- unsigned char *p
- = (unsigned char *)(debug_screen_save + 3) + 2 * (cols * y + x);
- while (*txt)
- *p++ = *txt++,
- *p++ = screen_attr;
- }
- /* ------------------------------------------------------------------------- */
- /* At position (X,Y) left-justify to width L this TXT in the debugger
- screen. */
-
- inline void
- putl (int x, int y, int l, unsigned char *txt)
- {
- unsigned char *p
- = (unsigned char *)(debug_screen_save + 3) + 2 * (cols * y + x);
- while (*txt && l > 0)
- *p++ = *txt++,
- *p++ = screen_attr,
- l--;
- while (l-- > 0)
- *p++ = ' ',
- *p++ = screen_attr;
- }
- /* ------------------------------------------------------------------------- */
- /* At position (X,Y) place CHAR. Add DELTA to the screen address and repeat
- COUNT times. This is mainly used to draw frames. */
-
- inline void
- draw (int x, int y, unsigned char ch, int delta, int count)
- {
- short unsigned *p
- = (short unsigned *)(debug_screen_save + 3) + (cols * y + x);
- short unsigned attrch = ((unsigned)screen_attr << 8) + ch;
- while (count--)
- *p = attrch,
- p += delta;
- }
- /* ------------------------------------------------------------------------- */
- /* Highlight the text at (X,Y) length LEN by updating the attribute. */
-
- void
- highlight (int x, int y, int len)
- {
- unsigned short *p
- = (unsigned short *)(debug_screen_save + 4) + (cols * y + x);
- while (len--)
- *(unsigned char *)p = screen_attr,
- p++;
- }
- /* ------------------------------------------------------------------------- */
- /* Draw a frame with its corners at (X1,Y1) and (X2,Y2). */
-
- void
- frame (int x1, int y1, int x2, int y2)
- {
- draw (x1 + 1, y1, '─', 1, x2 - x1 - 1);
- draw (x1 + 1, y2, '─', 1, x2 - x1 - 1);
- draw (x1, y1 + 1, '│', cols, y2 - y1 - 1);
- draw (x2, y1 + 1, '│', cols, y2 - y1 - 1);
- put (x1, y1, "┌");
- put (x2, y1, "┐");
- put (x1, y2, "└");
- put (x2, y2, "┘");
- }
- /* ------------------------------------------------------------------------- */
- /* Display (on the physical screen) some virtual SCREEN. */
-
- void
- put_screen (char *screen)
- {
- int addr;
-
- switch (*screen++)
- {
- case 0:
- /* Text screen, primary display. */
- ScreenSetCursor (screen[0], screen[1]);
- ScreenUpdate (screen + 2);
- break;
- case 1:
- /* Text screen, secondary display. */
- addr = (screen[0] * cols + screen[1]) * 2;
- outportb (0x3b4, 0xf); outportb (0x3b5, addr & 0xff);
- outportb (0x3b4, 0xe); outportb (0x3b5, addr >> 8);
- movedata (_go32_my_ds (), (unsigned) (screen + 2),
- _go32_conventional_mem_selector (), 0xb0000,
- cols * rows * 2);
- break;
- }
- }
- /* ------------------------------------------------------------------------- */
- /* Return a (malloc'ed) virtual copy of the currently displayed screen. */
-
- char *
- get_screen (void)
- {
- char *p;
- int r, c, addr;
-
- p = xmalloc (cols * rows * 2 + 3);
- if (dual_monitor_p)
- {
- /* Get the secondary display's contents. */
-
- p[0] = 1;
- addr = (outportb (0x3b4, 0xf), inportb (0x3b5))
- + (outportb (0x3b4, 0xe), inportb (0x3b5) << 8);
- p[1] = (addr / 2) / cols;
- p[2] = (addr / 2) % cols;
- movedata (_go32_conventional_mem_selector (), 0xb0000,
- _go32_my_ds (), (unsigned) (p + 3),
- cols * rows * 2);
- }
- else
- {
- /* Get the primary display's contents. */
- ScreenGetCursor (&r, &c);
- p[0] = 0;
- p[1] = r;
- p[2] = c;
- ScreenRetrieve (p + 3);
- }
- return p;
- }
- /* ------------------------------------------------------------------------- */
- /* Display the debugger screen (if not already displayed). */
-
- void
- debug_screen (void)
- {
- if (!debug_screen_p)
- {
- if (!dual_monitor_p)
- {
- user_screen_save = get_screen ();
- put_screen (debug_screen_save);
- }
- debug_screen_p = 1;
- }
- }
- /* ------------------------------------------------------------------------- */
- /* Display the user screen (if not already displayed). */
-
- void
- user_screen (void)
- {
- if (debug_screen_p)
- {
- if (!dual_monitor_p)
- {
- put_screen (user_screen_save);
- free (user_screen_save);
- }
- debug_screen_p = 0;
- }
- }
- /* ------------------------------------------------------------------------- */
- /* Reportedly, `sleep' & `gettimeofday' are buggy under Dpmi -- emulate.
- Anyway, this means that we can make a keypress abort the sleeping. */
-
- static int
- mysleep (int secs)
- {
- struct time now;
- unsigned now100, then100;
-
- gettime (&now);
- then100
- = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec + secs) * 100
- + now.ti_hund;
- do
- {
- gettime (&now);
- now100 = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec) * 100
- + now.ti_hund;
- if (now100 < 100 || kbhit ())
- break; /* Day turnover or key pressed. */
- }
- while (now100 < then100);
- return 0;
- }
- /* ------------------------------------------------------------------------- */
- void
- message (CL_TYPE class, char *fmt, ...)
- {
- char *save, *buf = alloca (cols);
- unsigned char saveattr = screen_attr;
- int len, y = rows / 2;
-
- vsprintf (buf, fmt, (&fmt) + 1);
- len = strlen (buf);
- save = debug_screen_save;
- debug_screen_save = get_screen ();
- switch (class)
- {
- case CL_Error:
- screen_attr = screen_attr_error;
- break;
- default:
- screen_attr = screen_attr_message;
- }
- frame (1, y - 1, cols - 2, y + 1);
- draw (2, y, ' ', 1, cols - 4);
- put ((cols - len) / 2, y, buf);
- screen_attr = saveattr;
- put_screen (debug_screen_save);
- switch (class)
- {
- case CL_Info:
- mysleep (2);
- break;
- case CL_Msg:
- case CL_Error:
- (void) getxkey ();
- }
- free (debug_screen_save);
- debug_screen_save = save;
- put_screen (debug_screen_save);
- }
- /* ------------------------------------------------------------------------- */
- /* Read a string from the keyboard to `read_buffer'. The entry is started
- with STARTTEXT. This function uses an obscene amount of redrawing, but
- who cares? */
-
- int
- read_string (char *starttext)
- {
- char *save;
- int key, esc = 0, pos, leave = 0, y = rows / 2;
-
- save = debug_screen_save;
- debug_screen_save = get_screen ();
- strcpy (read_buffer, starttext);
- pos = strlen (read_buffer);
-
- frame (1, y - 1, cols - 2, y + 1);
- do
- {
- draw (2, y, ' ', 1, cols - 4);
- put (3, y, read_buffer);
- pos = strlen (read_buffer);
- put_screen (debug_screen_save);
- ScreenSetCursor (y, 3 + pos);
- key = getxkey ();
- switch (key)
- {
- case K_Return:
- leave = 1;
- break;
- case K_Escape:
- leave = 1;
- esc = 1;
- read_buffer[0] = '\0';
- break;
- case K_BackSpace:
- if (pos > 0)
- read_buffer[--pos] = '\0';
- break;
- default:
- if (key >= ' ' && key <= 0xff && pos <= cols - 7)
- {
- read_buffer[pos++] = key & 0xff;
- read_buffer[pos] = '\0';
- }
- }
- }
- while (!leave);
- free (debug_screen_save);
- debug_screen_save = save;
- put_screen (debug_screen_save);
- return esc;
- }
- /* ------------------------------------------------------------------------- */
- void
- init_screen (void)
- {
- if (dual_monitor_p)
- rows = 25, cols = 80;
- else
- {
- cols = ScreenCols ();
- rows = ScreenRows ();
- if (cols < 80 || rows < 25)
- {
- fprintf (stderr, "\n\
- Debugger error:\n\
- There are only %d columns and %d rows\n\
- in this display mode.\n\
- The debugger needs at least\n\
- 80 columns and 25 rows.\n",
- cols, rows);
- exit (1);
- }
- }
- toplines = (rows / 2) + 4;
- bottomlines = rows - 3 - toplines;
- }
- /* ------------------------------------------------------------------------- */
- /* Set the default colours. */
-
- void
- init_colours (void)
- {
- switch (dual_monitor_p ? 7 : ScreenMode ())
- {
- case 2:
- case 7:
- /* Mono */
- screen_attr_normal = (A_black << 4) + A_grey;
- screen_attr_source = screen_attr_normal;
- screen_attr_focus = (A_grey << 4) + A_black;
- screen_attr_break = (A_black << 4) + A_white;
- screen_attr_message = (A_grey << 4) + A_white;
- screen_attr_error = (A_grey << 4) + A_white;
- screen_attr_menu = (A_grey << 4) + A_black;
- screen_attr_menufocus = (A_black << 4) + A_white;
- screen_attr_editframe = (A_grey << 4) + A_black;
- screen_attr_edittxt = (A_grey << 4) + A_black;
- screen_attr_editfield = (A_grey << 4) + A_black;
- screen_attr_editfocus = (A_black << 4) + A_white;
- break;
- default:
- /* Colour */
- screen_attr_normal = (A_cyan << 4) + A_blue;
- screen_attr_source = (A_cyan << 4) + A_black;
- screen_attr_focus = (A_blue << 4) + A_white;
- screen_attr_break = (A_red << 4) + A_white;
- screen_attr_message = (A_green << 4) + A_white;
- screen_attr_error = (A_red << 4) + A_white;
- screen_attr_menu = (A_grey << 4) + A_black;
- screen_attr_menufocus = (A_black << 4) + A_white;
- screen_attr_editframe = (A_blue << 4) + A_grey;
- screen_attr_edittxt = (A_blue << 4) + A_grey;
- screen_attr_editfield = (A_blue << 4) + A_white;
- screen_attr_editfocus = (A_red << 4) + A_white;
- }
- }
- /* ------------------------------------------------------------------------- */
- void
- screen_mode (int rows)
- {
- union REGS regs;
- int font, cursor;
-
- switch (rows)
- {
- case 43:
- case 50:
- font = 0x1112;
- cursor = 0x0607;
- break;
- case 25:
- case 28:
- default:
- font = 0x1111;
- cursor = 0x0607;
- }
- regs.w.ax = 0x0003;
- int86 (0x10, ®s, ®s);
- regs.w.ax = font;
- regs.h.bl = 0;
- int86 (0x10, ®s, ®s);
- regs.w.ax = 0x1200;
- regs.h.bl = 32;
- int86 (0x10, ®s, ®s);
- if (rows == 25)
- {
- regs.w.ax = 0x0003;
- int86 (0x10, ®s, ®s);
- }
- regs.w.ax = 0x0100;
- regs.w.cx = cursor;
- int86 (0x10, ®s, ®s);
- }
- /* ------------------------------------------------------------------------- */
- int
- menu (char *title, MENU_ITEM *m, int *focus)
- {
- char *save;
- int width, i, count, state;
- unsigned char saveattr = screen_attr;
- int x0, y0;
-
- save = debug_screen_save;
- debug_screen_save = get_screen ();
-
- width = title ? strlen (title) : 0;
- for (count = 0; m[count].txt; count++)
- {
- i = strlen (m[count].txt);
- if (i > width) width = i;
- }
- width += 2;
- x0 = cols / 2 - width / 2;
- y0 = rows / 2 - count / 2;
-
- screen_attr = screen_attr_menu;
- frame (x0 - 1, y0 - 1, x0 + width, y0 + count);
- if (title)
- put (cols / 2 - strlen (title) / 2, y0 - 1, title);
-
- state = 0;
- while (state == 0)
- {
- for (i = 0; i < count; i++)
- {
- screen_attr
- = (i == *focus) ? screen_attr_menufocus : screen_attr_menu;
- putl (x0 + 1, y0 + i, width - 1, m[i].txt);
- put (x0, y0 + i, " ");
- }
- put_screen (debug_screen_save);
- switch (getxkey ())
- {
- case K_Escape:
- state = 1;
- break;
- case K_Return:
- state = 2;
- break;
- case K_Up:
- case K_EUp:
- case K_Left:
- case K_ELeft:
- if (*focus) (*focus)--;
- break;
- case K_Down:
- case K_EDown:
- case K_Right:
- case K_ERight:
- if (*focus < count - 1) (*focus)++;
- break;
- case K_Home:
- case K_EHome:
- *focus = 0;
- break;
- case K_End:
- case K_EEnd:
- *focus = count - 1;
- break;
- }
- }
- screen_attr = saveattr;
- free (debug_screen_save);
- debug_screen_save = save;
- put_screen (debug_screen_save);
- if (state == 2)
- {
- if (m[*focus].handler)
- m[*focus].handler (m[*focus].info);
- return *focus;
- }
- else
- return -1;
- }
- /* ------------------------------------------------------------------------- */
- int
- edit (char *title, EDIT_ITEM *fields, int focus)
- {
- char *save;
- unsigned char saveattr = screen_attr;
- int i, leave, esc = 0, count, key = 0, width, *length;
- int x0, y0, x, y, len;
- char *data;
-
- save = debug_screen_save;
- debug_screen_save = get_screen ();
-
- for (count = 0; fields[count].txt; count++)
- /* Nothing. */;
- x0 = 3;
- y0 = rows / 2 - count / 2;
- screen_attr = screen_attr_editframe;
- length = alloca (count * sizeof (int));
- frame (x0 - 1, y0 - 1, cols - x0, y0 + count);
- if (title)
- put (cols / 2 - strlen (title) / 2, y0 - 1, title);
-
- screen_attr = screen_attr_edittxt;
- for (i = 0; i < count; i++)
- {
- put (x0, y0 + i, " ");
- put (x0 + 1, y0 + i, fields[i].txt);
- length[i] = strlen (fields[i].txt);
- }
-
- leave = 0;
- while (!leave)
- {
- for (i = 0; i < count; i++)
- {
- screen_attr = screen_attr_editfield;
- width = cols - 8 - length[i];
- x = x0 + length[i] + 1, y = y0 + i;
- put (x - 1, y, " ");
- putl (x, y, 1 + width, fields[i].data);
- }
- data = fields[focus].data;
- screen_attr = screen_attr_editfocus;
- width = cols - 8 - length[focus];
- x = x0 + length[focus] + 1, y = y0 + focus;
- put (x - 1, y, " ");
- len = strlen (data);
- while (!leave)
- {
- putl (x, y, 1 + width, data);
- put_screen (debug_screen_save);
- ScreenSetCursor (y, x + len);
- switch ((key = getxkey ()))
- {
- case K_Left:
- case K_ELeft:
- case K_BackSpace:
- if (len)
- data[--len] = 0;
- break;
- case ' ' ... '~':
- if (len < width)
- data[len++] = key, data[len] = 0;
- break;
- default:
- leave = 1;
- break;
- }
- }
- leave = 0;
- switch (key)
- {
- case K_Escape:
- leave = esc = 1;
- break;
- case K_Up:
- case K_EUp:
- focus = focus ? focus - 1 : count - 1;
- break;
- case K_Return:
- leave = (focus == count - 1);
- /* Fall through. */
- case K_Down:
- case K_EDown:
- focus = (focus == count - 1) ? 0 : focus + 1;
- break;
- case K_Home:
- case K_EHome:
- focus = 0;
- break;
- case K_End:
- case K_EEnd:
- focus = count - 1;
- break;
- }
- }
-
- screen_attr = saveattr;
- free (debug_screen_save);
- debug_screen_save = save;
- put_screen (debug_screen_save);
- return !esc;
- }
- /* ------------------------------------------------------------------------- */
- static void
- attr2text (char *buf, unsigned char attr)
- {
- sprintf (buf, "%s on %s%s",
- colours[attr & 15], colours[(attr >> 4) & 7], \
- (attr & 128) ? ", blinking" : "");
- buf[0] = toupper (buf[0]);
- }
-
- static int
- text2attr (char *s)
- {
- char *s1, *s2, *cs;
- int f, b, l;
-
- l = strlen (s) + 1;
- s = strcpy (alloca (l), s);
- s1 = alloca (l);
- s2 = alloca (l);
- if ((cs = strchr (s, ',')))
- if (stricmp (cs, ", blinking"))
- return -1;
- else
- *cs = 0;
- if (sscanf (s, "%s on %s", s1, s2) == 2)
- {
- for (f = 0; f < 16; f++)
- if (stricmp (colours[f], s1) == 0)
- break;
- for (b = 0; b < 8; b++)
- if (stricmp (colours[b], s2) == 0)
- break;
- if (f < 16 && b < 8)
- return (cs ? 128 : 0) | (b << 4) | f;
- }
- return -1;
- }
-
- void
- edit_colours (int dummy)
- {
- int i, focus;
- static EDIT_ITEM form[] = {
- {"Normal ..............: ", 0},
- {"Source Code .........: ", 0},
- {"Foci ................: ", 0},
- {"Breakpoints .........: ", 0},
- {"Messages ............: ", 0},
- {"Errors ..............: ", 0},
- {"Menus ...............: ", 0},
- {"Menu Foci ...........: ", 0},
- {"Form Frames .........: ", 0},
- {"Form Legends ........: ", 0},
- {"Form Fields .........: ", 0},
- {"Form Foci ...........: ", 0},
- {0, 0}};
-
- for (i = 0; form[i].txt; i++) form[i].data = alloca (cols);
- attr2text (form[ 0].data, screen_attr_normal);
- attr2text (form[ 1].data, screen_attr_source);
- attr2text (form[ 2].data, screen_attr_focus);
- attr2text (form[ 3].data, screen_attr_break);
- attr2text (form[ 4].data, screen_attr_message);
- attr2text (form[ 5].data, screen_attr_error);
- attr2text (form[ 6].data, screen_attr_menu);
- attr2text (form[ 7].data, screen_attr_menufocus);
- attr2text (form[ 8].data, screen_attr_editframe);
- attr2text (form[ 9].data, screen_attr_edittxt);
- attr2text (form[10].data, screen_attr_editfield);
- attr2text (form[11].data, screen_attr_editfocus);
- focus = 0;
- while (edit ("Edit Colour Scheme", form, focus))
- {
- for (focus = 0; form[focus].txt; focus++)
- if (text2attr (form[focus].data) == -1)
- break;
- if (form[focus].txt == 0)
- {
- screen_attr_normal = text2attr (form[ 0].data);
- screen_attr_source = text2attr (form[ 1].data);
- screen_attr_focus = text2attr (form[ 2].data);
- screen_attr_break = text2attr (form[ 3].data);
- screen_attr_message = text2attr (form[ 4].data);
- screen_attr_error = text2attr (form[ 5].data);
- screen_attr_menu = text2attr (form[ 6].data);
- screen_attr_menufocus = text2attr (form[ 7].data);
- screen_attr_editframe = text2attr (form[ 8].data);
- screen_attr_edittxt = text2attr (form[ 9].data);
- screen_attr_editfield = text2attr (form[10].data);
- screen_attr_editfocus = text2attr (form[11].data);
- return;
- }
- }
- }
- /* ------------------------------------------------------------------------- */
-