home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
fed0217s.zip
/
source
/
vio.cpp
< prev
Wrap
C/C++ Source or Header
|
2001-11-06
|
22KB
|
837 lines
/*
** Module :VIO.C
** Abstract :Screen and keyboard I/O routines
**
** Copyright (C) Sergey I. Yevtushenko
**
** Log: Wed 29/01/1997 Created
** Sun 09/11/1997 Some minor changes and updates
*/
#include <string.h>
#include <stdio.h>
#include <vio.h>
#include <fio.h>
#include <_ctype.h>
#include <keynames.h>
#include <version.h>
#include <pmproc.h>
#define ScreenOffset(Row,Col) (((Row) * Cols + (Col)) << 1)
#define ScreenPtr(Row,Col) \
((((Row) * Cols + (Col)) << 1) < BufLen ? \
(&Screen[(((Row) * Cols + (Col)) << 1)]): \
0)
BOOL (APIENTRY *_inCloseClipbrd)(HAB);
HMQ (APIENTRY *_inCreateMsgQueue)(HAB, LONG);
BOOL (APIENTRY *_inDestroyMsgQueue)(HMQ);
BOOL (APIENTRY *_inEmptyClipbrd)(HAB);
HAB (APIENTRY *_inInitialize)(ULONG);
BOOL (APIENTRY *_inOpenClipbrd)(HAB);
ULONG(APIENTRY *_inQueryClipbrdData)(HAB, ULONG);
BOOL (APIENTRY *_inQueryClipbrdFmtInfo)(HAB, ULONG, PULONG);
BOOL (APIENTRY *_inSetClipbrdData)(HAB, ULONG, ULONG, ULONG);
BOOL (APIENTRY *_inTerminate)(HAB);
HSWITCH (APIENTRY *_inQuerySwitchHandle)(HWND, PID);
ULONG (APIENTRY *_inQuerySwitchEntry)(HSWITCH, PSWCNTRL);
ULONG (APIENTRY *_inChangeSwitchEntry)(HSWITCH, PSWCNTRL);
LONG (APIENTRY *_inQueryWindowText)(HWND, LONG, PCH);
BOOL (APIENTRY *_inSetWindowText)(HWND, PCSZ);
HAB hab;
HMQ hmq;
HWND hwndFrame;
char cOldTitle[257];
HSWITCH hSw;
SWCNTRL swOldData = {0};
static int VioInitComplete = 0;
static VIOCURSORINFO CUR_SAVE;
static void importKey(KeyInfo*, USHORT, USHORT);
KeyInfo kiLastKey;
int init_pm(int)
{
PPIB pib;
PTIB tib;
APIRET rc;
HMODULE hMte = 0;
char loadErr[256];
if(hab || hmq)
return 0;
//Store startup directory
get_cur_dir(StartupDir);
rc = DosGetInfoBlocks(&tib, &pib);
DD_TRACE("DosGetInfoBlocks",rc);
rc = DosQueryModuleName(pib->pib_hmte, FED_MAXPATH, _cFedPATH);
DD_TRACE("DosQueryModuleName",rc);
// rc = DosQueryModuleHandle("PMWIN", &hMte);
// mutex \SEM32\PMDRAG.SEM
rc = 0;
if(pib->pib_ultype < 2) //If this is an full screen session
{
HMTX hMtx = 0;
rc = DosOpenMutexSem((PCH)"\\SEM32\\PMDRAG.SEM", &hMtx);
if(!rc)
DosCloseMutexSem(hMtx);
}
if(!rc)
{
pib->pib_ultype = 3;
rc = DosLoadModule((PCH)loadErr, 256, (PCH)"PMWIN", &hMte);
if(rc)
return 1;
rc = DosQueryProcAddr(hMte, 707, 0, (PFN*)&_inCloseClipbrd);
rc = DosQueryProcAddr(hMte, 716, 0, (PFN*)&_inCreateMsgQueue);
rc = DosQueryProcAddr(hMte, 726, 0, (PFN*)&_inDestroyMsgQueue);
rc = DosQueryProcAddr(hMte, 733, 0, (PFN*)&_inEmptyClipbrd);
rc = DosQueryProcAddr(hMte, 763, 0, (PFN*)&_inInitialize);
rc = DosQueryProcAddr(hMte, 793, 0, (PFN*)&_inOpenClipbrd);
rc = DosQueryProcAddr(hMte, 806, 0, (PFN*)&_inQueryClipbrdData);
rc = DosQueryProcAddr(hMte, 807, 0, (PFN*)&_inQueryClipbrdFmtInfo);
rc = DosQueryProcAddr(hMte, 854, 0, (PFN*)&_inSetClipbrdData);
rc = DosQueryProcAddr(hMte, 888, 0, (PFN*)&_inTerminate);
rc = DosQueryProcAddr(hMte, 841, 0, (PFN*)&_inQueryWindowText);
rc = DosQueryProcAddr(hMte, 877, 0, (PFN*)&_inSetWindowText);
rc = DosLoadModule((PCH)loadErr, 256, (PCH)"PMSHAPI", &hMte);
if(rc)
return 1;
rc = DosQueryProcAddr(hMte, 123, 0, (PFN*)&_inChangeSwitchEntry);
rc = DosQueryProcAddr(hMte, 124, 0, (PFN*)&_inQuerySwitchEntry );
rc = DosQueryProcAddr(hMte, 125, 0, (PFN*)&_inQuerySwitchHandle);
hab = _inInitialize(0);
hmq = _inCreateMsgQueue(hab, 0);
hSw = _inQuerySwitchHandle(0, pib->pib_ulpid);
if(hSw)
{
_inQuerySwitchEntry(hSw, &swOldData);
hwndFrame = swOldData.hwnd;
if(hwndFrame)
_inQueryWindowText(hwndFrame, sizeof(cOldTitle), (PCH)cOldTitle);
}
return 0;
}
return 1;
}
void deinit_pm(void)
{
if(hwndFrame)
set_title(cOldTitle);
_inChangeSwitchEntry(hSw, &swOldData);
if(hmq)
_inDestroyMsgQueue(hmq);
if(hab)
_inTerminate(hab);
}
void set_title(char *title)
{
if(hmq)
{
static char vTitle[FED_MAXPATH]="";
if(strcmp(vTitle, title))
{
SWCNTRL swData = swOldData;
strcpy(vTitle, title);
strncpy(swData.szSwtitle, title, MAXNAMEL);
_inChangeSwitchEntry(hSw, &swData);
_inSetWindowText(hwndFrame, (PCH)title);
}
}
}
void vio_init(void)
{
USHORT blen = 0;
ULONG badr = 0;
HKBD hKbd = 0;
VIOMODEINFO MI;
KBDINFO kbInfo;
APIRET rc;
if(VioInitComplete)
return;
memset(&MI, 0, sizeof(MI));
MI.cb = sizeof(MI);
rc = VioGetMode(&MI, 0);
DD_TRACE("VioGetMode",rc);
VioGetBuf(&badr, &blen, 0);
DD_TRACE("VioGetBuf",rc);
Rows = MI.row;
Cols = MI.col;
Screen = (char *) (((badr >> 3) & 0xffff0000L) | (badr & 0xffffL));
BufLen = blen;
kbInfo.cb = sizeof(KBDINFO);
rc = KbdFlushBuffer(hKbd);
DD_TRACE("KbdFlushBuffer",rc);
rc = KbdGetStatus(&kbInfo, hKbd);
DD_TRACE("KbdGetStatus",rc);
if(!rc)
{
kbInfo.fsMask = KEYBOARD_BINARY_MODE | KEYBOARD_SHIFT_REPORT ;
rc = KbdSetStatus(&kbInfo, hKbd);
DD_TRACE("KbdSetStatus",rc);
}
rc = KbdFlushBuffer(hKbd);
DD_TRACE("KbdFlushBuffer",rc);
rc = DosAllocMem((PPVOID)&AlignedBuffer,
BufLen,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE);
DD_TRACE("DosAllocMem",rc);
rc = VioGetCurType(&CUR_SAVE,0);
DD_TRACE("VioGetCurType",rc);
__nls_init();
init_pm(0);
VioInitComplete = 1;
}
void vio_shutdown(void)
{
deinit_pm();
vio_cls(0x07);
vio_show();
vio_cursor_pos(0, 0);
VioSetCurType(&CUR_SAVE, 0);
}
void vio_read_key(KeyInfo* key)
{
KBDKEYINFO skInfo;
KBDKEYINFO skNewInfo;
HKBD hKbd = 0;
APIRET rc = 0;
USHORT usKey = 0;
USHORT usShift = 0;
key->rep_count = 1;
rc = KbdCharIn(&skInfo, IO_WAIT, hKbd);
if(!rc)
{
usKey = (USHORT)(skInfo.chScan << 8) | skInfo.chChar;
usShift = skInfo.fsState;
key->old_key = usKey;
do
{
rc = KbdPeek(&skNewInfo, hKbd);
if(!rc)
{
if( skInfo.chScan == skNewInfo.chScan
&& skInfo.chChar == skNewInfo.chChar
&& skInfo.fsState== skNewInfo.fsState
&& skInfo.time != skNewInfo.time)
{
rc = KbdCharIn(&skInfo, IO_WAIT, hKbd);
key->rep_count++;
}
else
rc = (APIRET)-1;
}
}
while(!rc);
}
importKey(key, usKey, usShift);
}
void vio_cls(int Color)
{
// memset((unsigned int *)Screen, (Color << 8), BufLen);
vio_fill(Color, ' ');
}
void vio_fill(int Color, int Char)
{
unsigned short *uScr = (unsigned short *)Screen;
int i;
for(i = 0; i < (BufLen /2); i++)
*uScr++ = (unsigned short)((Color << 8) | (Char & 0xFF));
}
void vio_print2(int Row, int Col, char *String, int MaxLen, int Color)
{
vio_print(Row, Col, String, MaxLen, Color);
vio_show_str(Row, Col, MaxLen);
}
void vio_print(int Row, int Col, char *String, int MaxLen, int Color)
{
int i;
char *sptr = ScreenPtr(Row, Col);
if(!String)
return;
if((Cols - Col) < MaxLen)
MaxLen = Cols - Col;
for(i = 0; i < MaxLen; i++)
{
#ifdef __FED_DEBUG__
if(((char*)sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d,\"%s\" (%s,%d)",
Row, Col, String, __FILE__, __LINE__);
#endif
*sptr ++ = (*String) ? (*String):' ';
*sptr++ = (char)Color;
if(*String)
String++;
}
}
void vio_printh(int Row, int Col, char *String, int MaxLen, int Color, int ColorH)
{
int i;
char *sptr = ScreenPtr(Row, Col);
char *Ccolor = (char *) &Color;
if(!String)
return;
if((Cols - Col) < MaxLen)
MaxLen = Cols - Col;
for(i = 0; i < MaxLen; i++)
{
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) \"%s\" (%s,%d)",
Row, Col, String, __FILE__, __LINE__);
#endif
if(*String == SWITCH_CHAR)
{
/*Swap colors*/
Ccolor = (Ccolor == (char *) &Color) ?
((char *) &ColorH):
((char *) &Color);
i--;
}
else
{
*sptr ++ = (*String) ? (*String):' ';
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) \"%s\" (%s,%d)",
Row, Col, String, __FILE__, __LINE__);
#endif
*sptr ++ = *Ccolor;
}
if(*String)
String++;
}
}
void vio_hdraw(int Row, int Col, char Char, int Len, int Color)
{
char *sptr = ScreenPtr(Row, Col);
int i;
if((Cols - Col) < Len)
Len = Cols - Col;
for(i = 0; i < Len; i++)
{
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) (%s,%d)",
Row, Col, __FILE__, __LINE__);
#endif
*sptr ++ = Char;
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) (%s,%d)",
Row, Col, __FILE__, __LINE__);
#endif
*sptr ++ = (char)Color;
}
}
void vio_vdraw(int Row, int Col, char Char, int Len, int Color)
{
char *sptr = ScreenPtr(Row, Col);
int Shift = (Cols - 1) << 1;
int i;
if((Rows - Row) < Len)
Len = Rows - Row;
for(i = 0; i < Len; i++)
{
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) (%s,%d)",
Row, Col, __FILE__, __LINE__);
#endif
*sptr++ = Char;
#ifdef __FED_DEBUG__
if((sptr-Screen) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) (%s,%d)",
Row, Col, __FILE__, __LINE__);
#endif
*sptr++ = (char)Color;
sptr += Shift;
}
}
void vio_box(int Row, int Col, int Hight, int Width, int Type, int Color)
{
static char* sideTypes[]=
{
/*Corners, Top, Bottom, Left, Right sides */
"┌┐└┘──││", /*Single line */
"╒╕└┘═─││", /*Double top */
"╔╗╚╝══║║", /*Double */
"╒╕└╝═─││", /*Double top, resizeable */
"││└┘█─││", /*Single line, bold top */
" "
};
#define UL_Corner 0
#define UR_Corner 1
#define BL_Corner 2
#define BR_Corner 3
#define T_Side 4
#define B_Side 5
#define L_Side 6
#define R_Side 7
if(Type < (sizeof(sideTypes)/sizeof(char *)))
{
vio_hdraw(Row , Col , sideTypes[Type][UL_Corner], 1, Color);
vio_hdraw(Row , Col + Width - 1, sideTypes[Type][UR_Corner], 1, Color);
vio_hdraw(Row + Hight - 1, Col , sideTypes[Type][BL_Corner], 1, Color);
vio_hdraw(Row + Hight - 1, Col + Width - 1, sideTypes[Type][BR_Corner], 1, Color);
vio_hdraw(Row , Col + 1 , sideTypes[Type][T_Side], Width - 2, Color);
vio_hdraw(Row + Hight - 1, Col + 1 , sideTypes[Type][B_Side], Width - 2, Color);
vio_vdraw(Row + 1 , Col , sideTypes[Type][L_Side], Hight - 2, Color);
vio_vdraw(Row + 1 , Col + Width - 1, sideTypes[Type][R_Side], Hight - 2, Color);
}
}
void vio_show(void)
{
VioShowBuf((USHORT) 0, (USHORT)BufLen, 0);
}
void vio_cursor_pos(int row, int col)
{
VioSetCurPos((USHORT)row, (USHORT)col, 0);
}
void vio_cursor_type(int shape)
{
VIOCURSORINFO cursor;
cursor.cEnd = (USHORT)-100;
cursor.cx = 1;
cursor.attr = (USHORT)-1;
if(iShape[0] <= 0)
iShape[0] = 10;
if(iShape[0] >= 100)
iShape[0] = 90;
if(iShape[1] <= 0)
iShape[1] = 10;
if(iShape[1] >= 100)
iShape[1] = 90;
cursor.yStart = (USHORT)(iShape[0] - 100);
switch(shape)
{
case BigCursor:
cursor.yStart = (USHORT)(iShape[1] - 100);
case Underline :
cursor.attr = 0;
case NoCursor :
break;
}
VioSetCurType(&cursor, 0);
}
struct stScreen
{
int Row;
int Col;
int Rows;
int Cols;
char Data[1];
};
void *vio_save_box(int Row, int Col, int Hight, int Width)
{
stScreen * save_data;
if(Hight * Width <= 0 || Row < 0 && Col < 0)
return 0;
save_data = (stScreen *) new char[(sizeof(stScreen) + (Hight*Width) << 1)];
save_data->Row = Row ;
save_data->Col = Col ;
save_data->Rows = Hight;
save_data->Cols = Width;
int offset_sb = 0;
int offset = ScreenOffset(Row, Col);
for(int i = 0; i < Hight; i++)
{
#ifdef __FED_DEBUG__
if(offset + (Width << 1) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) %d (%s,%d)",
Row, Col, offset, __FILE__, __LINE__);
#endif
memcpy(&save_data->Data[offset_sb], &Screen[offset], Width << 1);
offset += Cols << 1;
offset_sb += Width << 1;
}
return save_data;
}
void vio_restore_box(void *data)
{
stScreen * save_data = (stScreen *)data;
if(!save_data)
return;
int offset_sb = 0;
int offset = ScreenOffset(save_data->Row, save_data->Col);
for(int i = 0; i < save_data->Rows; i++)
{
#ifdef __FED_DEBUG__
if(offset + (save_data->Cols << 1) >= (BufLen - 1))
fprintf(stderr, "access out of bounds (%d,%d) %d (%s,%d)",
save_data->Row, save_data->Col, offset, __FILE__, __LINE__);
#endif
memcpy(&Screen[offset], &save_data->Data[offset_sb], save_data->Cols << 1);
VioShowBuf((USHORT)offset, (USHORT)(save_data->Cols << 1), 0);
offset += Cols << 1;
offset_sb += save_data->Cols << 1;
}
delete save_data;
}
void vio_show_str(int Row, int Col, int Len)
{
USHORT offset = (USHORT)ScreenOffset(Row,Col);
VioShowBuf((USHORT)offset, (USHORT)(Len << 1), 0);
}
void vio_show_buf(int Offset, int Len)
{
VioShowBuf((USHORT)Offset, (USHORT)Len, 0);
}
char *vio_set_work_buff(char *buff)
{
char *old = Screen;
Screen = buff;
return old;
}
void importKey(KeyInfo* key, USHORT usKey, USHORT usShift)
{
key->skey = AltKey[usKey >> 8].code;
key->key = (unsigned short)(usKey & 0x00FF);
key->KeyName[0] = 0;
if(key->skey == kbEsc) //ESC-key handling
key->skey |= shIsCtrl;
if(usShift & 8)
key->skey |= shIsCtrl | shAlt;
if(usShift & 4)
key->skey |= shIsCtrl | shCtrl;
if(usShift & 3) //'Shift' pressed
{
key->skey |= shShift;
//Shift can be pressed in many situations
//We will try to separate them into two categories:
//1. Shift pressed with usual alpha-numeric key
//2. Shift pressed with control key
//First try:
// If this key don't have ASCII code this is control key
//Second try:
// Another similar case: ASCII code for this key is 0xE0
//Last try:
// If ASCII code for this key is from '0' to '9', or '.',
// and shift is pressed, we assume that this is control key
// By the way: this codes cant come from another source, because
// from the other sources they come _without_ Shift pressed
if( (usKey & 0x00FF) == 0 ||
(usKey & 0x00FF) == 0xE0 ||
((usKey & 0x00FF) >= '0' && (usKey & 0x00FF) <= '9') ||
((usKey & 0x00FF) == '.' && (usKey & 0xFF00) != 0))
{
key->skey |= shIsCtrl;
}
}
if((usKey & 0x00FF) == 0 ||
((usKey & 0x00FF) == 0xE0 && (usKey & 0xFF00) != 0))
key->skey |= shIsCtrl;
if((usKey & 0x00FF) == 0x0D)
key->skey |= shIsCtrl;
if((usKey & 0x00FF) == 0x08)
key->skey |= shIsCtrl;
if((usKey & 0xFF00) == 0x4A00)
key->skey |= shIsCtrl;
if((usKey & 0xFF00) == 0x4E00)
key->skey |= shIsCtrl;
if(key->skey & shIsCtrl)
{
char *ptr = key->KeyName;
static char cAlt []="Alt";
static char cCtrl []="Ctrl";
static char cShift[]="Shift";
*ptr++ = 'k';
*ptr++ = 'b';
if(key->skey & shAlt)
{
memcpy(ptr, cAlt, sizeof(cAlt) - 1);
ptr += sizeof(cAlt) - 1;
}
if(key->skey & shCtrl)
{
memcpy(ptr, cCtrl, sizeof(cCtrl) - 1);
ptr += sizeof(cCtrl) - 1;
}
if(key->skey & shShift)
{
memcpy(ptr, cShift, sizeof(cShift) - 1);
ptr += sizeof(cShift) - 1;
}
// Copy string from array, including '\x00' terminator
memcpy(ptr, AltKey[usKey >> 8].name, strlen(AltKey[usKey >> 8].name) + 1);
}
else
{
key->KeyName[0] = key->key;
key->KeyName[1] = 0;
}
memcpy(&kiLastKey, key, sizeof(kiLastKey));
}
int cstrlen(char *str)
{
int rc = 0;
if(str)
{
while(*str)
{
if(*str != SWITCH_CHAR)
rc++;
str++;
}
}
return rc;
}
void vio_draw_attr(int Row, int Col, int Len, int Color)
{
char *sptr = ScreenPtr(Row, Col);
int i;
if((Cols - Col) < Len)
Len = Cols - Col;
for(i = 0; i < Len; i++)
{
sptr ++;
*sptr ++ = (char)Color;
}
}
void vio_scroll(int Dir, Rect& rect, int Num, int Attr)
{
static BYTE cell[]= {' ', ' '};
cell[1] = (BYTE)Attr;
switch(Dir)
{
case SCROLL_UP:
VioScrollUp((USHORT)rect.row,
(USHORT)rect.col,
(USHORT)(rect.row + rect.rows - Num),
(USHORT)(rect.col + rect.cols),
(USHORT)Num,
(PBYTE)cell,
0);
break;
case SCROLL_DN:
VioScrollDn((USHORT)rect.row,
(USHORT)rect.col,
(USHORT)(rect.row + rect.rows - Num),
(USHORT)(rect.col + rect.cols),
(USHORT)Num,
(PBYTE)cell,
0);
break;
case SCROLL_LT:
VioScrollLf((USHORT)rect.row,
(USHORT)rect.col,
(USHORT)(rect.row + rect.rows - 1),
(USHORT)(rect.col + rect.cols - Num),
(USHORT)Num,
(PBYTE)cell,
0);
break;
case SCROLL_RT:
VioScrollRt((USHORT)rect.row,
(USHORT)rect.col,
(USHORT)(rect.row + rect.rows - 1),
(USHORT)(rect.col + rect.cols - Num),
(USHORT)Num,
(PBYTE)cell,
0);
break;
}
}
char * cvt_num(unsigned int ulID, int minlen)
{
static char numbuff[12];
char *buff = numbuff;
char *str;
int slen = 0;
str = buff;
do
{
*str++ = (char)((ulID % 10) + '0');
ulID /= 10;
slen++;
}
while(ulID);
while(slen < minlen)
{
*str++ = '0';
slen++;
}
*str-- = 0;
for(; str > buff; str--, buff++)
{
*buff ^= *str;
*str ^= *buff;
*buff ^= *str;
}
return numbuff;
}
char * xcvt_char(int chr)
{
static char numbuff[3];
char nibble;
nibble = (char)(chr >> 4);
numbuff[0] = (char)((nibble > 9) ? (nibble + 'A' - 10) : (nibble + '0'));
nibble = (char)(chr & 0x0F);
numbuff[1] = (char)((nibble > 9) ? (nibble + 'A' - 10) : (nibble + '0'));
numbuff[2] = 0;
return numbuff;
}
char *str_dup(char* str, int len)
{
if(len < 0)
len = (str) ? strlen(str):0;
char *ptr = new char[len+1];
if(len)
{
if(str)
memcpy(ptr, str, len);
else
memset(ptr, ' ', len);
}
ptr[len] = 0;
return ptr;
}
//-----------------------------------------
// Thread level HAB/HMQ handler
//-----------------------------------------
PMObj::PMObj():hab(0),hmq(0)
{
if(!::hmq)
return;
hab = _inInitialize(0);
hmq = _inCreateMsgQueue(hab, 0);
}
PMObj::~PMObj()
{
if(hmq)
_inDestroyMsgQueue(hmq);
if(hab)
_inTerminate(hab);
}