home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / INTR_DMO.ZIP / INTR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-19  |  15.5 KB  |  428 lines

  1. Program Demonstrate_Interrupt_Handlers;
  2.  
  3. { This program is placed in the public domain by Steve Wood, author of
  4.   the book Using Turbo Pascal, published by Osborne McGraw-Hill. }
  5.  
  6. { Compile as a .COM program with segment sizes specified as follows:
  7.   For cOde enter 320
  8.   For Data enter 790
  9.   For mAx  enter 400
  10.   For mIn  enter 400 }
  11.  
  12. {$V-}  { These compiler directives should not be changed }
  13. {$K-}
  14. {$C-}
  15. {$R-}
  16.  
  17. {$I STD-ATTR.INC}  { Video addresses and attribute control routines. }
  18. {$I STD-CTV.INC}   { Standard global constants, types and variables. }
  19. {$I PLS-UTIL.INC}  { Misc. global procedures and functions. }
  20. {$I PLS-INP.INC}   { Controlled input and related routines. }
  21. {$I PLS-DISP.INC}  { Video display and related routines. }
  22. {$I DEMO-CTV.INC}  { Constants, types and vars specific to this program. }
  23.  
  24. const INTR_VECTOR = $80; { Defines the interrupt vector for the
  25.                            interrupt routine being defined.
  26.                            Be sure it does not conflict with
  27.                            other interrupt drivers that have
  28.                            been or will be installed. }
  29.  
  30. { Typed constants hold values pertinent to the calling
  31.   program (hold_xxx) and the interrupt program (new_xxx). }
  32.  
  33.       hold_sseg   : Integer = ZERO;
  34.       hold_sp     : Integer = ZERO;
  35.       new_dseg    : Integer = ZERO;
  36.       new_sseg    : Integer = ZERO;
  37.       new_sp      : Integer = ZERO;
  38.       mem_size    : Integer = $11B0;  { Indicates the amount of memory
  39.                                         ( in 16 byte paragraphs )
  40.                                         to be reserved for the resident
  41.                                         interrupt handler. This should
  42.                                         be equal or greater than the sum
  43.                                         of the code segment size, data
  44.                                         segment size and heap/stack size,
  45.                                         all of which must be specified
  46.                                         when the program is compiled. }
  47.  
  48.       NOTICE : Str_40 = 'copyright 1985 precision logic systems';
  49.  
  50. var   ms_reg      : RegPack;
  51.       hold_image  : Scrn_Image;
  52.  
  53. procedure Clear_Reg(var regs: RegPack);
  54.  
  55.   begin
  56.     FillChar(regs, sizeof(regs), ZERO);
  57.   end;  { Clear_Reg }
  58.  
  59. procedure NumLock_On;
  60.  
  61. { This procedure is not used in this program. I left it in because
  62.   it illustrates how Turbo can be used to control the hardware at
  63.   the lowest levels and felt you would find it of interest. SW }
  64.  
  65.   const NUMLOCK_ON    = $20;
  66.  
  67.   var   kbd_stat   : byte absolute $0000:$0417; { Keyboard status byte }
  68.  
  69.   begin
  70.     kbd_stat := (kbd_stat or NUMLOCK_ON);  { Set bit 5 forcing NumLock On }
  71.   end; { NumLock_On }
  72.  
  73. procedure Demo_Menu; { This is the procedure that is activated by
  74.                        interrupt $80. }
  75.  
  76.   procedure Initialize;
  77.     begin
  78.       usr_ptr[1] := Ofs(Usr_Out_Driver);  { Install Usr_Out_Driver as the }
  79.       usr_ptr[2] := Cseg;                 { Usr device driver.            }
  80.       vid_attr := BRIGHT_VID;
  81.       Load_Screen('PLS-MENU' + SCR_EXT,menu_buf);
  82.       Get_System_Date;
  83.       end_session := FALSE; esc_flag := FALSE; err_flag := FALSE;
  84.       help_flag := FALSE; msg_on := TRUE;
  85.       Load_Screen('PLS-PRMT' + SCR_EXT,prompt_dat);
  86.     end; { Initialize }
  87.  
  88. { The following procedures do not have to be overlay procedures. This
  89.   was done to illustrate the little known fact that interrupt handlers
  90.   can contain overlays. This means that a memory resident interrupt handler
  91.   need not be truly memory resident and its size is unlimited for all
  92.   practical purposes. }
  93.  
  94.   overlay procedure Not_Available;
  95.     begin
  96.       Disp_Prompt(MSG_BOX_PROMPT);
  97.       Display_Prompt(PROMPT_LINE,'MSG','Selection not yet available. Press'
  98.                                         + ENTER_KEY);
  99.       repeat Read_Kbd(inchr,inctl) until (inctl = CR);
  100.     end; { Not_Avaliable }
  101.  
  102.   overlay procedure Input_Demo_Data;
  103.  
  104.     var valid_set : Any_Char;
  105.  
  106.     function Current_Value(field: Byte): Str_80;
  107.       var num_str : Str_20;
  108.           len     : Byte;
  109.  
  110.       begin
  111.         Current_Value := NULL_STR;
  112.         len := fld_dat[field].fld_len;
  113.         with demo, fld_dat[field] do
  114.           case field of
  115.             1    : Current_Value := name;
  116.             2    : Current_Value := addr.attn;
  117.             3    : Current_Value := addr.addr;
  118.             4    : Current_Value := addr.city;
  119.             5    : Current_Value := addr.state;
  120.             6    : Current_Value := addr.zip1;
  121.             7    : Current_Value := addr.zip2;
  122.             8    : begin
  123.                      if (phone.area > ZERO) then
  124.                        Str(phone.area:3,num_str)
  125.                      else
  126.                        num_str := NULL_STR;
  127.                      Current_Value := num_str;
  128.                    end;
  129.             9    : begin
  130.                      if (phone.prefix > ZERO) then
  131.                        Str(phone.prefix:3,num_str)
  132.                      else
  133.                        num_str := NULL_STR;
  134.                      Current_Value := num_str;
  135.                    end;
  136.             10   : begin
  137.                      if (phone.number > ZERO) then
  138.                        Str(phone.number:4,num_str)
  139.                      else
  140.                        num_str := NULL_STR;
  141.                      Current_Value := num_str;
  142.                    end;
  143.           end; {case}
  144.       end; { Current_Value }
  145.  
  146.       procedure Disp_Field_Value(field: Byte);
  147.         var fld_str : Str_80;
  148.  
  149.         begin
  150.           fld_str := Current_Value(field);
  151.           if fld_str <> NULL_STR then
  152.             with fld_dat[field] do
  153.             begin  { Display fld_str and clear to end of field. }
  154.               GoTo_XY(xloc,yloc); Write_Usr_Str(fld_str);
  155.               Repeat_Usr_Char(SPACE,(fld_len - Length(fld_str)));
  156.             end
  157.           else
  158.             Init_Field(FILL_CHAR,fld_dat[field],fld_dat[field].disp_attr);
  159.         end; { Disp_Field_Value }
  160.  
  161.       procedure Display_Current_Values;
  162.         var  fld_no  : Byte;
  163.  
  164.         begin
  165.           cur_scrn := buf_scrn;
  166.           for fld_no := 1 to fld_cnt do
  167.             Disp_Field_Value(fld_no);
  168.         end; { Display_Current_Values }
  169.  
  170.     procedure Update_Demo_File;
  171.       begin
  172.         Seek(demo_file,ZERO);
  173.         Write(demo_file,demo);
  174.         modified := FALSE;
  175.       end; { Update_Parm_File }
  176.  
  177.     procedure Modify_Demo(fld_no,last_fld: Byte);
  178.  
  179.       procedure Input_Field;
  180.         var parms     : Fld_Parms;
  181.             err_msg,
  182.             cmd_msg   : Str_80;
  183.             len, i    : Byte;
  184.  
  185.         procedure Display_Default;
  186.           begin
  187.              vid_attr := REVERSE_VID;
  188.             with parms do
  189.             begin
  190.               GoTo_XY(xloc,yloc);
  191.               Write_Usr_Str(default);
  192.               Repeat_Usr_Char(SPACE,fld_len - Length(default));
  193.               vid_attr := BRIGHT_VID;
  194.               GoToXY(xloc,yloc);
  195.             end; {with}
  196.           end; { Display_Default }
  197.  
  198.         begin { Input_Field }
  199.           default := Current_Value(fld_no);
  200.           Disp_Prompt(FLD_INP_PROMPT);
  201.           GoTo_XY(7,MSG_LINE);
  202.           Write_Usr_Str(default);
  203.           parms := fld_dat[fld_no];
  204.           len := parms.fld_len;
  205.           Display_Default;
  206.           with demo do
  207.           case fld_no of
  208.                1    : name := Valid_Str(parms);
  209.                2    : addr.attn := Valid_Str(parms);
  210.                3    : addr.addr := Valid_Str(parms);
  211.                4    : addr.city := Valid_Str(parms);
  212.                5    : addr.state := Valid_Str(parms);
  213.                6    : addr.zip1 := Valid_Str(parms);
  214.                7    : addr.zip2 := Valid_Str(parms);
  215.                8    : phone.area := Valid_Int(parms,0,999);
  216.                9    : phone.prefix := Valid_Int(parms,0,999);
  217.                10   : phone.number := Valid_Int(parms,0,9999);
  218.              end; {case}
  219.           Disp_Field_Value(fld_no);  { Redisplay formated input }
  220.         end; { Input_Field }
  221.  
  222.       begin { Modify_Demo }
  223.         modified := TRUE;
  224.         accepted := FALSE;
  225.         repeat
  226.           Input_field;
  227.           if help_flag then
  228.             begin
  229.               Load_Screen('DEMO-HLP' + SCR_EXT,help_buf);
  230.               Disp_Help(1,5,18,[ESC]);
  231.               help_flag := FALSE;
  232.             end;
  233.           fld_no := fld_no + direction;
  234.           if (fld_no < 1) then
  235.             fld_no := 1;
  236.         until (accepted  or esc_flag) or (fld_no > last_fld);
  237.         if esc_flag then
  238.           esc_flag := FALSE;
  239.         if accepted then
  240.           Update_Demo_File;
  241.       end; { Modify_Demo }
  242.  
  243.       procedure Select_Field;
  244.         const  parms: Fld_Parms = (xloc      : 38;
  245.                                    yloc      : PROMPT_LINE;
  246.                                    fld_len   : 2;
  247.                                    fld_type  : NUMERIC;
  248.                                    exit_type : MANUAL;
  249.                                    inp_attr  : REVERSE_VID;
  250.                                    disp_attr : BRIGHT_VID;
  251.                                    msg_ptr   : 255);
  252.  
  253.         var i, fld_no  : Integer;
  254.             hold_vid   : Inp_Scrn;
  255.             prompt_msg : Str_80;
  256.  
  257.         begin  { Select_Field }
  258.           hold_vid := cur_scrn;
  259.           cur_scrn := buf_scrn;
  260.           Rev_Video;
  261.           for i := 1 to 10 do
  262.             with fld_dat[i] do
  263.             begin
  264.               GoToXY(xloc,yloc);
  265.               Write(SPACE,i,SPACE);
  266.             end;
  267.           Norm_Video;
  268.           repeat
  269.             Disp_Prompt(MSG_BOX_PROMPT);
  270.             vid_line[25] := prompt_ln[20];
  271.             prompt_msg := ('Enter field number. (1-10) ' + ARROW);
  272.             Display_Prompt(PROMPT_LINE,'INP',prompt_msg);
  273.             Init_Field(SPACE,parms,parms.inp_attr); default := '0';
  274.             fld_no := Valid_Int(parms,1,10);
  275.           until (fld_no in [1..10]) or esc_flag;
  276.           if esc_flag then
  277.             esc_flag := FALSE
  278.           else
  279.             begin
  280.               cur_scrn := hold_vid;
  281.               Modify_Demo(fld_no,10);
  282.             end;
  283.         end; { Select_Field }
  284.  
  285.     begin { Input_Demo_Data }
  286.       usr_ptr[1] := Ofs(Usr_Out_Driver);  { Install Usr_Out_Driver as the }
  287.       usr_ptr[2] := Cseg;                 { Usr video output driver.      }
  288.       Load_Inp_Scrn('DEMO-INP' + SCR_EXT,hold_vid[1]);
  289.       buf_scrn := vid_buf[1].buf_scrn;
  290.       fld_dat := vid_buf[1].buf_parm;
  291.       fld_cnt := fld_dat[72].fld_len;
  292.       cur_scrn := buf_scrn;
  293.       Disp_Prompt(ACCEPT_PROMPT); vid_line[25] := prompt_ln[19];
  294.       GoTo_XY(3,1); Write_Usr_Str((SPACE + sys_date + SPACE));
  295.       Assign(demo_file,'DEMO.DAT');
  296.       Reset(demo_file);
  297.       Read(demo_file,demo); modified := FALSE;
  298.       FillChar(fld_msg,SizeOf(fld_msg),ZERO);
  299.       Load_Fld_Msgs('DEMO.MSG');
  300.       mode := UPDATE;
  301.       repeat
  302.         Display_Current_Values;
  303.         Disp_Prompt(ACCEPT_PROMPT); vid_line[25] := prompt_ln[19];
  304.         GoToXY(43,MSG_LINE);
  305.         valid_set := (UPDT_SET + ACPT_SET) + (CANCEL_SET + HELP_SET);
  306.         inctl := Valid_Key(valid_set);
  307.         case inctl of
  308.           UPDT_REC    : Modify_Demo(1,10);
  309.           SLCT_FLD    : Select_Field;
  310.           ACCEPT      : begin
  311.                            Update_Demo_File;
  312.                            esc_flag := TRUE;
  313.                         end;
  314.           ESC         : if modified then
  315.                           Verify_Cancel
  316.                         else
  317.                           esc_flag := TRUE;
  318.           HELP        : begin
  319.                           Load_Screen('MENU-HLP.TSM',help_buf);
  320.                           Disp_Help(13,13,10,[ESC]);
  321.                         end;
  322.         end;
  323.       until (esc_flag or err_flag);
  324.       esc_flag := FALSE;
  325.       Close(demo_file);
  326.     end; { Input_Demo_Data }
  327.  
  328.     begin { Demo_Menu }
  329.       hold_image := vid_scrn;             { Save callers video screen image. }
  330.       repeat
  331.         Initialize;
  332.         Disp_Menu('DEMO.MNU',' D E M O   M E N U ');
  333.         GoToXY(65,21); Write(' End Session   ');
  334.         GoToXY(22,PROMPT_LINE); esc_flag := FALSE;
  335.         current_selection := Valid_Menu_Selection(6);
  336.         if esc_flag then
  337.           Verify_Exit;
  338.         if end_session then
  339.           begin
  340.             ClrScr; WriteLn('Session ended.'); WriteLn;
  341.           end
  342.         else
  343.           case current_selection of
  344.             1       : Input_Demo_Data;
  345.             2..6    : Not_Available;
  346.                       { To make selections valid, insert procedures
  347.                         as illustrated with case #1. }
  348.           end; {case}
  349.       until (end_session or err_flag);
  350.       if err_flag then
  351.         begin
  352.          WriteLn; WriteLn; WriteLn;
  353.          WriteLn('Session Terminated due to error indicated above.');
  354.          Write('Press any key. '); Read(Kbd,inchr);
  355.        end;
  356.      vid_scrn := hold_image;          { Restore callers video screen image. }
  357.     end; { Demo_Menu }
  358.  
  359.   procedure Save_Turbo_Values;
  360.  
  361.     begin
  362.       new_dseg := Dseg;              { Save Dseg          }
  363.       new_sseg := Sseg;              { Save Sseg          }
  364.       inline($2E/$89/$26/new_sp);    { MOV [cs:new_sp],sp }
  365.     end;  { Save_Turbo_Values }
  366.  
  367.   procedure Interrupt;
  368.  
  369. { ***** This is the entry point for the interrupt handler ***** }
  370.  
  371.     begin
  372.       inline($2E/$8C/$16/hold_sseg/ { Save current Sseg }
  373.              $2E/$89/$26/hold_sp/   { Save current sp }
  374.              $2E/$8E/$16/new_sseg/  { Point Sseg to new stack seg.}
  375.              $2E/$8B/$26/new_sp);   { Points sp to new TOS }
  376.  
  377.       inline($50/$53/$51/$52/$57/$56/$06/$1E); { PUSH ax, bx, cx, dx,
  378.                                                       di, si, es, ds }
  379.  
  380.       inline($2E/$A1/new_dseg/      { MOV ax,[cs:new_dseg] }
  381.              $8E/$D8/               { MOV ds,ax      Point to new ds }
  382.              $FB);                  { STI }
  383.  
  384.       Demo_Menu; { This may be replaced with any defined procedure identifier }
  385.  
  386.       inline($FA/                             { CLI }
  387.              $1F/$07/$5E/$5F/$5A/$59/$5B/$58/ { POP  ds, es, si, di,
  388.                                                      dx, cx, bx, ax }
  389.              $2E/$8E/$16/hold_sseg/           { MOV  ss,[cs:hold_sseg] }
  390.              $2E/$8B/$26/hold_sp/             { MOV  sp,[cs:hold_sp] }
  391.              $5D/$5D/$CF);                    { POP return addr and IRET }
  392.  
  393.     end; { Interrupt }
  394.  
  395. {  The main program starts here. Its purpose is to install the address
  396.    of Interrupt in the interrupt vector table as interrupt $80 and to
  397.    allocate enough memory to make the program memory resident. When
  398.    executed it will produce no visible results unless interrupt $80
  399.    is already used. }
  400.  
  401. begin { Demonstrate_Interrupt_Handler }
  402.   Save_Turbo_Values;   { So you can set up the environment in Interrupt. }
  403.   with ms_reg do
  404.   begin
  405.     Clear_Reg(ms_reg); { Not absolutely necessary, but not a bad idea. }
  406.  
  407. { Check to see if interrupt has already been installed. }
  408.  
  409.     ah := $35;  al := INTR_VECTOR; MsDos(ms_reg);
  410.     if es <> $00 then
  411.       begin
  412.         WriteLn(' Interrupt handler already installed.');
  413.         halt;                       { Quit if already installed }
  414.       end;
  415.  
  416. {  Install Interrupt procedure address at interrupt vector INTR_VECTOR. }
  417.  
  418.     ah := $25; al := INTR_VECTOR;
  419.     ds := Cseg; dx := Ofs(Interrupt);
  420.     MsDos(ms_reg);
  421.  
  422. { Make program memory resident reserving memory indicated by mem_size.}
  423.  
  424.     Clear_Reg(ms_reg);
  425.     ax := $3100; dx := mem_size;  MsDos(ms_reg);
  426.   end;  {with}
  427. end. { Demonstrate_Interrupt_Handlers }
  428.