518 lines
10 KiB
C
518 lines
10 KiB
C
/*
|
|||
|
|
TA3.C
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <p_std.h>
|
||
|
|
#include <p_sys.h>
|
||
|
|
#include <wlib.h>
|
||
|
|
#include <hwif.h>
|
||
|
|
|
||
|
|
|
||
|
|
GLREF_D UWORD DatLocked;
|
||
|
|
|
||
|
|
LOCAL_D TEXT *cmds[]=
|
||
|
|
{
|
||
|
|
"rReset score",
|
||
|
|
"lLimits",
|
||
|
|
"mMode",
|
||
|
|
"tTiming",
|
||
|
|
"xExit",
|
||
|
|
NULL
|
||
|
|
};
|
||
|
|
|
||
|
|
#define TABLES_ITEMS 5
|
||
|
|
|
||
|
|
LOCAL_D H_MENU_DATA mdata[]=
|
||
|
|
{
|
||
|
|
"Tables",TABLES_ITEMS,
|
||
|
|
NULL
|
||
|
|
};
|
||
|
|
|
||
|
|
GLDEF_D TEXT ** _cmds=(&cmds[0]);
|
||
|
|
GLDEF_D H_MENU_DATA * _mdata=(&mdata[0]);
|
||
|
|
|
||
|
|
|
||
|
|
LOCAL_D UINT MainWid;
|
||
|
|
|
||
|
|
typedef struct
|
||
|
|
{
|
||
|
|
UWORD TableEnd;
|
||
|
|
UWORD MaxTable;
|
||
|
|
UWORD Tested;
|
||
|
|
UWORD Correct;
|
||
|
|
UWORD Timing;
|
||
|
|
UWORD Mode;
|
||
|
|
} TSTATE;
|
||
|
|
|
||
|
|
LOCAL_D TSTATE state={12,12,0,0,5,1};
|
||
|
|
|
||
|
|
LOCAL_D TEXT *EnvName="TABLES";
|
||
|
|
#define ENV_NAME_LEN 6
|
||
|
|
|
||
|
|
LOCAL_D ULONG seed;
|
||
|
|
|
||
|
|
|
||
|
|
LOCAL_C VOID DrawLine(INT j,TEXT *pb)
|
||
|
|
{
|
||
|
|
P_RECT box;
|
||
|
|
|
||
|
|
box.tl.x=4;
|
||
|
|
box.br.x=189-4;
|
||
|
|
box.tl.y=4+9*j;
|
||
|
|
box.br.y=box.tl.y+9;
|
||
|
|
gPrintBoxText(&box,8,G_TEXT_ALIGN_CENTRE,0,pb,p_slen(pb));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DisplayScores(VOID)
|
||
|
|
{
|
||
|
|
TEXT buf[40];
|
||
|
|
|
||
|
|
p_atos(&buf[0],"Score: %u correct out of %u",state.Correct,state.Tested);
|
||
|
|
DrawLine(0,&buf[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DisplayMode(VOID)
|
||
|
|
{
|
||
|
|
TEXT *pb;
|
||
|
|
TEXT buf[40];
|
||
|
|
|
||
|
|
if (state.Mode==1)
|
||
|
|
pb="Testing all tables";
|
||
|
|
else
|
||
|
|
{
|
||
|
|
p_atos(&buf[0],"Testing %d times table",state.Mode);
|
||
|
|
pb=(&buf[0]);
|
||
|
|
}
|
||
|
|
DrawLine(1,pb);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DisplayLimits(VOID)
|
||
|
|
{
|
||
|
|
TEXT buf[40];
|
||
|
|
|
||
|
|
p_atos(&buf[0],"(up to %d times %d)",
|
||
|
|
(state.Mode==1? state.MaxTable: state.Mode),state.TableEnd);
|
||
|
|
DrawLine(2,&buf[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DrawButton(INT state)
|
||
|
|
{
|
||
|
|
P_RECT box;
|
||
|
|
|
||
|
|
box.tl.x=34+36;
|
||
|
|
box.br.x=34+36+38;
|
||
|
|
box.tl.y=47;
|
||
|
|
box.br.y=47+14;
|
||
|
|
wDrawButton(&box,"Enter",state);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DisplayPressButton(VOID)
|
||
|
|
{
|
||
|
|
gPrintText(34,56,"Press",5);
|
||
|
|
DrawButton(FALSE);
|
||
|
|
gPrintText(34+36+38+6,56,"to test",7);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID Display(VOID)
|
||
|
|
{
|
||
|
|
DisplayScores();
|
||
|
|
DisplayMode();
|
||
|
|
DisplayLimits();
|
||
|
|
DisplayPressButton();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ResetScore(VOID)
|
||
|
|
{
|
||
|
|
if (!state.Tested)
|
||
|
|
{
|
||
|
|
wInfoMsg("No score to reset");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (uOpenDialog("Reset score to zero"))
|
||
|
|
return;
|
||
|
|
if (uAddButtonList("No",-'n',"Yes",'y',NULL))
|
||
|
|
return;
|
||
|
|
if (uRunDialog()=='y')
|
||
|
|
{
|
||
|
|
state.Tested=0;
|
||
|
|
state.Correct=0;
|
||
|
|
DisplayScores();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ChangeLimits(VOID)
|
||
|
|
{
|
||
|
|
LONG lTableEnd;
|
||
|
|
LONG lMaxTable;
|
||
|
|
H_DI_NUMBER end;
|
||
|
|
H_DI_NUMBER last;
|
||
|
|
|
||
|
|
lTableEnd=state.TableEnd;
|
||
|
|
lMaxTable=state.MaxTable;
|
||
|
|
if (uOpenDialog("Limits for testing"))
|
||
|
|
return;
|
||
|
|
end.value=(&lTableEnd);
|
||
|
|
end.low=10;
|
||
|
|
end.high=99;
|
||
|
|
if (uAddDialogItem(H_DIALOG_NUMBER,"Tables end at",&end))
|
||
|
|
return;
|
||
|
|
last.value=(&lMaxTable);
|
||
|
|
last.low=2;
|
||
|
|
last.high=99;
|
||
|
|
if (uAddDialogItem(H_DIALOG_NUMBER,"Highest table",&last))
|
||
|
|
return;
|
||
|
|
if (uRunDialog()<=0)
|
||
|
|
return;
|
||
|
|
state.TableEnd=lTableEnd;
|
||
|
|
state.MaxTable=lMaxTable;
|
||
|
|
if (state.Mode>state.MaxTable)
|
||
|
|
state.Mode=state.MaxTable;
|
||
|
|
DisplayMode();
|
||
|
|
DisplayLimits();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ChangeTiming(VOID)
|
||
|
|
{
|
||
|
|
LONG lTiming;
|
||
|
|
H_DI_NUMBER tim;
|
||
|
|
|
||
|
|
lTiming=state.Timing;
|
||
|
|
if (uOpenDialog("Timing"))
|
||
|
|
return;
|
||
|
|
tim.value=(&lTiming);
|
||
|
|
tim.low=1;
|
||
|
|
tim.high=20;
|
||
|
|
if (uAddDialogItem(H_DIALOG_NUMBER,"Number of seconds allowed",&tim))
|
||
|
|
return;
|
||
|
|
if (uRunDialog()<=0)
|
||
|
|
return;
|
||
|
|
state.Timing=lTiming;
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ChangeMode(VOID)
|
||
|
|
{
|
||
|
|
H_DI_CHOICE ch;
|
||
|
|
INT j;
|
||
|
|
TEXT buf[20];
|
||
|
|
|
||
|
|
if (uOpenDialog("Mode"))
|
||
|
|
return;
|
||
|
|
if (uBeginDCL(&ch))
|
||
|
|
return;
|
||
|
|
if (uGrowDCL(&ch,"All tables"))
|
||
|
|
return;
|
||
|
|
for (j=2; j<=state.MaxTable; j++)
|
||
|
|
{
|
||
|
|
p_atos(&buf[0],"%d times table",j);
|
||
|
|
if (uGrowDCL(&ch,&buf[0]))
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (uAddDCL("Test which tables",&state.Mode,&ch))
|
||
|
|
return;
|
||
|
|
if (uRunDialog()<=0)
|
||
|
|
return;
|
||
|
|
DisplayMode();
|
||
|
|
DisplayLimits();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ExitApplication(VOID)
|
||
|
|
{
|
||
|
|
uErrorValue(p_setenviron(EnvName,ENV_NAME_LEN,&state,sizeof(TSTATE)));
|
||
|
|
p_exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ManageCommand(INT index)
|
||
|
|
{
|
||
|
|
switch (index)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
ResetScore();
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
ChangeLimits();
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
ChangeMode();
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
ChangeTiming();
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
ExitApplication();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID TryExecuteCommand(INT keycode)
|
||
|
|
{
|
||
|
|
keycode=uLocateCommand(keycode);
|
||
|
|
if (keycode>=0)
|
||
|
|
ManageCommand(keycode);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C INT FindRandom(INT low,INT high)
|
||
|
|
{
|
||
|
|
INT range;
|
||
|
|
|
||
|
|
range=high-low+1;
|
||
|
|
return(low+(INT)(p_randl(&seed)%range));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID FindFactors(WORD *pa,WORD *pb)
|
||
|
|
{
|
||
|
|
*pa=(state.Mode==1? FindRandom(2,state.MaxTable): state.Mode);
|
||
|
|
*pb=FindRandom(2,state.TableEnd);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID SwitchStyle(INT style)
|
||
|
|
{
|
||
|
|
G_GC gc;
|
||
|
|
|
||
|
|
gc.style=style;
|
||
|
|
gSetGC(0,G_GC_MASK_STYLE,&gc);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID *CreateEditor(VOID)
|
||
|
|
{
|
||
|
|
H_EDIT_BOX heb;
|
||
|
|
|
||
|
|
heb.maxchars=4;
|
||
|
|
heb.vulen=30;
|
||
|
|
heb.pos.x=113;
|
||
|
|
heb.pos.y=45;
|
||
|
|
heb.win=MainWid;
|
||
|
|
heb.font=WS_FONT_BASE;
|
||
|
|
heb.style=G_STY_DOUBLE;
|
||
|
|
return(hEBOpen(H_EDIT_BOX_FONT,&heb));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ClearBottomArea(VOID)
|
||
|
|
{
|
||
|
|
P_RECT box;
|
||
|
|
|
||
|
|
box.tl.x=4;
|
||
|
|
box.br.x=189-4;
|
||
|
|
box.tl.y=4+3*9;
|
||
|
|
box.br.y=80-4;
|
||
|
|
gClrRect(&box,G_TRMODE_CLR);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID Beep(VOID)
|
||
|
|
{
|
||
|
|
p_sound(-5,320);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID SelectAll(VOID *ebH)
|
||
|
|
{
|
||
|
|
hEBSetSelect(ebH,0,p_slen(hEBSenseText(ebH)));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C INT SenseNumberTyped(VOID *ebH)
|
||
|
|
{
|
||
|
|
TEXT *pb;
|
||
|
|
WORD num;
|
||
|
|
|
||
|
|
pb=hEBSenseText(ebH);
|
||
|
|
p_stoi(&pb,&num);
|
||
|
|
return(num);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C INT AddTextItem(TEXT *pmt,TEXT *pbod)
|
||
|
|
{
|
||
|
|
H_DI_TEXT txt;
|
||
|
|
TEXT buf[20];
|
||
|
|
|
||
|
|
txt.type=H_DTEXT_ALIGN_CENTRE;
|
||
|
|
uZTStoBCS(txt.str=(&buf[0]),pbod);
|
||
|
|
return(uAddDialogItem(H_DIALOG_TEXT,pmt,&txt));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C INT Complain(INT a,INT b,INT c)
|
||
|
|
{
|
||
|
|
TEXT buf[20];
|
||
|
|
|
||
|
|
if (uOpenDialog("Incorrect"))
|
||
|
|
return(-1);
|
||
|
|
p_atos(&buf[0],"%d \236 %d",a,b);
|
||
|
|
if (AddTextItem("The question",&buf[0]))
|
||
|
|
return(-1);
|
||
|
|
buf[p_itob(&buf[0],c)]=0;
|
||
|
|
if (AddTextItem("Your answer",&buf[0]))
|
||
|
|
return(-1);
|
||
|
|
if (uAddButtonList("Help",W_KEY_ESCAPE,"Retry",W_KEY_RETURN,NULL))
|
||
|
|
return(-1);
|
||
|
|
if (uRunDialog()==W_KEY_RETURN)
|
||
|
|
return(0);
|
||
|
|
p_atos(&buf[0],"%d \236 %d = %d",a,b,a*b);
|
||
|
|
if (uOpenDialog(&buf[0]))
|
||
|
|
return(-1);
|
||
|
|
if (uAddButtonList("Continue",W_KEY_RETURN,NULL))
|
||
|
|
return(-1);
|
||
|
|
uRunDialog();
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C INT BadKey(INT k)
|
||
|
|
{
|
||
|
|
return(k<256 && p_isprint(k) && !p_isdigit(k));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DisplayQuestion(VOID)
|
||
|
|
{
|
||
|
|
TEXT buf[30];
|
||
|
|
WMSG_KEY key;
|
||
|
|
P_RECT box;
|
||
|
|
VOID *ebH;
|
||
|
|
WORD a;
|
||
|
|
WORD b;
|
||
|
|
WORD c;
|
||
|
|
WORD ans;
|
||
|
|
|
||
|
|
ebH=CreateEditor();
|
||
|
|
if (!ebH)
|
||
|
|
return;
|
||
|
|
ClearBottomArea();
|
||
|
|
hEBEmphasise(ebH,TRUE);
|
||
|
|
FindFactors(&a,&b);
|
||
|
|
ans=a*b;
|
||
|
|
p_atos(&buf[0],"%d \236 %d = ",a,b);
|
||
|
|
box.tl.x=53;
|
||
|
|
box.br.x=113;
|
||
|
|
box.tl.y=45;
|
||
|
|
box.br.y=45+17;
|
||
|
|
SwitchStyle(G_STY_DOUBLE);
|
||
|
|
gPrintBoxText(&box,15,G_TEXT_ALIGN_RIGHT,0,&buf[0],p_slen(&buf[0]));
|
||
|
|
SwitchStyle(G_STY_NORMAL);
|
||
|
|
DatLocked=TRUE;
|
||
|
|
state.Tested++;
|
||
|
|
FOREVER
|
||
|
|
{
|
||
|
|
uGetKey(&key);
|
||
|
|
if (BadKey(key.keycode))
|
||
|
|
Beep();
|
||
|
|
else if (key.keycode!=W_KEY_RETURN)
|
||
|
|
hEBHandleKey(ebH,key.keycode,key.modifiers);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
c=SenseNumberTyped(ebH);
|
||
|
|
if (c==ans)
|
||
|
|
{
|
||
|
|
state.Correct++;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
Beep();
|
||
|
|
hEBEmphasise(ebH,FALSE);
|
||
|
|
if (Complain(a,b,c))
|
||
|
|
break;
|
||
|
|
DisplayScores();
|
||
|
|
state.Tested++;
|
||
|
|
hEBEmphasise(ebH,TRUE);
|
||
|
|
SelectAll(ebH);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
DatLocked=FALSE;
|
||
|
|
hEBClose(ebH);
|
||
|
|
ClearBottomArea();
|
||
|
|
DisplayPressButton();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID MakeButtonDance(VOID)
|
||
|
|
{
|
||
|
|
DrawButton(TRUE);
|
||
|
|
wFlush();
|
||
|
|
p_sleep(2);
|
||
|
|
DrawButton(FALSE);
|
||
|
|
wFlush();
|
||
|
|
p_sleep(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID DoTest(VOID)
|
||
|
|
{
|
||
|
|
MakeButtonDance();
|
||
|
|
DisplayQuestion();
|
||
|
|
DisplayScores();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID MainLoop(VOID)
|
||
|
|
{
|
||
|
|
INT ret;
|
||
|
|
WMSG_KEY key;
|
||
|
|
|
||
|
|
FOREVER
|
||
|
|
{
|
||
|
|
uGetKey(&key);
|
||
|
|
if (key.keycode&W_EVENT_KEY)
|
||
|
|
{
|
||
|
|
if (key.keycode==CONS_EVENT_COMMAND)
|
||
|
|
ExitApplication();
|
||
|
|
}
|
||
|
|
else if (key.keycode&W_SPECIAL_KEY)
|
||
|
|
TryExecuteCommand(key.keycode&(~W_SPECIAL_KEY));
|
||
|
|
else if (key.keycode==W_KEY_MENU && !(key.modifiers&W_CTRL_MODIFIER))
|
||
|
|
{
|
||
|
|
ret=uPresentMenus();
|
||
|
|
if (ret>0)
|
||
|
|
TryExecuteCommand(ret);
|
||
|
|
}
|
||
|
|
else if (key.keycode==W_KEY_RETURN)
|
||
|
|
DoTest();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ReadState(VOID)
|
||
|
|
{
|
||
|
|
INT len;
|
||
|
|
UBYTE buf[P_ENVMAX];
|
||
|
|
|
||
|
|
len=p_getenviron(EnvName,ENV_NAME_LEN,&buf[0]);
|
||
|
|
if (len<0 || len!=sizeof(TSTATE))
|
||
|
|
return;
|
||
|
|
p_bcpy(&state,&buf[0],sizeof(TSTATE));
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID InitSeed(VOID)
|
||
|
|
{
|
||
|
|
seed=p_date();
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID ReduceScreenSize(VOID)
|
||
|
|
{
|
||
|
|
W_WINDATA wd;
|
||
|
|
|
||
|
|
wd.extent.tl.x=wd.extent.tl.y=0;
|
||
|
|
wd.extent.width=189;
|
||
|
|
wd.extent.height=80;
|
||
|
|
wSetWindow(MainWid,W_WIN_EXTENT,&wd);
|
||
|
|
if (uErrorValue(wCheckPoint()))
|
||
|
|
p_exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID CreateGC(VOID)
|
||
|
|
{
|
||
|
|
INT hgc;
|
||
|
|
|
||
|
|
hgc=gCreateGC0(uFindMainWid());
|
||
|
|
if (hgc<0)
|
||
|
|
p_exit(hgc);
|
||
|
|
}
|
||
|
|
|
||
|
|
LOCAL_C VOID SpecificInit(VOID)
|
||
|
|
{
|
||
|
|
uEscape(FALSE);
|
||
|
|
hCrackCommandLine();
|
||
|
|
MainWid=uFindMainWid();
|
||
|
|
ReduceScreenSize();
|
||
|
|
CreateGC();
|
||
|
|
gBorder(W_BORD_CORNER_4);
|
||
|
|
wsEnable();
|
||
|
|
ReadState();
|
||
|
|
Display();
|
||
|
|
InitSeed();
|
||
|
|
}
|
||
|
|
|
||
|
|
GLDEF_C VOID main(VOID)
|
||
|
|
{
|
||
|
|
uCommonInit();
|
||
|
|
SpecificInit();
|
||
|
|
MainLoop();
|
||
|
|
}
|