home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a039 / 3.ddi / PASSAMP.ZIP / FONEDEX.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-03-11  |  19.6 KB  |  895 lines

  1. {$N+,E+}
  2. (*       Copyright (c) 1990 by Borland International, Inc. *)
  3. program Fonedex;
  4.  
  5. uses
  6.   CRT, PXEngine;
  7. (*
  8.  * FONEDEX.PAS
  9.  * Simple electronic file card application
  10.  *
  11.  * Description:
  12.  *   Allows simple database design and access of an electronic file
  13.  *   card database. Records can be added, deleted, updated and searched
  14.  *   in a multiuser environment.
  15.  *
  16.  *   The structure  of new tables is kept in the ASCII file
  17.  *   STRUCTUREFILE. Each line of the file represents a field
  18.  *   in the Paradox table DATAFILE. It has the format:
  19.  *   <field type> <field name>
  20.  *   where <field name> and <field type> are legal Paradox names and
  21.  *   field types.
  22.  *
  23.  * Complilation:
  24.  *   To compile and link the example program, make sure that your
  25.  *   Turbo Pascal compiler (version 5.5 or 6.0) has been correctly
  26.  *   installed.
  27.  *
  28.  * Execution:
  29.  *   To run the example program enter the following command:
  30.  *     fonedex
  31.  *   You can then choose different options through a very simple menu
  32.  *   interface.
  33.  *)
  34.  
  35. const
  36.   SUCCESS = True;
  37.   FAILURE = False;
  38.   MAXFIELDS = 20;
  39.   MAXFIELDSIZE = 50;
  40.   StructureFile = 'fonedex.dat';
  41.   DataFile = 'fonedex';
  42.  
  43.   (* Constants for PXNetInit (modify these constants to match your network) *)
  44.  
  45.   UserName = 'Engine';
  46.   NetType = NOTONNET;
  47.   NetDir = '';
  48.  
  49. var
  50.   RecHandle: RecordHandle;              (* record buffer *)
  51.   TblHandle: TableHandle;               (* table handle *)
  52.   Names,                                (* field names *)
  53.    Types: NamesArrayPtr;                (* field types *)
  54.   TableIsOpen: Boolean;                 (* flag for open Table *)
  55.   NFields: Integer;                     (* number of fields *)
  56.  
  57. (*
  58.  *    Procedure:
  59.  *          Strip
  60.  *
  61.  *    Arguments:
  62.  *          S       String to be stripped of white space.
  63.  *
  64.  *    Description:
  65.  *          Strips a string of leading and trailing white space.
  66.  *)
  67. procedure Strip(var S: String );
  68.  
  69.   var
  70.     L1, L2: Byte;
  71.  
  72.   begin
  73.     L1 := 1;
  74.     while (L1 < Length(S)) and (S[L1] in [#9..#13, ' ']) do
  75.       Inc(L1);
  76.     L2 := Length(S);
  77.     while (L2 > 0) and (S[L2] in [#9..#13, ' ']) do
  78.       Dec(L2);
  79.     S := Copy(S, L1, L2 - L1 + 1);
  80.   end; (* Strip *)
  81.  
  82.  
  83. (*
  84.  *    Function:
  85.  *      Error
  86.  *
  87.  *    Arguments:
  88.  *        RC                  return code from a PX... function
  89.  *
  90.  *    Description:
  91.  *        Writes error message if an error has occurred.
  92.  *
  93.  *    Returns:
  94.  *      True if Error
  95.  *      else False
  96.  *)
  97. function Error(RC: Integer): Boolean;
  98.  
  99.   begin
  100.     if RC <> PXSUCCESS then
  101.       WriteLn('FONEDEX: ', PXErrMsg(RC));
  102.     Error := RC <> PXSUCCESS;
  103.   end; (* Error *)
  104.  
  105.  
  106. (*
  107.  *    Procedure:
  108.  *      ErrIgnore
  109.  *
  110.  *    Arguments:
  111.  *        RC                  return code from a PX... function
  112.  *
  113.  *    Description:
  114.  *        Writes error message if an error has occurred.
  115.  *
  116.  *    Returns:
  117.  *      None
  118.  *)
  119. procedure ErrIgnore(RC: Integer);
  120.  
  121.   begin
  122.     if Error(RC) then; (* ignore error return code *)
  123.   end; (* ErrIgnore *)
  124.  
  125.  
  126. (*
  127.  *    Function:
  128.  *          LoadTableStructure
  129.  *
  130.  *    Arguments:
  131.  *          None
  132.  *
  133.  *    Description:
  134.  *          Loads a table structure from an ASCII disk file.
  135.  *
  136.  *    Returns:
  137.  *          SUCCESS     structure loaded
  138.  *          FAILURE     error occurred
  139.  *)
  140. function LoadTableStructure: Boolean;
  141.  
  142.   var
  143.     F: Text;
  144.     FldName, FldType, Help: String;
  145.  
  146.   begin
  147.     (* Open the structure file *)
  148.  
  149.     Assign(F, StructureFile);
  150. {$I-}
  151.     Reset(F);
  152. {$I+}
  153.     if IoResult <> 0 then
  154.       begin
  155.         WriteLn('can''t open Structure file');
  156.         LoadTableStructure := FAILURE;
  157.         Exit;
  158.       end;
  159.     (* Read in the structure *)
  160.     NFields := 0;
  161.     New(Names);
  162.     New(Types);
  163.  
  164.     while not Eof(F) and (NFields < MAXFIELDS) do
  165.  
  166.       begin
  167.  
  168.         (* read data, bewaring of unexpected EOF *)
  169. {$I-}
  170.         ReadLn(F, Help);
  171. {$I+}
  172.         if (IoResult = 0) and (Help <> '') then
  173.           begin
  174.  
  175.             Inc(NFields);
  176.             Strip(Help);
  177.             FldType := Copy(Help, 1, Pos(' ', Help) - 1);
  178.             FldName := Copy(Help, Pos(' ', Help), Length(Help));
  179.             (* remove trailing and leading white space from name *)
  180.             Strip(FldName);
  181.             Names^[NFields] := FldName;
  182.             Types^[NFields] := FldType;
  183.  
  184.           end; (* THEN *)
  185.       end; (* WHILE *)
  186.  
  187.     Close(F);
  188.     (* Return error if no fields were found *)
  189.     if NFields = 0 then
  190.       LoadTableStructure := FAILURE
  191.     else
  192.       LoadTableStructure := SUCCESS;
  193.  
  194.   end; (* LoadTableStructure *)
  195.  
  196.  
  197. (*
  198.  *   Procedure:
  199.  *          FreeTableStructure
  200.  *
  201.  *    Arguments:
  202.  *          None
  203.  *
  204.  *    Description:
  205.  *          Frees memory associated with table structure
  206.  *
  207.  *    Returns:
  208.  *          None
  209.  *)
  210.  
  211. procedure FreeTableStructure;
  212.  
  213.   begin
  214.     Dispose(Names);
  215.     Dispose(Types);
  216.   end; (* FreeTableStructure *)
  217.  
  218.  
  219. (*
  220.  *    Procedure:
  221.  *          NewFonedex
  222.  *
  223.  *    Arguments:
  224.  *          None
  225.  *
  226.  *    Description:
  227.  *          Create a new fonedex database. The structure of this data
  228.  *          base is read in from an ASCII disk file.
  229.  *
  230.  *    Returns:
  231.  *          None
  232.  *)
  233. procedure NewFonedex;
  234.  
  235.   begin
  236.     (* First load the structure of the table from an ASCII data file *)
  237.  
  238.     if LoadTableStructure = FAILURE then
  239.       WriteLn('FONEDEX: Cannot load table structure')
  240.     else (* try and create it *)
  241.     if not Error(PXTblCreate(DataFile, NFields, Names, Types)) then (* Free up
  242.                                         the table structure *)
  243.       FreeTableStructure;
  244.  
  245.   end; (* NewFonedex *)
  246.  
  247.  
  248. (*
  249.  *    Function:
  250.  *          GetTableStructure
  251.  *
  252.  *    Arguments:
  253.  *          None
  254.  *
  255.  *    Description:
  256.  *          Retrieves table field names and types.
  257.  *
  258.  *    Returns:
  259.  *          SUCCESS     structure loaded
  260.  *          FAILURE     error occurred
  261.  *)
  262.  
  263. function GetTableStructure: Boolean;
  264.  
  265.   var
  266.     FldName, FldType: NameString;
  267.     I: Word;
  268.  
  269.   begin
  270.  
  271.     NFields := 0;
  272.     New(Names);
  273.     New(Types);
  274.  
  275.     if Error(PXRecNFlds(TblHandle, NFields)) then; (* ignore Result *)
  276.     for I := 1 to NFields do
  277.  
  278.       if not Error(PXFldName(TblHandle, I, FldName)) and
  279.          not Error(PXFldType(TblHandle, I, FldType)) then
  280.         begin
  281.           Names^[I] := FldName;
  282.           Types^[I] := FldType;
  283.         end
  284.       else
  285.         begin
  286.           GetTableStructure := FAILURE;
  287.           Exit;
  288.         end;
  289.     GetTableStructure := SUCCESS;
  290.  
  291.   end; (* GetTableStructure *)
  292.  
  293.  
  294. (*
  295.  *    Procedure:
  296.  *          OpenFonedex
  297.  *
  298.  *    Arguments:
  299.  *          None
  300.  *
  301.  *    Description:
  302.  *          Opens the fonedex table
  303.  *
  304.  *    Returns:
  305.  *          None
  306.  *)
  307. procedure OpenFonedex;
  308.  
  309.   begin
  310.     (* Attempt to open the table and allocate a record buffer. If table
  311.        is open, inidicate an error *)
  312.  
  313.     if TableIsOpen then
  314.       begin
  315.         WriteLn('table already opened');
  316.         Exit;
  317.       end;
  318.     (* Now try and open the table *)
  319.     if Error(PXTblOpen(DataFile, TblHandle, 0, False)) then
  320.       Exit;
  321.  
  322.     (* Allocate a record buffer *)
  323.  
  324.     if Error(PXRecBufOpen(TblHandle, RecHandle)) then
  325.       Exit;
  326.     if GetTableStructure = FAILURE then
  327.       Exit;
  328.     TableIsOpen := True;
  329.  
  330.   end; (* OpenFonedex *)
  331.  
  332.  
  333. (*
  334.  *    Procedure:
  335.  *          CloseFonedex
  336.  *
  337.  *    Arguments:
  338.  *          None
  339.  *
  340.  *    Description:
  341.  *          Closes the fonedex table if opened
  342.  *
  343.  *    Returns:
  344.  *          None
  345.  *)
  346. procedure CloseFonedex;
  347.  
  348.   begin
  349.  
  350.     if not TableIsOpen then
  351.       begin
  352.         WriteLn('table not open');
  353.         Exit;
  354.       end;
  355.     (* Free the record buffer *)
  356.     if Error(PXRecBufClose(RecHandle)) then
  357.       Exit;
  358.  
  359.     (* Close the table *)
  360.  
  361.     if Error(PXTblClose(TblHandle)) then
  362.       Exit;
  363.     FreeTableStructure;
  364.     TableIsOpen := False;
  365.  
  366.   end; (* CloseFonedex *)
  367.  
  368.  
  369. (*
  370.  *    Function:
  371.  *          GetData
  372.  *
  373.  *    Arguments:
  374.  *          FH       field number to retrieve data
  375.  *          S        string where data is stored
  376.  *
  377.  *    Description:
  378.  *          Retrieves in a string format any valid Paradox type.
  379.  *
  380.  *    Returns:
  381.  *          SUCCESS  No errors retrieving data
  382.  *          FAILURE  Error retrieving data
  383.  *)
  384.  
  385. function GetData(FH: FieldHandle;
  386.                  var S: String ): Boolean;
  387.  
  388.  
  389.   var
  390.     TheDate: TDate;
  391.     Month, Day, Year: Integer;
  392.     TheValue: Double;
  393.     TheShort: Integer;
  394.     IsBlank: Boolean;
  395.     Help: String ;
  396.  
  397.   begin
  398.     (* if this field is blank, we want to return a blank string *)
  399.  
  400.     GetData := SUCCESS;
  401.     if not Error(PXFldBlank(RecHandle, FH, IsBlank)) then
  402.       if IsBlank then
  403.         S := ''
  404.  
  405.       else
  406.         case UpCase(Types^[FH][1]) of
  407.           'A':
  408.             if Error(PXGetAlpha(RecHandle, FH, S)) then
  409.               GetData := FAILURE;
  410.           'D':
  411.             if not Error(PXGetDate(RecHandle, FH, TheDate)) then
  412.               begin
  413.                 ErrIgnore(PXDateDecode(TheDate, Month, Day, Year));
  414.                 Str(Month, S);
  415.                 Str(Day, Help);
  416.                 S := S + '/' + Help;
  417.                 Str(Year, Help);
  418.                 S := S + '/' + Help;
  419.               end
  420.             else
  421.               GetData := FAILURE;
  422.           'N':
  423.             if not Error(PXGetDoub(RecHandle, FH, TheValue)) then
  424.               Str(TheValue: 5: 0, S)
  425.             else
  426.               GetData := FAILURE;
  427.           '$':
  428.             if not Error(PXGetDoub(RecHandle, FH, TheValue)) then
  429.               Str(TheValue: 6: 2, S)
  430.             else
  431.               GetData := FAILURE;
  432.           'S':
  433.             if not Error(PXGetShort(RecHandle, FH, TheShort)) then
  434.               Str(TheShort, S)
  435.             else
  436.               GetData := FAILURE;
  437.         end (* case *)
  438.     else
  439.       GetData := FAILURE; (* an error occured in PXFldBlank *)
  440.  
  441.   end; (* GetData *)
  442.  
  443.  
  444. (*
  445.  *    Function:
  446.  *          PutData
  447.  *
  448.  *    Arguments:
  449.  *          FieldNumber             field number to store data
  450.  *          S                       string to be stored
  451.  *
  452.  *    Description:
  453.  *          Stores a string in any valid Paradox type.
  454.  *
  455.  *    Returns:
  456.  *          SUCCESS  No errors storing data
  457.  *          FAILURE  Error storing data
  458.  *)
  459.  
  460. function PutData(FH: FieldHandle;
  461.                  S: String ): Boolean;
  462.  
  463.   var
  464.     TheDate: TDate;
  465.     Month, Day, Year: Integer;
  466.     TheValue: Double;
  467.     TheShort: Integer;
  468.     Code: Integer;                      (* needed for VAL *)
  469.  
  470.  
  471.  
  472.   function GetNextWVal(var S: String ): Word;
  473.  
  474.     const
  475.       Delim = '/';
  476.  
  477.     var
  478.       L: Byte;
  479.       Help: Word;
  480.       Code: Integer;
  481.  
  482.     begin
  483.       L := Pos(Delim, S);
  484.       if L = 0 then
  485.         L := Length(S) + 1;
  486.       Val(Copy(S, 1, L - 1), Help, Code);
  487.       S := Copy(S, L + 1, Length(S));
  488.       if Code = 0 then
  489.         GetNextWVal := Help
  490.       else
  491.         GetNextWVal := 0;
  492.     end; (* GetNextWVal *)
  493.   begin
  494.  
  495.     PutData := SUCCESS;
  496.     case UpCase(Types^[FH][1]) of
  497.       'A':
  498.         if Error(PXPutAlpha(RecHandle, FH, S)) then
  499.           PutData := FAILURE;
  500.       'D':
  501.         begin
  502.           Month := GetNextWVal(S);
  503.           Day := GetNextWVal(S);
  504.           Year := GetNextWVal(S);
  505.           if Error(PXDateEncode(Month, Day, Year, TheDate)) or
  506.              Error(PXPutDate(RecHandle, FH, TheDate)) then
  507.             PutData := FAILURE;
  508.         end;
  509.       '$', 'N':
  510.         begin
  511.           Val(S, TheValue, Code);
  512.           if Error(PXPutDoub(RecHandle, FH, TheValue)) then
  513.             PutData := FAILURE;
  514.         end;
  515.       'S':
  516.         begin
  517.           Val(S, TheShort, Code);
  518.           if Error(PXPutShort(RecHandle, FH, TheShort)) then
  519.             PutData := FAILURE;
  520.         end;
  521.  
  522.     end; (* case *)
  523.   end; (* PutData *)
  524.  
  525.  
  526. (*
  527.  *    Function:
  528.  *          InputRecord
  529.  *
  530.  *    Arguments:
  531.  *          None
  532.  *
  533.  *    Description:
  534.  *          Allows editing of an existing record buffer and lets
  535.  *          user accept, cancel, or re-edit.
  536.  *
  537.  *    Returns:
  538.  *          SUCCESS     User accepts changes
  539.  *          FAILURE     Changes declined
  540.  *)
  541. function InputRecord: Boolean;
  542.  
  543.   var
  544.     C: Char;
  545.     I: Word;
  546.     Buf: String ;
  547.  
  548.   begin
  549.     InputRecord := FAILURE;
  550.     (* Keep attempting to input until user selects DONE or CANCEL *)
  551.  
  552.     while True do
  553.       begin
  554.         (* Go through all fields *)
  555.         for I := 1 to NFields do
  556.           begin
  557.             (* translate the current value into the input buffer *)
  558.             if GetData(I, Buf) <> SUCCESS then
  559.               Exit;
  560.  
  561.             WriteLn(Buf);
  562.             (* ask for the new value *)
  563.             Write(Names^[I], ': ');
  564.             ReadLn(Buf);
  565.  
  566.       (* Now translate it back into the record buffer unless old value
  567.          is kept by just hitting return. *)
  568.  
  569.             if Length(Buf) > 0 then
  570.               if PutData(I, Buf) <> SUCCESS then
  571.                 Exit;
  572.  
  573.           end; (* for *)
  574.         (* Ask what to do with this input *)
  575.  
  576.         WriteLn('S)ave, C)ancel, R)edo:');
  577.         repeat
  578.           C := UpCase(ReadKey);
  579.         until C in ['S', 'C', 'R'];
  580.         case C of
  581.           'S':
  582.             begin
  583.               InputRecord := SUCCESS;
  584.               Exit;
  585.             end;
  586.           'C': Exit;
  587.         end; (* case *)
  588.  
  589.       end; (* while *)
  590.   end; (* InputRecord *)
  591.  
  592.  
  593. (*
  594.  *    Procedure:
  595.  *          AddEntry
  596.  *
  597.  *    Arguments:
  598.  *          None
  599.  *
  600.  *    Description:
  601.  *          Add a new record to the fonedex table
  602.  *
  603.  *    Returns:
  604.  *          None
  605.  *)
  606. procedure AddEntry;
  607.  
  608.   begin
  609.  
  610.     if not TableIsOpen then
  611.       begin
  612.         WriteLn('Table not opened');
  613.         Exit;
  614.       end;
  615.     (* Empty the current record buffer *)
  616.     if Error(PXRecBufEmpty(RecHandle)) then
  617.       Exit;
  618.  
  619.     (* get the fields unless input is cancelled by user *)
  620.     if InputRecord = FAILURE then
  621.       Exit;
  622.     (* Attempt to append the record *)
  623.     ErrIgnore(PXRecAppend(TblHandle, RecHandle));
  624.  
  625.   end; (* AddEntry *)
  626.  
  627.  
  628. (*
  629.  *    Function:
  630.  *          InputField
  631.  *
  632.  *    Arguments:
  633.  *          FieldNumber          Field number selected
  634.  *
  635.  *    Description:
  636.  *          Displays and accepts a legal field number
  637.  *
  638.  *    Returns:
  639.  *          SUCCESS              valid field number entered
  640.  *          FAILURE              invalid field number entered
  641.  *)
  642. function InputField(var FieldNumber: FieldHandle): Boolean;
  643.  
  644.   var
  645.     Buf: String ;
  646.  
  647.   begin
  648.     (* Get the field number as an integer *)
  649.  
  650.     FieldNumber := Ord(ReadKey) - Ord('0');
  651.     if (FieldNumber < 1) or (FieldNumber > NFields) then
  652.       begin
  653.         WriteLn('illegal field number');
  654.         InputField := FAILURE;
  655.         Exit;
  656.       end;
  657.  
  658.     (* Input the field *)
  659.  
  660.     Write(Names^[FieldNumber], ': ');
  661.     ReadLn(Buf);
  662.     (* And translate it *)
  663.     if PutData(FieldNumber, Buf) <> SUCCESS then
  664.       begin
  665.         InputField := FAILURE;
  666.         Exit;
  667.       end;
  668.     InputField := SUCCESS;
  669.  
  670.   end; (* InputField *)
  671.  
  672.  
  673. (*
  674.  *    Procedure:
  675.  *          SearchUpdate
  676.  *
  677.  *    Arguments:
  678.  *          None
  679.  *
  680.  *    Description:
  681.  *          Edits and Updates the currently selected record.    Record
  682.  *          locking is used to stop multiple updates.
  683.  *
  684.  *    Returns:
  685.  *          None
  686.  *)
  687. procedure SearchUpdate;
  688.  
  689.   var
  690.     LckHandle: LockHandle;
  691.  
  692.   begin
  693.     (* Lock the record *)
  694.  
  695.     if not Error(PXNetRecLock(TblHandle, LckHandle)) then (* Edit the record *)
  696.       begin
  697.         if InputRecord <> FAILURE then (* Update it *)
  698.           if PXRecUpdate(TblHandle, RecHandle) <> PXSUCCESS then
  699.             Exit;
  700.         (* And unlock it *)
  701.         ErrIgnore(PXNetRecUnlock(TblHandle, LckHandle));
  702.       end;
  703.  
  704.   end; (* SearchUpdate *)
  705.  
  706.  
  707. (*
  708.  *    Procedure:
  709.  *          ProcessSearch
  710.  *
  711.  *    Arguments:
  712.  *          FieldNumber             field number to search on
  713.  *
  714.  *    Description:
  715.  *          Performs actual search on given field.    Allows user to
  716.  *          Delete and Update records.
  717.  *
  718.  *    Returns:
  719.  *          None
  720.  *)
  721. procedure ProcessSearch(FieldNumber: FieldHandle);
  722.  
  723.   var
  724.     Mode: Integer;
  725.     I: Integer;
  726.     Done: Boolean;
  727.     Buf: String ;
  728.  
  729.   begin
  730.     Mode := SEARCHFIRST;
  731.     Done := True;
  732.  
  733.     while True do
  734.       begin
  735.         (* If no match found, get out *)
  736.         if PXSrchFld(TblHandle, RecHandle, FieldNumber,
  737.            Mode) <> PXSUCCESS then
  738.           begin
  739.             WriteLn('No Matches');
  740.             Exit;
  741.           end;
  742.  
  743.         (* Get the record found *)
  744.  
  745.         if Error(PXRecGet(TblHandle, RecHandle)) then
  746.           Exit;
  747.         (* Print the record *)
  748.         for I := 1 to NFields do
  749.           begin
  750.             if GetData(I, Buf) <> SUCCESS then
  751.               Exit;
  752.             WriteLn(Names^[I], ': ', Buf);
  753.           end;
  754.  
  755.         WriteLn('N)ext, D)elete, U)pdate, E)xit Search:');
  756.         repeat
  757.           case UpCase(ReadKey) of
  758.             'N':
  759.               begin (* Search for the next occurrence *)
  760.                 Mode := SEARCHNEXT;
  761.                 Done := True;
  762.               end;
  763.             'D':
  764.               begin
  765.                 ErrIgnore(PXRecDelete(TblHandle));
  766.                 Exit;
  767.               end;
  768.             'U':
  769.               begin
  770.                 SearchUpdate;
  771.                 Exit;
  772.               end;
  773.             'E': Exit;
  774.             else Done := False;
  775.           end; (* case *)
  776.         until Done;
  777.       end; (* while *)
  778.  
  779.   end; (* ProcessSearch *)
  780.  
  781.  
  782. (*
  783.  *    Procedure:
  784.  *          Search
  785.  *
  786.  *    Arguments:
  787.  *          None
  788.  *
  789.  *    Description:
  790.  *          Search functions
  791.  *
  792.  *    Returns:
  793.  *          None
  794.  *)
  795. procedure Search;
  796.  
  797.   var
  798.     FieldNumber, I: Word;
  799.  
  800.   begin
  801.     (* Make sure table is opened *)
  802.  
  803.     if not TableIsOpen then
  804.       begin
  805.         WriteLn('table not open');
  806.         Exit;
  807.       end;
  808.     (* Refresh the database in case anyone else has updated it *)
  809.     ErrIgnore(PXNetTblRefresh(TblHandle));
  810.  
  811.     (* List the fields to search on *)
  812.  
  813.     WriteLn('Select Field');
  814.     for I := 1 to NFields do
  815.       WriteLn(I, ' ', Names^[I]);
  816.     (* Get the input field to search on *)
  817.     if InputField(FieldNumber) = FAILURE then
  818.       Exit;
  819.     (* Perform Search Options *)
  820.     ProcessSearch(FieldNumber);
  821.  
  822.   end; (* Search *)
  823.  
  824.  
  825. (*
  826.  *  Procedure:
  827.  *    Menu
  828.  *
  829.  *  Arguments:
  830.  *    None
  831.  *
  832.  *  Description:
  833.  *    Displays a menu structure, gets a valid menu response
  834.  *    and dispatches to the appropriate function.
  835.  *
  836.  *  Returns:
  837.  *    None
  838.  *
  839.  *)
  840. procedure Menu;
  841.  
  842.   var
  843.     C: Char;
  844.  
  845.   begin
  846.  
  847.     repeat
  848.       WriteLn;
  849.       WriteLn('Main Menu');
  850.       WriteLn('   1  -  New Fonedex');
  851.       WriteLn('   2  -  Open Fonedex');
  852.       WriteLn('   3  -  Close Fonedex');
  853.       WriteLn('   4  -  Add Entry');
  854.       WriteLn('   5  -  Search');
  855.       WriteLn('   6  -  Quit');
  856.       C := ReadKey;
  857.  
  858.       case C of
  859.         '1': NewFonedex;
  860.         '2': OpenFonedex;
  861.         '3': CloseFonedex;
  862.         '4': AddEntry;
  863.         '5': Search;
  864.         '6': ; (* Do nothing *)
  865.         else WriteLn('Invalid option.');
  866.       end; (* case *)
  867.     until C = '6';
  868.  
  869.   end; (* menu *)
  870.  
  871.  
  872. (*
  873.  * Description:
  874.  *   Initializes the Engine and calls the main menu
  875.  *   When the main menu returns, the table is closed
  876.  *   if it was left open.
  877.  *)
  878.  
  879. begin
  880.   TableIsOpen := False; (* table is not open *)
  881.   (* Initialize the Engine *)
  882.   if Error(PXNetInit(NetDir, NetType, UserName)) then
  883.     Halt(1);
  884.   (* Menu loop *)
  885.   Menu;
  886.   (* Close table if open *)
  887.  
  888.   if TableIsOpen then
  889.     CloseFonedex;
  890.   (* Terminate the Engine *)
  891.   if Error(PXExit) then
  892.     Halt(1);
  893.  
  894. end.
  895.