STDWIN 0.9.6 patches, part 3/5
Guido van Rossum
guido at cwi.nl
Fri Jun 7 23:32:04 AEST 1991
Archive-name: stdwin0.9.6/patch3
*** 0.9.5/Ports/mac/stdwin.c Thu Feb 21 10:54:56 1991
--- stdwin/Ports/mac/stdwin.c Tue May 28 22:27:01 1991
***************
*** 11,16 ****
--- 11,24 ----
#endif
+ /* Parameters for top left corner choice algorithm in wopen() */
+
+ #define LEFT 20 /* Initial left */
+ #define TOP 40 /* Initial top */
+ #define HINCR 20 /* Increment for left */
+ #define VINCR 16 /* Increment for top */
+
+
/* GLOBAL DATA. */
/* XXX choose less obvious names */
***************
*** 17,25 ****
GrafPtr screen; /* The Mac Window Manager's GrafPort */
TEXTATTR wattr; /* Current or default text attributes */
! static int def_left= LEFT;
! static int def_top= TOP;
! static int def_width, def_height;
/* INITIALIZATION AND TERMINATION. */
--- 25,38 ----
GrafPtr screen; /* The Mac Window Manager's GrafPort */
TEXTATTR wattr; /* Current or default text attributes */
! static int def_left = 0;
! static int def_top = 0;
! static int def_width = 0;
! static int def_height = 0;
! static int def_horscroll = 0;
! static int def_verscroll = 1;
! static int next_left = LEFT; /* For default placement algorithm */
! static int next_top = TOP;
/* INITIALIZATION AND TERMINATION. */
***************
*** 85,91 ****
#ifdef MPW
set_open_hook(std_open_hook);
#endif
- wsetdefwinsize(0, 0);
set_watch();
}
--- 98,103 ----
***************
*** 101,107 ****
Rect r;
r= screen->portRect;
*pwidth= r.right - r.left;
! *pheight= r.bottom - r.top;
}
void
--- 113,119 ----
Rect r;
r= screen->portRect;
*pwidth= r.right - r.left;
! *pheight= r.bottom - r.top - MENUBARHEIGHT;
}
void
***************
*** 108,120 ****
wgetscrmm(pmmwidth, pmmheight)
int *pmmwidth, *pmmheight;
{
! Rect r;
! r= screen->portRect;
/* XXX Three pixels/mm is an approximation of the truth at most */
! *pmmwidth= (r.right - r.left) / 3;
! *pmmheight= (r.bottom - r.top) / 3;
}
/* Routine called by "Resume" button in bomb box (passed to InitDialogs).
I have yet to see a program crash where an attempted exit to the
Finder caused any harm, so I think it's safe.
--- 120,139 ----
wgetscrmm(pmmwidth, pmmheight)
int *pmmwidth, *pmmheight;
{
! int width, height;
! wgetscrsize(&width, &height);
/* XXX Three pixels/mm is an approximation of the truth at most */
! *pmmwidth= width / 3;
! *pmmheight= height / 3;
}
+ int
+ wgetmouseconfig()
+ {
+ return WM_BUTTON1 | WM_SHIFT | WM_META | WM_LOCK | WM_OPTION;
+ /* XXX Should figure out if we have a Control button as well */
+ }
+
/* Routine called by "Resume" button in bomb box (passed to InitDialogs).
I have yet to see a program crash where an attempted exit to the
Finder caused any harm, so I think it's safe.
***************
*** 126,131 ****
--- 145,151 ----
ExitToShell();
}
+
/* WINDOWS. */
/* Find the WINDOW pointer corresponding to a WindowPtr. */
***************
*** 154,186 ****
{
WINDOW *win= ALLOC(WINDOW);
Rect r;
if (win == NULL) {
! dprintf("wopen: ALLOC failed"); /* XXX */
return NULL;
}
!
! /* Find a nice position for the window. */
! if (def_left + def_width + BAR + LSLOP + RSLOP
! > screen->portRect.right) {
! def_left= LEFT;
! CLIPMAX(def_left, screen->portRect.right -
! (def_width + BAR + LSLOP + RSLOP));
! CLIPMIN(def_left, 0);
}
! if (def_top + def_height + BAR > screen->portRect.bottom) {
! def_top= TOP;
! CLIPMAX(def_top, screen->portRect.bottom -
! (def_height + BAR));
! CLIPMIN(def_top, MENUBARHEIGHT + TITLEBARHEIGHT);
}
! SetRect(&r, def_left, def_top,
! def_left+def_width + BAR + LSLOP + RSLOP,
! def_top+def_height + BAR);
! def_left += HINCR;
! def_top += VINCR;
win->w= NewWindow((Ptr)NULL, &r, PSTRING(title), TRUE, zoomDocProc,
(WindowPtr)(-1), TRUE, 0L);
SetWRefCon(win->w, (long)win);
--- 174,270 ----
{
WINDOW *win= ALLOC(WINDOW);
Rect r;
+ int width, height; /* As seen by the user */
+ int tot_width, tot_height; /* Including slop & scroll bars */
+ int left, top; /* Window corner as seen by the user */
if (win == NULL) {
! dprintf("wopen: ALLOC failed");
return NULL;
}
!
! /* Determine window size.
! If the program specified a size, use that, within reason --
! sizes are clipped to 0x7000 to avoid overflow in QuickDraw's
! calculations.
! Otherwise, use two-third of the screen size, but at most
! 512x342 (to avoid creating gigantic windows by default on
! large screen Macs). */
!
! if (def_width <= 0) {
! width = screen->portRect.right * 2/3;
! CLIPMAX(width, 512);
}
! else {
! width = def_width;
! CLIPMAX(width, 0x7000);
}
+ if (def_horscroll)
+ CLIPMIN(width, 3*BAR);
+ tot_width = width + LSLOP + RSLOP;
+ if (def_verscroll)
+ tot_width += BAR;
! if (def_height <= 0) {
! height= screen->portRect.bottom * 2/3;
! CLIPMAX(height, 342);
! }
! else {
! height = def_height;
! CLIPMAX(height, 0x7000);
! }
! if (def_verscroll)
! CLIPMIN(height, 3*BAR);
! tot_height = height;
! if (def_horscroll)
! tot_height += BAR;
+ /* Determine window position.
+ It the program specified a position, use that, but make sure
+ that at least a small piece of the title bar is visible --
+ so the user can recover a window that "fell off the screen".
+ Exception: the title bar may hide completely under the menu
+ bar, since this is the only way to get an (almost) full
+ screen window.
+ Otherwise, place the window a little to the right and below
+ the last window placed; it it doesn't fit, move it up.
+ With default placement, the window will never hide under the
+ title bar. */
+
+ if (def_left <= 0) {
+ left = next_left;
+ if (left + tot_width >= screen->portRect.right) {
+ left = LEFT;
+ CLIPMAX(left, screen->portRect.right - tot_width);
+ CLIPMIN(left, 0);
+ }
+ }
+ else {
+ left = def_left - LSLOP;
+ CLIPMAX(left, screen->portRect.right - BAR);
+ CLIPMIN(left, BAR - tot_width);
+ }
+
+ if (def_top <= 0) {
+ top = next_top;
+ if (top + tot_height >= screen->portRect.bottom) {
+ top = TOP;
+ CLIPMAX(top, screen->portRect.bottom - tot_height);
+ CLIPMIN(top, MENUBARHEIGHT + TITLEBARHEIGHT);
+ }
+ }
+ else {
+ top = def_top;
+ CLIPMAX(top, screen->portRect.bottom);
+ CLIPMIN(top, MENUBARHEIGHT);
+ }
+
+ next_left = left + HINCR;
+ next_top = top + VINCR;
+
+ /* Create the window now and initialize its attributes */
+
+ SetRect(&r, left, top, left + tot_width, top + tot_height);
win->w= NewWindow((Ptr)NULL, &r, PSTRING(title), TRUE, zoomDocProc,
(WindowPtr)(-1), TRUE, 0L);
SetWRefCon(win->w, (long)win);
***************
*** 197,205 ****
win->orgv= 0;
win->timer= 0;
win->cursor = NULL;
initmbar(&win->mbar);
! makescrollbars(win);
return win;
}
--- 281,295 ----
win->orgv= 0;
win->timer= 0;
win->cursor = NULL;
+ win->fgcolor = _w_fgcolor;
+ win->bgcolor = _w_bgcolor;
+ SetPort(win->w);
+ _w_usefgcolor(win->fgcolor);
+ _w_usebgcolor(win->bgcolor);
+
initmbar(&win->mbar);
! makescrollbars(win, def_horscroll, def_verscroll);
return win;
}
***************
*** 230,235 ****
--- 320,345 ----
}
void
+ wgetwinpos(win, ph, pv)
+ WINDOW *win;
+ int *ph, *pv;
+ {
+ Point p;
+ GrafPtr saveport;
+
+ GetPort(&saveport);
+
+ SetPort(win->w);
+ p.h = win->w->portRect.left + LSLOP;
+ p.v = win->w->portRect.top;
+ LocalToGlobal(&p);
+ *ph = p.h;
+ *pv = p.v;
+
+ SetPort(saveport);
+ }
+
+ void
wsettitle(win, title)
WINDOW *win;
char *title;
***************
*** 272,282 ****
wsetdefwinpos(h, v)
int h, v;
{
! /* XXX Sanity checks? Change interaction with wopen()? */
! if (h > 0)
! def_left = h;
! if (v > 0)
! def_top = v;
}
void
--- 382,389 ----
wsetdefwinpos(h, v)
int h, v;
{
! def_left = h;
! def_top = v;
}
void
***************
*** 291,312 ****
wsetdefwinsize(width, height)
int width, height;
{
- /* XXX Shouldn't this be done by wopen() instead? */
- if (width <= 0) {
- width= screen->portRect.right * 2/3;
- CLIPMAX(width, 512);
- }
- CLIPMAX(width, screen->portRect.right - BAR - LSLOP - RSLOP);
- CLIPMIN(width, MIN_WIDTH);
-
- if (height <= 0) {
- height= screen->portRect.bottom * 2/3;
- CLIPMAX(height, 342);
- }
- CLIPMAX(height, screen->portRect.bottom
- - MENUBARHEIGHT - TITLEBARHEIGHT - BAR);
- CLIPMIN(height, MIN_HEIGHT);
-
def_width= width;
def_height= height;
}
--- 398,403 ----
***************
*** 320,327 ****
}
void
! wsetactive(win)
! WINDOW *win;
{
! SelectWindow(win->w);
}
--- 411,427 ----
}
void
! wsetdefscrollbars(hor, ver)
! int hor, ver;
{
! def_horscroll = hor;
! def_verscroll = ver;
! }
!
! void
! wgetdefscrollbars(phor, pver)
! int *phor, *pver;
! {
! *phor = def_horscroll;
! *pver = def_verscroll;
}
*** 0.9.5/Ports/msdos/README Thu Feb 28 11:30:38 1991
--- stdwin/Ports/msdos/README Tue Apr 23 15:56:24 1991
***************
*** 1,4 ****
Sorry, there is no real STDWIN port for MS-DOS yet. What you can is
! to port the alfa version with the help of the file "ptrm.c" in this
directory, which is a substitute (using the MS-DOS console driver) for
! the VTRM module used by the alfa version for all its tty I/O.
--- 1,5 ----
Sorry, there is no real STDWIN port for MS-DOS yet. What you can is
! to port the alfa version with the help of the file "vtrm.c" in this
directory, which is a substitute (using the MS-DOS console driver) for
! the VTRM module used by the alfa version for all its tty I/O (the UNIX
! version of vtrm.c is in ../vtrm).
*** 0.9.5/Ports/msdos/dir.c Wed Jun 24 13:40:34 1987
--- stdwin/Ports/msdos/dir.c Tue Apr 23 15:56:39 1991
***************
*** 1,28 ****
/*
* MS-DOS version of UNIX directory access package.
* (opendir, readdir, closedir).
*/
! #include <sys/types.h>
! #include <sys/stat.h>
! #include <errno.h>
#include <dos.h>
! extern int errno;
! #define MAXPATH 64
!
#include "dir.h"
- static char *firstf();
- static char *nextf();
typedef int bool;
! #define TRUE 1
! #define FALSE 0
#define EOS '\0'
- #define NULL 0
! static char dirpath[MAXPATH+1]= "";
! static bool busy= FALSE;
/*
* Open a directory.
* This MS-DOS version allows only one directory to be open at a time.
--- 1,38 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1990. */
+
/*
* MS-DOS version of UNIX directory access package.
* (opendir, readdir, closedir).
*/
! #include <stdio.h>
! #include <ctype.h>
! #include <string.h>
#include <dos.h>
! #include <errno.h>
! #include <sys\types.h>
! #include <sys\stat.h>
#include "dir.h"
+ #define Visible
+ #define Hidden static
+ #define Procedure
+
typedef int bool;
!
! #define Yes ((bool) 1)
! #define No ((bool) 0)
!
! #define MAXPATH 64
#define EOS '\0'
! extern int errno;
! Hidden char *firstf();
! Hidden char *nextf();
+ Hidden char dirpath[MAXPATH+1] = "";
+ Hidden bool busy = No;
+
/*
* Open a directory.
* This MS-DOS version allows only one directory to be open at a time.
***************
*** 30,153 ****
* Then it only saves the file name and returns a pointer to it.
*/
! char *
! opendir(path)
! char *path;
{
struct stat buffer;
if (dirpath[0] != EOS) {
! errno= EMFILE;
return NULL; /* Only one directory can be open at a time */
}
if (stat(path, &buffer) == -1)
return NULL; /* Directory doesn't exist */
if ((buffer.st_mode & S_IFMT) != S_IFDIR) {
! errno= ENOENT;
return NULL; /* Not a directory */
}
strcpy(dirpath, path);
! path= dirpath + strlen(dirpath);
if (path > dirpath && path[-1] != ':' && path[-1] != '/' &&
path[-1] != '\\')
*path++ = '\\';
strcpy(path, "*.*");
! busy= FALSE; /* Tell readdir this is the first time */
! return dirpath;
}
/*
- * Close a directory.
- * We must clear the first char of dirpath to signal opendir that
- * no directory is open.
- */
-
- closedir(dirp)
- char *dirp;
- {
- dirp[0]= EOS;
- }
-
- /*
* Read the next directory entry.
*/
! struct direct *
! readdir(dp)
! char *dp;
{
static struct direct buffer;
char *p;
if (!busy)
! p= firstf(dp);
else
! p= nextf();
! busy= (p != NULL);
if (!busy)
return NULL;
strcpy(buffer.d_name, p);
! buffer.d_namlen= strlen(p);
return &buffer;
}
/*
! * Low-level implementation -- access to DOS system calls FIRST and NEXT.
*/
! static char dta[64]; /* Device Transfer Area */
! /* File attributes */
! #define READONLY 0x01
! #define HIDDEN 0x02
! #define SYSTEM 0x04
! #define VOLUMEID 0x08
! #define DIRECTORY 0x10
! #define ARCHIVE 0x20
! #define MATCHATTR (HIDDEN|SYSTEM|DIRECTORY)
! static char *
! firstf(pat)
! char *pat;
{
! int flags;
! union REGS regs;
! struct SREGS segregs;
! setdta(dta);
! segread(&segregs);
! regs.h.ah = 0x4e;
! regs.x.cx = MATCHATTR;
#ifdef M_I86LM /* Large Model -- far pointers */
! regs.x.dx = FP_OFF(pat);
! segregs.ds = FP_SEG(pat);
#else
! regs.x.dx = (int) pat;
#endif
! flags= intdosx(®s, ®s, &segregs);
! if (regs.x.cflag)
! return NULL;
! fixfile();
! return dta + 30;
}
! static char *
! nextf()
{
! int flags;
! union REGS regs;
! setdta(dta);
! regs.h.ah = 0x4f;
! flags= intdos(®s, ®s);
! if (regs.x.cflag)
! return NULL;
! fixfile();
! return dta + 30;
}
/*
--- 40,151 ----
* Then it only saves the file name and returns a pointer to it.
*/
! Visible DIR *opendir(path)
! char *path;
{
struct stat buffer;
if (dirpath[0] != EOS) {
! errno = EMFILE;
return NULL; /* Only one directory can be open at a time */
}
if (stat(path, &buffer) == -1)
return NULL; /* Directory doesn't exist */
if ((buffer.st_mode & S_IFMT) != S_IFDIR) {
! errno = ENOENT;
return NULL; /* Not a directory */
}
strcpy(dirpath, path);
! path = dirpath + strlen(dirpath);
if (path > dirpath && path[-1] != ':' && path[-1] != '/' &&
path[-1] != '\\')
*path++ = '\\';
strcpy(path, "*.*");
! busy = No; /* Tell readdir this is the first time */
! return (DIR *) dirpath;
}
/*
* Read the next directory entry.
*/
! Visible struct direct *readdir(dp)
! char *dp;
{
static struct direct buffer;
char *p;
if (!busy)
! p = firstf((char *)dp);
else
! p = nextf();
! busy = (p != NULL);
if (!busy)
return NULL;
strcpy(buffer.d_name, p);
! buffer.d_namlen = strlen(p);
return &buffer;
}
/*
! * Close a directory.
! * We must clear the first char of dirpath to signal opendir that
! * no directory is open.
*/
! Visible Procedure closedir(dirp)
! DIR *dirp;
! {
! dirp[0] = EOS;
! }
! /*
! * Low-level implementation -- access to DOS system calls FIRST and NEXT.
! */
! Hidden char dta[64]; /* Device Transfer Area */
! #define DIRATTR 0x10
!
! Hidden char *firstf(pat)
! char *pat;
{
! static int flags;
! union REGS regs;
! struct SREGS segregs;
! setdta(dta);
! segread(&segregs);
! regs.h.ah = 0x4e;
! regs.x.cx = DIRATTR;
#ifdef M_I86LM /* Large Model -- far pointers */
! regs.x.dx = FP_OFF(pat);
! segregs.ds = FP_SEG(pat);
#else
! regs.x.dx = (int) pat;
#endif
! flags = intdosx(®s, ®s, &segregs);
! if (regs.x.cflag)
! return NULL;
! fixfile();
! return dta + 30;
}
! Hidden char *nextf()
{
! int flags;
! union REGS regs;
! setdta(dta);
! regs.h.ah = 0x4f;
! flags = intdos(®s, ®s);
! if (regs.x.cflag)
! return NULL;
! fixfile();
! return dta + 30;
}
/*
***************
*** 154,166 ****
* Convert the file name in the Device Transfer Area to lower case.
*/
! static
! fixfile()
{
char *cp;
! for (cp= dta+30; *cp != EOS; ++cp)
! *cp= tolower(*cp);
}
/*
--- 152,163 ----
* Convert the file name in the Device Transfer Area to lower case.
*/
! Hidden Procedure fixfile()
{
char *cp;
! for (cp = dta+30; *cp != EOS; ++cp)
! *cp = tolower(*cp);
}
/*
***************
*** 167,186 ****
* Tell MS-DOS where the Device Transfer Area is.
*/
! static
! setdta(dta)
! char *dta;
{
! union REGS regs;
! struct SREGS segregs;
! segread(&segregs);
! regs.h.ah = 0x1a;
#ifdef M_I86LM /* Large Model -- far pointers */
! regs.x.dx = FP_OFF(dta);
! segregs.ds = FP_SEG(dta);
#else
! regs.x.dx = (int) dta;
#endif
! intdosx(®s, ®s, &segregs);
}
--- 164,182 ----
* Tell MS-DOS where the Device Transfer Area is.
*/
! Hidden Procedure setdta(dta)
! char *dta;
{
! union REGS regs;
! struct SREGS segregs;
! segread(&segregs);
! regs.h.ah = 0x1a;
#ifdef M_I86LM /* Large Model -- far pointers */
! regs.x.dx = FP_OFF(dta);
! segregs.ds = FP_SEG(dta);
#else
! regs.x.dx = (int) dta;
#endif
! intdosx(®s, ®s, &segregs);
}
*** 0.9.5/Ports/msdos/dir.h Wed Jun 24 13:38:30 1987
--- stdwin/Ports/msdos/dir.h Tue Apr 23 15:56:53 1991
***************
*** 1,3 ****
--- 1,5 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1990. */
+
/*
* Interface for MS-DOS version of UNIX directory access package.
* (opendir, readdir, closedir).
***************
*** 10,14 ****
typedef char DIR;
! DIR *opendir();
! struct direct *readdir();
--- 12,17 ----
typedef char DIR;
! extern DIR *opendir();
! extern struct direct *readdir();
! extern closedir();
*** 0.9.5/Ports/msdos/lib. Fri Sep 4 16:17:13 1987
--- stdwin/Ports/msdos/lib. Tue Apr 23 15:57:05 1991
***************
*** 24,32 ****
style.obj:
! PTRM= ptrm.obj
! ptrm.obj:
ALFA= bind.obj draw.obj event.obj keymap.obj measure.obj \
menu.obj scroll.obj stdwin.obj syswin.obj
--- 24,32 ----
style.obj:
! VTRM= vtrm.obj
! vtrm.obj:
ALFA= bind.obj draw.obj event.obj keymap.obj measure.obj \
menu.obj scroll.obj stdwin.obj syswin.obj
***************
*** 49,52 ****
syswin.obj: alfa.h
! ALL= $(TOOLS) $(TEXTEDIT) $(PTRM) $(ALFA)
--- 49,52 ----
syswin.obj: alfa.h
! ALL= $(TOOLS) $(TEXTEDIT) $(VTRM) $(ALFA)
*** /dev/null Fri Jun 7 14:31:40 1991
--- stdwin/Ports/msdos/vtrm.c Tue Apr 23 15:52:28 1991
***************
*** 0 ****
--- 1,1137 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1991. */
+
+ /*
+ * ibm Pc virtual TeRMinal package.
+ *
+ * (Under reconstruction by Guido!)
+ *
+ * An implementation of the VTRM interface for MS-DOS machines.
+ *
+ * This code supports two modes of accessing the screen.
+ * The first one (BIOS) will be used, unless the user overwrites this
+ * by setting the SCREEN environment variable.
+ * This variable can also be used to convey a screen size that differs
+ * from the default 25 lines and 80 columns. See below.
+ *
+ * The two modes are:
+ *
+ * 1) IBM BIOS interrupt 10 hex, video io.
+ * (See IBM PC XT Technical Reference 6936833, May 1983,
+ * Appendix A, pages A46-A47).
+ * This is what you really want to use, since it's the only one that
+ * can decently scroll. It cannot insert or delete characters, so
+ * most optimisations from the unix version of vtrm.c are useless
+ * and taken out.
+ * Unfortunately, not every PC-compatible machine supports this BIOS
+ * interrupt, so for these unlucky souls there is the following escape:
+ *
+ * 2) The ANSI.SYS driver.
+ * (See IBM MS-DOS 6936839, Jan 1983, Version 2.00, Chapter 13.)
+ * (Some compatibles don't have a separate ANSI.SYS driver but do the
+ * same escape interpretation by default.)
+ * This works reasonably, apart from scrolling downward, or part of
+ * the screen, which is clumsy.
+ * (The ANSI standard provides an escape sequence for scrolling
+ * but ANSI.SYS does not support it, nor any other way of scrolling.)
+ *
+ * The rest of the interface is the same as described in the unix version,
+ * with the following exceptions:
+ * - to ease coding for ansi scrolls, the terminal is supposed to
+ * contain blanks at positions that were not written yet;
+ * the unknown rubbish that is initially on the screen can
+ * only be cleared by the caller by scrolling the whole screen up
+ * by one or more lines;
+ * - the number of lines on the terminal is assumed to be 25;
+ * the number of columns is (1) determined by a BIOS function, or
+ * (2) assumed to be 80 for ANSI;
+ * the user can overwrite this by setting the environment variable:
+ *
+ * SET SCREEN=BIOS y x
+ * or
+ * SET SCREEN=ANSI y x
+ *
+ * where x and y are the number of lines and columns respectively.
+ *
+ * The lines and columns of our virtual terminal are numbered
+ * y = {0...lines-1} from top to bottom, and
+ * x = {0...cols-1} from left to right,
+ * respectively.
+ *
+ * The Visible Procedures in this package are as described in the unix version.
+ *
+ */
+
+ /* Includes: */
+
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <string.h>
+ #include <dos.h>
+ #include <fcntl.h>
+ #include <io.h>
+ #include "vtrm.h"
+
+ /* Style definitions: */
+
+ #define Visible
+ #define Hidden static
+ #define Procedure
+
+ typedef int bool;
+ typedef char *string;
+ typedef short intlet;
+
+ #define Yes ((bool) 1)
+ #define No ((bool) 0)
+
+ /* Forward declarations: */
+
+ extern char *malloc();
+
+ /* Data definitions: */
+
+ #ifdef VTRMTRACE
+ #define TRACEFILE "TRACE.TRM"
+ Hidden FILE *vtrmfp= (FILE *) NULL;
+ #endif
+
+ #define STDIN_HANDLE 0
+
+ #define Undefined (-1)
+
+ #define Min(a,b) ((a) <= (b) ? (a) : (b))
+
+ /* terminal status */
+
+ Hidden int started = No;
+
+ Hidden int scr_mode = 0;
+ #define ANSI 'A'
+ #define BIOS 'B'
+
+ #define Nlines 25
+ #define Ncols 80
+ Hidden int lines = Nlines;
+ Hidden int cols = Ncols;
+ Hidden int flags = 0;
+
+ /* current standout mode */
+ #define Off PLAIN
+ #define On STANDOUT
+ Hidden int so_mode = Off;
+
+ /* current cursor position */
+ Hidden intlet cur_y = Undefined, cur_x = Undefined;
+
+ /* "linedata[y][x]" holds the char on the terminal,
+ * "linemode[y][x]" the STANDOUT bit.
+ * The STANDOUT bit tells whether the character is standing out.
+ * "lenline[y]" holds the length of the line.
+ * (Partially) empty lines are distinghuished by "lenline[y] < cols".
+ * Unknown chars will be ' ', so the scrolling routines for ANSI
+ * can use "unwritten" chars (with indent > 0 in trmputdata).
+ * To make the optimising compare in putline fail, lenline[y] is initially 0.
+ * The latter implies that if a line is first addressed with trmputdata,
+ * any rubbish that is on the screen beyond the data that gets put, will
+ * remain there.
+ */
+
+ Hidden char **linedata = 0;
+ Hidden char **linemode = 0;
+
+ Hidden intlet *lenline = 0;
+
+ /* To compare the mode part of the line when the
+ * mode parameter of trmputdata == NULL, we use the following:
+ */
+ Hidden char plain[1]= {PLAIN};
+
+ /* Make the cursor invisible when trmsync() tries to move outside the screen */
+ Hidden bool no_cursor = No;
+
+ /*
+ * Starting, Ending and (fatal) Error.
+ */
+
+ Hidden bool wasbreak;
+
+ /*
+ * Initialization call.
+ * Determine terminal mode.
+ * Start up terminal and internal administration.
+ * Return Yes if succeeded, No if trouble (which doesn't apply here).
+ */
+
+ Visible int trmstart(plines, pcols, pflags)
+ int *plines;
+ int *pcols;
+ int *pflags;
+ {
+ static char setup = No;
+ int err;
+
+ #ifdef VTRMTRACE
+ if (!started) vtrmfp= fopen(TRACEFILE, vtrmfp ? "a" : "w");
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmstart(&li, &co, &fl);\n");
+ #endif
+
+ if (started)
+ return TE_TWICE;
+
+ if (!setup) {
+ err = set_screen_up();
+ if (err != TE_OK)
+ return err;
+ setup = Yes;
+ }
+
+ err = start_trm(); /* internal administration */
+ if (err != TE_OK)
+ return err;
+
+ *plines = lines;
+ *pcols = cols;
+ *pflags = flags;
+
+ setmode(STDIN_HANDLE, O_BINARY); /* Don't translate CRLF to LF */
+ setraw(STDIN_HANDLE, Yes);
+ wasbreak = getbreak(); /* Save BREAK status; restore when done */
+ setbreak(No);
+
+ started = Yes;
+ return TE_OK;
+ }
+
+ Hidden int set_screen_up()
+ {
+ int height;
+ int width;
+ int get_screen_env();
+ int get_cols();
+
+ height = width = 0;
+ scr_mode = get_screen_env(&height, &width);
+
+ switch (scr_mode) {
+ case BIOS:
+ case TE_OK:
+ cols = get_cols();
+ flags = HAS_STANDOUT|CAN_SCROLL;
+ break;
+ case ANSI:
+ flags = HAS_STANDOUT;
+ break;
+ default:
+ return scr_mode; /* Error flag */
+ }
+
+ /* allow x and y in environment variable SCREEN to override */
+ if (height > 0)
+ lines = height;
+ if (width > 0)
+ cols = width;
+ return TE_OK;
+ }
+
+ Hidden int get_screen_env(pheight, pwidth)
+ int *pheight;
+ int *pwidth;
+ {
+ string s;
+ int mode;
+ char screrr;
+ string getenv();
+ string strip();
+ string skip();
+
+ screrr = No;
+ s = getenv("SCREEN");
+ if (s == NULL)
+ return BIOS;
+
+ s = strip(s);
+ switch (*s) {
+ case '\0':
+ return BIOS;
+ case 'a':
+ mode = ANSI;
+ s = skip(s, "ansi");
+ break;
+ case 'A':
+ mode = ANSI;
+ s = skip(s, "ANSI");
+ break;
+ case 'b':
+ mode = BIOS;
+ s = skip(s, "bios");
+ break;
+ case 'B':
+ mode = BIOS;
+ s = skip(s, "BIOS");
+ break;
+ default:
+ mode = BIOS;
+ screrr = Yes;
+ }
+
+ /* *pheight and *pwidth were set to 0 above */
+ s = strip(s);
+ while (isdigit(*s)) {
+ *pheight = *pheight * 10 + (*s++ - '0');
+ }
+ s = strip(s);
+ while (isdigit(*s)) {
+ *pwidth = *pwidth * 10 + (*s++ -'0');
+ }
+ s = strip(s);
+ if (screrr || *s != '\0')
+ return TE_BADSCREEN;
+
+ return mode;
+ }
+
+ Hidden string strip(s)
+ string s;
+ {
+ while (*s == ' ' || *s == '\t')
+ ++s;
+ return s;
+ }
+
+ Hidden string skip(s, pat)
+ string s;
+ string pat;
+ {
+ while (*s && *s == *pat)
+ ++s, ++pat;
+ return s;
+ }
+
+ /* initialise internal administration */
+
+ Hidden int start_trm()
+ {
+ register int y;
+
+ if (linedata == NULL) {
+ if ((linedata = (char**) malloc(lines * sizeof(char*))) == NULL)
+ return TE_NOMEM;
+ for (y = 0; y < lines; y++) {
+ if ((linedata[y] = (char*) malloc(cols * sizeof(char))) == NULL)
+ return TE_NOMEM;
+ }
+ }
+ if (linemode == NULL) {
+ if ((linemode = (char**) malloc(lines * sizeof(char*))) == NULL)
+ return TE_NOMEM;
+ for (y = 0; y < lines; y++) {
+ if ((linemode[y] = (char*) malloc(cols * sizeof(char))) == NULL)
+ return TE_NOMEM;
+ }
+ }
+ if (lenline == 0) {
+ if ((lenline = (intlet *) malloc(lines * sizeof(intlet))) == NULL)
+ return TE_NOMEM;
+ }
+
+ trmundefined();
+ return TE_OK;
+ }
+
+ /*
+ * Termination call.
+ * Beware that it might be called by a catched interrupt even in the middle
+ * of trmstart()!
+ */
+
+ Visible Procedure trmend()
+ {
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmend();\n");
+ #endif
+ if (started && so_mode != Off)
+ standend();
+ if (scr_mode == ANSI) {
+ fflush(stdout);
+ }
+ /* Always turn off RAW mode -- it is unlikely that anybody
+ would want to interface to COMMAND.COM in raw mode.
+ This way, if you were accidentally left in RAW mode
+ because of a crash, it will go away if you re-enter. */
+ setraw(STDIN_HANDLE, No);
+ setbreak(wasbreak);
+
+ started = No;
+ #ifdef VTRMTRACE
+ if (vtrmfp) fclose(vtrmfp);
+ #endif
+ }
+
+ /*
+ * Set all internal statuses to undefined, especially the contents of
+ * the screen, so a hard redraw will not be optimised to heaven.
+ */
+
+ Visible Procedure trmundefined()
+ {
+ register int y, x;
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmundefined();\n");
+ #endif
+
+ cur_y = cur_x = Undefined;
+ so_mode = Undefined;
+
+ for (y = 0; y < lines; y++) {
+ for (x = 0; x < cols; x++) {
+ linedata[y][x] = ' ';
+ linemode[y][x] = PLAIN;
+ }
+ /* they may get printed in scrolling */
+ lenline[y] = cols;
+ }
+ }
+
+ #ifdef VTRMTRACE
+
+ Hidden Procedure check_started(m)
+ char *m;
+ {
+ if (!started) {
+ trmend();
+ if (vtrmfp) fprintf(vtrmfp, "Not started: %s\n", m);
+ exit(TE_TWICE);
+ }
+ }
+ #else
+
+ #define check_started(m) /*empty*/
+
+ #endif
+
+ /*
+ * Sensing the cursor.
+ * (NOT IMPLEMENTED, since there is no way to locally move the cursor.)
+ */
+
+ /*
+ * Sense the current (y, x) cursor position, after a possible manual
+ * change by the user with local cursor motions.
+ * If the terminal cannot be asked for the current cursor position,
+ * or if the string returned by the terminal is garbled,
+ * the position is made Undefined.
+ */
+ Visible Procedure trmsense(sense, format, py, px)
+ string sense;
+ string format;
+ int *py;
+ int *px;
+ {
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmsense(&yy, &xx);\n");
+ #endif
+ check_started("trmsense called outside trmstart/trmend");
+
+ /* *py = *px = Undefined;
+ *
+ *
+ * if (flags&CAN_SENSE && getpos(py, px)) {
+ * if (*py < 0 || lines <= *py || *px < 0 || cols <= *px)
+ * *py = *px = Undefined;
+ * }
+ */
+ *py = *px= Undefined;
+ }
+
+ /*
+ * Putting data on the screen.
+ */
+
+ /*
+ * Fill screen area with given "data".
+ * Characters for which the corresponding chars in "mode" have the value
+ * STANDOUT must be put in inverse video.
+ */
+ Visible Procedure trmputdata(yfirst, ylast, indent, data, mode)
+ int yfirst;
+ int ylast;
+ register int indent;
+ register string data;
+ string mode;
+ {
+ register int y;
+ int x, len, lendata, space;
+
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmputdata(%d, %d, %d, \"%s\");\n",
+ yfirst, ylast, indent, data);
+ #endif
+ check_started("trmputdata called outside trmstart/trmend");
+
+ if (yfirst < 0)
+ yfirst = 0;
+ if (ylast >= lines)
+ ylast = lines-1;
+ space = cols*(ylast-yfirst+1) - indent;
+ if (space <= 0)
+ return;
+ yfirst += indent/cols;
+ indent %= cols;
+ y = yfirst;
+ if (data) {
+ x = indent;
+ lendata = strlen(data);
+ if (ylast == lines-1 && lendata >= space)
+ lendata = space - 1;
+ len = Min(lendata, cols-x);
+ while (/*** len > 0 && ***/ y <= ylast) {
+ put_line(y, x, data, mode, len);
+ y++;
+ lendata -= len;
+ if (lendata > 0) {
+ x = 0;
+ data += len;
+ if (mode != NULL)
+ mode += len;
+ len = Min(lendata, cols);
+ }
+ else
+ break;
+ }
+ }
+ if (y <= ylast)
+ clear_lines(y, ylast);
+ }
+
+ /*
+ * We will try to get the picture:
+ *
+ * op>>>>>>>>>>>op oq
+ * ^ ^ ^
+ * <xskip><-----m1----><---------------od-------------------->
+ * OLD: "You're in a maze of twisty little pieces of code, all alike"
+ * NEW: "in a maze of little twisting pieces of code, all alike"
+ * <-----m1----><----------------nd--------------------->
+ * ^ ^ ^
+ * np>>>>>>>>>>>np nq
+ * where
+ * op, oq, np, nq are pointers to start and end of Old and New data,
+ * and
+ * xskip = length of indent to be skipped,
+ * m1 = length of Matching part at start,
+ * od = length of Differing end on screen,
+ * nd = length of Differing end in data to be put.
+ */
+ Hidden int put_line(y, xskip, data, mode, len)
+ int y;
+ int xskip;
+ string data;
+ string mode;
+ int len;
+ {
+ register char *op, *oq, *mp;
+ char *np, *nq, *mo;
+ int m1, od, nd, delta;
+
+ /* Bugfix GvR 19-June-87: */
+ while (lenline[y] < xskip) {
+ linedata[y][lenline[y]] = ' ';
+ linemode[y][lenline[y]] = PLAIN;
+ lenline[y]++;
+ }
+
+ /* calculate the magic parameters */
+ op = &linedata[y][xskip];
+ oq = &linedata[y][lenline[y]-1];
+ mp = &linemode[y][xskip];
+ np = data;
+ nq = data + len - 1;
+ mo = (mode != NULL ? mode : plain);
+ m1 = 0;
+ while (*op == *np && *mp == *mo && op <= oq && np <= nq) {
+ op++, np++, mp++, m1++;
+ if (mode != NULL) mo++;
+ }
+ od = oq - op + 1;
+ nd = nq - np + 1;
+ /* now we have the picture above */
+
+ if (od==0 && nd==0)
+ return;
+
+ delta = nd - od;
+ move(y, xskip + m1);
+ if (nd > 0) {
+ mo= (mode != NULL ? mode+(np-data) : NULL);
+ put_str(np, mo, nd);
+ }
+ if (delta < 0) {
+ clr_to_eol();
+ return;
+ }
+ lenline[y] = xskip + len;
+ if (cur_x == cols) {
+ cur_y++;
+ cur_x = 0;
+ }
+ }
+
+ /*
+ * Scrolling (part of) the screen up (or down, dy<0).
+ */
+
+ Visible Procedure trmscrollup(yfirst, ylast, by)
+ register int yfirst;
+ register int ylast;
+ register int by;
+ {
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmscrollup(%d, %d, %d);\n", yfirst, ylast, by);
+ #endif
+ check_started("trmscrollup called outside trmstart/trmend");
+
+ if (by == 0)
+ return;
+
+ if (yfirst < 0)
+ yfirst = 0;
+ if (ylast >= lines)
+ ylast = lines-1;
+
+ if (yfirst > ylast)
+ return;
+
+ if (so_mode != Off)
+ standend();
+
+ if (by > 0 && yfirst + by > ylast
+ ||
+ by < 0 && yfirst - by > ylast)
+ {
+ clear_lines(yfirst, ylast);
+ return;
+ }
+
+ switch (scr_mode) {
+ case BIOS:
+ biosscrollup(yfirst, ylast, by);
+ break;
+ case ANSI:
+ if (by > 0 && yfirst == 0) {
+ lf_scroll(ylast, by);
+ }
+ else if (by > 0) {
+ move_lines(yfirst+by, yfirst, ylast-yfirst+1-by, 1);
+ clear_lines(ylast-by+1, ylast);
+ }
+ else {
+ move_lines(ylast+by, ylast, ylast-yfirst+1+by, -1);
+ clear_lines(yfirst, yfirst-by-1);
+ }
+ break;
+ }
+ }
+
+ /*
+ * Synchronization, move cursor to given position (or previous if < 0).
+ */
+
+ Visible Procedure trmsync(y, x)
+ int y;
+ int x;
+ {
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmsync(%d, %d);\n", y, x);
+ #endif
+ check_started("trmsync called outside trmstart/trmend");
+
+ if (0 <= y && y < lines && 0 <= x && x < cols) {
+ move(y, x);
+ }
+ fflush(stdout);
+ }
+
+ /*
+ * Send a bell, visible if possible.
+ */
+
+ Visible Procedure trmbell() {
+ #ifdef VTRMTRACE
+ if (vtrmfp) fprintf(vtrmfp, "\ttrmbell();\n");
+ #endif
+ check_started("trmbell called outside trmstart/trmend");
+ ring_bell();
+ }
+
+ /*
+ * Now for the real work: here are all low level routines that really
+ * differ for BIOS or ANSI mode.
+ */
+
+ /*
+ * BIOS video io is called by generating an 8086 software interrupt,
+ * using lattice's int86() function.
+ * To ease coding, all routines fill in the apropriate parameters in regs,
+ * and then call bios10(code), where code is to be placed in ah.
+ */
+
+ Hidden union REGS regs, outregs;
+
+ /* A macro for speed */
+ #define bios10(code) (regs.h.ah = (code), int86(0x10, ®s, ®s))
+ #define nbios10(code) (regs.h.ah = (code), int86(0x10, ®s, &outregs))
+
+ /* Video attributes: (see the BASIC manual) (used for standout mode) */
+
+ Hidden int video_attr;
+ #define V_NORMAL 7
+ #define V_STANDOUT (7<<4)
+
+ /* Some BIOS only routines */
+
+ Hidden get_cols()
+ {
+ bios10(15);
+ return regs.h.ah;
+ }
+
+ /*
+ * ANSI escape sequences
+ */
+ #define A_CUP "\033[%d;%dH" /* cursor position */
+ #define A_SGR0 "\033[0m" /* set graphics rendition to normal */
+ #define A_SGR7 "\033[7m" /* set graphics rendition to standout */
+ #define A_ED "\033[2J" /* erase display (and cursor home) */
+ #define A_EL "\033[K" /* erase (to end of) line */
+
+ /*
+ * The following routine is the time bottleneck, I believe!
+ */
+
+ Hidden Procedure put_str(data, mode, n)
+ char *data;
+ char *mode;
+ int n;
+ {
+ register char c, mo, so;
+
+ so = so_mode;
+ if (scr_mode == BIOS) {
+ regs.x.cx = 1; /* repition count */
+ regs.h.bh = 0; /* page number */
+ regs.h.bl = video_attr;
+ while (--n >= 0) {
+ c = *data++;
+ mo= (mode != NULL ? *mode++ : PLAIN);
+ if (mo != so) {
+ so= mo;
+ so ? standout() : standend();
+ regs.h.bl = video_attr;
+ }
+ regs.h.al = c /* &CHAR */;
+ nbios10(9);
+ if (cur_x >= cols-1) {
+ linedata[cur_y][cols-1] = c;
+ linemode[cur_y][cols-1] = mo;
+ continue;
+ }
+ regs.h.dh = cur_y;
+ regs.h.dl = cur_x + 1;
+ nbios10(2);
+ linedata[cur_y][cur_x] = c;
+ linemode[cur_y][cur_x]= mo;
+ cur_x++;
+ }
+ }
+ else {
+ while (--n >= 0) {
+ c = *data++;
+ mo= (mode != NULL ? *mode++ : PLAIN);
+ if (mo != so) {
+ so= mo;
+ so ? standout() : standend();
+ }
+ putch(c);
+ linedata[cur_y][cur_x] = c;
+ linemode[cur_y][cur_x]= mo;
+ cur_x++;
+ }
+ }
+ }
+
+ /*
+ * Move to position y,x on the screen
+ */
+
+ Hidden Procedure move(y, x)
+ int y;
+ int x;
+ {
+ if (scr_mode != BIOS && cur_y == y && cur_x == x)
+ return;
+ switch (scr_mode) {
+ case BIOS:
+ regs.h.dh = y;
+ regs.h.dl = x;
+ regs.h.bh = 0; /* Page; must be 0 for graphics */
+ bios10(2);
+ break;
+ case ANSI:
+ cprintf(A_CUP, y+1, x+1);
+ break;
+ }
+ cur_y = y;
+ cur_x = x;
+ }
+
+ Hidden Procedure standout()
+ {
+ so_mode = On;
+ switch (scr_mode) {
+ case BIOS:
+ video_attr = V_STANDOUT;
+ break;
+ case ANSI:
+ cputs(A_SGR7);
+ break;
+ }
+ }
+
+ Hidden Procedure standend()
+ {
+ so_mode = Off;
+ switch (scr_mode) {
+ case BIOS:
+ video_attr = V_NORMAL;
+ break;
+ case ANSI:
+ cputs(A_SGR0);
+ break;
+ }
+ }
+
+ Hidden Procedure clear_lines(yfirst, ylast)
+ int yfirst;
+ int ylast;
+ {
+ register int y;
+
+ if (scr_mode == BIOS) {
+ regs.h.al = 0; /* scroll with al = 0 means blank window */
+ regs.h.ch = yfirst;
+ regs.h.cl = 0;
+ regs.h.dh = ylast;
+ regs.h.dl = cols-1;
+ regs.h.bh = V_NORMAL;
+ bios10(6);
+ for (y = yfirst; y <= ylast; y++)
+ lenline[y] = 0;
+ return;
+ }
+ /* scr_mode == ANSI */
+ if (yfirst == 0 && ylast == lines-1) {
+ if (so_mode == On)
+ standend();
+ move(0, 0); /* since some ANSI'd don't move */
+ cputs(A_ED);
+ cur_y = cur_x = 0;
+ for (y = yfirst; y < ylast; y++)
+ lenline[y] = 0;
+ return;
+ }
+ for (y = yfirst; y <= ylast; y++) {
+ if (lenline[y] > 0) {
+ move(y, 0);
+ clr_to_eol();
+ }
+ }
+ }
+
+ Hidden Procedure clr_to_eol()
+ {
+ if (so_mode == On)
+ standend();
+ switch (scr_mode) {
+ case BIOS:
+ regs.h.bh = 0; /* page */
+ regs.x.cx = lenline[cur_y] - cur_x;
+ regs.h.al = ' ';
+ regs.h.bl = V_NORMAL;
+ bios10(9);
+ break;
+ case ANSI:
+ cputs(A_EL);
+ break;
+ }
+ lenline[cur_y] = cur_x;
+ }
+
+ /* scrolling for BIOS */
+
+ Hidden Procedure biosscrollup(yfirst, ylast, by)
+ int yfirst;
+ int ylast;
+ int by;
+ {
+ regs.h.al = (by < 0 ? -by : by);
+ regs.h.ch = yfirst;
+ regs.h.cl = 0;
+ regs.h.dh = ylast;
+ regs.h.dl = cols-1;
+ regs.h.bh= V_NORMAL;
+ bios10(by < 0 ? 7 : 6);
+ cur_y = cur_x = Undefined;
+ if (by > 0)
+ scr_lines(yfirst, ylast, by, 1);
+ else
+ scr_lines(ylast, yfirst, -by, -1);
+ }
+
+ /* Reset internal administration accordingly */
+
+ Hidden Procedure scr_lines(yfrom, yto, n, dy)
+ int yfrom;
+ int yto;
+ int n;
+ int dy;
+ {
+ register int y, x;
+ char *savedata;
+ char *savemode;
+
+ while (n-- > 0) {
+ savedata = linedata[yfrom];
+ savemode= linemode[yfrom];
+ for (y = yfrom; y != yto; y += dy) {
+ linedata[y] = linedata[y+dy];
+ linemode[y] = linemode[y+dy];
+ lenline[y] = lenline[y+dy];
+ }
+ linedata[yto] = savedata;
+ linemode[yto] = savemode;
+ for (x = 0; x < cols; x++ ) {
+ linedata[yto][x] = ' ';
+ linemode[yto][x] = PLAIN;
+ }
+ lenline[yto] = 0;
+ }
+ }
+
+ Hidden Procedure lf_scroll(yto, by)
+ int yto;
+ int by;
+ {
+ register int n = by;
+
+ move(lines-1, 0);
+ while (n-- > 0) {
+ putch('\n');
+ }
+ scr_lines(0, lines-1, by, 1);
+ move_lines(lines-1-by, lines-1, lines-1-yto, -1);
+ clear_lines(yto-by+1, yto);
+ }
+
+ /* for dumb scrolling, uses and updates internal administration */
+
+ Hidden Procedure move_lines(yfrom, yto, n, dy)
+ int yfrom;
+ int yto;
+ int n;
+ int dy;
+ {
+ while (n-- > 0) {
+ put_line(yto, 0, linedata[yfrom], linemode[yfrom], lenline[yfrom]);
+ yfrom += dy;
+ yto += dy;
+ }
+ }
+
+ Hidden Procedure ring_bell()
+ {
+ switch (scr_mode) {
+ case BIOS:
+ regs.h.al = '\007';
+ regs.h.bl = V_NORMAL;
+ bios10(14);
+ break;
+ case ANSI:
+ putch('\007');
+ break;
+ }
+ }
+
+ /*
+ * Show the current internal statuses of the screen on vtrmfp.
+ * For debugging only.
+ */
+
+ #ifdef SHOW
+ Visible Procedure trmshow(s)
+ char *s;
+ {
+ int y, x;
+
+ if (!vtrmfp)
+ return;
+ fprintf(vtrmfp, "<<< %s >>>\n", s);
+ for (y = 0; y < lines; y++) {
+ for (x = 0; x <= lenline[y] /*** && x < cols ***/ ; x++) {
+ fputc(linedata[y][x], vtrmfp);
+ }
+ fputc('\n', vtrmfp);
+ for (x = 0; x <= lenline[y] && x < cols-1; x++) {
+ if (linemode[y][x] == STANDOUT)
+ fputc('-', vtrmfp);
+ else
+ fputc(' ', vtrmfp);
+ }
+ fputc('\n', vtrmfp);
+ }
+ fprintf(vtrmfp, "CUR_Y = %d, CUR_X = %d.\n", cur_y, cur_x);
+ fflush(vtrmfp);
+ }
+ #endif
+
+ /*
+ * Interrupt handling.
+ *
+ * (This has not properly been tested, nor is it clear that
+ * this interface is what we want. Anyway, it's here for you
+ * to experiment with. What does it do, you may ask?
+ * Assume an interactive program which reads its characters
+ * through trminput. Assume ^C is the interrupt character.
+ * Normally, ^C is treated just like any other character: when
+ * typed, it turns up in the input. The program may understand
+ * input ^C as "quit from the current mode".
+ * Occasionally, the program goes into a long period of computation.
+ * Now it would be uninterruptible, except if it calls a routine,
+ * say pollinterrupt(), at times in its computational loop;
+ * pollinterrupt() magically looks ahead in the input queue,
+ * via trmavail() and trminput(), and if it sees a ^C, discards all input
+ * before that point and returns Yes. It also sets a flag, so that
+ * the interupt "sticks around" until either trminput or trmavail
+ * is called. It is undefined whether typing ^C several times in
+ * a row is seen as one interrupt, or an interrupt followed by input
+ * of ^C's. A program should be prepared for either.)
+ */
+
+ #ifdef NOT_USED
+
+ extern bool intrflag;
+
+ bool trminterrupt()
+ {
+ /* Force a check for ^C which will call handler. */
+ /* (This does a ^C check even if stdin is in RAW mode. */
+ (void) kbhit();
+ return intrflag;
+ }
+
+ #endif /* NOT_USED */
+
+
+ /* Definitions for DOS function calls. */
+
+ #define IOCTL 0x44
+ #define IOCTL_GETDATA 0x4400
+ #define IOCTL_SETDATA 0x4401
+ #define DEVICEBIT 0x80
+ #define RAWBIT 0x20
+
+ #define BREAKCK 0x33
+ #define GET 0x00
+ #define SET 0x01
+
+ #define IOCTL_GETSTS 0x4406
+
+ /*
+ * Terminal input without echo.
+ */
+
+ Visible int trminput()
+ {
+ char c;
+
+ #ifdef NOT_USED
+ intrflag= No;
+ #endif
+ /* Assume stdin is in RAW mode; this turns echo and ^C checks off. */
+ if (read(STDIN_HANDLE, &c, 1) < 1)
+ return -1;
+ else
+ return c;
+ }
+
+ /*
+ * Check for character available.
+ *
+ */
+
+ Visible bool trmavail()
+ {
+ #ifdef NOT_USED
+ intrflag= No;
+ #endif
+ regs.x.ax = IOCTL_GETSTS;
+ regs.x.bx = STDIN_HANDLE;
+ intdos(®s, ®s);
+ if (regs.x.cflag)
+ return -1; /* Error */
+ return regs.h.al != 0;
+ }
+
+ /* Issue an IOCTL to turn RAW for a device on or off. */
+
+ Hidden Procedure setraw(handle, raw)
+ int handle;
+ bool raw;
+ {
+ regs.x.ax = IOCTL_GETDATA;
+ regs.x.bx = handle;
+ intdos(®s, ®s);
+ if (regs.x.cflag || !(regs.h.dl & DEVICEBIT))
+ return; /* Error or not a device -- ignore it */
+ regs.h.dh = 0;
+ if (raw)
+ regs.h.dl |= RAWBIT;
+ else
+ regs.h.dl &= ~RAWBIT;
+ regs.x.ax = IOCTL_SETDATA;
+ intdos(®s, ®s);
+ /* Ignore errors */
+ }
+
+ /* Get the raw bit of a device. */
+
+ Hidden int getraw(handle)
+ int handle;
+ {
+ regs.x.ax = IOCTL_GETDATA;
+ regs.x.bx = handle;
+ intdos(®s, ®s);
+ return !regs.x.cflag &&
+ (regs.h.dh & (DEVICEBIT|RAWBIT)) == (DEVICEBIT|RAWBIT);
+ }
+
+ /* Set the break status. */
+
+ Hidden Procedure setbreak(on)
+ bool on;
+ {
+ bdos(BREAKCK, on, SET);
+ }
+
+ /* Get the break status. */
+
+ Hidden int getbreak()
+ {
+ regs.x.ax = (BREAKCK << 8) | GET;
+ intdos(®s, ®s);
+ return regs.h.dl;
+ }
+
+ Visible int trmsuspend()
+ {
+ return spawnlp(P_WAIT, "COMMAND.COM", NULL) == 0;
+ }
*** /dev/null Fri Jun 7 14:31:40 1991
--- stdwin/Ports/vtrm/os.h Tue May 14 13:45:59 1991
***************
*** 0 ****
--- 1,33 ----
+ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1991. */
+
+ /* Auto-configuration file for vtrm.
+ Edit this if you have portability problems. */
+
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <string.h> /* Or <strings.h> for 4.2 BSD */
+
+ /* is this a termio system ? */
+ #ifdef SYSV
+ #define HAS_TERMIO
+ #endif
+
+ /* 4.2 BSD select() system call available ? */
+ #ifndef SYSV
+ #define HAS_SELECT
+ #endif
+
+ /* can #include <signal.h> ? */
+ #define SIGNAL
+
+ #ifdef SIGNAL
+ #define SIGTYPE void
+ /* type returned by signal handler function: (used to be int) */
+ #endif
+
+ /* can #include <setjmp.h> ? */
+ #define SETJMP
+
+ /* VOID is used in casts only, for quieter lint */
+ /* make it empty if your compiler doesn't have void */
+ #define VOID (void)
*** 0.9.5/Ports/x11/dialog.c Thu Oct 18 13:58:40 1990
--- stdwin/Ports/x11/dialog.c Wed Apr 3 22:10:08 1991
***************
*** 3,8 ****
--- 3,16 ----
#include "x11.h"
#include "llevent.h"
+ /* Forward static function declarations */
+
+ static int dialog _ARGS((char *, char *, int, int, int));
+ static void addbutton _ARGS((int, char *, int, bool, int, int, int, int));
+ static int dialogeventloop _ARGS((int));
+ static int charcode _ARGS((XKeyEvent *));
+ static bool addchar _ARGS((int));
+
/* The kinds of dialogs we know */
#define MESSAGEKIND 0
***************
*** 76,81 ****
--- 84,97 ----
static int promptwidth;
static int buttonwidth;
+ /* Forward static function declarations */
+
+ static bool buttonevent _ARGS((struct button *, XEvent *));
+ static void drawbutton _ARGS((struct button *));
+ static void hilitebutton _ARGS((struct button *, bool));
+ static void gettext _ARGS((char *, int));
+ static void killbuttons _ARGS((void));
+
/* Dialog routine.
Create the window and subwindows, then engage in interaction.
Return the proper return value for waskync or waskstr.
***************
*** 191,200 ****
/* Create the box window and its GC */
! fg= _wgetpixel("menuForeground", "Foreground",
! BlackPixelOfScreen(_ws));
! bg= _wgetpixel("menuBackground", "Background",
! WhitePixelOfScreen(_ws));
box.border= 2*IBORDER;
(void) _wcreate(&box, RootWindowOfScreen(_ws), 0, FALSE, fg, bg);
_wsaveunder(&box, True);
--- 207,214 ----
/* Create the box window and its GC */
! fg = _wgetpixel("menuForeground", "MenuForeground", _w_fgcolor);
! bg = _wgetpixel("menuBackground", "MenuBackground", _w_bgcolor);
box.border= 2*IBORDER;
(void) _wcreate(&box, RootWindowOfScreen(_ws), 0, FALSE, fg, bg);
_wsaveunder(&box, True);
***************
*** 201,206 ****
--- 215,221 ----
XSelectInput(_wd, box.wid,
ExposureMask|KeyPressMask|StructureNotifyMask);
b_gc= _wgcreate(box.wid, _wf->fid, fg, bg);
+ XSetPlaneMask(_wd, b_gc, fg ^ bg);
/* Keep window managers happy:
a name for WM's that insist on displaying a window title;
***************
*** 330,336 ****
/* Add a command button */
! static
addbutton(type, text, ret, def, x, y, width, height)
int type;
char *text;
--- 345,351 ----
/* Add a command button */
! static void
addbutton(type, text, ret, def, x, y, width, height)
int type;
char *text;
***************
*** 559,565 ****
/* Draw procedure to draw a command button or text item */
! static
drawbutton(bp)
struct button *bp;
{
--- 574,580 ----
/* Draw procedure to draw a command button or text item */
! static void
drawbutton(bp)
struct button *bp;
{
***************
*** 590,596 ****
/* Highlight or unhighlight a command button */
! static
hilitebutton(bp, hilite)
struct button *bp;
bool hilite;
--- 605,611 ----
/* Highlight or unhighlight a command button */
! static void
hilitebutton(bp, hilite)
struct button *bp;
bool hilite;
***************
*** 604,610 ****
/* Extract the text from the text item */
! static
gettext(buf, len)
char *buf;
int len;
--- 619,625 ----
/* Extract the text from the text item */
! static void
gettext(buf, len)
char *buf;
int len;
***************
*** 619,625 ****
/* Destroy all buttons and associated data structures */
! static
killbuttons()
{
int i;
--- 634,640 ----
/* Destroy all buttons and associated data structures */
! static void
killbuttons()
{
int i;
*** 0.9.5/Ports/x11/draw.c Thu Oct 18 13:58:40 1990
--- stdwin/Ports/x11/draw.c Tue May 14 13:47:44 1991
***************
*** 6,29 ****
static Window wid;
static GC gc;
! static unsigned long fg, bg;
- /* Start using the given Window ID, GC, fg and bg.
- (I had hoped to use this from the Dialog and Menu modules,
- but this hope didn't come true.) */
-
- static void
- _wusewgc(awid, agc, afg, abg)
- Window awid;
- GC agc;
- unsigned long afg, abg;
- {
- wid= awid;
- gc= agc;
- fg= afg;
- bg= abg;
- }
-
/* Put the current font's ID in the current GC, if non-null.
Called by _wfontswitch. */
--- 6,13 ----
static Window wid;
static GC gc;
! COLOR _w_fgcolor, _w_bgcolor;
/* Put the current font's ID in the current GC, if non-null.
Called by _wfontswitch. */
***************
*** 43,48 ****
--- 27,33 ----
should occur. */
static TEXTATTR saveattr;
+ static COLOR savefgcolor, savebgcolor;
void
wbegindrawing(win)
***************
*** 51,58 ****
_wtrace(4, "wbegindrawing(win = 0x%lx)", (long)win);
if (wid != 0)
_werror("recursive wbegindrawing");
! _wusewgc(win->wa.wid, win->gca, win->fga, win->bga);
saveattr= wattr;
wsettextattr(&win->attr);
if (win->caretshown)
_winvertcaret(win); /* Hide caret temporarily */
--- 36,50 ----
_wtrace(4, "wbegindrawing(win = 0x%lx)", (long)win);
if (wid != 0)
_werror("recursive wbegindrawing");
! savefgcolor = _w_fgcolor;
! savebgcolor = _w_bgcolor;
saveattr= wattr;
+ wid = win->wa.wid;
+ gc = win->gca;
+ _w_fgcolor = win->fga;
+ _w_bgcolor = win->bga;
+ XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
+ XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
wsettextattr(&win->attr);
if (win->caretshown)
_winvertcaret(win); /* Hide caret temporarily */
***************
*** 68,76 ****
if (wid != win->wa.wid)
_werror("wrong call to enddrawing");
else {
if (win->caretshown)
_winvertcaret(win); /* Put it back on */
! _wusewgc((Window)0, (GC)0, 0L, 0L); /* Clear all */
wsettextattr(&saveattr);
XFlush(_wd);
}
--- 60,74 ----
if (wid != win->wa.wid)
_werror("wrong call to enddrawing");
else {
+ wnoclip();
if (win->caretshown)
_winvertcaret(win); /* Put it back on */
! _w_fgcolor = savefgcolor;
! _w_bgcolor = savebgcolor;
! XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
! XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
! wid = 0;
! gc = 0;
wsettextattr(&saveattr);
XFlush(_wd);
}
***************
*** 230,237 ****
--- 228,237 ----
_wtrace(7, "wxorline((h1,v1)=(%d,%d), (h2,v2)=(%d,%d))",
h1, v1, h2, v2);
XSetFunction(_wd, gc, GXinvert);
+ XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
XDrawLine(_wd, wid, gc, h1, v1, h2, v2);
XSetFunction(_wd, gc, GXcopy);
+ XSetPlaneMask(_wd, gc, AllPlanes);
}
/* Draw a rectangle *inside* the given coordinate box */
***************
*** 259,267 ****
Can't set function to GXclear because it doesn't work
with color. So we fill with the background color. */
! XSetForeground(_wd, gc, bg);
XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
! XSetForeground(_wd, gc, fg);
}
/* Invert the bits in the given rectangle.
--- 259,267 ----
Can't set function to GXclear because it doesn't work
with color. So we fill with the background color. */
! XSetForeground(_wd, gc, (unsigned long) _w_bgcolor);
XFillRectangle(_wd, wid, gc, left, top, right-left, bottom-top);
! XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
}
/* Invert the bits in the given rectangle.
***************
*** 275,282 ****
if (left >= right || top >= bottom)
return;
!
_winvert(wid, gc, left, top, right-left, bottom-top);
}
/* Paint a given rectangle black */
--- 275,287 ----
if (left >= right || top >= bottom)
return;
!
! /* _winvert assumes the plane mask is the XOR of fg and bg color;
! this is no longer standard now we support colors... */
!
! XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
_winvert(wid, gc, left, top, right-left, bottom-top);
+ XSetPlaneMask(_wd, gc, AllPlanes);
}
/* Paint a given rectangle black */
***************
*** 318,327 ****
int radius;
{
_wtrace(7, "wdrawcircle(h=%d, v=%d, radius=%d)", h, v, radius);
! XDrawArc(_wd, wid, gc, h-radius, v-radius, 2*radius, 2*radius,
0, 360*64);
}
/* Draw an elliptical arc.
The begin and end angles are specified in degrees (I'm not sure this
is a good idea, but I don't like X's degrees*64 either...).
--- 323,360 ----
int radius;
{
_wtrace(7, "wdrawcircle(h=%d, v=%d, radius=%d)", h, v, radius);
! XDrawArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
0, 360*64);
}
+ /* Fill a circle with given center and radius */
+
+ void
+ wfillcircle(h, v, radius)
+ int h, v;
+ int radius;
+ {
+ _wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
+ XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
+ 0, 360*64);
+ }
+
+ /* Invert a circle with given center and radius */
+
+ void
+ wxorcircle(h, v, radius)
+ int h, v;
+ int radius;
+ {
+ _wtrace(7, "wfillcircle(h=%d, v=%d, radius=%d)", h, v, radius);
+ XSetFunction(_wd, gc, GXinvert);
+ XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ XFillArc(_wd, wid, gc, h-radius, v-radius, 2*radius-1, 2*radius-1,
+ 0, 360*64);
+ XSetFunction(_wd, gc, GXcopy);
+ XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+
/* Draw an elliptical arc.
The begin and end angles are specified in degrees (I'm not sure this
is a good idea, but I don't like X's degrees*64 either...).
***************
*** 336,345 ****
{
_wtrace(7, "wdrawelarc(%d, %d, %d, %d, %d, %d)",
h, v, hhalf, vhalf, angle1, angle2);
! XDrawArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf, 2*vhalf,
angle1*64, angle2*64);
}
/* Clip drawing output to a rectangle. */
void
--- 369,449 ----
{
_wtrace(7, "wdrawelarc(%d, %d, %d, %d, %d, %d)",
h, v, hhalf, vhalf, angle1, angle2);
! XDrawArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
angle1*64, angle2*64);
}
+ /* Fill an elliptical arc segment */
+
+ void
+ wfillelarc(h, v, hhalf, vhalf, angle1, angle2)
+ int h, v; /* Center */
+ int hhalf, vhalf; /* Half axes */
+ int angle1, angle2; /* Begin, end angle */
+ {
+ _wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
+ h, v, hhalf, vhalf, angle1, angle2);
+ XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
+ angle1*64, angle2*64);
+ }
+
+ /* Invert an elliptical arc segment */
+
+ void
+ wxorelarc(h, v, hhalf, vhalf, angle1, angle2)
+ int h, v; /* Center */
+ int hhalf, vhalf; /* Half axes */
+ int angle1, angle2; /* Begin, end angle */
+ {
+ _wtrace(7, "wfillelarc(%d, %d, %d, %d, %d, %d)",
+ h, v, hhalf, vhalf, angle1, angle2);
+ XSetFunction(_wd, gc, GXinvert);
+ XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ XFillArc(_wd, wid, gc, h-hhalf, v-vhalf, 2*hhalf-1, 2*vhalf-1,
+ angle1*64, angle2*64);
+ XSetFunction(_wd, gc, GXcopy);
+ XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+
+ /* Draw n-1 lines connecting n points */
+
+ void
+ wdrawpoly(n, points)
+ int n;
+ POINT *points;
+ {
+ _wtrace(7, "wdrawpoly(%d, ...)", n);
+ XDrawLines(_wd, wid, gc, (XPoint *)points, n, CoordModeOrigin);
+ }
+
+ /* Fill a polygon given by n points (may be self-intersecting) */
+
+ void
+ wfillpoly(n, points)
+ int n;
+ POINT *points;
+ {
+ _wtrace(7, "wfillpoly(%d, ...)", n);
+ XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
+ Complex, CoordModeOrigin);
+ }
+
+ /* Invert a polygon given by n points (may be self-intersecting) */
+
+ void
+ wxorpoly(n, points)
+ int n;
+ POINT *points;
+ {
+ _wtrace(7, "wfillpoly(%d, ...)", n);
+ XSetFunction(_wd, gc, GXinvert);
+ XSetPlaneMask(_wd, gc, _w_fgcolor ^ _w_bgcolor);
+ XFillPolygon(_wd, wid, gc, (XPoint *)points, n,
+ Complex, CoordModeOrigin);
+ XSetFunction(_wd, gc, GXcopy);
+ XSetPlaneMask(_wd, gc, AllPlanes);
+ }
+
/* Clip drawing output to a rectangle. */
void
***************
*** 362,365 ****
--- 466,518 ----
wnoclip()
{
XSetClipMask(_wd, gc, None);
+ }
+
+
+ /* Color stuff. */
+
+ void
+ _w_initcolors()
+ {
+ _w_fgcolor = _wgetpixel("foreground", "Foreground",
+ BlackPixelOfScreen(_ws));
+ _w_bgcolor = _wgetpixel("background", "Background",
+ WhitePixelOfScreen(_ws));
+
+ /* Swap the pixel values if 'reverse' specified */
+ if (_wgetbool("reverse", "Reverse", 0)) {
+ unsigned long temp= _w_fgcolor;
+ _w_fgcolor = _w_bgcolor;
+ _w_bgcolor = temp;
+ }
+ }
+
+ COLOR
+ wgetfgcolor()
+ {
+ return _w_fgcolor;
+ }
+
+ COLOR
+ wgetbgcolor()
+ {
+ return _w_bgcolor;
+ }
+
+ void
+ wsetfgcolor(color)
+ COLOR color;
+ {
+ _w_fgcolor = color;
+ if (gc != 0)
+ XSetForeground(_wd, gc, (unsigned long) _w_fgcolor);
+ }
+
+ void
+ wsetbgcolor(color)
+ COLOR color;
+ {
+ _w_bgcolor = color;
+ if (gc != 0)
+ XSetBackground(_wd, gc, (unsigned long) _w_bgcolor);
}
More information about the Alt.sources
mailing list