T H E ô ô C ÀoÍÍoÙ L ÛÛÛÛß M O U S E ÛÛßÜ C U R S O R ß ßÜ ßÜ Version 1.1 30-DAY FREE TRIAL MANUAL A "Real" Mouse for Turbo Vision 2.0 and Turbo Pascal 7.0 This true-arrow, text-mode mouse is so REAL-looking it will have you doubting your eyes . . . and reaching for a piece of cheese. TABLE OF CONTENTS I. Introduction & Ordering Information II. Disclaimer III. Files You Should Have IV. How to Add the COOL MOUSE CURSOR to an Application V. How to Toggle Between Mouse Shapes VI. How to Sing the COOL MOUSE CURSOR to sleep VII. How to Control Which Character Patterns get Over-written VIII. Text Mode Artifacts and Steady Backgrounds IX. Programmer's Reference -------------------------------------------------------- I. INTRODUCTION & ORDERING INFORMATION Every now and then some program performs a bit of magic--the software version of sawing a lady in half--leaving the rest of us scouring our manuals to figure out how it was done. Norton Utilities 5.0 included such a trick: a mouse cursor that was a "real" mouse--a true arrow--not the inelegant block we thought we had to use in our text mode programs. And yet NU was definitely in text mode . . . . You've probably seen either the Norton Utilities mouse cursor or another like it (such as the mouse cursor in the shareware image-viewing program CShow). It's as if a spirit has been summoned from the higher planes of graphics into our chunky world of 80x25 screens. These amazing mouse cursors are real arrows that glide--half on one letter, half on another; they refuse to limit themselves to the character tiles that text mode allows. As programmers who use Turbo Vision 2.0, we know that it is an impressive application framework which handles overlapping windows, pull-down menus, buttons, input lines, and many other controls like a virtuoso; in every respect, at least from a functional point of view, it is equal or superior to any other text-mode interface we've seen. However, some other text-mode user interfaces have concentrated more on taking advantage of the special capabilities of today's video adapters. This concentration has allowed some of those interfaces to look a little slicker, a little more polished--it has let them make use of cool devices . . . such as the graphical, arrow-shaped mouse! Sadly, Turbo Vision saddles us with the same old text-mode mouse cursor: a block; a chunk; a mere "XOR" of color. In every practical respect, that's fine; it's functional; it just doesn't give our applications that gleam of the latest technology that might help them impress and sell. But now we're proud to introduce a gleam--a text-mode, arrow-shapped, graphical mouse cursor that works with Turbo Vision 2.0 and Turbo Pascal 7.0. Naturally it's called the COOL MOUSE CURSOR: it can make all our Turbo Vision 2.0 applications appear truly "cool." Since you are reading this 30-day trial version manual you should also have in your possession all the files that you need in order to see the COOL MOUSE CURSOR in action, gliding across the text mode characters as if it is in graphics mode; and you should also have all the files you need in order to try out the COOL MOUSE CURSOR in your own existing Turbo Vision 2.0/Turbo Pascal 7.0 programs! You can add the true arrow COOL MOUSE CURSOR to your existing applications merely by including one extra unit in your USES clause and one extra statement in your application object's constructor. You will need to add a couple more statements if your application shells out to DOS, or executes another program, or changes font sizes or modes--but this is all simple to do. The COOL MOUSE CURSOR works on EGA/VGA/SVGA adapters--that is, it works on most adapters extant in the PC marketplace, and it will work on nearly every new PC that's being sold. But the COOL MOUSE CURSOR is not cool only because of how cool it looks and works, but also because it is a savvy little rodent. For instance, it automatically senses when a mouse is not present and doesn't install itself in that case. It also automatically senses when a suitable video adapter is not present and steps gracefully out of the way, allowing the normal block mouse cursor to do its work. And since it's a good citizen, it cleans up all its messes, undoing any changes it makes to the font patterns in video memory. You are invited to try out the COOL MOUSE CURSOR in your own Turbo Vision 2.0/Turbo Pascal 7.0 applications for 30 days. (However, you are not authorized to release to the public any versions of your software that use the COOL MOUSE CURSOR until you register it.) If, by the end of that time you think the COOL MOUSE CURSOR is really cool and you would like to use it in your programs, then register yourself as a user. There are two ways to register. (1) For just $10.00 (plus $3.00 postage and handling) you'll receive the latest version of the COOL MOUSE CURSOR compiled in both real mode and protected modes (.TPU and .TPP), with some added bells and whistles not in the trial version, and you'll also receive the latest version of the COOL MOUSE MANUAL. You'll be able to use the COOL MOUSE CURSOR, royalty free, in all your Turbo Vision 2.0 applications. You'll also get a price break on future updates. (2) For just $40.00 (plus $3.00 postage and handling) you'll receive everything listed in number (1) above, plus you'll recieve the complete, well-commented source code for the COOL MOUSE CURSOR and a well-written 4,000 word article explaining how the COOL MOUSE CURSOR works. If you're handy and willing to open up the hood, you'll be able to customize the COOL MOUSE CURSOR for your own needs. In case you cannot locate the file ORDER.FRM which contains the order blank for the COOL MOUSE CURSOR, send a check, money order, or bank draft (for overseas customers) for either of the above amounts (be sure to include $3.00 for postage and handling) to Ed Jordan 3418 Yale Circle Riverview, FL 33569 If you are a Florida resident, please include sales tax. Don't forget to include your own address! The rest of this manual explains how easy it is to incorporate the COOL MOUSE CURSOR into your existing (or new) Turbo Vision 2.0/Turbo Pascal programs. Good luck. And cool it. II. DISCLAIMER The creator of this product hereby disclaims all warranties relating to it, whether express or implied, including without limitation any implied warranties of merchantability or fitness for a particular purpose. The creator cannot and will not be liable for any special, incidental, consequential, indirect or similar damages due to loss of data or any other reason, even if the author or an authorized agent has been advised of the possibility of such damages. In no event shall the liability for any damages ever exceed the price paid for the license to use the software, regardless of the form and/or extent of the claim. The user of this program bears all risk as to the quality and performance of the software. III. FILES YOU SHOULD HAVE The following files should accompany this 30-day trial manual: COOLDEMO.EXE -- a demonstration Turbo Vision application that uses the COOL MOUSE CURSOR COOLDEMO.PAS -- the Pascal source code for COOLDEMO.EXE COOLMOU.TPU -- the real mode compiled unit containing the Turbo Pascal 7.0 COOL MOUSE CURSOR code. COOLMOU.TPP -- the protected mode compiled unit containing the Turbo Pascal 7.0 COOL MOUSE CURSOR code. COOLMOU.INT -- the interface for the the COOL MOUSE CURSOR code. ORDER.FRM -- the order form for the COOL MOUSE CURSOR FILE_ID.DIZ -- a brief description of the COOL MOUSE CURSOR IV. HOW TO ADD THE COOL MOUSE CURSOR TO AN APPLICATION This section covers the bare bones way to add the COOL MOUSE CURSOR to an existing application--and really there's not much more to it than this. TO ADD THE COOL MOUSE CURSOR TO AN EXISTING APPLICATION: (1) Add the COOLMOU unit to your main program's USES clause. For example, if your old USES clause looked like this USES Dos, Objects, Views; then your new USES clause should look something like this USES CoolMou, Dos, Objects, Views; Of course, you'll also have to make sure that the COOLMOU.TPU file is in a directory that is accessible by the compiling programs that want to use it. (2) Add the following statement to the end of your application object's INIT constructor: SetMouseState(msArrow); For an example of these statements in action, see the file COOLDEMO.PAS. V. HOW TO TOGGLE BETWEEN MOUSE SHAPES In the section above, you were instructed to put the statement SetMouseState(msArrow); in your application object's INIT constructor. The reason we told you to do this is that we assumed you would want the COOL MOUSE CURSOR to get into its arrow costume right away. The COOL MOUSE CURSOR, however, can assume either the arrow shape or the normal text mode block shape; after all, users have their own tastes, and it's conceivable (though likely rare) that some users will prefer the stodgy block to the cool arrow. So the COOL MOUSE CURSOR allows you (and, if you decide to make the capability available, allows your users) to toggle the cursor shape between arrow and block as often as you desire. You change the mouse cursor shape by specifying a new shape "state" for the COOL MOUSE CURSOR. The COOL MOUSE CURSOR actually has five states, given as an enumerated type in the interface section of the COOLMOU unit: type TMouseState = ( msUninstalled, msAsleep, msAwake, msArrow, msBlock); The two states that determine shape are msArrow and msBlock. We'll talk about the other states later. At startup, if the COOL MOUSE CURSOR can install itself, it retains the msBlock state and the block shape; consequently, the mouse cursor looks no different than if the COOL MOUSE weren't involved at all. But when you insert the statement SetMouseState(msArrow); into your code, you command the COOL MOUSE CURSOR to change its state and shape to the cooler version--the arrow. Later, after the mouse cursor has changed to an arrow, the statement SetMouseState(msBlock); will command the mouse cursor to assume block form again; it will make Superman put back on his Clark Kent glasses. The current state of the mouse cursor can be ascertained with a call to the function MouseState, which returns a value of type TMouseState (the enumerated type listed above). One way to toggle between block and arrow shapes would go something like this: if (MouseState = msArrow) then SetMouseState(msBlock) else if (MouseState = msBlock) then SetMouseState(msArrow); However, the COOLMOU unit provides a better way to do this-- through the "ToggleMouseShape" function. ToggleMouseShape toggles the shape of the mouse cursor between arrow and block, and returns a value of type TMouseState to indicate what the current state of the mouse is after the toggling. So, if you decide to provide a "Toggle Mouse Shape" option on your menubar, you should implement the toggling in the simplest way; merely use the statement ToggleMouseShape; and arrow will become block, or block will become arrow. VI. HOW TO SING THE COOL MOUSE CURSOR TO SLEEP There are times when you will want to temporarily deactivate the COOL MOUSE CURSOR (put it to sleep). When you're shelling to DOS, or using EXEC to execute another program, or when you're doing anything else that potentially turns over control of the mouse to another application, you'll want to set the COOL MOUSE down for a little nap. Don't worry, he'll wake up and play again as soon as the strangers are gone. Deactivating and reactivating the COOL MOUSE CURSOR is simple: SetMouseState(msAsleep); deactivates the COOL MOUSE; SetMouseState(msAwake); reactivates it. Basically, when you're performing any process that doesn't agree with the mouse, you can surround the command to perform that process with the mouse command to sleep and the mouse command to wake. To enable a mouse-friendly shell to DOS, for example, place the following code in your application's HandleEvent method before you call the inherited HandleEvent method: if (Event.What = evCommand) and (Event.Command = cmDosShell) then begin SetMouseState(msAsleep); { Temporarily deactivates mouse } DosShell; SetMouseState(msAwake); { Reactivates the mouse } end; Because shelling to DOS is so common, the COOLMOU unit provides a special procedure, MouseSafeDosShell, that replaces the three lines between the BEGIN and END above. You can simply insert the following in the same position in you application's HandleEvent method: if (Event.What = evCommand) and (Event.Command = cmDosShell) then MouseSafeDosShell; Changing fonts or modes is another process that the COOL MOUSE CURSOR would rather sleep through. Surround the actual font-changing process like this: HideMouse; SetMouseState(msAsleep); { Mode/font change } if ScreenMode and smFont8x8 = 0 then SetScreenMode((ScreenMode or smFont8x8)) else SetScreenMode((ScreenMode and not smFont8x8)); SetMouseState(msAwake); ShowMouse; Hiding the mouse and showing the mouse before and after the font change may not be strictly necessary, but it's sometimes a good idea to hide the mouse as well as deactivating it before certain processes. (By the way, the COOL MOUSE CURSOR should work with nearly any size font you use in your text-mode programs.) Various examples of deactivating and reactivating the COOL MOUSE CURSOR can be found in the file COOLDEMO.PAS. VII. HOW TO CONTROL WHICH CHARACTER PATTERNS GET OVER-WRITTEN In order to draw the graphical arrow on the text mode screen, the COOLMOU unit takes 9 seldom-used ASCII symbols and overwrites their font patterns on the fly. These nine symbols are listed in Table 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TABLE 1: Default characters in the mouse overwrite string. STRING POSITION 1 2 3 4 5 6 7 8 9 ASCII CODE #208 #209 #210 #214 #215 #216 #233 #234 #235 SYBMOL Ð Ñ Ò Ö × Ø é ê ë . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The COOLMOU UNIT saves the original patterns of the overwrite characters before it overwrites them, and restores the original patterns when you deactivate the mouse or when the program ends, so this overwriting causes no harm to your system or to any programs that run after yours. However, on the off chance that your program makes use of one or more of these seldom-used symbols, the COOL MOUSE UNIT provides a way for you to control which ASCII symbol definitions get overwritten. The example below assumes that your program wants to employ ASCII code #233 on screen, and that you have therefore decided to substitute #236 as a code to be overwritten. procedure ChangeMouseChar; var MouseString: TMouseString; begin MouseString := MouseChars; { Get a copy of the current Mouse overwrite string } MouseString[7] := #236; { Substitue #236 in place of #233 } SetMouseChars(MouseString); { Set this changed string as the new overwrite string } end; "TMouseString," referred to above, is defined in the COOLMOU unit interface as a string of 9 characters, equivalent to String[9]. "MouseChars," also referred to in the example above, is a function that returns a TMouseString containing all 9 characters currently slated to be overwritten. "SetMouseChars" is a function that installs a new set of 9 characters to be overwritten, and which returns true if the installation was successful. The example above uses the MouseChars function to get a copy of the current string of overwrite characters; it changes the seventh character in that copy of the string, which from the table above we can see is #233, the character we want to protect; it then uses SetMouseChars to install the changed copy as the new overwrite string. Now the pattern for character #233 will not be overwritten, and the program is free to display it on screen. There are a couple of important restrictions on which characters can be substituted into the overwrite string. For the COOL MOUSE to operate properly, the first 6 characters in the mouse string MUST BE chosen from among the graphics characters in Table 2 below (and the last 3 characters in the mouse string MUST NOT BE chosen from among the graphics characters in Table 2 below). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TABLE 2: Characters that can be substituted into the first 6 characters of the mouse overwrite string, and which CANNOT be substituted into the last three characters of the mouse overwrite string. #192 #193 #194 #195 #196 #197 #198 #199 #200 #201 #202 À Á Â Ã Ä Å Æ Ç È É Ê #203 #204 #205 #206 #207 #208 #209 #210 #211 #212 #213 Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ #214 #215 #216 #218 #219 #220 #223 Ö × Ø Ú Û Ü ß . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Thus, if you wanted to substitute some other character for #208, which is among the first 6 characters in the overwrite string, you would have to use one of the characters from Table 2; but if you wanted to substitute for character #233, which is among the last three characters in the overwrite string, you would have to use some character that was NOT in Table 2. These restrictions help insure that the mouse and the characters beneath it retain a wholesome appearance on screen. Passing invalid characters to SetMouseChars will cause it to do nothing and return False as its result. By the way, changes to the mouse overwrite characters can be made at any time, not just at the beginning of a program. VIII. TEXT MODE ARTIFACTS AND STEADY BACKGROUNDS Although in nearly every respect the COOL MOUSE CURSOR looks and behaves like a graphics mouse cursor, the reality is that it is still operating in text mode. This causes a few text mode "artifacts" to appear as it glides magically across the tile- based characters below it. For one thing, colors in text mode are controlled by attributes that belong to each individual character. There is no way to ensure that the COOL MOUSE CURSOR will always be drawn white-on-black as graphics mode mouse cursors usually are. In fact, the COOL MOUSE CURSOR must, like a chameleon, take its colors from whatever it rests on. If the characters below it are yellow-on-blue, the COOL MOUSE CURSOR will be yellow-on-blue. If it is resting on two different characters, the left one white-on- black and the right one yellow-on-blue, the mouse cursor itself will be those same four colors. This is unavoidable; it is the same behavior exhibited by other graphical text mode cursors; and in fact real users either don't notice the color changes or forget about them. The most important effect is still pure cool arrow. A second text mode artifact is that the right sides of certain characters which the mouse passes over will sometimes slightly thicken; this happens with M's, for instance. This thickening is due to the fact that the COOL MOUSE CURSOR, to avoid gapping, must make use of graphics characters in order to draw itself. (The graphics characters in Table 2 have their eigth column of pixels repeated as their ninth column, so that solid lines can be drawn across the screen.) A full explanation is slightly too involved to go into here, but again the thickening is an artifact of being in text mode (it doesn't occur, by the way, in 43- or 50-line modes). Again, this is the same behavior exhibited by other graphical text-mode mouse cursors (check the Norton Utilities mouse or the CShow mouse and see). And again, real users don't seem to notice or mind. The coolness of the mouse cursor itself is much more obvious. The situation in which the thickening shows up most is when the mouse cursor moves against the traditional Turbo Vision half- tone background character, #176. A tall, thin shadow of thickened dots follows the mouse cursor across the screen. Fortunately, the COOLMOU unit provides a solution to this thickening in the form of the "InstallSteadyBkgd" function. InstallSteadyBkgd takes two parameters: (1) a pattern character and (2) a graphics character (from Table 2) whose pattern will be overwritten. For example, to use the traditional Turbo Vision half-tone background pattern, but in a form that does not shadow as the mouse passes across it, call InstallSteadyBkgd(#176, #202); (#202 is just one example; it could be replaced by any other graphics character from Table 2.) InstallSteadyBkgd copies the font pattern of the pattern character (the first parameter) into the font pattern of the graphics character (the second parameter). It then installs the graphics character as the background character for the application and redraws the screen. This solves the problem. Of course, the graphics character that you pass to InstallSteadyBkgd SHOULD NOT BE one of the first six characters in the mouse overwrite string! To enable you to reverse the steadying process, the COOLMOU unit contains the function "RemoveSteadyBkgd," which restores the font pattern of the graphics character and re-installs the pattern character as the background character for the application. (Unlike InstallSteadyBkgd, RemoveSteadyBkgd does not go so far as to redraw the screen.) You do not have to call RemoveSteadyBkgd before your application ends--that's done automatically for you. But you may want to use it if your application makes use of multiple background patterns. The file COOLDEMO.PAS contains an example of toggling between two different backgrounds, a solid one and the steady half-toned one. IX. PROGRAMMER'S REFERENCE InstallSteadyBkgd ---------------------------------- function InstallSteadyBkgd(PatternChar, GraphChar: Char): Boolean; InstallSteadyBkgd takes two parameters: a pattern character and a graphics character (from Table 2 in section VII of this manual) whose pattern will be overwritten. To use the traditional Turbo Vision half-tone background pattern, but in a form that does not shadow as the mouse passes across it, call InstallSteadyBkgd(#176, #202); (#202 could be replaced by any other graphics character from Table 2.) InstallSteadyBkgd copies the font pattern of the pattern character (the first parameter) into the font pattern of the graphics character (the second parameter). It then installs the graphics character as the background character for the application and redraws the screen. The graphics character SHOULD NOT BE one of the first six characters in the mouse overwrite string! An invalid parameter will cause InstallSteadyBkgd to do nothing and return False as its result. See also: RemoveSteadyBkgd, SetMouseChars. MouseChars ---------------------------------- function MouseChars: TMouseString; Returns the string of characters which are currently having their font patterns overwritten in order that the COOL MOUSE CURSOR can be drawn. See also: TMouseString, SetMouseChars. MouseSafeDosShell ---------------------------------- procedure MouseSafeDosShell; Shells out to DOS, with automatic deactivation of the COOL MOUSE CURSOR beforehand and automatic reactivation afterward. Equivalent to SetMouseState(msAsleep); DosShell; SetMouseState(msAwake); See also: SetMouseState. MouseState ---------------------------------- function MouseState: TMouseState; Returns the state of the mouse as a value of type TMouseState. See also: TMouseState, SetMouseState. NUM_OVERWRITTEN_DEFS ---------------------------------- const NUM_OVERWRITTEN_DEFS = 9; Number of character definitions in the mouse overwrite string. See also: MouseChars. RemoveSteadyBkgd ---------------------------------- function RemoveSteadyBkgd: Boolean; RemoveSteadyBkgd restores the font pattern of the graphics character that was previously passed to InstallSteadyBkgd. It also re-installs the pattern character that was passed to InstallSteadyBkgd as the background character for the application. You do not have to call RemoveSteadyBkgd before your application ends--that's done automatically for you if you have used InstallSteadyBkgd. But you may want to use RemoveSteadyBkgd if your application makes use of multiple background patterns. Unlike InstallSteadyBkgd, RemoveSteadyBkgd does not redraw the screen. You can do that yourself in the following way: DoneMemory; Redraw; RemoveSteadyBkgd returns True if it the removal was successful. See also: InstallSteadyBkgd. SetMouseChars ---------------------------------- function SetMouseChars(S: TMouseString): Boolean; Used to set the string of characters which have their font patterns overwritten in order to draw the COOL MOUSE CURSOR. It returns True if successful. Characters 1-6 of the string S should be graphics characters from Table 2 in section 7 of this manual, and none of them should be the same as the graphics character used to steady the background (if any). Characters 7-9 of the string S should NOT be graphics characters from Table 2 in section 7 of this manual. Invalid characters in the string S will cause SetMouseChars to do nothing and return False as its result. See also: MouseChars, TMouseString, InstallSteadyBkgd. SetMouseState ---------------------------------- function SetMouseState(AMouseState: TMouseState): Boolean; Accepts a parameter of type TMouseState and sets the state of the mouse. Returns True as its result if the designated mouse state could be successfully set. See also: TMouseState, ToggleMouseShape, MouseState. TMouseState ---------------------------------- type TMouseState = (msUninstalled, msAsleep, msAwake, msArrow, msBlock); The possible "states" of the true arrow mouse. If the COOL MOUSE CURSOR is not able to install itself (because the host has no mouse or has an unsuitable display adapter), the mouse state becomes "msUninstalled." By checking whether the mouse state is equal to msUninstalled, you can determine whether to gray out any menubar options that pertain to the COOL MOUSE CURSOR. msAsleep and msAwake are used to temporarily deactivate, then reactivate the COOL MOUSE CURSOR. msArrow and msBlock are used to set the shape of the cursor. See also: MouseState, SetMouseState. TMouseString ---------------------------------- type TMouseString = String[NUM_OVERWRITTEN_DEFS]; The type used to set which characters will have their definitions overwritten in order to draw the arrow cursor. Since NUM_OVERWRITTEN_DEFS is equal to 9, TMouseString is equivalent to String[9]. Characters 1-6 should be graphics characters from Table 2 in Section VII of this manual. Characters 7-9 should be "normal" characters, NOT from Table 2. See also: NUM_OVERWRITTEN_DEFS. ToggleMouseShape ---------------------------------- function ToggleMouseShape: TMouseState; Toggles the shape of the mouse between arrow and block, and the state of the mouse between msArrow and msBlock. Returns the state of the mouse after the toggling is done. See also: SetMouseState, TMouseState.