home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-10 | 48.0 KB | 1,059 lines |
- Toolkit Basics
-
-
-
- "No, what I said was 'No new taxis'" Georgio Bush, 1990
-
-
-
-
- An Object Primer
-
- Let's talk cars. We all know that you don't need to be a combustion
- mechanic to drive a car (that's a veeehickle if you're from Texas), but
- most good drivers know a few basic principles about how a car works.
- The same philosophy is true for object oriented programming: you don't
- need to be an OOP guru to use the Toolkit but a little understanding is
- helpful. The modest goal of this section is to explain some of the
- object oriented principles to help you get up and running with the
- Toolkit as soon as possible. Over time, you will gain OOP expertise
- without even trying! If you are already familiar with OOP, skip to the
- next section.
- For now, we will concentrate on those aspects of OOP you will need in
- order to understand how to use the Toolkit. In Part 2: Extending the
- Toolkit, the more advanced concepts of inheritance and extensibility
- are addressed.
-
-
- In plain Pascal, there are types like integer, real, string, etc. and
- you declare variables to be of a specific type. You can even define new
- types. For example, the following declaration defines a new type
- Address:
-
- TYPE
- Address = record
- Name: string[20];
- Street: string[30];
- CityStZip: string[20];
- end;
-
- Having defined the type Address, you can then create variables of this
- type, e.g.
-
- VAR
- BobsHouse: Address;
-
- In most programs, you will write procedures and functions that can
- manipulate the data stored in these variables, e.g.
-
- procedure PrintLabel(Addr: address);
- function Zip(Addr:address): string;
-
-
-
- 3-2 User's Guide
- --------------------------------------------------------------------------------
-
- But most of you know this stuff anyway. Things aren't so very different
- with OOP. The primary difference is that, with OOP, the data and the
- procedures and functions which manipulate the data are combined into a
- single type, called an object. This concept of combining data and
- procedures/functions is referred to as encapsulation. Listed below is a
- way to create an object type called AddressOBJ:
-
- TYPE
- AddressOBJ = object
- Name: string[20];
- Street: string[30];
- CityStZip: string[20];
- {methods ...}
- procedure PrintLabel;
- function Zip: string;
- end; {object}
-
- VAR
- BobsHouse: AddressOBJ;
-
- Notice that the object type declaration is very similar to a record
- declaration, but the keyword object is used instead of record. The
- procedure and function declaration are included in the object declara-
- tion, and are referred to (in OOP nomenclature) as methods. The methods
- are not passed the address record as a parameter, because the procedure
- and functions in an object can directly access the data in the object,
- and so don't need to be passed the data. The "variable" BobsHouse,
- which is of type AddressOBJ, is referred to as an instance - in other
- words, object variables are called instances! All object type declara-
- tions in the Toolkit end with the characters "OBJ".
-
- The individual elements of an object (just like a record) can be
- accessed by using the "dot" notation. For example, to print a label,
- you would use the following statement:
- BobsHouse.PrintLabel
-
-
- You can also use the "with identifier do" shortcut, e.g.
- with BobsHouse do
- begin
- PrintLabel
- .....
- end; {with}
-
-
- In theory, you could also access the data elements using the dot
- method, e.g. BobsHouse.Street := '12 Paradise Drive', but you
- shouldn't! While it is syntactically correct and will compile, this is
- bad practice. A basic precept of encapsulation is that you never access
-
-
- Toolkit Basics 3-3
- --------------------------------------------------------------------------------
-
- the data elements of an instance directly. You should create methods
- within the object to access the object's data. In the above example,
- there is no way to access the data in the object (other than breaking
- the rules) so a data update method would need to be created. Listed
- below is an improved type declaration of the AddressOBJ:
-
- TYPE
- AddressOBJ = object
- Name: string[20];
- Street: string[30];
- CityStZip: string[20];
- {methods ...}
- procedure Adddata(Nam,St,Ci,St,Zp:string);
- procedure PrintLabel;
- function Zip: string;
- end; {object}
-
- The new AddData method would be used to set the values of the Name,
- Street and CityStZip elements. For example, the following two state-
- ments would print the label:
-
- with BobsHouse do
- begin
- AddData('Bobbo','12 Paradise Drive',
- 'Dome','TX','77186');
- Printlabel;
- end;
-
- If you are curious, each method identified in an object must be
- included in the body of the program or unit. For example, later in the
- program there might be the following method definition:
-
- ...
-
- procedure AddressOBJ.Adddata(Nam,St,Ci,St,Zp:string);
- {}
- begin
- Name := copy(Nam,1,20);
- Street := copy(St,1,30);
- ...
- end; {of proc}
-
- ...
-
- Now, back to the main discussion. The advantage of using methods to
- access the object data is that the object user (that's you) does not
- need to know or care about how the data is stored within the object.
- The internal data structure might be modified at some stage to use
-
-
-
- 3-4 User's Guide
- --------------------------------------------------------------------------------
-
- pointers or to store ASCIIZ strings, etc, but the same method AddData
- can still be called in the same way as previously. What Adddata does
- (behind the scenes) may have changed, but your program still compiles
- and runs without modification.
-
- For various reasons, many objects need to be initialized before they
- can be used. For example, some memory may need to be allocated on the
- heap. When you have finished with such an object, the memory will need
- to be disposed of. Just because the procedure in which you declared an
- object instance (i.e. variable) has terminated, it does not necessarily
- mean that the object data has been removed.
- Although not mandatory, a de facto OOP standard is to have two special
- methods for all objects. Namely, INIT and DONE. These special methods
- are used to initialize an object and dispose of an object, respec-
- tively. Throughout the Toolkit, every object has INIT and DONE methods.
- Always call INIT before any other object methods, and always call DONE
- when you have finished with an object. In some instances the INIT
- method may require some parameters.
-
- In our example, the object is useless if no data has been assigned.
- Adopting the new convention, it might be more appropriate to rename the
- AddData method INIT, since you will always want to assign values before
- calling other object methods. We should also add a DONE method which
- will provide a way of disposing of any dynamic data we might incorpo-
- rate at a later stage. The revised object declaration would be as fol-
- lows:
- TYPE
- AddressOBJ = object
- Name: string[20]
- Street: string[30]
- CityStZip: string[20]
- {methods ...}
- procedure Init(Nam,St,Ci,St,Zp:string);
- procedure PrintLabel;
- function Zip: string;
- procedure Done;
- end; {object}
-
-
- For now, the DONE procedure will probably be empty, i.e. it performs no
- action. This is referred to as an abstract method. The following code
- fragment shows how to use this revised object:
- with BobsHouse do
- begin
- Init('Bobbo','12 Paradise Drive','Dome','TX','77186');
- Printlabel;
- Done;
- end;
-
-
-
- Toolkit Basics 3-5
- --------------------------------------------------------------------------------
-
- Note: there is an even more compelling reason to have INIT and DONE
- methods. One of the most powerful features of OOP is polymorphism,
- which allows you to declare virtual methods (discussed in part 2). In
- general, objects which use virtual methods must have a constructor and
- a destructor, and these are normally called INIT and DONE.
-
-
- To recap, the following key points should be remembered:
-
- q All Toolkit objects end with the characters OBJ.
- q Use the "dot" notation to access object methods.
-
- q When using the Toolkit always initialize an instance with INIT,
- and dispose of it with DONE.
-
-
- Having covered the OOP basics as they relate to the Toolkit, it is
- worthwhile reviewing the message demo program that was discussed in
- chapter 2:
-
- program DemoMessage1;
- {demms1}
-
- Uses DOS, CRT,
- totFAST, totMSG;
- Var MsgWin : MessageOBJ;
-
- begin
- Screen.Clear(white,'░'); {paint the screen}
- with MsgWin do
- begin
- Init(1,' Message ');
- AddLine('');
- AddLine('The message unit provides a');
- AddLine('very easy way of displaying');
- AddLine('pop-up messages in a move-');
- AddLine('able window.');
- AddLine('');
- Show;
- Done;
- end;
- end.
-
- Hopefully, the statements make more sense now!
-
-
-
- 3-6 User's Guide
- --------------------------------------------------------------------------------
-
- "So what?" and "Why bother?" you may ask. It is not appropriate, at
- this stage, to explore the advantages of encapsulation. Just use the
- Toolkit a little, and you will see what can be done with OOP! We have
- covered everything you need to know about OOP to use the Toolkit (and
- then some), but as a programmer it is always good to explore "under the
- hood". A great way to learn practical insights into OOP is to explore
- the Toolkit source code. When you are ready to extend the Toolkit to
- meet your specific needs, refer to Part 2. Also, read some of the OOP
- literature in magazines and books - OOP is here to stay.
-
- Meanwhile, be happy with the "how" for now. The "why" will become all
- too clear in time.
-
-
- Building the Toolkit TPUs
-
- The file TOTBUILD.PAS is an "empty" file which USES all the Toolkit
- units. Its sole purpose is to provide an easy way of re-compiling the
- Toolkit units.
- If you ever need to rebuild all the TPUs, load the TOTBUILD.PAS file
- from the C:\TURBO\TOT directory (or wherever you installed the source
- files), and select Compile Build. If the program does not successfully
- compile, refer to the problems section at the end of chapter 2.
-
-
-
- Compiler Directives
- Every unit in the Toolkit has an include statement to include the file
- TOTFLAGS.INC. This file is designed to specify all the common compiler
- directives that you want to apply to every unit in your program.
-
- The compiler directives added to your main program apply only to that
- module and not to any of the units used by the program. So if you
- wanted to ensure that a specific compiler directive is operative in
- every unit, you would have to edit every unit source code file and add
- the appropriate directive. (Yes, you could add them to the IDE options
- menu, but if you work on multiple projects, you would have to keep
- swapping the directives in and out as necessary.)
- Whenever you develop a program using the Toolkit, you should add an
- include directive to your main program and any other units you develop,
- as follows:
-
- {$I TOTFLAGS.INC}
-
- Any compiler directives you set in the file TOTFLAGS.INC file will then
- affect your code and the Toolkit code.
-
-
-
- Toolkit Basics 3-7
- --------------------------------------------------------------------------------
-
- The TOTFLAGS.INC file contains a host of standard Turbo Pascal compiler
- directives which are controlled with four special compiler directives:
- FINAL, OVERLAY, FLOAT and FLOATEM. These four compiler directives are
- located at the top of the file in an enabled or disabled state. For
- example, in the disabled state the $DEFINE directive is broken up with
- spaces, e.g.
-
- { $ DEFINE OVERLAY}
-
- To activate a directive simply remove the leading spaces, e.g.
-
- {$DEFINE OVERLAY}
-
- To disable the directive again just put the spaces back!
-
- The four compiler directives have a significant impact on the final
- program code, and are discussed in detail below.
-
-
- FINAL
- During program development it is a good idea to switch on range check-
- ing and stack checking, etc. These directives keep you honest and
- reduce the likelihood of a machine "hang" or lock-up. For example, if
- you try to assign a value of 300 to a byte, the compiler will identify
- the problem before it goes too far. The bad news is that programs
- compiled in the check everything state tend to be slower and larger
- than their carefree brethren. So, once you have debugged and tested
- your program and you are confident that the checking is no longer nec-
- essary, you should switch off the appropriate directives.
-
- The FINAL compiler directive is designed to simplify this task. During
- program development, you should disable the FINAL compiler directive,
- and then enable it when you are ready to build and distribute your
- production program.
- At the time of printing, the following compiler directives are
- influenced by the FINAL directive:
-
- FINAL enabled {$S-} no stack checking
- {$R-} no range checking
- {SD-} no debug information
- {$L-} no local symbols
- FINAL disabled {$S+} stack checking on
- {$R+} range checking on
- {SD+} debug information on
- {$L+} local symbols on
-
-
-
- 3-8 User's Guide
- --------------------------------------------------------------------------------
-
- When FINAL is disabled, another Toolkit directive is defined: CHECK.
- When CHECK is enabled, the Toolkit uses some additional code to check
- parameters passed to methods. For example, in the WINOBJ method
- SetSize, a check is made to ensure the window coordinates fit on the
- screen. When the FINAL directive is enabled, CHECK is automatically
- disabled to reduce program size. If a program runs fine until you set
- the FINAL directive, check the parameters you are using in the problem
- area of the code.
-
- Remember that if you want to use the IDE or stand alone debugger on
- your application, you must disable the FINAL directive.
-
-
- OVERLAY
-
- Any of the Toolkit units can be overlaid.
- Turbo Pascal requires that all overlaid units include a {$O+} compiler
- directive, and that all methods, procedures and functions use the far
- call method, i.e. they are compiled in the {$F+} state. By activating
- the {$DEFINE OVERLAY} statement in the TOTFLAGS.INC file, all the Tool-
- kit units will be compiled in the {$F+,O+} state.
-
- It is important to note that Turbo Pascal imposes an important restric-
- tion on an overlaid unit - there must be no initialization statements
- at the end of the unit. Every Toolkit unit has an initialization
- procedure, and this procedure name is consistently the unit name minus
- the TOT prefix plus the characters "INIT". For example, the initializa-
- tion procedures for the TOTFAST and TOTSYS units are FASTINIT and SYSI-
- NIT, respectively.
- IMPORTANT: When the OVERLAY compiler directive is activated, you must
- call each overlay unit's INIT procedure as the first statements in your
- main program.
-
- Listed below is a small demo program, DEMOV1.PAS, which is an overlaid
- version of the DEMMS1.PAS file reviewed earlier.
- program DemoOverlay1;
- {demov1.pas - make sure the OVERLAY compiler directive
- is enabled in the TOTFLAGS.INC file before compiling}
-
- {$I TOTFLAGS.INC}
- Uses OVERLAY, DOS, CRT,
- totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
-
- {$O totSYS}
- {$O TOTLOOK}
- {$O totINPUT}
- {$O totFAST}
-
-
-
- Toolkit Basics 3-9
- --------------------------------------------------------------------------------
-
- {$O totWIN}
- {$O totIO1}
- {$O totMSG}
-
- Var
- MsgWin : MessageOBJ;
- begin
- OvrInit('DEMOV1.OVR');{initialize the overlay}
- OvrInitEMS;
- SYSInit; {initialize the Toolkit units}
- LOOKInit;
- INPUTInit;
- FASTInit;
- WINInit;
- IO1Init;
- MSGInit;
- Screen.Clear(white,'░'); {paint the screen}
- with MsgWin do
- begin
- Init(1,' Message ');
- AddLine('');
- AddLine('The message unit provides a');
- AddLine('very easy way of displaying');
- AddLine('pop-up messages in a move-');
- AddLine('able window.');
- AddLine('');
- Show;
- Done;
- end;
- end.
-
-
- Note that all the units used directly or indirectly by the totMSG unit
- are used and the appropriate INIT procedure is called. The order of the
- INIT procedure calls is important. If you are using any Toolkit units
- which write to the screen and poll the keyboard, then you should, as a
- minimum, call the following procedures in the specified order:
- SYSInit;
- LOOKInit;
- INPUTInit;
- FASTInit;
- WINInit;
-
- If you execute the DEMOV1 program you will notice it is unbearably
- slow! As the demo ably illustrates, you should not overlay the primary
- Toolkit units totSYS, totINPUT, and totFAST. Routines from these units
- are called very frequently, and placing them in overlays will really
- slooooow your application down. DEMOV2.PAS, listed below, is a more
- practical overlay solution:
-
-
- 3-10 User's Guide
- --------------------------------------------------------------------------------
-
- program DemoOverlay2;
- {demov2 - make sure the OVERLAY compiler directive
- is enabled in the TOTFLAGS.INC file before compiling}
-
- {$I TOTFLAGS.INC}
- Uses OVERLAY, DOS, CRT,
- totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
-
- {$O totWIN}
- {$O totIO1}
- {$O totMSG}
- Var
- MsgWin : MessageOBJ;
-
- begin
- OvrInit('DEMOV2.OVR');{initialize the overlay}
- OvrInitEMS;
- SYSInit; {initialize the Toolkit units}
- LOOKInit;
- INPUTInit;
- FASTInit;
- WINInit;
- IO1Init;
- MSGInit;
- Screen.Clear(white,'░'); {paint the screen}
- with MsgWin do
- begin
- Init(1,' Message ');
- AddLine('');
- AddLine('The message unit provides a');
- AddLine('very easy way of displaying');
- AddLine('pop-up messages in a move-');
- AddLine('able window.');
- AddLine('');
- Show;
- Done;
- end;
- end.
-
- In this example, only the three units totWIN, totIO1 and totMSG are
- overlaid, and performance is almost as good as a non-overlaid version.
- It is important to note the OVERLAY compiler directive disables all the
- Toolkit initialization procedures regardless of whether each unit is
- actually overlaid or not. For this reason, the second demo still ini-
- tializes all of the Toolkit units. Refer to the Flash cards for a list
- of unit dependencies, i.e. which files to INIT when you use a unit.
-
-
-
- Toolkit Basics 3-11
- --------------------------------------------------------------------------------
-
- Finally, if you are new to overlays, don't forget that the overlay file
- (.OVR) can be combined back into the EXE file using the following DOS
- command:
-
- COPY/B progname.EXE + progname.OVR
- The OvrInit procedure must initialize the overlay file from the EXE
- file, and this can be achieved with the following command:
-
- OvrInit(ParamStr(0));
-
-
- FLOAT
-
- Turbo Pascal and the Toolkit support extended reals. By default, Turbo
- Pascal uses six byte reals, but using compiler directives high preci-
- sion Single, Double, Extended and Comp reals can be used.
- If you want to use the higher precision reals, activate the FLOAT com-
- piler directive. The Toolkit will automatically set the necessary Turbo
- Pascal compiler directives. When FLOAT is enabled, the Toolkit supports
- all real types. When FLOAT is disabled, all the real types are type-
- cast to the base REAL type. In other words, the types SINGLE, DOUBLE,
- EXTENDED and COMP appear to the compiler as plain old REAL. This
- type-casting is performed in the small totREAL unit.
-
- If the software compiled in the FLOAT state is to be run on a computer
- without a math co-processor, the FLOATEM compiler directive (discussed
- next) must also be enabled. Note that the totSYS unit provides an
- object for checking the presence of a math co-processor.
-
-
- FLOATEM
-
- Turbo Pascal is capable of emulating an 8087 math co-processor if the
- PC does not have one installed. Enable the FLOAT and FLOATEM (short for
- float emulation) directives if you want to use high precision reals on
- PCs with no math co-processor.
- Note that the use of FLOATEM will increase the size of the program,
- because Turbo Pascal links in the 8087 emulation code. Only use this
- directive when necessary.
-
-
-
- Using Standard Objects
- Virtually all programs built with the Toolkit perform some basic tasks
- such as writing to the screen and polling the keyboard. The Toolkit
- provides a number of object instances (i.e. object variables) that are
- automatically initialized when you use the related unit. For example,
- the totFAST unit includes an instance of a ScreenOBJ called SCREEN.
-
-
-
- 3-12 User's Guide
- --------------------------------------------------------------------------------
-
- Listed below are each of the instances which provide the basic program-
- ming facilities:
-
- SCREEN The SCREEN instance is of type ScreenOBJ and is
- declared in the totFAST unit. SCREEN should be used
- for all writing to the screen. For more details, refer
- to chapter 5: Writing to the Screen.
- MOUSE The MOUSE instance is of type MouseOBJ and is declared
- in the totINPUT unit. The primary purpose of MOUSE is
- to provide a convenient way of controlling the mouse
- cursor. The methods HIDE and SHOW control whether the
- mouse is visible, and the method function VISIBLE
- returns true if the mouse is on display. Note that the
- Toolkit automatically hides the mouse while screen
- writing occurs. For further information, refer to
- chapter 6: Keyboard and Mouse Input.
-
- KEY The KEY instance is of type KeyOBJ and is also
- declared in the totINPUT unit. This instance provides
- all the methods for accessing the user's keyboard and
- mouse input. The main method is Getkey, which waits
- for the user to press a key or click a mouse button.
- More details are described in chapter 6.
- MONITOR^ The MONITOR instance is a pointer to a DisplayOBJ and
- is declared in the totSYS unit. MONITOR^ can be used
- to ascertain the width and depth of the display, as
- well as set condensed mode display on or off. Refer to
- chapter 4: Determining and Controlling Hardware for
- more information.
-
-
-
- Controlling a Program's Look & Feel
- As well as the global instances described in the last section, the
- Toolkit includes a variety of object instances which can be used to
- control the overall look and feel of a program. For example, the
- SCROLLTOT^ instance controls the way that scroll bars are drawn.
-
- To change the look of your application, all you have to do is modify
- the appropriate instance. To save data space, all these instances are
- dynamically created on the heap and must be referenced with the pointer
- symbol (^). For example, to call the SCROLLTOT method SetScrollChars,
- you would use the following syntax:
- ScrollTOT^.SetScrollChars(....);
-
-
-
- Toolkit Basics 3-13
- --------------------------------------------------------------------------------
-
- Listed below is a full description of each global instance which con-
- trols the look and feel of your application. All these instances are
- automatically initialized by the Toolkit, and a set of more than
- adequate defaults (!) are assigned.
-
- In addition to these instances, there is a byte variable LPTPORT, in
- the totMISC unit, which is used to indicate the default printer port
- (set to 0 for LPT1, 1 for LPT2, etc.).
-
-
- Note: the Toolkit uses a single byte to indicate the display
- attribute or color - that is, the foreground and background bytes
- combined into a single attribute byte. The totFAST unit provides
- three functions to help you manipulate color attributes. The CATTR
- function is passed a foreground and background color and returns a
- single combined attribute byte. The FATTR function is passed an
- attribute byte and returns the foreground color component. The
- BATTR function is passed an attribute byte and returns the back-
- ground color component.
-
- For example, the expression CAttr(white,blue); returns the value of
- 31, and the expression FAttr(31) returns 15, which is white.
-
- In all, there are 256 different foreground and background color
- combinations; the Flash Cards include a chart which details them
- all.
-
- When assigning colors, be sure to check the Monitor^.ColorOn bool-
- ean function method to determine whether the system is using a
- color or a monochrome device.
-
-
-
- LookTOT
-
- The unit totLOOK is designed specifically to provide you with an easy
- way to change the overall cosmetic appearance of your programs. The
- unit includes a single instance LookTOT which is a pointer to a LookOBJ
- object. LookTOT controls the window, menu and list default display
- characteristics. If you want to change the overall color and style of
- your program, change the LookTOT settings, and these will be inherited
- by the window, menu and list objects.
- Listed below are the methods for setting the various defaults:
-
-
- SetWindow(Border,Body,Icons,Title: byte);
-
-
-
- 3-14 User's Guide
- --------------------------------------------------------------------------------
-
- This method sets the display attributes for the window border (where
- the box is drawn), the central part of the window, the close and zoom
- characters, and the window title. The defaults depend on whether the
- host PC is using a color or a monchrome display.
-
-
- SetWinKeys(Move,Stretch,Zoom: word);
- This method sets the values of the keys which will invoke the window
- move, stretch and zoom commands. The defaults are [KEYCAP], [KEYCAP],
- and [KEYCAP].
-
-
- SetListKeys(Endkey,Esc,Toggle,Tag,UnTag: word);
- SetListKeys sets the values of the keys which are used with a ListOBJ
- instance. The EndKey and Esc keys are used to remove the list window,
- and the defaults are [KEYCAP] and [KEYCAP]. The Toggle key is used to
- select or deselect individual items in the list and the default is the
- [KEYCAP]. The Tag and UnTag keys are used to globally select or dese-
- lect all items in the list, and the defaults are [KEYCAP] and [KEYCAP].
-
-
- SetListChars(LeftChar,RightChar,ToggleOnChar,ToggleOffChar:char);
- Sets the display characters which are used to emphasize the highlighted
- topic in a list, as well as the characters used to indicate whether an
- item in a list is selected or not.
-
-
- SetMenu(Bor,Tit,Icon,HiHot,HiNorm,LoHot,LoNorm,Off:byte)
- Sets the display characteristics of the pop-up and pull-down menus. The
- method is passed eight (count 'em) parameters to give you complete
- control of all the menu display colors. The first three parameters set
- the attribute of the menu window border, title and close icon. The next
- four parameters specify the attributes for the highlighted and normal
- menu items. (Each menu item may be displayed in two colors to emphasize
- a specific letter or word.) The last parameter is the attribute for
- non-selectable (i.e. turned-off) menu items.
-
-
- SetDefaults;
- Call this method with no parameters if you want to reset all the Look-
- TOT settings to the Toolkit defaults.
-
-
-
- Toolkit Basics 3-15
- --------------------------------------------------------------------------------
-
- ShadowTOT
-
- ShadowTOT is a pointer to an instance of type ShadowOBJ, and is
- declared in the totFAST unit. ShadowTOT is used to control the size,
- color and perspective of the shadows used by pop-up windows, lists,
- menus and the like.
- An enumerated type ShadowPosition is used to describe the shadow per-
- spective, and the elements are defined as UpLeft, UpRight, DownLeft,
- and DownRight. Shadows can be set as see-through or solid characters,
- the choice is yours! You can even set how wide and deep the shadow will
- be.
-
- The following methods are used to set the shadow characteristics:
-
- SetShadowStyle(ShadP:ShadowPosition;ShadA:byte;ShadC:char);
-
- The first parameter indicates the direction of the shadow using a mem-
- ber of the ShadowPosition enumerated type. The second parameter is the
- display attribute of the shadow, and the third is the character used to
- draw the shadow. If a space (' ') is passed, the shadow will be see-
- through, otherwise the shadow will be drawn using the specified charac-
- ter.
-
- SetShadowSize(ShadW,ShadD:byte);
-
- This method controls the size of the shadow. Pass the number of charac-
- ters wide and deep that you want the shadow to be. If the width and
- depth are set to zero, no shadows will be drawn.
-
- SetDefaults;
-
- Call this method with no parameters if you want to reset all the Shad-
- owTOT settings to the Toolkit defaults.
-
- The following program, DEMSH1.PAS, illustrates how to change the shadow
- settings, and figure 3.1 shows the resultant output when the program is
- executed.
-
- program DemoShadow1;
- {demsh1}
- Uses DOS, CRT,
- totFAST;
-
- begin
- with Screen do
- begin
- Clear(white,'░'); {paint the screen}
- ShadFillBox(3,3,20,8,31,1);
- ShadowTOT^.SetShadowStyle(Upleft,lightgray,' ');
-
-
- 3-16 User's Guide
- --------------------------------------------------------------------------------
-
- ShadFillBox(3,12,20,19,47,2);
- ShadowTOT^.SetShadowStyle(Downleft,lightblue,' ');
- ShadowTOT^.SetShadowSize(4,1);
- ShadFillBox(35,2,70,10,94,3);
- ShadowTOT^.SetShadowStyle(DownLeft,white,'!');
- ShadFillBox(40,13,60,18,15,4);
- ShadowTOT^.SetDefaults;
- ShadFillBox(5,21,75,23,78,5);
- end; {with}
- end.
-
-
-
- Figure 3.1 [SCREEN]
- The Shadow Demo
- Program
-
-
-
- ScrollTOT
- ScrollTOT is a pointer to an instance of type ScrollOBJ, and is
- declared in the totFAST unit. ScrollTOT is used to control the charac-
- ters used to build the scroll bars displayed in scrolling windows.
-
- There are basically four different characters used to create a scroll
- bar. There is the directional arrow at each end, the background charac-
- ter, and the elevator (or slider) character. These characters are con-
- trolled with the following two methods:
-
- SetScrollChars(U,D,L,R,E,B:char);
-
- These six parameters represent the up and down directional arrows on
- vertical scroll bars, the left and right directional arrows on horizon-
- tal scroll bars, the elevator character and the background character.
-
- SetDefaults;
-
- Call this method with no parameters if you want to reset all the
- ScrollTOT settings to the Toolkit defaults.
-
-
- ScrollTOT does not affect the display attributes of the scroll bars.
- The window border attribute is normally used.
- SCREEN provides two methods for writing scroll bars anywhere on the
- display: WriteHScrollBar, WriteVScrollBar. Refer to Chapter 5 for fur-
- ther information.
-
-
-
- Toolkit Basics 3-17
- --------------------------------------------------------------------------------
-
- IOTOT
-
- Using consistent color schemes is particularly important during full-
- screen input. The totIO1 unit includes IOTOT which is designed to con-
- trol all the IO display attributes. IOTOT is a pointer to an object of
- type InputOBJ. The uses of IOTOT are discussed in detail in chapter 11.
-
-
- FmtNumberTOT
-
- The totIO2 unit provides routines for the input of REAL and INTEGER
- values. These values can be optionally formatted when the user moves to
- the next field, i.e. when the user is editing, the number is unfor-
- matted, but when the user exits the field, the number can be formatted
- in a variety of styles. For example, the number 123456.78 might be
- formatted as $123,456.78.
- The totIO2 unit includes FmtNumberTOT, a pointer to an object instance
- of type FmtNumberOBJ. This instance defines the default formatting that
- will be applied to real and integer fields during full-screen input.
- Any of the format defaults can be overridden for individual fields.
- Field formatting is discussed in detail in chapter 11: Controlling User
- Input.
-
-
-
- DateTOT
- The totDATE unit provides functions for manipulating and converting
- Julian and Gregorian dates. A number of default values, e.g. the char-
- acter used to separate the month from the day and the year (like ' /
- / '), are defined in DateTOT, a pointer to an object instance of type
- DateOBJ. These defaults are used in both the totDATE and totIO2 units.
- Refer to chapter 13: Managing Dates for further details.
-
-
-
- AlphabetTOT
- The totINPUT unit includes the object AlphabetOBJ for managing upper-
- and lower-case characters, and the global instance AlphabetTOT is a
- pointer to an AlphabetOBJ object.
-
- AlphabetTOT controls how the Toolkit determines/changes the case of
- alpha-characters. It is designed for international Toolkit users who
- want to use a non-English alphabet. If you are writing "English-
- speaking" programs, you do not need to tamper with this object.
- The object contains a list of all valid upper-case letters, lower-case
- letters and punctuation characters. The totLOOK unit includes the type
- declaration CharSet, which is equal to a set of char. Some methods are
-
-
-
- 3-18 User's Guide
- --------------------------------------------------------------------------------
-
- passed a parameter of type CharSet. You may specify multiple characters
- and/or ranges of characters, provided that they are enclosed in square
- brackets []. For example, the following expressions are valid CharSets:
-
- ['a','b','f'..'z']
- ['A'..'Z',#129..#148]
- ['a'..'z']
- [',','.']
- AlphabetTOT methods can be called using the syntax AlphabetTOT^.method,
- and the following methods are supported:
-
-
- SetUpper(Letters:CharSet);
- Defines which characters comprise the upper-case alphabet. The method
- is passed one parameter of type CharSet, e.g. SetUpper(['A'..'Z']);.
-
-
- SetLower(Letters:CharSet);
- Defines which characters comprise the lower-case alphabet. The method
- is passed one parameter of type CharSet, e.g. SetLower(['a'..'z']);.
-
-
- SetPunctuation(Letters:CharSet);
- Defines which characters are used in normal punctuation. The method is
- passed one parameter of type CharSet, e.g. SetPunctua-
- tion([',',';','.',':',' ']);.
-
-
- IsUpper(K:word): boolean;
- This function method is passed one parameter, representing the ordinal
- value of a character, and returns true if the character is listed in
- the upper-case alphabet, e.g. IsUpper(ord('A'));.
-
-
- IsLower(K:word): boolean;
- This function method is passed one parameter, representing the ordinal
- value of a character, and returns true if the character is listed in
- the lower-case alphabet, e.g. IsLower(107);.
-
-
- IsLetter(K:word): boolean;
- This function method is passed one parameter, representing the ordinal
- value of a character, and returns true if the character is listed in
- either the upper- or lower-case alphabet.
-
-
- IsPunctuation(K:word): boolean;
-
-
-
- Toolkit Basics 3-19
- --------------------------------------------------------------------------------
-
- This function method is passed one parameter, representing the ordinal
- value of a character, and returns true if the character is listed as a
- punctuation character.
-
-
-
- On occasion, the Toolkit needs to convert the case of alpha characters.
- To accommodate international users, the Toolkit uses AlphabetTOT to
- convert character case, rather than rely on the English-specific rou-
- tines provided with Turbo Pascal. The Toolkit calls the following two
- methods to convert character case:
-
-
- GetUpCase(Ch:char):char;
- This method is passed a character, and returns the upper-case equiva-
- lent of the character.
-
-
- GetLoCase(Ch:char):char;
- This method is passed a character, and returns the lower-case equiva-
- lent of the character.
-
-
- You can control precisely how characters are converted by creating your
- own conversion routines. All you have to do is create two functions
- following some specific rules, and then call the methods Alphabet-
- TOT^.AssignUpCaseFunc and AlphabetTOT^.AssignLoCaseFunc to instruct the
- Toolkit to use your functions.
- For a function to be eligible as a character case converter it must
- adhere to the following three rules:
-
- Rule 1 The function must be declared as a FAR function. This can be
- achieved by preceding the function with a {$F+} compiler
- directive, and following the function with a {$F-} direc-
- tive. Alternatively, Turbo 6 users can use the new keyword
- FAR following the procedure statement.
- Rule 2 The function must be declared with one passed parameter of
- type char, and it must return a char.
-
- Rule 3 The function must be at the root level, i.e. the function
- cannot be nested within another procedure or function.
- The following function declaration follows these rules:
-
- {$F+}
- function MyUpConverter(Ch:char):char;
- .....{statements}
- end;
- {$F-}
-
-
-
- 3-20 User's Guide
- --------------------------------------------------------------------------------
-
- Internally, these functions should check the value of the passed char-
- acter, and return the character converted to the appropriate case. If
- the character is not suited to conversion, e.g. '1', simply return the
- character that was passed. Once you have created two functions (one for
- upper-case conversion and one for lower-case conversion), you should
- call the following assignment methods to instruct AlphabetTOT to use
- your routines:
-
-
- AssignUpCaseFunc(Func:CaseFunc);
- This method is passed the name of the function used to convert charac-
- ters to upper case. The procedure must adhere to the rules outlined
- above.
-
-
- AssignLoCaseFunc(Func:CaseFunc);
- This method is passed the name of the function used to convert charac-
- ters to lower case. The procedure must adhere to the rules outlined
- above.
-
-
- In summary, AlphabetTOT provides you with complete control over how the
- Toolkit determines and changes the case of alpha characters.
-
-
- Program Size
-
- A constant battle during the development of the Toolkit was to minimize
- the size of programs developed with the Toolkit. A valid criticism of
- OOP is that it tends to swell the final program size, which makes it a
- subject of concern to most developers (that's you folks).
- With a hierarchical object organization even small applications tend to
- attract a high code overhead. However, the more features of the Toolkit
- you use, the more efficient your program will be. For example, listed
- below are the EXE file sizes of three of the demo programs:
-
- DemFM8 114k
- DemDR1 92k
- DemMS1 56k
- The combined file size of the three programs is 262k. However, if these
- three examples are combined into a single example, the file size is
- actually 141k. The reason for the reduction is that each of the small
- programs uses common routines which can be shared in the combined
- program.
-
-
-
- Toolkit Basics 3-21
- --------------------------------------------------------------------------------
-
- In real life, your fledgling program will start out bigger than you
- expected, but it will grow much less than anticipated as your program
- expands. Remember that compiler directives have a significant impact on
- program size, and you should enable the FINAL compiler directive for
- the production build of your application.
-
- If EXE file size is your concern, rather than code size, consider com-
- pressing the EXE file with a compression utility like PKlite from
- PKWare, Inc., or LZEXE by Fabrice Bellard.