home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / happydays-src-1.37.tar.gz / happydays-src-1.37.tar / happydays-1.37 / address.c next >
C/C++ Source or Header  |  2000-07-27  |  15KB  |  422 lines

  1. /*
  2. HappyDays - A Birthdate displayer for the PalmPilot
  3. Copyright (C) 1999-2000 JaeMok Jeong
  4.  
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. */
  19.  
  20. /*
  21.  * Just so you know some of these routines are pulled from the Address
  22.  * source code as provided by Palm.  At least that is what I started from,
  23.  * I may have touched a few lines to get it to compile with gcc without
  24.  * warnings.
  25.  */
  26.  
  27. #include <PalmOS.h>
  28.  
  29. #include "happydaysRsc.h"
  30. #include "happydays.h"
  31. #include "address.h"
  32. #include "util.h"
  33.  
  34.  
  35. char *UnnamedRecordStringPtr="";
  36.  
  37. /************************************************************
  38.  *
  39.  *  FUNCTION: AddrUnpack
  40.  *
  41.  *  DESCRIPTION: Fills in the AddrDBRecord structure
  42.  *
  43.  *  PARAMETERS: address record to unpack
  44.  *                the address record to unpack into
  45.  *
  46.  *  RETURNS: the record unpacked
  47.  *
  48.  *  CREATED: 1/14/95 
  49.  *
  50.  *  BY: Roger Flores
  51.  *
  52.  *************************************************************/
  53. void AddrUnpack(AddrPackedDBRecord *src, AddrDBRecordPtr dest)
  54. {
  55.     Int16 index;
  56.     UInt32 flags;
  57.     char *p;
  58.  
  59.     dest->options = src->options;
  60.     flags = src->flags.allBits;
  61.     p = &src->firstField;
  62.          
  63.     for (index=firstAddressField; index < addressFieldsCount; index++) {
  64.         /* If the flag is set point to the string else NULL */
  65.         if (GetBitMacro(flags, index) != 0) {
  66.             dest->fields[index] = p;
  67.             p += StrLen(p) + 1;
  68.         } else dest->fields[index] = NULL;
  69.     }
  70. }
  71.  
  72. /***********************************************************************
  73.  *
  74.  * FUNCTION:    DetermineRecordName
  75.  *
  76.  * DESCRIPTION: Determines an address book record's name.  The name
  77.  * varies based on which fields exist and what the sort order is.
  78.  *
  79.  * PARAMETERS:  recordP - address record
  80.  *              sortByCompany - sort by company field
  81.  *              
  82.  * RETURNED:    name1, name2 - first and seconds names to draw
  83.  *              Boolean - name1/name2 priority based on sortByCompany
  84.  *
  85.  * REVISION HISTORY:
  86.  *            Name        Date        Description
  87.  *            ----        ----        -----------
  88.  *            roger        6/20/95    Initial Revision
  89.  *            frigino      970813     Added priority return value
  90.  *
  91.  ***********************************************************************/
  92. Boolean
  93. DetermineRecordName(AddrDBRecordPtr recordP, 
  94.                     Boolean sortByCompany,
  95.                     Char **name1,
  96.                     Char **name2)
  97. {
  98.     UInt16 fieldNameChoiceList[4];
  99.     UInt16 fieldNameChoice;
  100.     Boolean name1HasPriority;
  101.  
  102.     *name1 = NULL;
  103.     *name2 = NULL;
  104.  
  105.     if (sortByCompany) {
  106.         /* When sorting by company, always treat name2 as priority. */
  107.         name1HasPriority = false;
  108.         fieldNameChoiceList[3] = addressFieldsCount;
  109.         fieldNameChoiceList[2] = firstName;
  110.         fieldNameChoiceList[1] = name;
  111.         fieldNameChoiceList[0] = company;
  112.         fieldNameChoice = 0;
  113.  
  114.         while ((*name1 == NULL) &&
  115.                (fieldNameChoiceList[fieldNameChoice] != addressFieldsCount)) {
  116.             *name1 = recordP->fields[fieldNameChoiceList[fieldNameChoice++]];
  117.         }
  118.  
  119.         /*
  120.          * When sorting by company, treat name2 as priority if we
  121.          * succeed in getting the company name as the name1
  122.          * Did we get the company name?
  123.          */
  124.         if (fieldNameChoice > 1) {
  125.             /*
  126.              * No. We got a last name, first name, or nothing.
  127.              * Priority switches to name1
  128.              */
  129.             name1HasPriority = true;
  130.         }
  131.  
  132.         while ((*name2 == NULL) &&
  133.                (fieldNameChoiceList[fieldNameChoice] != addressFieldsCount)) {
  134.             *name2 = recordP->fields[fieldNameChoiceList[fieldNameChoice++]];
  135.         }
  136.     } else {
  137.         /* When not sorting by company, always treat name1 as priority. */
  138.         name1HasPriority = true;
  139.  
  140.         fieldNameChoiceList[3] = addressFieldsCount;
  141.         fieldNameChoiceList[2] = addressFieldsCount;
  142.         fieldNameChoiceList[1] = firstName;
  143.         fieldNameChoiceList[0] = name;
  144.         fieldNameChoice = 0;
  145.  
  146.         while ((*name1 == NULL) &&
  147.                (fieldNameChoiceList[fieldNameChoice] != addressFieldsCount)) {
  148.             *name1 = recordP->fields[fieldNameChoiceList[fieldNameChoice++]];
  149.         }
  150.  
  151.         if (*name1 == NULL) {
  152.             *name1 = recordP->fields[company];
  153.             *name2 = NULL;
  154.         } else {
  155.             while ((*name2 == NULL) &&
  156.                    (fieldNameChoiceList[fieldNameChoice] != addressFieldsCount)) {
  157.                 *name2 =
  158.                     recordP->fields[fieldNameChoiceList[fieldNameChoice++]];
  159.             }
  160.         }         
  161.     }
  162.     /* Return priority status */
  163.     return name1HasPriority;
  164. }
  165.  
  166. /***********************************************************************
  167.  *
  168.  * FUNCTION:    DrawRecordName
  169.  *
  170.  * DESCRIPTION: Draws an address book record name.  It is used
  171.  * for the list view and note view.
  172.  *
  173.  * PARAMETERS:  name1, name2 - first and seconds names to draw
  174.  *              nameExtent - the space the names must be drawn in
  175.  *              *x, y - where the names are drawn
  176.  *
  177.  * RETURNED:    x is set after the last char drawn
  178.  *
  179.  * REVISION HISTORY:
  180.  *            Name        Date      Description
  181.  *            ----        ----      -----------
  182.  *            roger      6/20/95   Initial Revision
  183.  *            frigino    970813    Rewritten. Now includes a variable ratio for
  184.  *                             name1/name2 width allocation, a prioritization
  185.  *                             parameter, and a word break search to allow
  186.  *                             reclaiming of space from the low priority
  187.  *                             name.
  188.  *            jmjeong    99/12/22  Abridged version. make the num of
  189.  *                                     parameters small
  190.  *
  191.  ***********************************************************************/
  192.  
  193. void DrawRecordName(
  194.     char* name1, char* name2,
  195.     UInt16 nameExtent, Int16 *x, Int16 y,
  196.     Boolean center, Boolean priorityIsName1)
  197. {
  198.     Int16 name1MaxWidth;
  199.     Int16 name2MaxWidth;
  200.     Boolean ignored;
  201.     Int16 totalWidth;
  202.     Char * lowPriName;
  203.     Int16 highPriNameWidth;
  204.     Int16 lowPriNameWidth;
  205.     Int16 highPriMaxWidth;
  206.     Int16 lowPriMaxWidth;
  207.     Char * spaceP;
  208.     UInt16 shortenedFieldWidth;
  209.     UInt16 fieldSeparatorWidth;
  210.     Int16 name1Length, name1Width;
  211.     Int16 name2Length, name2Width;
  212.  
  213.     shortenedFieldWidth =  FntCharsWidth(shortenedFieldString, 
  214.                                          shortenedFieldLength);
  215.     fieldSeparatorWidth = FntCharsWidth(fieldSeparatorString, 
  216.                                         fieldSeparatorLength);
  217.  
  218.     if (*name1) {
  219.         /* Only show text from the first line in the field */
  220.         name1Length = nameExtent; /* longer than possible */
  221.         name1Width = nameExtent;  /* wider than possible */
  222.         FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
  223.     } else {
  224.         /* Set the name to the unnamed string */
  225.         name1 = UnnamedRecordStringPtr;
  226.         name1Length = StrLen(UnnamedRecordStringPtr);
  227.         name1Width = FntCharsWidth(UnnamedRecordStringPtr,
  228.                                    name1Length);
  229.     }
  230.       
  231.     if (*name2) {
  232.         /* Only show text from the first line in the field */
  233.         name2Length = nameExtent; /* longer than possible */
  234.         name2Width = nameExtent;  /* wider than possible */
  235.         FntCharsInWidth(name2, &name2Width, &name2Length, &ignored);
  236.     } else {
  237.         name2Length = 0;
  238.         name2Width = 0;
  239.     }
  240.  
  241.     /* Check if both names fit */
  242.     totalWidth = name1Width + (*name2 ? fieldSeparatorWidth : 0) + name2Width;
  243.  
  244.     /*
  245.      * If we are supposed to center the names then move in the x position
  246.      * by the amount that centers the text
  247.      */
  248.     if (center && (nameExtent > totalWidth)) {
  249.         *x += (nameExtent - totalWidth) / 2;
  250.     }
  251.  
  252.     /* Special case if only name1 is given */
  253.     if (!*name2) {
  254.         /*
  255.          * For some reason, OS3 changed the code so that it doesn't show
  256.          * ellipses if there is only name1.  I liked it the old way!
  257.          */
  258.         /* Does name1 fit in its maximum width? */
  259.         if (name1Width > nameExtent) {
  260.             /* No. Draw it to max width minus the ellipsis */
  261.             name1Width = nameExtent-shortenedFieldWidth;
  262.             FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
  263.             WinDrawChars(name1, name1Length, *x, y);
  264.             *x += name1Width;
  265.             /* Draw ellipsis */
  266.             WinDrawChars(shortenedFieldString, shortenedFieldLength, *x, y);
  267.             *x += shortenedFieldWidth;
  268.         } else {
  269.             /* Yes. Draw name1 within its width */
  270.             FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
  271.             WinDrawChars(name1, name1Length, *x, y);
  272.             *x += name1Width;
  273.         }
  274.         return;
  275.     }
  276.  
  277.     /* Remove name separator width */
  278.     nameExtent -= fieldSeparatorWidth;
  279.  
  280.     /* Test if both names fit */
  281.     if ((name1Width + name2Width) <= nameExtent) {
  282.         name1MaxWidth = name1Width;
  283.         name2MaxWidth = name2Width;
  284.     } else {
  285.         /*
  286.          * They dont fit. One or both needs truncation
  287.          * Establish name priorities and their allowed widths
  288.          * Change this to alter the ratio of the low and high
  289.          * priority name spaces
  290.          */
  291.         highPriMaxWidth = (nameExtent << 1)/3; /* 1/3 to low and 2/3 to high */
  292.         lowPriMaxWidth = nameExtent-highPriMaxWidth;
  293.  
  294.         /* Save working copies of names and widths based on priority */
  295.         if (priorityIsName1) {
  296.             /* Priority is name1 */
  297.             highPriNameWidth = name1Width;
  298.             lowPriName = name2;
  299.             lowPriNameWidth = name2Width;
  300.         } else {
  301.             /* Priority is name2 */
  302.             highPriNameWidth = name2Width;
  303.             lowPriName = name1;
  304.             lowPriNameWidth = name1Width;
  305.         }
  306.  
  307.         /* Does high priority name fit in high priority max width? */
  308.         if (highPriNameWidth > highPriMaxWidth) {
  309.             /* No. Look for word break in low priority name */
  310.             spaceP = StrChr(lowPriName, spaceChr);
  311.             if (spaceP != NULL) {
  312.                 /* Found break. Set low priority name width to break width */
  313.                 lowPriNameWidth = FntCharsWidth(lowPriName, spaceP-lowPriName);
  314.                 /*
  315.                  * Reclaim width from low pri name width to low pri max width,
  316.                  * if smaller.
  317.                  */
  318.                 if (lowPriNameWidth < lowPriMaxWidth) {
  319.                     lowPriMaxWidth = lowPriNameWidth;
  320.                     /* Set new high pri max width */
  321.                     highPriMaxWidth = nameExtent-lowPriMaxWidth;
  322.                 }
  323.             }
  324.         } else {
  325.             /* Yes. Adjust maximum widths */
  326.             highPriMaxWidth = highPriNameWidth;
  327.             lowPriMaxWidth = nameExtent-highPriMaxWidth;
  328.         }
  329.  
  330.         /* Convert priority widths back to name widths */
  331.         if (priorityIsName1) {
  332.             /* Priority is name1 */
  333.             name1Width = highPriNameWidth;
  334.             name2Width = lowPriNameWidth;
  335.             name1MaxWidth = highPriMaxWidth;
  336.             name2MaxWidth = lowPriMaxWidth;
  337.         } else {
  338.             /* Priority is name2 */
  339.             name1Width = lowPriNameWidth;
  340.             name2Width = highPriNameWidth;
  341.             name1MaxWidth = lowPriMaxWidth;
  342.             name2MaxWidth = highPriMaxWidth;
  343.         }
  344.     }
  345.  
  346.     /* Does name1 fit in its maximum width? */
  347.     if (name1Width > name1MaxWidth) {
  348.         /* No. Draw it to max width minus the ellipsis */
  349.         name1Width = name1MaxWidth-shortenedFieldWidth;
  350.         FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
  351.         WinDrawChars(name1, name1Length, *x, y);
  352.         *x += name1Width;
  353.  
  354.         /* Draw ellipsis */
  355.         WinDrawChars(shortenedFieldString, shortenedFieldLength, *x, y);
  356.         *x += shortenedFieldWidth;
  357.     } else {
  358.         /* Yes. Draw name1 within its width */
  359.         FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
  360.         WinDrawChars(name1, name1Length, *x, y);
  361.         *x += name1Width;
  362.     }
  363.  
  364.     if (*name1 && *name2) {
  365.         /* Draw name separator */
  366.         WinDrawChars(fieldSeparatorString, fieldSeparatorLength, *x, y);
  367.         *x += fieldSeparatorWidth;
  368.     }
  369.     
  370.     /* Draw name2 within its maximum width */
  371.     FntCharsInWidth(name2, &name2MaxWidth, &name2Length, &ignored);
  372.     WinDrawChars(name2, name2Length, *x, y);
  373.     *x += name2MaxWidth;
  374. }
  375.  
  376. Int16 GotoAddress(Int16 index)
  377. {
  378.     GoToParamsPtr theGotoPointer;
  379.     DmSearchStateType searchInfo;
  380.     UInt16 cardNo;
  381.     LocalID dbID;
  382.  
  383.     theGotoPointer = MemPtrNew(sizeof(GoToParamsType));
  384.     if (!theGotoPointer) return -1;
  385.     /* Set the owner of the pointer to be the
  386.        system. This is required because all memory
  387.        allocated by our application is freed when
  388.        the application quits. Our application will
  389.        quit the next time through our event
  390.        handler.
  391.     */
  392.     if ((MemPtrSetOwner(theGotoPointer, 0) == 0) &&
  393.         (DmGetNextDatabaseByTypeCreator(true, &searchInfo, 'DATA',
  394.                                         AddressAppID, true, &cardNo, &dbID)
  395.          == 0)) {
  396.  
  397.         // copy all the goto information into the
  398.         // GotoParamsPtr structure
  399.         theGotoPointer->searchStrLen = 0;
  400.         theGotoPointer->dbCardNo = cardNo;
  401.         theGotoPointer->dbID = dbID;
  402.         theGotoPointer->recordNum = index;
  403.         theGotoPointer->matchPos = 0;
  404.         theGotoPointer->matchFieldNum = 0;
  405.         theGotoPointer->matchCustom = 0;
  406.  
  407.         if ((DmGetNextDatabaseByTypeCreator
  408.              (true, &searchInfo,
  409.               sysFileTApplication, AddressAppID,
  410.               true, &cardNo, &dbID) == 0)) {
  411.             SysUIAppSwitch(cardNo, dbID,
  412.                            sysAppLaunchCmdGoTo,
  413.                            (MemPtr) theGotoPointer);
  414.             return 0;
  415.         }
  416.     }
  417.     else {
  418.         MemPtrFree(theGotoPointer);
  419.     }
  420.     return -1;
  421. }
  422.