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,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;
-
- /* this string defines the contents of the menu */
- char menu1[] = "\n\
- WASHUMUP Laundry Service\n\n\
- Wash Time: [ ] seconds\n\n\
- Water Temperature: Hot Warm Cold\n\n\
- Options: 2nd Rinse Beep when done\n\n\
- Indicators: Wash Rinse Spin\n\
- ───────────────────────────────────────────\n\
- START = Enter STOP = F1 EXIT = Esc";
-
-
- /* this string defines the field table for the menu */
- char ftab1[] = {ftab(12,FTH_KEYSELECT+FTH_MODIFIED+FTH_AUTORESET,0,0,9,2),
- 3,15,3,16,FTE_INPUT,FTE_RIGHTJUST+FTE_CLEARDFLT,0,0,
- 5,21,5,25,FTE_SELECT,0,1,0,
- 5,27,5,32,FTE_SELECT,0,1,0,
- 5,34,5,39,FTE_SELECT,0,1,0,
- 7,14,7,24,FTE_SELECT,0,1,0,
- 7,27,7,42,FTE_SELECT,0,1,0,
- 11,0,11,14,FTE_SELECT,13,1,0,
- 11,17,11,27,FTE_INACTIVE,0,1,0x3B,
- 11,30,11,41,FTE_SELECT,27,1,0,
- 9,14,9,19,FTE_OUTPUT,0,0,0,
- 9,21,9,27,FTE_OUTPUT,0,0,0,
- 9,29,9,34,FTE_OUTPUT,0,0,0,
- };
-
- /**********************************************************************
- * 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 a new window for the menu and set to use logical attributes */
- win = win_new ("",0,12,43);
- win_logattr (win,1);
- win_attr (win,1);
- win_erase (win);
-
- /* create keyboard for menu. Open in field mode with hardware cursor */
- kbd = key_new();
- key_open (kbd,win);
- key_addto (kbd,KBF_FIELD+KBF_CURSOR);
-
- /* create timer object */
- tim = tim_new();
-
- /* write menu contents and field table. Highlight heading line. */
- win_swrite (win,menu1);
- win_cursor (win,1,9);
- win_repattr (win,26,9);
- win_stream (win,ftab1);
-
- /* position menu, mark as displayable, and make topmost in application. */
- win_move (win,5,17);
- win_unhide (win);
- win_top (win);
-
- /* 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;
-
- /* 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 */
- tim_free (tim);
- key_free (kbd);
- win_free (win);
- }
-
-
- /**********************************************************************
- * 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);
- }
-
-
-
-
-
-
-
-
-
-