home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
DESQVIEW
/
API_EXAM.ZIP
/
WASHER.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1988-10-03
|
12KB
|
446 lines
(****************************************************************
*
* 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.
*
****************************************************************)
program Washer;
uses DVAPI;
const
(* minimum API version required *)
REQUIRED = $201;
(* possible values of the "temperature" variable *)
HOT = 0;
WARM = 1;
COLD = 2;
(* possible values of the "state" variable *)
IDLE = 0;
WASHING = 1;
FIRST_RINSE = 2;
FIRST_SPIN = 3;
FINAL_RINSE = 4;
FINAL_SPIN = 5;
(* panel library filename in ASCIIZ string format *)
lib : string = 'examples.plb'#$00;
(* name of panel within panel library *)
name : string = 'washer';
var
(* actual API version number *)
version : integer;
(* object handles *)
winme,pan,win,kbd,tim,obj : ULONG;
type
(* keyboard buffer definition *)
KEYBUF = array [0..4] of byte;
var
(* variables used when reading from the menu *)
kptr,kend : pointer;
kbufptr : ^KEYBUF;
field,kstatus : byte;
klng,fsize,err : integer;
field1 : string[2];
(* variables set according to menu input *)
wash_time,temperature : integer;
second_rinse,bell : boolean;
(* state related variables *)
state,indicator : integer;
done : boolean;
(* variables for saving the cursor position *)
row,col : integer;
(* unused function results *)
status : integer;
(* TFDD text files *)
tfdme,tfd : text;
const
(* boolean values *)
ON = True;
OFF = False;
(**********************************************************************
* 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.
***********************************************************************)
procedure stop_cycle;
begin
tim_erase (tim);
fld_type (win,1,FLT_INPUT);
fld_type (win,7,FLT_DESELECT);
fld_type (win,8,FLT_INACTIVE);
end;
(**********************************************************************
* change_state - changes the current state of the wash cycle and
* lights the specified indicator. The previously
* lighted indicator, if any, is turned off.
***********************************************************************)
procedure change_state (newstate, field : integer);
begin
(* log new state *)
state := newstate;
(* if an indicator is ON, turn it OFF *)
if (indicator <> 0) then
fld_attr (win,indicator,1);
(* turn ON the requested indicator and remember it *)
if (field <> 0) then
fld_attr (win,field,5);
indicator := field;
end;
(**********************************************************************
* radio_button - select a specified field and deselect all others in
* the given range.
***********************************************************************)
procedure radio_button (win : ULONG; first,last,chosen : integer);
var
i : integer;
begin
(* loop for each field in range "first" through "last" *)
for i := first to last do
(* change "chosen" field type to SELECTed, others to DESELECTed *)
if (i = chosen) then
fld_type (win,i,FLT_SELECT)
else
fld_type (win,i,FLT_DESELECT);
end;
(**********************************************************************
* process_timer_event - process timer expiration
***********************************************************************)
procedure process_timer_event;
var
time : longint;
begin
(* read the timer object to clear the event *)
time := tim_read(tim);
(* save cursor position. Decrement time remaining and display. *)
wash_time := wash_time - 1;
qry_cursor (win,row,col);
fld_cursor (win,1);
write (tfd,wash_time:2);
(* 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) then
begin
case (state) of
WASHING :
if (second_rinse) then
change_state (FIRST_RINSE,11)
else
change_state (FINAL_RINSE,11);
FIRST_RINSE :
change_state (FIRST_SPIN,12);
FIRST_SPIN :
change_state (FINAL_RINSE,11);
FINAL_RINSE :
change_state (FINAL_SPIN,12);
FINAL_SPIN : (* Cycle complete - switch to IDLE state, beep if
requested. Restore original field types. *)
begin
change_state (IDLE,0);
if (bell) then
api_sound (2000,18);
stop_cycle;
end;
end;
(* 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) then
begin
wash_time := 3;
tim_addto (tim,100)
end
end
(* if clock is still counting, simply set timer for another second *)
else
tim_addto (tim,100);
(* restore cursor to its original position *)
win_cursor (win,row,col);
end;
(**********************************************************************
* process_menu_event - process data returned from the menu.
***********************************************************************)
procedure process_menu_event;
begin
(* get menu data and determine what event caused data to be returned *)
key_read (kbd,kptr,klng);
kbufptr := kptr;
kstatus := key_status (kbd);
(* beep and return if anything but a field selection *)
if (kstatus <> 1) then
begin
api_sound (1000,5);
exit;
end;
(* point just past returned data. Save current cursor position. *)
kend := @kbufptr^[klng];
qry_cursor (win,row,col);
(* loop once for each field returned *)
while (kbufptr <> kend) do
begin
(* get field # and length. Log field info to task window. *)
field := kbufptr^[0];
fsize := kbufptr^[1] + (kbufptr^[2] * 256);
write (tfdme,'field = ',field,' length = ',fsize,' contents = ');
win_write (winme,@kbufptr^[3],fsize);
writeln (tfdme);
(* dispatch based on field number *)
case (field) of
1 : (* wash time changed *)
begin
(* copy returned data to two character string variable *)
field1 := ' ';
move (kbufptr^[3],field1[1],2);
(* convert to integer, clip at zero, and set state to IDLE *)
val (field1,wash_time,err);
if (wash_time < 0) then
wash_time := 0;
change_state (IDLE,0);
end;
2 : (* Hot water selected - Select field 2. Deselect fields
3 and 4. Log temperature. *)
begin
radio_button (win,2,4,2);
temperature := HOT;
end;
3 : (* Warm water selected - Select field 3. Deselect fields
2 and 4. Log temperature. *)
begin
radio_button (win,2,4,3);
temperature := WARM;
end;
4 : (* Cold water selected - Select field 4. Deselect fields
2 and 3. Log temperature. *)
begin
radio_button (win,2,4,4);
temperature := COLD;
end;
5 : (* Second rinse - if the field data is "Y", the field is
selected. Otherwise, the data will be "N". *)
second_rinse := (chr(kbufptr^[3]) = 'Y');
6 : (* Beep when done - if the field data is "Y", the field is
selected. Otherwise, the data will be "N". *)
bell := (chr(kbufptr^[3]) = 'Y');
7 : (* Start button *)
begin
(* 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) then
begin
(* 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,100);
if (state = IDLE) then
change_state (WASHING,10);
end;
end;
8 : (* Stop button - stop cycle and reset field types. *)
stop_cycle;
9 : (* Exit button - stop cycle, reset fields, and set "done". *)
begin
stop_cycle;
done := True;
end;
else (* unknown field number - should never happen. *)
begin
writeln (tfdme,'impossible!');
end;
end;
(* bump pointer to next field and loop *)
kbufptr := @kbufptr^[fsize + 3];
end;
(* restore original cursor position *)
win_cursor (win,row,col);
end;
(**********************************************************************
* program_body - initialize application and loop processing events.
***********************************************************************)
procedure program_body;
begin
(* 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_sopen (pan,lib);
(* apply named panel, and return window & keyboard handles *)
status := pan_sapply (pan,winme,name,win,kbd);
(* open TFDDs and assign to windows *)
tfd_open (tfdme,winme);
tfd_open (tfd,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 := False;
(* initialize to default variables set according to menu input *)
wash_time := 0;
temperature := HOT;
second_rinse := False;
bell := False;
(* show panel window *)
win_top (win);
(* loop until "done" becomes TRUE *)
while (not done) do
begin
(* 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) then
process_menu_event
else
if (obj = tim) then
process_timer_event;
end;
(* close TFDDs *)
tfd_close (tfd);
tfd_close (tfdme);
(* free all allocated objects and return *)
key_free (kbd);
win_free (win);
pan_free (pan);
tim_free (tim);
end;
(**********************************************************************
* main - check for DESQview present and enable required extensions.
***********************************************************************)
begin
(* initialize Pascal 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) then
writeln ('This program requires DESQview version ',REQUIRED div 256,
'.',(REQUIRED mod 256) div 16,(REQUIRED mod 256) mod 16,' or later.')
(* tell DESQview what extensions to enable and start application *)
else
begin
api_level (REQUIRED);
program_body;
end;
(* disable Pascal interfaces and return from program *)
api_exit;
end.