guido@cwi.nl (Guido van Rossum) (06/07/91)
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); }