home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / desqview / api_exam.arc / WASHER.C < prev    next >
C/C++ Source or Header  |  1988-04-28  |  13KB  |  397 lines

  1. /****************************************************************
  2. *
  3. *  Name:          WASHER
  4. *
  5. *  Function:      Emulate a washing machine control panel.
  6. *
  7. *  Shows how to:  1. construct complex menus (dialogues) including 
  8. *                    select, input, output, and inactive fields.
  9. *                 2. change field types dynamically.
  10. *                 3. implement "radio button" select fields.
  11. *                 4. use a timer object to measure time intervals.
  12. *                 5. use an objectq to wait for multiple events.
  13. *
  14. ****************************************************************/
  15.  
  16.  
  17. #include <stdio.h>
  18. #include "dvapi.h"
  19.  
  20. /* minimum API version required */
  21. #define required 0x201
  22.  
  23. /* possible values of the "temperature" variable */
  24. #define HOT  0
  25. #define WARM 1
  26. #define COLD 2
  27.  
  28. /* possible values of the "state" variable */
  29. #define IDLE            0
  30. #define WASHING         1
  31. #define FIRST_RINSE     2
  32. #define FIRST_SPIN      3
  33. #define FINAL_RINSE     4
  34. #define FINAL_SPIN      5
  35.  
  36. /* actual API version number */
  37. int     version;
  38.  
  39. /* object handles */
  40. ulong   winme,win,kbd,tim,obj;
  41.  
  42. /* variables used when reading from the menu */
  43. char    *kptr,*kend,field,field1[3];
  44. int     klng,kstatus,fsize;
  45.  
  46. /* variables set according to menu input */
  47. int     wash_time,temperature,second_rinse,bell;
  48.  
  49. /* state related variables */
  50. int     state,indicator,done;
  51.  
  52. /* variables for saving the cursor position */
  53. int     row,col;
  54.  
  55. /* this string defines the contents of the menu */
  56. char menu1[] = "\n\
  57.           WASHUMUP Laundry Service\n\n\
  58.  Wash Time:   [  ] seconds\n\n\
  59.  Water Temperature:   Hot   Warm   Cold\n\n\
  60.  Options:      2nd Rinse    Beep when done\n\n\
  61.  Indicators:   Wash   Rinse   Spin\n\
  62. ───────────────────────────────────────────\n\
  63.  START = Enter    STOP = F1    EXIT = Esc";
  64.  
  65.  
  66. /* this string defines the field table for the menu */
  67. char ftab1[] = {ftab(12,FTH_KEYSELECT+FTH_MODIFIED+FTH_AUTORESET,0,0,9,2),
  68.                      3,15,3,16,FTE_INPUT,FTE_RIGHTJUST+FTE_CLEARDFLT,0,0,
  69.                      5,21,5,25,FTE_SELECT,0,1,0,
  70.                      5,27,5,32,FTE_SELECT,0,1,0,
  71.                      5,34,5,39,FTE_SELECT,0,1,0,
  72.                      7,14,7,24,FTE_SELECT,0,1,0,
  73.                      7,27,7,42,FTE_SELECT,0,1,0,
  74.                      11,0,11,14,FTE_SELECT,13,1,0,
  75.                      11,17,11,27,FTE_INACTIVE,0,1,0x3B,
  76.                      11,30,11,41,FTE_SELECT,27,1,0,
  77.                      9,14,9,19,FTE_OUTPUT,0,0,0,
  78.                      9,21,9,27,FTE_OUTPUT,0,0,0,
  79.                      9,29,9,34,FTE_OUTPUT,0,0,0,
  80.                      };
  81.  
  82. /**********************************************************************
  83. *  main  -  check for DESQview present and enable required extensions.
  84. ***********************************************************************/
  85.  
  86. main () {
  87.   /* initialize C interfaces and get API version number */
  88.   version = api_init();
  89.  
  90.   /* if DESQview is not running or version is too low, display a message */ 
  91.   if (version < required) {
  92.     printf ("This program requires DESQview version %d.02%d or later.\n",
  93.              required/256,required%256);
  94.     }
  95.  
  96.   /* tell DESQview what extensions to enable and start application */
  97.   else {
  98.     api_level (required);
  99.     program_body();
  100.     }
  101.  
  102.   /* disable C interfaces and return from program */
  103.   api_exit();
  104.   }
  105.  
  106.  
  107. /**********************************************************************
  108. *  program_body  -  initialize application and loop processing events.
  109. ***********************************************************************/
  110.  
  111. program_body () {
  112.   /* get task window handle and open objectq */
  113.   winme = win_me();             
  114.   obq_open();                   
  115.  
  116.   /* create a new window for the menu and set to use logical attributes */
  117.   win = win_new ("",0,12,43);   
  118.   win_logattr (win,1);          
  119.   win_attr (win,1);             
  120.   win_erase (win);              
  121.  
  122.   /* create keyboard for menu.  Open in field mode with hardware cursor */
  123.   kbd = key_new();              
  124.   key_open  (kbd,win);          
  125.   key_addto (kbd,KBF_FIELD+KBF_CURSOR); 
  126.                                        
  127.   /* create timer object */
  128.   tim = tim_new();              
  129.  
  130.   /* write menu contents and field table.  Highlight heading line. */
  131.   win_swrite (win,menu1);       
  132.   win_cursor (win,1,9);         
  133.   win_repattr (win,26,9);       
  134.   win_stream (win,ftab1);       
  135.  
  136.   /* position menu, mark as displayable, and make topmost in application. */
  137.   win_move (win,5,17);          
  138.   win_unhide (win);             
  139.   win_top (win);                
  140.                                 
  141.   /* preselect "hot water".  Jump cursor to field 1.  Set "state" to idle */
  142.   radio_button (win,2,4,2);     
  143.   fld_cursor (win,1);           
  144.   change_state (IDLE,0);        
  145.   done = 0;
  146.  
  147.   /* loop until "done" becomes TRUE */
  148.   while (!done) {                       
  149.  
  150.     /* wait for input from any open object and return its handle */
  151.     obj = obq_read();           
  152.  
  153.     /* determine which object it is and process accordingly */
  154.     if (obj == kbd)             
  155.       process_menu_event();     
  156.     else
  157.     if (obj == tim)             
  158.       process_timer_event();    
  159.     };                          
  160.  
  161.   /* free all allocated objects and return */
  162.   tim_free (tim);
  163.   key_free (kbd);
  164.   win_free (win);
  165.   }                     
  166.  
  167.  
  168. /**********************************************************************
  169. *  process_menu_event  -  process data returned from the menu.
  170. ***********************************************************************/
  171.  
  172. process_menu_event () {
  173.   /* get menu data and determine what event caused data to be returned */
  174.   key_read (kbd,&kptr,&klng);   
  175.   kstatus = key_status (kbd);   
  176.  
  177.   /* beep and return if anything but a field selection */
  178.   if (kstatus != 1) {           
  179.     api_sound (1000,5);
  180.     return;
  181.     };
  182.  
  183.   /* point just past returned data.  Save current cursor position. */
  184.   kend = kptr+klng;             
  185.   qry_cursor (win,&row,&col);   
  186.  
  187.   /* loop once for each field returned */
  188.   while (kptr < kend) {         
  189.  
  190.     /* get field # and length.  Log field info to task window. */
  191.     field = *kptr;
  192.     fsize = *(int *)(kptr+1);    
  193.     win_printf (winme,"field = %d   length = %d   contents = ",field,fsize);
  194.     win_write (winme,kptr+3,fsize); 
  195.     win_printf (winme,"\n");
  196.  
  197.     /* dispatch based on field number */
  198.     switch (field) {            
  199.  
  200.       case 1: /* wash time changed */                   
  201.         /* copy returned data to string variable and zero terminate */
  202.         memcpy (field1,kptr+3,2);            
  203.         field1[2] = 0;               
  204.  
  205.         /* convert to integer, clip at zero, and set state to IDLE */
  206.         wash_time = atoi (field1);           
  207.         if (wash_time < 0)           
  208.           wash_time = 0;
  209.         change_state (IDLE,0);       
  210.         break;                       
  211.  
  212.       case 2: /* Hot water selected -  Select field 2.  Deselect fields
  213.                  3 and 4.  Log temperature. */ 
  214.         radio_button (win,2,4,2);            
  215.         temperature = HOT;                   
  216.         break;                       
  217.  
  218.       case 3: /* Warm water selected - Select field 3.  Deselect fields
  219.                  2 and 4.  Log temperature. */                  
  220.         radio_button (win,2,4,3);            
  221.         temperature = WARM;          
  222.         break;                       
  223.  
  224.       case 4: /* Cold water selected - Select field 4.  Deselect fields
  225.                  2 and 3.  Log temperature. */
  226.         radio_button (win,2,4,4);            
  227.         temperature = COLD;          
  228.         break;                       
  229.  
  230.       case 5: /* Second rinse - if the field data is "Y", the field is
  231.                  selected.  Otherwise, the data will be "N". */
  232.         second_rinse = (*(kptr+3) == 'Y'); 
  233.         break;                          
  234.  
  235.       case 6: /* Beep when done - if the field data is "Y", the field is
  236.                  selected.  Otherwise, the data will be "N". */         
  237.         bell = (*(kptr+3) == 'Y');           
  238.         break;                       
  239.  
  240.       case 7: /* Start button */
  241.         /* deselect field so it does not remain highlighted */
  242.         fld_type (win,7,FLT_DESELECT);  
  243.  
  244.         /* ignore if no wash time has been selected.  Otherwise ... */
  245.         if (wash_time != 0) {        
  246.  
  247.           /* convert field 1 to an output field.  Disable the start button
  248.              and enable the stop button */
  249.           fld_type (win,1,FLT_OUTPUT);   
  250.           fld_type (win,7,FLT_INACTIVE); 
  251.           fld_type (win,8,FLT_DESELECT); 
  252.  
  253.           /* set timer to run 1 second.  If IDLE, set state to WASHING. */
  254.           tim_addto (tim,100L);      
  255.           if (state == IDLE)         
  256.             change_state (WASHING,10);
  257.           }
  258.         break;                       
  259.  
  260.       case 8: /* Stop button - stop cycle and reset field types. */
  261.         stop_cycle();
  262.         break;                       
  263.  
  264.       case 9: /* Exit button - stop cycle, reset fields, and set "done". */
  265.         stop_cycle();
  266.         done = 1;
  267.         break;
  268.  
  269.       default: /* unknown field number - should never happen. */
  270.         win_printf (winme,"impossible!\n");
  271.       }
  272.  
  273.     /* bump pointer to next field and loop */
  274.     kptr += (fsize+3);          
  275.     }                           
  276.  
  277.   /* restore original cursor position */
  278.   win_cursor (win,row,col);     
  279.   }                             
  280.  
  281.  
  282. /**********************************************************************
  283. *  process_timer_event  -  process timer expiration
  284. ***********************************************************************/
  285.  
  286. process_timer_event () {
  287.   long time;                    
  288.  
  289.   /* read the timer object to clear the event */
  290.   time = tim_read(tim);         
  291.  
  292.   /* save cursor position.  Decrement time remaining and display. */
  293.   wash_time -= 1;               
  294.   qry_cursor (win,&row,&col);   
  295.   fld_cursor (win,1);           
  296.   win_printf (win,"%2d",wash_time);  
  297.  
  298.   /* if the clock has expired, dispatch based on current state.
  299.      In each case, switch to the next state and light the appropriate
  300.      indicator. */
  301.   if (wash_time == 0) {         
  302.     switch (state) {            
  303.       case WASHING:             
  304.         change_state ((second_rinse) ? FIRST_RINSE:FINAL_RINSE, 11);
  305.         break;
  306.       case FIRST_RINSE:         
  307.         change_state (FIRST_SPIN,12);
  308.         break;
  309.       case FIRST_SPIN:          
  310.         change_state (FINAL_RINSE,11);
  311.         break;
  312.       case FINAL_RINSE:         
  313.         change_state (FINAL_SPIN,12);
  314.         break;
  315.       case FINAL_SPIN: /* Cycle complete - switch to IDLE state, beep if
  316.                           requested.  Restore original field types. */
  317.         change_state (IDLE,0);
  318.         if (bell == 1) api_sound (2000,18);
  319.         stop_cycle();
  320.         break;                          
  321.       }
  322.  
  323.     /* unless we are now IDLE, we need to start a rinse or spin cycle.
  324.        do so by setting the clock to 3 seconds and setting the timer to
  325.        expire in 1 second. */
  326.     if (state != IDLE) {                
  327.       wash_time = 3;            
  328.       tim_addto (tim,100L);     
  329.       }
  330.     }
  331.  
  332.   /* if clock is still counting, simply set timer for another second */
  333.   else                          
  334.     tim_addto (tim,100L);       
  335.  
  336.   /* restore cursor to its original position */
  337.   win_cursor (win,row,col);     
  338.   }
  339.  
  340.  
  341. /**********************************************************************
  342. *  radio_button  -  select a specified field and deselect all others in 
  343. *                   the given range.
  344. ***********************************************************************/
  345.  
  346. radio_button (win,first,last,chosen) ulong win; int first,last,chosen; {
  347.   int i;
  348.  
  349.   /* loop for each field in range "first" through "last" */
  350.   for (i=first; i<=last; i++)
  351.  
  352.     /* change "chosen" field type to SELECTed, others to DESELECTed */
  353.     fld_type (win,i,(i==chosen) ? FLT_SELECT : FLT_DESELECT);
  354.   }
  355.  
  356.  
  357. /**********************************************************************
  358. *  change_state  -  changes the current state of the wash cycle and 
  359. *                   lights the specified indicator.  The previously
  360. *                   lighted indicator, if any, is turned off.
  361. ***********************************************************************/
  362.  
  363. change_state (newstate,field) int newstate,field; {
  364.   /* log new state */
  365.   state = newstate;
  366.  
  367.   /* if an indicator is ON, turn it OFF */
  368.   if (indicator != 0) fld_attr (win,indicator,1);
  369.  
  370.   /* turn ON the requested indicator and remember it */
  371.   if (field != 0)     fld_attr (win,field,5);
  372.   indicator = field;
  373.   }
  374.  
  375.  
  376. /**********************************************************************
  377. *  stop_cycle  -  stops the current timer, if any.  Changes field 1 back
  378. *                 to an input field, enables the start button, and 
  379. *                 disables the stop button.
  380. ***********************************************************************/
  381.  
  382. stop_cycle () {
  383.   tim_erase (tim);                   
  384.   fld_type (win,1,FLT_INPUT);     
  385.   fld_type (win,7,FLT_DESELECT);  
  386.   fld_type (win,8,FLT_INACTIVE);  
  387.   }  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.