home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / calentool / part05 / printer.c
Encoding:
C/C++ Source or Header  |  1991-04-06  |  13.4 KB  |  503 lines

  1. /*
  2.  * $Header: printer.c,v 1.1 91/03/27 16:46:20 billr Exp $
  3.  */
  4. /*
  5.  * printer.c
  6.  *
  7.  * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations.
  8.  *
  9.  * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  10.  *
  11.  * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  12.  *    All Rights Reserved
  13.  * Permission is hereby granted to use and modify this program in source
  14.  * or binary form as long as it is not sold for profit and this copyright
  15.  * notice remains intact.
  16.  *
  17.  *
  18.  * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  19.  *
  20.  * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
  21.  *    All Rights Reserved
  22.  * Permission is hereby granted to use and modify the modifications in source
  23.  * or binary form as long as they are not sold for profit and this copyright
  24.  * notice remains intact.
  25.  * Modified parse_date to allow +nnn and -nnn syntax for dates relative to the
  26.  * current date.  Peter Marshall <peter.marshall@uwo.ca>. 1989-09-19.
  27.  */
  28. /********************************************
  29.  *                        *
  30.  *              Printing routines.        *
  31.  *                        *
  32.  ********************************************/
  33.  
  34. #include "ct.h"
  35. #include <stdio.h>
  36. #include <suntool/sunview.h>
  37. #include <suntool/canvas.h>
  38. #include <sys/time.h>
  39.  
  40. extern struct tm current, today;
  41. extern int n_slots;
  42. extern struct dayslot *slots;
  43. extern char apts_pathname[];
  44. extern int nr_weekdays, n_tslots;
  45. extern char *mailto;
  46. extern int findex;
  47. extern struct appt_entry future[];
  48. extern char printer[];
  49. extern Canvas canvas;
  50. extern Pixwin *main_pixwin;
  51. extern int mainsw_state;
  52. extern Pixfont *font, *sfont;
  53. extern int monday_first, hour24, day_first;
  54. extern int print_to_file;
  55. extern int print_dev, week_ofs;
  56. extern char *daynames[], *monthnames[];
  57. extern char clockstr[], strbuf[];
  58.  
  59. char rasfile[] = "/usr/tmp/calentool.ras";
  60. char psfile[] = "/usr/tmp/calentool.ps";
  61.  
  62.  
  63. /*
  64.  * convert appt entry to ASCII string for display with date, time and msg
  65.  */
  66. char *
  67. format_appt(appt)
  68. struct appt_entry *appt;
  69. {
  70.     int e_hour, e_minutes, duration;
  71.     struct tm Save;
  72.  
  73.     if (appt->arrows > 0) {
  74.         duration = appt->arrows + 1;
  75.         e_hour = appt->hour + duration/2;
  76.         e_minutes = appt->minute + ((duration%2) * 30);
  77.     } else {
  78.         e_hour = appt->hour;
  79.         e_minutes = appt->minute + 30;
  80.     }
  81.     if (e_minutes == 60) {
  82.         e_minutes = 0;
  83.         ++e_hour;
  84.     }
  85.     /* get day of week */
  86.     Save = current;
  87.     current.tm_year = appt->year;
  88.     current.tm_mon = appt->month;
  89.     current.tm_mday = appt->day;
  90.     fix_current_day();
  91.  
  92.     if (appt->flags & A_NOTE) {
  93.         /* note */
  94.         if (appt->flags & ALL_YEARS)
  95.             if (day_first)
  96.                 sprintf(strbuf,"%3.3s %2d/%02d    --  %s",
  97.                     daynames[current.tm_wday], appt->day,
  98.                     appt->month+1, appt->str);
  99.             else
  100.                 sprintf(strbuf,"%3.3s %2d/%02d    --  %s",
  101.                     daynames[current.tm_wday], appt->month+1,
  102.                     appt->day, appt->str);
  103.         else if (appt->year > 99)
  104.             if (day_first)
  105.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  106.                     daynames[current.tm_wday], appt->day,
  107.                     appt->month+1, appt->year-100, appt->str);
  108.             else
  109.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  110.                     daynames[current.tm_wday], appt->month+1,
  111.                     appt->day, appt->year-100, appt->str);
  112.         else
  113.             if (day_first)
  114.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  115.                     daynames[current.tm_wday], appt->day,
  116.                     appt->month+1, appt->year, appt->str);
  117.             else
  118.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  119.                     daynames[current.tm_wday], appt->month+1,
  120.                     appt->day, appt->year, appt->str);
  121.     } else {
  122.         /* standard appointment */
  123.         if (hour24)
  124.             if (day_first)
  125.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d to %2d:%02d   %s",
  126.                     daynames[current.tm_wday], appt->day,
  127.                     appt->month+1, appt->year, appt->hour, appt->minute,
  128.                     e_hour, e_minutes, appt->str);
  129.             else
  130.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d to %2d:%02d   %s",
  131.                     daynames[current.tm_wday], appt->month+1,
  132.                     appt->day, appt->year, appt->hour, appt->minute,
  133.                     e_hour, e_minutes, appt->str);
  134.         else
  135.             if (day_first)
  136.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d%s to %2d:%02d%s   %s",
  137.                     daynames[current.tm_wday], appt->day,
  138.                     appt->month+1, appt->year, (appt->hour < 13 ? appt->hour : appt->hour-12), appt->minute,
  139.                     (appt->hour < 12 ? "am" : "pm"),
  140.                     (e_hour < 13 ? e_hour : e_hour-12), e_minutes,
  141.                     (e_hour < 12 ? "am" : "pm"),
  142.                     appt->str);
  143.             else
  144.                 sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d%s to %2d:%02d%s   %s",
  145.                     daynames[current.tm_wday], appt->month+1,
  146.                     appt->day, appt->year, (appt->hour < 13 ? appt->hour : appt->hour-12), appt->minute,
  147.                     (appt->hour < 12 ? "am" : "pm"),
  148.                     (e_hour < 13 ? e_hour : e_hour-12), e_minutes,
  149.                     (e_hour < 12 ? "am" : "pm"),
  150.                     appt->str);
  151.     }
  152.     current = Save;
  153.     return(strbuf);
  154. }
  155.  
  156. /*
  157.  * convert appt entry to ASCII string for display with time and msg
  158.  *    if <esc_parens> is true then put '\' in front of parens (for Ps)
  159.  */
  160. char *
  161. format_appt_nd(appt, esc_parens)
  162. struct appt_entry *appt;
  163. int    esc_parens;
  164. {
  165.     int e_hour, e_minutes, duration;
  166.     char *p, *q;
  167.     struct tm Save;
  168.  
  169.     if (appt->arrows > 0) {
  170.         duration = appt->arrows + 1;
  171.         e_hour = appt->hour + duration/2;
  172.         e_minutes = appt->minute + ((duration%2) * 30);
  173.     } else {
  174.         e_hour = appt->hour;
  175.         e_minutes = appt->minute + 30;
  176.     }
  177.     if (e_minutes == 60) {
  178.         e_minutes = 0;
  179.         ++e_hour;
  180.     }
  181.  
  182.     strbuf[0] = '\0';
  183.     if (!(appt->flags & A_NOTE)) {
  184.         /* standard appointment */
  185.         if (hour24)
  186.             sprintf(strbuf,"%2d:%02d to %2d:%02d  ",
  187.                 appt->hour, appt->minute, e_hour, e_minutes);
  188.         else
  189.             sprintf(strbuf,"%2d:%02d%s to %2d:%02d%s  ",
  190.                 (appt->hour < 13 ? appt->hour : appt->hour-12), appt->minute,
  191.                 (appt->hour < 12 ? "am" : "pm"),
  192.                 (e_hour < 13 ? e_hour : e_hour-12), e_minutes,
  193.                 (e_hour < 12 ? "am" : "pm"));
  194.     }
  195.     p = appt->str;
  196.     q = strbuf + strlen(strbuf);
  197.     while (*p) {
  198.         if (esc_parens)
  199.             switch (*p) {
  200.                 /* ignore these */
  201.                 case '\b':
  202.                 case '\f':
  203.                 case '\n':
  204.                 case '\r':
  205.                 case '\t':
  206.                     break;
  207.                 /* escape these for PostScript */
  208.                 case '\\':
  209.                 case '(':
  210.                 case ')':
  211.                     *q++ = '\\';
  212.                     break;
  213.             }
  214.         *q++ = *p++;
  215.     }
  216.     *q = '\0';
  217.  
  218.     return(strbuf);
  219. }
  220.  
  221. /*
  222.  * Print today's appointments to stdout or mail (useful if we only have an ASCII
  223.  * terminal connected to our Sun). Invoked by the "-p", "-P", "-m" or
  224.  * "-M" options. The -T option is used to select print device
  225.  * (PostScript or ASCII).
  226.  * Month information is only printed as PostScript output.
  227.  */
  228. print_apts(which, dest)
  229. int which, dest;
  230. {
  231.     int i, gd_rtn, target;
  232.     FILE *output, *pfp, *popen();
  233.     char cmd[80], *name, *cuserid(), *mail_subj();
  234.     struct tm Save;
  235.  
  236.     fix_current_day();
  237.     gd_rtn = get_day_appts();
  238.     if (which == PRI_DAY && !gd_rtn)
  239.         return;    /* nothing to show */
  240.     if (which == PRI_DAY_XNOTES && gd_rtn == SOME_MKNOTES)
  241.         /* all we have is marked notes */
  242.         return;    /* nothing to show */
  243.     if (dest == DST_MAIL) {
  244.         if (mailto != NULL) {
  245.             name = mailto;
  246.         } else if ((name = cuserid(NULL)) == NULL) {
  247.             err_rpt("nobody to mail to", FATAL);
  248.         }
  249.         sprintf(cmd, "%s -s \"Appointments for %s\" %s", MAILPROG, mail_subj(), name);
  250.         if ((output = popen(cmd, "w")) == NULL)
  251.             err_rpt("Couldn't pipe to 'mail'", FATAL);
  252.     } else {
  253.         output = stdout;
  254.     }
  255.     
  256.     if (which == PRI_DAY || which == PRI_DAY_XNOTES) {
  257.         if (print_dev == PR_POSTSCRIPT)
  258. #ifdef RASTER_ONLY
  259.             fprintf(output, "PostScript output option not compiled in\n");
  260. #else
  261.             print_psday(output, (which == PRI_DAY_XNOTES ? TRUE : FALSE));
  262. #endif
  263.         else
  264.             print_one_day(which, output, gd_rtn);
  265.     } else if (which == PRI_WEEK || which == PRI_WEEK_XNOTES) {
  266.         Save = current;
  267.         if (!week_ofs) {
  268.             /* start printing on first dow */
  269.             if (nr_weekdays == 7 && !monday_first)
  270.                 target = SUN;
  271.             else
  272.                 target = MON;
  273.             if (current.tm_wday >= target)
  274.                 while (current.tm_wday-- > target)
  275.                     current.tm_mday--;
  276.             else
  277.                 /* looking at Sun */
  278.                 current.tm_mday++;
  279.             fix_current_day();
  280.         }
  281.         if (print_dev == PR_POSTSCRIPT)
  282. #ifdef RASTER_ONLY
  283.             fprintf(output, "PostScript output option not compiled in\n");
  284. #else
  285.             print_psweek(output, (which == PRI_WEEK_XNOTES ? TRUE : FALSE));
  286. #endif
  287.         else
  288.             for (i=0;i<nr_weekdays;i++) {
  289.                 gd_rtn = get_day_appts();
  290.                 if ((gd_rtn && which == PRI_WEEK) ||
  291.                     (gd_rtn & ~SOME_MKNOTES && which == PRI_WEEK_XNOTES))
  292.                     print_one_day(which, output, gd_rtn);
  293.                 current.tm_mday++;
  294.                 fix_current_day();
  295.             }
  296.         current = Save;
  297.     } else if (which == PRI_MONTH || which == PRI_MONTH_XNOTES) {
  298.         if (print_dev == PR_POSTSCRIPT)
  299. #ifdef RASTER_ONLY
  300.             fprintf(output, "PostScript output option not compiled in\n");
  301. #else
  302.             print_psmonth(output, (which == PRI_MONTH_XNOTES ? TRUE : FALSE));
  303. #endif
  304.         else
  305.             fprintf(output, "\nNo ASCII month printout is available\n");
  306.     }
  307.     fflush(output);
  308.     if (dest == DST_MAIL)
  309.         pclose(output);
  310. }
  311.  
  312. print_one_day(which, output, gdrtn)
  313. int which;
  314. FILE *output;
  315. int gdrtn;
  316. {
  317.     int i;
  318.     struct appt_entry tmp_apt, *aptr;
  319.     char *format_appt();
  320.  
  321.     if (day_first)
  322.         fprintf(output,"\n\t*** Appointments for %s %d %s %d ***\n\n", 
  323.             daynames[current.tm_wday], current.tm_mday,
  324.             monthnames[current.tm_mon], current.tm_year+1900);
  325.     else
  326.         fprintf(output,"\n\t*** Appointments for %s %s %d, %d ***\n\n", 
  327.             daynames[current.tm_wday], monthnames[current.tm_mon],
  328.             current.tm_mday, current.tm_year+1900);
  329.  
  330.     for (i=0; i<n_slots; i++) {
  331.         if (i == n_tslots)
  332.             /* start of notes section */
  333.             if ((gdrtn & SOME_NOTES) ||
  334.                (!(which & PRI_XNOTES) && (gdrtn & SOME_MKNOTES)))
  335.                 fprintf(output,"\n\t\t     ===== Notes =====\n");
  336.         if (slots[i].first != NULL && slots[i].active > 0) {
  337.             /* at least one appt here */
  338.             aptr = slots[i].first;
  339.             do {
  340.                 if ((which & PRI_XNOTES) && ((aptr->flags & MARKED_NOTE) == MARKED_NOTE))
  341.                     continue;
  342.                 if (chk_deleted(&slots[i], aptr))
  343.                     continue;
  344.                 tmp_apt = *aptr;
  345.                 tmp_apt.year = current.tm_year;
  346.                 tmp_apt.month = current.tm_mon;
  347.                 tmp_apt.day = current.tm_mday;
  348.                 fprintf(output, "%s\n", format_appt(&tmp_apt));
  349.             } while ((aptr = aptr->next) != NULL);
  350.         }
  351.     }
  352.     if (findex) {
  353.         /* print out future appointments */
  354.         fprintf(output, "\n\t\t===== Future Reminders =====\n");
  355.         for (i=0; i<findex; i++)
  356.             fprintf(output, "%s\n", format_appt(&future[i]));
  357.     }
  358.     fprintf(output,"\n------------------------------------------------------------------\n");
  359. }
  360.  
  361. /*
  362.  * mail_subj() - make subject line for appointment mail. Use "today"
  363.  * or "tomorrow" if appropriate, otherwise use the actual date.
  364.  */
  365. char *
  366. mail_subj()
  367. {
  368.     struct tm Save;
  369.  
  370.     if (!ymd_compare(current, today))
  371.         sprintf(strbuf, "today");
  372.     else {
  373.         Save = current;
  374.         current.tm_mday--;
  375.         fix_current_day();
  376.         if (!ymd_compare(current, today))
  377.             sprintf(strbuf, "tomorrow");
  378.         else if (day_first)
  379.             sprintf(strbuf, "%s %d %s %d.",
  380.                 daynames[current.tm_wday], current.tm_mday,
  381.                 monthnames[current.tm_mon], current.tm_year+1900);
  382.         else
  383.             sprintf(strbuf, "%s %s %d, %d",
  384.                 daynames[current.tm_wday], monthnames[current.tm_mon],
  385.                 current.tm_mday, current.tm_year+1900);
  386.         current = Save;
  387.     }
  388.     return (strbuf);
  389. }
  390.  
  391. #ifndef NO_PRINTER
  392. /*
  393.  * Print to Postscript compatable printer.  If we are displaying
  394.  * the year page, then create a raster file of the canvas and
  395.  * feed it to a raster->ps filter (sun2ps).  If on any other page,
  396.  * then print a pretty PostScript calendar with appts written in
  397.  * (as best can be).
  398.  */
  399. print_calendar(file_type)
  400. int file_type;
  401. {
  402.     char prntcmd[64];
  403.     FILE *fp, *pfp;
  404.     struct tm Save;
  405.     int target;
  406.  
  407.     lock_cursors();
  408.     working(TRUE);
  409. #ifndef RASTER_ONLY
  410.     if (file_type == PR_POSTSCRIPT) {
  411.         if ((pfp = fopen(psfile, "w")) == NULL) {
  412.             err_rpt("can't open tmp ps file", NON_FATAL);
  413.             return;
  414.         }
  415.         switch (mainsw_state) {
  416.             case DISPLAYING_DAY:
  417.                 print_psday(pfp, FALSE);
  418.                 break;
  419.             case DISPLAYING_WEEK:
  420.                 /* start printing on first dow */
  421.                 Save = current;
  422.                 if (nr_weekdays == 7 && !monday_first)
  423.                     target = SUN;
  424.                 else
  425.                     target = MON;
  426.                 if (current.tm_wday >= target)
  427.                     while (current.tm_wday-- > target)
  428.                         current.tm_mday--;
  429.                 else
  430.                     /* looking at Sun */
  431.                     current.tm_mday++;
  432.                 fix_current_day();
  433.                 print_psweek(pfp, FALSE);
  434.                 current = Save;
  435.                 break;
  436.             case DISPLAYING_MONTH:
  437.                 print_psmonth(pfp, TRUE);
  438.                 break;
  439.             case DISPLAYING_YEAR:
  440.                 if (dorasfile()) {
  441.                     fp = fopen(rasfile, "r");
  442.                     /* ras2ps closes the files that
  443.                      * we opened here.
  444.                      */
  445.                     ras2ps(fp, pfp);
  446.                 }
  447.                 break;
  448.         }
  449.         fclose(pfp);
  450.         if (!print_to_file) {
  451.             sprintf(prntcmd, "%s %s", printer, psfile);
  452.             system(prntcmd);
  453.             unlink(psfile);
  454.         }
  455.     } else {
  456. #else
  457.     {
  458. #endif /* RASTER_ONLY */
  459.         if (dorasfile() && !print_to_file) {
  460.             sprintf(prntcmd, "%s -v %s", printer, rasfile);
  461.             system(prntcmd);
  462.             unlink(rasfile);
  463.         }
  464.     }
  465.     working(FALSE);
  466.     unlock_cursors();
  467. }
  468.  
  469. /*
  470.  * convert screen display to sun raster format
  471.  */
  472. dorasfile()
  473. {
  474.     Pixrect *save_pr;
  475.     int type = RT_STANDARD;
  476.     int copy_flag = TRUE;
  477.     Rect *rect;
  478.     struct pr_prpos where;
  479.     char buf[128], *cuserid();
  480.     FILE *fp;
  481.  
  482.     sprintf(buf, "Appointments file \"%s\" printed for %s on %s",
  483.         apts_pathname, cuserid(NULL), clockstr);
  484.  
  485.     if ((fp = fopen(rasfile, "w")) != NULL) {
  486.         rect = (Rect *) window_get(canvas, WIN_RECT);
  487.         save_pr = mem_create(rect->r_width, rect->r_height+3*sfont->pf_defaultsize.y, 1);
  488.         pr_rop(save_pr,0,0,rect->r_width-3,rect->r_height,PIX_SRC,main_pixwin->pw_prretained,0,0);
  489.         where.pr = save_pr;
  490.         where.pos.x = 6 * font->pf_defaultsize.x;
  491.         where.pos.y = rect->r_height + 2*sfont->pf_defaultsize.y;
  492.         pf_text(where, PIX_SRC, sfont, buf);
  493.         pr_dump(save_pr, fp, NULL, type, copy_flag);
  494.         fclose(fp);
  495.         pr_destroy(save_pr);
  496.         return (1);
  497.     } else {
  498.         err_rpt("can't open tmp raster file", NON_FATAL);
  499.         return (0);
  500.     }
  501. }
  502. #endif    /* NO_PRINTER */
  503.