home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / pascal / pasdox / aesvdi.txt < prev    next >
Text File  |  1985-11-18  |  13KB  |  290 lines

  1. { -----------------------------------------------------------------------------
  2.  
  3.                                  NOTICE:
  4.  
  5.       THESE MATERIALS are UNSUPPORTED by OSS!  If you do not understand how to
  6.       use them do not contact OSS for help!  We will not teach you how to 
  7.       program in Pascal.  If you find an error in these materials, feel free
  8.       to SEND US A LETTER explaining the error, and how to fix it.
  9.  
  10.       THE BOTTOM LINE:
  11.  
  12.          Use it, enjoy it, but you are on your own when using these materials!
  13.  
  14.  
  15.                                DISCLAIMER:
  16.  
  17.       OSS makes no representations or warranties with respect to the contents
  18.       hereof and specifically disclaim all warranties of merchantability or
  19.       fitness for any particular purpose.   This document is subject to change
  20.       without notice.
  21.       
  22.       OSS provides these materials for use with Personal Pascal.  Use them in
  23.       any way you wish.
  24.  
  25.    -------------------------------------------------------------------------- }
  26.  
  27.  
  28. MAKING GENERIC AES AND VDI CALLS FROM PERSONAL PASCAL
  29. -----------------------------------------------------
  30.  
  31. As some of you have discovered, because of prior experience with the Atari ST
  32. developer's package, there are a number of calls within the GEM system (AES and
  33. VDI) which are not yet supported by Personal Pascal.  Luckily, within the
  34. PASGEM library there are two routines which already support additional calls to
  35. GEM.  This document gives you the information you need in order to call these
  36. two generic GEM routines.
  37.  
  38. AES CALLS
  39. ---------
  40.  
  41. First of all, we are going to tackle AES calls.  In the process of explaining
  42. how to call the generalized AES routine, we will be implementing a new call
  43. which is not supported by Pascal.  This routine, which is called "graf_mkstate"
  44. in the C bindings, returns the current state of the mouse buttons and the key-
  45. board modifier keys (i.e., alternate, left and right shift keys, and control).
  46. This routine takes four parameters which are the addresses of four two-byte
  47. variables in which to put the mouse and keyboard state information.  Since
  48. passing an address in Pascal is equivalent to passing a variable as a VAR
  49. parameter, the declaration of the routine we're going to construct is going
  50. to start like this:
  51.  
  52.   { Mouse_Key_State - Return the current mouse position and the state of both
  53.       the mouse buttons and the keyboard modifier keys. }
  54.  
  55.   PROCEDURE Mouse_Key_State( VAR x, y, buttons, keys : integer ) ;
  56.  
  57. Before we start filling in the rest of the procedure, we have to look at how
  58. parameters are passed to the AES.  There are four separate areas in which
  59. values are passed to and returned from AES.  The first area is the "global
  60. parameter area", where AES stores various parameters it needs to keep around
  61. between calls.  Since the application program should not modify these values,
  62. there is no way to access the "global" array from Pascal.  The second area is
  63. the "integer input array", in which various integer values may be passed to
  64. AES.  Similarly, there is an "integer output array" in which AES passes values
  65. back to the calling program.  The fourth and fifth arrays are the "address
  66. input array" and the "address output array".  These two areas will contain
  67. address parameters passed to or from AES.  The Pascal library keeps track of
  68. the global parameter area, since it must remain intact, but the other arrays
  69. must be declared in your GEM program if you want to make calls to the AES
  70. handler.  In order to declare the arrays easily, we will set up their types
  71. first:
  72.  
  73.   TYPE
  74.     Pointer = ^char ;   { Just a filler declaration! }
  75.     Int_In_Parms    = ARRAY [ 0..15 ] OF integer ;
  76.     Int_Out_Parms   = ARRAY [ 0..45 ] OF integer ;
  77.     Addr_In_Parms   = ARRAY [ 0..1 ] OF Pointer ;
  78.     Addr_Out_Parms  = ARRAY [ 0..0 ] OF Pointer ;
  79.  
  80. The declaration of "Pointer" is just used to emphasize that the address in and
  81. out parameters are ADDRESSES, and not just numeric values.  Notice that the
  82. integer arrays only have lengths 16 and 46, respectively.  This is sufficient
  83. for most calls, but if you want to make a call to VDI (see below) which needs
  84. more slots in these arrays, increase the size accordingly.  Now that we know
  85. the TYPEs of the local variables we need, we can declare them:
  86.  
  87.   VAR
  88.     int_in   : Int_In_Parms ;
  89.     int_out  : Int_Out_Parms ;
  90.     addr_in  : Addr_In_Parms ;
  91.     addr_out : Addr_Out_Parms ;
  92.  
  93. OK, we're ready to look into the actual routine which we will be calling to
  94. interface to GEM.  It takes five parameters.  The first is the AES call number,
  95. which is 79 for out "graf_mkstate" call.  The next four parameters are just the
  96. arrays which we just declared, passed as VAR parameters.  The routine should be
  97. declared EXTERNAL as follows:
  98.  
  99.   PROCEDURE AES_Call( op : integer ;
  100.                 VAR int_in : Int_In_Parms ; VAR int_out : Int_Out_Parms ;
  101.                 VAR addr_in : Addr_In_Parms ; VAR addr_out : Addr_Out_Parms ) ;
  102.     EXTERNAL ;
  103.  
  104. Now that we know all of our variables and parameters, and everything the
  105. AES_Call routine is expecting, we can look at what we need to do to actually
  106. perform the GEM call.  According to the AES documentation, the "graf_mkstate"
  107. call doesn't expect any parameters, and it returns the results in the "integer
  108. output array" as follows:
  109.  
  110.     int_out[0] -- error code (0 if no error occurred)
  111.     int_out[1] -- current mouse x position
  112.     int_out[2] -- mouse y position
  113.     int_out[3] -- mouse button state
  114.     int_out[4] -- keyboard modifier state
  115.  
  116. We should never get an error with this call, since no parameters are passed in,
  117. so we're going to ignore the error code.  This isn't a good idea in general,
  118. but it simplifies our presentation somewhat.  The complete code required to
  119. perform the call and return the result values in the proper parameters is as
  120. follows:
  121.  
  122.   BEGIN
  123.     AES_Call( 79, int_in, int_out, addr_in, addr_out ) ;
  124.     x := int_out[1] ;
  125.     y := int_out[2] ;
  126.     buttons := int_out[3] ;
  127.     keys    := int_out[4] ;
  128.   END ;
  129.  
  130. To summarize this section on making AES calls, here is a complete listing of
  131. the Mouse_Key_State routine, without the intervening text:
  132.  
  133.   { Mouse_Key_State - Return the current mouse position and the state of both
  134.       the mouse buttons and the keyboard modifier keys. }
  135.  
  136.   PROCEDURE Mouse_Key_State( VAR x, y, buttons, keys : integer ) ;
  137.  
  138.     TYPE
  139.       Pointer = ^char ;   { Just a filler declaration! }
  140.       Int_In_Parms    = ARRAY [ 0..15 ] OF integer ;
  141.       Int_Out_Parms   = ARRAY [ 0..45 ] OF integer ;
  142.       Addr_In_Parms   = ARRAY [ 0..1 ] OF Pointer ;
  143.       Addr_Out_Parms  = ARRAY [ 0..0 ] OF Pointer ;
  144.  
  145.     VAR
  146.       int_in   : Int_In_Parms ;
  147.       int_out  : Int_Out_Parms ;
  148.       addr_in  : Addr_In_Parms ;
  149.       addr_out : Addr_Out_Parms ;
  150.  
  151.     PROCEDURE AES_Call( op : integer ;
  152.                 VAR int_in : Int_In_Parms ; VAR int_out : Int_Out_Parms ;
  153.                 VAR addr_in : Addr_In_Parms ; VAR addr_out : Addr_Out_Parms ) ;
  154.       EXTERNAL ;
  155.  
  156.     BEGIN
  157.       AES_Call( 79, int_in, int_out, addr_in, addr_out ) ;
  158.       x := int_out[1] ;
  159.       y := int_out[2] ;
  160.       buttons := int_out[3] ;
  161.       keys    := int_out[4] ;
  162.     END ;
  163.  
  164. VDI CALLS
  165. ---------
  166.  
  167. Accessing the VDI system is very similar to the discussion of AES calls above.
  168. The only main difference is that, although there is a "global parameter array",
  169. it doesn't need to stay intact.  Also, sometimes you need to get return values
  170. in this array.  Also, no address parameters are ever passed, but a new type of
  171. value is passed and returned, points.  So the TYPE declarations for the various
  172. arrays we need are slightly different:
  173.  
  174.   TYPE
  175.     Ctrl_Parms      = ARRAY [ 0..11 ] OF integer ;
  176.     Int_In_Parms    = ARRAY [ 0..15 ] OF integer ;
  177.     Int_Out_Parms   = ARRAY [ 0..45 ] OF integer ;
  178.     Pts_In_Parms    = ARRAY [ 0..11 ] OF integer ;
  179.     Pts_Out_Parms   = ARRAY [ 0..11 ] OF integer ;
  180.  
  181. For our VDI calling example, we're going to implement the call which allows you
  182. to control the height of text that is drawn using the "Draw_String" call.  This
  183. call is known in the VDI documentation as "vst_height", but we're going to
  184. declare it like this:
  185.  
  186.   { Text_Height - Set the height in pixels of text, when it is drawn using the
  187.       Draw_String library call. }
  188.  
  189.   PROCEDURE Text_Height( height : integer ) ;
  190.  
  191. Again, we need to declare the variables which we are going to pass to VDI:
  192.  
  193.     VAR
  194.       control : Ctrl_Parms ;
  195.       int_in  : Int_In_Parms ;
  196.       int_out : Int_Out_Parms ;
  197.       pts_in  : Pts_In_Parms ;
  198.       pts_out : Pts_Out_Parms ;
  199.  
  200. The actual generic routine we are going to call to perform VDI operations is
  201. very similar to the AES_Call routine described above.  One difference is that
  202. we pass two command numbers instead of one.  The second number is only used
  203. when we call the GSX graphics primitives; it is the GSX primitive number which
  204. we want to use.  For all non-GSX calls (i.e., most of the time), this second
  205. number will be zero (as it is in this case).  Also, there is one additional
  206. parameter, called "translate" in the declaration below, which specifies whether
  207. to translate the points in the "pts_in" and "pts_out" array RELATIVE to the
  208. current origin.  What this means is that if you use the Set_Window call to
  209. make a window current, all points passed to or from VDI will be translated
  210. to screen coordinates such that (0,0) is equivalent to the upper left of that
  211. window, PROVIDED the value of "translate" is true.  If you don't want such
  212. translation to occur (we don't, in this case, since the "point" we are passing
  213. is actually the height we want!), pass in "false" for this parameter.  The
  214. declaration of the generic VDI call is as follows:
  215.  
  216.   PROCEDURE VDI_Call( cmd, sub_cmd : integer ; nints, npts : integer ;
  217.                 VAR ctrl : Ctrl_Parms ;
  218.                 VAR int_in : Int_In_Parms ; VAR int_out : Int_Out_Parms ;
  219.                 VAR pts_in : Pts_In_Parms ; VAR pts_out : Pts_Out_Parms ;
  220.                 translate : boolean ) ;
  221.     EXTERNAL ;
  222.  
  223. Notice that we must tell VDI the number of integers and points which we are
  224. passing.  The particular call we want to use is number 12, "set character
  225. height, absolute mode".  It expects two parameters, as follows:
  226.  
  227.     pts_in[0] -- 0 (the value zero)
  228.     pts_in[1] -- desired height in pixels
  229.  
  230. It returns several parameters:
  231.  
  232.     pts_out[0] -- character width selected
  233.     pts_out[1] -- character height selected
  234.     pts_out[2] -- character cell width selected
  235.     pts_out[3] -- character cell height selected
  236.  
  237. Why are there four return values instead of two?  The first two (0 and 1) are
  238. usually SMALLER than the other two, for the following reason.  The "character
  239. height" (not cell height) is measured from the baseline (the bottom of capital
  240. letters) to the top line (the top of capitals, including a little space).  The
  241. character width is, similarly, measured from the left edge to the right edge
  242. of characters.  The "cell width" and "cell height", on the other hand, are
  243. measured from the very bottom to the very top and the very left to the very
  244. right of the "cell" in which a character is drawn.  Since some space is put
  245. on all sides of a character, the "cell" measurements are a little larger than
  246. the other measurements.  We're actually going to ignore all of the return
  247. parameters, since we just want to set the values and assume they are correct.
  248. The main body of our PROCEDURE is, then:
  249.  
  250.   BEGIN
  251.     pts_in[0] := 0 ;
  252.     pts_in[1] := height ;
  253.     VDI_Call( 12, 0, 0, 2, control, int_in, int_out, pts_in, pts_out, false ) ;
  254.   END ;
  255.  
  256. In order to look at the routine as a whole, here are all the neccessary
  257. declarations and code together, without the intervening text:
  258.  
  259.   { Text_Height - Set the height in pixels of text, when it is drawn using the
  260.       Draw_String library call. }
  261.  
  262.   PROCEDURE Text_Height( height : integer ) ;
  263.  
  264.     TYPE
  265.       Ctrl_Parms      = ARRAY [ 0..11 ] OF integer ;
  266.       Int_In_Parms    = ARRAY [ 0..15 ] OF integer ;
  267.       Int_Out_Parms   = ARRAY [ 0..45 ] OF integer ;
  268.       Pts_In_Parms    = ARRAY [ 0..11 ] OF integer ;
  269.       Pts_Out_Parms   = ARRAY [ 0..11 ] OF integer ;
  270.  
  271.     VAR
  272.       control : Ctrl_Parms ;
  273.       int_in  : Int_In_Parms ;
  274.       int_out : Int_Out_Parms ;
  275.       pts_in  : Pts_In_Parms ;
  276.       pts_out : Pts_Out_Parms ;
  277.  
  278.     PROCEDURE VDI_Call( cmd, sub_cmd : integer ; nints, npts : integer ;
  279.                 VAR ctrl : Ctrl_Parms ;
  280.                 VAR int_in : Int_In_Parms ; VAR int_out : Int_Out_Parms ;
  281.                 VAR pts_in : Pts_In_Parms ; VAR pts_out : Pts_Out_Parms ;
  282.                 translate : boolean ) ;
  283.       EXTERNAL ;
  284.  
  285.     BEGIN
  286.       pts_in[0] := 0 ;
  287.       pts_in[1] := height ;
  288.       VDI_Call(12, 0, 0, 2, control, int_in, int_out, pts_in, pts_out, false);
  289.     END ;
  290.