home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a006 / 1.ddi / CSAMP.ZIP / FONEDEX.C next >
Encoding:
C/C++ Source or Header  |  1991-03-11  |  19.4 KB  |  868 lines

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