











                                      
                                                               
                                                                           
                                                                           
                                    ////////    //    //    //   
                                   //    //    ///   //    //    
                                  //    //    ////  //    //     
                                 ////////    // // //    //      
                                //          //  ////    //       
                               //          //   ///    //          
                              //          //    //    ///////    
                                                                           
                                                                           
                                                                       
                                                                      
                                                                      
                                      Pascal NewsLetter         
                                          Issue #5
                                       December, 1990             
                                                                      
                                                                      
                                      Editor: Pete Davis         
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                      
                                                                          
                        The Programmer's Forum BBS is the home of
                        PNL. It can be reached in Washington, DC at
                        (202)966-3647. Information is available 
                        through the following locations:        
                                           
                        FidoNet:  Pete Davis@1:109/138           
                        GEnie:    P.DAVIS5                          
                        BitNet:   HJ647C@GWUVM & UE356C@GWUVM
                        InterNet: HJ647C@GWUVM.GWU.EDU 
                               or UE356C@GWUVM.GWU.EDU
                        Uucp:     Pete.Davis@f138.n109.z1.fidonet.org


                                                                        2

                                  Table of Contents



               Introduction ...............................  3  (P.D.)


               The Lazy Programmer's Guide
               to Graphics in Pascal ......................  4  (R.M.)


               Introduction to Multiple Concept
               Pascal Programming ......................... 15  (P.R.)


               For Beginners .............................. 22  (B.G.)


               Recursion is Easy .......................... 32  (C.B.)


               Conclusion ................................. 38  (P.D.)


               Distribution List .......................... 40





               

             P.D. -> Pete Davis          (Editor-in-Chief, Writer)
             R.M. -> Richard A. Morris   (Editor-Over-the-Pond, Writer)
             B.G. -> Bob Gowans          (Staff writer)
             P.R. -> Paul Robinson       (Contributing writer)
             C.B. -> Chris Burke         (Contributing writer)

                                                                        3

                                     Introduction

                  Well,  finally getting to  another issue of  the Pascal
             NewsLetter. We're making  a few changes in  the organization
             of  PNL. First of  all, I've  promoted myself  to Editor-in-
             Chief. That's really what I've been all along, but it was to
             make room for some new titles.

                  We've got a  new staffer, Richard  A. Morris, with  the
             distinguished title of  'Editor-Over-the-Pond'. Richard will
             be a collection point in Australia for PNL contributions and
             will be editing  and sending them on to me  for inclusion in
             the NewsLetter.  For a profile  of Richard, read the  end of
             his  article.   If  you   live  in   Australia,  send   your
             Contributions  to Richard A. Morris. His Fido-Net Address is
             3:640/378. His system's phone number is 61-7-878-1194.

                  Richard is also writing "The Lazy Programmer's Guide to
             Graphics in Pascal", a series of articles about, you guessed
             it,  graphics programming  in Pascal.  It's   very  thorough
             coverage of  graphics, so  many of you  will surely  find it
             interesting.

                  Many  of  you probably  already  know that  I  had been
             planning on  putting the  newsletter  out as  'Subscription-
             only'.  Well, I  ran into  some problems  un-related to  the
             newsletter which have forced me to  postpone, at least until
             summer, this course.

                  Also,  I  would like  to  thank everyone  who  has been
             contributing. It  seems that  the number  of submissions  is
             increasing slightly, which is a  terrific bonus. If you  can
             keep them coming in, the newsletter just might find a way to
             come out a bit more often. 

                  In  this  issue, Paul  Robinson will  be talking  a bit
             about  writing large programs in Pascal  and will cover some
             programming  techniques. Bob  Gowans  continues his  popular
             "For  Beginner's" column,  and last,  but  not least,  Chris
             Burke shows you how simple recursion can be.

                  Well, that's about it for  this issue. I hope you enjoy
             it.

                                                                        4

                   The Lazy Programmers Guide to Graphics in Pascal
                                 by Richard A. Morris
                                    Fido 3:640/378
                                 Brisbane, AUSTRALIA

                  I have been  running a BBS and reading  FIDO echoes for
             some years  now and  invariably the  first  2 things  Novice
             programmers  want to  write with  their new  language are  a
             better BBS, and a better Graphic Game.  Well I'll leave  the
             intricate subject  of Data  communications to  the "Build  a
             better Mousetrap "experts, and Game theory to the Academics,
             Rather  in  the  next  6  Articles  I'll  discuss   Graphics
             programming with Turbo Pascal.

                  The Idea behind the Lazy programmers Guide, is that  if
             you are like  me, you often wondered how easy it would be to
             do some particular programming task,  but never had the time
             or inclination to  get around to opening the  manual at that
             section.  Well this article is both for the  novice, and the
             experienced  (Lazy Programmer) and  will take you  from very
             simplistic exercises to quite complex Graphic programming in
             a  short  time,  by  program  examples,  and  prodding  your
             imagination to experiment a bit :-).

                  These articles are based on Turbo Pascal on the PC, and
             I  apologize  in  advance  to   those  not  using  that,  in
             particular  versions  4,  5, and  5.5  (And  I apologize  in
             Advance to all Americans as I intend to use the word Color a
             lot :-). I  am sure that the  topics I intend to  cover will
             have some  relevance for  all Graphic  programming. I  don't
             promise  that you  will be  able  to write  a better  Flight
             Simulator (Although if you do  I want a mention :-)  but you
             will understand a bit more about how it's done, and probably
             gain a lot of respect for these Graphic Wizards.

                  The articles will  assume that you have  some knowledge
             of  programming   concepts  (Such  as   Binary  mathematics,
             Trigonometry)  and Turbo Pascal  (there will be  very little
             handholding  :-), and will take  you from simple graphics to
             quite Advanced programming concepts.

             The Articles will comprise the following Topics;
                                                             
                     Basic Graphics with Turbo Pascal GRAPH unit.
                     Graphs, Statistics, and windows with the GRAPH unit.
                     Simple Animation and Sprites using the GRAPH unit.
                     User defined programming in the GRAPH Unit
                     Writing Directly to the EGA/VGA.
                     Animation using Direct writes to the EGA/VGA.
                     Three Dimensional Graphics directly to the EGA/VGA.



                                                                        5


             ------------------------------------------------------------
             The Lazy Programmers guide to Turbo Pascal Graphics - Part 1
                     - Basic Graphics with the GRAPH unit -
             ------------------------------------------------------------


             A Brief  History of  PC Displays -  Apologies to  S. Hawkins
             :-).
             ------------------------------------------------------------

                  Graphics  in  the  Personal  computer  world  refer  to
             non-text  display information.  The original  PC  released a
             decade  ago,  was   equipped  with  a  display   called  the
             Monochrome Display, and a  driver called (Surprise surprise)
             the   Monochrome  Display  Adapter.    This  Display  had  a
             resolution   of  720x350  and  displayed  ONLY  the  IBM  PC
             character set in black and white.

                  It was not long before the popularity of computers such
             as the Apple II, with it's bit mapped display, caused demand
             for a  graphic display, and  the Hercules (from a  PC add-on
             company  Hercules  Computer  Technology)  was  born.     The
             Hercules  still displayed  data in black  and white,  but it
             allowed you  to show bitmapped  graphics.  Soon IBM  got the
             hint and released  the Color Graphics Adapter  with 16 color
             text and 4 color bit mapped  graphics, unfortunately the CGA
             design  featured a  lot  of compromises  such as  display to
             inferior  composite  displays,   and  offered  poor  display
             resolution (320x200), but  it did have Color, and  it is one
             of the most popular displays around.

                     Eventually due  to increasing  market pressure  from
             companies  like Apple, Atari, and Commodore, IBM brought out
             a reasonable display  called the ECD, and drove  it with the
             Enhanced  Color Adapter, this  gave programmers access  to a
             resolution of  640x350 with  16 simultaneous  Colors from  a
             palette of 64.  Lately VGA technology has become  a standard
             and it increases  displays up to 640x480 and  256 colors (at
             320x200).   These articles will  concentrate on the  EGA and
             VGA modes, but the GRAPH  unit stuff will cover some aspects
             of general graphic  device programming, and this  first part
             only requires a CGA Screen..


             BGI - The Borland Graphics Interface
             ------------------------------------

                  Due to the nature of  the PC market, any programmer who
             wrote his code  for any particular Graphic  standard limited
             his earnings by limiting his User base to only that machine.
             True, most of  the standards are Downward  compatible, which


                                                                        6

             means that  a CGA only application  would run on a  VGA, but
             given the choice  a VGA owner would surely  choose a product
             that displayed VGA graphics. 

                  Until  Borland brought out BGI's most Languages did not
             support Graphics at  all, relying on third  party toolboxes,
             with Turbo Pascal and Turbo C Borland introduced the concept
             of a  Graphic Interface whereby  a programmer wrote  code to
             call the  BGI  which would  then  do all  the  hard work  of
             working out what device it was talking to and how to display
             that information.

                  This is a great concept,  as it provides portability of
             programs  across  graphic  devices,  but of  late  a  lot of
             programmers  have decided  to bypass  Borlands interface  to
             talk  instead directly  with the  graphic  device. The  main
             reason for this  is speed, Borland Drivers  use the computer
             BIOS in  a lot of  cases (Which itself wastes  time deciding
             what  device it  is  talking to),  and are  themselves quite
             slow,  hence I  shall devote  a  fair bit  of time  in later
             Articles on programming Directly to the Graphic device.


             Setting up to display Graphics
             ------------------------------

             Firstly to  Show graphics  on our monitor  we must  tell the
             device to get  into graphics mode, at the  end of displaying
             what we want we must also return  the system to the original
             display mode.  Additionally as  we will be using BGIs during
             this article,  we must tell  Turbo pascal where to  find our
             BGI control files.

                  A sample of a simple  program to get into graphics mode
             display a line of text  (More of this in this article),  and
             go back to text mode is in the following program put it into
             a  file called GRAPH_TE.PAS.  To compile it load it into the
             editor, change  line 7  to make BGI_Directory  point to  the
             directory  you have  put all  the BGI  files into  (eg:I use
             c:\TP\BGI).

             ~ Prog 1 ~~~~~~GRAPH_TE.PAS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             {$M 16384,16384,655360}
             Program Graph_Test;
             Uses
               CRT,
               GRAPH;
             Const
               BGI_Directory = 'C:\TP\BGI';
             var
               GraphDriver   : Integer;
               GraphMode     : Integer;

                                                                        7

               ErrorCode     : Integer;
               tempstr       : String;
             begin
               GraphDriver := Detect;
               InitGraph(GraphDriver,GraphMode,BGI_Directory);
               ErrorCode := GraphResult;
               if ErrorCode <> grok then
               begin
                     Writeln('Error initialising Graphics :',ErrorCode);
                     Writeln('Error Message :',GraphErrorMsg(ErrorCode));
                     Halt(1);
               end;

               {Graphics stuff begins}
               Str(GraphMode,TempStr);
               OutText('We are in Graphics mode number :'+TempStr);
               Str(GraphDriver,TempStr);
               OutText('This is Device number :'+TempStr);
               {End of Graphics stuff}

               delay(1000);
               CloseGraph;
             end.
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  O.K. let's dissect this test program, firstly in line 4
             we USE the  GRAPH unit, this will  give us access to  all of
             the  graphics  routines,  and  constants.  We   declare  the
             directory  that all  the  BGI  files will  be  found into  a
             constant, and declare  4 variables GraphDriver to  store the
             type  of graphics  device we  have, GraphMode  to store  the
             graphics mode  we  will use,  ErrorCode to  store any  error
             numbers,  and  TempStr  to  temporarily  store  integers  as
             strings.

                  Then we set  GraphDriver to the GRAPH  constant DETECT.
             DETECT  is  defined as  0  and  will  tell Turbo  Pascal  to
             automatically detect the Graphic device connected to the PC,
             and  select for us the  maximum available Graphics mode. The
             next line calls  the GRAPH function INITGRAPH,  we tell this
             function  what device  to talk  to  (or AUTO  detect in  our
             case), which mode we want (In this case the Auto detect will
             select one for us), and the  location of the BGI files.   We
             can actually pre-select the type of device by specifying the
             GraphDriver and  GraphMode before  running InitGraph,  as in
             the following inset (Replace Grafdriver := detect).

             ~~~~~~~~~~~~~~~~~~~~~~
               GraphDriver := CGA;
               GraphMode := cgac0;
             ~~~~~~~~~~~~~~~~~~~~~~


                                                                        8

                  This will set up the  Graphic device for working with a
             CGA compatible device,  running in mode CGAc0, or  the first
             CGA color mode.  InitGraph allocates some memory on the heap
             to work  with, so you  must have some heap  memory available
             (Hence the  $M directive  in line 1),  such as a  general 4K
             buffer for graphics, and space to put the BGI file.

                  The GRAPH  function GraphResult will have  an errorcode
             after most  GRAPH routines and  will be zero if  the routine
             proceeded without error, or will contain an error  number if
             an error occurred, the function GraphErrorMsg can give you a
             textual error message if you send  it the error number as we
             have  in the test  program.  If an  error occurs the program
             describes the error and aborts.

                  Assuming  successful  initialization   of  the  Graphic
             system the  next step is  to perform the  Graphics routines,
             which in this case is to write  out a message describing the
             Device  that autodetect found and the  Mode.  We have to use
             the str  routine to  convert integers into  strings, as  the
             Graph  text writing  expects a  string as  a  parameter, and
             can't use  the abilities of  write and writeln.   Finally we
             close  the graphics  drivers  with CLOSEGRAPH.  Close  Graph
             releases all memory  assigned by InitGraph and  restores the
             original text mode.

                  Now when you  run the program  it will quickly  display
             the  graphics data,  and jump  back  to text  mode, so  I've
             inserted a delay in before the call to close graph.  You may
             notice  a delay  before loading  graphics  while the  system
             loads the BGI file, in some systems this may be unacceptable
             or  you may  wish to  distribute just  on  EXE file  and not
             include a whole  lot of  BGIs, so Borland  have given you  a
             demo of how to do this in the example file BGILINK.PAS.

                  If you have problems  with this sample file  you should
             check that you have a  graphics capable device, and that the
             BGI files are indeed where you specified them.


             Displaying Pixels
             -----------------

                  O.K. so far you've managed to Display some funny shaped
             text on the screen, Big Deal you say.  Well from here on  in
             this part we will use the program Graph_Test,  to set up the
             graphics device, and close it after use, and in place of the
             above Graphics stuff  (In this case the OUTTEXTs)  we put in
             specialized code.   The next step is  to display a  point on
             the screen, we call one of these a PiXel or Picture Element.

                  As  you   know  different  Display   technologies  have


                                                                        9

             different  Screen resolutions  (Pixels  on  the Screen)  for
             example you fit 320 pixels  across and 200 down in CGA  mode
             5.   In the BGI routines, you can  put a pixel in a location
             that is not  on the screen.  This may seem strange, but when
             you realize  that under EGA you can put  a pixel in the last
             column at column 639 (the first  column is always 0 so 0-639
             = 640 pixels), which would be way of the screen in CGA.  For
             the purposes  of this Article  we'll do most of  our work in
             the range of 0 - 99 columns  and 1 - 99 rows, which will  be
             displayable on all monitors.

                  The  routine  to display  a  pixel  on  the  screen  is
             (Surprise) PutPixel(x,y : Integer; Color:  word) X and Y are
             not  surprisingly Column and  Row coordinates, and  Color is
             the  color of  the pixel.   O.K. so  lets do  some Graphics.
             Insert  the  following  declarations  at  the  beginning  of
             Graph_Test, and the routine in the Graphics stuff section.

             ~ Declarations ~~~~~~~~~~~~~~~~~~~~~~~~
             VAR
               Counter : Integer;
               Color : Word;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               Color := 1;
               For Counter := 0 to 99 do
               begin
                 PutPixel(0      ,Counter,color);
                 PutPixel(99     ,Counter,color);
                 PutPixel(Counter,0      ,color);
                 PutPixel(Counter,99     ,color);
               end;
               PutPixel(50 ,50 ,Color);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  This routine will Firstly  set the variable color  to 1
             (The  first available color, in which  case all devices will
             show a color  distinct from the background color),  which in
             most modes is Dark blue, in  the 320x200 cga modes this will
             be  Green, or Cyan.  The system then counts from 0 to 99 and
             puts a  box on the screen, by plotting  a point in the left,
             right, top and Bottom edge.  To see how it does  this dot by
             dot put  the line DELAY(100) before the end in the FOR loop,
             you will see each dot  being drawn.  Then it will  put a dot
             almost in the middle of the box, depending on the resolution
             of  your display  mode, the  box  could be  anything from  a
             perfect  square to  an  elongated  rectangle,  GRAPH  has  a
             procedure  called  GetAspectRatio  which will  tell  you the
             ratio you may use to draw a perfect square (We'll talk about
             this later on), and various functions and  procedures to ask
             the Graphics device how wide and tall  (in pixels) it is, we
             will discuss these in the next article on Graphs.


                                                                       10

                     Play  with   the  colors  for  your   default  (Auto
             detected) mode,  then try playing  with the  Graphdevice and
             Graph mode, to get the hang of your Graphics device, as  you
             will  need  to know  later  on  about  the  capabilities  of
             your system.  You can also  move the  x,y  position  of  the
             single  pixel, or even draw some simple shapes.

                  An example of  a little function to draw  a shape would
             be to stick this line in the FOR loop.

             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                         
             PutPixel(Counter,50+trunc(sin((counter/100)*2*pi)*20),color)
             ;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  It plots a point for  each x position of counter, based
             on a sin function (A Turbo function  that gives a value on a
             sin curve  (Wave !?!)  between -1 and  1 for  every position
             between 0 and  2*Pi radians).  TRUNC converts  the Sin value
             from  a  Real  into  an  integer  for  PutPixels  Y   value,
             sin((Counter/100)*2*pi) gives  a real  between -1  and 1  as
             (Counter/100) goes from 0 to  almost 1, and we multiply this
             by 20 to  make the wave oscillate between 50-20 and 50+20 to
             put the wave in the middle of the box.


             Lines, Arcs and other Objects
             -----------------------------

                  Drawing a  line is  a bit  slow plotting  a pixel  at a
             time,  so Turbos  GRAPH  unit includes  a  LINE function  so
             firstly  we'll replace  our FOR  Loop  box Drawing  routines
             with;

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetLineStyle(SolidLn,0,NormWidth);
               SetColor(1);
               Line(0,0,0,99);
               Line(0,99,99,99);
               Line(99,99,99,0);
               Line(99,0,0,0);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  You  will also notice that LINE doesn't include a color
             parameter, GRAPH has a routine called SETCOLOR (Which we set
             before we draw the lines) which  defines a color to be  used
             by all line and object  drawing routines.  Graph has another
             surprise  with a routine called SETLINESTYLE which allows us
             to  select the  style, pattern,  and thickness of  the lines


                                                                       11

             we'll  draw,  again  I've  included  that  one  above for  a
             SolidLn, but  you  might like  to  try styles  of  DottedLn,
             CentreLn,  or  DashedLn  and   a  Thickness  of  Thickwidth.
             Pattern is a special value we'll discuss in the next topic.

                     There is  an even  Better  method to  display a  Box
             called RECTANGLE, which  combined the 4 lines  commands, try
             this.

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetLineStyle(SolidLn,0,NormWidth);
               SetColor(1);
               Rectangle(0,0,99,99);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                     Now try  this, it uses three more  line based object
             drawing routines;
             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetLineStyle(SolidLn,0,NormWidth);
               SetColor(1);
               Rectangle(0,0,99,99);
               Circle(50,50,40);
               Arc(50,60,225,315,20);
               Ellipse(40,40,0,360,5,10);
               Ellipse(60,40,0,360,5,10);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  What these routines do is Draw a Circle with the centre
             at  50,50 with  a radius  of  40 pixels  (This routine  uses
             GetAspectRatio to makes as round a circle as  possible), Arc
             draws a  part of a circle with a  centre at 50,60 (10 pixels
             below  the  centre of  the  circle) going  from  225 degrees
             (Unlike the  Trigonometric functions  the Graphics  routines
             represent angles in Degrees, starting from 0 horizontally to
             the right) to 315  degrees with a radius  of 20 pixels,  the
             two  Ellipses  draw  two  identical  squashed  circles  with
             centres 10  pixels either side  of the middle point,  and 10
             pixels above  it, each  ellipse goes from  angle 0  around a
             full circle to 360, and with a x radius of  5 and a Y radius
             of 10.  If this explanation seems a bit obtuse, run the demo
             first and you'll see what I mean <grin>.

                  The  Last  Line  Based Object  drawing  routine  is the
             PolyDraw  routine which will  draw any polygon,  although it
             needs a bit of setting up.   What you have to do is define a
             variable as  an array of  pointType which is a  GRAPH global
             type,  a record  of (x,y)  coordinates.   Then you  fill the
             array  elements with x,y coordinate data  (I often use Graph
             paper to  work out how I'm going to  do a shape), and simply
             call the DrawPoly routine with the number of points, and the
             Shapearray, try  this one which  draws two triangles  on our
             face shape;

             ~ Delcaration ~~~~~~~~~~~~~~~~~~~~~~~~~


                                                                       12

               Triangle : Array[1..4] of PointType;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               Triangle[1].x := 50;
               Triangle[1].y := 85;
               Triangle[2].x := 20;
               Triangle[2].y := 75;
               Triangle[3].x := 20;
               Triangle[3].y := 95;
               Triangle[4].x := 50;
               Triangle[4].y := 85;
               DrawPoly(4, Triangle);
               Triangle[2].x := 80;
               Triangle[3].x := 80;
               DrawPoly(4, Triangle);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             Patterns and fills
             ------------------

                  O.K. from the previous program, add the following lines
             after that last DrawPoly routine;

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetFillStyle(solidFill,Color);
               FloodFill(50,5,Color);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  A fill is a  bit like a color-in that kids  do, it will
             fill an  area with  a color.   Now this one  takes a  bit of
             explaining, firstly SetFillStyle  sets the type of  fill any
             solid routine will use, and the color that it  will color in
             with, in this case it will be a SolidFill, you can fill with
             diagonal  lines  (SlashFill),  or hatchs  (HatchFill),  dots
             (CloseDotFill) or  others, play around with it.   The second
             line calls the  fill, by specifying the x and  y position of
             any point within the area  to fill, and the color that  will
             border the area.

                  If there  are any breaks  in the border then  the flood
             fill  will leak through, try  putting this routine to remove
             one of  the bowties edges  in before the  FloodFill Routine,
             you'll  notice  the  floodfill will  bleed  into  the second
             triangle;

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetColor(0);

             Line(Triangle[2].x,Triangle[2].y,Triangle[3].x,Triangle[3].y
             );
               SetColor(1);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  You can  draw the  polygon and fill  at the  same time,

                                                                       13

             with  a GRAPH routine  called FillPoly, remove  the previous
             routine to  delete  the  edge  of  the  bowtie,  remove  the
             floodfill, and Change  the two DRAWPOLYs into  FILLPOLLY and
             put 
             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetFillStyle(WideDotFill,Color);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             anywhere before both FillPolys and the routines will perform
             a poly  draw AND  a fill  at the  same  time.   You can  use
             FillEllipse in  the same way to draw and fill an ellipse, or
             Bar to draw and fill a rectangle.


             Text and Fonts
             --------------

                  To  draw  text  there are  several  commands  the first
             SetTextStyle loads up BGI files for the Font type (Much like
             initgraph sets up the Device BGI files), sets  the direction
             of the text (Try this next procedure with VertDir instead of
             HorizDir, and set the text  to start at 10,5), and  the size
             of  the  characters.  The  second  Command  OutTextXY(X,Y  :
             Integer;Text  : String) sends  text of the  defined Style to
             the output port at the requested X,Y location.

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetTextStyle(DefaultFont,HorizDir,1);
               OutTextXY(20,5,'Mr Happy');
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  Try  different   commands  such   as  different   fonts
             (TriplexFont, GothicFont), different  sizes (Each fonts text
             will be a different size), and different orientations.

                  One  major  problem  with  Ad  hoc  text  placement  in
             Graphics modes is working out where to put the next line, as
             you probably won't know where the current text  finishes and
             the  next should  begin.    Turbo  provides  two  procedures
             TextHeight and TextWidth for just this problem.  Simply said
             they return the size in pixels  take up by a string.   Let's
             go straight to an example, and I'll show you what I mean.

             Remove  all  the  old graphic  stuff  leaving  only  the Box
             routine, and after drawing the box, add the following;

             ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               SetTextStyle(DefaultFont,HorizDir,1);
               Charheight := TestHeight('M');
               OutTextXY(20,5,'Simple example');
               OutTextXY(20,5+textheight,'of text spaced');
               OutTextXY(20,5+textheight+textheight,'at even heights');
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


                                                                       14

                  As you  see you will  get each new line  starting after
             the  previous   line  has  finished,   regardless  of  font,
             character, or graphics device.


             Summary
             -------

                  Well I hope  I haven't offended too  many sensibilities
             with the  simplistic nature of  the exercises, we  have gone
             over  some  very  basic  Graphic  concepts  here,  that  are
             fundamental to  further understanding  graphic manipulation.
             Next  PNL  I  will be  discussing  Business,  mathematic and
             Scientific Graphics such as Bar, Pie, Scatter, Hi_Lo graphs,
             the graphing of mathematic functions in 2 and 3  dimensions,
             and Fractal representations such as Sierpenski,  Mandlebrot,
             and  Benoit sets.   As  well as  topics, like  windows, Auto
             Scaling graph  axes, and  further discussion  of aspects  of
             text drawing.

             Author
             ------

                  Richard  Morris   is  the   Owner/operator  of   KHIRON
             Software,  in Brisbane AUSTRALIA, a company that specializes
             in  Graphic  Databases  in  Turbo  Pascal  for  Health  care
             professionals,  as well as  providing contract staff  for as
             diverse projects  as  Robotic process  control software,  to
             various   Industry  support   software.  Current   Supported
             Packages  DENTAPAC tm  -  Dental practice  management tools,
             PHYSIOPAC tm - Phyiotherapy management tools, and ORTHOPAC -
             Orthodontic practice management tools.

             References
             -----------

             The Turbo Pascal Reference Guide
             (C)89 Borland Int.

             Advanced Programmer's Guide to the EGA/VGA
             George Sutty/Steve Blair

             Advanced MsDos
             Ray Duncan

             INTER490
             Ralf Brown


                                                                       15

                (C) Copyright 1990, Tansin A. Darcos & Co.  Commercial
                          Reproduction rights are reserved.

                   Introduction to Multiple-Concept Pascal Programs
                                    Paul Robinson

                  Most large or commercial programs  tend to do  a number
             of things.   I was trying to  do a  program that would count
             all the words  in a text  file - which  might be almost  any
             line format,  and produce   an alphabetical  list  of words.
             This meant that I had to do several things:

                  o  Read a  file that  might have Carriage Return 
                    ("CR")  followed by Line  Feed ("LF")  for an
                    end  of line,  LF then  CR, LF  only,   or CR
                    only, or  might be  from one  of those  weird
                    programs that  just generates  "stream ASCII"
                    in which it takes words  until the  line is  
                    full then  at the next space issues a "soft" 
                    carriage  return.   The only  requirement was
                    that  the  file  be   non-coded,  i.e.   that
                    characters  appear as normal character values
                    (Wordstar, for example,  puts a high-bit code
                    on some  words to  use as  paragraph or  line
                    breaks).

                  o  When reading the words, store them in memory.  The
                    program might read a small  file or  it might
                    read a 1/2  million word book, so  the number
                    of  words would  be  indeterminant, and   the
                    word  sizes  would  all be different.

                  o  List each word and the number of times used, in
                    alphabetical order.  The first  qualification
                    precluded  the   use  of   Pascal's  standard
                    READLN/EOLN  construct  to check  for  end of
                    line.   This meant I'd have  to read the file
                    in  on a character  by character basis.   The
                    second provision  was because,  with as  much
                    memory as is on a PC, there is really no need
                    - unless  you get  a huge file - to  use disk
                    space  to store word  counts (also because of
                    something I was trying to do that I wanted to
                    use    a  in-memory  word  list).  The  third
                    provision  was    what I    had  wanted:   an
                    alphabetical word list.  (If I had  been more
                    concerned with the  number of  uses, I  would
                    have had the  words listed in order by number
                    of usages rather  than alphabetically). These
                    provisions  made  the   choice  of    using a
                    linked list quite obvious. The questions that
                    came  up included what type of linked list to


                                                               16

                    use and  how to implement  it.  That  will be
                    discussed below.



                           Understanding Pointer Variables
                                    Paul Robinson

                  One of  the things  I needed to do one day was read one
             or more  disk files and  create an alphabetized list  of the
             words in  each file,  for something I  was working  on.    I
             wanted to   store  the list  of words  used in  the file  in
             memory because I did not want to spend a lot of time reading
             and  writing   the disk in  addition to  all the  disk reads
             being used to  read the original file(s).   Since the number
             of words   to  be   stored  would   vary, storing   them  in
             arrays might either not provide enough memory space or waste
             a lot of memory.

                  Pascal (and   other languages)   have a   capability in
             which a  variable can point  to  a  block  of storage   that
             only   exists after   the program explicitly requests  to be
             issued that storage.  Arrays and variables  are created (for
             the main program) when it is executed,  and exist  until the
             program  ends.     This  special   storage    is   allocated
             dynamically   if,  as   and when  needed, by the  programmer
             specifically asking  to  be   given   a   block   of    this
             memory.    The programmer  can   also give back  this memory
             when finished using it, and perhaps even re-use it later on.

                  To access this dynamic memory, the programmer creates a
             class   of variable  called a   pointer.    A pointer   is a
             variable that describes  a memory location indirectly.   Let
             me explain that a little closer.

                  An ordinary variable  exists at a specific  location in
             memory, and  contains a  value  such  as   a number,   or  a
             character (or  two). This is an ordinary, direct access to a
             value.  A pointer, however, goes  one step  further, in that
             it contains not a value, but the address of a value.

                  For example, let me examine a record:

                  TYPE
                     maxstring = STRING[255];

                     tokp = ^tok ;
                     tok  = RECORD
                                next  : tokp ;
                                count : LONGINT ;
                                token : maxstring;
                            END ;
                                                                       17

                  The  first    item  indicates    that  the   identifier
             'maxstring'  is a  string  of  the maximum  size.   Next,  I
             indicate that the  identifier 'tokp' is a pointer to (that's
             what  the  ^ indicates: "Pointer to")  the identifier 'tok'.
             But tok is  not defined until after  tokp.  This is  the one
             exception to  the rule  in Pascal that  everything   must be
             defined  before use; pointers may refer to identifiers which
             are not defined when the pointer is.

                  Tok is  a record beginning  with a 'next'  field, which
             since we know tokp is a pointer,  that 'next'  is  a pointer
             to another record of the same type.  The 'count' variable is
             a long integer,  and 'token' is a string  of maximum length.
             Why is   there yet   another pointer   when one   is already
             defined?   The 'next' field  is what is called  a 'traverse'
             pointer.  In order to  find records  in  a linked list,  you
             have  to be able to follow ('traverse') the list in whatever
             order it is maintained.  The  way to  do this  is to  change
             the   pointer that  looks at   a  record   from the  current
             record to the  next one in the list.   This would   be  done
             by   assigning  the  'next'  value   to  the  pointer  which
             is referencing this   record.   Some  pointer  records  will
             also carry a 'back' or 'prev'  pointer to go backward in the
             list.   Note   that all  this has  done is  create a  set of
             names so  that we can use this record - or the tokp pointer-
             in  the program, but we  cannot yet use  them because we did
             not define variables that do, like this:

                  VAR
                       name:maxstring;
                       T,t1: tokp;

                  We  still   can't  access   the   memory,  because  the
             pointers do not really contain the  data, they  contain only
             the address  of the  data.    We have to allocate the  space
             for  that data   in order to be able to  access them.  There
             are  two ways  that a programmer  can be   given access   to
             dynamic   memory.    Both  require the    programmer pass  a
             pointer  to  a  procedure  that  allocates  memory  to  that
             pointer.

                  The first method is the NEW procedure, which is  called
             in the form

                       NEW(T);

             however, in  our instance,  allocating 255 bytes  for   each
             word  probably  wastes memory, especially  since  each  word
             probably is no larger than 20 characters. There are two ways
             around this:  pick  a  maximum and  assume no   word will be
             larger  than that,  or size  the  records to  fit, which  is
             option 2.

                                                                       18

                  The second  method involves   knowing what  the program
             does; since I will know  that 'name' will contain the string
             to be stored in the  'token' field of the tok  record.   So,
             I could  allocate a  specific sized block  of memory  with a
             special procedure available  in Turbo Pascal called  GETMEM,
             and it  works like this:

                       GETMEM(T,LENGTH(NAME)+10);

             where  the first  argument is  the pointer  to use,  and the
             second argument is the amount of memory in bytes to allocate
             to the pointer.  The  LENGTH(NAME) value gives us the actual
             size of the string, the  +10 is because the pointer takes  4
             bytes, the longint  takes 4 bytes, the length  of the string
             adds  one byte, and I want  the next allocation to come on a
             word boundary.

                  In either the  NEW or GETMEM  options, the variable  is
             now  ready for  use. We  can  access it  by referencing  the
             pointer followed by a fieldname:

                       T^.Count := 1;      or   T^.Token := Name;
                       T^.Token := Name;        T^.Count := 1;

                  Also, it is  usually best to   ensure that   any unused
             or traverse pointers are cleared, so we should also say:

                       T^.Next := NIL;

             (NIL is a special value which indicates a pointer  is not in
             use).

                  If we  later  add  another record, we have  to keep the
             old one, so we might do something like this:

                       T1 := T;
                       WHILE T1^.Next <> NIL DO
                            T1 := T1^.NEXT;
                       GETMEM(T1^.Next,LENGTH(Name)+10);
                       T1 := T1^.Next;

                  (I am trying to simplify this  example.    Things  like
             alphabetizing the  entries, checking  for duplicates,  etc.,
             has been omitted.)

                  When finished with the memory pointed to by  a pointer,
             you release it back to the system.  On some systems they use
             MARK and  RELEASE, in which  you create a mark  pointer, and
             store the current memory list in the marked pointer with

                       MARK(markpointer);


                                                                       19

             then when you don't need the memory any more, you get rid of
             it with

                       RELEASE(markpointer);

                  This cancels   all usage  of  the  NEW procedure   done
             after the MARK procedure call.  Any pointers allocated after
             that MARK are now  invalid.    Some systems do a  better job
             at allocating memory, in which you use the NEW procedure (or
             on Turbo Pascal, you  can   also  use  GETMEM),   then  when
             you   don't  need a particular piece  of memory, you can use
             DISPOSE (if  you  called  NEW) or  FREEMEM  (if  you  called
             GETMEM).  You would use them like this:

                       NEW(T1);

                       ...

                       DISPOSE(T1);  


                         (* OR *)

                       GETMEM(T1,LENGTH(NAME)+10);

                       ...

                       FREEMEM(T1,LENGTH(NAME)+10);

                  Note: if  a program is  exiting, it does  not have   to
             release  the memory it allocated; the system will do so  for
             it.

                  Pointers do   not have  to  point to records.   In some
             systems,  pointers  are used  as  a  means to  simulate  the
             PEEK/POKE  function   from   BASIC,   as   in the  following
             example:

                  PP = ^CHAR;
                  VAR 
                       P: PP;
                       I: array[1..2] of integer absolute P;
                       Colr,Mono,Both:boolean;

                  BEGIN
                       I[2] := $B800;
                       I[1] := 0;
                       Colr := FALSE;
                       Mono := FALSE;
                       P^ := 'A';
                       IF P^ = 'A' THEN Colr := TRUE;
                       I[2] := $B000;


                                                                       20

                       I[1] := 0;
                       P^ := 'A';
                       IF P^ = 'A' THEN Mono := TRUE;
                       IF Colr and Mono THEN Both := True;
                       ...


                  This little  program segment checks  to see if  a color
             adapter is installed, then it  checks to see if a monochrome
             adapter  is  installed, by   checking the physical addresses
             to see   if there is memory in their  spaces.  This piece of
             code  is  here to  show that  a   pointer   can   point   to
             something   other   than a record.    Turbo Pascal   has the
             MemW[] and Mem[] arrays, but some compilers do not, and this
             is one way it may be simulated.

                             Understanding A Linked List
                                    Paul Robinson


                  Going back  to my original idea,   I wanted   to create
             an  alphabetized word  list.    I  wanted  merely  to   do a
             single linked list where each item points to the next one in
             memory.   If I  checked the words  first, I  could store the
             table  automatically  in    alphabetical  order    and  thus
             generating the  table would be trivial.

                  Almost all  the books and  articles  I  see  deal  only
             with double-linked  lists, where  there is   a pointer  to a
             previous record,  and a  pointer to a record that is next in
             line.   This  would be   overcomplicated  for   something as
             simple  as    just  generating    a  list    of  words    in
             alphabetical  order. I  didn't want  frequency  counts in  a
             binary tree, I just wanted a  list of words - and it  seemed
             trivial.

                  I have   used Pascal  for over 5  years and doing  this
             little exercise taught  me something about the  language and
             how  it works.  It also taught me   a little about the way I
             was thinking about certain concepts.

                  Every time I started on the means to store the table, I
             kept  either losing  items or  not storing the  new entries.
             The standard  method for  working with a  linked list  is to
             have a start pointer, and additionally  to have a 'traverse'
             pointer,  as described above.   You  follow  down  the links
             until you  find the entry you  want or until you run out  of
             items.

                  One thing I had misunderstood  was that when you have a
             second  pointer,  the  pointer  is  not  the  data,  and two
             pointers  pointing to    the same   place  are not  the same


                                                                       21

             thing.  This means, if you have

                       var
                            T,T1:Tokp;
                            name:maxstring;

                       begin
                            NEW(T);
                            T1 := T;

                  That any  change to  T1 will not have any effect on the
             system, unless you do something to one of the fields pointed
             to by t1.  Remember, just   because T and T1  point  to  the
             same  place do not  make them the  same thing.   And that is
             what caused me so much trouble.

                  In  the enclosed  program (WORDCOUNT.PAS)  is the  word
             count program I wrote. If you notice the section where T2 is
             allocated then the values are all moved:

                         IF t1^.token > tab.sym THEN
                            BEGIN
                                 new(t2);
                                 tab.nwords := tab.nwords+1;
                                 t2^.count := t1^.count;
                                 t2^.token := t1^.token;
                                 t2^.next  := t1^.next;
                                 t1^.count := 1;
                                 t1^.token := tab.sym;
                                 t1^.next  := t2;
                            END;

                  Merely assigning  values to   T2 would not have worked,
             because T2  is local to  that procedure.   The only   way to
             get the  values to  stick is  to use the existing values and
             attach these.

                  This  program sample  was  added  to  fix  two  glaring
             deficiencies:  the  lack of  an  explanation in  the  use of
             single  linked   lists,  and   one   mistake  I was  making,
             confusing  the reference pointer with the data.  My guess is
             that if I am doing this, others are also.

                                                                       22

                                    For Beginners
                                    By Bob Gowans
              
                  Having discussed important features of programming such
             as design, input and output statements in Pascal, the use of
             relevant  comments  and  programming   style  we  can   give
             ourselves  a self  congratulatory pat  on the back,   but...
             before  you  can  achieve the  ultimate  goal,  writing that
             elusive master program, complete with pop  up menus and user
             friendly screens you  must learn to master the  art of being
             selectively  repetitive in  your programming  technique. The
             computer is  really worth  it's weight in  gold when  it can
             carry out,  on our behalf,  long and boring  tasks producing
             results at  amazing speed.  For example  a payroll  program,
             used by a large company, has to calculate net pay of each of
             it's employees  - this is essentially a repetitive task. The
             same  program may  base it's  calculations  on variable  tax
             rates,  depending  on gross  pay. Thus,  the program  has to
             select  a  course of action  for certain circumstances. Lets
             take the issue of selection and repetition and treating each
             as a separate  concept briefly consider their use in program
             design.
              
             Selection
             =========
              
                  When we are faced with a problem we usually embark on a
             course of action arrived at through a mental  process called
             decision making.  Decisions are   an important  part of  our
             everyday lives, we  make countless decisions  each day   and
             branch out along different courses of action to achieve what
             we  want. From  many  different  alternatives  we  SELECT  a
             particular course of action.  IF I  get home on time tonight
             THEN  I will  watch the game  on T.V.  ELSE I will  read PNL
             might  be a  simplified way  to express  a form  of decision
             making. In terms  of program  design decision  making is  an
             important concept  and one way   to deal  with this is  very
             similar  to the human decision example given above. We would
             express this as follows :-
              
               if ( test of truth of a statement)
               then
                  carry out a set of instructions when the test is true
               else
                  carry out a set of instructions when the test is false
               ifend
              
                  For  example,  what  follows   is  a  design   language
             implementation  of a simple  selection statement which tests
             whether a person is married or  not and writes out a message
             accordingly.


                                                                       23

              
                  1.1 if married = true
                  1.2 then
                  1.3  write out 'congratulations'
                  1.4 else
                  1.5  write out 'keep trying'
                  1.6 ifend
             If   the   person   is   married   he   gets   the   message
             'congratulations', if not  then is presented with  the 'keep
             trying'  message. Remember  the position  of  the words  if,
             then, else and ifend and note the indentation of the actions
             to be performed.
              
              
             Repetition
             ==========
              
                  Repetitive execution of program statements involves the
             use  of loops. A conditional loop  is controlled ie. started
             or  finished, by  simple  or  complex  conditions.There  are
             several  ways in which loops  can be implemented , initially
             we   will   deal   with   a  type   that   tests   for   the
             stopping/starting condition at  the beginning of a  loop. At
             this stage we will not be dealing with unconditional loops,
             this type of loop will execute a predetermined number of
             statements, however  it is as  well that you are  aware that
             they exist. If  the loop is to be executed while a condition
             is  true, then  the loop  control is  written as  LOOP WHILE
             condition.  The loop will take the following form :-
              
             loop test   (ie. loop while condition is true.)
                statement 1
                statement 2
                etc...
             loopend
              
                  It is very  important to observe  two  rules when using
             conditional  loops.  The  first rule  is  to  initialize any
             variables, prior to entering the loop, which will be updated
             within  the  loop. The  second  rule  is to  initialize  any
             variables used in the loop test ( ie. the  condition ) prior
             to entering  the loop. To illustrate the  importance of this
             lets consider the following  design which repetitively reads
             in a real number from the keyboard and sums the total of all
             the numbers entered and outputs the final total.
              
             1 initialize variables updated in the loop
             2 read in first number
             3 loop while number is positive
             4   update total
             5   read in next number
             6 loopend


                                                                       24

             7 write out total
              
             Note that total  is a variable that is consistently updated,
             within  the loop  and that  number is  the variable  used to
             determine the condition  of the loop ( ie.  continue or stop
             ). This information can be tabulated as follows :-
              
             Identifier     Description                    Type
             =========      ===========                    =====
              
             number         number input                   real variable
              
             total          accumulated total of
                            numbers input                  real variable
              
             Following the top-down methodology lets individually  refine
             the steps given above.
              
             Steps 2,4,5 and 7 are easy :-
              
             2.1 read in number
              
             4.1 set total to total + number
              
             5.1 read in number
              
             7.1 write out 'The total sum of all the numbers is ',total.
              
             Lets not forget to include relevant input prompts. Steps 2.1
             and 5.1 will require further refinement.
              
             2.1 write out 'Enter any positive number (negative number to
             quit)'
             2.2 read in number
              
             5.1 write out 'Enter any positive number (negative number to
             end)'
             5.2 read in number
              
              
                  The two  steps that read  in number at 2.2  and 5.2 are
             required because the initial condition of the loop at step 3
             depends  on the value of  number read in  at step 2.2  -  we
             have thus  met the  requirement of loop  rule #2  by setting
             number to it's initial value. Once the loop has been entered
             control  passes through steps  4.1,5.1,5.2 until at  step 6,
             control passes back to step 3. The condition of the  loop is
             tested again and  it's execution depends on the data entered
             at step  5.2. The two  input statements are necessary  - the
             first to test  the loop initially and the  second to provide
             subsequent test of the loop condition.
           

                                                                       25

                  Refining  step  three  requires  us  to  see  that  the
             condition  is true  as long  as  number is  positive. So  if
             number is  entered as  a negative  the loop will  terminate.
             This is a  simple condition and can be  expressed as follows
             :-
              
             3.1 loop while number >= 0
              
                  If  you are unsure  what the condition  operators mean,
             refer to  the table under  the section IMPLEMENTATION  OF IF
             THEN ELSE which is further on in the article.
              
                  The  stopping data  item (  ie a  negative number  ) is
             known  as a  SENTINEL VALUE.  If the  number variable  has a
             negative value the  loop condition is not true  and the loop
             is not executed. In this case  the execution of the loop  is
             controlled by user input.
              
                  To  further  refine  step  1  we  require  to know  the
             variables that will  be updated in the loop.  Both total and
             number are updated within the loop but only total is updated
             by assignment ( number is updated as being input ), so total
             requires  to be initialized  before being used  in the loop.
             This would necessitate  setting total to zero.  The complete
             design is given below :
              
             1.1 set total to 0
             2.1 write out 'Enter any positive number (negative number to
             quit)'
             2.2 read in number
             3.1 loop while number >= 0
             4.1    set total to total + number
             5.1       write  out 'Enter  any  positive number  (negative
             quits)'
             5.2    read in number
             6   loopend
             7.1 write out 'The total sum of all the numbers is ',total.
              
                  We have dealt, briefly with a method of selection and a
             method  of  repetition and  program  language  methods which
             allow these concepts  are called CONTROL STRUCTURES.  As you
             guessed there are other control structures but we will leave
             those for another  article. Lets go on to  implement the two
             control structures we have discussed in Pascal.
              
              
             IMPLEMENTATION OF IF THEN ELSE
             ==============================
              
                  The if statements of the design are written, in Pascal,
             similarly  except you  do  not  need  to include  the  ifend
             statement.



                                                                       26

              
             if condition
             then
                begin
                    statement 1;
                    statement 2;
                    ........ etc
                end
             else
                begin
                   statement 1;
                   statement 2;
                   ......... etc
                end;
              
                  Note that  the Pascal reserved words BEGIN and END mark
             the start  and finish  of multiple  statements. If  there is
             only one statement to be executed then the BEGIN and END may
             be excluded. Lets discuss the  implementation of  our design
             concerning the married or single survey. I have added to the
             basic design  by  stipulating an  interactive  program  that
             prompts  the user to respond 'y' or  'n' to a question. This
             introduces us  to  the data  structure CHAR.  The data  type
             char, provided by Pascal, enables us to manipulate character
             sets including  upper-case  letters,  the  digits  and  some
             punctuation marks and  mathematical symbols.  When the  user
             inputs a  character -  in this case  either 'y' or  'n', the
             character input is  assigned to the char  variable RESPONSE.
             By using  the if...  then... else...  control structure  the
             program   determines  what   the   user  input;   the  users
             response.If it is 'y' then the a message is output, if it is
             'n'  then a different  message is  output. Please  note that
             when  testing  for  characters they  should  be  included in
             single  quotation  marks.  When  inputting  characters  they
             should be written as they are - without quotation marks.
              
             program ismarried;
              
             var
              
                response : char;
              
             begin
               write('Are you married ( enter y or n ) > ');
               read(response);
               if response = 'y' {Condition test. Note
                                  test for character uses ''}
                  then
                     writeln('You lucky person')
                  else
                     writeln('What''s your phone number?'); {Ifend}
                  writeln;
                                                                       27

             end.
              
                  A  condition is  a test  which  is carried  out on  the
             values of  variables to  compare them in  some way.  As your
             knowledge  of  Pascal  evolves their  use  will  become more
             apparent to you.  For now lets  summarize the various  tests
             for conditions in a table.  

             Operator                         Condition
             ========                         =========
              
              >                               is greater than
              <                               is less than
              =                               is equal to
              <>                              is not equal to
              >=                              is greater than or equal to
              <=                              is less than or equal to
              
                  You can probably  see, that comparison operators  are a
             powerful programming  tool that  can be used  to test  for a
             variety of  conditions.  Now try  the  following  exercises.
             Solutions will be given at the end of the article.
              
              
             Ex1
             ____________________________________________________________
              
                  Devise a  design to read  in two numbers,  compare them
             and print out the two numbers in ascending order.
              
              
             Ex2
              
              
                  Length, width  and  height are  integer  variables  and
             woman,  man  and  child are  char  variables.  Which of  the
             following are valid conditions?

             Solutions are given at end of article.
              
             (a) length > 24
             (b) woman = 'Wendy'
             (c) child = 5
             (d) height = 63
             (e) man >= 70
             (f) width = '6'
             (g) child = 'C'


                                                                       28

             IMPLEMENTATION OF THE WHILE DO LOOP
             ===================================
              
                  While loops are implemented in Pascal as given below
              
             while condition do 
                  begin
                     statement1;
                     statement2;
                     .........etc
                  end;
              
                  The statements  to be executed repeatedly are separated
             by semicolons and if there  is only one statement within the
             loop  the keywords BEGIN and END may be exclude. Now lets go
             back  to  our  design from  the  REPETITION  section  in the
             article and implement this in Pascal.
              
             program addup;
             { Adds up  and prints total, to the  screen, of real numbers
             input by the user }
             var
                total,number : real;
              
             begin
                total := 0; {Initialize variables updated in loop}
                write('Enter a  positive number (negative number to exit)
             > ');
                readln(number);
                while number >= 0 do { start of loop }
                   begin
                     total := total + number;
                     writeln;
                     write('Enter a positive # (neg. # to exit) > ');
                     readln(number)
                   end;{ of while do loop }
                writeln;
                writeln('The total sum of numbers entered is ',total:5:2)
             end.
              
                  As you can see the actual implementation  of the design
             into Pascal was  fairly straightforward, the brain  work was
             required at the design stage.  So while you are in  the mood
             try out the following exercise :-
              
             Ex3
              
              
                  Design a program  that will read in the ages of all the
             participants,  the program will  keep a  count of  the total
             amount of users and will print out  the maximum age plus the
             total amount of users. Hint - do not forget the sentinel.

                                                                       29

              
                  Before  I give the solutions to the exercises I thought
             I would include this useful Turbo Pascal routine that checks
             the amount  of space available  on a default hard  disk. The
             routine is  not really aimed  at beginners but gives  you an
             insight into the power of Turbo Pascal and it's control over
             DOS. To more experienced users, feel free to modify the code
             to suit your own needs.
              
             program HDcheck;
              
             uses crt,dos;
              
             var
               i : integer;
               totalspace,usedspace,freespace : real;
              
             begin
                clrscr;
                writeln;
                totalspace := disksize(0)/1000000;
                writeln('Total disk space = ',totalspace:5:2,' MBytes');
                writeln;
                usedspace := (disksize(0) - diskfree(0))/1000000;
                writeln('Disk space used  = ',usedspace:5:2,' MBytes');
                writeln;
                freespace := diskfree(0)/1000000;
                writeln('Space free       = ',freespace:5:2,' MBytes');
                for i := 1 to 15 do
                writeln;
                writeln('HDCheck by B.Gowans');
                writeln;
                writeln('Press enter to continue');
                readln;
                clrscr
             end.
              
                  The use of control  statements such as IF...THEN...ELSE
             and WHILE DO will greatly enhance your programming abilities
             and  this  is  just  the start  of  the  control  structures
             available  to  Pascal.  Practice using  these  structures by
             following  the  examples found  in  the text  books  and get
             comfortable in using them. Here are the solutions to the
             exercises
              
             Ex1 :
              
             1 initialize variables
             2 compare the numbers
             3 write out numbers in order
              
             1.1 read in number1


                                                                       30

             1.2 read in number2
             2.1 if number1 > number2
             2.2 then
             2.3   write out number1
             2.4   write out number2
             2.5 else
             2.6   write out number2
             2.7   write out number1
             2.8 ifend
              
              
              
             Ex2 :
              
             (a) valid
             (b) invalid - variable is of type char and not string.
             (c) invalid - variable is of type char and not integer.
             (d) valid
             (e) invalid - for same reasons as (c).
             (f) invalid - width is integer variable and not char.
             (g) valid.
              
             Ex3 :
              
             1. initialize variables
             2. loop while users to be processed
             3.   process age
             4.   process count
             5. loopend
             6. write out count, maxage
              
             Further refinement :-
              
                1.1  set count to 0
                1.2  set max to 0
              1.3.1  write out 'Please enter age ( enter -1 to quit )'
              1.3.2  read in age
                2.1  loop while age < > -1
                3.1     if age > max
                3.2     then
                3.3        set max to age
                3.4     else
                3.5        { do nothing }
                3.6     ifend
                4.1     set count to count + 1
                4.2     write out 'Please enter age ( enter -1 to quit )'
                4.3     read in age
                  5     loopend
                6.1     write out 'The maximum age was ',maxage
                6.2     write out 'Out of a total of ',count,' people.'
              
             The implementation in Pascal follows - please note there may

                                                                       31

             be small  changes in the  implementation which does  not affect
             the overall design.
              
             program age_survey;
              
             var
              
             age : integer;
             maxage : integer;
             count : integer;
              
             begin
                write('Enter age to nearest year ( -1 to quit ) > ');
                readln(age);
                count :=  0;
                maxage := 0;
                while age <> -1 do { start loop, stop with age = -1 }
                   begin
                     if age > maxage { if start }
                     then
                        maxage := age
                     else
               { do nothing };{no other branching is necessary so ifend}
                     count := count + 1;
                     writeln;
                     write('Enter age to nearest year (-1 to quit ) > ');
                     readln(age)
                   end;
                   writeln;
                   writeln('The greatest age was ',maxage,' years');
                   writeln;
                   writeln('The total number surveyed was ',count)
             end.
              
                  All  the code  in  this article  has  been written  and
             compiled  using Turbo Pascal v4. The executable code was run
             on an Opus  PC 5 under DOS  3.3. There is no  guarantee that
             the  same   code  will   run  under   your  own   particular
             configuration.

                                                                       32

                                  Recursion is Easy
                                    By Chris Burke

                  Recursion and pointers seem to be the two subjects that
             cause beginners  in pascal  the most  heartache. This  brief
             article aims to delve into the subject of recursion.

             Introduction

                  Imagine you (Alfred) are talking to Bob, when Christine
             walks  up and rudely  interrupts and starts  talking to you.
             You put  up with it and  talk to Christine (she  is prettier
             than  Bob anyway).  While  talking  to  Christine,  her  mum
             (Daphne) wants  a bit of a chat -  you being the wise person
             you are  (and liking  Christine so much)  decide to  talk to
             Daphne,  just  after  finishing  your  chat  and  commencing
             conversing  with Christine, the telephone rings - you answer
             and  (OH  NO!!) it  is Elaine  wanting to  go to  the movies
             tonight, you quickly say sure no problems see you  at 8, see
             you then,  bye and  continue talking to  Christine. After  a
             little while  Christine leaves  and you  restart talking  to
             Bob.

             So, What have you been doing - well
             1. You have been two-timing, and deserve all you get.
             2. You have been using your 'Talk' function recursively.

             i.e.
               Talk(Bob)
                Talk(Christine)
                 Talk(Daphne)
                Return to Talk(Christine)
                 Talk(Elaine)
                Return to Talk(Christine)
               Return to Talk(Bob)

                  So now that you understand  a bit about the concepts of
             recursion  lets go onto  more computer oriented  problems of
             recursion. 

                  One  of the most  common examples  of recursion  is the
             factorial program -  as it gets quoted so  often I shall use
             the  example here.  For  those  not  familiar  with  what  a
             factorial is - here is an explanation :

                  The  factorial  of  a  positive  number  (0,1,2...)  is
             defined as follows :

               factorial of N = N*(N-1)*(N-2)....*1
               factorial  of 0  = 1  (by definition  - i.e.  for no  real
             reason)


                                                                       33

             (For  those with  a  little curiosity,  there  is a  related
             function called the  gamma function which works  on negative
             numbers and non-integers.)

             The factorial is represented using the ! symbol

               i.e. 12! represents the factorial of 12

                  The first way the programmer would  go about defining a
             function to calculate the factorial is as follows :

               function factorial(N:longint):longint;
               var
                Count,Temp:longint;
               begin
                Temp:=1;
                for Count:=1 to N do
                  Temp:=Temp*Count;
                Factorial:=Temp;
               end;

             which would in effect for N=5 calculate the following

                 factorial(N) = 1*2*3*4*5

             which adheres to the formula above.


             The Quantum Leap

                  The  quantum leap  in thought  is to  realize that  the
             above formula:

                N!=N*(N-1)*(N-2)*(N-3)...*1 can be written differently.

             Lets take an example, say 5!.

                5!=5*(5-1)*(5-2)*(5-3)*(5-4)

             or    =5*   4  *   3  *   2  *   1   BUT LOOK!! this  can be
             written

                  =5*   4!
             and
                4!=4*3*2*1 = 4*3!    AND SO ON.....

             which means the original formula can be written as

                N!=N*(N-1)!   -  This is the mathematical equivalent of
                                 recursion.

             converting this to pascal is a fairly simple step :

                                                                       34

             function factorial(N:longint):longint;
             begin
               factorial:=N*factorial(N-1)
             end;

             EASY - just a straight implementation in pascal....

                  The only thing left to do is to implement what is known
             as  an  exit condition  - or  a termination  condition, this
             tells  the above  factorial  function when  to stop  what is
             currently an infinite loop, the easiest way to do this is to
             realize that factorial(0)=1  as defined by our  mathematical
             gurus. The modified code is :

             function factorial(N:longint):longint;
             begin
               if N=0 then factorial:=1
                      else factorial:=N*factorial(N-1)
             end;

                  This  is where the IDE  environment in the turbo pascal
             compiler  comes  in  handy.  Write  a  little  program  that
             includes the above function as follows :

             program TestRecursion;
             function factorial(N:longint):longint;
             begin
               if N=0 then factorial:=1
                      else factorial:=N*factorial(N-1)
             end;
             begin
              writeln('Factorial 5=',factorial(5));
              writeln('Factorial 0=',factorial(0));
             end.

                  Try  tracing through this  code remembering to  use the
             'step  over' on the 'begin'  and the 'step  into' on the two
             writeln  statements.  After  a little  playing  and  placing
             watches on N.  (Don't forget  to put Local Symbols and Debug
             Information on in  the options). By now  recursion should be
             somewhat more obvious.

             Something A Little More Useful

                  This subject may be of a little more interest, but as I
             have  always found -  the best way of  learning is by doing,
             and when you have it working you will be far more satisfied.

                  The following  hints should  get you on  your way  to a
             routine  which does some  function MYFUNC  on every  file on
             your hard disk - in every directory on your hard drive.

                                                                       35

             In english here is what you would do :

             1.  Write a  routine which does  MYFUNC on  every file  in a
             specified
             directory something like the following :

                procedure DoMyFuncHere(D:Pathstring);
                var
                 F:FileString;
                begin
                 F:=GetFirstName; (* Remember : *)
                 while F is valid do (* we want all directories
                                        and files               *)
                 begin
                   MYFUNC(D+F);
                   F:=GetNextName;
                 end;
                end;

              test this procedure out and see if it works - OK

             2. Modify this  routine so that it  calls itself recursively
             when there is a subdirectory  (remember - don't get  worried
             by the fact that the routine is calling itself)

               { Ed. Note: Semi-Pascal algorithm }

             |   procedure DoMyFuncHere(D:Pathstring);
             |   var
             |    F:FileString;
             |
             |   begin
             |    F:=GetFirstName; (* Remember : *)
             |     while F  is valid do   (* we want all  directories and
             files *)
             |    begin
             |      if (F='.') or (F='..') then
             |                                                           
             DontGoHereThereIsProblemsIfYouDo;
             |      else if F_IsADirectory then
             |                            DoMyFuncHere(D+F)
             |      else MYFUNC(D+F);
             |      F:=GetNextName;
             |    end;
             |   end;

               { Ed. Note: Actual Pascal algorithm }
             ~program test;
             ~uses crt,dos;
             ~
             ~  Procedure MyFunc (FileRec : SearchRec);
             ~  begin
             ~        Writeln(FileRec.Name);
             ~  end;
             ~
                                                                       36

             ~  procedure DoMyFuncHere(D:Pathstr);
             ~  var
             ~  SR : SearchRec;
             ~
             ~  begin
             ~    FindFirst(D+'*.*',Directory+Archive,SR);
             ~    while DosError = 0 do
             ~    begin
             ~      if (SR.Name <> '.') AND (SR.Name <> '..') then
             ~        If (SR.Attr AND Directory) > 0 then
             ~          DoMyFuncHere(SR)
             ~        else
             ~          MYFUNC(D+SR.NAME);
             ~      FindNext(SR);
             ~    end;
             ~  end;
             ~
             ~begin
             ~  DoMyFuncHere('C:\');
             ~end.

             Try this out by calling DoMyFuncHere('C:\');
             I  am sure you can put your  imagination to other  uses for
             such a recursive directory engine, ie: finding and deleting
             ALL  BAK  files  on a drive,   or  counting  the  size   of
             subdirectories, you can modify the search criterion in  the
             FINDFIRST line.

             A BIT OF EXPLAINING
             ------------------
             Imagine a simple directory like this,

               COMMAND.COM     1 calls MYFUNC
               AUTOEXEC.BAT    1 calls MYFUNC
               <DOS>           1 calls DoMyFuncHere - recursively
                 <.>            2 skips
                 <..>           2 skips
                 FDISK.COM      2 calls MYFUNC
                 DEBUG.COM      2 calls MYFUNC
                                2 returns from second level
               CONFIG.SYS      1 calls MYFUNC
               <UTILS>         1 calls DoMyFuncHere - recursively
                 <.>            2 skips
                 <..>           2 skips
                 LIST.COM       2 calls MYFUNC
                 <NU>           2 calls DoMyFuncHere - recursively
                   <.>           3 skips
                   <..>          3 skips
                   SI.EXE        3 calls MYFUNC
                                 3 returns from third level
                                                                       37

                 4EDIT.EXE      2 calls MYFUNC
                                2 returns from second level
               4DOS.COM        1 calls MYFUNC
                               1 returns and exits to main program

                  By  following the above (the number represents how deep
             you have gone)  you should  be able  to see  how simple  the
             program to look at every file on your hard disk is.

             If you want any more assistance on recursion see the section
             above called 'A BIT OF EXPLAINING' otherwise continue to the
             conclusion.

             Conclusion

                  I hope that  this description of recursion  will answer
             your questions on  recursion, if you have  any questions for
             me then I have a point called 'Mindware' fidonet 3:640/305.1

                                                     Christopher Burke
                                                     Brisbane, Queensland
                                                     AUSTRALIA


                  Chris Burke is owner/operator of a contract Programming
             company called Mindware in Brisbane, Australia.  He programs
             commercially using various languages  including Turbo Pascal
             from  version 2.0 through to version 5.5 professional (Using
             Object Professional), Assembler, and Clarion.
                  He runs a point Fidonet system, and can be contacted at
             3:640/305.1.


                                                                         38

                                      Conclusion

               There  are a  couple things  I'd  like to  point about  some
          future issues.  Bob Gowans will,  of course, continue  to produce
          his column, which has become incredibly popular. Richard is going
          to give us quite bit of stuff on graphics in Pascal, so that will
          also  be a  regular contribution.  I  will be  starting a  series
          pretty soon  on doing large  projects. I am  just finishing  up a
          large project that  involved 5 other programmers and  quite a bit
          of design work before the  implementation. I'd like to go  over a
          lot  of the stuff we did. This  alone should take several issues,
          but I  think you will find  it very interesting. The  code alone,
          because it is  so vast, will be broken up into several issues and
          each unit will be covered alone and then the final integration of
          the entire project will be examined.

               I feel bad  that I can't seem  to get the newsletter  out as
          often as I  would like, but  like many of you,  I have to  set my
          priorities, one  of them, earning  a living.  Hopefully you  will
          forgive me  for this. All I can do is  make a promise that I will
          try my best to get each issue out as soon as possible. 

               I would also like  to ask, as I do in  every issue, that you
          try  to find the  time to send  in some of  your own material for
          inclusion in the  newsletter. Without user contributions,  I just
          can't  keep this going. They  have been good  lately, but I could
          handle  a  few  more.  So,  please, if  you  don't  feel  you can
          contribute, try to find friends that can. Try to get them to send
          in stuff they've done.

               One last word  on the distribution list. I  keep quite a bit
          of the updates in  a directory which I search  at the end of  the
          month to make updates to the distribution list. Several days ago,
          because of a strange problem, that directory, almost exclusively,
          was  completely  wiped  out.  I  have been  unable  to  make  any
          corrections  to  the  distribution   list.  If  you  sent   in  a
          correction, or addition, please send me the information  again so
          that  I   can  make   those  corrections.  I'm   sorry  for   any
          inconvenience this may have caused.

               Ah,  and  one final  thing  that  I  almost forgot.  I  have
          recently put a second computer  together. This should help me put
          a little more  time into the newsletter, as I won't have to worry
          about bringing  my BBS  down every  time I  want to  work on  the
          newsletter. 

               Well, enjoy the holidays and hopefully I'll have a brand new
          issue out in early January.
                                  
                                                   _Pete Davis


                                                                         39


               The  Pascal   NewsLetter  is  Copyrighted   by  Pete  Davis.
          Articles submitted by others are  the property of the authors and
          are  used with  permission. They  may not  be treated  separately
          from this  newsletter without  the author's  permission and  thus
          maintain all distribution rules of  the newsletter as a whole. It
          may be  freely distributed  in un-modified   form, but  no charge
          whatsoever may be incurred on the recipient. All code is provided
          'as-is' with no guarantees whatsoever.

               The   Pascal   NewsLetter    can   be   obtained   from  the
          following locations:

                         GEnie : General Electric Network for Information  
                                 Exchange. It is located in the IBMPC 
                                 filelist.

                        Simtel : Internet address: 26.2.0.74 or            
                                 Simtel20.ARPA It is located in the        
                                 <MSDOS.PASCAL> directory.

            Programmer's Forum : This is the home of the PNL.              
                                 Each issue can be found in                
                                 the MAG directory from the main area.
                                 The number is on the title page.

               If   you  would  like  to   receive  back   issues   of  PNL
          directly  from  me,  send  a  diskette  and  $2.00  for shipping.
          Don't forget to include your address.

                         Send your order to:
                            Peter Davis
                            4851 Brandywine St. NW
                            Washington, DC   20016

               If you  are   a SysOp that   will regularly  carry PNL   and
          would like  to  have  your bulletin board  listed as such,  here,
          send  me  a  message either  by  postal  mail or  at  one  of the
          electronic  addresses  given   on  the  title   page,  with  your
          bulletin board's name, phone number, and your name.

                                                                         40

                                  Distribution List

               The following  is the phone numbers to bulletin boards known
          to carry  PNL. If you would  like your bulletin board's  name and
          number added  to  or deleted  from this  list, please  send me  a
          message at one of my many addresses. I can not guarantee whether 
          a listed board will have any particular issue.

             The Programmer's Forum ................. Phone: (202) 966-3647
                   The Programmer's Forum is the home of the PNL.

          BBS                       | FidoNet Addrs        |  Phone #
          --------------------------+----------------------+---------------
          The Bored                 | 1:397/3              | (512) 303-0471
          Classic City BBS          | 1:370/10             | (404) 548-0726
          Thieve's World BBS        | 1:106/805            | (713) 463-8053
          Hippocampus BBS           | 1:141/205            | (203) 484-4621
          Rogers State College      | 1:170/708            | (918) 341-8982
          The Foxtrot BBS           | 1:272/26             | (914) 567-1814
          Turbo City BBS            | 1:208/2              | (209) 599-7435
          Austin IEMUG/MIDI BBS     | 1:382/14             | (512) 258-0626
          Laser Publishers          | 1:170/403            | (918) 438-2749
          Fargo RBBS-PC             | 1:10/8               | (701) 293-5973
          Momentary Lapse of Reason |                      | (704) 327-6361
          The Demon's Den           |                      | (508) 433-2702
          The Cannibal Cafe         |                      | (508) 840-6589
          IBM Tech FIDO             |                      | (508) 433-6491
          The User Friendly BBS     |                      | (704) 323-8223
          The Disseminator BBS      | 3:640/378            | 61-7-368-1239
          Beyound Fronttiers BBS    | 2:230/101            | (+45)8694-1609
          Collision Theory          |                      | (703) 503-9441
          Merlin's Mailbox          | 2:245/39             |
          Ed-Net9600                | 1:153/734            | (604) 732-8877

























