Gered
43d7eb4f73
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 ...
1172 lines
26 KiB
C++
1172 lines
26 KiB
C++
/* 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];
|
||
}
|