home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
VSCPPv8.zip
/
VACPP
/
IBMCPP
/
samples
/
TOOLKIT
/
OS2
/
CONSOLIO
/
WORMS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-17
|
23KB
|
845 lines
/*=========================================================================\
* *
* FILE:worms.c *
* *
* DESCRIPTION: Full Screen Mixed-mode programming sample *
* *
* Created 1991 IBM Corp. *
* *
* DISCLAIMER OF WARRANTIES. The following [enclosed] code is *
* sample code created by IBM Corporation. This sample code is not *
* part of any standard or IBM product and is provided to you solely *
* for the purpose of assisting you in the development of your * *
* applications. The code is provided "AS IS", without *
* warranty of any kind. IBM shall not be liable for any damages *
* arising out of your use of the sample code, even if they have been *
* advised of the possibility of such damages. * *
* *
*-------------------------------------------------------------------------*
* This source file contains the following functions:
*
* main
* WormsMainProcess
* ProcessCmdLine
* ErrorMessage
* WormsExit
*
\*==============================================================*/
/*--------------------------------------------------------------*\
* Include files, macros, defined constants, and externs
\*--------------------------------------------------------------*/
#define INCL_VIO
#define INCL_KBD
#define INCL_MOU
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#include <os2.h>
#include <string.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "worms.h"
#include "wrmthrd.h"
#include "init.h"
#include "wrmhelp.h"
/*--------------------------------------------------------------*\
*Global definitions for this module
\*--------------------------------------------------------------*/
#define STACK_SIZE_WORMTHRD 32678
#define BOX_ROW 6
#define BOX_COL 10
#define HEIGHT_BOX 9
#define BOX_WIDTH 70
#define DEBUG 1
/*--------------------------------------------------------------*\
* Global variables for this module
\*--------------------------------------------------------------*/
SHORT sCurrentThread = 0;
BOOL fThreadsContinue = TRUE;
BOOL fSilent = FALSE;
SHORT sStartWorms = 1;
BOOL fQuit = FALSE; /*Global quit flag all threads*/
BOOL fDraw = TRUE; /*Global draw flag all threads*/
BOOL bHelpEnabled = FALSE;
BOOL bMessage = FALSE;
VIOCURSORINFO viociCursor;
VIOMODEINFO VioModeInfo;
HVIO hvio = 0 ;
THREAD_DATA ThreadData[] =
/* background/text */
/* TID Active Row Col Attribute sCurrentDirection*/
{
0L, FALSE, BOT_ROW / 2 ,FIRST_COL ,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL ,MKATRB(WM_BROWN,WM_CYAN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL / 2,MKATRB(WM_MAGENTA,WM_PALEGRAY),0,
0L, FALSE, FIRST_ROW + 5,RGT_COL / 4,MKATRB(WM_LRED,WM_GREEN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL - 3,MKATRB(WM_YELLOW,WM_WHITE) ,0,
0L, FALSE, BOT_ROW - 4 ,FIRST_COL ,MKATRB(WM_GREEN,WM_LBLUE) ,0,
0L, FALSE, FIRST_ROW + 4,RGT_COL ,MKATRB(WM_BROWN,WM_YELLOW) ,0,
0L, FALSE, BOT_ROW - 2 ,RGT_COL / 2,MKATRB(WM_DKGREY,WM_GREEN) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL / 4,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, BOT_ROW - 3 ,RGT_COL - 3,MKATRB(WM_WHITE,WM_LBLUE) ,0,
0L, FALSE, BOT_ROW / 2 ,FIRST_COL ,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL ,MKATRB(WM_BROWN,WM_CYAN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL / 2,MKATRB(WM_MAGENTA,WM_PALEGRAY),0,
0L, FALSE, FIRST_ROW + 5,RGT_COL / 4,MKATRB(WM_LRED,WM_GREEN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL - 3,MKATRB(WM_YELLOW,WM_WHITE) ,0,
0L, FALSE, BOT_ROW - 4 ,FIRST_COL ,MKATRB(WM_GREEN,WM_LBLUE) ,0,
0L, FALSE, FIRST_ROW + 4,RGT_COL ,MKATRB(WM_BROWN,WM_YELLOW) ,0,
0L, FALSE, BOT_ROW - 2 ,RGT_COL / 2,MKATRB(WM_DKGREY,WM_GREEN) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL / 4,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, BOT_ROW - 3 ,RGT_COL - 3,MKATRB(WM_WHITE,WM_LBLUE) ,0,
0L, FALSE, BOT_ROW / 2 ,FIRST_COL ,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL ,MKATRB(WM_BROWN,WM_CYAN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL / 2,MKATRB(WM_MAGENTA,WM_PALEGRAY),0,
0L, FALSE, FIRST_ROW + 5,RGT_COL / 4,MKATRB(WM_LRED,WM_GREEN) ,0,
0L, FALSE, BOT_ROW ,RGT_COL - 3,MKATRB(WM_YELLOW,WM_WHITE) ,0,
0L, FALSE, BOT_ROW - 4 ,FIRST_COL ,MKATRB(WM_GREEN,WM_LBLUE) ,0,
0L, FALSE, FIRST_ROW + 4,RGT_COL ,MKATRB(WM_BROWN,WM_YELLOW) ,0,
0L, FALSE, BOT_ROW - 2 ,RGT_COL / 2,MKATRB(WM_DKGREY,WM_GREEN) ,0,
0L, FALSE, FIRST_ROW ,RGT_COL / 4,MKATRB(WM_BLUE,WM_RED) ,0,
0L, FALSE, BOT_ROW - 3 ,RGT_COL - 3,MKATRB(WM_WHITE,WM_LBLUE) ,0,
};
CHAR *pszBox [HEIGHT_BOX]=
{
"╔════════════════════════════════════════════════════════╗",
"║ ║",
"║ Process Message: ║",
"║ ║",
"║ ║",
"║ ║",
"║ ║",
"║ ║",
"╚════════════════════════════════════════════════════════╝",
};
CHAR *pszWormMessages [] =
{
"Worms Mixed-Mode Program Normal Exit",
"Undetermined Error Occurred",
"Worms Mixed Mode Program Initialization Failure",
"Maximum Number of Threads Reached for this Process",
"Error Creating Thread",
"Unable To Display Help Screen",
"Unable To Create Mouse Event Thread",
"Hit Any Key to Exit Process",
"Waiting for Threads To Exit",
"Any Key to Continue",
};
#define MAX_ERROR_MSGS (sizeof (pszErrorMessage) )
#define MAX_THREADS ( ( sizeof(ThreadData) / sizeof(THREAD_DATA) ) -1 )
#define ONCE while( 0 )
/*--------------------------------------------------------------*\
* Entry point declarations
\*--------------------------------------------------------------*/
INT
main (SHORT sArgc , CHAR *ppArgv[]);
VOID
WormsExit(SHORT sExitStatus);
BOOL
WormsMainProcess(SHORT *psStatus);
BOOL
ProcessCmdLine(SHORT sArgc,CHAR **ppArgv);
/****************************************************************\
* Routine Name:main()
*--------------------------------------------------------------
*
* Name: main()
*
* Purpose:Main entry point for the worms program
*
*
*
* Usage: Main entry point for the worms program.
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns:
*
*
\****************************************************************/
INT
main (SHORT sArgc,CHAR *ppArgv[])
{
SHORT sExitStatus = WRM_NORMAL_EXIT;
do
{
/*
*process the command line
*/
if(ProcessCmdLine(sArgc,ppArgv) )
{
break;
}
/*
*initialize resources
*/
if(Init(&sExitStatus) )
{
ErrorMessage(sExitStatus,TRUE);
break;
}
/*
*start up the main process
*/
if(WormsMainProcess(&sExitStatus) )
{
ErrorMessage(sExitStatus,TRUE);
break;
}
} ONCE;
WormsExit(WRM_NORMAL_EXIT);
return( (INT) sExitStatus);
}/*main entry point*/
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name:WormsMainProcess
*
* Purpose:
*
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns:
* FALSE - if sucessful execution completed
* TRUE - if error ,See *psStatus for error definition
\****************************************************************/
BOOL
WormsMainProcess(SHORT *psStatus)
{
BOOL fError = FALSE;
KBDKEYINFO kbdkeyinfo;
USHORT usId;
ULONG ulPosts;
do
{
/*
*sit here and wait on
*user input
*/
KbdCharIn(&kbdkeyinfo,IO_WAIT,
0) ;
/*
*if help was enabled don't allow any other input
*/
if(!bHelpEnabled && !bMessage)
{
/*
*regular keys
*/
if( kbdkeyinfo.chChar )
{
switch(kbdkeyinfo.chChar)
{
case 'd':
case 'D':
WormDelete();
break;
case 'e':
case 'E':
fQuit = TRUE;
fDraw = FALSE;
break;
case 'a':
case 'A':
WormCreate();
break;
case 'h':
case 'H':
if( WormHelp() )
{
ErrorMessage(ERROR_DISP_HELP,TRUE);
}
break;
default:
DosBeep(1200,175);
break;
}
}
/*
*extended keys
*/
else
{
switch(kbdkeyinfo.chScan )
{
case F1:
if( WormHelp() )
{
ErrorMessage(ERROR_DISP_HELP,TRUE);
}
break;
default:
DosBeep(1200,175);
break;
}
}
}
/*
*another threads waiting for keyboard input
*free them up
*/
else
{
DosPostEventSem(hevWormSem);
}
}while(!fQuit );
/*
*set each thread as inactive
*/
for(usId = 2; usId <= MAX_THREADS + 2; usId++)
{
ThreadData[usId - 2].fActive = FALSE;
}
/*
*make sure we don't get
*pre-empted
*/
DosEnterCritSec();
ulPosts = 0;
DosResetEventSem(hevDrawOk,&ulPosts);
DosExitCritSec();
/*
*wait till all of the
*threads have
*posted on the way out
*/
while(ulPosts < sCurrentThread)
{
DosWaitEventSem(hevDrawOk,SEM_INDEFINITE_WAIT);
DosQueryEventSem(hevDrawOk,&ulPosts);
}
/*
*display message that process is shutting down
*/
Message(WAITING_THREADS_EXIT,FALSE,FALSE,TRUE,FALSE);
return ( fError) ;
}/*main process loop */
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name: WormCreate()
*
* Purpose:
*
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns:
* TRUE - Error occurred
* FALSE - No error occurred
\****************************************************************/
BOOL
WormCreate(VOID )
{
if( sCurrentThread == MAX_THREADS )
{
/*
*thread limit exceeeded
*/
ErrorMessage(MAX_THREADS_EXCEEDED,TRUE );
return(TRUE);
}
ThreadData[sCurrentThread].fActive = TRUE;
ThreadData[sCurrentThread].tidWorm =
_beginthread( WormThread,
NULL,
STACK_SIZE_WORMTHRD,
&ThreadData[sCurrentThread]);
if(ThreadData[sCurrentThread].tidWorm == -1 )
{
ErrorMessage(ERROR_CREATING_THREAD,TRUE );
return(TRUE);
}
sCurrentThread++;
return(FALSE);
}
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name: ErrorMessage()
*
* Purpose: Display Error Messages to the user.
*
*
*
* Usage: sErrorMessage - Message number to display.
* fBeep - Beep or not.
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns: VOID
\****************************************************************/
VOID ErrorMessage(SHORT sErrorMessage,BOOL fBeep)
{
KBDKEYINFO kbdkeyinfo;
BYTE bAttr = MKATRB(WM_RED,WM_WHITE );
USHORT usAttrib = VP_WAIT | VP_OPAQUE;
USHORT usRow,usIndex;
USHORT usStatus = MOUSE_DISABLED;
BYTE bCell[2];
PVOID pvSaveWindBuf;
PTIB ptib ;
PPIB ppib ;
ULONG ulPosts;
bCell[0] = 0x20;
bCell[1] = WM_BACKGROUND;
bMessage = TRUE;
if(fBeep)
{
DosBeep(675,1200);
}
/*
*freeze all threads
*while pop-up is up
*/
SuspendAllThreads();
/*
*make sure each thread has had enough time
*to complete
*what they are doin before waiting on the drawing semaphore
*/
// DosSleep(PAUSE_TIME * 40);
/*
*read the screen and save
*it
*/
if(SaveScreen(&pvSaveWindBuf) )
{
return;
}
VioScrollDn(0,0,0xFFFF,0xFFFF,0xFFFF,bCell,hvio);
/*
*put up the message box
*/
for(usRow = BOX_ROW,usIndex = 0;usIndex < HEIGHT_BOX; usIndex++,
usRow++ )
{
VioWrtCharStrAtt(pszBox[usIndex],strlen(pszBox[usIndex]),
usRow,
BOX_COL,
&bAttr,
hvio );
}
/*
*display
*error message
*/
VioWrtCharStrAtt( pszWormMessages[sErrorMessage],
strlen(pszWormMessages[sErrorMessage]),
BOX_ROW + 5,
( ((LAST_COL - FIRST_COL ) -
strlen(pszWormMessages[sErrorMessage])) / 2) ,
&bAttr,
hvio );
/*
*any key to continue
*/
VioWrtCharStrAtt( pszWormMessages[ANY_KEY_TO_CONTINUE],
strlen(pszWormMessages[ANY_KEY_TO_CONTINUE]),
BOX_ROW + 6,
( ((LAST_COL - FIRST_COL ) -
strlen(pszWormMessages[ANY_KEY_TO_CONTINUE])) / 2) ,
&bAttr,
hvio );
DosGetInfoBlocks(&ptib,&ppib);
/*
*if we are not
*calling from thread
*one suspend the calling thread
*so only one thread at a time
*is hitting the keyboard queue
*/
if(ptib->tib_ptib2->tib2_ultid != 1 )
{
DosWaitEventSem(hevWormSem,SEM_INDEFINITE_WAIT);
DosResetEventSem(hevWormSem,&ulPosts);
}
else
{
/*
*wait for any
*response if thread 1
*/
KbdCharIn(&kbdkeyinfo,IO_WAIT,
0) ;
}
VioScrollDn(0,0,0xFFFF,0xFFFF,0xFFFF,bCell,hvio);
/*
*restore the screen
*/
ReDisplayScreen(pvSaveWindBuf);
/*
*resume all threads
*/
ResumeAllThreads();
bMessage = FALSE;
}
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name: Message()
*
* Purpose:Generic message routine. Allows all threads to continue,
* while message is up.
*
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns: VOID
*
*
\****************************************************************/
VOID Message( SHORT sErrorMessage,BOOL fBeep,BOOL fKeyBoardWait,
BOOL fClsConsole,BOOL fSuspendThreads )
{
KBDKEYINFO kbdkeyinfo;
BYTE bAttr = MKATRB(WM_RED,WM_WHITE );
USHORT usAttrib = VP_WAIT | VP_OPAQUE;
USHORT usRow,usIndex;
BYTE bCell[2];
BYTE bhAttr = WM_BACKGROUND;
bCell[0] = 0x20;
bCell[1] = WM_BACKGROUND;
/*
*display
*the error message to the
*screen
*/
if(fBeep)
{
DosBeep(675,1200);
}
if(fSuspendThreads)
{
SuspendAllThreads();
}
DosSleep(1000L);
if(fClsConsole)
{
/*
*clear the screen
*/
VioScrollDn(0,0,0xFFFF,0xFFFF,0xFFFF,bCell,hvio);
}
/*
*put up the message box
*/
for(usRow = BOX_ROW,usIndex = 0;usIndex < HEIGHT_BOX; usIndex++,
usRow++ )
{
VioWrtCharStrAtt(pszBox[usIndex],strlen(pszBox[usIndex]),
usRow,
BOX_COL,
&bAttr,
hvio );
}
/*
*display
*message
*/
VioWrtCharStrAtt( pszWormMessages[sErrorMessage],
strlen(pszWormMessages[sErrorMessage]),
BOX_ROW + 5,
( ((LAST_COL - FIRST_COL ) -
strlen(pszWormMessages[sErrorMessage])) / 2) ,
&bAttr,
hvio );
/*
*sit here and wait on
*user input
*/
if(fKeyBoardWait)
{
VioWrtCharStrAtt( pszWormMessages[sErrorMessage],
strlen(pszWormMessages[sErrorMessage]),
BOX_ROW + 6,
( ((LAST_COL - FIRST_COL ) -
strlen(pszWormMessages[ANY_KEY_TO_CONTINUE])) / 2) ,
&bAttr,
hvio );
KbdCharIn(&kbdkeyinfo,IO_WAIT,
0 ) ;
}
}
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name:WormsExit()
*
* Purpose: Generic exit routine. All exit processing should be done
* at this point.
*
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns: VOID
*
*
\****************************************************************/
VOID
WormsExit(SHORT sExitStatus)
{
USHORT usRow,usCol;
BYTE bCell[2];
BYTE bhAttr = MKATRB(WM_BLUE,WM_RED);
bCell[0] = 0x20;
bCell[1] = WM_BACKGROUND;
/*
*do any clean up
*necessary
*/
/*
*clear the screen
*/
VioScrollDn(0,0,0xFFFF,0xFFFF,0xFFFF,bCell,hvio);
/*
*reset the old
*cursor
*/
VioSetCurType(&viociCursor,hvio);
/*
*display the exit message
*/
VioWrtCharStrAtt( pszWormMessages[sExitStatus],
strlen(pszWormMessages[sExitStatus]),
2,1,
&bhAttr,hvio );
VioSetCurPos(3,2,hvio);
}
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name:ProcessCmdLine()
*
* Purpose:Parse arguments passed on the command line.
*
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns:
* FALSE - at present time
*
\****************************************************************/
BOOL ProcessCmdLine(SHORT sArgc,CHAR **ppArgv)
{
SHORT sArgnum = 1;
BOOL fError = FALSE;
while(--sArgc )
{
if( *ppArgv[sArgnum] == '-' ||
*ppArgv[sArgnum] == '/' )
{
switch(*(ppArgv[sArgnum] + 1) )
{
case 'S':
case 's':
fSilent = TRUE;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
sStartWorms = atoi(ppArgv[sArgnum] + 1);
if(sStartWorms > MAX_THREADS )
{
sStartWorms = MAX_THREADS;
}
break;
}
}
sArgnum++;
}
return(fError);
}
/****************************************************************\
*
*--------------------------------------------------------------
*
* Name:WormDelete()
*
* Purpose:Set the active flag to false for the last active
* thread to FALSE.
*
*
* Usage:
*
* Method:
* -
*
* -
* -
*
* -
* -
*
* Returns:
*
* VOID
\****************************************************************/
VOID WormDelete(VOID )
{
if(sCurrentThread > 0 )
{
ThreadData[--sCurrentThread].fActive = FALSE;
}
else
{
DosBeep(675,1200);
}
}