home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / oop.swg / 0013_OOPINFO.PAS.pas < prev    next >
Pascal/Delphi Source File  |  1993-05-28  |  31KB  |  826 lines

  1.  My understanding of OOP revolves around three principles:
  2.  
  3.   ENCAPSULATION:  All data-Types, Procedures, Functions are placed
  4.                   within a new Type of wrapper called an Object.
  5.  
  6.                   This new wrapper is very simillar to a standard
  7.                   Record structure, except that it also contains
  8.                   the routines that will act on the data-Types
  9.                   within the Object.
  10.  
  11.                   The Object-oriented style of Programming requires
  12.                   that you should ONLY use the routines within the
  13.                   Object to modify/retrieve each Object's data-Types.
  14.                   (ie: Don't access the Variables directly.)
  15.  
  16.  
  17.       Structured Style                 OOP Style
  18.       ================                 =========
  19.       MyRecord = Record                MyObject = Object
  20.                    1st Variable;                    1st Variable;
  21.                    2nd Variable;                    2nd Variable;
  22.                    3rd Variable                     3rd Variable;
  23.                  end;                               Procedure One;
  24.                                                     Procedure Two;
  25.                                                     Function One;
  26.                                                     Function Two;
  27.                                                   end;
  28.  
  29.      inHERITANCE: This gives you the ability to make a new Object by
  30.                   cloning an old Object. The new Object will contain
  31.                   all the abilities of the old Object.
  32.                   (ie: Variables, Procedures/Functions).
  33.  
  34.                    You can add additional abilities to this new Object,
  35.                    or replace old ones.
  36.  
  37.                                +--------------+
  38.                                |  New Object  |
  39.                                |  +--------+  |
  40.                                |  |  Old   |  |
  41.                                |  | Object |  |
  42.                                |  +--------+  |
  43.                                +--------------+
  44.  
  45.                    With Inheritance, you don't have to go back and
  46.                    re-Write old routines to modify them into new
  47.                    ones. Instead, simply clone the old Object and
  48.                    add or replace Variables/Procedures/Functions.
  49.  
  50.                    This makes the whole process of rewriting/modifying
  51.                    a Program MUCH faster/easier. Also there is less
  52.                    chance of creating new bugs from your old bug-free
  53.                    source-code.
  54.  
  55.  
  56.   POLYMorPHISM:    The name Sounds intimidating, but the concept is
  57.                    simple.
  58.  
  59.                    Polymorphism allows one Procedure/Function to
  60.                    act differently between one Object and all its
  61.                    descendants. (Clones)
  62.  
  63.                    These Type of "polymorphic" Procedures/Functions
  64.                    know which Object they are working on, and act
  65.                    accordingly. For example:
  66.  
  67.                    Say you've created an Object (Object-1) that
  68.                    contains a Procedure called DrawWindow, to draw
  69.                    the main screen of a Program.
  70.  
  71.                    DrawWindow relies on another Procedure SetBorder
  72.                    within Object-1, to set the borders used in the
  73.                    main screen.
  74.  
  75.                    Now you clone Object-2 from Object-1.
  76.  
  77.                    You want to use Object-2 to handle pop-up Windows,
  78.                    but you want the pop-ups to have a different border
  79.                    style.
  80.  
  81.                   if you call the DrawWindow Procedure that Object-2
  82.                    inherited from Object-1, you'll end up With a Window
  83.                    With the wrong border-style.
  84.  
  85.                    to get around this you could change the SetBorder
  86.                    Procedure to a "Virtual" Procedure, and add a
  87.                    second identically named "Virtual" Procedure
  88.                    (SetBorder) within Object-2.
  89.  
  90.                    A "Virtual" Procedure relies on a "Virtual Table"
  91.                    (Which is basicly a Chart to indicate which
  92.                     "Virtual" routine belongs to which Object)
  93.                    to, indicate which version of the identically
  94.                    named Procedures should be used within different
  95.                    Objects.
  96.  
  97.                    So within Object-1, the DrawWindow routine will
  98.                    use the SetBorder Procedure within Object-1.
  99.  
  100.                    Within Object-2, the inherited DrawWindow routine
  101.                    will use the other SetBorder Procedure that belongs
  102.                    to Object-2.
  103.  
  104.                    This works because the "Virtual Table" tells the
  105.                    DrawWindow routine which SetBorder Procedure to
  106.                    use For each different Object.
  107.  
  108.                    So a call to the SetBorder Procedure now acts
  109.                    differently, depending on which Object called it.
  110.                    This is "polymorphism" in action.
  111.  
  112.  
  113.   OOP LANGUAGE LinGO: The following are some of the proper names For
  114.                       OOP syntax.
  115.  
  116.      Structured Programming       OOP Programming
  117.      ======================       ===============
  118.       Variables                   Instances
  119.       Procedures/Functions        Methods
  120.       Types                       Classes
  121.       Records                     Objects
  122.  
  123. {
  124. > i have a parent Object defined With Procedure a and b.
  125. > i have a child Object With Procedure a, b and c.
  126.  
  127. > when i declare say john being a child, i can use a, b, or c With no
  128. > problem.  when i declare john as being a parent, i can use a or b.
  129.  
  130. > if i declare john as being a parent and initialise it with
  131. > new (childPTR,init) it seems i have access to the parent fields
  132.  
  133. After reading twice, I understand you mean Object classes dealing With humans,
  134. not trees (happen to have parents & childs too).
  135.  
  136. > parent a,b,c,d,e,f
  137.  (bad)
  138. > parent a,b
  139.  (good)
  140. > child a,b,c
  141. > child2 a,b,d
  142. > child3 a,b,e,f
  143.  (redefine a, b For childs as Far as they differ from parent a,b)
  144.  
  145. Next example could be offensive For christians, atheists and media-people.
  146. }
  147.  
  148. Type
  149.   TParent = Object    { opt. (tObject) For Stream storage }
  150.     Name : String;
  151.     Constructor Init(AName: String);
  152.     Procedure Pray;             { your A,
  153.                                   they all do it the same way }
  154.     Procedure Decease; Virtual; { your B, Virtual, some instances
  155.                                   behave different (Heaven/Hell) }
  156.     Destructor Done; Virtual;
  157.   end;
  158.   TChild1 = Object(TParent)
  159.     Disciples : Byte;
  160.     Constructor Init(AName: String; DiscipleCount: Byte);
  161.     { do not override Decease } { calling it will result in a
  162.                                   call to TParent.Decease }
  163.     Procedure Resurrection;     { your C }
  164.   end;
  165.   TChild2 = Object(TParent)
  166.     BulletstoGo : LongInt;
  167.     Constructor Init(DisciplesCount: Byte; Ammo: LongInt);
  168.     Procedure Decease; Virtual;         { override }
  169.     Procedure Phone(Who: Caller);  { your D }
  170.   end;
  171.  
  172.   Constructor TParent.Init(AName: String);
  173.   begin
  174.     Name := AName;
  175.   end;
  176.   Destructor TParent.Done;
  177.   begin
  178.     {(...)}
  179.   end;
  180.   Procedure TParent.Pray;
  181.   begin
  182.     ContactGod;
  183.   end;
  184.   Procedure TParent.Decease;
  185.   begin
  186.     GotoHeaven;
  187.   end;
  188.  
  189.   Constructor TChild1.Init(AName: String; DiscipleCount: Byte);
  190.   begin
  191.     inherited Init(AName);
  192.     Disciples := DiscipleCount;
  193.   end;
  194.   Procedure TChild1.Resurrection;
  195.   begin
  196.     RiseFromTheDead;
  197.   end;
  198.  
  199.   Constructor TChild2.Init(AName: String;
  200.                            DiscipleCount: Byte; Ammo: LongInt);
  201.   begin
  202.     inherited Init(DiscipleCount);
  203.     BulletstoGo := Ammo;
  204.   end;
  205.   Procedure TChild2.Decease;
  206.   begin
  207.     EternalBurn;
  208.   end;
  209.   Procedure TChild2.Phone(Who: Caller);
  210.   begin
  211.     Case Who of
  212.       AFT   : Ventriloquize;
  213.       Media : Say('Burp');
  214.     end;
  215.   end;
  216. {
  217. In the next fragment all three Types of instances are put into a collection.
  218. }
  219. Var
  220.   Christians : PCollection;
  221.  
  222. begin
  223.   Christians := New(PCollection, Init(2,1));
  224.   With Christians^ do begin
  225.     Insert(PParent, Init('Mary'));
  226.     Insert(PParent, Init('John'));
  227.     Insert(PChild1, Init('Jesus', 12));
  228.     Insert(PChild2, Init('Koresh', 80, 1000000));
  229.   end;
  230. {
  231. Now you can have all instances pray ...
  232. }
  233.   Procedure DoPray(Item: Pointer); Far;
  234.   begin
  235.     { unTyped Pointers cannot have method tables. The PParent
  236.       Typecast Forces a lookup of Pray in the method table.
  237.       All instances With a TParent ancestor will point to
  238.       the same (non-Virtual) method }
  239.     PParent(Item)^.Pray;
  240.   end;
  241.   { being sure all Items in Christians are derived from TParent }
  242.   Christians^.ForEach(@DoPray);
  243. {
  244. and because all mortals will die...
  245. }
  246.   Procedure endVisittoEarth(Item: Pointer); Far;
  247.   begin
  248.     { Decease is a Virtual method. The offset of a location in
  249.       the VMT With the address of a Virtual method is determined by
  250.       the Compiler. At run-time, For each Type of instance 1 VMT
  251.       will be created, it's method-fields filled With the
  252.       appropriate addresses to call.
  253.       Each instance of an Object derived from TParent will have the
  254.       address of it's VMT at the same location. Calling a Virtual
  255.       method results in
  256.          1) retrieving that VMT address at a known offset in
  257.             the instance's data structure
  258.          2) calling a Virtual method at a known offset in the
  259.             VMT found in 1)
  260.       ThereFor mr. Koresh will go to hell: PChild2's VMT contains
  261.       at the offset For Decease the address of the overridden
  262.       method. Mr. Jesus, a PChild1 instance, simply inherits the
  263.       address of PParent's Decease method at that offset in the
  264.       VMT.                                                        }
  265.     PParent(Item)^.Decease;
  266.   end;
  267.   Christians^.ForEach(@endVisittoEarth);
  268.  
  269.  
  270.  
  271. ->   ...I've no problem posting my code, but I'm still not Really happy
  272. ->   With it's present Implementation. I also don't think that dynamic
  273. ->   Array Objects are very good examples of OOP. (For example, what
  274. ->   do extend the dynamic-Array Object into, via inheiritance???)
  275. ->
  276. ->   ...Something more like a generic "Menu" or "Line-Editor" Object
  277. ->   might be a better example.
  278.  
  279. Well I don't know exactly what you are trying to do With your dynamic
  280. Array but it can be OOP'ed.  Linked lists are a prime example (I hope
  281. this is close)  By using OOP to Write link lists you can come up with
  282. Objects such as:
  283.  
  284. Type
  285.     ListPtr = ^List;
  286.     NodePtr = ^ListNode;
  287.  
  288.     List (Object)
  289.       TNode   : Pointer;  {Pointer to the top Record}
  290.       BNode   : Pointer;  {Pointer ro the bottom Record}
  291.       CurNode : Pointer;  {Current Pointer}
  292.  
  293.     Constructor Init;             {Initializes List Object}
  294.     Destructor  Done;  Virtual;   {Destroys the list and all its nodes}
  295.  
  296.     Function top    (Var Node : ListNode) : NodePtr;
  297.     Function Bottom (Var Node : ListNode) : NodePtr;
  298.     Function Next   (Var Node : ListNode) : NodePtr;
  299.     Function Prev   (Var Node : ListNode) : NodePtr;
  300.     Function Current(Var Node : ListNode) : NodePtr;
  301.  
  302.     Procedure AttachBeFore (Var Node : ListNode);
  303.     Procedure AttachAfter  (Var Node : ListNode);
  304.     Procedure Detach       (Var NodePtr : Pointer);
  305.  
  306.   end;
  307.  
  308.   ListNode = Object;
  309.     Prev : NodePtr;
  310.     Next : NodePtr;
  311.  
  312.   Constructor Init;
  313.   Destructor  Done;  Virtual;
  314.  
  315.   end;
  316.  
  317. The list Object is just that.  It has the basic operations you would do
  318. with a list.  You can have more than one list but only one set of
  319. methods will be linked in.  The List node Dosn't have much other than
  320. the Pointers to link them into a list and an Init, done methods.  Sounds
  321. like a ton of work just to implement a list but there is so much you can
  322. do easely With OOP that you would have a hard time doing conventionally.
  323. One example, because the ListNode's Done Destructor is Virtual the Done
  324. of the list can accually tranvirs the list and destroy all Objects in
  325. the list.  One list can accually contain Objects that are not the
  326. same!!!  Yep it sure can.  As long as an Object is dirived from ListNode
  327. the list can handel it.  Try to do that using conventional methods!!
  328.  
  329. I'm assuming that your dynamic Array will do something similar which is
  330. why I suggested it.  A Menu and Line editor Objects are High level
  331. Objects that should be based on smaller Objects.  I'd assume that a line
  332. editor would be a Complex list of Strings so the list and ListNode
  333. Objects would need to be built.  See what I mean???
  334.  
  335. then you get into Abstract Objects.  These are Objects that define
  336. common methods For its decendants but do not accually have any code to
  337. suport them.  This way you have set up a standard set of routines that
  338. all decendants would have and Programs could be written using them.  THe
  339. results of which would be a Program that could handel any Object based
  340. on the abstract.
  341.  
  342. -> RM>I have mixed feeling on this. I see OOP and Object as tools For a
  343. -> RM>Program to manipulate.
  344. ->
  345. -> RM>  IE: File Objects, Screen Objects, ect then bind them together
  346. -> RM>      in a Program using conventional style coding.
  347. ->
  348. ->   ...to my understanding of the OOP style of Programming, this would
  349. ->   be a "NO-NO".
  350.  
  351. OK well With the exception of TApplication Object in Turbo Vision a
  352. Program is a speciaized code that more than likely can't be of any use
  353. For decendants.  That was my reasioning at least.  and the Tapp Object
  354. isn't a Program eather.  YOu have to over ride a ton of methods to get
  355. it to do anything.
  356. Unit OpFile;  {*******   Capture this For future referance   *******}
  357.  
  358. Interface
  359.  
  360. Type
  361.  
  362. DateTimeRec = Record
  363.               {Define the fields you want For date and time routines}
  364.               end;
  365.  
  366. AbstractFile = Object
  367.  
  368.   Function  Open : Boolean;                                   Virtual;
  369.     {Opens the File in the requested mode base on internal Variables }
  370.     {Returns True if sucessfull                                      }
  371.  
  372.   Procedure Close;                                            Virtual;
  373.     {Flush all buffers and close the File                            }
  374.  
  375.   Function  Exists : Boolean;                                 Virtual;
  376.     {Returns True is the File exists                                 }
  377.  
  378.   Function  Create : Boolean;                                 Virtual;
  379.     {Will create the File or overWrite it if it already exists       }
  380.  
  381.   Procedure Delete;                                           Virtual;
  382.     {Will delete the File.                                           }
  383.  
  384.   Function  Rename : Boolean;                                 Virtual;
  385.     {Will rename the File returns True if successfull                }
  386.  
  387.   Function  Size : LongInt;                                   Virtual;
  388.     {Returns the size of the File.                                   }
  389.  
  390.   Procedure Flush;                                            Virtual;
  391.     {Will flush the buffers without closing the File.                }
  392.  
  393.   Function  Lock : Boolean;                                   Virtual;
  394.     {Will attempt to lock the File in a network enviroment, returns  }
  395.     {True if sucessfull                                              }
  396.  
  397.   Procedure Unlock;                                           Virtual;
  398.     {Will unlock the File in a network enviroment                    }
  399.  
  400.   Function  Copy (PathName : String) : Boolean;               Virtual;
  401.     {Will copy its self to another File, returns True is successfull.}
  402.  
  403.   Function  GetDateTime (Var DT : DateTimeRec) : Boolean;     Virtual;
  404.     {Will get the File date/time stamp.                              }
  405.  
  406.   Function  SetDateTime (Var DT : DateTimeRec) : Boolean;     Virtual;
  407.     {Will set the File date stamp.                                   }
  408.  
  409.   Function  GetAttr : Byte;                                   Virtual;
  410.     {Will get the File attributes.                                   }
  411.  
  412.   Function  SetAttr (Atr : Byte) : Boolean;                   Virtual;
  413.     {Will set a File's attributes.                                   }
  414.  
  415. end; {of AbstractFile Object}
  416.  
  417. Implementation
  418.  
  419.   Procedure Abstract;    {Cause a run time error of 211}
  420.     begin
  421.     Runerror (211);
  422.     end;
  423.  
  424.   Function  AbstractFile.Open : Boolean;
  425.     begin
  426.     Abstract;
  427.     end;
  428.  
  429.   Procedure AbstractFile.Close;
  430.     begin
  431.     Abstract;
  432.     end;
  433.  
  434.   Function  AbstractFile.Exists : Boolean;
  435.     begin
  436.     Abstract;
  437.     end;
  438.  
  439.   Function  AbstractFile.Create : Boolean;
  440.     begin
  441.     Abstract;
  442.     end;
  443.  
  444.   Procedure AbstractFile.Delete;
  445.     begin
  446.     Abstract;
  447.     end;
  448.  
  449.   Function  AbstractFile.Rename : Boolean;
  450.     begin
  451.     Abstract;
  452.     end;
  453.  
  454. Ok theres a few things we have to talk about here.
  455.  
  456. 1.  This is an ABSTRACT Object.  It only defines a common set of
  457. routines that its decendants will have.
  458.  
  459. 2.  notice the Procedure Abstract.  It will generate a runtime error
  460. 211.  This is not defined by TP.  Every Method of an Object has to do
  461. somthing.  if we just did nothing we could launch our Program into
  462. space.  By having all methods call Abstract it will error out the
  463. Program and you will know that you have called and abstract method.
  464.  
  465. 3.  I'm sure some may question why some are Procedures and some are
  466. Functions ie Open is a Function and close is a Boolean.   What I based
  467. them on is if an error check a mandatory it will be a Function Boolean;
  468. This way loops will be clean.  Open in a network Open will require a
  469. check because it may be locked.  Which brings up point 4.
  470.  
  471. 4.  We are not even finished With this Object yet.  We still have to
  472. define a standard error reporting / checking methods and also lock loop
  473. control methods.  not to mention some kind of common data and methods to
  474. manipulate that data.  Moving to point 5.
  475.  
  476. 5.  Where does it end???  Well we hvae added quite a few Virtual methods
  477. While thsi is not bad it does have a negative side.  All Virtual methods
  478. will be linked in to the final EXE weather it is used or not.  There are
  479. valid reasions For this but you don't want to make everything Virtual if
  480. it Dosn't have to be.  My thinking is this.  if it should be a standard
  481. routine For all decendants then it should be Virtual.  if required
  482. methods call a method then why not make it Virtual (this will become
  483. more apparent in network methods and expanding this Object)
  484.  
  485. Now personally I get a feeling that the DateTime and Attr methods
  486. shouldnn't be there or at least not Virtual as the vast majority of
  487. Programs will not need them and its pushing the limits of Operating
  488. system spisific methods.  SO it will probly be a Dos only Object.  (Yes
  489. there are others that have this but I think its over kill)  The same
  490. goes For the copy and rename methods so I would lean to removing them
  491. from this Object and define them in decendants.
  492.  
  493. So what do you think we need to have For error checking / reporting
  494. methods???  Do you think we could use more / different methods???
  495.  
  496.  
  497. {
  498.  DW> I am trying to teach myself about Object orientated Programming and
  499.  DW> about 'inheritence'. This is my code using Records.
  500.  
  501. The idea of Object oriented Programing is what is refered to as
  502. encapsulation.  Your data and the Functions that manipulate it are
  503. grouped together.  As an example, in a traditional Program, a linked
  504. list would look something like:
  505. }
  506.  
  507. Type
  508.   Linked_List =
  509.     Record
  510.       Data : Integer; {Some data}
  511.       Next : ^Linked_List; {Next data}
  512.       Prev : ^Linked_List; {Prev data}
  513.     end;
  514.  
  515. then you would have a whole slew of Functions that took Linked_List as a
  516. parameter.  Under OOP, it would look more like
  517.  
  518. Type
  519.   Linked_List =
  520.     Object
  521.       Data : Integer;
  522.       Next : ^Linked_List;
  523.       Prev : ^Linked_List;
  524.  
  525.       Constructor Init();   {Initializes Linked_List}
  526.       Destructor  DeInit(); {Deinitializes Linked_List}
  527.       Procedure AddItem(aData : Integer);
  528.       Procedure GetItem(Var aData : Integer);
  529.     end;
  530.  
  531. then, to add an item to a particular list, the code would look like:
  532. This_Linked_List.AddItem(10);
  533.  
  534. This is easier to understand.  An easy way to think about this is that
  535. an Object is an entity sitting out there.  You tell it what you want to
  536. do, instead of calling a Function you can't identify.  Inheritance
  537. allows you to make a linked list that holds a different Type, but Uses
  538. the same Interface funtions.  More importantly, using the same method
  539. and Pointers, you could have both Types in the same list, depending on
  540. how you implemented it.
  541.  
  542. It helps debugging time, because if you wanted to add a Walk_List
  543. Function, you could add it and get it working For the parent Object, and
  544. (since the mechanics of it would be the same For ANY Linked List), you
  545. could Write it once and use it without problems.  That is a clear
  546. advantage.  Other Uses include:
  547.  
  548. (For a door Type Program) and Input/Output Object that serves as a base
  549. For a console Object and a modem Object, and thusly allows you to treat
  550. the two as the same device, allowing you to easily use both.
  551.  
  552. (For a BBS Message base kit) a Generic Message Object that serves as a
  553. base For a set of Objects, each of which implements a different BBS'
  554. data structures.  Using this kit, a Program could send a message to any
  555. of the BBSes just by knowing the core Object's mechanics.
  556.  
  557. (For Windows) a Generic Object represents a Generic Window.  By
  558. inheritance, you inherit the Functionality of the original Window.  By
  559. creating an Object derived from the generic Window, you can add
  560. additional Functionality, without having to first Write routines to
  561. mirror existing Functionality.
  562.  
  563. (For Sound) a Generic Object represents a generic Sound device.
  564. Specific child Object translate basic commands (note on, note off, etc)
  565. to device specific commands.  Again, the Program doesn't have to know
  566. whether there is a PC speaker or an Adlib or a SoundBlaster--all it has
  567. to know is that it calls note_on to start a note and note_off to end a
  568. note.
  569.  
  570. There are thousands on thousands of other examples.  if you read through
  571. the turbo guides to turbovision or to Object oriented Programming, they
  572. will help you understand.  Also, a good book on Object oriented
  573. Programming doesn't hurt ;>.
  574.  
  575.  
  576.  
  577.  
  578. {
  579. > Now, the questions:
  580. > 1. How do I discretly get the Lat & Long into separate
  581. > Collections? In other Words (psuedocode):
  582.  
  583. No need For seperate collections, put all the inFormation in a Single
  584. collection.
  585.  
  586. > Any hints would be appreciated. Thanks!
  587.  
  588. I'll not give any help With parsing the Text File, there will probably be a ton
  589. of advice there, but here is a little Program that I threw together (and
  590. tested) that will list the inFormation and present the additional data.
  591. Have fun With it.
  592. }
  593.  
  594. Program Test;
  595. Uses Objects,dialogs,app,drivers,views,menus,msgbox;
  596.  
  597. Type
  598.   (*Define the Data Element Type*)
  599.   Data = Record
  600.            Location : PString;
  601.            Long,Lat : Real;
  602.          end;
  603.   PData = ^Data;
  604.  
  605.   (*Define a colection of the data elements*)
  606.   DataCol = Object(TCollection)
  607.               Procedure FreeItem(Item:Pointer); Virtual;
  608.             end;
  609.   PDC     =^DataCol;
  610.  
  611.   (*Define a list to display the collection*)
  612.   DataList = Object(TListBox)
  613.                Function GetText(item:Integer;maxlen:Integer):String; Virtual;
  614.                Destructor done; Virtual;
  615.              end;
  616.   PDL = ^DataList;
  617.  
  618.   (*Define a dialog to display the list *)
  619.   DataDlg = Object(TDialog)
  620.               Pc : PDC;
  621.               Pl : PDL;
  622.               Ps : PScrollBar;
  623.               Constructor Init(Var bounds:Trect;Atitle:TTitleStr);
  624.               Procedure HandleEvent(Var Event:TEvent); Virtual;
  625.             end;
  626.   PDD     = ^DataDlg;
  627.  
  628. Const
  629.   CmCo = 100;
  630.   CmGo = 101;
  631.  
  632.  
  633. Procedure DataCol.FreeItem(Item:Pointer);
  634.    begin
  635.      disposeStr(PString(PData(Item)^.Location));
  636.      dispose(PData(Item));
  637.    end;
  638.  
  639. Function DataList.GetText(item:Integer;maxlen:Integer):String;
  640.    begin
  641.      GetText := PString(PData(List^.At(item))^.Location)^;
  642.    end;
  643.  
  644. Destructor DataList.Done;
  645.    begin
  646.      Dispose(PDC(List),Done);
  647.      TListBox.Done;
  648.    end;
  649.  
  650. Constructor DataDLG.Init(Var bounds:Trect;Atitle:TTitleStr);
  651.    Var
  652.    r  : trect;
  653.    pd : pdata;
  654.    begin
  655.      TDialog.Init(bounds,ATitle);
  656.      geTextent(r); r.grow(-1,-1); r.a.x := r.b.x - 1; dec(r.b.y);
  657.      new(ps,init(r)); insert(ps);
  658.  
  659.      geTextent(r); r.grow(-1,-1); dec(r.b.x); dec(r.b.y);
  660.      new(pl,init(r,1,ps)); insert(pl);
  661.  
  662.      geTextent(r); r.grow(-1,-1); r.a.y := r.b.y - 1;
  663.      insert(new(pstatusline,init(r,
  664.                 newstatusdef(0,$FFFF,
  665.                 newstatuskey('~[Esc]~ Quit ',kbesc,CmGo,
  666.                 newstatuskey('   ~[Alt-C]~ Co-ordinates ',kbaltc,CmCo,
  667.                 newstatuskey('',kbenter,CmCo,nil))),nil))));
  668.  
  669.      new(Pc,init(3,0));
  670.      With pc^ do        (*parse your File and fill the*)
  671.        begin            (*collection here             *)
  672.          new(pd);
  673.          pd^.location := newstr('Port Arthur, Texas');
  674.          pd^.long := 29.875; pd^.lat  := 93.9375;
  675.          insert(pd);
  676.          new(pd);
  677.          pd^.location := newstr('Port-au-Prince, Haiti');
  678.          pd^.long := 18.53; pd^.lat  := 72.33;
  679.          insert(pd);
  680.          new(pd);
  681.          pd^.location := newstr('Roswell, New Mexico');
  682.          pd^.long := 33.44118; pd^.lat  := 104.5643;
  683.          insert(pd);
  684.       end;
  685.      Pl^.newlist(pc);
  686.   end;
  687.  
  688. Procedure DataDlg.HandleEvent(Var Event:TEvent);
  689.    Var
  690.     los,las : String;
  691.    begin
  692.      TDialog.HandleEvent(Event);
  693.      if Event.What = EvCommand then
  694.         Case Event.Command of
  695.           CmGo : endModal(Event.Command);
  696.           CmCo : begin
  697.              str(PData(Pl^.List^.At(Pl^.Focused))^.Long:3:3,los);
  698.              str(PData(Pl^.List^.At(Pl^.Focused))^.Lat:3:3,las);
  699.              MessageBox(
  700.              #3+PString(PData(Pl^.List^.At(Pl^.Focused))^.Location)^ +
  701.              #13+#3+'Longitude : '+los+#13+#3+'Latitude  : '+las,
  702.              nil,mfinFormation+mfokbutton);
  703.                  end;
  704.          end;
  705.     end;
  706.  
  707. Type  (*the application layer *)
  708.   myapp = Object(Tapplication)
  709.             Procedure run; Virtual;
  710.           end;
  711.  
  712. Procedure myapp.run;
  713.    Var r:trect;
  714.        p:PDD;
  715.    begin
  716.      geTextent(r);
  717.      r.grow(-20,-5);
  718.      new(p,init(r,'Dialog by ken burrows'));
  719.      if p <> nil then
  720.         begin
  721.           desktop^.execview(p);
  722.           dispose(p,done);
  723.         end;
  724.    end;
  725.  
  726. Var
  727.  a:myapp;
  728.  
  729. begin
  730.   a.init;
  731.   a.run;
  732.   a.done;
  733. end.
  734.  
  735.  
  736.  
  737.  
  738. >   I am having a problem.  I would like to Write an editor.  The
  739. > problem is I dont understand a thing about Pointers (which everyone
  740. > seems to use For editors).
  741.  
  742.    I'm certainly no TP expert, but I might be able to help out With the
  743. Pointers.  Pointers are just special 4-Byte Variables that contain (
  744. point to) a specific position in memory.  You can also make a Pointer
  745. act like the thing to which it is pointing is a particular Type of
  746. Variable (Byte, String, etc).  Unlike normal Var Variables, however, these
  747. Variables are what's referred to as Virtual -- they aren't fixed in the
  748. .EXE code like Var Vars, so you can have as many of them as you like,
  749. within memory Constraints.  Each is created when needed using the GetMem
  750. statement.  This statement makes a request For some more memory to be
  751. used in the heap (all left-over memory when the Program loads usually).
  752.  
  753. What you need in a editor is to be able to somehow link the Strings
  754. that make up the document into what's called a list (first line, next,
  755. ... , last line).  The easiest way to visualize this is a bunch of people
  756. in a line holding hands, each hand being a Pointer.  The hand is not the
  757. entire person, it just connects to the next one.  So, what you do is
  758. use a Record that contains one String For one line of Text, a Pointer to
  759. the previous line of Text in the document, and a Pointer to the next line
  760. in the document.  A Record like this should do it:
  761.     {+------------------------- Usually used in starting a Type of Pointer}
  762.     {|+------------------------ Points to a String in the document        }
  763.     {||            +----------- This is usedto mean that PStringItem is   }
  764.      ||            |            to be a Pointer pointing to a Record      }
  765.      ||            |            known as TStringItem                      }
  766.     {vv            v
  767. Type PStringItem = ^TStringItem;
  768.      TStringItem : Record
  769.         LineOText : String [160]; {Double the screen width should do it}
  770.         NextLine  : PStringItem;  {Points to the next line in memory}
  771.         PrevLine  : PStringItem;  {Points to the previous line in memory}
  772.         end;
  773.  
  774. In your editor main Program, use
  775.  
  776. Var FirstLine, LastLine, StartLine, CurrLine : PStringItem;
  777.  
  778. to create Varibles giving you `bookmarks' to the first line in the
  779. File, last in the File, the one the cursor is on, and the one that
  780. starts the screen.  All of these will change.
  781.  
  782. to create the first line in the document, use:
  783.  
  784. GetMem (FirstLine, Sizeof (TStringItem)); {get memory enough For one line}
  785. CurrLine := FirstLine;   {of course, only one line in the doc so Far!}
  786. LastLine := FirstLine;
  787. StartLine := FirstLine;
  788. FirstLine^.NextLine := nil; {nil means no particular place-- there's no}
  789. FirstLine^.PrevLine := nil; {line beFore of after FirstLine yet        }
  790.  
  791. Now the Variable FirstLine will contain the address of the newly created
  792. Variable.  to address that Variable, use the carrot (^), like this:
  793.  
  794. FirstLine^.LineOText := 'Hello World!');
  795.  
  796. to make a new line in the list just get more memory For another line:
  797.  
  798. GetMem (LastLine^.NextLine, Sizeof (TStringItem));
  799. LastLine := LastLine^.NextLine;
  800.  
  801. This will get more memory and set the last line in the File's
  802. next line Pointer to the new String, then make the new String the
  803. last line.
  804.  
  805. Deleting a line is almost as simple.  You use the FreeMem Procedure
  806. to release the memory used by a Variable.  if it's in the middle of the
  807. list, just set the to-be-deleted's next line's previous line to the
  808. to-be deleted's previous line, and the previous line's next to the one
  809. after the one to be deleted, essentially removing it from the list and
  810. then tieing the peices back together.  You can then kill off the memory
  811. used by that line.
  812.  
  813. {Delete current line}
  814. if CurrLine^.NextLine <> nil then {there's a line after this one}
  815.    CurrLine^.NextLine^.PrevLine := CurrLine^.PrevLine;
  816. if CurrLine^.PrevLine <> nil then {there's a line beFore this one}
  817.    CurrLine^.PrevLine^.NextLine := CurrLine^.NextLine;
  818. FreeMem (CurrLine, Sizeof (TStringItem));
  819.  
  820. to insert a line, just do about the opposite.
  821.  
  822. if you don't understand, I won't blame you, I'm half asleep anyway...
  823. but I hoe it clears some of the fog.  if the manual isn't helpful
  824. enough now, try tom Swan's _Mastering Turbo Pascal_, an excellent
  825. book.
  826.