home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Merciful 3
/
Merciful_Release_3.bin
/
software
/
e
/
elanv1.00.lha
/
elan
/
src
/
os2
/
console.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-13
|
14KB
|
608 lines
#define INCL_WIN
#define INCL_GPI
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "system.h"
#include "console.h"
#include "coredefs.h"
#define CON_COLS (MAP_COLS + 30)
#define CON_ROWS (MAP_ROWS + 20)
void EXPENTRY windowthread(ULONG arg);
MRESULT EXPENTRY ElanProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
void paintch(void);
void makerect(RECTL *r, short r1, short c1, short r2, short c2);
void makepos(POINTL *p, short r, short c);
void rect2path(HPS hps, RECTL *r);
static const long colormap[] = { CLR_BLACK, CLR_BLUE, CLR_RED, CLR_PINK,
CLR_GREEN, CLR_CYAN, CLR_YELLOW, CLR_WHITE, CLR_DARKGRAY,
CLR_DARKBLUE, CLR_DARKRED, CLR_DARKPINK, CLR_DARKGREEN,
CLR_DARKCYAN, CLR_BROWN, CLR_PALEGRAY };
colors_pair pen_colors[PEN_NUMBER];
char screentext[CON_ROWS * CON_COLS];
int screencolor[CON_ROWS * CON_COLS];
HEV initializationsem;
int initresult;
HWND elanhwnd;
HWND framehwnd;
TID thr;
HAB elanhab;
HMQ elanhmq;
int curr_pen = 0;
signed char row;
signed char col;
HQUEUE kbq;
short cursorvisible;
short cursorenabled;
HPS hps;
HMTX psaccess;
short textoffs;
short sizex;
short sizey;
int open_console(const char *title_string, int x, int y, int l, int h)
{
elanhab = WinInitialize(0L);
elanhmq = WinCreateMsgQueue(elanhab, 0L);
memset(screentext, ' ', sizeof(screentext));
memset(screencolor, 0, sizeof(screencolor));
if(DosCreateEventSem(0, &initializationsem, 0, FALSE) == 0 &&
DosCreateMutexSem(0, &psaccess, 0, FALSE) == 0 &&
DosCreateQueue(&kbq, 0, "\\QUEUES\\ELAN\\KBQUEUE") == 0 &&
DosCreateThread(&thr, windowthread, (ULONG)title_string, 0, 65536) == 0 &&
DosWaitEventSem(initializationsem, SEM_INDEFINITE_WAIT) == 0 &&
initresult == 0)
{
DosCloseEventSem(initializationsem);
}
else
{
initresult = 1;
WinDestroyMsgQueue(elanhmq);
WinTerminate(elanhab);
}
return initresult;
}
void EXPENTRY windowthread(ULONG arg)
{
HAB hab;
HMQ hmq;
QMSG qmsg;
ULONG fcf = FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON |
FCF_BORDER | FCF_TASKLIST | FCF_ICON;
initresult = 0;
hab = WinInitialize(0L);
hmq = WinCreateMsgQueue(hab, 0L);
WinRegisterClass(hab, "Elan", ElanProc, CS_SYNCPAINT, 0L);
if((framehwnd = WinCreateStdWindow(HWND_DESKTOP, WS_ANIMATE,
&fcf, "Elan", (char *)arg, WS_VISIBLE, 0L, 1L, &elanhwnd)) == 0)
initresult = 1;
DosPostEventSem(initializationsem);
if(initresult == 0)
{
/* Event loop
*/
while(WinGetMsg(hab, &qmsg, 0, 0, 0))
WinDispatchMsg(hab, &qmsg);
}
WinDestroyWindow(framehwnd);
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
}
MRESULT EXPENTRY ElanProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static HAB hab;
static LONG incr[CON_COLS + 1];
MRESULT ret = (MRESULT)FALSE;
SIZEL size;
RECTL rec;
RECTL back;
HDC hdc;
POINTL pos;
FATTRS font;
short wndx;
short wndy;
LONG len;
LONG run;
LONG offs;
SIZEF box;
FONTMETRICS fm;
short y;
short i;
short tmp;
FONTMETRICS *afm = NULL;
LONG count = 0;
short xlimit;
short ylimit;
short dist;
short mindist;
short found;
switch(msg)
{
case WM_CREATE :
ret = (MRESULT)TRUE;
size.cx = 0;
size.cy = 0;
hab = WinQueryAnchorBlock(hwnd);
hdc = WinOpenWindowDC(hwnd);
hps = GpiCreatePS(hab, hdc, &size, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
if(hps != 0)
{
memset(&font, 0, sizeof(font));
font.usRecordLength = sizeof(font);
count = GpiQueryFonts(hps, QF_PUBLIC, "System VIO", &count,
sizeof(*afm), (PFONTMETRICS)NULL);
if((afm = malloc(sizeof(*afm) * count)) != 0)
{
GpiQueryFonts(hps, QF_PUBLIC, "System VIO",
&count, sizeof(*afm), afm);
xlimit = (0.75 * WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)) / CON_COLS;
ylimit = (0.75 * (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR))) / CON_ROWS;
found = -1;
for(i = 0; i < count; i++)
{
if(! (afm[i].fsDefn & FM_DEFN_OUTLINE) &&
afm[i].lMaxBaselineExt <= ylimit &&
afm[i].lAveCharWidth <= xlimit)
{
dist = (ylimit - afm[i].lMaxBaselineExt) + (xlimit - afm[i].lAveCharWidth);
if(found == -1 || dist < mindist)
{
mindist = dist;
found = i;
}
}
}
if(found != -1)
{
strcpy(font.szFacename, afm[found].szFacename);
font.idRegistry = afm[found].idRegistry;
font.lMaxBaselineExt = afm[found].lMaxBaselineExt;
font.lAveCharWidth = afm[found].lAveCharWidth;
GpiCreateLogFont(hps, 0, 42, &font);
GpiSetCharSet(hps, 42);
GpiQueryFontMetrics(hps, sizeof(fm), &fm);
sizex = fm.lMaxCharInc;
sizey = fm.lEmHeight * 1.3 + fm.lExternalLeading;
textoffs = fm.lMaxDescender + (sizey - fm.lEmHeight - fm.lExternalLeading) / 2;
for(i = 0; i < CON_COLS + 1; i++)
incr[i] = sizex;
wndx = 2 * WinQuerySysValue(HWND_DESKTOP, SV_CXBORDER) +
CON_COLS * sizex;
wndy = WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR) +
2 * WinQuerySysValue(HWND_DESKTOP, SV_CYBORDER) +
CON_ROWS * sizey;
WinSetWindowPos(WinQueryWindow(hwnd, QW_PARENT), 0, 10, 10,
wndx, wndy, SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE);
WinStartTimer(hab, hwnd, 100, WinQuerySysValue(HWND_DESKTOP, SV_CURSORRATE));
cursorvisible = 0;
cursorenabled = 0;
ret = (MRESULT)FALSE;
}
free(afm);
}
}
break;
case WM_DESTROY :
if(DosWriteQueue(kbq, 27, 0, 0, 0) == 0 &&
DosWriteQueue(kbq, 27, 0, 0, 0) == 0)
GpiDestroyPS(hps);
else
DosBeep(880, 100);
break;
case WM_CHAR :
if(! (SHORT1FROMMP(mp1) & KC_KEYUP) && SHORT1FROMMP(mp2) != 0)
if(DosWriteQueue(kbq, SHORT1FROMMP(mp2), 0, 0, 0) != 0)
DosBeep(880, 100);
ret = (MRESULT)TRUE; /* eat event */
break;
case WM_PAINT :
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
WinBeginPaint(hwnd, hps, &rec);
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_OVERPAINT);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
for(y = 0; y < CON_ROWS; y++)
{
pos.x = 0;
pos.y = sizey * (CON_ROWS - 1 - y) + textoffs;
offs = CON_COLS * y;
run = 0;
do
{
len = 1;
while(run + len < CON_COLS && screencolor[offs + len] == screencolor[offs])
len++;
GpiSetMix(hps, FM_OVERPAINT);
GpiSetColor(hps, colormap[pen_colors[screencolor[offs]].fg]);
GpiSetBackColor(hps, colormap[pen_colors[screencolor[offs]].bg]);
makerect(&back, y, run, y, run + len);
GpiCharStringPosAt(hps, &pos, &back, CHS_VECTOR | CHS_OPAQUE,
len, screentext + offs, incr);
pos.x += len * sizex;
offs += len;
run += len;
}
while(run < CON_COLS);
pos.y -= sizey;
}
WinEndPaint(hps);
DosReleaseMutexSem(psaccess);
ret = (MRESULT)FALSE;
break;
case WM_TIMER :
if(cursorenabled && DosRequestMutexSem(psaccess, SEM_IMMEDIATE_RETURN) == 0)
{
makerect(&rec, row, col, row, col);
GpiSetColor(hps, CLR_WHITE);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_XOR);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
cursorvisible = 1 - cursorvisible;
DosReleaseMutexSem(psaccess);
}
break;
default :
ret = WinDefWindowProc(hwnd, msg, mp1, mp2);
break;
}
return ret;
}
void close_console()
{
WinPostMsg(elanhwnd, WM_QUIT, MPVOID, MPVOID);
DosWaitThread(&thr, DCWW_WAIT);
DosCloseMutexSem(psaccess);
DosCloseQueue(kbq);
WinDestroyMsgQueue(elanhmq);
WinTerminate(elanhab);
}
char read_char()
{
REQUESTDATA req;
void *data;
ULONG size;
BYTE pri;
DosReadQueue(kbq, &req, &size, &data, 0, DCWW_WAIT, &pri, 0);
return req.ulData;
}
char async_read_char()
{
REQUESTDATA req;
void *data;
ULONG size;
BYTE pri;
char c;
if(DosReadQueue(kbq, &req, &size, &data, 0, DCWW_NOWAIT, &pri, 0) == ERROR_QUE_EMPTY)
c = 0;
else
c = req.ulData;
return c;
}
void con_printf(const char *format_string,...)
{
char buffer[STRING_MAX_LEN];
va_list arg_list;
va_start(arg_list, format_string);
vsprintf(buffer, format_string, arg_list);
write_string(buffer);
}
void begin_redraw()
{
hide_cursor();
clear_screen();
}
void end_redraw()
{
show_cursor();
}
int register_pen(colors_pair pair)
{
static int last_pen = 0;
int pen;
for(pen = 0; pen < last_pen; pen++)
if(pen_colors[pen].fg == pair.fg && pen_colors[pen].bg == pair.bg)
return pen;
pen_colors[last_pen] = pair;
pen_colors[reverse_pen(last_pen)].fg = pair.bg;
pen_colors[reverse_pen(last_pen)].bg = pair.fg;
return last_pen++;
}
void set_pen(int pen)
{
curr_pen = pen;
}
void locate(signed char i, signed char j)
{
RECTL rec;
if(cursorvisible)
{
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
makerect(&rec, row, col, row, col);
GpiSetColor(hps, CLR_WHITE);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_XOR);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
cursorvisible = 0;
DosReleaseMutexSem(psaccess);
}
row = i;
col = j;
}
void clear_screen()
{
memset(screentext, ' ', sizeof(screentext));
memset(screencolor, 0, sizeof(screencolor));
}
void clear_to_eos()
{
RECTL rec;
short pos = CON_COLS * row + col;
memset(screentext + pos, ' ', sizeof(screentext) - pos * sizeof(screentext[0]));
memset(screencolor + pos, 0, sizeof(screencolor) - pos * sizeof(screencolor[0]));
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
makerect(&rec, row, col, row, CON_COLS - 1);
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_OVERPAINT);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
makerect(&rec, row + 1, 0, CON_ROWS - 1, CON_COLS - 1);
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_OVERPAINT);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
DosReleaseMutexSem(psaccess);
}
void clear_to_eol()
{
RECTL rec;
short pos = CON_COLS * row + col;
short size = CON_COLS - col;
memset(screentext + pos, ' ', size * sizeof(screentext[0]));
memset(screencolor + pos, 0, size * sizeof(screencolor[0]));
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
makerect(&rec, row, col, row, CON_COLS - 1);
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_OVERPAINT);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
DosReleaseMutexSem(psaccess);
}
void show_cursor()
{
cursorenabled = 1;
}
void hide_cursor()
{
RECTL rec;
cursorenabled = 0;
if(cursorvisible)
{
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
makerect(&rec, row, col, row, col);
GpiSetColor(hps, CLR_WHITE);
GpiSetBackColor(hps, CLR_BLACK);
GpiSetMix(hps, FM_XOR);
GpiBeginPath(hps, 1L);
rect2path(hps, &rec);
GpiEndPath(hps);
GpiFillPath(hps, 1L, FPATH_ALTERNATE);
cursorvisible = 0;
DosReleaseMutexSem(psaccess);
}
}
void write_char(char output_char)
{
if(output_char == 0x0a)
{
col = 0;
row++;
if(row == CON_ROWS)
row = 0;
}
else
{
screentext[CON_COLS * row + col] = output_char;
screencolor[CON_COLS * row + col] = curr_pen;
paintch();
col++;
if(col == CON_COLS)
{
col = 0;
row++;
if(row == CON_ROWS)
row = 0;
}
}
}
void write_string(const char *string)
{
while(*string)
{
if(*string == 0x0a)
{
col = 0;
row++;
if(row == CON_ROWS)
row = 0;
}
else
{
screentext[CON_COLS * row + col] = *string;
screencolor[CON_COLS * row + col] = curr_pen;
paintch();
col++;
if(col == CON_COLS)
{
col = 0;
row++;
if(row == CON_ROWS)
row = 0;
}
}
string++;
}
}
void paintch(void)
{
short offs = CON_COLS * row + col;
POINTL pos;
RECTL back;
DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
GpiSetMix(hps, FM_OVERPAINT);
GpiSetColor(hps, colormap[pen_colors[screencolor[offs]].fg]);
GpiSetBackColor(hps, colormap[pen_colors[screencolor[offs]].bg]);
makepos(&pos, row, col);
makerect(&back, row, col, row, col);
GpiCharStringPosAt(hps, &pos, &back, CHS_OPAQUE, 1, screentext + offs, 0);
DosReleaseMutexSem(psaccess);
}
void makerect(RECTL *r, short r1, short c1, short r2, short c2)
{
short t;
if(r2 < r1)
t = r1, r1 = r2, r2 = t;
if(c2 < c1)
t = c1, c1 = c2, c2 = t;
r->xLeft = sizex * c1;
r->xRight = sizex * c2 + sizex - 1;
r->yTop = sizey * (CON_ROWS - 1 - r1) + sizey - 1;
r->yBottom = sizey * (CON_ROWS - 1 - r2);
}
void makepos(POINTL *p, short r, short c)
{
p->x = sizex * c;
p->y = sizey * (CON_ROWS - 1 - r) + textoffs;
}
void rect2path(HPS hps, RECTL *r)
{
POINTL pos;
pos.x = r->xLeft;
pos.y = r->yBottom;
GpiMove(hps, &pos);
pos.x = r->xRight;
pos.y = r->yBottom;
GpiLine(hps, &pos);
pos.x = r->xRight;
pos.y = r->yTop;
GpiLine(hps, &pos);
pos.x = r->xLeft;
pos.y = r->yTop;
GpiLine(hps, &pos);
pos.x = r->xLeft;
pos.y = r->yBottom;
GpiLine(hps, &pos);
}