Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : APICSAMP.ZIP
Filename : WASHER.C

 
Output of file : WASHER.C contained in archive : APICSAMP.ZIP
/****************************************************************
*
* Name: WASHER
*
* Function: Emulate a washing machine control panel.
*
* Shows how to: 1. construct complex menus (dialogues) including
* select, input, output, and inactive fields.
* 2. change field types dynamically.
* 3. implement "radio button" select fields.
* 4. use a timer object to measure time intervals.
* 5. use an objectq to wait for multiple events.
*
****************************************************************/


#include
#include "dvapi.h"

/* minimum API version required */
#define required 0x201

/* possible values of the "temperature" variable */
#define HOT 0
#define WARM 1
#define COLD 2

/* possible values of the "state" variable */
#define IDLE 0
#define WASHING 1
#define FIRST_RINSE 2
#define FIRST_SPIN 3
#define FINAL_RINSE 4
#define FINAL_SPIN 5

/* actual API version number */
int version;

/* object handles */
ulong winme,pan,win,kbd,tim,obj;

/* variables used when reading from the menu */
char *kptr,*kend,field,field1[3];
int klng,kstatus,fsize;

/* variables set according to menu input */
int wash_time,temperature,second_rinse,bell;

/* state related variables */
int state,indicator,done;

/* variables for saving the cursor position */
int row,col;

/* panel library filename in ASCIIZ string format */
char lib[] = "examples.plb\x00";

/* name of panel within panel library */
char name[] = "washer";

/* status of last pan_open and pan_apply operation */
int status;


/**********************************************************************
* main - check for DESQview present and enable required extensions.
***********************************************************************/

main () {
/* initialize C interfaces and get API version number */
version = api_init();

/* if DESQview is not running or version is too low, display a message */
if (version < required) {
printf ("This program requires DESQview version %d.02%d or later.\n",
required/256,required%256);
}

/* tell DESQview what extensions to enable and start application */
else {
api_level (required);
program_body();
}

/* disable C interfaces and return from program */
api_exit();
}


/**********************************************************************
* program_body - initialize application and loop processing events.
***********************************************************************/

program_body () {
/* get task window handle and open objectq */
winme = win_me();
obq_open();

/* create timer object */
tim = tim_new();

/* create and open panel object, and associate it with panel library */
pan = pan_new();
status = pan_open (pan,lib,sizeof (lib));

/* apply named panel, and return window & keyboard handles */
status = pan_apply (pan,winme,name,strlen (name),&win,&kbd);

/* preselect "hot water". Jump cursor to field 1. Set "state" to idle */
radio_button (win,2,4,2);
fld_cursor (win,1);
change_state (IDLE,0);
done = 0;

/* position menu, mark as displayable, and make topmost in application. */
win_top (win);

/* loop until "done" becomes TRUE */
while (!done) {

/* wait for input from any open object and return its handle */
obj = obq_read();

/* determine which object it is and process accordingly */
if (obj == kbd)
process_menu_event();
else
if (obj == tim)
process_timer_event();
};

/* free all allocated objects and return */
key_free (kbd);
win_free (win);
pan_free (pan);
tim_free (tim);

}


/**********************************************************************
* process_menu_event - process data returned from the menu.
***********************************************************************/

