home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / TOTDOC.ZIP / CHAPT3.TXT < prev    next >
Encoding:
Text File  |  1991-02-10  |  48.0 KB  |  1,059 lines

  1.                                                                   Toolkit Basics
  2.  
  3.  
  4.  
  5.  
  6.  
  7.          "No, what I said was 'No new taxis'"        Georgio Bush, 1990
  8.  
  9.  
  10.  
  11.  
  12.  
  13. An Object Primer
  14.  
  15.          Let's talk cars. We all know that you don't need to be a combustion
  16.          mechanic to drive a car (that's a veeehickle if you're from Texas), but
  17.          most good drivers know a few basic principles about how a car works.
  18.          The same philosophy is true for object oriented programming: you don't
  19.          need to be an OOP guru to use the Toolkit but a little understanding is
  20.          helpful. The modest goal of this section is to explain some of the
  21.          object oriented principles to help you get up and running with the
  22.          Toolkit as soon as possible. Over time, you will gain OOP expertise
  23.          without even trying! If you are already familiar with OOP, skip to the
  24.          next section.
  25.  
  26.          For now, we will concentrate on those aspects of OOP you will need in
  27.          order to understand how to use the Toolkit. In Part 2: Extending the
  28.          Toolkit, the more advanced concepts of inheritance and extensibility
  29.          are addressed.
  30.  
  31.  
  32.  
  33.          In plain Pascal, there are types like integer, real, string, etc. and
  34.          you declare variables to be of a specific type. You can even define new
  35.          types. For example, the following declaration defines a new type
  36.          Address:
  37.  
  38.                   TYPE
  39.                   Address = record
  40.                      Name: string[20];
  41.                      Street: string[30];
  42.                      CityStZip: string[20];
  43.                   end;
  44.  
  45.  
  46.          Having defined the type Address, you can then create variables of this
  47.          type, e.g.
  48.  
  49.                   VAR
  50.                   BobsHouse: Address;
  51.  
  52.  
  53.          In most programs, you will write procedures and functions that can
  54.          manipulate the data stored in these variables, e.g.
  55.  
  56.                   procedure PrintLabel(Addr: address);
  57.                   function  Zip(Addr:address): string;
  58.  
  59.  
  60.  
  61. 3-2                                                                 User's Guide
  62.  
  63. --------------------------------------------------------------------------------
  64.  
  65.          But most of you know this stuff anyway. Things aren't so very different
  66.          with OOP. The primary difference is that, with OOP, the data and the
  67.          procedures and functions which manipulate the data are combined into a
  68.          single type, called an object. This concept of combining data and
  69.          procedures/functions is referred to as encapsulation. Listed below is a
  70.          way to create an object type called AddressOBJ:
  71.  
  72.                   TYPE
  73.                   AddressOBJ = object
  74.                      Name: string[20];
  75.                      Street: string[30];
  76.                      CityStZip: string[20];
  77.                      {methods ...}
  78.                      procedure PrintLabel;
  79.                      function  Zip: string;
  80.                   end; {object}
  81.  
  82.                   VAR
  83.                   BobsHouse: AddressOBJ;
  84.  
  85.  
  86.          Notice that the object type declaration is very similar to a record
  87.          declaration, but the keyword object is used instead of record. The
  88.          procedure and function declaration are included in the object declara-
  89.          tion, and are referred to (in OOP nomenclature) as methods. The methods
  90.          are not passed the address record as a parameter, because the procedure
  91.          and functions in an object can directly access the data in the object,
  92.          and so don't need to be passed the data. The "variable" BobsHouse,
  93.          which is of type AddressOBJ, is referred to as an instance - in other
  94.          words, object variables are called instances! All object type declara-
  95.          tions in the Toolkit end with the characters "OBJ".
  96.  
  97.          The individual elements of an object (just like a record) can be
  98.          accessed by using the "dot" notation. For example, to print a label,
  99.          you would use the following statement:
  100.  
  101.                   BobsHouse.PrintLabel
  102.  
  103.  
  104.          You can also use the "with identifier do" shortcut, e.g.
  105.  
  106.                   with BobsHouse do
  107.                   begin
  108.                      PrintLabel
  109.                      .....
  110.                   end; {with}
  111.  
  112.  
  113.          In theory, you could also access the data elements using the dot
  114.          method, e.g. BobsHouse.Street := '12 Paradise Drive', but you
  115.          shouldn't! While it is syntactically correct and will compile, this is
  116.          bad practice. A basic precept of encapsulation is that you never access
  117.  
  118.  
  119. Toolkit Basics                                                               3-3
  120.  
  121. --------------------------------------------------------------------------------
  122.  
  123.          the data elements of an instance directly. You should create methods
  124.          within the object to access the object's data. In the above example,
  125.          there is no way to access the data in the object (other than breaking
  126.          the rules) so a data update method would need to be created. Listed
  127.          below is an improved type declaration of the AddressOBJ:
  128.  
  129.                   TYPE
  130.                   AddressOBJ = object
  131.                      Name: string[20];
  132.                      Street: string[30];
  133.                      CityStZip: string[20];
  134.                      {methods ...}
  135.                      procedure Adddata(Nam,St,Ci,St,Zp:string);
  136.                      procedure PrintLabel;
  137.                      function  Zip: string;
  138.                   end; {object}
  139.  
  140.  
  141.          The new AddData method would be used to set the values of the Name,
  142.          Street and CityStZip elements. For example, the following two state-
  143.          ments would print the label:
  144.  
  145.                   with BobsHouse do
  146.                   begin
  147.                      AddData('Bobbo','12 Paradise Drive',
  148.                              'Dome','TX','77186');
  149.                      Printlabel;
  150.                   end;
  151.  
  152.  
  153.          If you are curious, each method identified in an object must be
  154.          included in the body of the program or unit. For example, later in the
  155.          program there might be the following method definition:
  156.  
  157.                   ...
  158.  
  159.                   procedure AddressOBJ.Adddata(Nam,St,Ci,St,Zp:string);
  160.                   {}
  161.                   begin
  162.                      Name := copy(Nam,1,20);
  163.                      Street := copy(St,1,30);
  164.                      ...
  165.                   end; {of proc}
  166.  
  167.                   ...
  168.  
  169.  
  170.          Now, back to the main discussion. The advantage of using methods to
  171.          access the object data is that the object user (that's you) does not
  172.          need to know or care about how the data is stored within the object.
  173.          The internal data structure might be modified at some stage to use
  174.  
  175.  
  176.  
  177. 3-4                                                                 User's Guide
  178.  
  179. --------------------------------------------------------------------------------
  180.  
  181.          pointers or to store ASCIIZ strings, etc, but the same method AddData
  182.          can still be called in the same way as previously. What Adddata does
  183.          (behind the scenes) may have changed, but your program still compiles
  184.          and runs without modification.
  185.  
  186.          For various reasons, many objects need to be initialized before they
  187.          can be used. For example, some memory may need to be allocated on the
  188.          heap. When you have finished with such an object, the memory will need
  189.          to be disposed of. Just because the procedure in which you declared an
  190.          object instance (i.e. variable) has terminated, it does not necessarily
  191.          mean that the object data has been removed.
  192.  
  193.          Although not mandatory, a de facto OOP standard is to have two special
  194.          methods for all objects. Namely, INIT and DONE. These special methods
  195.          are used to initialize an object and dispose of an object, respec-
  196.          tively. Throughout the Toolkit, every object has INIT and DONE methods.
  197.          Always call INIT before any other object methods, and always call DONE
  198.          when you have finished with an object. In some instances the INIT
  199.          method may require some parameters.
  200.  
  201.          In our example, the object is useless if no data has been assigned.
  202.          Adopting the new convention, it might be more appropriate to rename the
  203.          AddData method INIT, since you will always want to assign values before
  204.          calling other object methods. We should also add a DONE method which
  205.          will provide a way of disposing of any dynamic data we might incorpo-
  206.          rate at a later stage. The revised object declaration would be as fol-
  207.          lows:
  208.  
  209.                   TYPE
  210.                   AddressOBJ = object
  211.                      Name: string[20]
  212.                      Street: string[30]
  213.                      CityStZip: string[20]
  214.                      {methods ...}
  215.                      procedure Init(Nam,St,Ci,St,Zp:string);
  216.                      procedure PrintLabel;
  217.                      function  Zip: string;
  218.                      procedure Done;
  219.                   end; {object}
  220.  
  221.  
  222.          For now, the DONE procedure will probably be empty, i.e. it performs no
  223.          action. This is referred to as an abstract method. The following code
  224.          fragment shows how to use this revised object:
  225.  
  226.                   with BobsHouse do
  227.                   begin
  228.                      Init('Bobbo','12 Paradise Drive','Dome','TX','77186');
  229.                      Printlabel;
  230.                      Done;
  231.                   end;
  232.  
  233.  
  234.  
  235. Toolkit Basics                                                               3-5
  236.  
  237. --------------------------------------------------------------------------------
  238.  
  239.          Note: there is an even more compelling reason to have INIT and DONE
  240.          methods. One of the most powerful features of OOP is polymorphism,
  241.          which allows you to declare virtual methods (discussed in part 2). In
  242.          general, objects which use virtual methods must have a constructor and
  243.          a destructor, and these are normally called INIT and DONE.
  244.  
  245.  
  246.  
  247.          To recap, the following key points should be remembered:
  248.  
  249.          q     All Toolkit objects end with the characters OBJ.
  250.  
  251.          q     Use the "dot" notation to access object methods.
  252.  
  253.          q     When using the Toolkit always initialize an instance with INIT,
  254.                and dispose of it with DONE.
  255.  
  256.  
  257.  
  258.          Having covered the OOP basics as they relate to the Toolkit, it is
  259.          worthwhile reviewing the message demo program that was discussed in
  260.          chapter 2:
  261.  
  262.  
  263.                  program DemoMessage1;
  264.                  {demms1}
  265.  
  266.                  Uses DOS, CRT,
  267.                       totFAST, totMSG;
  268.  
  269.                  Var  MsgWin : MessageOBJ;
  270.  
  271.                  begin
  272.                     Screen.Clear(white,'░'); {paint the screen}
  273.                     with MsgWin do
  274.                     begin
  275.                        Init(1,' Message ');
  276.                        AddLine('');
  277.                        AddLine('The message unit provides a');
  278.                        AddLine('very easy way of displaying');
  279.                        AddLine('pop-up messages in a move-');
  280.                        AddLine('able window.');
  281.                        AddLine('');
  282.                        Show;
  283.                        Done;
  284.                     end;
  285.                  end.
  286.  
  287.  
  288.          Hopefully, the statements make more sense now!
  289.  
  290.  
  291.  
  292. 3-6                                                                 User's Guide
  293.  
  294. --------------------------------------------------------------------------------
  295.  
  296.          "So what?" and "Why bother?" you may ask. It is not appropriate, at
  297.          this stage, to explore the advantages of encapsulation. Just use the
  298.          Toolkit a little, and you will see what can be done with OOP! We have
  299.          covered everything you need to know about OOP to use the  Toolkit (and
  300.          then some), but as a programmer it is always good to explore "under the
  301.          hood". A great way to learn practical insights into OOP is to explore
  302.          the Toolkit source code. When you are ready to extend the Toolkit to
  303.          meet your specific needs, refer to Part 2. Also, read some of the OOP
  304.          literature in magazines and books - OOP is here to stay.
  305.  
  306.          Meanwhile, be happy with the "how" for now. The "why" will become all
  307.          too clear in time.
  308.  
  309.  
  310.  
  311. Building the Toolkit TPUs
  312.  
  313.          The file TOTBUILD.PAS is an "empty" file which USES all the Toolkit
  314.          units. Its sole purpose is to provide an easy way of re-compiling the
  315.          Toolkit units.
  316.  
  317.          If you ever need to rebuild all the TPUs, load the TOTBUILD.PAS file
  318.          from the C:\TURBO\TOT directory (or wherever you installed the source
  319.          files), and select Compile Build. If the program does not successfully
  320.          compile, refer to the problems section at the end of chapter 2.
  321.  
  322.  
  323.  
  324. Compiler Directives
  325.  
  326.          Every unit in the Toolkit has an include statement to include the file
  327.          TOTFLAGS.INC. This file is designed to specify all the common compiler
  328.          directives that you want to apply to every unit in your program.
  329.  
  330.          The compiler directives added to your main program apply only to that
  331.          module and not to any of the units used by the program. So if you
  332.          wanted to ensure that a specific compiler directive is operative in
  333.          every unit, you would have to edit every unit source code file and add
  334.          the appropriate directive. (Yes, you could add them to the IDE options
  335.          menu, but if you work on multiple projects, you would have to keep
  336.          swapping the directives in and out as necessary.)
  337.  
  338.          Whenever you develop a program using the Toolkit, you should add an
  339.          include directive to your main program and any other units you develop,
  340.          as follows:
  341.  
  342.                   {$I TOTFLAGS.INC}
  343.  
  344.  
  345.          Any compiler directives you set in the file TOTFLAGS.INC file will then
  346.          affect your code and the Toolkit code.
  347.  
  348.  
  349.  
  350. Toolkit Basics                                                               3-7
  351.  
  352. --------------------------------------------------------------------------------
  353.  
  354.          The TOTFLAGS.INC file contains a host of standard Turbo Pascal compiler
  355.          directives which are controlled with four special compiler directives:
  356.          FINAL, OVERLAY, FLOAT and FLOATEM. These four compiler directives are
  357.          located at the top of the file in an enabled or disabled state. For
  358.          example, in the disabled state the $DEFINE directive is broken up with
  359.          spaces, e.g.
  360.  
  361.                     { $ DEFINE OVERLAY}
  362.  
  363.  
  364.          To activate a directive simply remove the leading spaces, e.g.
  365.  
  366.                     {$DEFINE OVERLAY}
  367.  
  368.  
  369.          To disable the directive again just put the spaces back!
  370.  
  371.          The four compiler directives have a significant impact on the final
  372.          program code, and are discussed in detail below.
  373.  
  374.  
  375.  
  376. FINAL
  377.  
  378.          During program development it is a good idea to switch on range check-
  379.          ing and stack checking, etc. These directives keep you honest and
  380.          reduce the likelihood of a machine "hang" or lock-up. For example, if
  381.          you try to assign a value of 300 to a byte, the compiler will identify
  382.          the problem before it goes too far. The bad news is that programs
  383.          compiled in the check everything state tend to be slower and larger
  384.          than their carefree brethren. So, once you have debugged and tested
  385.          your program and you are confident that the checking is no longer nec-
  386.          essary, you should switch off the appropriate directives.
  387.  
  388.          The FINAL compiler directive is designed to simplify this task. During
  389.          program development, you should disable the FINAL compiler directive,
  390.          and then enable it when you are ready to build and distribute your
  391.          production program.
  392.  
  393.          At the time of printing, the following compiler directives are
  394.          influenced by the FINAL directive:
  395.  
  396.          FINAL enabled        {$S-} no stack checking
  397.                               {$R-} no range checking
  398.                               {SD-} no debug information
  399.                               {$L-} no local symbols
  400.  
  401.          FINAL disabled       {$S+} stack checking on
  402.                               {$R+} range checking on
  403.                               {SD+} debug information on
  404.                               {$L+} local symbols on
  405.  
  406.  
  407.  
  408. 3-8                                                                 User's Guide
  409.  
  410. --------------------------------------------------------------------------------
  411.  
  412.          When FINAL is disabled, another Toolkit directive is defined: CHECK.
  413.          When CHECK is enabled, the Toolkit uses some additional code to check
  414.          parameters passed to methods. For example, in the WINOBJ method
  415.          SetSize, a check is made to ensure the window coordinates fit on the
  416.          screen. When the FINAL directive is enabled, CHECK is automatically
  417.          disabled to reduce program size. If a program runs fine until you set
  418.          the FINAL directive, check the parameters you are using in the problem
  419.          area of the code.
  420.  
  421.          Remember that if you want to use the IDE or stand alone debugger on
  422.          your application, you must disable the FINAL directive.
  423.  
  424.  
  425.  
  426. OVERLAY
  427.  
  428.          Any of the Toolkit units can be overlaid.
  429.  
  430.          Turbo Pascal requires that all overlaid units include a {$O+} compiler
  431.          directive, and that all methods, procedures and functions use the far
  432.          call method, i.e. they are compiled in the {$F+} state. By activating
  433.          the {$DEFINE OVERLAY} statement in the TOTFLAGS.INC file, all the Tool-
  434.          kit units will be compiled in the {$F+,O+} state.
  435.  
  436.          It is important to note that Turbo Pascal imposes an important restric-
  437.          tion on an overlaid unit - there must be no initialization statements
  438.          at the end of the unit. Every Toolkit unit has an initialization
  439.          procedure, and this procedure name is consistently the unit name minus
  440.          the TOT prefix plus the characters "INIT". For example, the initializa-
  441.          tion procedures for the TOTFAST and TOTSYS units are FASTINIT and SYSI-
  442.          NIT, respectively.
  443.  
  444.          IMPORTANT: When the OVERLAY compiler directive is activated, you must
  445.          call each overlay unit's INIT procedure as the first statements in your
  446.          main program.
  447.  
  448.          Listed below is a small demo program, DEMOV1.PAS, which is an overlaid
  449.          version of the DEMMS1.PAS file reviewed earlier.
  450.  
  451.               program DemoOverlay1;
  452.               {demov1.pas - make sure the OVERLAY compiler directive
  453.               is enabled in the TOTFLAGS.INC file before compiling}
  454.  
  455.               {$I TOTFLAGS.INC}
  456.  
  457.               Uses OVERLAY, DOS, CRT,
  458.                    totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
  459.  
  460.               {$O totSYS}
  461.               {$O TOTLOOK}
  462.               {$O totINPUT}
  463.               {$O totFAST}
  464.  
  465.  
  466.  
  467. Toolkit Basics                                                               3-9
  468.  
  469. --------------------------------------------------------------------------------
  470.  
  471.               {$O totWIN}
  472.               {$O totIO1}
  473.               {$O totMSG}
  474.  
  475.               Var
  476.                  MsgWin : MessageOBJ;
  477.  
  478.               begin
  479.                  OvrInit('DEMOV1.OVR');{initialize the overlay}
  480.                  OvrInitEMS;
  481.                  SYSInit;          {initialize the Toolkit units}
  482.                  LOOKInit;
  483.                  INPUTInit;
  484.                  FASTInit;
  485.                  WINInit;
  486.                  IO1Init;
  487.                  MSGInit;
  488.                  Screen.Clear(white,'░'); {paint the screen}
  489.                  with MsgWin do
  490.                  begin
  491.                     Init(1,' Message ');
  492.                     AddLine('');
  493.                     AddLine('The message unit provides a');
  494.                     AddLine('very easy way of displaying');
  495.                     AddLine('pop-up messages in a move-');
  496.                     AddLine('able window.');
  497.                     AddLine('');
  498.                     Show;
  499.                     Done;
  500.                  end;
  501.               end.
  502.  
  503.  
  504.          Note that all the units used directly or indirectly by the totMSG unit
  505.          are used and the appropriate INIT procedure is called. The order of the
  506.          INIT procedure calls is important. If you are using any Toolkit units
  507.          which write to the screen and poll the keyboard, then you should, as a
  508.          minimum, call the following procedures in the specified order:
  509.  
  510.                SYSInit;
  511.                LOOKInit;
  512.                INPUTInit;
  513.                FASTInit;
  514.                WINInit;
  515.  
  516.          If you execute the DEMOV1 program you will notice it is unbearably
  517.          slow! As the demo ably illustrates, you should not overlay the primary
  518.          Toolkit units totSYS, totINPUT, and totFAST. Routines from these units
  519.          are called very frequently, and placing them in overlays will really
  520.          slooooow your application down. DEMOV2.PAS, listed below, is a more
  521.          practical overlay solution:
  522.  
  523.  
  524. 3-10                                                                User's Guide
  525.  
  526. --------------------------------------------------------------------------------
  527.  
  528.                program DemoOverlay2;
  529.                {demov2 - make sure the OVERLAY compiler directive
  530.                 is enabled in the TOTFLAGS.INC file before compiling}
  531.  
  532.                {$I TOTFLAGS.INC}
  533.  
  534.                Uses OVERLAY, DOS, CRT,
  535.                     totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
  536.  
  537.                {$O totWIN}
  538.                {$O totIO1}
  539.                {$O totMSG}
  540.  
  541.                Var
  542.                   MsgWin : MessageOBJ;
  543.  
  544.                begin
  545.                   OvrInit('DEMOV2.OVR');{initialize the overlay}
  546.                   OvrInitEMS;
  547.                   SYSInit;         {initialize the Toolkit units}
  548.                   LOOKInit;
  549.                   INPUTInit;
  550.                   FASTInit;
  551.                   WINInit;
  552.                   IO1Init;
  553.                   MSGInit;
  554.                   Screen.Clear(white,'░'); {paint the screen}
  555.                   with MsgWin do
  556.                   begin
  557.                      Init(1,' Message ');
  558.                      AddLine('');
  559.                      AddLine('The message unit provides a');
  560.                      AddLine('very easy way of displaying');
  561.                      AddLine('pop-up messages in a move-');
  562.                      AddLine('able window.');
  563.                      AddLine('');
  564.                      Show;
  565.                      Done;
  566.                   end;
  567.                end.
  568.  
  569.  
  570.          In this example, only the three units totWIN, totIO1 and totMSG are
  571.          overlaid, and performance is almost as good as a non-overlaid version.
  572.          It is important to note the OVERLAY compiler directive disables all the
  573.          Toolkit initialization procedures regardless of whether each unit is
  574.          actually overlaid or not. For this reason, the second demo still ini-
  575.          tializes all of the Toolkit units. Refer to the Flash cards for a list
  576.          of unit dependencies, i.e. which files to INIT when you use a unit.
  577.  
  578.  
  579.  
  580. Toolkit Basics                                                              3-11
  581.  
  582. --------------------------------------------------------------------------------
  583.  
  584.          Finally, if you are new to overlays, don't forget that the overlay file
  585.          (.OVR) can be combined back into the EXE file using the following DOS
  586.          command:
  587.  
  588.                   COPY/B progname.EXE + progname.OVR
  589.  
  590.          The OvrInit procedure must initialize the overlay file from the EXE
  591.          file, and this can be achieved with the following command:
  592.  
  593.                   OvrInit(ParamStr(0));
  594.  
  595.  
  596.  
  597. FLOAT
  598.  
  599.          Turbo Pascal and the Toolkit support extended reals. By default, Turbo
  600.          Pascal uses six byte reals, but using compiler directives high preci-
  601.          sion Single, Double, Extended and Comp reals can be used.
  602.  
  603.          If you want to use the higher precision reals, activate the FLOAT com-
  604.          piler directive. The Toolkit will automatically set the necessary Turbo
  605.          Pascal compiler directives. When FLOAT is enabled, the Toolkit supports
  606.          all real types. When FLOAT is disabled, all the real types are type-
  607.          cast to the base REAL type. In other words, the types SINGLE, DOUBLE,
  608.          EXTENDED and COMP appear to the compiler as plain old REAL. This
  609.          type-casting is performed in the small totREAL unit.
  610.  
  611.          If the software compiled in the FLOAT state is to be run on a computer
  612.          without a math co-processor, the FLOATEM compiler directive (discussed
  613.          next) must also be enabled. Note that the totSYS unit provides an
  614.          object for checking the presence of a math co-processor.
  615.  
  616.  
  617.  
  618. FLOATEM
  619.  
  620.          Turbo Pascal is capable of emulating an 8087 math co-processor if the
  621.          PC does not have one installed. Enable the FLOAT and FLOATEM (short for
  622.          float emulation) directives if you want to use high precision reals on
  623.          PCs with no math co-processor.
  624.  
  625.          Note that the use of FLOATEM will increase the size of the program,
  626.          because Turbo Pascal links in the 8087 emulation code. Only use this
  627.          directive when necessary.
  628.  
  629.  
  630.  
  631. Using Standard Objects
  632.  
  633.          Virtually all programs built with the Toolkit perform some basic tasks
  634.          such as writing to the screen and polling the keyboard. The Toolkit
  635.          provides a number of object instances (i.e. object variables) that are
  636.          automatically initialized when you use the related unit. For example,
  637.          the totFAST unit includes an instance of a ScreenOBJ called SCREEN.
  638.  
  639.  
  640.  
  641. 3-12                                                                User's Guide
  642.  
  643. --------------------------------------------------------------------------------
  644.  
  645.          Listed below are each of the instances which provide the basic program-
  646.          ming facilities:
  647.  
  648.          SCREEN           The SCREEN instance is of type ScreenOBJ and is
  649.                           declared in the totFAST unit. SCREEN should be used
  650.                           for all writing to the screen. For more details, refer
  651.                           to chapter 5: Writing to the Screen.
  652.  
  653.          MOUSE            The MOUSE instance is of type MouseOBJ and is declared
  654.                           in the totINPUT unit. The primary purpose of MOUSE is
  655.                           to provide a convenient way of controlling the mouse
  656.                           cursor. The methods HIDE and SHOW control whether the
  657.                           mouse is visible, and the method function VISIBLE
  658.                           returns true if the mouse is on display. Note that the
  659.                           Toolkit automatically hides the mouse while screen
  660.                           writing occurs. For further information, refer to
  661.                           chapter 6: Keyboard and Mouse Input.
  662.  
  663.          KEY              The KEY instance is of type KeyOBJ and is also
  664.                           declared in the totINPUT unit. This instance provides
  665.                           all the methods for accessing the user's keyboard and
  666.                           mouse input. The main method is Getkey, which waits
  667.                           for the user to press a key or click a mouse button.
  668.                           More details are described in chapter 6.
  669.  
  670.          MONITOR^         The MONITOR instance is a pointer to a DisplayOBJ and
  671.                           is declared in the totSYS unit. MONITOR^ can be used
  672.                           to ascertain the width and depth of the display, as
  673.                           well as set condensed mode display on or off. Refer to
  674.                           chapter 4: Determining and Controlling Hardware for
  675.                           more information.
  676.  
  677.  
  678.  
  679. Controlling a Program's Look & Feel
  680.  
  681.          As well as the global instances described in the last section, the
  682.          Toolkit includes a variety of object instances which can be used to
  683.          control the overall look and feel of a program. For example, the
  684.          SCROLLTOT^ instance controls the way that scroll bars are drawn.
  685.  
  686.          To change the look of your application, all you have to do is modify
  687.          the appropriate instance. To save data space, all these instances are
  688.          dynamically created on the heap and must be referenced with the pointer
  689.          symbol (^). For example, to call the SCROLLTOT method SetScrollChars,
  690.          you would use the following syntax:
  691.  
  692.                   ScrollTOT^.SetScrollChars(....);
  693.  
  694.  
  695.  
  696. Toolkit Basics                                                              3-13
  697.  
  698. --------------------------------------------------------------------------------
  699.  
  700.          Listed below is a full description of each global instance which con-
  701.          trols the look and feel of your application. All these instances are
  702.          automatically initialized by the Toolkit, and a set of more than
  703.          adequate defaults (!) are assigned.
  704.  
  705.          In addition to these instances, there is a byte variable LPTPORT, in
  706.          the totMISC unit, which is used to indicate the default printer port
  707.          (set to 0 for LPT1, 1 for LPT2, etc.).
  708.  
  709.  
  710.  
  711.             Note: the Toolkit uses a single byte to indicate the display
  712.             attribute or color - that is, the foreground and background bytes
  713.             combined into a single attribute byte. The totFAST unit provides
  714.             three functions to help you manipulate color attributes. The CATTR
  715.             function is passed a foreground and background color and returns a
  716.             single combined attribute byte. The FATTR function is passed an
  717.             attribute byte and returns the foreground color component. The
  718.             BATTR function is passed an attribute byte and returns the back-
  719.             ground color component.
  720.  
  721.             For example, the expression CAttr(white,blue); returns the value of
  722.             31, and the expression FAttr(31) returns 15, which is white.
  723.  
  724.             In all, there are 256 different foreground and background color
  725.             combinations; the Flash Cards include a chart which details them
  726.             all.
  727.  
  728.             When assigning colors, be sure to check the Monitor^.ColorOn bool-
  729.             ean function method to determine whether the system is using a
  730.             color or a monochrome device.
  731.  
  732.  
  733.  
  734.  
  735. LookTOT
  736.  
  737.          The unit totLOOK is designed specifically to provide you with an easy
  738.          way to change the overall cosmetic appearance of your programs. The
  739.          unit includes a single instance LookTOT which is a pointer to a LookOBJ
  740.          object. LookTOT controls the window, menu and list default display
  741.          characteristics. If you want to change the overall color and style of
  742.          your program, change the LookTOT settings, and these will be inherited
  743.          by the window, menu and list objects.
  744.  
  745.          Listed below are the methods for setting the various defaults:
  746.  
  747.  
  748.          SetWindow(Border,Body,Icons,Title: byte);
  749.  
  750.  
  751.  
  752. 3-14                                                                User's Guide
  753.  
  754. --------------------------------------------------------------------------------
  755.  
  756.          This method sets the display attributes for the window border (where
  757.          the box is drawn), the central part of the window, the close and zoom
  758.          characters, and the window title. The defaults depend on whether the
  759.          host PC is using a color or a monchrome display.
  760.  
  761.  
  762.          SetWinKeys(Move,Stretch,Zoom: word);
  763.  
  764.          This method sets the values of the keys which will invoke the window
  765.          move, stretch and zoom commands. The defaults are [KEYCAP], [KEYCAP],
  766.          and [KEYCAP].
  767.  
  768.  
  769.          SetListKeys(Endkey,Esc,Toggle,Tag,UnTag: word);
  770.  
  771.          SetListKeys sets the values of the keys which are used with a ListOBJ
  772.          instance. The EndKey and Esc keys are used to remove the list window,
  773.          and the defaults are [KEYCAP] and [KEYCAP]. The Toggle key is used to
  774.          select or deselect individual items in the list and the default is the
  775.          [KEYCAP]. The Tag and UnTag keys are used to globally select or dese-
  776.          lect all items in the list, and the defaults are [KEYCAP] and [KEYCAP].
  777.  
  778.  
  779.          SetListChars(LeftChar,RightChar,ToggleOnChar,ToggleOffChar:char);
  780.  
  781.          Sets the display characters which are used to emphasize the highlighted
  782.          topic in a list, as well as the characters used to indicate whether an
  783.          item in a list is selected or not.
  784.  
  785.  
  786.          SetMenu(Bor,Tit,Icon,HiHot,HiNorm,LoHot,LoNorm,Off:byte)
  787.  
  788.          Sets the display characteristics of the pop-up and pull-down menus. The
  789.          method is passed eight (count 'em) parameters to give you complete
  790.          control of all the menu display colors. The first three parameters set
  791.          the attribute of the menu window border, title and close icon. The next
  792.          four parameters specify the attributes for the highlighted and normal
  793.          menu items. (Each menu item may be displayed in two colors to emphasize
  794.          a specific letter or word.) The last parameter is the attribute for
  795.          non-selectable (i.e. turned-off) menu items.
  796.  
  797.  
  798.          SetDefaults;
  799.  
  800.          Call this method with no parameters if you want to reset all the Look-
  801.          TOT settings to the Toolkit defaults.
  802.  
  803.  
  804.  
  805. Toolkit Basics                                                              3-15
  806.  
  807. --------------------------------------------------------------------------------
  808.  
  809. ShadowTOT
  810.  
  811.          ShadowTOT is a pointer to an instance of type ShadowOBJ, and is
  812.          declared in the totFAST unit. ShadowTOT is used to control the size,
  813.          color and perspective of the shadows used by pop-up windows, lists,
  814.          menus and the like.
  815.  
  816.          An enumerated type ShadowPosition is used to describe the shadow per-
  817.          spective, and the elements are defined as UpLeft, UpRight, DownLeft,
  818.          and DownRight. Shadows can be set as see-through or solid characters,
  819.          the choice is yours! You can even set how wide and deep the shadow will
  820.          be.
  821.  
  822.          The following methods are used to set the shadow characteristics:
  823.  
  824.  
  825.          SetShadowStyle(ShadP:ShadowPosition;ShadA:byte;ShadC:char);
  826.  
  827.          The first parameter indicates the direction of the shadow using a mem-
  828.          ber of the ShadowPosition enumerated type. The second parameter is the
  829.          display attribute of the shadow, and the third is the character used to
  830.          draw the shadow. If a space (' ') is passed, the shadow will be see-
  831.          through, otherwise the shadow will be drawn using the specified charac-
  832.          ter.
  833.  
  834.  
  835.          SetShadowSize(ShadW,ShadD:byte);
  836.  
  837.          This method controls the size of the shadow. Pass the number of charac-
  838.          ters wide and deep that you want the shadow to be. If the width and
  839.          depth are set to zero, no shadows will be drawn.
  840.  
  841.  
  842.          SetDefaults;
  843.  
  844.          Call this method with no parameters if you want to reset all the Shad-
  845.          owTOT settings to the Toolkit defaults.
  846.  
  847.  
  848.          The following program, DEMSH1.PAS, illustrates how to change the shadow
  849.          settings, and figure 3.1 shows the resultant output when the program is
  850.          executed.
  851.  
  852.          program DemoShadow1;
  853.          {demsh1}
  854.  
  855.          Uses DOS, CRT,
  856.               totFAST;
  857.  
  858.          begin
  859.             with Screen do
  860.             begin
  861.                Clear(white,'░'); {paint the screen}
  862.                ShadFillBox(3,3,20,8,31,1);
  863.                ShadowTOT^.SetShadowStyle(Upleft,lightgray,' ');
  864.  
  865.  
  866. 3-16                                                                User's Guide
  867.  
  868. --------------------------------------------------------------------------------
  869.  
  870.                ShadFillBox(3,12,20,19,47,2);
  871.                ShadowTOT^.SetShadowStyle(Downleft,lightblue,' ');
  872.                ShadowTOT^.SetShadowSize(4,1);
  873.                ShadFillBox(35,2,70,10,94,3);
  874.                ShadowTOT^.SetShadowStyle(DownLeft,white,'!');
  875.                ShadFillBox(40,13,60,18,15,4);
  876.                ShadowTOT^.SetDefaults;
  877.                ShadFillBox(5,21,75,23,78,5);
  878.             end; {with}
  879.          end.
  880.  
  881.  
  882.  
  883.  
  884. Figure 3.1                                                              [SCREEN]
  885. The Shadow Demo
  886. Program
  887.  
  888.  
  889.  
  890. ScrollTOT
  891.  
  892.          ScrollTOT is a pointer to an instance of type ScrollOBJ, and is
  893.          declared in the totFAST unit. ScrollTOT is used to control the charac-
  894.          ters used to build the scroll bars displayed in scrolling windows.
  895.  
  896.          There are basically four different characters used to create a scroll
  897.          bar. There is the directional arrow at each end, the background charac-
  898.          ter, and the elevator (or slider) character. These characters are con-
  899.          trolled with the following two methods:
  900.  
  901.  
  902.          SetScrollChars(U,D,L,R,E,B:char);
  903.  
  904.          These six parameters represent the up and down directional arrows on
  905.          vertical scroll bars, the left and right directional arrows on horizon-
  906.          tal scroll bars, the elevator character and the background character.
  907.  
  908.  
  909.          SetDefaults;
  910.  
  911.          Call this method with no parameters if you want to reset all the
  912.          ScrollTOT settings to the Toolkit defaults.
  913.  
  914.  
  915.  
  916.          ScrollTOT does not affect the display attributes of the scroll bars.
  917.          The window border attribute is normally used.
  918.  
  919.          SCREEN provides two methods for writing scroll bars anywhere on the
  920.          display: WriteHScrollBar, WriteVScrollBar. Refer to Chapter 5 for fur-
  921.          ther information.
  922.  
  923.  
  924.  
  925. Toolkit Basics                                                              3-17
  926.  
  927. --------------------------------------------------------------------------------
  928.  
  929. IOTOT
  930.  
  931.          Using consistent color schemes is particularly important during full-
  932.          screen input. The totIO1 unit includes IOTOT which is designed to con-
  933.          trol all the IO display attributes. IOTOT is a pointer to an object of
  934.          type InputOBJ. The uses of IOTOT are discussed in detail in chapter 11.
  935.  
  936.  
  937.  
  938. FmtNumberTOT
  939.  
  940.          The totIO2 unit provides routines for the input of REAL and INTEGER
  941.          values. These values can be optionally formatted when the user moves to
  942.          the next field, i.e. when the user is editing, the number is unfor-
  943.          matted, but when the user exits the field, the number can be formatted
  944.          in a variety of styles. For example, the number 123456.78 might be
  945.          formatted as $123,456.78.
  946.  
  947.          The totIO2 unit includes FmtNumberTOT, a pointer to an object instance
  948.          of type FmtNumberOBJ. This instance defines the default formatting that
  949.          will be applied to real and integer fields during full-screen input.
  950.          Any of the format defaults can be overridden for individual fields.
  951.          Field formatting is discussed in detail in chapter 11: Controlling User
  952.          Input.
  953.  
  954.  
  955.  
  956. DateTOT
  957.  
  958.          The totDATE unit provides functions for manipulating and converting
  959.          Julian and Gregorian dates. A number of default values, e.g. the char-
  960.          acter used to separate the month from the day and the year (like '  /
  961.          /  '), are defined in DateTOT, a pointer to an object instance of type
  962.          DateOBJ. These defaults are used in both the totDATE and totIO2 units.
  963.          Refer to chapter 13: Managing Dates for further details.
  964.  
  965.  
  966.  
  967. AlphabetTOT
  968.  
  969.          The totINPUT unit includes the object AlphabetOBJ for managing upper-
  970.          and lower-case characters, and the global instance AlphabetTOT is a
  971.          pointer to an AlphabetOBJ object.
  972.  
  973.          AlphabetTOT controls how the Toolkit determines/changes the case of
  974.          alpha-characters. It is designed for international Toolkit users who
  975.          want to use a non-English alphabet. If you are writing "English-
  976.          speaking" programs, you do not need to tamper with this object.
  977.  
  978.          The object contains a list of all valid upper-case letters, lower-case
  979.          letters and punctuation characters. The totLOOK unit includes the type
  980.          declaration CharSet, which is equal to a set of char. Some methods are
  981.  
  982.  
  983.  
  984. 3-18                                                                User's Guide
  985.  
  986. --------------------------------------------------------------------------------
  987.  
  988.          passed a parameter of type CharSet. You may specify multiple characters
  989.          and/or ranges of characters, provided that they are enclosed in square
  990.          brackets []. For example, the following expressions are valid CharSets:
  991.  
  992.                     ['a','b','f'..'z']
  993.                     ['A'..'Z',#129..#148]
  994.                     ['a'..'z']
  995.                     [',','.']
  996.  
  997.          AlphabetTOT methods can be called using the syntax AlphabetTOT^.method,
  998.          and the following methods are supported:
  999.  
  1000.  
  1001.          SetUpper(Letters:CharSet);
  1002.  
  1003.          Defines which characters comprise the upper-case alphabet. The method
  1004.          is passed one parameter of type CharSet, e.g. SetUpper(['A'..'Z']);.
  1005.  
  1006.  
  1007.          SetLower(Letters:CharSet);
  1008.  
  1009.          Defines which characters comprise the lower-case alphabet. The method
  1010.          is passed one parameter of type CharSet, e.g. SetLower(['a'..'z']);.
  1011.  
  1012.  
  1013.          SetPunctuation(Letters:CharSet);
  1014.  
  1015.          Defines which characters are used in normal punctuation. The method is
  1016.          passed one parameter of type CharSet, e.g. SetPunctua-
  1017.          tion([',',';','.',':',' ']);.
  1018.  
  1019.  
  1020.          IsUpper(K:word): boolean;
  1021.  
  1022.          This function method is passed one parameter, representing the ordinal
  1023.          value of a character, and returns true if the character is listed in
  1024.          the upper-case alphabet, e.g. IsUpper(ord('A'));.
  1025.  
  1026.  
  1027.          IsLower(K:word): boolean;
  1028.  
  1029.          This function method is passed one parameter, representing the ordinal
  1030.          value of a character, and returns true if the character is listed in
  1031.          the lower-case alphabet, e.g. IsLower(107);.
  1032.  
  1033.  
  1034.          IsLetter(K:word): boolean;
  1035.  
  1036.          This function method is passed one parameter, representing the ordinal
  1037.          value of a character, and returns true if the character is listed in
  1038.          either the upper- or lower-case alphabet.
  1039.  
  1040.  
  1041.          IsPunctuation(K:word): boolean;
  1042.  
  1043.  
  1044.  
  1045. Toolkit Basics                                                              3-19
  1046.  
  1047. --------------------------------------------------------------------------------
  1048.  
  1049.          This function method is passed one parameter, representing the ordinal
  1050.          value of a character, and returns true if the character is listed as a
  1051.          punctuation character.
  1052.  
  1053.  
  1054.  
  1055.  
  1056.          On occasion, the Toolkit needs to convert the case of alpha characters.
  1057.          To accommodate international users, the Toolkit uses AlphabetTOT to
  1058.          convert character case, rather than rely on the English-specific rou-
  1059.          tines provided with Turbo Pascal. The Toolkit calls the following two
  1060.          methods to convert character case:
  1061.  
  1062.  
  1063.          GetUpCase(Ch:char):char;
  1064.  
  1065.          This method is passed a character, and returns the upper-case equiva-
  1066.          lent of the character.
  1067.  
  1068.  
  1069.          GetLoCase(Ch:char):char;
  1070.  
  1071.          This method is passed a character, and returns the lower-case equiva-
  1072.          lent of the character.
  1073.  
  1074.  
  1075.          You can control precisely how characters are converted by creating your
  1076.          own conversion routines. All you have to do is create two functions
  1077.          following some specific rules, and then call the methods Alphabet-
  1078.          TOT^.AssignUpCaseFunc and AlphabetTOT^.AssignLoCaseFunc to instruct the
  1079.          Toolkit to use your functions.
  1080.  
  1081.          For a function to be eligible as a character case converter it must
  1082.          adhere to the following three rules:
  1083.  
  1084.          Rule 1     The function must be declared as a FAR function. This can be
  1085.                     achieved by preceding the function with a {$F+} compiler
  1086.                     directive, and following the function with a {$F-} direc-
  1087.                     tive. Alternatively, Turbo 6 users can use the new keyword
  1088.                     FAR following the procedure statement.
  1089.  
  1090.          Rule 2     The function must be declared with one passed parameter of
  1091.                     type char, and it must return a char.
  1092.  
  1093.          Rule 3     The function must be at the root level, i.e. the function
  1094.                     cannot be nested within another procedure or function.
  1095.  
  1096.          The following function declaration follows these rules:
  1097.  
  1098.                   {$F+}
  1099.                   function MyUpConverter(Ch:char):char;
  1100.                   .....{statements}
  1101.                   end;
  1102.                   {$F-}
  1103.  
  1104.  
  1105.  
  1106. 3-20                                                                User's Guide
  1107.  
  1108. --------------------------------------------------------------------------------
  1109.  
  1110.          Internally, these functions should check the value of the passed char-
  1111.          acter, and return the character converted to the appropriate case. If
  1112.          the character is not suited to conversion, e.g. '1', simply return the
  1113.          character that was passed. Once you have created two functions (one for
  1114.          upper-case conversion and one for lower-case conversion), you should
  1115.          call the following assignment methods to instruct AlphabetTOT to use
  1116.          your routines:
  1117.  
  1118.  
  1119.          AssignUpCaseFunc(Func:CaseFunc);
  1120.  
  1121.          This method is passed the name of the function used to convert charac-
  1122.          ters to upper case. The procedure must adhere to the rules outlined
  1123.          above.
  1124.  
  1125.  
  1126.          AssignLoCaseFunc(Func:CaseFunc);
  1127.  
  1128.          This method is passed the name of the function used to convert charac-
  1129.          ters to lower case. The procedure must adhere to the rules outlined
  1130.          above.
  1131.  
  1132.  
  1133.          In summary, AlphabetTOT provides you with complete control over how the
  1134.          Toolkit determines and changes the case of alpha characters.
  1135.  
  1136.  
  1137.  
  1138. Program Size
  1139.  
  1140.          A constant battle during the development of the Toolkit was to minimize
  1141.          the size of programs developed with the Toolkit. A valid criticism of
  1142.          OOP is that it tends to swell the final program size, which makes it a
  1143.          subject of concern to most developers (that's you folks).
  1144.  
  1145.          With a hierarchical object organization even small applications tend to
  1146.          attract a high code overhead. However, the more features of the Toolkit
  1147.          you use, the more efficient your program will be. For example, listed
  1148.          below are the EXE file sizes of three of the demo programs:
  1149.  
  1150.                 DemFM8           114k
  1151.                 DemDR1           92k
  1152.                 DemMS1           56k
  1153.  
  1154.          The combined file size of the three programs is 262k. However, if these
  1155.          three examples are combined into a single example, the file size is
  1156.          actually 141k. The reason for the reduction is that each of the small
  1157.          programs uses common routines which can be shared in the combined
  1158.          program.
  1159.  
  1160.  
  1161.  
  1162. Toolkit Basics                                                              3-21
  1163.  
  1164. --------------------------------------------------------------------------------
  1165.  
  1166.          In real life, your fledgling program will start out bigger than you
  1167.          expected, but it will grow much less than anticipated as your program
  1168.          expands. Remember that compiler directives have a significant impact on
  1169.          program size, and you should enable the FINAL compiler directive for
  1170.          the production build of your application.
  1171.  
  1172.          If EXE file size is your concern, rather than code size, consider com-
  1173.          pressing the EXE file with a compression utility like PKlite from
  1174.          PKWare, Inc., or LZEXE by Fabrice Bellard.
  1175.