home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
s12628.zip
/
PMACCESS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-01
|
26KB
|
772 lines
/* pmaccess.c RHS
*
* application that uses PMSERVER for accessing PM services
*
*
*/
#define INCL_SUB
#define INCL_DOSERRORS
#define INCL_DOS
#include<os2.h>
#include<mt\stdio.h>
#include<mt\string.h>
#include<mt\stdlib.h>
#include<mt\process.h>
#include<mt\dos.h>
#include"mou.h"
#include"kbd.h"
#include"pmserver.h"
#include"moudefs.h"
#include"kbddefs.h"
#include"msgq.h"
#include"button.h"
#include"errexit.h"
#include"msgs.h"
#define MAINMSGQUEUE "\\QUEUES\\PMLITE.QUE"
#define VIOHDL 0
#define KEYTHREADSTACK 500 // keyboard stack
#define REQUESTTHREADSTACK 500 // request stack
#define MOUTHREADSTACK 800 // mouse stack
#define BORDERCOL 79
#define BORDERROW 17
#define BORDERROW2 21
#define STARTROW 0
#define ENDROW 20
#define BUTTON_ON 0x70
#define BUTTON_OFF 0x0f
#define NORMAL BUTTON_OFF
#define HIGHLIGHT BUTTON_ON
#define beep() DosBeep(440,200)
#define Lastchar(str) (str[strlen(str)-1])
#define MAXREQUESTCOUNT 10
#define REQUESTTHREADSLEEPTIME 3000L
/********************* Buttons ****************************/
#define BUTTONLIST 13
BUTTON buttonlist[BUTTONLIST] =
{
/* text title row,col,row,col,attr, type left val, right val,
accelerator */
{" ","Application Name",
18,16, 0, 0, BUTTON_OFF, INPUT, MSG_APPNAME,
MSG_APPNAME,
ALT_1, 0},
{" ", "Topic Name",
18,43, 0, 0, BUTTON_OFF, INPUT, MSG_TOPICNAME,
MSG_TOPICNAME,
ALT_2, 0},
{" ", "Item Name",
18,62, 0, 0, BUTTON_OFF, INPUT, MSG_ITEMNAME,
MSG_ITEMNAME,
ALT_3, 0},
{"Copy","", 22, 0, 0, 0, BUTTON_OFF, BPRESS, MSG_COPY, MSG_COPY,
ALT_O, 0},
{"Cut","", 22, 7, 0, 0, BUTTON_OFF, BPRESS, MSG_CUT, MSG_CUT,
ALT_U, 0},
{"Paste","", 22,13, 0, 0, BUTTON_OFF, BPRESS, MSG_PASTE, MSG_PASTE,
ALT_P, 0},
{"Initiate","",22,23,0, 0, BUTTON_OFF, BPRESS, MSG_INIT, MSG_INIT,
ALT_I, 0},
{"Request","",22,34, 0, 0, BUTTON_OFF, BPRESS, MSG_REQUEST,
MSG_REQUEST,
ALT_R, 0},
{"Advise","", 22,44, 0, 0, BUTTON_OFF, BPRESS, MSG_ADVISE,
MSG_ADVISE,
ALT_A},
{"Terminate","",22,53,0,0, BUTTON_OFF, BPRESS, MSG_TERM, MSG_TERM,
ALT_T, 0},
{"Clear","", 22,67, 0, 0, BUTTON_OFF, BPRESS, MSG_CLR, MSG_CLR,
ALT_C, 0},
{"Esc","", 22,75, 0, 0, BUTTON_OFF, BPRESS, MSG_ESCAPE,
MSG_ESCAPE,
ESC, 0},
{NULL, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0}
};
/**********************************************************/
typedef struct _screen_label
{
PCHAR text;
SHORT row;
SHORT column;
} SCREEN_LABEL;
#define SCREEN_LABELS 4
SCREEN_LABEL screen_labels[SCREEN_LABELS] =
{
{"Clipboard Functions", BORDERROW2, 1},
{"DDE Functions", BORDERROW2, 35},
{"Gen'l", BORDERROW2, 72},
{"DDE Parameters:", BORDERROW+2, 0}
};
PCHAR mainmsgqueue = MAINMSGQUEUE;
BYTE MouThreadStack[MOUTHREADSTACK];
BYTE KbdThreadStack[KEYTHREADSTACK];
BYTE RequestThreadStack[REQUESTTHREADSTACK];
long MouSem = 0L, KbdSem = 0L;
unsigned BlankCell = 0x0f20;
USHORT dirrow = BORDERROW;
USHORT DDEstartrow,DDEstartcol,DDEendrow,DDEendcol;
USHORT rowBlockBeg,colBlockBeg,startBlock,ScreenRows,ScreenCols,
blocksize;
USHORT startrow,startcol,endrow,endcol;
BYTE highlight_att = HIGHLIGHT,normal_att = NORMAL;
PBYTE blockptr, bufptr;
HQUEUE pmshdl;
BYTE tempbuffer[8192];
USHORT clipboard_data = TRUE, dde_init = FALSE, Server = FALSE;
PIDINFO pidinfo;
char appname[MAXAPPNAME], topicname[MAXTOPICNAME],
itemname[MAXITEMLEN];
BUTTON *app, *topic, *item;
/********************* Function Prototypes ********************/
void main(void);
void RequestThread(void);
void InitScreen(void);
void SetBlock(USHORT row, USHORT col);
void ResetScreen(void);
void BlankBlock(void);
void ResetBlock(void);
void ButtonPress(USHORT *eventcode);
USHORT prepare_CLPBRDblock(void);
void PMS_Init(HQUEUE serverhandle,char *qname);
void PMS_Terminate(HQUEUE serverhandle);
USHORT readtextblock(PCHAR buffer,
USHORT srow, USHORT scol, USHORT erow, USHORT ecol);
void activate_entrybutton(BUTTON *b, char *buttonfield);
void main(void)
{
USHORT pause = 0, msg, capture, valid_block, msgsize, retval, i;
USHORT post_on = FALSE,row,col;
HQUEUE qhandle;
PVOID *msgdata;
BUTTON *b;
PBYTE p;
app = &buttonlist[0];
topic = &buttonlist[1];
item = &buttonlist[2];
*appname = *topicname = *itemname = '\0';
DosGetPID(&pidinfo); // get process id
MsgQCreate(&qhandle,MAINMSGQUEUE);
if(retval = MsgQOpen(&pmshdl,PMSERVERQUE))
error_exit(retval,
"MsgQOpen - PM Server probably hasn\'t started...");
DosSemSet(&MouSem);
DosSemSet(&KbdSem);
//start other threads
if(_beginthread(MouThread,MouThreadStack,
sizeof(MouThreadStack),NULL) == -1)
error_exit(0,"_beginthread(Mouse)");
if(_beginthread(KbdThread,KbdThreadStack,
sizeof(KbdThreadStack),NULL) == -1)
error_exit(0,"_beginthread(Keyboard)");
if(_beginthread(RequestThread,RequestThreadStack,
sizeof(RequestThreadStack),NULL) == -1)
error_exit(0,"_beginthread(Request)");
DosSemWait(&MouSem,SEM_INDEFINITE_WAIT); // get threads going
DosSemWait(&KbdSem,SEM_INDEFINITE_WAIT);
InitButtons();
InitScreen();
DisplayButtons();
VioGetBuf((PULONG)&bufptr, &msg, VIOHDL);
PMS_Init(pmshdl,MAINMSGQUEUE);
while(TRUE)
{
MsgQGet(qhandle, &msgdata, &msgsize, &msg);
if(ButtonEvent(msg))
ButtonPress(&msg);
switch(msg)
{
case MSG_ESCAPE:
case ESC:
MsgQClose(qhandle); // close queue
// clear the screen
VioScrollUp(0,0,-1,-1,-1,(char *)&BlankCell,VIOHDL);
PMS_Terminate(pmshdl);
DosExit(EXIT_PROCESS,0); // get out of Dodge
break;
case MSG_CLR: // clear screen
VioScrollUp(0,0,BORDERROW-1,ScreenCols,0xffff,
(char *)&BlankCell,VIOHDL);
InitScreen();
DisplayButtons();
VioWrtCharStr(appname,strlen(appname),
app->startrow+1,app->startcol+1,VIOHDL);
VioWrtCharStr(topicname,strlen(topicname),
topic->startrow+1,topic->startcol+1,VIOHDL);
VioWrtCharStr(itemname,strlen(itemname),
item->startrow+1,item->startcol+1,VIOHDL);
MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
PMS_CLPBRD_QUERY);
VioSetCurPos(0,0,VIOHDL);
MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
break;
// ************* Mouse Message handling
case MSG_B1DOWN:
// clear any existing block and set up a new one
valid_block = FALSE;
ResetScreen();
capture = TRUE;
rowBlockBeg = MOUMSG(msgdata)->row;
colBlockBeg = MOUMSG(msgdata)->col;
startBlock = (rowBlockBeg * ScreenCols)+colBlockBeg;
SetBlock(rowBlockBeg,colBlockBeg);
VioSetCurPos(rowBlockBeg,colBlockBeg,VIOHDL);
break;
case MSG_MOUSEMOVED:
if(capture)
SetBlock(MOUMSG(msgdata)->row,
MOUMSG(msgdata)->col);
break;
case MSG_B1UP:
if(capture)
{
capture = FALSE;
valid_block = TRUE;
SetBlock(MOUMSG(msgdata)->row,
MOUMSG(msgdata)->col);
}
break;
case MSG_APPNAME:
activate_entrybutton(app,appname);
break;
case MSG_ITEMNAME:
activate_entrybutton(item,itemname);
break;
case MSG_TOPICNAME:
activate_entrybutton(topic,topicname);
break;
case MSG_RESETINITBUTTON:
findbutton("Initiate",&b);
ButtonPaint(b,(BYTE)(dde_init ?
BUTTON_ON : BUTTON_OFF));
break;
case MSG_RESETPASTEBUTTON:
findbutton("Paste", &b);
ButtonPaint(b,(BYTE)(clipboard_data ?
BUTTON_ON : BUTTON_OFF));
break;
// ************* Keyboard message handling
case MSG_CHAR:
{
int c = KBDMSG(msgdata)->chChar;
VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
b = IsButton(row,col);
if(b)
if(c == '\r')
break;
else if((c == '\b') && (col == b->startcol+1))
break;
if(!b || ((col > b->startcol) && (col < b->endcol)))
VioWrtTTY((PCH)&c,1,VIOHDL);
switch(c)
{
case '\b':
if(b && (row == b->startcol+1))
break;
VioWrtTTY(" \b",2,VIOHDL);
break;
case '\r':
if(row == ScreenRows)
VioScrollUp(0,0,BORDERROW-1,ScreenCols,1,
(char *)&BlankCell,VIOHDL);
else
VioWrtTTY("\n",1,VIOHDL);
break;
}
}
break;
case MSG_UPARROW:
case MSG_DOWNARROW:
case MSG_LEFTARROW:
case MSG_RIGHTARROW:
case MSG_HOME:
case MSG_END:
{
BUTTON *b;
USHORT start = 0,end = ScreenCols-1;
VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
if(b = IsButton(row,col))
{
start = b->startcol+1;
end = b->endcol-1;
}
switch(msg)
{
case MSG_UPARROW:
if(!b && (row > 0))
row--;
break;
case MSG_DOWNARROW:
if(!b && (row < BORDERROW))
row++;
break;
case MSG_LEFTARROW:
if(col > start)
col--;
break;
case MSG_RIGHTARROW:
if(col < end)
col++;
break;
case MSG_HOME:
col = start;
break;
case MSG_END:
col = end;
break;
}
VioSetCurPos(row,col,VIOHDL);
}
break;
// *******************Clipboard handling****************
case MSG_COPY: // user copy to clipboard
case MSG_CUT: // user cut to clipboard
if(!valid_block) // if no block selected
{
beep(); // warn user
break; // forget it
}
i = prepare_CLPBRDblock();
// pass data to server
MsgQSend(pmshdl,tempbuffer,i,PMS_CLPBRD_COPY);
if(msg == MSG_CUT) // reset screen
BlankBlock();
else
ResetBlock();
valid_block = FALSE;
break;
case MSG_PASTE: // user paste
MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
PMS_CLPBRD_PASTE);
break;
// ********************DDE handling*********************
case MSG_INIT: // user wants dde
if(dde_init) // if dde active
{
beep();
break;
}
{
CLIENTDATA *pclientdata = (CLIENTDATA *)tempbuffer;
PBYTE p;
ButtonRead(app,appname); // get app name
ButtonRead(topic,topicname); // get topic name
pclientdata->pid = pidinfo.pid; // set up PID
strcpy(pclientdata->qname,appname);// add app name
p = pclientdata->qname;
p += strlen(p)+1;
strcpy(p,topicname); // add topic name
p += strlen(p)+1;
if(i = (p-(PBYTE)pclientdata)) // size
{
// request initiation of DDE conversation
dde_init = TRUE;
MsgQSend(pmshdl,tempbuffer,i,PMS_DDE_INIT);
}
}
break;
case MSG_REQUEST:
case MSG_ADVISE:
case MSG_TERM:
{
int i;
if(!dde_init)
beep();
else
{
CLIENTDATA *pclientdata =
(CLIENTDATA *)tempbuffer;
pclientdata->pid = pidinfo.pid; // set up PID
ButtonRead(item,itemname);
strcpy(pclientdata->qname,itemname);
i = sizeof(PID)+strlen(pclientdata->qname)+1;
switch(msg)
{
case MSG_REQUEST:
MsgQSend(pmshdl,tempbuffer,i,
PMS_DDE_REQUEST);
break;
case MSG_ADVISE:
MsgQSend(pmshdl,tempbuffer,i,
PMS_DDE_ADVISE);
break;
case MSG_TERM:
MsgQSend(pmshdl,tempbuffer,sizeof(PID),
PMS_DDE_TERMINATE);
dde_init = FALSE;
ButtonDisplay(app);
ButtonDisplay(topic);
ButtonDisplay(item);
MsgQSend(qhandle,0,0,
MSG_RESETINITBUTTON);
break;
}
}
}
break;
// **************** PMServer message handling ***********
case PMS_CLPBRD: // data available
case PMS_CLPBRD_EMPTY: // clpbrd is empty
clipboard_data = ((msg == PMS_CLPBRD) ? TRUE :
FALSE);
MsgQSend(qhandle,0,0,MSG_RESETPASTEBUTTON);
break;
case PMS_DDE_INITACK: // DDE available
MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
beep();
break;
case PMS_DDE_INITNAK: // DDE not available
dde_init = FALSE;
beep();
break;
case PMS_DDE_TERMINATE: // DDE conversation terminated
if(dde_init)
{
dde_init = FALSE;
beep();
MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
}
break;
case PMS_CLPBRD_DATA: // clipboard data rec'd
case PMS_DDE_DATA: // dde data rec'd
{
PITEMREQ pitemreq = (PITEMREQ)msgdata;
PBYTE mptr;
if(msg == PMS_DDE_DATA)
{
if(stricmp(pitemreq->item,itemname))
break;
mptr = pitemreq->value;
msgsize = strlen(mptr)+1;
}
else
mptr = (PBYTE)msgdata;
VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
for(i = 0, p = (PBYTE)mptr; *p; p++)
if(*p == 13) // if a linefeed
i++; // # of lines in text
if(row+i > ScreenRows)
{
int j = (row+i)-ScreenRows;
VioScrollUp(0,0,BORDERROW-1,ScreenCols,j,
(char *)&BlankCell,VIOHDL);
row -= j;
VioSetCurPos(row,col,VIOHDL);
}
VioWrtTTY((PCH)mptr,msgsize-1,VIOHDL);
if(msg == PMS_CLPBRD_DATA)
MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
PMS_CLPBRD_QUERY);
}
break;
case PMS_NO_INIT: // server can't init
error_exit(msg,
"PMS_Init - unable to access PM Server");
break;
case PMS_SERVER_TERM: // server has terminated
error_exit(msg,
"PMAccess: Server had terminated, exiting");
Server = FALSE;
break;
case PMS_INIT_ACK: // server initialized
Server = TRUE;
clipboard_data = FALSE; // then fall thru
default:
break;
}
if(msgdata != NULL)
DosFreeSeg(SELECTOROF(msgdata));
}
}
// terminates PMServer connection
void PMS_Terminate(HQUEUE serverhandle)
{
// terminate connection
MsgQSend(serverhandle,&pidinfo.pid,sizeof(PID),PMS_TERMINATE);
MsgQClose(serverhandle); // close queue
}
// initializes PMServer connection
void PMS_Init(HQUEUE serverhandle,char *qname)
{
CLIENTDATA clientdata;
strcpy(clientdata.qname,qname); // set up qname
clientdata.pid = pidinfo.pid; // set up PID
// initialize connection
MsgQSend(serverhandle,&clientdata,sizeof(clientdata),PMS_INIT);
}
// prepare data for clipboard
USHORT prepare_CLPBRDblock(void)
{
return readtextblock(tempbuffer,startrow,startcol,endrow,endcol);
}
// read text from screen
USHORT readtextblock(PCHAR buffer,USHORT srow, USHORT scol,
USHORT erow, USHORT ecol)
{
USHORT i,row,len,col;
for( row = srow, col = scol, i = 0; row <= erow; row++)
{
len = ScreenCols;
if(row != srow)
col = 0;
if(row == erow)
len = ecol+1;
VioReadCharStr(&buffer[i],&len,row,col,VIOHDL);
i += len-1;
while(buffer[i] == ' ')
i--;
buffer[++i] = '\r';
buffer[++i] = '\n';
i++;
}
buffer[i] = '\0';
return i+1; // return length of block
}
// set screen text block
void SetBlock(USHORT row, USHORT col)
{
USHORT endBlock = (row * ScreenCols) + col;
USHORT presize,postsize,start;
if(startBlock <= endBlock) // block end at/after start
{
// normal from top to startBlock-1,
// highlight from startBlock to endBlock
// normal from endBlock+1 to bottom
presize = startBlock;
startrow = rowBlockBeg;
startcol = colBlockBeg;
blocksize = endBlock-startBlock+1;
endBlock++;
endrow = (endBlock/ScreenCols);
endcol = (endBlock%ScreenCols);
postsize = (ScreenRows*ScreenCols)-endBlock+1;
}
else // block end before start
{
// normal from top to endBlock-1
// highlight from endBlock to startBlock
// normal from startBlock+1 to bottom
presize = endBlock;
startrow = row;
startcol = col;
blocksize = startBlock-endBlock+1;
start = startBlock+1;
endrow = (start/ScreenCols);
endcol = (start%ScreenCols);
postsize = (ScreenRows*ScreenCols)-start+1;
}
blockptr = bufptr+presize; // set to beginning of block
// now write pre-block and post-block normal, highlight block
VioWrtNAttr(&normal_att,presize,0,0,VIOHDL);
VioWrtNAttr(&highlight_att,blocksize,startrow,startcol,VIOHDL);
VioWrtNAttr(&normal_att,postsize,endrow,endcol,VIOHDL);
}
// reset screen work area
void ResetScreen(void)
{
USHORT i;
for( i = STARTROW; i <= ENDROW; i++)
VioWrtNAttr(&normal_att,BORDERCOL,STARTROW,0,VIOHDL);
}
// blank screen text block
void BlankBlock(void)
{
VioWrtNCell((PBYTE)&BlankCell,blocksize,startrow,startcol,
VIOHDL);
}
// reset screen to normal
void ResetBlock(void)
{
VioWrtNAttr(&normal_att,(ScreenCols*ScreenRows),0,0,
VIOHDL);
}
// initialize screen
void InitScreen(void)
{
SHORT i;
char c = 196;
VIOMODEINFO modeinfo;
VioGetMode(&modeinfo,VIOHDL); // get screen mode, rows, cols
ScreenCols = modeinfo.col;
ScreenRows = modeinfo.row;
if(ScreenRows > BORDERROW-1)
ScreenRows = BORDERROW-1;
VioScrollUp(0,0,-1,-1,-1,(char *)&BlankCell,VIOHDL); // clear scr
VioSetCurPos(0,0,VIOHDL); // set cursor
VioWrtNChar(&c,ScreenCols,BORDERROW,0,VIOHDL); // draw border
VioWrtNChar(&c,ScreenCols,BORDERROW2,0,VIOHDL); // draw border
for( i = 0; i < SCREEN_LABELS; i++) // write labels
VioWrtCharStr(screen_labels[i].text,
strlen(screen_labels[i].text),
screen_labels[i].row,screen_labels[i].column,VIOHDL);
}
// manipulate buttons for specific event code and button type
void ButtonPress(USHORT *eventcode)
{
BUTTON *b = &buttonlist[0];
MOUSECODEOFF(*eventcode); // turn off mouse bit
for( ; b->text; b++) // find the button
if((b->left_button_val == *eventcode) ||
(b->right_button_val == *eventcode) ||
(b->accelerator == *eventcode))
{
switch(b->type)
{
case BPRESS: // if a press button
ButtonPaint(b,BUTTON_ON); // turn it on
DosSleep(100L); // wait
ButtonPaint(b,BUTTON_OFF); // turn it off
break;
case BTOGGLE: // if a toggle button
b->state = !b->state; // toggle it
// and toggle color
ButtonPaint(b,(b->state ? (BYTE)BUTTON_ON :
b->attribute));
break;
default:
break;
}
return;
}
}
void activate_entrybutton(BUTTON *b, char *buttonfield)
{
int i;
ButtonRead(b,buttonfield); // read button
for(i = 0; buttonfield[i]; i++); // get # of chars
// cursor to end
VioSetCurPos(b->startrow+1,b->startcol+1+i,VIOHDL);
}
/******* end of main thread code **************************/
/******* start of request thread code *********************/
// periodically wakes up and queries PMServer about Clipboard
void RequestThread(void)
{
USHORT count = 0;
while(TRUE)
{
if(!clipboard_data && Server) // if invalidated
// ask if paste
MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
PMS_CLPBRD_QUERY);
DosSleep(REQUESTTHREADSLEEPTIME); // sleep a while
count++;
if(count >= MAXREQUESTCOUNT) // count over limit?
{
clipboard_data = FALSE; // invalidate flag
count = 0; // reset count
}
}
}
/******* end of request thread code ***********************/
/********************** end of pmlite.c ********************/