process_menu_event () {
/* get menu data and determine what event caused data to be returned */
key_read (kbd,&kptr,&klng);
kstatus = key_status (kbd);

/* beep and return if anything but a field selection */
if (kstatus != 1) {
api_sound (1000,5);
return;
};

/* point just past returned data. Save current cursor position. */
kend = kptr+klng;
qry_cursor (win,&row,&col);

/* loop once for each field returned */
while (kptr < kend) {

/* get field # and length. Log field info to task window. */
field = *kptr;
fsize = *(int *)(kptr+1);
win_printf (winme,"field = %d length = %d contents = ",field,fsize);
win_write (winme,kptr+3,fsize);
win_printf (winme,"\n");

/* dispatch based on field number */
switch (field) {

case 1: /* wash time changed */
/* copy returned data to string variable and zero terminate */
memcpy (field1,kptr+3,2);
field1[2] = 0;

/* convert to integer, clip at zero, and set state to IDLE */
wash_time = atoi (field1);
if (wash_time < 0)
wash_time = 0;
change_state (IDLE,0);
break;

case 2: /* Hot water selected - Select field 2. Deselect fields
3 and 4. Log temperature. */
radio_button (win,2,4,2);
temperature = HOT;
break;

case 3: /* Warm water selected - Select field 3. Deselect fields
2 and 4. Log temperature. */
radio_button (win,2,4,3);
temperature = WARM;
break;

case 4: /* Cold water selected - Select field 4. Deselect fields
2 and 3. Log temperature. */
radio_button (win,2,4,4);
temperature = COLD;
break;

case 5: /* Second rinse - if the field data is "Y", the field is
selected. Otherwise, the data will be "N". */
second_rinse = (*(kptr+3) == 'Y');
break;

case 6: /* Beep when done - if the field data is "Y", the field is
selected. Otherwise, the data will be "N". */
bell = (*(kptr+3) == 'Y');
break;

case 7: /* Start button */
/* deselect field so it does not remain highlighted */
fld_type (win,7,FLT_DESELECT);

/* ignore if no wash time has been selected. Otherwise ... */
if (wash_time != 0) {

/* convert field 1 to an output field. Disable the start button
and enable the stop button */
fld_type (win,1,FLT_OUTPUT);
fld_type (win,7,FLT_INACTIVE);
fld_type (win,8,FLT_DESELECT);

/* set timer to run 1 second. If IDLE, set state to WASHING. */
tim_addto (tim,100L);
if (state == IDLE)
change_state (WASHING,10);
}
break;

case 8: /* Stop button - stop cycle and reset field types. */
stop_cycle();
break;

case 9: /* Exit button - stop cycle, reset fields, and set "done". */
stop_cycle();
done = 1;
break;

default: /* unknown field number - should never happen. */
win_printf (winme,"impossible!\n");
}

/* bump pointer to next field and loop */
kptr += (fsize+3);
}

/* restore original cursor position */
win_cursor (win,row,col);
}


/**********************************************************************
* process_timer_event - process timer expiration
***********************************************************************/

process_timer_event () {
long time;

/* read the timer object to clear the event */
time = tim_read(tim);

/* save cursor position. Decrement time remaining and display. */
wash_time -= 1;
qry_cursor (win,&row,&col);
fld_cursor (win,1);
win_printf (win,"%2d",wash_time);

/* if the clock has expired, dispatch based on current state.
In each case, switch to the next state and light the appropriate
indicator. */
if (wash_time == 0) {
switch (state) {
case WASHING:
change_state ((second_rinse) ? FIRST_RINSE:FINAL_RINSE, 11);
break;
case FIRST_RINSE:
change_state (FIRST_SPIN,12);
break;
case FIRST_SPIN:
change_state (FINAL_RINSE,11);
break;
case FINAL_RINSE:
change_state (FINAL_SPIN,12);
break;
case FINAL_SPIN: /* Cycle complete - switch to IDLE state, beep if
requested. Restore original field types. */
change_state (IDLE,0);
if (bell == 1) api_sound (2000,18);
stop_cycle();
break;
}

/* unless we are now IDLE, we need to start a rinse or spin cycle.
do so by setting the clock to 3 seconds and setting the timer to
expire in 1 second. */
if (state != IDLE) {
wash_time = 3;
tim_addto (tim,100L);
}
}

/* if clock is still counting, simply set timer for another second */
else
tim_addto (tim,100L);

/* restore cursor to its original position */
win_cursor (win,row,col);
}


/**********************************************************************
* radio_button - select a specified field and deselect all others in
* the given range.
***********************************************************************/

radio_button (win,first,last,chosen) ulong win; int first,last,chosen; {
int i;

/* loop for each field in range "first" through "last" */
for (i=first; i<=last; i++)

/* change "chosen" field type to SELECTed, others to DESELECTed */
fld_type (win,i,(i==chosen) ? FLT_SELECT : FLT_DESELECT);
}


/**********************************************************************
* change_state - changes the current state of the wash cycle and
* lights the specified indicator. The previously
* lighted indicator, if any, is turned off.
***********************************************************************/

change_state (newstate,field) int newstate,field; {
/* log new state */
state = newstate;

/* if an indicator is ON, turn it OFF */
if (indicator != 0) fld_attr (win,indicator,1);

/* turn ON the requested indicator and remember it */
if (field != 0) fld_attr (win,field,5);
indicator = field;
}


/**********************************************************************
* stop_cycle - stops the current timer, if any. Changes field 1 back
* to an input field, enables the start button, and
* disables the stop button.
***********************************************************************/

stop_cycle () {
tim_erase (tim);
fld_type (win,1,FLT_INPUT);
fld_type (win,7,FLT_DESELECT);
fld_type (win,8,FLT_INACTIVE);
}











  3 Responses to “Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : APICSAMP.ZIP
Filename : WASHER.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/