home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
tktools.zip
/
typefast
/
typefast.c
< prev
next >
Wrap
Text File
|
1992-07-17
|
20KB
|
566 lines
/* TYPEFAST for PM is written by Turgut Kalfaoglu <turgut@frors12.bitnet> */
/* This code can be compiled with IBM C/SET 2 Compiler */
#define INCL_WIN
#define INCL_GPI
#define INCL_DOSDATETIME
#include <os2.h> /* PM header file */
#include "typefast.h" /* Resource symbolic identifiers*/
#include <io.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
CHAR *findword(void);
/* Define parameters by type */
HAB hab; /* PM anchor block handle */
PSZ pszErrMsg;
POINTL pt;
CHAR *words[30], kbbuf[256];
INT wordx[30],wordy[30],activewords,lost,score,maxactivewords,timertime,difflevel;
LONG CharHeight, CharWidth, topx,topy;
FILE *wordfile;
BOOL anykeyhit, pausemode, gameover, sound,lastwordheight=0, respectCase=0;
ULONG wordcount, wordcountcorr;
float startsec;
CHAR *copyright="TYPEFAST V1.1 (C)1992 Turgut Kalfaoglu <TURGUT@FRORS12.BITNET>";
INT main (VOID)
{
HMQ hmq; /* Message queue handle */
HWND hwndClient = NULLHANDLE; /* Client area window handle */
HWND hwndFrame = NULLHANDLE; /* Frame window handle */
QMSG qmsg; /* Message from message queue */
ULONG flCreate; /* Window creation control flags*/
init();
if ((hab = WinInitialize(0)) == 0L) /* Initialize PM */
AbortTypeFast(hwndFrame, hwndClient); /* Terminate the application */
if ((hmq = WinCreateMsgQueue( hab, 0 )) == 0L)/* Create a msg queue */
AbortTypeFast(hwndFrame, hwndClient); /* Terminate the application */
if (!WinRegisterClass( /* Register window class */
hab, /* Anchor block handle */
(PSZ)"MyWindow", /* Window class name */
(PFNWP)MyWindowProc, /* Address of window procedure */
CS_SIZEREDRAW, /* Class style */
0 /* No extra window words */
))
AbortTypeFast(hwndFrame, hwndClient); /* Terminate the application */
flCreate = FCF_STANDARD; /* Set frame control flags to */
/* standard */
if ((hwndFrame = WinCreateStdWindow(
HWND_DESKTOP, /* Desktop window is parent */
WS_VISIBLE, /* STD. window styles */
&flCreate, /* Frame control flag */
"MyWindow", /* Client window class name */
"TypeFast", /* No window text */
0L, /* No special class style */
(HMODULE)0L, /* Resource is in .EXE file */
ID_WINDOW, /* Frame window identifier */
&hwndClient /* Client window handle */
)) == 0L)
AbortTypeFast(hwndFrame, hwndClient); /* Terminate the application */
WinSetWindowText(hwndFrame, "TypeFast!");
WinStartTimer(hab, hwndClient, 1, timertime);
/*
* Get and dispatch messages from the application message queue
* until WinGetMsg returns FALSE, indicating a WM_QUIT message.
*/
while( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) )
WinDispatchMsg( hab, &qmsg );
WinStopTimer(hab,hwndClient, 1);
WinDestroyWindow(hwndFrame); /* Tidy up... */
WinDestroyMsgQueue( hmq ); /* Tidy up... */
WinTerminate( hab ); /* Terminate the application */
} /* End of main */
/**************************************************************************
*
* Name : MyWindowProc
*
* Description: The window procedure associated with the client area in
* the standard frame window. It processes all messages
* either sent or posted to the client area, depending on
* the message command and parameters.
*
* Parameters : hwnd = window handle
* msg = message code
* mp1 = first message parameter
* mp2 = second message parameter
*
* Return : depends on message sent
*
*************************************************************************/
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
DATETIME dt;
static HWND hwndMenu;
switch( msg )
{
case WM_CREATE:
{
INT i;
FONTMETRICS fm;
HPS hps;
/* Learn size of characters */
hps = WinGetPS(hwnd);
GpiQueryFontMetrics(hps,(LONG) sizeof fm, &fm);
CharHeight = (INT) fm.lMaxBaselineExt;
CharWidth = (INT) fm.lMaxCharInc;
if (CharHeight < 1 | CharHeight > 50)
notify(hwnd,"CharHeight is %d!",CharHeight);
if (CharWidth < 1 | CharWidth > 100)
notify(hwnd,"CharWidth is %d!",CharWidth);
WinReleasePS(hps);
wordfile = fopen("TYPEFAST.DAT","rb");
if (wordfile == NULL) {
notify(hwnd,"Cannot find TYPEFAST.DAT");
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );
}
kbbuf[0] = 0; /* init keyb buffer */
for (i=0;i<30;i++)
words[i] = (char *) malloc(sizeof(CHAR)*20);
DosGetDateTime(&dt);
srand(dt.hours*100+dt.minutes*10+dt.seconds);
fseek (wordfile,(LONG) rand()%10240L, SEEK_CUR);
hwndMenu = WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),FID_MENU);
difflevel = ID_EASY;
return 0;
}
case WM_COMMAND:
{
USHORT command; /* WM_COMMAND command value */
command = SHORT1FROMMP(mp1); /* Extract the command value */
switch (command)
{
case ID_EASY:
case ID_MEDIUM:
case ID_HARD:
/* remove check mark */
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(difflevel,TRUE),
MPFROM2SHORT(MIA_CHECKED,0));
difflevel = COMMANDMSG(&msg)->cmd;
maxactivewords = 4;
timertime = difflevel;
WinStartTimer(hab, hwnd, 1, timertime);
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(difflevel,TRUE),
MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED));
return 0;
case ID_ABOUT:
WinMessageBox(HWND_DESKTOP,
hwnd, /* Owner window is our frame */
"TypeFast allows you to practice your typing by providing you"
" with words of your choice (simply provide a text file to the"
" program by naming it TYPEFAST.DAT), and measures the time it"
" takes you to type words. You can use SPACE or RETURN between"
" words. The program stays in demo mode until you hit a key.\n"
"TypeFast for PM is written by Turgut Kalfaoglu, <turgut@frmop11.bitnet>\n"
"Shareware: $10 donation requested if you find it useful."
" Send donation to: Turgut Kalfaoglu, 1378 Sok 8/10, Izmir Turkey\n"
" Thank you for trying TYPEFAST!",
"About TypeFast",
MSGBOXID,
MB_ICONEXCLAMATION | MB_OK ); /* Flags */
return 0;
case ID_RESTART:
{
INT keepdiff, keepsound;
keepdiff = difflevel;
keepsound = sound;
init();
difflevel = keepdiff;
sound = keepsound;
timertime = difflevel;
WinStartTimer(hab,hwnd,1,timertime);
return 0;
}
case ID_SOUND:
sound = !sound;
if (!sound) /* remove tick (check) mark */
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(ID_SOUND,TRUE),
MPFROM2SHORT(MIA_CHECKED,FALSE));
else /* put tick (check) mark */
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(ID_SOUND,TRUE),
MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED));
return 0;
case ID_CASE:
respectCase = !respectCase;
if (!respectCase)
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(ID_CASE,TRUE),
MPFROM2SHORT(MIA_CHECKED,FALSE));
else
WinSendMsg(hwndMenu,MM_SETITEMATTR,
MPFROM2SHORT(ID_CASE,TRUE),
MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED));
return 0;
case ID_EXITPROG:
WinPostMsg( hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 );
return 0;
default:
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
return 0;
}
case WM_SIZE:
topx = SHORT1FROMMP(mp2);
topy = SHORT2FROMMP(mp2);
return 0;
case WM_ERASEBACKGROUND:
/*
* Return TRUE to request PM to paint the window background
* in SYSCLR_WINDOW.
*/
return (MRESULT)( TRUE );
case WM_CHAR:
{
CHAR keycode, skeycode[2];
INT i;
if (!(CHARMSG(&msg)->fs & KC_CHAR)) return 0; /* we're not interested */
if (CHARMSG(&msg)->fs & KC_KEYUP) return 0;
if (!anykeyhit) {
i = DosGetDateTime(&dt);
startsec = (float) (dt.hours*3600 + dt.minutes*60 + dt.seconds);
anykeyhit = 1;
} /* endif */
keycode = CHARMSG(&msg)->chr;
if ((keycode == 13) || (keycode == ' ')) { /* end of word? */
for (i=0;i<30;i++) {
if (!wordx[i]) continue;
if ( !respectCase && !stricmp(kbbuf,words[i]) || /* hit! */
respectCase && !strcmp (kbbuf,words[i])) {
score++;
activewords--;
wordx[i] = 0;
if (sound) DosBeep(2000,40);
wordcountcorr++;
if ( (score%20)==0) {
if (maxactivewords<29)
maxactivewords++;
if (score%50==0) {
timertime -= 20;
maxactivewords /= 2;
if (timertime < 50) timertime = 50;
WinStartTimer(hab, hwnd, 1, timertime);
if (sound) DosBeep(4000,40);
}
}
break;
}/* hit */
}
wordcount++;
kbbuf[0]=0;
return 0;
} /* user hit space or c/r */
skeycode[0] = keycode;
skeycode[1] = 0;
strcat(kbbuf,skeycode);
return 0;
}
case WM_SETFOCUS:
if (SHORT1FROMMP(mp2)) /* if we got focus */
pausemode = 0;
else
pausemode = 1;
return 0;
case WM_TIMER:
{
HPS hps;
RECTL rc;
INT i,wordsize;
if (pausemode || gameover) break;
if (activewords < 4 && maxactivewords>5) {
timertime -= 50;
if (timertime<51) timertime=51;
WinStartTimer(hab, hwnd, 1, timertime);
}
if (activewords < maxactivewords) {
for (i=0;i<30;i++)
if (wordx[i] == 0) break;
/* Creating a new word.. */
if (i<30) {
activewords++;
wordx[i] = rand() % topx + 1;
strcpy(words[i],findword());
wordsize = CharWidth*(strlen(words[i])+1);
if (wordx[i]+wordsize > topx ) {
wordx[i] -= wordsize;
if (wordx[i]<1) wordx[i]=1;
}
wordy[i] = topy-1;
}
}
WinInvalidateRect(hwnd,NULL,FALSE);
/* move down everyone by one */
for (i=0;i<30;i++) {
if (wordx[i] !=0) {
pt.x = wordx[i];
pt.y = wordy[i];
/* move down */
wordy[i] -= CharHeight+1;
/* reach the bottom? */
if (wordy[i] < CharHeight) {
wordx[i] = 0;
if (anykeyhit) {
lost++;
if (sound) DosBeep(400,10); }
activewords--;
if (lost>14) {
gameover = 1;
break;
}
}
pt.y = wordy[i];
}
}
break;
}
case WM_PAINT:
/*
* Window contents are drawn here in WM_PAINT processing.
*/
{
HPS hps; /* Presentation Space handle */
RECTL rc,rcl;
POINTL pt; /* String screen coordinates */
/* Create a presentation space */
CHAR dest;
INT i;
CHAR buffer[80];
DATETIME dt;
float elapsedsec;
WinQueryWindowRect(hwnd, &rcl);
topx = rcl.xRight;
topy = rcl.yTop;
hps = WinBeginPaint( hwnd, 0L, &rc );
GpiErase(hps);
GpiSetColor( hps, CLR_NEUTRAL ); /* colour of the text, */
GpiSetBackColor( hps, CLR_BACKGROUND ); /* its background and */
GpiSetBackMix( hps, BM_OVERPAINT ); /* how it mixes, */
/* and draw the string...*/
if (gameover) {
pt.x = 10;
pt.y = topy - 60;
DosGetDateTime(&dt);
WinStopTimer(hab, hwnd, 1);
elapsedsec = (float) (dt.hours*3600+dt.minutes*60+dt.seconds) - startsec;
if (elapsedsec == 0L) elapsedsec = 1L;
sprintf(buffer,"That's %d words. You got %d words right, ",lost,score);
GpiCharStringAt(hps,&pt,(LONG)strlen(buffer),buffer);
pt.y -= CharHeight*2;
sprintf(buffer,"and your WPM=%3.1f, correct WPM=%3.1f",
(float) wordcount / elapsedsec * 60.0,
(float) wordcountcorr / elapsedsec * 60.0);
GpiCharStringAt(hps,&pt,(LONG)strlen(buffer),buffer);
pt.y -= CharHeight*2;
strcpy(buffer,"Select \"Restart\" for another game.");
GpiCharStringAt(hps,&pt,(LONG)strlen(buffer),buffer);
}
else
for (i=0;i<30;i++)
if (wordx[i] != 0) {
pt.y = wordy[i];
pt.x = wordx[i];
GpiCharStringAt( hps, &pt, (LONG)strlen(words[i]), words[i]);
}
WinEndPaint( hps ); /* Drawing is complete */
return 0;
}
case WM_CLOSE:
/*
* This is the place to put your termination routines
*/
fclose(wordfile);
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );/* Cause termination*/
break;
default:
/*
* Everything else comes here. This call MUST exist
* in your window procedure.
*/
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
return (MRESULT)FALSE;
} /* End of MyWindowProc */
/**************************************************************************
*
* Name : AbortTypeFast
*
* Description: Report an error returned from an API service
*
* Concepts : use of message box to display information
*
* API's : DosBeep
* WinGetErrorInfo
* WinMessageBox
* WinFreeErrorInfo
* WinPostMsg
*
* Parameters : hwndFrame = frame window handle
* hwndClient = client window handle
*
* Return : [none]
*
*************************************************************************/
VOID AbortTypeFast(HWND hwndFrame, HWND hwndClient)
{
PERRINFO pErrInfoBlk;
PSZ pszOffSet;
void stdprint(void);
if (sound) DosBeep(100,50);
if ((pErrInfoBlk = WinGetErrorInfo(hab)) != (PERRINFO)NULL)
{
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PSHORT)pszOffSet);
if((INT)hwndFrame && (INT)hwndClient)
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
hwndFrame, /* Owner window is our frame */
(PSZ)pszErrMsg, /* PMWIN Error message */
"Error Msg", /* Title bar message */
MSGBOXID, /* Message identifier */
MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL ); /* Flags */
WinFreeErrorInfo(pErrInfoBlk);
}
WinPostMsg(hwndClient, WM_QUIT, (MPARAM)NULL, (MPARAM)NULL);
} /* End of AbortTypeFast */
INT notify(HWND hwndFrame,char *blurb, INT code)
{
CHAR out[80];
sprintf(out,blurb,code);
if (sound) DosBeep(1000,100);
if (sound) DosBeep(2000,100);
if (sound) DosBeep(3000,100);
DosSleep(2000);
WinMessageBox(HWND_DESKTOP,
hwndFrame,
(PSZ) out,
"Oops!",
MSGBOXID,
MB_MOVEABLE | MB_INFORMATION | MB_OK ); /* Flags */
}
BOOL goodword(char *p)
{
INT i;
/* we admit short words, but not too often */
if (strlen(p)<3) return 0; /* not too short */
if (strlen(p)<5 && rand()<20000) return 0;
for (i=0;i<30;i++)
if (wordx[i] && stricmp(p,words[i])==0) return 0;
while (*p) {
if (ispunct(*p)) return 0;
p++;
}
return 1;
}
CHAR *findword() {
static CHAR wordfound[40];
CHAR buffer[255];
INT i=0;
wordfound[0]=0;
while (!goodword(wordfound)) {
readline(buffer);
if (buffer[0] == 0) return NULL; /* error reading */
while (!isspace(*(buffer+i))) { /* find a space.. */
i++;
if (*(buffer+i) == '\0') {
i=0;
readline(buffer);
}
}
while (isspace(*(buffer+i))) { /* find a non-space */
i++;
if (*(buffer+i) == '\0') {
i=0;
readline(buffer);
}
}
sscanf(buffer+i,"%s",wordfound);
}
return wordfound;
}
INT readline(char *p)
{
*p = 0;
while (1) {
fseek (wordfile,(LONG) rand()%80L, SEEK_CUR);
if (fgets(p,250,wordfile) == NULL) {
fclose(wordfile);
wordfile = fopen("TYPEFAST.DAT","rb");
if (wordfile == NULL) return 1;
fseek(wordfile,1L,SEEK_SET);
continue; }
break;
}
}
INT init() {
INT i;
activewords = 0;
lost = 0; score = 0; maxactivewords=4; timertime=ID_EASY;
topx = 400L; topy = 400L; anykeyhit=0; pausemode=0; gameover=0;
wordcount=0L; wordcountcorr=0L; lastwordheight=0;
kbbuf[0]=0; sound=1;
for(i=0;i<30;i++)
wordx[i]=0;
}