home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / linkmaster-src-1.0.4.tar.gz / linkmaster-src-1.0.4.tar / linkmaster-1.0.4 / linkmaster.c < prev    next >
C/C++ Source or Header  |  2000-10-12  |  15KB  |  628 lines

  1. /* linkmaster.c
  2.    Copyright (C) 1999 Ben Darnell
  3.    This file is a part of LinkMaster,
  4.    which is distributed under the GNU GPL.
  5. */
  6.  
  7. /* prefs info:
  8.    pref 0: histprefs (from linkaware.h)
  9.    pref 1: pending link (unsaved)
  10.    pref 2: history time limit
  11. */
  12.  
  13. #include <Pilot.h>
  14. #include "callback.h"
  15.  
  16. #include "linkaware.h"
  17. #include "linkmaster.h"
  18. #include "linkmasterRsc.h"
  19.  
  20.  
  21. static DmOpenRef LinkDB;
  22. static Word mode;
  23.  
  24. static void LinkListDrawFunc(UInt item, RectanglePtr bounds, CharPtr* text)
  25. {
  26.    VoidHand h;
  27.    Ptr p;
  28.    CALLBACK_PROLOGUE;
  29.  
  30.    h=DmQueryRecord(LinkDB, item);
  31.    p=MemHandleLock(h);
  32.    WinDrawChars(p+64, StrLen(p+64), bounds->topLeft.x, bounds->topLeft.y);
  33.    MemHandleUnlock(h);
  34.    
  35.    CALLBACK_EPILOGUE;
  36. }
  37.  
  38. static void InitForm(FormPtr frm)
  39. {
  40.    ListPtr list;
  41.  
  42.    list=FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, MainLinkList));
  43.    LstSetListChoices(list, NULL, DmNumRecords(LinkDB));
  44.    LstSetDrawFunction(list, LinkListDrawFunc);
  45.  
  46.    if (mode==linkAppLaunchRequestLink) {
  47.       CtlHideControl(FrmGetObjectPtr(frm,
  48.                      FrmGetObjectIndex(frm, MainDelLink)));
  49.       CtlHideControl(FrmGetObjectPtr(frm,
  50.                      FrmGetObjectIndex(frm, MainGo)));
  51.    };
  52. }
  53.  
  54. static void NewLink()
  55. {
  56.    FrmPopupForm(NewLinkForm);
  57. }
  58.  
  59. static void DelLink()
  60. {
  61.    FormPtr frm;
  62.    ListPtr list;
  63.    Word sel;
  64.    
  65.    frm=FrmGetActiveForm();
  66.    list=FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, MainLinkList));
  67.    sel=LstGetSelection(list);
  68.  
  69.    if (sel==-1) return;
  70.  
  71.    DmRemoveRecord(LinkDB, sel);
  72.    FrmUpdateForm(MainForm, frmRedrawUpdateCode);
  73. }
  74.  
  75. static void Go()
  76. {
  77.    FormPtr frm;
  78.    ListPtr list;
  79.    Word sel;
  80.    VoidHand hrec;
  81.    Ptr prec, tmpptr;
  82.  
  83.    frm=FrmGetActiveForm();
  84.    list=FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, MainLinkList));
  85.    sel=LstGetSelection(list);
  86.  
  87.    if (sel==-1) return;
  88.  
  89.    hrec=DmQueryRecord(LinkDB, sel);
  90.    prec=MemHandleLock(hrec);
  91.    tmpptr=MemPtrNew(64);
  92.    MemMove(tmpptr, prec, 64);
  93.    MemHandleUnlock(hrec);
  94.    LinkFollow((LinkInfoPtr)prec);
  95.    MemPtrFree(tmpptr);
  96. }
  97.  
  98. static void AddTitle(VoidHand h)
  99. {
  100.    LinkInfoPtr p;
  101.    Char name[32];
  102.    Err err;
  103.    DmSearchStateType searchstate;
  104.    UInt cardno;
  105.    LocalID dbid;
  106.    Char title[64];
  107.    DateTimeType date;
  108.    
  109.    if (MemHandleSize(h)>64)
  110.       return; /* it already has a title */
  111.  
  112.    p=(LinkInfoPtr)MemHandleLock(h);
  113.    err=DmGetNextDatabaseByTypeCreator(true, &searchstate, 'appl', p->creator,
  114.                       true, &cardno, &dbid);
  115.    MemHandleUnlock(h);
  116.    if (err)
  117.       name[0]=0;
  118.    else 
  119.       DmDatabaseInfo(cardno, dbid, name,
  120.              NULL,NULL,NULL,NULL,NULL,
  121.              NULL,NULL,NULL,NULL,NULL);
  122.  
  123.    TimSecondsToDateTime(TimGetSeconds(), &date);
  124.    StrPrintF(title, "%s %d:%d", name, date.hour, date.minute);
  125.  
  126.    MemHandleResize(h, 65+StrLen(title));
  127.    p=MemHandleLock(h);
  128.    DmWrite(p, 64, title, StrLen(title)+1);
  129.    MemHandleUnlock(h);
  130. }
  131.  
  132. /* if there is a link pending, sends this link to it and returns true.
  133.    else returns false
  134. */
  135. static Boolean PendingLink(LinkInfoPtr info)
  136. {
  137.    LinkInfoType preflink;
  138.    Ptr output;
  139.    Err err;
  140.    DmSearchStateType searchstate;
  141.    UInt cardno;
  142.    LocalID dbid;
  143.    Word size=64;
  144.  
  145.    if (PrefGetAppPreferences('Link', 1, &preflink, &size, false)
  146.        ==noPreferenceFound) {
  147.       return false;
  148.    };
  149.  
  150.    output=MemPtrNew(MemPtrSize(info)+64);
  151.    MemMove(output, &preflink, 64);
  152.    MemMove(output+64, info, MemPtrSize(info));
  153.  
  154.    err=DmGetNextDatabaseByTypeCreator(true, &searchstate,
  155.                       'appl', preflink.creator,
  156.                       true, &cardno, &dbid);
  157.    if (err) return false;
  158.    MemPtrSetOwner(output, 0);
  159.    SysUIAppSwitch(cardno, dbid, linkAppLaunchReturnLink, (Ptr)output);
  160.  
  161.    /* remove preference */
  162.    PrefSetAppPreferences('Link', 1, 0, NULL, 0, false);
  163.    
  164.    return true;
  165. }
  166.  
  167. static void StoreLink(LinkInfoPtr info)
  168. {
  169.    VoidHand hrec;
  170.    Ptr prec;
  171.    UInt index=0;
  172.  
  173.    hrec=DmNewRecord(LinkDB, &index, MemPtrSize(info));
  174.    prec=MemHandleLock(hrec);
  175.    DmWrite(prec, 0, info, MemPtrSize(info));
  176.    MemHandleUnlock(hrec);
  177.  
  178.    AddTitle(hrec);
  179.  
  180.    DmReleaseRecord(LinkDB, index, true);
  181. }
  182.  
  183. static void HistoryPush(LinkInfoPtr linkinfo)
  184. {
  185.    DmOpenRef db;
  186.    VoidHand hrec;
  187.    Ptr prec;
  188.    UInt index=0;
  189.    int i;
  190.    LinkHistoryPrefsType histprefs;
  191.    LinkHistoryPrefsType2 histprefs2;
  192.    Word prefssize;
  193.    UInt cardno;
  194.    LocalID dbid;
  195.    ULong moddate;
  196.    SWord prefsver;
  197.  
  198.    db=DmOpenDatabaseByTypeCreator('HIST', 'Link', dmModeReadWrite);
  199.  
  200.    /* the database is already open if HistoryBack/Forward is called
  201.       with the LinkHistoryHack loggin app use.  In this case, the link
  202.       just passed is already in the history, so it's safe to ignore */
  203.    if ((!db)&&(DmGetLastErr()!=dmErrCantFind))
  204.       return;
  205.    
  206.    if (!db) {
  207.       UInt cardno;
  208.       LocalID dbid;
  209.       UInt attr;
  210.       
  211.       if (DmCreateDatabase(0, "LinkMasterHist", 'Link', 'HIST', false))
  212.      ErrDisplay("Error creating database");
  213.       db=DmOpenDatabaseByTypeCreator('HIST', 'Link', dmModeReadWrite);
  214.       DmOpenDatabaseInfo(db, &dbid, NULL, NULL, &cardno, NULL);
  215.       DmDatabaseInfo(cardno, dbid, NULL, &attr, NULL,
  216.              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  217.       attr|=dmHdrAttrBackup;
  218.       DmSetDatabaseInfo(cardno, dbid, NULL, &attr, NULL,
  219.             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  220.  
  221.       /* set preference */
  222.       prefssize=sizeof(histprefs);
  223.       if (PrefGetAppPreferences('Link', 0, &histprefs, &prefssize, true)
  224.       ==noPreferenceFound) {
  225.      histprefs.max=50;
  226.       };
  227.       histprefs.current=0;
  228.       PrefSetAppPreferences('Link', 0, 0, &histprefs, prefssize, true);
  229.    };
  230.  
  231.    prefssize=sizeof(histprefs);
  232.    PrefGetAppPreferences('Link', 0, &histprefs, &prefssize, true);
  233.  
  234.    prefssize=sizeof(histprefs2);
  235.    prefsver=PrefGetAppPreferences('Link', 2, &histprefs2, &prefssize, true);
  236.    if (prefsver<0) {
  237.       histprefs2.mintime=2;
  238.       histprefs2.allowdups=0;
  239.    };
  240.  
  241.    /* if the previous item was created too recently, replace it */
  242.    DmOpenDatabaseInfo(db, &dbid, NULL, NULL, &cardno, NULL);
  243.    DmDatabaseInfo(cardno, dbid, NULL,NULL,NULL,NULL, &moddate,
  244.           NULL,NULL,NULL,NULL,NULL,NULL);
  245.    if ((moddate>(TimGetSeconds()-histprefs2.mintime))
  246.        &&(DmNumRecords(db)>histprefs.current))
  247.       DmRemoveRecord(db, histprefs.current);
  248.  
  249.    /* always disallow consecutive duplicates */
  250.    if (DmNumRecords(db)>histprefs.current) {
  251.       hrec=DmQueryRecord(db, histprefs.current);
  252.       if (hrec) {
  253.          Boolean match=true;
  254.          prec=MemHandleLock(hrec);
  255.          /* use longs here for speed */
  256.          for (i=0; i<(64/sizeof(long)); i++) {
  257.         if (((LongPtr)prec)[i]!=((LongPtr)linkinfo)[i]) {
  258.            match=false;
  259.            break;
  260.         }
  261.          };
  262.          MemHandleUnlock(hrec);
  263.          if (match) {
  264.         DmCloseDatabase(db);
  265.         return;
  266.          };
  267.       };
  268.    };
  269.    if (!histprefs2.allowdups) {
  270.       int j;
  271.       for (j=DmNumRecords(db); j>=0; j--) {
  272.      hrec=DmQueryRecord(db, j);
  273.      if (hrec) {
  274.         Boolean match=true;
  275.         prec=MemHandleLock(hrec);
  276.         for (i=0; i<(64/sizeof(long)); i++) {
  277.            if (((LongPtr)prec)[i]!=((LongPtr)linkinfo)[i]) {
  278.           match=false;
  279.           break;
  280.            }
  281.         };
  282.         MemHandleUnlock(hrec);
  283.         if (match) {
  284.            DmRemoveRecord(db, j);
  285.            break; /* we can stop looking for matches here */
  286.         };
  287.      }
  288.       }
  289.    }
  290.    
  291.    /* clear "forward" buffer */
  292.    for (i=0; i<histprefs.current; i++)
  293.       DmRemoveRecord(db, 0);
  294.    histprefs.current=0;
  295.    PrefSetAppPreferences('Link', 0, 0, &histprefs, prefssize, true);
  296.  
  297.    hrec=DmNewRecord(db, &index, MemPtrSize(linkinfo));
  298.    prec=MemHandleLock(hrec);
  299.    DmWrite(prec, 0, linkinfo, MemPtrSize(linkinfo));
  300.    MemHandleUnlock(hrec);
  301.    AddTitle(hrec);
  302.    DmReleaseRecord(db, index, true);
  303.  
  304.    /* check max size */
  305.    for (i=DmNumRecords(db)-1; i>histprefs.max; i--)
  306.       DmRemoveRecord(db, i);
  307.    
  308.    DmCloseDatabase(db);
  309. }
  310.  
  311. static DWord HistoryBack()
  312. {
  313.    DmOpenRef db;
  314.    VoidHand hrec;
  315.    Ptr prec;
  316.    LinkHistoryPrefsType histprefs;
  317.    Word prefssize;
  318.    Ptr tmpptr;
  319.  
  320.    db=DmOpenDatabaseByTypeCreator('HIST', 'Link', dmModeReadOnly);
  321.  
  322.    if (!db) return appErrorClass;
  323.  
  324.    prefssize=sizeof(histprefs);
  325.    PrefGetAppPreferences('Link', 0, &histprefs, &prefssize, true);
  326.  
  327.    if (histprefs.current>=DmNumRecords(db)) {
  328.       DmCloseDatabase(db);
  329.       return appErrorClass;
  330.    };
  331.  
  332.    /* increment position */
  333.    histprefs.current++;
  334.    PrefSetAppPreferences('Link', 0,0, &histprefs, prefssize, true);
  335.  
  336.    /* follow link */
  337.    /* allocate a temporary here because the record should be unlocked
  338.       when we call linkfollow (because it could start a chain of events
  339.       that alters the history, possibly deleting the record)
  340.    */
  341.    hrec=DmQueryRecord(db, histprefs.current);
  342.    prec=MemHandleLock(hrec);
  343.    tmpptr=MemPtrNew(64);
  344.    MemMove(tmpptr, prec, 64);
  345.    MemHandleUnlock(hrec);
  346.    LinkFollow((LinkInfoPtr)tmpptr);
  347.    MemPtrFree(tmpptr);
  348.  
  349.    DmCloseDatabase(db);
  350.    return 0;
  351. }
  352.  
  353. static DWord HistoryForward()
  354. {
  355.    DmOpenRef db;
  356.    VoidHand hrec;
  357.    Ptr prec;
  358.    LinkHistoryPrefsType histprefs;
  359.    Word prefssize;
  360.    Ptr tmpptr;
  361.  
  362.    db=DmOpenDatabaseByTypeCreator('HIST', 'Link', dmModeReadOnly);
  363.  
  364.    if (!db) return appErrorClass;
  365.  
  366.    prefssize=sizeof(histprefs);
  367.    PrefGetAppPreferences('Link', 0, &histprefs, &prefssize, true);
  368.  
  369.    if (histprefs.current==0) {
  370.       DmCloseDatabase(db);
  371.       return appErrorClass;
  372.    };
  373.  
  374.    /* decrement position */
  375.    histprefs.current--;
  376.    PrefSetAppPreferences('Link', 0,0, &histprefs, prefssize, true);
  377.  
  378.    /* follow link */
  379.    /* see note in HistoryBack */
  380.    hrec=DmQueryRecord(db, histprefs.current);
  381.    prec=MemHandleLock(hrec);
  382.    tmpptr=MemPtrNew(64);
  383.    MemMove(tmpptr, prec, 64);
  384.    MemHandleUnlock(hrec);
  385.    LinkFollow((LinkInfoPtr)tmpptr);
  386.    MemPtrFree(tmpptr);
  387.  
  388.    DmCloseDatabase(db);
  389.    return 0;
  390. }
  391.  
  392. static Boolean MainFormHandleEvent (EventPtr e)
  393. {
  394.     Boolean handled = false;
  395.     FormPtr frm;
  396.     
  397.     CALLBACK_PROLOGUE
  398.  
  399.     switch (e->eType) {
  400.     case frmOpenEvent:
  401.     frm = FrmGetActiveForm();
  402.     InitForm(frm);
  403.     FrmDrawForm(frm);
  404.     handled = true;
  405.     break;
  406.  
  407.     case frmUpdateEvent:
  408.        InitForm(FrmGetActiveForm());
  409.        break;
  410.  
  411.     case menuEvent:
  412.     MenuEraseStatus(NULL);
  413.  
  414.     switch(e->data.menu.itemID) {
  415.     case MainMenuNewLink:
  416.        NewLink();
  417.        break;
  418.  
  419.     case MainMenuDelLink:
  420.        DelLink();
  421.        break;
  422.  
  423.     case MainMenuPrefs:
  424.        FrmPopupForm(PrefsForm);
  425.        break;
  426.        
  427.     case MainMenuAbout:
  428.        FrmAlert(AboutAlert);
  429.        break;
  430.     }
  431.  
  432.         handled = true;
  433.     break;
  434.  
  435.     case ctlSelectEvent:
  436.     switch(e->data.ctlSelect.controlID) {
  437.     case MainNewLink:
  438.        NewLink();
  439.        break;
  440.  
  441.     case MainDelLink:
  442.        DelLink();
  443.        break;
  444.  
  445.     case MainGo:
  446.        Go();
  447.        break;
  448.     }
  449.     break;
  450.  
  451.     case lstSelectEvent:
  452.        if (e->data.lstSelect.listID!=MainLinkList)
  453.       break;
  454.        if (mode==linkAppLaunchRequestLink) {
  455.       VoidHand hrec;
  456.       Ptr prec;
  457.  
  458.       hrec=DmQueryRecord(LinkDB, e->data.lstSelect.selection);
  459.       prec=MemHandleLock(hrec);
  460.       PendingLink((LinkInfoPtr)prec);
  461.       MemHandleUnlock(hrec);
  462.        }
  463.        break;
  464.  
  465.     case popSelectEvent:
  466.        if (e->data.popSelect.listID!=MainModeList)
  467.       break;
  468.        switch (e->data.popSelect.selection) {
  469.        case 0: /* published links */
  470.       DmCloseDatabase(LinkDB);
  471.       LinkDB=DmOpenDatabaseByTypeCreator('DATA', 'Link', dmModeReadWrite);
  472.       frm=FrmGetActiveForm();
  473.       CtlShowControl(FrmGetObjectPtr(frm,
  474.                      FrmGetObjectIndex(frm, MainDelLink)));
  475.       InitForm(frm);
  476.       FrmDrawForm(frm);
  477.       break;
  478.  
  479.        case 1: /* history */
  480.       DmCloseDatabase(LinkDB);
  481.       LinkDB=DmOpenDatabaseByTypeCreator('HIST', 'Link', dmModeReadOnly);
  482.       if (!LinkDB) {
  483.          if (DmCreateDatabase(0, "LinkMasterHist", 'Link', 'HIST', false))
  484.         ErrDisplay("Error creating database");
  485.          LinkDB=DmOpenDatabaseByTypeCreator('HIST', 'Link',
  486.                         dmModeReadOnly);
  487.       };
  488.       frm=FrmGetActiveForm();
  489.       CtlHideControl(FrmGetObjectPtr(frm,
  490.                      FrmGetObjectIndex(frm, MainDelLink)));
  491.       InitForm(frm);
  492.       FrmDrawForm(frm);
  493.       break;
  494.  
  495.        default: break;
  496.        };
  497.        break;
  498.  
  499.     default:
  500.         break;
  501.     }
  502.  
  503.     CALLBACK_EPILOGUE
  504.  
  505.     return handled;
  506. }
  507.  
  508. static Boolean ApplicationHandleEvent(EventPtr e)
  509. {
  510.     FormPtr frm;
  511.     Word    formId;
  512.     Boolean handled = false;
  513.  
  514.     if (e->eType == frmLoadEvent) {
  515.     formId = e->data.frmLoad.formID;
  516.     frm = FrmInitForm(formId);
  517.     FrmSetActiveForm(frm);
  518.  
  519.     switch(formId) {
  520.     case MainForm:
  521.         FrmSetEventHandler(frm, MainFormHandleEvent);
  522.         break;
  523.  
  524.     case NewLinkForm:
  525.        FrmSetEventHandler(frm, NewLinkFormHandleEvent);
  526.        break;
  527.  
  528.     case PrefsForm:
  529.        FrmSetEventHandler(frm, PrefsFormHandleEvent);
  530.        break;
  531.     }
  532.     handled = true;
  533.     }
  534.  
  535.     return handled;
  536. }
  537.  
  538. /* Get preferences, open (or create) app database */
  539. static Word StartApplication(void)
  540. {
  541.    LinkDB=DmOpenDatabaseByTypeCreator('DATA', 'Link', dmModeReadWrite);
  542.  
  543.    if (!LinkDB) {
  544.       if (DmCreateDatabase(0, "LinkMasterDB", 'Link', 'DATA', false))
  545.      ErrDisplay("Error creating database");
  546.       LinkDB=DmOpenDatabaseByTypeCreator('DATA', 'Link', dmModeReadWrite);
  547.    };
  548.    
  549.    FrmGotoForm(MainForm);
  550.    return 0;
  551. }
  552.  
  553. /* Save preferences, close forms, close app database */
  554. static void StopApplication(void)
  555. {
  556.    DmCloseDatabase(LinkDB);
  557.    
  558.    FrmSaveAllForms();
  559.    FrmCloseAllForms();
  560. }
  561.  
  562. /* The main event loop */
  563. static void EventLoop(void)
  564. {
  565.     Word err;
  566.     EventType e;
  567.  
  568.     do {
  569.     EvtGetEvent(&e, evtWaitForever);
  570.     if (! SysHandleEvent (&e))
  571.         if (! MenuHandleEvent (NULL, &e, &err))
  572.         if (! ApplicationHandleEvent (&e))
  573.             FrmDispatchEvent (&e);
  574.     } while (e.eType != appStopEvent);
  575. }
  576.  
  577. /* Main entry point; it is unlikely you will need to change this except to
  578.    handle other launch command codes */
  579. DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
  580. {
  581.     Word err;
  582.  
  583.     switch (cmd) {
  584.     case linkAppLaunchRequestLink:
  585.        /* store link in prefs */
  586.        PrefSetAppPreferences('Link', 1, 0, cmdPBP, 64, false);
  587.        /* fall thru */
  588.        
  589.     case sysAppLaunchCmdNormalLaunch:
  590.        mode=cmd;
  591.        err = StartApplication();
  592.        if (err) return err;
  593.        
  594.        EventLoop();
  595.        StopApplication();
  596.        break;
  597.        
  598.        
  599.     case linkAppLaunchReturnLink:
  600.        if (PendingLink((LinkInfoPtr)cmdPBP))
  601.       break;
  602.        
  603.        err=StartApplication();
  604.        if (err) return err;
  605.        StoreLink((LinkInfoPtr)cmdPBP);
  606.        EventLoop();
  607.        StopApplication();
  608.        break;
  609.  
  610.     case linkAppLaunchHistoryPush:
  611.        HistoryPush((LinkInfoPtr)cmdPBP);
  612.        break;
  613.  
  614.     case linkAppLaunchHistoryBack:
  615.        return HistoryBack();
  616.        break;
  617.  
  618.     case linkAppLaunchHistoryForward:
  619.        return HistoryForward();
  620.        break;
  621.        
  622.     default:
  623.        return sysErrParamErr;
  624.     };
  625.     
  626.     return 0;
  627. }
  628.