home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / progect-src-0.20.tar.gz / progect-src-0.20.tar / progect-0.20 / progectdb.c < prev    next >
C/C++ Source or Header  |  2000-10-26  |  24KB  |  976 lines

  1. /* -*-Mode:C; tab-width:4; indent-tabs-mode:t; c-file-style:"stroustrup";-*- */
  2. #include "task.h"
  3. #include "progect.h"
  4. #include "progectdb.h"
  5. #include "progectRsc.h"
  6.  
  7.  
  8. /****************************************************************************
  9.  * Name : AddRecord
  10.  * Desc : add a record to the database
  11.  * In   : database, record to add
  12.  * Out  : new index
  13.  * Auth : lb, 27.07.2000
  14.  * Mod  : lb, 03.08.2000
  15.  *             support to insert as a brother of selected task
  16.  * Mod  : lb, 22.08.2000
  17.  *             added field for note
  18.  * Rem  : doesn't handle err codes
  19.  ***************************************************************************/
  20. Err AddRecord(DmOpenRef dbP, TaskTypePtr task, UInt16 *index)
  21. {
  22.     MemHandle h;
  23.     TaskRecordType *p;
  24.     UInt32 size = TaskRecordTypeSize;
  25.     Err Err = errNone;
  26.     UInt16 realIndex;
  27.  
  28.     // pack this in a newly allocated record
  29.  
  30.     // calc the needed size
  31.     size += (StrLen(task->description) + StrLen(task->note));
  32.  
  33.     // get a handle on a newly created record
  34.     // new one always comes after actual
  35.     if (DmNumRecords(dbP) == 0)
  36.     {
  37.         realIndex = 0;
  38.     }
  39.     else if (DmNumRecords(dbP) > 1 && TaskGetHasChild(dbP, gParentTask))
  40.     {
  41.         realIndex = TaskGetNextRelativeIndex(dbP, *index); // place of new one
  42.     }
  43.     else
  44.     {
  45.         realIndex = gParentTask + 1;
  46.     }
  47.  
  48.     if (!realIndex)
  49.     {
  50.         realIndex = dmMaxRecordIndex;
  51.     }
  52.     h = DmNewRecord(dbP, &realIndex, size);
  53.  
  54.     task->attr.allBits = 0;
  55.     task->attr.bits.opened = 1;
  56.     //now fixed by task defaults dialog
  57.     //task->priority = 6;
  58.     task->dueDate.year = 0;
  59.     task->dueDate.month = 0;
  60.     task->dueDate.day = 0;
  61.  
  62.     // if index = 0, this is the first one
  63.     // it's not a real task !!!
  64.     if (realIndex == 0)
  65.     {
  66.         task->attr.bits.hasChild = 0;
  67.     }
  68.     else
  69.     {
  70.         // retrieve info about user of previous index
  71.         // this sets : level, next
  72.         if (*index == 0 || !TaskGetHasChild(dbP, gParentTask))
  73.         {
  74.             // this is a first child
  75.             task->attr.bits.level = gRefLevel + 1;
  76.             TaskSetHasChild(dbP, gParentTask, true);
  77.         }
  78.         else
  79.         {
  80.             task->attr.bits.level = TaskGetLevel(dbP, *index);
  81.             task->attr.bits.hasPrev = 1;
  82.             task->attr.bits.hasNext = TaskGetHasNext(dbP, *index);
  83.  
  84.             // update hasNext field in previous
  85.             TaskSetHasNext(dbP, *index, true);
  86.             if (gProjectPrefs.useFatherStatus)
  87.             {
  88.                 if ((task->attr.bits.level) != FIRST_LEVEL)
  89.                 {
  90.                     UInt16 father = TaskGetFatherIndex(dbP, realIndex);
  91.                     task->dueDate = TaskGetDueDate(dbP, father);
  92.                     task->priority = TaskGetPriority(dbP, father);
  93.                 }
  94.             }
  95.         }
  96.     }
  97.     // no date by default
  98.     //task->dueDate = Today();
  99.  
  100.     // get a pointer on the record
  101.     p = MemHandleLock(h);
  102.  
  103.     // write the data
  104.     DmWrite(p, 0, task, OffsetOf(TaskRecordType, description));
  105.     DmStrCopy(p, OffsetOf(TaskRecordType, description), task->description);
  106.     DmStrCopy(p, OffsetOf(TaskRecordType, description) + StrLen(task->description) + 1, task->note);
  107.     //DEBUG2("Creating with task note : ", task->note);
  108.  
  109.     // unlock the pointer
  110.     MemHandleUnlock(h);
  111.  
  112.     // unlock the record
  113.     DmReleaseRecord(dbP, realIndex, true);
  114.  
  115.     *index = realIndex;
  116.  
  117.     return Err;
  118. } // static Err AddRecord(DmOpenRef dbP, TaskTypePtr task, UInt16 *index)
  119.  
  120.  
  121.  
  122. /****************************************************************************
  123.  * Name : AddRecordSub
  124.  * Desc : add a record to the database, as subtask of index
  125.  * In   : database, record to add, index
  126.  * Out  : new index
  127.  * Auth : lb, 04.08.2000
  128.  * Rem  : doesn't handle err codes
  129.  * Mod  : lb, 13.08.2000
  130.  *             fix bug, can now create more subtasks. Subtasks always created
  131.  *             as last child
  132.  * Mod  : lb, 22.08.2000
  133.  *             added field for note
  134.  ***************************************************************************/
  135. Err AddRecordSub(DmOpenRef dbP, TaskTypePtr task, UInt16 *index)
  136. {
  137.     MemHandle h;
  138.     TaskRecordType *p;
  139.     UInt32 size = TaskRecordTypeSize;
  140.     Err Err = errNone;
  141.     UInt16 realIndex;
  142.  
  143.     // pack this in a newly allocated record
  144.  
  145.     // calc the needed size
  146.     size += (StrLen(task->description) + StrLen(task->note));
  147.  
  148.     // get a handle on a newly created record
  149.     // new one always comes after actual
  150.     realIndex = TaskGetNextRelativeIndex(dbP, *index); // place of new one
  151.     if (!realIndex)
  152.     {
  153.         realIndex = dmMaxRecordIndex;
  154.     }
  155.     h = DmNewRecord(dbP, &realIndex, size);
  156.  
  157.     // retrieve info about user of previous index
  158.     // this sets : level, next
  159.     task->attr.allBits = 0;
  160.     task->attr.bits.level = TaskGetLevel(dbP, *index) + 1;
  161.     task->attr.bits.opened = 1;
  162.     task->attr.bits.hasPrev = TaskGetHasChild(dbP, *index);
  163.  
  164.     //task->priority = 6;
  165.     task->dueDate.year = 0;
  166.     task->dueDate.month = 0;
  167.     task->dueDate.day = 0;
  168.  
  169.     if (gProjectPrefs.useFatherStatus)
  170.     {
  171.         if ((task->attr.bits.level) != FIRST_LEVEL)
  172.         {
  173.             UInt16 father = TaskGetFatherIndex(dbP, realIndex);
  174.             task->dueDate = TaskGetDueDate(dbP, father);
  175.             task->priority = TaskGetPriority(dbP, father);
  176.         }
  177.     }
  178.     // if father had children already
  179.     if (TaskGetHasChild(dbP, *index))
  180.     {
  181.         // old last child has now a next
  182.         TaskSetHasNext(dbP, realIndex - 1, true);
  183.     }
  184.  
  185.     // update hasChild field in father
  186.     TaskSetHasChild(dbP, *index, true);
  187.  
  188.     // get a pointer on the record
  189.     p = MemHandleLock(h);
  190.  
  191.     // write the data
  192.     DmWrite(p, 0, task, OffsetOf(TaskRecordType, description));
  193.     DmStrCopy(p, OffsetOf(TaskRecordType, description), task->description);
  194.     DmStrCopy(p, OffsetOf(TaskRecordType, description) + StrLen(task->description) + 1, task->note);
  195.  
  196.     // unlock the pointer
  197.     MemHandleUnlock(h);
  198.  
  199.     // unlock the record
  200.     DmReleaseRecord(dbP, realIndex, true);
  201.  
  202.     *index = realIndex;
  203.  
  204.     return Err;
  205. } // static Err AddRecordSub(DmOpenRef dbP, TaskTypePtr task, UInt16 *index)
  206.  
  207.  
  208.  
  209. /****************************************************************************
  210.  * Name : CreateDB
  211.  * Desc : create a database
  212.  * In   : 
  213.  *             -> name without prepanding !
  214.  * Out  : -
  215.  * Auth : lb, 26.07.2000
  216.  * Rem  : doesn't handle err codes
  217.  * Mod  : lb, 17.08.2000
  218.  *             - prepand "lbPG-" to the dbname
  219.  ***************************************************************************/
  220. Err CreateDB(const char *nameP)
  221. {
  222.     UInt16 cardNo = 0;
  223.     Char dbname[32];
  224.     Err Err = errNone;
  225.     LocalID dbID;
  226.     TaskType task0;
  227.     UInt16 index = 0;
  228.  
  229.     StrCopy(dbname, gPrepend);
  230.     StrCat(dbname, nameP);
  231.  
  232.     dbID = DmFindDatabase(cardNo, dbname);
  233.  
  234.     // if database doesn't exist, create it
  235.     if (!dbID)
  236.     {
  237.         Err = DmCreateDatabase(cardNo, dbname, CREATOR, 'DATA', false);
  238.  
  239.         // debug code to initialise a test DB
  240.         // OpenDB takes a name without prepend
  241.         OpenDB(nameP, &gdbP);
  242.         task0 = gEmptyTask;
  243.         AddRecord(gdbP, &task0, &index);
  244.         CloseDB(gdbP);
  245.         gdbP = NULL;
  246.     } else
  247.             Err = dmErrAlreadyExists;
  248.  
  249.     return Err;
  250. } // static Err CreateDB(const char *nameP)
  251.  
  252.  
  253.  
  254. /****************************************************************************
  255.  * Name : RemoveDB
  256.  * Desc : remove a database
  257.  * In   : name of database to remove
  258.  * Out  : Err code
  259.  * Auth : lb, 27.07.2000
  260.  * Mod  : lb, 17.08.2000
  261.  *             prepending support
  262.  *             control of CREATOR ID
  263.  ***************************************************************************/
  264. Err RemoveDB(const char *nameP)
  265. {
  266.     UInt16 cardNo = 0;
  267.     Err Err = errNone;
  268.     LocalID dbID;
  269.     char dbname[32];
  270.     UInt32 creatorID;
  271.  
  272.     // try to prepend the name
  273.     StrCopy(dbname, gPrepend);
  274.     StrCat(dbname, nameP);
  275.  
  276.     dbID = DmFindDatabase(cardNo, dbname);
  277.  
  278.     // if database exists, delete it
  279.     if (dbID)
  280.     {
  281.         DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, 
  282.             NULL, NULL, NULL, NULL, NULL, &creatorID);
  283.         if (creatorID == CREATOR)
  284.         {
  285.             Err = DmDeleteDatabase(cardNo, dbID);
  286.         }
  287.     }
  288.     else
  289.     {
  290.         dbID = DmFindDatabase(cardNo, nameP);
  291.  
  292.         // if database exists, delete it
  293.         if (dbID)
  294.         {
  295.             DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, 
  296.                 NULL, NULL, NULL, NULL, NULL, &creatorID);
  297.             if (creatorID == CREATOR)
  298.             {
  299.                 Err = DmDeleteDatabase(cardNo, dbID);
  300.             }
  301.         }
  302.     }
  303.     return Err;
  304. } // static Err RemoveDB(const char *nameP)
  305.  
  306.  
  307.  
  308. /****************************************************************************
  309.  * Name : OpenDB
  310.  * Desc : open a database by name
  311.  * Prm  : 
  312.  *             ->  name of the db to open without prepending
  313.  *             <-> database reference
  314.  * Out  : Err code
  315.  * Auth : lb, 27.07.2000
  316.  * Mod  : lb, 14.08.2000
  317.  *             to save app current state
  318.  *           lb, 17.08.2000
  319.  *               try to prepend
  320.  *           lb, 24.08.2000
  321.  *               fix without prepending mode that caused a crash after two
  322.  *               come backs
  323.  ***************************************************************************/
  324. Err OpenDB(const char* nameP, DmOpenRef *dbP)
  325. {
  326.     UInt16 cardNo = 0;
  327.     UInt16 mode = dmModeReadWrite;
  328.     Err Err = 0;
  329.     char dbname[32];
  330.  
  331.     // try to prepend the name
  332.     StrCopy(dbname, gPrepend);
  333.     StrCat(dbname, nameP);
  334.  
  335.     // find the database
  336.     gdbID = DmFindDatabase(cardNo, dbname);
  337.     if (!gdbID)
  338.     {
  339.         // try without prepending (for databases before V0.10)
  340.         // find the database
  341.         StrCopy(dbname, nameP);
  342.         gdbID = DmFindDatabase(cardNo, dbname);
  343.  
  344.         // if found
  345.         if (!gdbID)
  346.         {
  347.             return DmGetLastErr();
  348.         }
  349.     }
  350.  
  351.     // open it
  352.     *dbP = DmOpenDatabase(cardNo, gdbID, mode);
  353.  
  354.     // if it failed
  355.     if (!*dbP)
  356.     {
  357.         // get error code
  358.         Err = DmGetLastErr();
  359.     }
  360.     else
  361.     {
  362.         StrCopy(gCurrentPrefs.openDBName, dbname);
  363.         gCurrentPrefs.openDB = true;
  364.         LoadDBPrefs(*dbP);
  365.         if (gProjectPrefs.autoSyncToDo)
  366.         {
  367.             TaskSyncAll();
  368.         }
  369.         // save/restore the pointer have no meaning,
  370.         // and it will be crash program.
  371.         //   NOTE: fix BUG#115440
  372.         //             "Newly created task/note has garbage text in it"
  373.         MemMove((MemPtr)&gEmptyTask,
  374.                 (MemPtr)&gProjectPrefs.taskDefaults,
  375.                 (UInt8*)&(gEmptyTask.description) - (UInt8*)&gEmptyTask);
  376. //        gEmptyTask = gProjectPrefs.taskDefaults;
  377.     }
  378.  
  379.     return Err;
  380. } // static Err OpenDB(const char* nameP, DmOpenRef *dbP)
  381.  
  382.  
  383.  
  384.  
  385. /****************************************************************************
  386.  * Name : OpenDBByID
  387.  * Desc : open a database by cardNo and dbID
  388.  * Prm  : 
  389.  *             ->  card no
  390.  *             ->  database id
  391.  *             <-> database reference
  392.  * Out  : Err code
  393.  ***************************************************************************/
  394. Err OpenDBByID(UInt16 cardNo, LocalID dbID, DmOpenRef* dbP)
  395. {
  396.     // Open 
  397.     Char* name;
  398.     DmOpenRef pDB = DmOpenDatabase(cardNo, dbID, dmModeReadWrite);
  399.     if (! pDB)
  400.         return DmGetLastErr();
  401.  
  402.     // close current opend DB
  403.     if (*dbP)
  404.         CloseDB(*dbP);
  405.  
  406.     // setting up global status.
  407.     *dbP = pDB;
  408.     gdbID = dbID;
  409.  
  410.     name = MemPtrNew(32);
  411.     DmDatabaseInfo(cardNo, dbID, name, NULL, NULL, NULL, NULL, NULL,
  412.                    NULL, NULL, NULL, NULL, NULL);
  413.     StrCopy(gCurrentPrefs.openDBName, name);
  414.     MemPtrFree(name);
  415.     gCurrentPrefs.openDB = true;
  416.     LoadDBPrefs(pDB);
  417.     if (gProjectPrefs.autoSyncToDo)
  418.         TaskSyncAll();
  419.  
  420.     return 0;
  421. } // static Err OpenDB(const char* nameP, DmOpenRef *dbP)
  422.  
  423.  
  424.  
  425. /****************************************************************************
  426.  * Name : CloseDB
  427.  * Desc : close the database
  428.  * In   : pointer to the database to close
  429.  * Out  : Err code
  430.  * Auth : lb, 27.07.2000
  431.  * Mod  : lb, 14.08.2000
  432.  *             to save app current state
  433.  ***************************************************************************/
  434. Err CloseDB(DmOpenRef dbP)
  435. {
  436.     Err Err;
  437.     SaveDBPrefs(dbP);
  438.     // close the database
  439.     Err = DmCloseDatabase(dbP);
  440.     gCurrentPrefs.openDB = false;
  441.     gCurrentPrefs.topTask = -1;
  442.     gdbID = 0;
  443.     gdbP = NULL;
  444.     return Err;
  445. } // static Err CloseDB(DmOpenRef dbP)
  446.  
  447.  
  448.  
  449. /****************************************************************************
  450.  * Name : RenameDB
  451.  * Desc : rename a database
  452.  * In   :
  453.  *             -> old name (with or without prepending)
  454.  *             -> new name (with or without prepending)
  455.  * Out  : -
  456.  * Auth : lb, 23.08.2000
  457.  ***************************************************************************/
  458. Err RenameDB(Char* oldName, Char* newName)
  459. {
  460.     UInt16 cardNo = 0;
  461.     LocalID dbID;
  462.  
  463.     Prepend(newName);
  464.  
  465.     // find the database (without prepending)
  466.     dbID = DmFindDatabase(cardNo, oldName);
  467.  
  468.     if (!dbID)
  469.     {
  470.         // try with prepending
  471.         // find the database
  472.         Prepend(oldName);
  473.         dbID = DmFindDatabase(cardNo, oldName);
  474.         if (!dbID)
  475.             return DmGetLastErr();
  476.     }
  477.     return DmSetDatabaseInfo(cardNo, dbID, newName, NULL, NULL, NULL, NULL, 
  478.                     NULL, NULL, NULL, NULL, NULL, NULL);
  479. } // static Err RenameDB(Char* oldName, Char* newName)
  480.  
  481.  
  482.  
  483. /****************************************************************************
  484.  * Name : SaveDBPrefs
  485.  * Desc : save the database preferences
  486.  * In   :
  487.  * Out  : -
  488.  * Auth : lb, 17.08.2000
  489.  ***************************************************************************/
  490. void SaveDBPrefs(DmOpenRef dbP)
  491. {
  492.     LocalID appInfoID;
  493.     DBInfoType* p;
  494.     MemHandle h;
  495.  
  496.     appInfoID = DmGetAppInfoID(dbP);
  497.  
  498.     // if there is no appInfoID, create it
  499.     if (! appInfoID)
  500.     {
  501.         h = DmNewHandle(dbP, sizeof(DBInfoType));
  502.         if (!h)
  503.             return;
  504.         appInfoID = MemHandleToLocalID(h);
  505.         DmSetDatabaseInfo(0, gdbID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
  506.             &appInfoID, NULL, NULL, NULL);
  507.  
  508.         p = MemLocalIDToLockedPtr(appInfoID, 0);
  509.         DmSet(p, 0, sizeof(DBInfoType), 0);
  510.         CategoryInitialize(&p->appInfo, InitialCategory);
  511.     }
  512.     else
  513.         p = MemLocalIDToLockedPtr(appInfoID, 0);
  514.  
  515.     // test the size
  516.     // if it's not good, the next LoadDBPrefs will correct it
  517.     if (MemPtrSize(p) == sizeof(DBInfoType))
  518.     {
  519.         // write the new prefs
  520.         DmWrite(p, OffsetOf(DBInfoType, pref),
  521.                 &gProjectPrefs, sizeof(ProjectPrefsType));
  522.     }
  523.     // unlock
  524.     MemPtrUnlock(p);
  525.  
  526. } // static void SaveDBPrefs(void)
  527.  
  528.  
  529.  
  530. /****************************************************************************
  531.  * Name : LoadDBPrefs
  532.  * Desc : load the database preferences
  533.  * In   :
  534.  * Out  : false = no prefs
  535.  *           true  = ok
  536.  * Auth : lb, 17.08.2000
  537.  * Mod  : lb, 17.08.2000
  538.  *             - pass db, because when OpenDB calls, gdbp is not set !
  539.  ***************************************************************************/
  540. Boolean LoadDBPrefs(DmOpenRef dbP)
  541. {
  542.     DBInfoType *p;
  543.     LocalID appInfoID;
  544.     LocalID oldInfoID = 0;
  545.  
  546.     appInfoID = DmGetAppInfoID(dbP);
  547.  
  548.     if (appInfoID)
  549.     {
  550.         p = MemLocalIDToLockedPtr(appInfoID, 0);
  551.         if (MemPtrSize(p) < 30 && *(UInt8*)p < 11)
  552.         {
  553.             DEBUG1("Old database version (<=0.11) conversion, please click OK and wait...");
  554.             MemPtrUnlock(p);
  555.             ConvertDB(11);
  556.         }
  557.         if (MemPtrSize(p) != sizeof(DBInfoType) )
  558.         {
  559.             MessageBox(StrPrefsHasBeenDeleted);
  560.             oldInfoID = appInfoID;
  561.             appInfoID = 0;
  562.             MemPtrUnlock(p);
  563.         }
  564.     }
  565.  
  566.     if (! appInfoID)
  567.     {
  568.         // create new prefs
  569.         MemHandle h = DmNewHandle(dbP, sizeof(DBInfoType));
  570.         if (! h)
  571.             return false;
  572.         appInfoID = MemHandleToLocalID(h);
  573.         DmSetDatabaseInfo(0, gdbID, NULL, NULL, NULL, NULL, NULL, 
  574.                           NULL, NULL, &appInfoID, NULL, NULL, NULL);
  575.         // get a pointer
  576.         p = MemLocalIDToLockedPtr(appInfoID, 0);
  577.         
  578.         // write the new prefs
  579.         DmSet(p, 0, sizeof(DBInfoType), 0);
  580.         CategoryInitialize(&p->appInfo, InitialCategory);
  581.         if (oldInfoID)
  582.         { // copy original categories
  583.             AppInfoType* pp = MemLocalIDToLockedPtr(oldInfoID, 0);
  584.             if (MemPtrSize(pp) > sizeof(AppInfoType) + 20)
  585.                 DmWrite(p, 0, pp, sizeof(AppInfoType));
  586.             MemPtrUnlock(pp);
  587.         }
  588.  
  589.         DmWrite(p, OffsetOf(DBInfoType, pref),
  590.                 &gProjectPrefs, sizeof(ProjectPrefsType));
  591.     }
  592.     // this produced an overlocked pointer => crash every 8th start
  593.     //else
  594.         //p = MemLocalIDToLockedPtr(appInfoID, 0);
  595.  
  596.     MemMove(&gProjectPrefs, &p->pref, sizeof(ProjectPrefsType));
  597.     MemPtrUnlock(p);
  598.  
  599.  
  600.     if (oldInfoID)
  601.     {
  602.         // ... ??? how to delete old ID ???
  603.     }
  604.  
  605.     return true;
  606. } // static Boolean LoadDBPrefs(DmOpenRef dbP)
  607.  
  608.  
  609.  
  610. /****************************************************************************
  611.  * Name : SaveAppPrefs
  612.  * Desc : save the application preferences
  613.  * In   :
  614.  *             -> saved : true for saved prefs, false for current prefs
  615.  * Out  : -
  616.  * Auth : lb, 14.08.2000
  617.  * Mod  : lb, 17.08.2000
  618.  *             support for saved prefs
  619.  ***************************************************************************/
  620. void SaveAppPrefs(Boolean saved)
  621. {
  622.     PrefSetAppPreferences(CREATOR, 0, 1, 
  623.         saved ? (void*)&gSavedPrefs : (void*)&gCurrentPrefs, 
  624.         saved ? sizeof(SavedPrefsType) : sizeof(CurrentPrefsType), 
  625.         saved);
  626. } // static void SaveAppPrefs(Boolean saved)
  627.  
  628.  
  629.  
  630. /****************************************************************************
  631.  * Name : LoadAppPrefs
  632.  * Desc : load the application preferences
  633.  * In   :
  634.  *             -> saved : true for saved prefs, false for current prefs
  635.  * Out  : false = no prefs
  636.  *           true  = ok
  637.  * Auth : lb, 14.08.2000
  638.  * Mod  : lb, 17.08.2000
  639.  *             support for saved prefs
  640.  ***************************************************************************/
  641. Boolean LoadAppPrefs(Boolean saved)
  642. {
  643.     UInt16 size = saved ? sizeof(SavedPrefsType) : sizeof(CurrentPrefsType);
  644.     UInt16 status;
  645.  
  646.     status = PrefGetAppPreferences(CREATOR, 0, 
  647.         saved ? (void*)&gSavedPrefs : (void*)&gCurrentPrefs, &size, saved);
  648.     status = (size == 
  649.         (saved ? sizeof(SavedPrefsType) : sizeof(CurrentPrefsType))) ? status : noPreferenceFound;
  650.     return status == noPreferenceFound ? false : true;
  651. } // static Boolean LoadAppPrefs(Boolean saved)
  652.  
  653.  
  654.  
  655. /****************************************************************************
  656.  * Name : ConvertDB
  657.  * Desc : convert an old DB to the actual format
  658.  * In   :
  659.  *             -> old format
  660.  * Out  : -
  661.  * Auth : lb, 22.08.2000
  662.  ***************************************************************************/
  663. void ConvertDB(UInt8 format)
  664. {
  665.     Char dbname[32];
  666.     Char tmp[32];
  667.     UInt16 recNum;
  668.     Char* tmpName = "lbPG-tmpConvertProcess";
  669.     LocalID newID, oldID;
  670.     DmOpenRef newDB, oldDB;
  671.     MemHandle hOld, hNew;
  672.     UInt16 i;
  673.     UInt16 fakeIndex;
  674.     UInt32 size;
  675.     UInt16 cardNo = 0;
  676.     TaskFormatType taskFormat = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  677.     TaskAttrType attr;
  678.  
  679.     StrCopy(dbname, gCurrentPrefs.openDBName);
  680.     switch (format)
  681.     {
  682.         case 11:
  683.             DmCloseDatabase(gdbP);
  684.             RenameDB(dbname, tmpName);
  685.  
  686.             // if the name was prepended
  687.             if (StrStr(dbname, gPrepend) == dbname)
  688.             {
  689.                 // create, pass the name without prepending
  690.                 CreateDB(&dbname[5]);
  691.                 // open (prepended name)
  692.                 newID = DmFindDatabase(cardNo, dbname);
  693.             }
  694.             else
  695.             {
  696.                 // create, pass the name
  697.                 CreateDB(dbname);
  698.                 // prepend for opening
  699.                 StrCopy(tmp, gPrepend);
  700.                 StrCat(tmp, dbname);
  701.                 StrCopy(dbname, tmp);
  702.                 newID = DmFindDatabase(cardNo, dbname);
  703.             }
  704.  
  705.             // open the databases
  706.             oldID = DmFindDatabase(cardNo, tmpName);
  707.             newDB = DmOpenDatabase(cardNo, newID, dmModeReadWrite);
  708.             oldDB = DmOpenDatabase(cardNo, oldID, dmModeReadOnly);
  709.             
  710.             // get the number of records
  711.             recNum = DmNumRecords(oldDB);
  712.  
  713.             taskFormat.hasDueDate = 1;
  714.             taskFormat.newFormat = 1;
  715.             
  716.             // convert each record (except task0)
  717.             for (i = 1; i < recNum; i++)
  718.             {
  719.                 TaskRecordTypeV011 *pOld;
  720.                 TaskRecordType *pNew;
  721.  
  722.                 // get the old one
  723.                 hOld = DmQueryRecord(oldDB, i);
  724.                 pOld = MemHandleLock(hOld);
  725.                 fakeIndex = dmMaxRecordIndex;
  726.  
  727.                 // calc the size of the new one
  728.                 size = TaskRecordTypeSize + StrLen(&pOld->description); 
  729.  
  730.                 // create a record
  731.                 hNew = DmNewRecord(newDB, &fakeIndex, size);
  732.                 
  733.                 // reget the pointer
  734.                 MemHandleUnlock(hOld);
  735.                 pOld = MemHandleLock(hOld);
  736.  
  737.                 // convert attributes
  738.                 attr.level = pOld->level;
  739.                 attr.hasNext = pOld->hasNext;
  740.                 attr.hasChild = pOld->hasChild;
  741.                 attr.opened = pOld->opened;
  742.                 attr.hasPrev = !pOld->firstChild;
  743.                 pNew = MemHandleLock(hNew);
  744.  
  745.                 // write
  746.                 // first, reset it (to have the note be \0)
  747.                 DmSet(pNew, 0, size, 0);
  748.                 DmWrite(pNew, OffsetOf(TaskRecordType, attr), &attr, 
  749.                     sizeof(UInt16));
  750.                 DmWrite(pNew, OffsetOf(TaskRecordType, format), &taskFormat, 
  751.                     sizeof(UInt16));
  752.                 DmWrite(pNew, OffsetOf(TaskRecordType, priority), 
  753.                     &pOld->priority, sizeof(UInt8));
  754.                 DmWrite(pNew, OffsetOf(TaskRecordType, completed), 
  755.                     &pOld->completed, sizeof(UInt8));
  756.                 DmWrite(pNew, OffsetOf(TaskRecordType, dueDate), 
  757.                     &pOld->dueDate, sizeof(DateType));
  758.                 DmStrCopy(pNew, OffsetOf(TaskRecordType, description), 
  759.                     &pOld->description);
  760.  
  761.                 MemHandleUnlock(hOld);
  762.                 MemHandleUnlock(hNew);
  763.                 DmReleaseRecord(newDB, fakeIndex, true);
  764.             }
  765.             gdbP = newDB;
  766.             gdbID = newID;
  767.             DmCloseDatabase(oldDB);
  768.             DmDeleteDatabase(cardNo, oldID);
  769.             break;
  770.         default:
  771.             break;
  772.     }
  773. } // static void ConvertDB(UInt8 format)
  774.  
  775.  
  776.  
  777. /****************************************************************************
  778.  * Name : Prepend
  779.  * Desc : check if a name is prepended, if not, prepend it
  780.  * In   :
  781.  *             <-> name
  782.  * Out  : -
  783.  * Auth : lb, 26.08.2000
  784.  ***************************************************************************/
  785. void Prepend(Char* name)
  786. {
  787.     Char tmp[32];
  788.     // if the name is not prepended
  789.     if (StrStr(name, gPrepend) != name)
  790.     {
  791.         // prepend the name
  792.         StrCopy(tmp, gPrepend);
  793.         StrCat(tmp, name);
  794.         StrCopy(name, tmp);
  795.     }
  796. } // void Prepend(Char* name)
  797.  
  798.  
  799.  
  800. /****************************************************************************
  801.  * Name : DuplicateDB
  802.  * Desc : duplicate a project
  803.  * In   :
  804.  *             -> source (with or without prepending)
  805.  *             -> dest   ( "         "      "       )
  806.  * Out  : -
  807.  * Auth : lb, 27.08.2000
  808.  ***************************************************************************/
  809. Err DuplicateDB(Char* src, Char* dbname)
  810. {
  811.     Char tmp[32];
  812.     UInt16 recNum;
  813.     LocalID newID, oldID;
  814.     DmOpenRef newDB, oldDB;
  815.     MemHandle hOld, hNew;
  816.     TaskRecordType *pOld, *pNew;
  817.     UInt16 i;
  818.     UInt16 index;
  819.     UInt16 cardNo = 0;
  820.     Err err;
  821.  
  822.     // if the name was prepended
  823.     if (StrStr(dbname, gPrepend) == dbname)
  824.     {
  825.         // create, pass the name without prepending
  826.         err = CreateDB(&dbname[5]);
  827.         // open (prepended name)
  828.         if (!err)
  829.             newID = DmFindDatabase(cardNo, dbname);
  830.         else
  831.             return err;
  832.     }
  833.     else
  834.     {
  835.         // create, pass the name
  836.         err = CreateDB(dbname);
  837.         // prepend for opening
  838.         if (!err) {
  839.             StrCopy(tmp, gPrepend);
  840.             StrCat(tmp, dbname);
  841.             StrCopy(dbname, tmp);
  842.             newID = DmFindDatabase(cardNo, dbname);
  843.         } else
  844.             return err;
  845.     }
  846.  
  847.     // prepend (if needed)
  848.     Prepend(src);
  849.  
  850.     // open the databases
  851.     oldID = DmFindDatabase(cardNo, src);
  852.     newDB = DmOpenDatabase(cardNo, newID, dmModeReadWrite);
  853.     oldDB = DmOpenDatabase(cardNo, oldID, dmModeReadOnly);
  854.     
  855.     // get the number of records
  856.     recNum = DmNumRecords(oldDB);
  857.  
  858.     // copy each record (except task0)
  859.     for (i = 1; i < recNum; i++)
  860.     {
  861.         index = dmMaxRecordIndex;
  862.         hOld = DmQueryRecord(oldDB, i);
  863.         pOld = MemHandleLock(hOld);
  864.         hNew = DmNewRecord(newDB, &index, MemPtrSize(pOld));
  865.         pNew = MemHandleLock(hNew);
  866.         DmWrite(pNew, 0, pOld, MemPtrSize(pOld));
  867.         MemHandleUnlock(hNew);
  868.         MemHandleUnlock(hOld);
  869.         DmReleaseRecord(newDB, index, true);
  870.     }
  871.     DmCloseDatabase(oldDB);
  872.     DmCloseDatabase(newDB);
  873.  
  874.     return errNone;
  875. } // void DuplicateDB(Char* src, Char* dbname)
  876.  
  877.  
  878.  
  879. /****************************************************************************
  880.  * Name : OpenClipboard
  881.  * Desc : open the clipboard, create it if it doesn't exist
  882.  * In   :
  883.  * Out  : -
  884.  * Auth : lb, 04.09.2000
  885.  ***************************************************************************/
  886. pgErr OpenClipboard(void)
  887. {
  888.     UInt16 cardNo = 0;
  889.     Err err = errNone;
  890.     LocalID dbID;
  891.     char dbname[] = "lbPG-Clipboard";
  892.     UInt16 index = 0;
  893.  
  894.     dbID = DmFindDatabase(cardNo, dbname);
  895.  
  896.     // if database doesn't exist, create it
  897.     if (!dbID)
  898.     {
  899.         err = DmCreateDatabase(cardNo, dbname, CREATOR, 'CLIP', false);
  900.         if (err)
  901.         {
  902.             DEBUG1("Cannot create a clipboard database.");
  903.             return pgError;
  904.         }
  905.         dbID = DmFindDatabase(cardNo, dbname);
  906.     }
  907.  
  908.     gClip = DmOpenDatabase(cardNo, dbID, dmModeReadWrite);
  909.     if (DmNumRecords(gClip) == 0)
  910.     {
  911.         DEBUG1("Adding task 0");
  912.         AddRecord(gClip, &gEmptyTask, &index);
  913.     }
  914.     return pgOK;
  915. } // pgErr OpenClipboard(void)
  916.  
  917.  
  918.  
  919. /****************************************************************************
  920.  * Name : CloseClipboard
  921.  * Desc : close the clipboard
  922.  * In   :
  923.  * Out  : -
  924.  * Auth : lb, 04.09.2000
  925.  ***************************************************************************/
  926. pgErr CloseClipboard(void)
  927. {
  928.     if (gClip)
  929.     {
  930.         DmCloseDatabase(gClip);
  931.         gClip = NULL;
  932.     }
  933.  
  934.     return pgOK;
  935. } // pgErr CloseClipboard(void)
  936.  
  937.  
  938.  
  939. /****************************************************************************
  940.  * Name : NewClipboard
  941.  * Desc : close the clipboard, remove it, create a new one, open it
  942.  * In   :
  943.  * Out  : -
  944.  * Auth : lb, 05.09.2000
  945.  ***************************************************************************/
  946. pgErr NewClipboard(void)
  947. {
  948.     UInt16 cardNo = 0;
  949.     Err err = errNone;
  950.     LocalID dbID;
  951.     char dbname[] = "lbPG-Clipboard";
  952.     UInt16 index = 0;
  953.  
  954.     CloseClipboard();
  955.  
  956.     dbID = DmFindDatabase(cardNo, dbname);
  957.  
  958.     // if database exists, remove it
  959.     if (dbID)
  960.     {
  961.         DmDeleteDatabase(cardNo, dbID);
  962.     }
  963.  
  964.     err = DmCreateDatabase(cardNo, dbname, CREATOR, 'CLIP', false);
  965.     if (err)
  966.         return pgError;
  967.  
  968.     dbID = DmFindDatabase(cardNo, dbname);
  969.  
  970.     gClip = DmOpenDatabase(cardNo, dbID, dmModeReadWrite);
  971.     AddRecord(gClip, &gEmptyTask, &index);
  972.  
  973.     return pgOK;
  974.         
  975. } // pgErr NewClipboard(void)
  976.