[comp.sys.handhelds] Phone number manager V1.3

ervin@pinbot.enet.dec.com (Joseph Ervin) (01/18/91)

Here's the newest version of my phone number manager.

New in this version:  a bug has been fixed which caused the program to
crash after  adding a name unless the program was exited and entered again. 
This has been fixed.

Also changed is the addition of a PREV menu choice when in the SRCH subsystem. 
Using this menu key now enables the user to step backward as well as forward
through the list of entries which have matched against the search string input
by the user. 


***************

   This program is a basic database program designed to keep a list of 
   phone numbers and provide access to them, editing, etc..

   To run it just download the following code and evaluate the program
   object. 

   The first time you run it, you'll be informed that no database exists
   and that you should create it.    

   When creating the database, which happens automatically the first time
   you run the program, you'll be prompted alternately for a name and a 
   phone number.  Just keep entering the data at the prompts, and when your
   through just hit ENTER at the name prompt without entering any data. 
   This will  terminate the input mode.  

   Note: This method of input termination works any time you are prompted
   for a  name and decide not to enter one.  Remember this as it will come
   in handy at  other times when the program prompts you for a name.

   Once you have created a database, running the program will prompt you as
   to  whether you want to search the list or edit the list.  

1. SEARCHING THE LIST. 
 
   The way to search the list is by pressing SRCH when prompted. The
   program will search each name in the  list for any occurance of the
   string you enter (when prompted).  This way,  you can search for people
   by last name, or whatever.  For example, if you  have the phone numbers
   of all the local movie theaters, then entering  CINEMA at the prompt
   will give you a list of all the movie theaters  (assuming you were smart
   enough to use the string "CINEMA" as part of the name for each movie
   theater).  You get the idea.

2. EDITING THE LIST.  

   Basically, just follow the prompts and you'll do well. I  tried to make
   this fairly straightforward, and I have put in some degree of error
   checking of input data to make sure it makes sense, but I'm sure you can
   get it to crash if you try.   Some simple rules to follow:  Avoid typing 
   over the ":Name:" or ":Number:" strings when entering data at a prompt. 
   The program uses these strings internally to find your input, so if you
   type  over them, the program will get confused trying to isolate the
   name and  number from within the input string.


   The program uses the SRCH algorithm described above to locate the exact
   item you wish to edit.  When you have the exact item you wish to edit on
   the  screen, press PICK and you will have a chance to make your changes. 
   This  goes for deleteing entries as well.

   Any time you see an EXIT option on the menu bar, you can press it to
   back  out of the program.  Sometimes it backs you out one menu level,
   and sometimes you exit the program entirely.  I tried to handle each
   case in the most natural way, rather than always doing the same thing. 
   I hope you agree that this was the way to go.



   Anyway, here's version 1.3 of the program.  I hope you like it.  The
   comments will automatically strip out when you download to your
   calculator. 

   Enjoy, and please give me your comments.

   Regards,

   >>>Joe

**********************   CUT HERE  **************************************

%%HP: T(3)A(R)F(.);
\<<  @ Start of Program @
@ PHONE V1.3 by Joe Ervin.  15-JAN-1991 @
@ NEW FEATURES FOR V1.3.   
@ Added a PREV menu choice in the PHSEARCH routine to allow the user to
@ move backwards through the list of matches.

CLEAR
{} @ Dummy value to hold place for PHNAMES. @
{} @ Dummy value to hold place for PHNUMBERS. @
0 
\-> PHNAMES PHNUMBERS  PHSIZE 
   @ Creates local storage for names and numbers. @

\<< @ Surounds the procedures as well as main routine. @

\<<  @Start definition of PHSEARCH routine.@ 
CLEAR

0 0 0 {} 0 \-> 
        SRCHNAME  @ Local variable to hold the search name. @
        DONE      @ Local variable to detect when search has finished. @
        MATCHNUM  @ Local variable to store the number of matches.  @
        MATCHLIST     @ Stores list of matches. @
        MATCHINDEX    @ Used to index into the match list. @

