home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / xcal / part04 / xcal_memo.c < prev    next >
C/C++ Source or Header  |  1991-05-12  |  15KB  |  600 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)xcal_memo.c    1.11 (Hillside Systems) 1/16/91";
  3. static char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
  4. #endif  /* lint */
  5. /***
  6.  
  7. * module name:
  8.     xcal_memo.c
  9. * function:
  10.     Deal with popup memo file
  11.     A single popup file is stored in a file called
  12.     memo on the Calendar directory
  13. * history:
  14.     Written December 1990
  15.     Peter Collinson
  16.     Hillside Systems
  17. * (C) Copyright: 1989,1990 Hillside Systems/Peter Collinson
  18.     
  19.     For full permissions and copyright notice - see xcal.c
  20. ***/
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <X11/Xos.h>
  24. #include <X11/Intrinsic.h>
  25. #include <X11/StringDefs.h>
  26. #include <X11/Shell.h>
  27. #include <X11/Xaw/AsciiText.h>
  28. #include <X11/Xaw/Text.h>
  29. #include <X11/Xaw/Command.h>
  30. #include <X11/Xaw/Label.h>
  31. #include <X11/Xaw/Paned.h>
  32. #include <X11/Xaw/Form.h>
  33. #include <X11/Xaw/Dialog.h>
  34. #include "xcal.h"
  35.  
  36. static XtCallbackRec callbacks[] = {
  37.    {NULL,NULL},
  38.    {NULL,NULL}
  39. };
  40. #define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
  41.  
  42. /*
  43.  *    Structure for storing relavant data about the
  44.  *    memo Edit
  45.  */
  46. typedef struct    memoEdit
  47. {
  48.     Widget    m_button;    /* widget of the control button */
  49.     Widget    m_popup;    /* widget of editor popup */
  50.     Widget    m_quit;        /* widget of quit button */
  51.     Widget    m_save;        /* widget of save button */
  52.     Boolean m_savesens;    /* state of the save button */
  53.     Widget    m_display;    /* widget of display title area */
  54.     Widget    m_text;        /* the text area */
  55.     Widget    m_today;    /* today's data */
  56.     Widget    m_weekly;    /* widget of text image of weekly events */
  57.     Cardinal m_size;    /* size of the buffer */
  58.     char    *m_data;    /* pointer to malloc'ed data buffer */
  59. } MemoEdit;
  60.  
  61. static    MemoEdit memo;
  62.  
  63. extern    Boolean FoundCalendarDir;               /* whether the Calendar directory exists */
  64.  
  65. static    String    memoContents;
  66.  
  67. extern void MemoHelp();                /* look in xcal_help.c */
  68.  
  69. /*
  70.  *    Internal routines
  71.  */
  72. void    MemoPopup();
  73. static void CleanMemo();
  74. static void MemoCheckExit();
  75. static void MCheckDia();
  76. static Boolean WriteMemoFile();
  77. static int NewlineCount();
  78. static String GetMemoFile();
  79. static void SaveMemoEdits();
  80. static void MemoTextChanged();
  81. static void FinishMemoEditing();
  82. static void YesCheck();
  83. static void NoCheck();
  84.  
  85. /*
  86.  *    Callback routine to display the memo file
  87.  */
  88.  
  89. void
  90. DoMemo(w, closure, call_data)
  91.     Widget w;
  92.     caddr_t    closure;
  93.     caddr_t call_data;
  94. {
  95.     static Arg args[1];
  96.     
  97.     /*
  98.      *    Make the button become a finish button
  99.      */
  100.     memo.m_button = w;
  101.     callbacks[0].callback = FinishMemoEditing;
  102.     callbacks[0].closure = (caddr_t)&memo;
  103.     XtSetArg(args[0], XtNcallback, callbacks);
  104.     XtSetValues(w, args, 1);
  105.     
  106.     MouseShow(w, False);
  107.     /*
  108.      *    Get existing memo contents
  109.      *    if the user is polling then re-read the file
  110.      */
  111.     if (appResources.update && memoContents != NULL)
  112.     {    XtFree(memoContents);
  113.         memoContents = NULL;
  114.     }
  115.     if (memoContents == NULL)
  116.         memoContents = GetMemoFile();
  117.  
  118.     /*
  119.      *    Set up the popup widget for editing
  120.      */
  121.     MemoPopup();
  122. }
  123.  
  124.  
  125. /*
  126.  *    Get old contents from a memo file if any
  127.  */
  128. static String
  129. GetMemoFile()
  130. {
  131.  
  132.     if (FoundCalendarDir && access(appResources.memoFile, F_OK) == 0)
  133.         return ReadCalendarFile(NULL, appResources.memoFile);
  134.     return NULL;
  135. }
  136.  
  137.  
  138. /*
  139.  *    Do the biz to popup an edit style window
  140.  */
  141. void
  142. MemoPopup()
  143. {
  144.     Widget        et, lw;
  145.     Widget        frame;
  146.     Arg        args[10];
  147.     Cardinal    nargs;
  148.     String        str;
  149.     MonthEntry    *me;
  150.     Dimension    charHeight;
  151.     char        buf[32];
  152.  
  153.     /*
  154.      *    set up edit buffer
  155.      */
  156.     if (memoContents)
  157.         memo.m_size = appResources.textbufsz + strlen(memoContents) + 1;
  158.     else    
  159.         memo.m_size = appResources.textbufsz;
  160.     memo.m_data = XtMalloc(memo.m_size);
  161.     if (memoContents)
  162.         strcpy(memo.m_data, memoContents);
  163.     else
  164.         *memo.m_data = '\0';
  165.     memo.m_popup = XtCreatePopupShell("memo", topLevelShellWidgetClass, toplevel, NULL, 0);
  166.  
  167.     /*
  168.      *    The first title line
  169.      */
  170.     et = XtCreateManagedWidget("memoPanel", panedWidgetClass, memo.m_popup, NULL, 0);
  171.  
  172.     nargs = 0;
  173.     XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  174.     XtSetArg(args[nargs], XtNskipAdjust, True); nargs++;
  175.     XtSetArg(args[nargs], XtNdefaultDistance, 1); nargs++;
  176.     frame = XtCreateManagedWidget("title", formWidgetClass, et, args, nargs);
  177.     /*
  178.      *    containing some buttons for controlling the world
  179.      */
  180.     /*
  181.      *    Take label "quit" from resources
  182.      */
  183.     callbacks[0].callback = FinishMemoEditing;
  184.     callbacks[0].closure = (caddr_t)&memo;
  185.     nargs = 0;
  186.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  187.     XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  188.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  189.     XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  190.     lw = memo.m_quit = XtCreateManagedWidget("quit", commandWidgetClass, frame, args, nargs);
  191.     /*
  192.      *    If we are dealing with  help then do it now
  193.      */
  194.     if (appResources.giveHelp)
  195.     {    /*
  196.          *    Take label "help" from resources
  197.          */
  198.         callbacks[0].callback = MemoHelp;
  199.         callbacks[0].closure = (caddr_t)0;
  200.         nargs = 0;
  201.         XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  202.         XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  203.         XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  204.         XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  205.         lw = XtCreateManagedWidget("help", commandWidgetClass, frame, args, nargs);
  206.     }
  207.     /*
  208.      *    The remaining bit here is a date label
  209.      */
  210.     PlaceStr(buf, &today, appResources.memoYearIs2);
  211.     nargs = 0;
  212.     XtSetArg(args[nargs], XtNlabel, buf); nargs++;
  213.     XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
  214.     XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  215.     XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
  216.     XtSetArg(args[nargs], XtNvertDistance, 2); nargs++;
  217.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  218.     XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  219.     lw = memo.m_display = XtCreateManagedWidget("date", labelWidgetClass, frame, args, nargs);
  220.     /*
  221.      *    Details for today
  222.      */
  223.     me = GetMonthEntry(today.year, today.month);
  224.     nargs = 0;
  225.     str = me->me_have[today.day];
  226.     if (str == NULL)
  227.         str = "";
  228.     XtSetArg(args[nargs], XtNstring, str); nargs++;
  229.     XtSetArg(args[nargs], XtNdisplayCaret, False); nargs++;
  230.     XtSetArg(args[nargs], XtNeditType, XawtextRead); nargs++;
  231.     memo.m_today = XtCreateManagedWidget("display", asciiTextWidgetClass, et, args, nargs);
  232.     {    Dimension height;
  233.  
  234.         XtSetArg(args[0], XtNheight, &height);
  235.         XtGetValues(memo.m_today, args, 1);
  236.         charHeight = height;
  237.         height = height*NewlineCount(str);
  238.         XtSetArg(args[0], XtNheight, height);
  239.         XtSetValues(memo.m_today, args, 1);
  240.     }
  241.  
  242.     /*
  243.      *    Weekly details - the data for today + an edit button
  244.      *    The header to this is a form
  245.      */
  246.     nargs = 0;
  247.     XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  248.     XtSetArg(args[nargs], XtNskipAdjust, True); nargs++;
  249.     XtSetArg(args[nargs], XtNdefaultDistance, 1); nargs++;
  250.     frame = XtCreateManagedWidget("weeklyMemo", formWidgetClass, et, args, nargs);
  251.  
  252.     /*
  253.      *    Take label "edit" from resources
  254.      */
  255.     callbacks[0].callback = DoWeekly;
  256.     callbacks[0].closure = (caddr_t)&memo;
  257.     nargs = 0;
  258.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  259.     XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  260.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  261.     XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  262.     lw = XtCreateManagedWidget("weeklyEdit", commandWidgetClass, frame, args, nargs);
  263.  
  264.     /*
  265.      *    Say this is a weekly commitment
  266.      */
  267.     nargs = 0;
  268.  
  269.     XtSetArg(args[nargs], XtNshowGrip, True); nargs++;
  270.     XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
  271.     XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  272.     XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
  273.     XtSetArg(args[nargs], XtNvertDistance, 2); nargs++;
  274.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  275.     XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  276.     lw = XtCreateManagedWidget("weeklyTitle", labelWidgetClass, frame, args, nargs);
  277.  
  278.     /*
  279.      *    Details for today
  280.      */
  281.     nargs = 0;
  282.     str = GetWeeklyFile(today.wday);
  283.     if (str == NULL)
  284.         str = "";
  285.     XtSetArg(args[nargs], XtNstring, str); nargs++;
  286.     XtSetArg(args[nargs], XtNdisplayCaret, False); nargs++;
  287.     XtSetArg(args[nargs], XtNeditType, XawtextRead); nargs++;
  288.     if (charHeight)
  289.         XtSetArg(args[nargs], XtNheight, NewlineCount(str)*charHeight); nargs++;
  290.     memo.m_weekly = XtCreateManagedWidget("display", asciiTextWidgetClass, et, args, nargs);
  291.     /*
  292.      *    Another form with some buttons
  293.      */
  294.     nargs = 0;
  295.     XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  296.     XtSetArg(args[nargs], XtNskipAdjust, True); nargs++;
  297.     XtSetArg(args[nargs], XtNdefaultDistance, 1); nargs++;
  298.     frame = XtCreateManagedWidget("memoMiddle", formWidgetClass, et, args, nargs);
  299.     /*
  300.      *    Take label "save" from resources
  301.      */
  302.     callbacks[0].callback = SaveMemoEdits;
  303.     callbacks[0].closure = (caddr_t)&memo;
  304.     nargs = 0;
  305.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  306.     XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  307.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  308.     XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  309.     XtSetArg(args[nargs], XtNsensitive, False); nargs++;
  310.     lw = memo.m_save = XtCreateManagedWidget("save", commandWidgetClass, frame, args, nargs);
  311.     memo.m_savesens = False;
  312.     /*
  313.      *    Say this is a memo edit
  314.      */
  315.     nargs = 0;
  316.     XtSetArg(args[nargs], XtNshowGrip, True); nargs++;
  317.     XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
  318.     XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  319.     XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
  320.     XtSetArg(args[nargs], XtNvertDistance, 2); nargs++;
  321.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  322.     XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  323.     lw = XtCreateManagedWidget("memoTitle", labelWidgetClass, frame, args, nargs);
  324.  
  325.      /*
  326.      *    The text widget is in the pane below
  327.      *    The Scroll Attributes are controlled from the application
  328.      *    defaults file
  329.      */
  330.     callbacks[0].callback = MemoTextChanged;
  331.     callbacks[0].closure = (caddr_t)&memo;
  332.     nargs = 0;
  333.     XtSetArg(args[nargs], XtNstring, memo.m_data); nargs++;
  334.     XtSetArg(args[nargs], XtNeditType, XawtextEdit); nargs++;
  335.     XtSetArg(args[nargs], XtNlength, memo.m_size); nargs++;
  336.     XtSetArg(args[nargs], XtNuseStringInPlace, True); nargs++;
  337.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  338.     memo.m_text = XtCreateManagedWidget("memoText", asciiTextWidgetClass, et, args, nargs);
  339.  
  340.     
  341.     XtPopup(memo.m_popup, XtGrabNone);
  342.     
  343. }
  344.  
  345. /*
  346.  *    Count newlines in a string
  347.  */
  348. static int
  349. NewlineCount(str)
  350.     String    str;
  351. {
  352.     register int sum = 0;
  353.  
  354.     while (*str)
  355.         if (*str++ == '\n')
  356.             sum++;
  357.     /* Add one line - assume last line does NOT have an nl */
  358.     sum++;
  359.     /* ignore a final newline */
  360.     if (str[-1] == '\n')
  361.         sum--;
  362.     if (sum <= 0) sum = 1;
  363.     return(sum > appResources.maxDisplayLines ? appResources.maxDisplayLines : sum);
  364. }
  365.  
  366. /*
  367.  *    Entry point from outside when today's text changed
  368.  */
  369. void
  370. UpdateMemo()
  371. {
  372.     Arg        args[1];
  373.     String        str;
  374.     Cardinal    nargs;
  375.     MonthEntry    *me;
  376.     char        buf[32];
  377.     
  378.     /*
  379.      * if the button widget is zero then we are displaying nothing
  380.      */
  381.     if (memo.m_button == 0)
  382.         return;
  383.  
  384.     me = GetMonthEntry(today.year, today.month);
  385.     nargs = 0;
  386.     str = me->me_have[today.day];
  387.     if (str == NULL)
  388.         str = "";
  389.     XtSetArg(args[0], XtNstring, str); nargs++;
  390.     XtSetValues(memo.m_today, args, 1);
  391.  
  392.     (void) sprintf(buf, "%d %s %d", today.day, appResources.mon[today.month], today.year);
  393.     XtSetArg(args[0], XtNlabel, buf);
  394.     XtSetValues(memo.m_display, args, 1);
  395.  
  396.     str = GetWeeklyFile(today.wday);
  397.     if (str == NULL)
  398.         str = "";
  399.     XtSetArg(args[0], XtNstring, str);
  400.     XtSetValues(memo.m_weekly, args, 1);
  401.  
  402. }
  403.  
  404. /*
  405.  *    Poll call from the alarm timeout
  406.  */
  407. void
  408. MemoPoll()
  409. {
  410.     int    size;
  411.     Arg    args[10];
  412.     int    nargs;
  413.     
  414.     if (memo.m_button == 0)
  415.         return;
  416.     if (memo.m_savesens == True)
  417.         return;
  418.  
  419.     if (memoContents)
  420.         XtFree(memoContents);
  421.     memoContents = GetMemoFile();
  422.     if (memoContents)
  423.     {    if (strcmp(memoContents, memo.m_data) == 0)
  424.             return;
  425.         size = strlen(memoContents) + 1;
  426.         if (size > memo.m_size)
  427.         {    size += appResources.textbufsz;
  428.             XtFree(memo.m_data);
  429.             memo.m_data = XtMalloc(memo.m_size = size);
  430.         }
  431.         strcpy(memo.m_data, memoContents);
  432.     }
  433.     else
  434.         *memo.m_data = '\0';
  435.         
  436.     nargs = 0;
  437.     XtSetArg(args[nargs], XtNstring, memo.m_data); nargs++;
  438.     XtSetArg(args[nargs], XtNlength, memo.m_size); nargs++;
  439.     XtSetArg(args[nargs], XtNuseStringInPlace, True); nargs++;
  440.     XtSetValues(memo.m_text, args, nargs);
  441. }
  442.         
  443. /*
  444.  *    Call backs for various buttons
  445.  */
  446. /* ARGSUSED */
  447. static void
  448. MemoTextChanged(w, closure, call_data)
  449.     Widget    w;
  450.     caddr_t    closure;
  451.     caddr_t call_data;
  452. {
  453.     register MemoEdit *memo = (MemoEdit *)closure;
  454.  
  455.     memo->m_savesens = True;
  456.     XtSetSensitive(memo->m_save, True);
  457. }
  458.  
  459. /*
  460.  *    Callback routines
  461.  */
  462. /* ARGSUSED */
  463. static void
  464. SaveMemoEdits(w, closure, call_data)
  465.     Widget    w;
  466.     caddr_t    closure;
  467.     caddr_t call_data;
  468. {
  469.     MemoEdit    *memo = (MemoEdit *)closure;
  470.  
  471.     if (WriteMemoFile(memo) == False)
  472.         return;
  473.     if (memoContents)
  474.     {    XtFree(memoContents);
  475.         memoContents = XtNewString(memo->m_data);
  476.     }
  477.     memo->m_savesens = False;
  478.     XtSetSensitive(memo->m_save, False);
  479. }
  480.  
  481. /*
  482.  *    Write the memo file out
  483.  */
  484. static Boolean
  485. WriteMemoFile(memo)
  486.     MemoEdit    *memo;
  487. {
  488.     Cardinal    len = strlen(memo->m_data);
  489.     String        fname;
  490.     int        fd;
  491.     extern        String MapStem;
  492.     
  493.     if (len == 0)
  494.     {    unlink(appResources.memoFile);
  495.         return(True);
  496.     }
  497.     /*
  498.      *    First let's see if we have 
  499.      *    to create the toplevel directory
  500.      */
  501.     if (!NeedTop())
  502.         return (False);
  503.  
  504.     fname = appResources.memoFile;
  505.  
  506.     if ((fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0)
  507.     {    XBell(XtDisplay(toplevel), 0);
  508.         fprintf(stderr, "xcal: Could not open %s/%s for writing.\n", MapStem, fname);
  509.         perror("xcal: open");
  510.         fflush(stderr);
  511.         return(False);
  512.     }
  513.  
  514.     if (write(fd, memo->m_data, len) != len)
  515.     {    XBell(XtDisplay(toplevel), 0);
  516.         fprintf(stderr, "xcal: Write error %s/%s file.\n", MapStem, fname);
  517.         perror("xcal: write");
  518.         fflush(stderr);
  519.         close(fd);
  520.         return(False);
  521.     }
  522.     close(fd);
  523.     return (True);
  524. }
  525.  
  526. static void
  527. FinishMemoEditing(w, closure, call_data)
  528.     Widget    w;
  529.     caddr_t    closure;
  530.     caddr_t call_data;
  531. {
  532.  
  533.     if (memo.m_savesens == True)
  534.     {    MemoCheckExit();
  535.         return;
  536.     }
  537.     CleanMemo();
  538. }
  539.  
  540. static void
  541. CleanMemo()
  542. {
  543.     static Arg args[1];
  544.     
  545.     callbacks[0].callback = DoMemo;
  546.     callbacks[0].closure = NULL;
  547.     XtSetArg(args[0], XtNcallback, callbacks);
  548.     XtSetValues(memo.m_button, args, 1);
  549.  
  550.     MouseShow(memo.m_button, True);
  551.     XtPopdown(memo.m_popup);
  552.     XtDestroyWidget(memo.m_popup);
  553.     XtFree(memo.m_data);
  554.     bzero((char *)&memo, sizeof(MemoEdit));
  555.  
  556. }
  557.  
  558. static void
  559. MemoCheckExit()
  560. {
  561.     DialogPopup(memo.m_quit, MCheckDia, &memo);
  562. }
  563.  
  564. static void
  565. MCheckDia(pop, ed)
  566.     Widget    pop;
  567.     MemoEdit *ed;
  568. {
  569.     Widget    dia;
  570.  
  571.     /* Take "Save file?" from resources */
  572.     dia =  XtCreateManagedWidget("check", dialogWidgetClass, pop, NULL, 0);
  573.     XawDialogAddButton(dia, "yes", YesCheck, ed);
  574.     XawDialogAddButton(dia, "no", NoCheck, ed);
  575. }
  576.  
  577. /* ARGSUSED */
  578. static void
  579. YesCheck(w, closure, call_data)
  580.     Widget w;
  581.     caddr_t    closure;
  582.     caddr_t call_data;
  583. {
  584.     SaveMemoEdits(w, closure, call_data);
  585.     CleanMemo();
  586.     XtDestroyWidget(XtParent(XtParent(w)));
  587.  
  588. }
  589.  
  590. /* ARGSUSED */
  591. static void
  592. NoCheck(w, closure, call_data)
  593.     Widget w;
  594.     caddr_t    closure;
  595.     caddr_t call_data;
  596. {
  597.     CleanMemo();
  598.     XtDestroyWidget(XtParent(XtParent(w)));
  599. }
  600.