This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/con_dosx.cpp
Gered 43d7eb4f73 properly hook up ScreenSizeX/Y global options & fix related mouse issues
note that 80x43 text mode is not currently working. if the int 10h can
be adjusted to set this mode correctly, the mouse fixes should all work
properly with it too ...
2019-03-31 17:13:55 -04:00

1172 lines
26 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* con_dosx.cpp
*
* Copyright (c) 1994-1996, Marko Macek
* Free 1996 F.Jalvingh
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
*/
// include
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#ifdef DJGPP
#include <sys/stat.h>
#endif
#include "sysdep.h"
#include "console.h"
#include "gui.h"
#include "c_config.h"
#include <stdlib.h>
#include <process.h>
#include "port.h" // DOS portability calls,
#define MAX_PIPES 4
#define PIPE_BUFLEN 4096
typedef struct {
int used;
int id;
// int reading;
int stopped;
// TID tid;
// HMTX Access;
// HEV ResumeRead;
// HEV NewData;
// char *buffer;
// int buflen;
// int bufused;
// int bufpos;
EModel *notify;
// char *Command;
// int RetCode;
// int DoTerm;
FILE *fp;
} GPipe;
static GPipe Pipes[MAX_PIPES] = {
{ 0 }, { 0 }, { 0 }, { 0 }
};
#if defined(__DJGPP__) || defined(WATCOM)
// adapted from djgpp library source - redirects stderr as well as stdout
// Original author: pacetti@fl-ngnet.army.mil
#include <io.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* hold file pointer, descriptor, command, mode, temporary file name,
and the status of the command */
struct pipe_list {
FILE *fp;
int fd;
int exit_status;
char *command, mode[10], temp_name[L_tmpnam];
struct pipe_list *next;
};
/* static, global list pointer */
static struct pipe_list *pl = NULL;
static FILE *
xpopen (const char *cm, const char *md) /* program name, pipe mode */
{
struct pipe_list *l1, *l2;
/* make new node */
if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL)
return NULL;
/* zero out elements to we'll get here */
l1->fd = 0;
l1->fp = NULL;
l1->next = NULL;
/* if empty list - just grab new node */
if (!pl)
pl = l1;
else
{
/* otherwise, find last node in list */
++(l1->fd);
l2 = pl;
while (l2->next)
{
++(l1->fd);
l2 = l2->next;
};
/* add new node to list */
l2->next = l1;
}
/* stick in elements we know already */
l1->exit_status = -1;
strcpy (l1->mode, md);
if (tmpnam (l1->temp_name) == NULL)
return NULL;
/* if can save the program name, build temp file */
if ((l1->command = (char *) malloc(strlen(cm)+1)))
{
strcpy(l1->command, cm);
/* if caller wants to read */
if (l1->mode[0] == 'r')
{
#if 1
int fd2 = -1;
#endif
/* dup stdout */
if ((l1->fd = dup (fileno (stdout))) == EOF)
l1->fp = NULL;
else if (!(l1->fp = freopen (l1->temp_name, "wb", stdout)))
l1->fp = NULL;
#if 1
/* dup stderr */
else if ((fd2 = dup (STDERR_FILENO)) == EOF)
l1->fp = NULL;
/* redirect stderr to new stdout */
else if (dup2(fileno(l1->fp),STDERR_FILENO) == EOF)
l1->fp = NULL;
#endif
else
/* exec cmd */
if ((l1->exit_status = system (cm)) == EOF)
l1->fp = NULL;
/* reopen real stdout */
if (dup2 (l1->fd, fileno (stdout)) == EOF)
l1->fp = NULL;
else
/* open file for reader */
l1->fp = fopen (l1->temp_name, l1->mode);
close(l1->fd);
#if 1
/* restore stderr */
if (fd2 >= 0) {
(void) dup2(fd2, STDERR_FILENO);
(void) close(fd2);
}
#endif
}
else
/* if caller wants to write */
if (l1->mode[0] == 'w')
/* open temp file */
l1->fp = fopen (l1->temp_name, l1->mode);
else
/* unknown mode */
l1->fp = NULL;
}
return l1->fp; /* return == NULL ? ERROR : OK */
}
static int
xpclose (FILE *pp)
{
struct pipe_list *l1, *l2; /* list pointers */
int retval=0; /* function return value */
/* if pointer is first node */
if (pl->fp == pp)
{
/* save node and take it out the list */
l1 = pl;
pl = l1->next;
}
else
/* if more than one node in list */
if (pl->next)
{
/* find right node */
for (l2 = pl, l1 = pl->next; l1; l2 = l1, l1 = l2->next)
if (l1->fp == pp)
break;
/* take node out of list */
l2->next = l1->next;
}
else
return -1;
/* if FILE not in list - return error */
if (l1->fp == pp)
{
/* close the (hopefully) popen()ed file */
fclose (l1->fp);
/* if pipe was opened to write */
if (l1->mode[0] == 'w')
{
/* dup stdin */
if ((l1->fd = dup (fileno (stdin))) == EOF)
retval = -1;
else
/* open temp stdin */
if (!(l1->fp = freopen (l1->temp_name, "rb", stdin)))
retval = -1;
else
/* exec cmd */
if ((retval = system (l1->command)) != EOF)
{
/* reopen stdin */
if (dup2 (l1->fd, fileno (stdin)) == EOF)
retval = -1;
}
close(l1->fd);
}
else
/* if pipe was opened to read, return the exit status we saved */
if (l1->mode[0] == 'r')
retval = l1->exit_status;
else
/* invalid mode */
retval = -1;
}
remove (l1->temp_name); /* remove temporary file */
free (l1->command); /* dealloc memory */
free (l1); /* dealloc memory */
l1 = NULL; /* make pointer bogus */
return retval; /* retval==0 ? OK : ERROR */
}
#endif /* defined(__DJGPP__) */
static long MouseAutoDelay = 400;
static long MouseAutoRepeat = 5;
static long MouseMultiClick = 300;
static int Initialized = 0;
static int MousePresent = 0;
static int CursorVisible = 1; /* 1 means visible */
static int MouseVisible = 0; /* 0 means hidden */
static TEvent MouseEv = { evNone };
static TEvent EventBuf = { evNone };
//static HMOU MouseHandle = 0;
//static KBDINFO SaveKbdState;
// misc
static void DrawCursor(int Show) {
}
static void DrawMouse(int Show)
{
if (!MousePresent) return;
if (Show)
MOUSCursen(TRUE);
else
MOUSCursen(FALSE);
}
static struct { // TransCharScan
unsigned short CharScan;
TKeyCode KeyCode;
} TransCharScan[] = {
{ 0x0100, kbEsc }, { 0x011B, kbEsc },
{ 0x1C0D, kbEnter }, { 0x1C0A, kbEnter },
{ 0x1C00, kbEnter }, { 0xE00D, kbEnter | kfGray },
{ 0xA600, kbEnter | kfGray }, { 0xE00A, kbEnter | kfGray },
{ 0x0E08, kbBackSp }, { 0x0E7F, kbBackSp },
{ 0x0E00, kbBackSp }, { 0x0F09, kbTab },
{ 0x9400, kbTab }, { 0xA500, kbTab },
{ 0x0F00, kbTab }, { 0x4E00, '+' | kfGray },
{ 0x9000, '+' | kfGray }, { 0x4E2B, '+' | kfGray },
{ 0x4A00, '-' | kfGray }, { 0x8E00, '-' | kfGray },
{ 0x4A2D, '-' | kfGray }, { 0x3700, '*' | kfGray },
{ 0x9600, '*' | kfGray }, { 0x372A, '*' | kfGray },
{ 0xE02F, '/' | kfGray }, { 0xA400, '/' | kfGray },
{ 0x9500, '/' | kfGray }, { 0x0300, 0 }
};
static struct { // TransScan
int ScanCode;
TKeyCode KeyCode;
} TransScan[] = {
{ 0x78, '1' }, { 0x79, '2' }, { 0x7A, '3' }, { 0x7B, '4' }, { 0x7C, '5' },
{ 0x7D, '6' }, { 0x7E, '7' }, { 0x7F, '8' }, { 0x80, '9' }, { 0x81, '0' },
{ 0x10, 'Q' }, { 0x11, 'W' }, { 0x12, 'E' }, { 0x13, 'R' }, { 0x14, 'T' },
{ 0x15, 'Y' }, { 0x16, 'U' }, { 0x17, 'I' }, { 0x18, 'O' }, { 0x19, 'P' },
{ 0x1E, 'A' }, { 0x1F, 'S' }, { 0x20, 'D' }, { 0x21, 'F' }, { 0x22, 'G' },
{ 0x23, 'H' }, { 0x24, 'J' }, { 0x25, 'K' }, { 0x26, 'L' },
{ 0x2C, 'Z' }, { 0x2D, 'X' }, { 0x2E, 'C' }, { 0x2F, 'V' }, { 0x30, 'B' },
{ 0x31, 'N' }, { 0x32, 'M' },
{ 0x29, '`' }, { 0x82, '-' }, { 0x83, '=' }, { 0x2B, '\\' }, { 0x1A, '[' },
{ 0x1B, ']' }, { 0x27, ';' }, { 0x28, '\'' }, { 0x33, ',' }, { 0x34, '.' },
{ 0x35, '/' }, { 0x37, '*' }, { 0x4E, '+' }, { 0x4A, '-' },
{ 0x3B, kbF1 }, { 0x3C, kbF2 }, { 0x3D, kbF3 },
{ 0x3E, kbF4 }, { 0x3F, kbF5 }, { 0x40, kbF6 },
{ 0x41, kbF7 }, { 0x42, kbF8 }, { 0x43, kbF9 },
{ 0x44, kbF10 }, { 0x85, kbF11 }, { 0x86, kbF12 },
{ 0x54, kbF1 }, { 0x55, kbF2 }, { 0x56, kbF3 },
{ 0x57, kbF4 }, { 0x58, kbF5 }, { 0x59, kbF6 },
{ 0x5A, kbF7 }, { 0x5B, kbF8 }, { 0x5C, kbF9 },
{ 0x5D, kbF10 }, { 0x87, kbF11 }, { 0x88, kbF12 },
{ 0x5E, kbF1 }, { 0x5F, kbF2 }, { 0x60, kbF3 },
{ 0x61, kbF4 }, { 0x62, kbF5 }, { 0x63, kbF6 },
{ 0x64, kbF7 }, { 0x65, kbF8 }, { 0x66, kbF9 },
{ 0x67, kbF10 }, { 0x89, kbF11 }, { 0x8A, kbF12 },
{ 0x68, kbF1 }, { 0x69, kbF2 }, { 0x6A, kbF3 },
{ 0x6B, kbF4 }, { 0x6C, kbF5 }, { 0x6D, kbF6 },
{ 0x6E, kbF7 }, { 0x6F, kbF8 }, { 0x70, kbF9 },
{ 0x71, kbF10 }, { 0x8B, kbF11 }, { 0x8C, kbF12 },
{ 0x47, kbHome }, { 0x48, kbUp }, { 0x49, kbPgUp },
{ 0x4B, kbLeft }, { 0x4C, kbCenter}, { 0x4D, kbRight },
{ 0x4F, kbEnd }, { 0x50, kbDown }, { 0x51, kbPgDn },
{ 0x52, kbIns }, { 0x53, kbDel },
{ 0x77, kbHome }, { 0x8D, kbUp }, { 0x84, kbPgUp },
{ 0x73, kbLeft }, { 0x74, kbRight },
{ 0x75, kbEnd }, { 0x91, kbDown }, { 0x76, kbPgDn },
{ 0x92, kbIns }, { 0x93, kbDel },
{ 0x97, kbHome | kfGray }, { 0x98, kbUp | kfGray }, { 0x99, kbPgUp | kfGray },
{ 0x9B, kbLeft | kfGray }, { 0x9D, kbRight | kfGray },
{ 0x9F, kbEnd | kfGray }, { 0xA0, kbDown | kfGray }, { 0xA1, kbPgDn | kfGray },
{ 0xA2, kbIns | kfGray }, { 0xA3, kbDel | kfGray }
};
int ReadKbdEvent(TEvent *Event, int Wait)
{
struct plKbdInfo ki;
UBYTE CharCode, ScanCode;
ULONG KeyCode, KeyFlags;
UWORD CharScan, Flags;
static ULONG PrevFlags = 0;
int I;
const int Tcs = (int) (sizeof(TransCharScan)/sizeof(TransCharScan[0]));
const int Ts = (int) (sizeof(TransScan)/sizeof(TransScan[0]));
Event->What = evNone;
if(! plKbdReadF(&ki)) return 0; // No data-> no read..
Event->What = evKeyDown;
CharCode = ki.ki_ascii;
ScanCode = ki.ki_scan;
CharScan = (UWORD)((((UWORD)ScanCode) << 8) | ((UWORD)CharCode));
Flags = ki.ki_flags;
KeyCode = 0;
KeyFlags = 0;
/* printf("Key: %X %X %X %X %X \n", (unsigned long) ki.bNlsShift, (unsigned long) ki.fbStatus, (unsigned long) Flags, (unsigned long) CharCode, (unsigned long) ScanCode);*/
if ((Flags & PLKF_SHIFT) != 0) KeyFlags |= kfShift;
if ((Flags & PLKF_CTRL) != 0) KeyFlags |= kfCtrl;
/* cpCount = sizeof(cpList);*/
/* rc = DosQueryCp(sizeof(cpList), cpList, &cpCount); // get active code page*/
if (CharCode != 0) {
// if ((Flags & PLKF_ALT) != 0) KeyFlags |= kfAlt;
} else {
if((Flags & PLKF_ALT) != 0) KeyFlags |= kfAlt;
}
/* if (rc != 0) printf("rc = %d\n", rc);*/
if (CharScan == 0) { /* shift/alt/ctrl/caps/scroll/num */
} else if (ScanCode == 0) { /* alt numeric */
KeyCode = CharCode;
KeyFlags |= kfAltXXX;
} else { /* now check special combinations */
for (I = 0; I < Tcs; I++)
if (TransCharScan[I].CharScan == CharScan) {
KeyCode = TransCharScan[I].KeyCode;
break;
}
if (KeyCode == 0) {
if ((CharCode == 0) || (CharCode == 0xE0)) {
if (CharCode == 0xE0)
KeyFlags |= kfGray;
for (I = 0; I < Ts; I++)
if (TransScan[I].ScanCode == ScanCode) {
KeyCode = TransScan[I].KeyCode;
break;
}
} else {
KeyCode = CharCode;
}
}
}
Event->Key.Code = KeyCode | KeyFlags;
PrevFlags = Flags;
return 1;
}
#define TM_DIFF(x,y) ((long)(((long)(x) < (long)(y)) ? ((long)(y) - (long)(x)) : ((long)(x) - (long)(y))))
int ReadMouseEvent(TEvent *Event, unsigned long EventMask)
{
static unsigned short PrevState = 0;
static unsigned short PrevButtons = 0;
static TEvent LastMouseEvent = { evNone };
static ULONG LastEventTime = 0;
static ULONG LastClick = 0;
static ULONG LastClickTime = 0;
static ULONG LastClickCount = 0;
// MOUEVENTINFO mi;
unsigned short Buttons, State, Btn;
// USHORT fWait = MOU_NOWAIT;
// MOUQUEINFO mq;
ULONG CurTime;
UWORD cx, cy;
int butf;
boolean rb, lb;
static int Scx = -1, Scy = -1;
static boolean Slb, Srb;
// CurTime = plTmGet(); // 2do!
Event->What = evNone;
//** Distill an event from the current position & button state of the mouse.
MOUSPos(&cx, &cy, &lb, &rb);
cx /= 8;
cy /= 8;
if(Scx == -1)
{
Scx = cx; // Force initial state to here.
Scy = cy;
}
//** Assume something happened.. Set the mouse' position,
butf = (lb ? 0x01 : 0) | (rb ? 0x02 : 0);
Event->Mouse.X = cx;
Event->Mouse.Y = cy;
Event->Mouse.Count = 1;
//** 1. Has the buttons state changed?
if(Slb != lb)
{
Event->What = lb ? evMouseDown : evMouseUp;
Event->Mouse.Buttons = 0x01; //lb ? 0x01 : 0;
Slb = lb;
}
else if(Srb != rb)
{
Event->What = rb ? evMouseDown : evMouseUp;
Event->Mouse.Buttons = 0x02; // rb ? 0x02 : 0;
Srb = rb;
}
else if(cx != Scx || cy != Scy)
{
//** Mouse move.
Event->What = evMouseMove;
Event->Mouse.Buttons = butf;
Event->Mouse.Count = 0;
}
//** Any event?
if(Event->What == evNone)
{
//** Handle repeat here!!
return 0;
}
// printf("[ev=%d, b=%d] ", Event->What, Event->Mouse.Buttons);
//** Something happened..
Scx = cx;
Scy = cy;
return 1;
}
#if 0
MouGetNumQueEl(&mq, MouseHandle);
if (mq.cEvents == 0) {
if (LastMouseEvent.What == evMouseAuto && (EventMask & evMouseAuto)) {
if (TM_DIFF(CurTime, LastEventTime) >= MouseAutoRepeat) {
*Event = LastMouseEvent;
DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
return 1;
}
}
if ((LastMouseEvent.What == evMouseDown || LastMouseEvent.What == evMouseMove)
&&
(LastMouseEvent.Mouse.Buttons)
&& (EventMask & evMouseAuto))
{
if (TM_DIFF(CurTime, LastEventTime) >= MouseAutoDelay) {
LastMouseEvent.What = evMouseAuto;
*Event = LastMouseEvent;
DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
return 1;
}
}
return 0;
}
if (MouReadEventQue(&mi, &fWait, MouseHandle) != 0) return 0;
Event->Mouse.X = mi.col;
Event->Mouse.Y = mi.row;
State = mi.fs;
Btn = Buttons = ((State & (2 | 4))?1:0) |
((State & (8 | 16))?2:0) |
((State & (32 | 64))?4:0);
if (Buttons != PrevButtons) {
Buttons ^= PrevButtons;
if (PrevButtons & Buttons)
Event->What = evMouseUp;
else
Event->What = evMouseDown;
} else
Event->What = evMouseMove;
Event->Mouse.Buttons = Buttons;
Event->Mouse.Count = 1;
PrevState = State;
PrevButtons = Btn;
if (Event->What == evMouseDown) {
if (LastClickCount) {
if (LastClick == Event->Mouse.Buttons) {
if (TM_DIFF(CurTime, LastClickTime) <= MouseMultiClick) {
Event->Mouse.Count = ++LastClickCount;
} else {
LastClickCount = 0;
}
} else {
LastClick = 0;
LastClickCount = 0;
LastClickTime = 0;
}
}
LastClick = Event->Mouse.Buttons;
if (LastClickCount == 0)
LastClickCount = 1;
DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastClickTime, 4);
}
/* if (Event->What == evMouseMove) {
LastClick = 0;
LastClickCount = 0;
LastClickTime = 0;
}*/
{
KBDINFO ki;
USHORT Flags;
TKeyCode KeyFlags = 0;
ki.cb = sizeof(ki);
KbdGetStatus(&ki, 0);
Flags = ki.fsState;
if ((Flags & (LEFTSHIFT | RIGHTSHIFT)) != 0) KeyFlags |= kfShift;
if ((Flags & (LEFTCONTROL | RIGHTCONTROL)) != 0) KeyFlags |= kfCtrl;
if ((Flags & (LEFTALT | RIGHTALT)) != 0) KeyFlags |= kfAlt;
Event->Mouse.KeyMask = KeyFlags;
}
LastMouseEvent = *Event;
DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
return 1;
}
#endif
int ConClear()
{
plScnSetCell(0, 0, plScnWidth(), plScnHeight(), 0x0720);
return 0;
}
int ConPutBox(int X, int Y, int W, int H, PCell Cell) {
int I;
int MX, MY;
int MouseHidden = 0;
char *p = (char *) Cell;
if (MouseVisible)
ConQueryMousePos(&MX, &MY);
for (I = 0; I < H; I++) {
if (MouseVisible)
if (Y + I == MY)
if ((MX >= X) && (MX <= X + W)) {
DrawMouse(0);
MouseHidden = 1;
}
plScnWrite(X, Y+I, (UWORD *)p, W);
if (MouseHidden) {
DrawMouse(1);
MouseHidden = 0;
}
p += W << 1;
}
return 0;
}
int ConGetBox(int X, int Y, int W, int H, PCell Cell) {
int I;
int MX, MY;
int MouseHidden = 0;
// USHORT WW = (U)(W << 1);
char *p = (char *) Cell;
if (MouseVisible)
ConQueryMousePos(&MX, &MY);
for (I = 0; I < H; I++) {
if (MouseVisible)
if (Y + I == MY)
if (MX >= X && MX < X + W) {
DrawMouse(0);
MouseHidden = 1;
}
plScnRead(X, Y+I, (unsigned short*) p, W);
if (MouseHidden) {
DrawMouse(1);
MouseHidden = 0;
}
p += W << 1;
}
return 0;
}
int ConPutLine(int X, int Y, int W, int H, PCell Cell)
{
int I;
int MX, MY;
int MouseHidden = 0;
char *p = (char *) Cell;
if (MouseVisible)
ConQueryMousePos(&MX, &MY);
for (I = 0; I < H; I++) {
if (MouseVisible)
if (Y + I == MY)
if (MX >= X && MX < X + W) {
DrawMouse(0);
MouseHidden = 1;
}
plScnWrite(X, Y+I, (UWORD *) p, W);
if (MouseHidden) {
DrawMouse(1);
MouseHidden = 0;
}
}
return 0;
}
int ConSetBox(int X, int Y, int W, int H, TCell Cell) {
int I;
int MX, MY;
int MouseHidden = 0;
char *p = (char *) &Cell;
if (MouseVisible)
ConQueryMousePos(&MX, &MY);
for (I = 0; I < H; I++) {
if (MouseVisible)
if (Y + I == MY)
if (MX >= X && MX < X + W) {
DrawMouse(0);
MouseHidden = 1;
}
plScnSetCell(X, Y+I, W, 1, (UWORD)Cell);
// VioWrtNCell(p, (USHORT)(W), (USHORT)(Y + I), (USHORT)X, 0);
if (MouseHidden) {
DrawMouse(1);
MouseHidden = 0;
}
}
return 0;
}
int ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count)
{
int MX, MY;
int MouseHidden = 0;
TCell FillCell = (TCell)(Fill << 8);
if (MousePresent && MouseVisible)
{
ConQueryMousePos(&MX, &MY);
if (MX >= X && MX < X + W && MY >= Y && MY < Y + H)
{
DrawMouse(0);
MouseHidden = 1;
}
}
switch (Way)
{
case csUp: plScnScrollUp(X, Y, X+W, Y+H, Count, (UWORD)FillCell); break;
case csDown:plScnScrollDown(X, Y, X+W, Y+H, Count, (UWORD)FillCell); break;
case csLeft:
// VioScrollLf((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
break;
case csRight:
// VioScrollRt((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
break;
}
if (MouseHidden)
DrawMouse(1);
return 0;
}
int ConSetSize(int X, int Y) {
// explicitly turn off/on the mouse and reset it's boundaries at the
// same time. the turn off/on thing ensures the cursor doesn't disappear
// after the screen mode switch
MOUSCursen(FALSE);
plScnSetSize(X, Y);
MOUSSetBounds();
MOUSCursen(TRUE);
return 0;
}
int ConQuerySize(int *X, int *Y) {
*X = plScnWidth();
*Y = plScnHeight();
return 0;
}
int ConSetCursorPos(int X, int Y) {
plScnCursorPos(X, Y);
return 0;
}
int ConQueryCursorPos(int *X, int *Y) {
plScnCursorPosGet(X, Y);
return 0;
}
int ConShowCursor() {
CursorVisible = 1;
plScnCursorOn(TRUE);
return 0;
}
int ConHideCursor() {
CursorVisible = 0;
plScnCursorOn(FALSE);
return 0;
}
int ConSetCursorSize(int Start, int End) {
return 0;
}
//int ConSetMousePos(int X, int Y) {
// return 0;
//}
/****************************************************************************/
/* */
/* CODING: Mouse stuff. */
/* */
/****************************************************************************/
int ConQueryMousePos(int *X, int *Y) {
UWORD a, b;
boolean lb, rb;
if(! MOUSIsPresent()) return -1;
MOUSPos(&a, &b, &lb, &rb);
*X = a / 8;
*Y = b / 8;
return 0;
}
int ConShowMouse()
{
MouseVisible = TRUE;
if(! MOUSIsPresent()) return -1;
MOUSCursen(TRUE);
return 0;
}
int ConHideMouse()
{
MouseVisible = FALSE;
if(! MOUSIsPresent()) return -1;
MOUSCursen(FALSE);
return 0;
}
int ConMouseVisible() {
return MouseVisible;
}
int ConQueryMouseButtons(int *ButtonCount) {
if(ButtonCount != 0) *ButtonCount = 2;
return 0;
}
int ConInit(int XSize, int YSize)
{
if(Initialized) return 0;
EventBuf.What = evNone;
ConSetSize(XSize, YSize);
MousePresent = MOUSInit();
ConContinue();
Initialized = 1;
return 0;
}
int ConDone()
{
return ConSuspend();
}
int ConSuspend()
{
plScnSetFlash(TRUE); // Set "flash" mode, not bright mode
ConHideMouse();
#if defined(SIGBREAK)
signal(SIGBREAK, SIG_DFL);
#endif
signal(SIGINT, SIG_DFL);
return 0;
}
int ConContinue()
{
#if defined(SIGBREAK)
signal(SIGBREAK, SIG_IGN);
#endif
signal(SIGINT, SIG_IGN);
plScnSetFlash(FALSE); // Set "bright" mode, not flashing
ConShowMouse();
return 0;
}
int GetPipeEvent(TEvent *Event) {
#if defined(DJGPP) || defined(WATCOM)
int i;
Event->What = evNone;
for (i = 0; i < MAX_PIPES; i++) {
if (Pipes[i].used == 0) continue;
if (Pipes[i].notify == 0) continue;
if (1) {
//fprintf(stderr, "Pipe New Data: %d\n", i);
Event->What = evNotify;
Event->Msg.View = 0;
Event->Msg.Model = Pipes[i].notify;
Event->Msg.Command = cmPipeRead;
Event->Msg.Param1 = i;
return 1;
}
}
#endif
return 0;
}
int ConGetEvent(TEventMask EventMask, TEvent *Event, int WaitTime, int Delete)
{
if (EventBuf.What != evNone)
{
*Event = EventBuf;
if (Delete) EventBuf.What = evNone;
return 0;
}
if (MouseEv.What != evNone)
{
*Event = MouseEv;
if (Delete) MouseEv.What = evNone;
return 0;
}
EventBuf.What = evNone;
Event->What = evNone;
if(! (ReadKbdEvent(Event, WaitTime) == 1) && (EventMask & evKeyboard))
{
if(MousePresent && (ReadMouseEvent(Event, EventMask) == 1) && (EventMask & evMouse))
;
else
{
if(GetPipeEvent(Event) != 1)
return -1;
}
}
if (Event->What != evNone)
{
if (Event->What == evMouseMove)
{
while (ReadMouseEvent(&MouseEv, EventMask) == 1)
{
if (MouseEv.What == evMouseMove)
{
*Event = MouseEv;
MouseEv.What = evNone;
}
else
break;
}
}
EventBuf = *Event;
if (Delete) EventBuf.What = evNone;
return 0;
}
return -1;
}
static PCell SavedScreen = 0;
static int SavedX, SavedY, SaveCursorPosX, SaveCursorPosY;
int SaveScreen() {
if (SavedScreen)
free(SavedScreen);
ConQuerySize(&SavedX, &SavedY);
SavedScreen = (PCell) malloc(SavedX * SavedY * sizeof(PCell));
if (SavedScreen)
ConGetBox(0, 0, SavedX, SavedY, SavedScreen);
ConQueryCursorPos(&SaveCursorPosX, &SaveCursorPosY);
return 0;
}
int RestoreScreen() {
if (SavedScreen) {
ConSetSize(SavedX, SavedY);
ConPutBox(0, 0, SavedX, SavedY, SavedScreen);
ConSetCursorPos(SaveCursorPosX, SaveCursorPosY);
}
return 1;
}
GUI::GUI(int &argc, char **argv, int XSize, int YSize) {
fArgc = argc;
fArgv = argv;
SaveScreen();
::ConInit(XSize, YSize);
gui = this;
#ifdef DJGPP
// speed up directory access by turning off unused stat functionality
_djstat_flags |= _STAT_INODE;
_djstat_flags |= _STAT_EXEC_EXT;
_djstat_flags |= _STAT_EXEC_MAGIC;
_djstat_flags |= _STAT_DIRSIZE;
_djstat_flags |= _STAT_ROOT_TIME;
_djstat_flags |= _STAT_WRITEBIT;
#endif
}
GUI::~GUI() {
RestoreScreen();
// HACK: clearing the screen to hide the fact that there's something
// screwy going on with the screen restore when using non-80x25 mode
// that i cannot pin down ...
::ConClear();
::ConDone();
if(SavedScreen)
{
free(SavedScreen);
SavedScreen = 0;
}
gui = 0;
}
int GUI::ConSuspend(void) {
RestoreScreen();
return ::ConSuspend();
}
int GUI::ConContinue(void) {
SaveScreen();
return ::ConContinue();
}
int GUI::ShowEntryScreen() {
TEvent E;
ConHideMouse();
RestoreScreen();
do { gui->ConGetEvent(evKeyDown, &E, -1, 1, 0); } while (E.What != evKeyDown);
ConSetSize(ScreenSizeX, ScreenSizeY);
ConShowMouse();
if (frames)
frames->Repaint();
return 1;
}
//static int CreatePipeChild(PID &pid, HPIPE &hfPipe, char *Command) {
// return 0;
//}
static void PipeThread(void *p) {
}
int GUI::OpenPipe(char *Command, EModel *notify) {
#if defined(DJGPP) || defined(WATCOM)
int i;
for (i = 0; i < MAX_PIPES; i++) {
if (Pipes[i].used == 0) {
Pipes[i].id = i;
Pipes[i].notify = notify;
Pipes[i].stopped = 1;
// when a long-ish running command gets run here, sometimes
// the mouse cursor disappears on returning from the command,
// so we turn it off/on here just to be safe
MOUSCursen(FALSE);
Pipes[i].fp = xpopen(Command,"r");
MOUSSetBounds();
MOUSCursen(TRUE);
if (Pipes[i].fp == NULL)
return -1;
Pipes[i].used = 1;
//fprintf(stderr, "Pipe Open: %d\n", i);
return i;
}
}
return -1;
#else
return 0;
#endif
}
int GUI::SetPipeView(int id, EModel *notify) {
#if defined(DJGPP) || defined(WATCOM)
if (id < 0 || id >= MAX_PIPES)
return -1;
if (Pipes[id].used == 0)
return -1;
//fprintf(stderr, "Pipe View: %d %08X\n", id, notify);
Pipes[id].notify = notify;
#endif
return 0;
}
int GUI::ReadPipe(int id, void *buffer, int len) {
#if defined(DJGPP) || defined(WATCOM)
int rc;
if (id < 0 || id >= MAX_PIPES)
return -1;
if (Pipes[id].used == 0)
return -1;
//fprintf(stderr, "Pipe Read: Get %d %d\n", id, len);
rc = fread(buffer,1,len,Pipes[id].fp);
//fprintf(stderr, "Pipe Read: Got %d %d\n", id, rc);
if (ferror(Pipes[id].fp)) {
Pipes[id].stopped = 1;
return 0;
}
return rc == 0 ? -1 : rc;
#else
return 0;
#endif
}
int GUI::ClosePipe(int id) {
#if defined(DJGPP) || defined(WATCOM)
if (id < 0 || id >= MAX_PIPES)
return -1;
if (Pipes[id].used == 0)
return -1;
Pipes[id].used = 0;
//fprintf(stderr, "Pipe Close: %d\n", id);
return xpclose(Pipes[id].fp);
#else
return 0;
#endif
}
int GUI::RunProgram(int mode, char *Command) {
int rc, W, H;
ConQuerySize(&W, &H);
ConHideMouse();
ConSuspend();
if (*Command == 0) // empty string = shell
Command = getenv(
"COMSPEC"
);
rc = system(Command);
ConContinue();
ConShowMouse();
// HACK: there used to be conditional logic here to check if a screen
// resize was actually needed using another call to ConQuerySize() to
// check the current size... i might need to revisit this again, but
// i opted to just always resize and repaint to ensure a consistent
// screen state always.
ConSetSize(W, H);
frames->Resize(W, H);
frames->Repaint();
return rc;
}
int ConSetTitle(char *Title, char *STitle) {
return 0;
}
int ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
strcpy(Title, "FTE");
strcpy(STitle, "FTE");
return 0;
}
int ConCursorVisible() {
return 0;
}
int ConPutEvent(TEvent Event)
{
EventBuf = Event;
return 0;
}
char ConGetDrawChar(int index) {
// static char tab[] = "ڿ<><DABF>ij<EFBFBD>ô<EFBFBD><C3B4>\x1A<31><04><19><>";
static const char tab[] = "ڿ<EFBFBD><EFBFBD>ij<EFBFBD>ô<EFBFBD><EFBFBD>\x1A<EFBFBD>\x04<EFBFBD>\x18\x19<EFBFBD><EFBFBD>\x1B\x1A";
assert(strlen(tab) > 20);
assert(index >= 0);
assert(index >= 0 && index < (int)strlen(tab));
return tab[index];
}