@ What we are going to do now is to step through each name in the list, and @
@ for each name, we will do a pattern match of the search name within each@ 
@ name in the list. If the searchname is found within a given name, then @
@ the index corresponding to the matched name will be added to MATCHLIST. @
@ This routine uses flag 1 to indicate success or failure to the calling @
@ routine. (SET = success, CLEAR = failure - i.e. no matches.  @ 
@ Flag 2 is also used to indicate whether the main routine should exit @
@ or prompt the user for another choice whether to search or edit the @
@ phone list. @
                                                                            
\<< @This delimiter surrounds PHSEARCH's local variables@


{} TMENU  @ Just to clear the menu from the main routine. @
"Enter name..." {":Name:" \Ga} INPUT @Prompt user for name to search.@

IF DUP SIZE 6 \<=   @ If no name was entered. @ 
THEN 
 1 SF  @ To indicate successfull completion of search routine. @
 2 SF  @ To cause the main routine to ask again: SEARCH or EDIT.  @
 4 CF @ Just in case this routine was called from PHEDIT. @
ELSE
  DUP SIZE 7 SWAP SUB 'SRCHNAME' STO
  PHNAMES  OBJ\->@ Puts the list of names on the stack.@
  IF SRCHNAME "*" SAME THEN 3 SF END
  1 SWAP FOR I  @ Step through the whole list of names. @
    SRCHNAME  @ Put the string to search for on the stack. @
    IF POS 3 FS? OR 
    @ If SRCHNAME exists anywhere within the name...@  
    THEN
      'MATCHNUM'  INCR DROP @ Add one to the number of matches. @
      'PHSIZE - I + 1' EVAL 
      'MATCHLIST' STO+  @ Add the match index to list of match indices. @
    END  @ End this match check. @
  1 STEP   @ End loop checking for matches. @
  3 CF

  IF MATCHNUM 0 \=/   @ IF there were at least some matches...@
  THEN 
    1 SF  2 CF   @ To indicate success to the calling routine. @
    MATCHLIST 
    1  @ To initialize index into matchlist. @
    DO   @ Display list of matches until done. @
      GETI  @ Fetch the next item pointed to by the matchindex. @ 
      'MATCHINDEX' STO DUP 
      IF 1 == THEN MATCHNUM ELSE DUP 1 - END
      @ Now display which match we are looking at. @
      "Match " SWAP + " of "  + MATCHNUM + 
      ":Number:" PHNUMBERS MATCHINDEX GET +  
      @ Concatenates label to number. @
      ":Name:" PHNAMES MATCHINDEX GET + 
      @ Concatenates label to name. @
      CLLCD 5 DISP 6 DISP 1 DISP 3 FREEZE
      IF 4 FC?
      THEN 
        {{"Next" \<< CONT \>> } {"Prev" \<<  \-> X
        \<< CASE
        'X==1' THEN 'MATCHNUM-1' EVAL CONT END @So next index will be MATCHNUM.
        'X==2' THEN MATCHNUM CONT END @ So next index will be 1.
        'X-2' EVAL CONT @ Do this by default to back up one index.
        END \>> @ end of case statement.
        \>> }                   
        {} {} {} {"Exit" 
        \<< 1 'DONE' STO CONT \>>} } TMENU HALT 
      ELSE
        {{"Next" \<< CONT \>> } {"Prev" \<<  \-> X
        \<< CASE
        'X==1' THEN 'MATCHNUM-1' EVAL CONT END @So next index will be MATCHNUM.
        'X==2' THEN MATCHNUM CONT END @ So next index will be 1.
        'X-2' EVAL CONT @ Do this by default to back up one index.
        END \>> @ end of case statement.
        \>> }                   
        {"Pick" 
        \<<IF DUP 1 == THEN DROP MATCHNUM ELSE 1 - END GET 1 'DONE' STO 
        4 CF CONT \>>} 
        {} {} {"Exit" 
        \<< 1 'DONE' STO 1 CF 2 SF CONT \>>} } TMENU HALT 
      END 
    UNTIL DONE
    END
  ELSE  @  If there were no matches...@
    "The specified name
was not found" @ To indicate search failure. @
    1 CF 2 CF @ To indicate failure to the calling routine. @
    CLLCD 1200 .1 BEEP 2 DISP 1 WAIT
  END
END
\>>
\>> @Ends definition of PHSEARCH routine.@ 

\-> PHSEARCH @ Creates the subroutine PHSEARCH. @
\<<
\<< @ Definition of the PHEDIT routine starts here. @
\-> P1 @ Take the parameter passed in on the stack. @
\<< IF P1 "INT" SAME 
THEN 

@ At this point, the local variables "PHNAMES" and "PHNUMBERS" contain the @
@ names and numbers of the list to be edited.  Now we need to present the @
@ user with a meaningful display from which to choose actions.  The actions @
@ allowed include "MODIFY" and "ADD".  The following code prompts the user @
@ to choose between these two options, and then performs the simple editing @
@ function. @

    "Do you want to add
to the list, modify
an existing entry,
or delete an entry?" 
    CLLCD 1 DISP 3
    FREEZE {{"Add" \<<"ADD" CONT\>>} {"Mdfy" \<<"MODIFY" 5 CF CONT\>>} 
    {"Del"  \<<"MODIFY" 5 SF CONT \>>} {} {} 
    {"EXIT" \<<2 SF CONT\>>}} TMENU HALT

ELSE CLEAR "ADD" @ This is for when PHEDIT was called by main with @
                 @ P1 of "NEW". @
END 

@ This is for the case when PHEDIT was called by the main routine for  @
@ the case where there was no phone list. @
 
IF 2 FC?C 
THEN 
     
{} TMENU  @ Clear the menu from what was previously there. @
0 0 0 0 \-> X TEMP LEN LEN2 DONE
\<< CASE  
@ Note the creation of the scratch variables 'TEMP', 'LEN', 'LEN2'.@
@ 'TEMP' is scratch for the name, LEN is scratch for the name's length, @
@ and 'LEN2' is scratch for the length of the phone number. @
@ DONE is used for the repeat loop. @
@ X gets the "ADD" or "MODIFY" string from the above prompt. @

  X "ADD" SAME @ Here we are adding to the list of names. @
      THEN
      DO 
        "Enter name..." {":Name:" \Ga} INPUT 
        @ Prompts the user to enter the name for this entry. @
        @ Now we need to build up the command line for the INPUT command @
        @ which will pull in the number for this entry.  We want to @
        @ display the name above where the user is going to enter the @
        @ number. @
        DUP SIZE 'LEN' STO 'TEMP' STO 
        IF LEN 6 \=/ 
        THEN 
          "Enter number..." TEMP EVAL "
:Number:" + { 2 9 }
          \Ga 3 \->LIST INPUT 
       
          @ The current prompt shows the name and prompts for @
          @ the phone number. @
       
          @ Now save the new information and update PHSIZE.
          DUP DUP SIZE 'LEN2' STO 7 LEN SUB PHNAMES + 'PHNAMES' STO 
          LEN 10 +
          LEN2 SUB PHNUMBERS + 'PHNUMBERS' STO 
          PHNAMES SIZE 'PHSIZE' STO
        ELSE 
          1 'DONE' STO
        END
      UNTIL DONE 
      END
    END  @"ADD"@

    X "MODIFY" SAME 
      THEN         @ User wants to edit the list @

      CLEAR
      0 0 ""  \-> INDEX  @ Stores the index of the entry to be edited. @
                DONE     @ Used to terminate DO UNTIL loop. @
                EDITSTRING   @ Stores the modified string. @

\<<
      @ Basically what I want to do here is to call the PHSEARCH routine @
      @ in a way that it will get the user to pick a specific entry.  @
      @ I want to use the PHSEARCH routine to do this since so much of @
      @ the code needed to do this is alread done.  The result of the @
      @ PHSEARCH routine is to return an index indicating the exact @
      @ entry which is to be edited.  This routine then needs only @
      @ display it in an input statement in such a way that the user @
      @ can modify it as it sits on the display.  When the user presses @
      @ ENTER, the modified entries (name and number) will be written @
      @ back into the database. @
      @ This routine also checks flag 5 to determine whether the user @
      @ wants to delete the record or simply modify it. @
     
      DO 
        4 SF PHSEARCH EVAL @ To get the index of entry to be modified. @
      UNTIL 1 FS?C @ Repeat search routine until user selects an entry @
                   @ or gives up. @
      END  
      4 CF   @ Flag 4 was set only to indicate to PHSEARCH to use "pick" in @
                @ the menu so user could choose the item to edit.
      IF 2 FC?C  @ If flag 2 is set, then the user must have given up @
                 @ trying to select an entry to edit. @
      THEN  @ Let's edit the selected entry @
      'INDEX' STO 
        IF 5 FC?C 
        THEN 
          DO 
            INDEX DUP 
            PHNAMES SWAP GET @ Gets the name to be modified. @
            SWAP PHNUMBERS SWAP GET   @ Gets number to be modified. @

            @ The stack now has           @
            @                   2: name   @
            @                   1: number @

            @ Now reformat the information for the INPUT command. @
        
            ":Number:" SWAP +
            SWAP ":Name:" SWAP +   @ Adds tags to the name and number. @
            "
"
            + SWAP +  @ Creates one long string with a carraige return @
            @ to separate the name and number strings. @
        

            @ Now display this information using INPUT so the user can @
            @ edit the strings. @


            "Edit entry..."  SWAP { 2 0 }
            2 \->LIST {} TMENU INPUT

            @ At this point, the user has been prompted with the name and @
            @ number to be modified.  The keyboard is in overstrike mode @
            @ and the cursor was left at the end of the number. @

            @ Now we must recover the new name and number from the @
            @ string on the stack. @
 
            DUP 'EDITSTRING' STO   @ Save a copy of the string. @
            IF DUP ":Name:" POS 1 ==   @ Test for existence of the name @
            SWAP DUP ":Number:" POS    @ and number tags within the string. @
            DUP 'TEMP' STO ROT AND    
            THEN    @ The user entered valid data. @

              @ Update the database with new name.@
              DUP 7 TEMP 2 - SUB @ Extract the name tag and modified name. @
              1 \->LIST PHNAMES SWAP INDEX SWAP REPL
              'PHNAMES' STO  

              @ Update the database with the new number. @
              TEMP 8 + EDITSTRING SIZE SUB @ Extract the new name. @
              1 \->LIST PHNUMBERS SWAP INDEX SWAP REPL 
              'PHNUMBERS' STO 

              1 'DONE' STO 
              CLEAR
            ELSE CLLCD 1200 .1 BEEP "Invalid Entry" 2 DISP 2 WAIT
            END
          UNTIL DONE
          END
        ELSE    @ The user wants to delete the entry.  @
          CLEAR INDEX DUP 
          PHNAMES SWAP GET @ Gets the name to be modified. @
          SWAP PHNUMBERS SWAP GET   @ Gets number to be modified. @

          @ The stack now has           @
          @                   2: name   @
          @                   1: number @

          @ Now reformat the information for the INPUT command. @
        
          ":Number:" SWAP +
          SWAP ":Name:" SWAP +   @ Adds tags to the name and number. @
          "
"
          + SWAP +  @ Creates one long string with a carraige return @
          @ to separate the name and number strings. @
        

          @ Now display this information and prompt user to verify that @
          @ this record should be deleted.   

          CLLCD  "Delete entry?"  1 DISP
          5 DISP 1200 .1 BEEP 3 FREEZE YN TMENU HALT
          IF   @ yes @
          THEN 
            PHNAMES  OBJ\->  DROP @ Put the list of names on the stack. @
            PHSIZE INDEX 1 - - ROLL 
            DROP   @ Deletes the entry pointed to by INDEX. @
            PHSIZE 1 - \->LIST 'PHNAMES' STO  

            PHNUMBERS  OBJ\->  DROP @ Put the list of names on the stack. @
            PHSIZE INDEX 1 - - ROLL 
            DROP  @ Deletes the entry pointed to by INDEX. @
            'PHSIZE'  DECR \->LIST 'PHNUMBERS' STO  
          END
        END
      ELSE 5 CF 
      END
\>>
    END
  END  
\>>    @end case@
END  @IF 2 FC?C

PHNUMBERS PHNAMES 2 \->LIST 'PHDAT' STO


\>> @ Surrounds PHEDIT's parameters. @
\>> @ Ends the definition of PHEDIT and pushes PHEDIT on the stack @
    @ to be defined later.@





 \-> PHEDIT @ Defines the subroutine "PHEDIT", which edits the database. @
           @ PHEDIT takes as parameters a single string which must have the @
           @ value "NEW", indicating a new list should be created, @
           @ or "INT", indicating the old list should be prompted as to 
           @ whether the current list is to be added to or edited. @
 
\<< @ The main routine starts here. @
IF 'PHDAT' VTYPE -1 ==   
  THEN
  CLLCD 
  "Phone Database does" 2 DISP "not exist.  Do you"
  3 DISP "want to create it?"
  4 DISP 3 FREEZE 
  YN TMENU HALT  @ Prompt the user for yes/no @
  IF 
    THEN  
    {} DUP 'PHNAMES' STO 'PHNUMBERS' STO 
    "NEW" PHEDIT  EVAL @ tells PHEDIT to go directly to the @
                             @ edit input mode on a new list @
  @ After the user exits PHEDIT, control falls down to main routine below.@
    ELSE

"You must create a
phone database before
any further action can
be taken."
      2 DISP CLEAR 2 MENU  1200 .1 BEEP 3 FREEZE  3 WAIT
      0 DOERR         @ Obviously, the user is a pinhead. @
    END 

  END 

@ We need to start the main routine.@
0 \-> DONE \<<
  @ First we need to suck in the database. @
     {} DUP 'PHNAMES' STO 'PHNUMBERS' STO 
  PHDAT EVAL
  'PHNAMES' STO  'PHNUMBERS' STO @ copies the database in the local  @
                                 @ variables 'PHNAMES' and PHNUMBERS' @

  PHNAMES SIZE 'PHSIZE' STO  @ Indicates the number of names in the list. @

  DO 
  @ Here we want to ask the user whether we are searching or editing. @
"Do you want to 
search the list or
edit the list?" 
  CLLCD 1 DISP 3 FREEZE
  {{"SRCH" \<< DO PHSEARCH EVAL UNTIL 1 FS?C END IF 2 FC?C THEN 
  1 'DONE' STO END CONT \>>}
  {"EDIT" \<< "INT" PHEDIT  EVAL CONT \>>} 
  {} 
  {} {} {"Exit" \<<1 'DONE' STO CONT \>>}} TMENU HALT
  @ "INT" for PHEDIT here to tell PHEDIT to prompt the user as to @
  @ whether he wants to edit (modify) the phone list or simply add to it.  @

  UNTIL DONE @ Keep on doing this loop until DONE. @
             @ This causes the loop to continue for "Edit". @  
  END
  \>> @ DO @
  CLEAR 2 MENU 
\>> @ Defines bounds for which PHSEARCH is defined. @
\>> @ Main Routine @
\>> @ Main routine and procedures @
\>> @ End of Program @
    

ervin@pinbot.enet.dec.com (Joseph Ervin) (01/18/91)

Terribly sorry, but I left out a needed element in my last posting of
PHONE013.   I have a simple OBJECT containing the menu
definition for a YES/NO response which I keep in my home directory for
any time
I need to ask the user for such a decision.  I inadvertently forgot to
post it
along with the program.  Stupid of me.

Here it is:

{ { "Yes" \<< 1 CONT \>> }
{} {} {} {} {"No" \<< 0 CONT \>>} }

Just enter this into the calculator and put it in your home directory so that
the PHONE program can find it.  THE OBJECT SHOULD BE NAMED "YN" so that the 
PHONE program can find it.

In retrospect, it was foolish of me to have a separate object for such a
small thing.  In the near future I will post a new version with the
above menu list 
included in the PHONE program.  I apologize for the inconvenience, and I
hope you will still try my program.  It DOES work well.  Really.

>>>Joe Ervin

Incidentally, you may find that the programs output looks nicer when you have
the display in STD mode.  That's the way I always run my machine, so I didn't 
think to force it in the program.  I'll add this function also in the
next release.

ervin@pinbot.enet.dec.com (Joseph Ervin) (01/18/91)

Sorry, I thought I said that, but I guess not.  Yes it is an HP48SX program.  

Give it a try and let me know what you think.  I'm open to suggestions for 
improvments/changes. 

>>>Joe Ervin

ardai@bass.bu.edu (Michael Ardai) (01/19/91)

PLEASE indicate what machine you are talking about.  Remember that this 
group is for any handheld computer, not just HPs.  
/mike
--
\|/ Michael L. Ardai     ardai@bu-pub.bu.edu   ...!sun!teda!ardai (preferred)
--- -------------------------------------------------------------------------
/|\ Teradyne EDA East    (617) 254-3420