home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- *
- * 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 <stdio.h>
- #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);
- }
-
-
-
-
-
-
-
-
-