"Fossies" - the Fresh Open Source Software Archive

Member "jpilot-2_0_1/print.c" (3 Apr 2021, 40224 Bytes) of package /linux/privat/jpilot-2_0_1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*******************************************************************************
    2  * print.c
    3  * A module of J-Pilot http://jpilot.org
    4  *
    5  * Copyright (C) 2000-2014 by Judd Montgomery
    6  *
    7  * This program is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; version 2 of the License.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  ******************************************************************************/
   20 
   21 /********************************* Includes ***********************************/
   22 #include "config.h"
   23 #include <stdlib.h>
   24 #include <stdio.h>
   25 #include <string.h>
   26 #include <time.h>
   27 #include <ctype.h>
   28 
   29 #include "print.h"
   30 #include "print_headers.h"
   31 #include "print_logo.h"
   32 #include "datebook.h"
   33 #include "calendar.h"
   34 #include "address.h"
   35 #include "todo.h"
   36 #include "sync.h"
   37 #include "prefs.h"
   38 #include "log.h"
   39 #include "i18n.h"
   40 #ifdef HAVE_LOCALE_H
   41 #  include <locale.h>
   42 #endif
   43 
   44 /********************************* Constants **********************************/
   45 #ifdef JPILOT_PRINTABLE
   46 #  define FLAG_CHAR 'A'
   47 #  define Q_FLAG_CHAR "A"
   48 #else
   49 #  define FLAG_CHAR 010
   50 #  define Q_FLAG_CHAR "\\010"
   51 #endif
   52 
   53 /******************************* Global vars **********************************/
   54 static FILE *out;
   55 static int first_hour, first_min, last_hour, last_min;
   56 extern int datebk_category;
   57 
   58 static const char *PaperSizes[] = { 
   59    "Letter", "Legal", "Statement", "Tabloid", "Ledger", "Folio", "Quarto",
   60    "7x9", "9x11", "9x12", "10x13", "10x14", "Executive", 
   61    "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10",
   62    "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", 
   63    "ISOB0", "ISOB1", "ISOB2", "ISOB3", "ISOB4", "ISOB5", "ISOB6", "ISOB7", 
   64    "ISOB8", "ISOB9", "ISOB10", 
   65    "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "DL", "Filo"
   66 };
   67 
   68 /****************************** Prototypes ************************************/
   69 static int fill_in(struct tm *date, CalendarEventList *a_list);
   70 static void ps_strncat(char *dest, const char *src, int n);
   71 
   72 /****************************** Main Code *************************************/
   73 static FILE *print_open(void)
   74 {
   75    const char *command;
   76 
   77    get_pref(PREF_PRINT_COMMAND, NULL, &command);
   78    if (command) {
   79       return popen(command, "w");
   80    } else {
   81       return NULL;
   82    }
   83 }
   84 
   85 static void print_close(FILE *f)
   86 {
   87    pclose(f);
   88 }
   89 
   90 static int courier_12(void)
   91 {
   92    /* fprintf(out, "/Courier 12 selectfont\n"); */
   93    fprintf(out, "%cC12\n", FLAG_CHAR);
   94    return EXIT_SUCCESS;
   95 }
   96 
   97 static int courier_bold_12(void)
   98 {
   99    /* fprintf(out, "/Courier-Bold 12 selectfont\n"); */
  100    fprintf(out, "%cCB12\n", FLAG_CHAR);
  101    return EXIT_SUCCESS;
  102 }
  103 
  104 static int clip_to_box(float x1, float y1, float x2, float y2)
  105 {
  106    fprintf(out, "%g inch %g inch %g inch %g inch rectclip\n",
  107                  x1,     y1,     x2-x1,  y2-y1);
  108    return EXIT_SUCCESS;
  109 }
  110 
  111 static int puttext(float x, float y, const char *text)
  112 {
  113    int len;
  114    char *buf;
  115 
  116    len = strlen(text);
  117    buf = malloc(2 * len + 1);
  118    memset(buf, 0, 2 * len + 1);
  119    ps_strncat(buf, text, 2 * len);
  120    fprintf(out, "%g inch %g inch moveto (%s) show\n", x, y, buf);
  121    free(buf);
  122    return EXIT_SUCCESS;
  123 }
  124 
  125 static int header(void)
  126 {
  127    time_t ltime;
  128 
  129    time(&ltime);
  130    fprintf(out,
  131            "%%!PS-Adobe-2.0\n"
  132            "%%%%Creator: J-Pilot\n"
  133            "%%%%CreationDate: %s"
  134            "%%%%DocumentData: Clean7Bit\n"
  135            "%%%%Orientation: Portrait\n"
  136            "%%DocumentFonts: Times-Roman Times-Bold Courier Courier-Bold\n"
  137            "%%%%Magnification: 1.0000\n"
  138            "%%%%Pages: 1\n"
  139            "%%%%EndComments\n"
  140            "%%%%BeginProlog\n"
  141            ,ctime(&ltime));
  142    fprintf(out, "/PageSize (%s) def\n\n", PaperSizes[PAPER_Letter]);
  143    print_common_prolog(out);
  144    fprintf(out,
  145            "%%%%EndProlog\n"
  146            "%%%%BeginSetup\n");
  147    print_common_setup(out);
  148    fprintf(out, "595 612 div 842 792 div Min dup scale %% HACK!!!! (CMB)\n");
  149            /* This hack pre-scales to compensate for the standard scaling
  150               mechanism below, to avoid me having to redo the layout of
  151               the dayview for the A4 standard size page. */
  152    fprintf(out,
  153            "%%%%EndSetup\n"
  154            "%%%%Page: 1 1\n\n");
  155 
  156    return EXIT_SUCCESS;
  157 }
  158 
  159 static int print_dayview(struct tm *date, CalendarEventList *ce_list)
  160 {
  161    char str[80];
  162    char datef[80];
  163    time_t ltime;
  164    struct tm *now;
  165    const char *svalue;
  166 
  167 #ifdef HAVE_LOCALE_H
  168    char *current_locale;
  169    current_locale = setlocale(LC_NUMERIC,"C");
  170 #endif
  171 
  172    header();
  173    /* Draw the 2 gray columns and header block */
  174    print_day_header(out);
  175 
  176    /* Put the month name up */
  177    fprintf(out, "/Times-Bold-ISOLatin1 findfont 20 scalefont setfont\n"
  178                 "newpath 0 setgray\n");
  179    get_pref(PREF_LONGDATE, NULL, &svalue);
  180    strftime(str, sizeof(str), _(svalue), date);
  181    puttext(0.5, 10.25, str);
  182 
  183    /* Put the weekday name up */
  184    fprintf(out, "/Times-Roman-ISOLatin1 findfont 15 scalefont setfont\n");
  185    strftime(str, sizeof(str), "%A", date);
  186    puttext(0.5, 10, str);
  187 
  188    /* Put the time of printing up */
  189    fprintf(out, "newpath\n"
  190                 "/Times-Roman-ISOLatin1 findfont 10 scalefont setfont\n");
  191 
  192    time(&ltime);
  193    now = localtime(&ltime);
  194    get_pref(PREF_SHORTDATE, NULL, &svalue);
  195    g_snprintf(datef, sizeof(datef), "%s %s", "Printed on: ", svalue);
  196    strftime(str, sizeof(str), datef, now);
  197    puttext(0.5, 0.9, str);
  198    puttext(7.5, 0.9, "J-Pilot");
  199    fprintf(out, "stroke\n");
  200 
  201    print_logo(out, 40, 90, 0.35);
  202 
  203    /* Put the appointments on the dayview calendar */
  204    fill_in(date, ce_list);
  205 
  206    fprintf(out, "showpage\n");
  207    fprintf(out, "%%%%EOF\n");
  208 
  209 #ifdef HAVE_LOCALE_H
  210    setlocale(LC_ALL, current_locale);
  211 #endif
  212 
  213    return EXIT_SUCCESS;
  214 }
  215 
  216 static int fill_in(struct tm *date, CalendarEventList *ce_list)
  217 {
  218    CalendarEventList *temp_cel;
  219    int i;
  220    int hours[24];
  221    int defaults1=0, defaults2=0;
  222    int hour24;
  223    int am;
  224    float top_y=9.40;
  225    float default_y=3.40;
  226    float indent1=1.25;
  227    float indent2=5.00;
  228    float step=0.12; /* This is the space between lines */
  229    float x,y;
  230    int max_per_line=4;
  231    char str[256];
  232    char datef[32];
  233 
  234    for (i=0; i<24; i++) {
  235       hours[i]=0;
  236    }
  237 
  238    /* We have to go through them twice, once for AM, and once for PM
  239     * This is because of the clipping */
  240    for (i=0; i<2; i++) {
  241       am=i%2;
  242       fprintf(out, "gsave\n");
  243       if (am) {
  244          clip_to_box(1.25, 0.5, 4.25, 9.5);
  245       } else {
  246          clip_to_box(5.0, 0.5, 8.0, 9.5);
  247       }
  248       for (temp_cel = ce_list; temp_cel; temp_cel=temp_cel->next) {
  249          if (temp_cel->mcale.cale.description == NULL) {
  250             continue;
  251          }
  252          if (temp_cel->mcale.cale.event) {
  253             strcpy(str, " ");
  254             if (!am) {
  255                continue;
  256             }
  257             x=indent1;
  258             y=default_y - defaults1 * step;
  259             defaults1++;
  260          } else {
  261             hour24 = temp_cel->mcale.cale.begin.tm_hour;
  262             if ((hour24 > 11) && (am)) {
  263                continue;
  264             }
  265             if ((hour24 < 12) && (!am)) {
  266                continue;
  267             }
  268 
  269             get_pref_time_no_secs(datef);
  270             strftime(str, sizeof(str), datef, &temp_cel->mcale.cale.begin);
  271 
  272             if (hour24 > 11) {
  273                x=indent2;
  274                y=top_y - (hour24 - 12) * 0.5 - (hours[hour24]) * step;
  275                hours[hour24]++;
  276                if (hours[hour24] > max_per_line) {
  277                   y=default_y - defaults2 * step;
  278                   defaults2++;
  279                }
  280             } else {
  281                x=indent1;
  282                y=top_y - (hour24) * 0.5 - (hours[hour24]) * step;
  283                hours[hour24]++;
  284                if (hours[hour24] > max_per_line) {
  285                   y=default_y - defaults1 * step;
  286                   defaults1++;
  287                }
  288             }
  289          }
  290          if (temp_cel->mcale.cale.description) {
  291             strcat(str, " ");
  292             strncat(str, temp_cel->mcale.cale.description, sizeof(str)-strlen(str)-2);
  293             str[128]='\0';
  294             /* FIXME: Add location in parentheses (loc) as the Palm does.
  295              * We would need to check strlen, etc., before adding */
  296          }
  297          if (y > 1.0) {
  298             puttext(x, y, str);
  299          } else {
  300             jp_logf(JP_LOG_WARN, "Too many appointments, dropping one\n");
  301          }
  302       }
  303       fprintf(out, "grestore\n");
  304    }
  305 
  306    return EXIT_SUCCESS;
  307 }
  308 
  309 int print_days_appts(struct tm *date)
  310 {
  311    CalendarEventList *ce_list;
  312 
  313    out = print_open();
  314    if (!out) {
  315       return EXIT_FAILURE;
  316    }
  317 
  318    ce_list = NULL;
  319 
  320    get_days_calendar_events2(&ce_list, date, 2, 2, 2, CATEGORY_ALL, NULL);
  321 
  322    print_dayview(date, ce_list);
  323 
  324    print_close(out);
  325 
  326    free_CalendarEventList(&ce_list);
  327 
  328    return EXIT_SUCCESS;
  329 }
  330 
  331 static int f_indent_print(FILE *f, int indent, char *str) {
  332    char *P;
  333    int i, col;
  334 
  335    col=indent;
  336    for (P=str; *P; P++) {
  337       col++;
  338       if ((*P==10) || (*P==13)) {
  339          fprintf(f, "%c", *P);
  340          for (i=indent; i; i--) {
  341             fprintf(f, " ");
  342          }
  343          col=indent;
  344          continue;
  345       }
  346       if (col>75) {
  347          fprintf(f, "\n");
  348          for (i=indent; i; i--) {
  349             fprintf(f, " ");
  350          }
  351          col=indent+1;
  352       }
  353       fprintf(f, "%c", *P);
  354    }
  355    return EXIT_SUCCESS;
  356 }
  357 
  358 /*----------------------------------------------------------------------
  359  * ps_strncat   Escapes brackets for printing in PostScript strings
  360  *----------------------------------------------------------------------*/
  361 
  362 void ps_strncat(char *dest, const char *src, int n)
  363 {
  364    int i = 0, j = 0;
  365    char *dest2;
  366    dest2 = strchr(dest, '\0');
  367    while (j < n) {
  368       if (src[i] == '\0') {
  369          dest2[j]='\0';
  370          break;
  371       }
  372       if (strchr("()", src[i]) != NULL) {
  373          if(j<n-1) dest2[j] = '\\'; else dest2[j]=' ';
  374          j++;
  375       }
  376       dest2[j] = src[i];
  377       i++;
  378       j++;
  379    }
  380 }
  381 
  382 /*----------------------------------------------------------------------
  383  * days_in_mon  Returns the number of days in the month containing the
  384  *              date passed in.
  385  *----------------------------------------------------------------------*/
  386 
  387 static int days_in_mon(struct tm *date)
  388 {
  389    int days_in_month[]={ 31,28,31,30,31,30,31,31,30,31,30,31 };
  390 
  391    if ((date->tm_year%4 == 0) &&
  392        !(((date->tm_year+1900)%100==0) && ((date->tm_year+1900)%400!=0))) {
  393        days_in_month[1]++;
  394    }
  395    return(days_in_month[date->tm_mon]);
  396 }
  397 
  398 /*----------------------------------------------------------------------
  399  * print_months_appts   Function to print the current month's
  400  *                      appointments.
  401  *----------------------------------------------------------------------*/
  402 
  403 static const char *MonthNames[] = {
  404    "January", "February", "March", "April", "May", "June", "July",
  405    "August", "September", "October", "November", "December"
  406 };
  407 
  408 int print_months_appts(struct tm *date_in, PaperSize paper_size)
  409 {
  410    CalendarEventList *ce_list;
  411    CalendarEventList *temp_cel;
  412    struct tm date;
  413    char desc[100];
  414    time_t ltime;
  415    int dow;
  416    int ndim;
  417    int n;
  418    long fdow;
  419    int mask;
  420 #ifdef ENABLE_DATEBK
  421    int cat_bit;
  422    int db3_type;
  423    long use_db3_tags;
  424    struct db4_struct db4;
  425 #endif
  426 #ifdef HAVE_LOCALE_H
  427    char *current_locale;
  428 #endif
  429 
  430    /*------------------------------------------------------------------
  431     * Set up the PostScript output file, and print the header to it.
  432     *------------------------------------------------------------------*/
  433    mask=0;
  434 
  435    time(&ltime);
  436 
  437 #ifdef ENABLE_DATEBK
  438    get_pref(PREF_USE_DB3, &use_db3_tags, NULL);
  439 #endif
  440 
  441 #ifdef HAVE_LOCALE_H
  442    current_locale = setlocale(LC_NUMERIC,"C");
  443 #endif
  444    if (! (out = print_open())) return(EXIT_FAILURE);
  445 
  446    fprintf(out,
  447            "%%!PS-Adobe-2.0\n"
  448            "%%%%Creator: J-Pilot\n"
  449            "%%%%CreationDate: %s"
  450            "%%%%DocumentData: Clean7Bit\n"
  451            "%%%%Orientation: Landscape\n\n"
  452            "%%DocumentFonts: Times-Roman Times-Bold Courier Courier-Bold\n"
  453            "%%%%Magnification: 1.0000\n"
  454            "%%%%Pages: 1\n"
  455            "%%%%EndComments\n"
  456            "%%%%BeginProlog\n"
  457            ,ctime(&ltime));
  458    fprintf(out, "/PageSize (%s) def\n\n", PaperSizes[paper_size]);
  459    print_common_prolog(out);
  460    fprintf(out,
  461            "%%%%EndProlog\n"
  462            "%%%%BeginSetup\n");
  463    print_common_setup(out);
  464    print_month_header(out);
  465    fprintf(out,
  466            "%%%%EndSetup\n"
  467            "%%%%Page: 1 1\n\n");
  468 
  469    /*------------------------------------------------------------------
  470     * Extract the appointments
  471     *------------------------------------------------------------------*/
  472    ce_list = NULL;
  473    memcpy(&date, date_in, sizeof(struct tm));
  474    /* Get all of the appointments */
  475 
  476    get_days_calendar_events2(&ce_list, NULL, 2, 2, 2, CATEGORY_ALL, NULL);
  477    get_month_info(date.tm_mon, 1, date.tm_year, &dow, &ndim);
  478    weed_calendar_event_list(&ce_list, date.tm_mon, date.tm_year, 0, &mask);
  479 
  480    /*------------------------------------------------------------------
  481     * Loop through the days in the month, printing appointments
  482     *------------------------------------------------------------------*/
  483    date.tm_mday=1;
  484    date.tm_sec=0;
  485    date.tm_min=0;
  486    date.tm_hour=11;
  487    date.tm_isdst=-1;
  488    mktime(&date);
  489 
  490    get_pref(PREF_FDOW, &fdow, NULL);
  491 
  492    fprintf(out,
  493            "(%s %d) %d (%s) (%s version %s) %ld InitialisePage\n\n",
  494            MonthNames[date_in->tm_mon], date_in->tm_year + 1900,
  495            date.tm_wday,
  496            ctime(&ltime),
  497            PN, VERSION, fdow);
  498 
  499    for (n=0, date.tm_mday=1; date.tm_mday<=ndim; date.tm_mday++, n++) {
  500       date.tm_sec=0;
  501       date.tm_min=0;
  502       date.tm_hour=11;
  503       date.tm_isdst=-1;
  504       date.tm_wday=0;
  505       date.tm_yday=1;
  506       mktime(&date);
  507 
  508       fprintf(out, "%%--------------------------------------------------\n"
  509               "%%Stuff for day %2d being printed\n", date.tm_mday);
  510       fprintf(out, "NextDay\n");
  511 
  512       for (temp_cel = ce_list; temp_cel; temp_cel=temp_cel->next) {
  513 #ifdef ENABLE_DATEBK
  514          if (use_db3_tags) {
  515             db3_parse_tag(temp_cel->mcale.cale.note, &db3_type, &db4);
  516             /* jp_logf(JP_LOG_DEBUG, "category = 0x%x\n", db4.category); */
  517             cat_bit=1<<db4.category;
  518             if (!(cat_bit & datebk_category)) {
  519                jp_logf(JP_LOG_DEBUG, "skipping rec not in this category\n");
  520                continue;
  521             }
  522          }
  523 #endif
  524          if (calendar_isApptOnDate(&(temp_cel->mcale.cale), &date)) {
  525             char tmp[20];
  526             char datef1[20];
  527             char datef2[20];
  528             tmp[0]='\0';
  529             if ( ! temp_cel->mcale.cale.event) {
  530                get_pref_time_no_secs(datef1);
  531                g_snprintf(datef2, sizeof(datef2), "(%s )", datef1);
  532                strftime(tmp, sizeof(tmp), datef2, &(temp_cel->mcale.cale.begin));
  533                tmp[19]='\0';
  534             }
  535             desc[0]='\0';
  536             if (temp_cel->mcale.cale.description) {
  537                ps_strncat(desc, temp_cel->mcale.cale.description, 100);
  538                desc[sizeof(desc)-1]='\0';
  539                /* FIXME: Add location in parentheses (loc) as the Palm does.
  540                 * We would need to check strlen, etc., before adding */
  541             }
  542             remove_cr_lfs(desc);
  543             fprintf(out, "%s (%s) %simedItem\n", tmp, desc,
  544                     (strlen(tmp) == 0) ? "Unt" : "T" );
  545          }
  546       }
  547    }
  548 
  549    /*------------------------------------------------------------------*/
  550    memcpy(&date, date_in, sizeof(struct tm));
  551    date.tm_mday = 1;    /* Go to the first of the month */
  552    mktime(&date);
  553    sub_months_from_date(&date, 1);
  554    strftime(desc, sizeof(desc), "(%B %Y) %w ", &date);
  555    fprintf(out, "\n\n%%----------------------------------------\n"
  556            "%% Now generate the small months\n\n"
  557            "%s %d ", desc, days_in_mon(&date));
  558 
  559    add_months_to_date(&date, 2);
  560    strftime(desc, sizeof(desc), "(%B %Y) %w ", &date);
  561    fprintf(out, "%s %d SmallMonths\n", desc, days_in_mon(&date));
  562 
  563    /*------------------------------------------------------------------*/
  564 
  565    free_CalendarEventList(&ce_list);
  566 
  567    fprintf(out, "grestore\n");
  568    print_logo(out, 20, 30, 0.35);
  569    fprintf(out, "\nshowpage\n");
  570    fprintf(out, "%%%%EOF\n");
  571 
  572    print_close(out);
  573 
  574 #ifdef HAVE_LOCALE_H
  575    setlocale(LC_NUMERIC, current_locale);
  576 #endif
  577    return EXIT_SUCCESS;
  578 }
  579 
  580 /*----------------------------------------------------------------------
  581  * reset_first_last     Routine to reset max/min appointment times
  582  *----------------------------------------------------------------------*/
  583 
  584 static void reset_first_last(void)
  585 {
  586    first_hour = 25;
  587    first_min  = 61;
  588    last_hour  = -1;
  589    last_min   = -1;
  590 }
  591 
  592 /*----------------------------------------------------------------------
  593  * check_first_last     Routine to track max/min appointment times
  594  *----------------------------------------------------------------------*/
  595 
  596 static void check_first_last(CalendarEventList *cel)
  597 {
  598    struct tm *ApptTime;
  599    ApptTime = &(cel->mcale.cale.begin);
  600    if (ApptTime->tm_hour == first_hour) {
  601       if (ApptTime->tm_min < first_min) first_min = ApptTime->tm_min;
  602    }
  603    else if (ApptTime->tm_hour < first_hour) {
  604       first_hour = ApptTime->tm_hour;
  605       first_min  = ApptTime->tm_min;
  606    }
  607 
  608    ApptTime = &(cel->mcale.cale.end);
  609    if (ApptTime->tm_hour == last_hour) {
  610       if (ApptTime->tm_min > last_min) last_min = ApptTime->tm_min;
  611    } else if (ApptTime->tm_hour > last_hour) {
  612       last_hour = ApptTime->tm_hour;
  613       last_min  = ApptTime->tm_min;
  614    }
  615 }
  616 
  617 /*----------------------------------------------------------------------
  618  * print_weeks_appts    Function to print a weeks appointments onto a
  619  *                      weekly plan. We assume that date_in is the chosen
  620  *                      first day of the week.
  621  *----------------------------------------------------------------------*/
  622 
  623 int print_weeks_appts(struct tm *date_in, PaperSize paper_size)
  624 {
  625    CalendarEventList *ce_list, *temp_cel;
  626    struct tm date;
  627    struct tm *today_date;
  628    char desc[256], short_date[32];
  629    int n;
  630    time_t ltime;
  631 #ifdef ENABLE_DATEBK
  632    int cat_bit;
  633    int db3_type;
  634    long use_db3_tags;
  635    struct db4_struct db4;
  636 #endif
  637 #ifdef HAVE_LOCALE_H
  638    char *current_locale;
  639 #endif
  640 
  641 #ifdef ENABLE_DATEBK
  642    get_pref(PREF_USE_DB3, &use_db3_tags, NULL);
  643 #endif
  644 #ifdef HAVE_LOCALE_H
  645    current_locale = setlocale(LC_NUMERIC,"C");
  646 #endif
  647 
  648    /*------------------------------------------------------------------
  649     * Set up the PostScript output file, and print the header to it.
  650     *------------------------------------------------------------------*/
  651    if (! (out = print_open())) return(EXIT_FAILURE);
  652 
  653    time(&ltime);
  654    fprintf(out,
  655            "%%!PS-Adobe-2.0\n"
  656            "%%%%Creator: J-Pilot\n"
  657            "%%%%CreationDate: %s"
  658            "%%%%DocumentData: Clean7Bit\n"
  659            "%%%%Orientation: Landscape\n"
  660            "%%DocumentFonts: Times-Roman Times-Bold Courier Courier-Bold\n"
  661            "%%%%Magnification: 1.0000\n"
  662            "%%%%Pages: 1\n"
  663            "%%%%EndComments\n"
  664            "%%%%BeginProlog\n"
  665            ,ctime(&ltime));
  666    /*------------------------------------------------------------------
  667     * These are preferences for page size (passed in), first and last
  668     * hours on the plan (default; scales if earlier or later are present),
  669     * and whether to print dashes across the page.
  670     *------------------------------------------------------------------*/
  671    fprintf(out, "/PageSize (%s) def\n\n", PaperSizes[paper_size]);
  672    fprintf(out, "/FirstHour  9 def\n"
  673                 "/LastHour  22 def\n");
  674    fprintf(out, "/Dashes true def\n");
  675    print_common_prolog(out);
  676    fprintf(out,
  677            "%%%%EndProlog\n"
  678            "%%%%BeginSetup\n");
  679    print_common_setup(out);
  680    print_week_header(out);
  681    fprintf(out,
  682            "%%%%EndSetup\n"
  683            "%%%%Page: 1 1\n\n");
  684 
  685    /*------------------------------------------------------------------
  686     * Run through the appointments, looking for earliest and latest
  687     *------------------------------------------------------------------*/
  688    ce_list = NULL;
  689    get_days_calendar_events2(&ce_list, NULL, 2, 2, 2, CATEGORY_ALL, NULL);
  690    reset_first_last();
  691 
  692    memcpy(&date, date_in, sizeof(struct tm));
  693    for (n = 0; n < 7; n++, add_days_to_date(&date, 1)) {
  694       for (temp_cel = ce_list; temp_cel; temp_cel=temp_cel->next) {
  695 #ifdef ENABLE_DATEBK
  696          if (use_db3_tags) {
  697             db3_parse_tag(temp_cel->mcale.cale.note, &db3_type, &db4);
  698             cat_bit=1<<db4.category;
  699             if (!(cat_bit & datebk_category)) continue;
  700          }
  701 #endif
  702          if (calendar_isApptOnDate(&(temp_cel->mcale.cale), &date))
  703             if (! temp_cel->mcale.cale.event)
  704                check_first_last(temp_cel);
  705       }
  706    }
  707    if (last_min > 0) last_hour++;
  708 
  709    /*------------------------------------------------------------------
  710     * Now put in the finishing touches to the header, and kick-start
  711     * the printing process
  712     *------------------------------------------------------------------*/
  713 
  714    today_date = localtime(&ltime);
  715    fprintf(out,
  716            "%%------------------------------------------------------------\n"
  717            "%% This is today's date, the date of printing, plus the hour\n"
  718            "%% before & after the first and last appointments, respectively\n"
  719            "%d %d %d %d %d startprinting\n\n",
  720            today_date->tm_mday, today_date->tm_mon + 1,
  721            today_date->tm_year + 1900, first_hour, last_hour);
  722    fprintf(out, "( by %s version %s) show\n", PN, VERSION);
  723 
  724    print_logo(out, 20, 30, 0.35);
  725 
  726    /*------------------------------------------------------------------
  727     * Run through the appointments, printing them out
  728     *------------------------------------------------------------------*/
  729    free_CalendarEventList(&ce_list);
  730    ce_list = NULL;
  731 
  732    /* Get all of the appointments */
  733    get_days_calendar_events2(&ce_list, NULL, 2, 2, 2, CATEGORY_ALL, NULL);
  734 
  735    /* iterate through seven days */
  736    memcpy(&date, date_in, sizeof(struct tm));
  737 
  738    for (n = 0; n < 7; n++, add_days_to_date(&date, 1)) {
  739       strftime(short_date, sizeof(short_date), "%a, %d %b, %Y", &date);
  740       fprintf(out, "%d startday\n(%s) dateline\n", n, short_date);
  741 
  742       for (temp_cel = ce_list; temp_cel; temp_cel=temp_cel->next) {
  743 #ifdef ENABLE_DATEBK
  744          if (use_db3_tags) {
  745             db3_parse_tag(temp_cel->mcale.cale.note, &db3_type, &db4);
  746             jp_logf(JP_LOG_DEBUG, "category = 0x%x\n", db4.category);
  747             cat_bit=1<<db4.category;
  748             if (!(cat_bit & datebk_category)) {
  749                jp_logf(JP_LOG_DEBUG, "skip rec not in this category\n");
  750                continue;
  751             }
  752          }
  753 #endif
  754          if (calendar_isApptOnDate(&(temp_cel->mcale.cale), &date)) {
  755             memset(desc, 0, sizeof(desc));
  756             memset(short_date, 0, sizeof(short_date));
  757 
  758             if ( ! temp_cel->mcale.cale.event)
  759               {
  760                  char t1[6], t2[6], ht[3], mt[3];
  761                  int j, m;
  762 
  763                  strftime(ht, sizeof(ht), "%H", &(temp_cel->mcale.cale.begin));
  764                  strftime(mt, sizeof(mt), "%M", &(temp_cel->mcale.cale.begin));
  765                  m = atoi(mt);
  766                  snprintf(t1, sizeof(t1), "%s.%02d", ht, (int)((m * 100.)/60));
  767 
  768                  strftime(ht, sizeof(ht), "%H", &(temp_cel->mcale.cale.end));
  769                  strftime(mt, sizeof(mt), "%M", &(temp_cel->mcale.cale.end));
  770                  m = atoi(mt);
  771                  snprintf(t2, sizeof(t2), "%s.%02d", ht, (int)((m * 100.)/60));
  772                  sprintf(short_date, "%s %s ", t1, t2);
  773                  for (j=0; j<30;j++) short_date[j] =tolower(short_date[j]);
  774               }
  775             if (temp_cel->mcale.cale.description) {
  776                ps_strncat(desc, temp_cel->mcale.cale.description, 250);
  777                /* FIXME: Add location in parentheses (loc) as the Palm does.
  778                 * We would need to check strlen, etc., before adding */
  779                remove_cr_lfs(desc);
  780             }
  781             fprintf(out, "%s (%s) itemline\n", short_date, desc);
  782          }
  783       }
  784    }
  785    free_CalendarEventList(&ce_list);
  786    fprintf(out, "\nfinishprinting\n");
  787    fprintf(out, "%%%%EOF\n");
  788    print_close(out);
  789 
  790 #ifdef HAVE_LOCALE_H
  791    setlocale(LC_ALL, current_locale);
  792 #endif
  793    return EXIT_SUCCESS;
  794 }
  795 
  796 /*
  797  * Address code
  798  */
  799 
  800 static int print_address_header(void)
  801 {
  802    time_t ltime;
  803    struct tm *date;
  804    const char *svalue;
  805    char str[256];
  806 
  807    time(&ltime);
  808    date = localtime(&ltime);
  809 
  810    get_pref(PREF_SHORTDATE, NULL, &svalue);
  811    strftime(str, sizeof(str), svalue, date);
  812 
  813    fprintf(out,
  814            "%%!PS-Adobe-2.0\n"
  815            "%%%%Creator: J-Pilot\n"
  816            "%%%%CreationDate: %s"
  817            "%%%%DocumentData: Clean7Bit\n"
  818            /* XXX Title */
  819            "%%%%Orientation: Portrait\n"
  820            /* XXX BoundingBox */
  821            "%%DocumentFonts: Times-Roman Times-Bold "
  822            "Courier Courier-Bold ZapfDingbats\n"
  823            "%%%%Magnification: 1.0000\n"
  824            "%%%%BoundingBox: 36 36 576 756\n"
  825            "%%%%EndComments\n",
  826            ctime(&ltime));
  827    fprintf(out,
  828            "%%%%BeginProlog\n"
  829            "%%%%BeginResource: procset\n"
  830            "/inch {72 mul} def\n"
  831            "/left {0.5 inch} def\n"
  832            "/bottom {1.0 inch} def\n"
  833            "/bottom_hline {2.0 inch} def\n"
  834            "/footer {0.9 inch} def\n"
  835            "/top {10.5 inch 14 sub} def\n"
  836            "/buffer 1024 string def\n"
  837            "/scratch 128 string def\n"
  838            "/printobject {\n"
  839            "dup 128 string cvs dup (--nostringval--) eq {\n"
  840            "pop type24 string cvs\n"
  841            "}{\n"
  842            "exch pop\n"
  843            "} ifelse\n"
  844            "} bind def\n");
  845    /* Checkbox stuff */
  846    fprintf(out,
  847            "/checkboxcheck {\n"
  848            "%%currentpoint 6 add moveto\n"
  849            "%%4 -5 rlineto\n"
  850            "%%6 12 rlineto\n"
  851            "/ZapfDingbats 14 selectfont (4) show\n" /* or 3 if you prefer */
  852            "} bind def\n"
  853            "/checkboxbox {\n"
  854            "8 0 rlineto\n"
  855            "0 8 rlineto\n"
  856            "-8 0 rlineto\n"
  857            "0 -8 rlineto\n"
  858            "} bind def\n"
  859            "/checkbox {\n"
  860            "currentpoint\n"
  861            "gsave\n"
  862            "newpath\n"
  863            "moveto\n"
  864            "1 setlinewidth\n"
  865            "checkboxbox\n"
  866            "stroke\n"
  867            "grestore\n"
  868            "} bind def\n"
  869            "/checkedbox {\n"
  870            "currentpoint\n"
  871            "gsave\n"
  872            "newpath\n"
  873            "moveto\n"
  874            "1 setlinewidth\n"
  875            "checkboxbox\n"
  876            "checkboxcheck\n"
  877            "stroke\n"
  878            "grestore\n"
  879            "} bind def\n"
  880            );
  881 
  882    /* Recode font function */
  883    fprintf(out,
  884            "/Recode {\n"
  885            "exch\n"
  886            "findfont\n"
  887            "dup length dict\n"
  888            "begin\n"
  889            "{ def\n"
  890            "} forall\n"
  891            "/Encoding ISOLatin1Encoding def\n"
  892            "currentdict\n"
  893            "end\n"
  894            "definefont pop\n"
  895            "} bind def\n");
  896    fprintf(out,
  897            "/Times-Roman  /Times-Roman-ISOLatin1 Recode\n"
  898            "/Courier      /Courier-ISOLatin1 Recode\n"
  899            "/Courier-Bold /Courier-Bold-ISOLatin1 Recode\n");
  900    fprintf(out,
  901           "/hline {\n"
  902            "currentpoint 1 add currentpoint 1 add\n"
  903            "currentpoint 4 add currentpoint 4 add\n"
  904            "gsave\n"
  905            "newpath\n"
  906            "moveto\n"
  907            "exch\n"
  908            "1.0 inch add\n"
  909            "exch\n"
  910            "7 setlinewidth\n"
  911            "lineto\n"
  912            "stroke\n"
  913            "%%\n"
  914            "newpath\n"
  915            "moveto\n"
  916            "exch\n"
  917            "7.5 inch add\n"
  918            "exch\n"
  919            "1 setlinewidth\n"
  920            "lineto\n"
  921            "stroke\n"
  922            "grestore\n"
  923            "} bind def\n"
  924            "%%\n"
  925            "%%\n");
  926    fprintf(out,
  927            "/setup\n"
  928            "{\n"
  929            "/Times-Roman-ISOLatin1 10 selectfont\n"
  930            "left footer moveto\n"
  931            "(%s) show\n"
  932            "7.5 inch footer moveto\n"
  933            "(J-Pilot) show\n"
  934            "%% This assumes that the prev page number is on the stack\n"
  935            "4.25 inch footer moveto\n"
  936            "1 add dup printobject show\n"
  937            "/Courier-ISOLatin1 12 selectfont\n"
  938            "left top moveto\n"
  939            "} bind def\n"
  940            "/printit\n"
  941            "{\n"
  942            "{ %%loop\n"
  943            "currentfile buffer readline { %%ifelse\n"
  944            "("Q_FLAG_CHAR"LINEFEED) search { %%if\n"
  945            "pop pop pop showpage setup ( )\n"
  946            "currentpoint 14 add moveto\n"
  947            "} if\n"
  948            "("Q_FLAG_CHAR"HLINE) search { %%if\n"
  949            "currentpoint exch pop bottom_hline le { %%if\n"
  950            "pop pop pop\n"
  951            "showpage setup\n"
  952            "0 0 0\n"
  953            "} if\n"
  954            "hline\n"
  955            "pop pop pop ( )\n"
  956            "} if\n"
  957            "("Q_FLAG_CHAR"END) search { %%if\n"
  958            "   showpage stop\n"
  959            "} if\n"
  960            "("Q_FLAG_CHAR"C12) search {\n"
  961            "/Courier-ISOLatin1 12 selectfont\n"
  962            "currentpoint 14 add moveto\n"
  963            "pop pop pop ( )\n"
  964            "} if\n"
  965            "("Q_FLAG_CHAR"CB12) search {\n"
  966            "/Courier-Bold-ISOLatin1 12 selectfont\n"
  967            "currentpoint 14 add moveto\n"
  968            "pop pop pop ( )\n"
  969            "} if\n",
  970            str
  971            );
  972    /* Check box */
  973    fprintf(out,
  974            "("Q_FLAG_CHAR"CHECKBOX) search {\n"
  975            "currentpoint exch pop bottom_hline le {\n"
  976            "pop pop pop\n"
  977            "showpage setup\n"
  978            "0 0 0\n"
  979            "} if\n"
  980            "checkbox\n"
  981            "currentpoint 14 add moveto\n"
  982            "pop pop pop ( )\n"
  983            "} if\n"
  984            );
  985    /* Check box */
  986    fprintf(out,
  987            "("Q_FLAG_CHAR"CHECKEDBOX) search {\n"
  988            "currentpoint exch pop bottom_hline le {\n"
  989            "pop pop pop\n"
  990            "showpage setup\n"
  991            "0 0 0\n"
  992            "} if\n"
  993            "checkedbox\n"
  994            "currentpoint 14 add moveto\n"
  995            "pop pop pop ( )\n"
  996            "} if\n"
  997            );
  998    fprintf(out,
  999            "%%%%EndResource\n"
 1000            "%%%%EndProlog\n"); /* XXX not exactly sure about position */
 1001 
 1002    fprintf(out,
 1003            "gsave show grestore\n"
 1004            "currentpoint 14 sub moveto\n"
 1005            "currentpoint exch pop bottom le { %%if\n"
 1006            "showpage setup\n"
 1007            "} if\n"
 1008            "}{ %%else\n"
 1009            "showpage exit\n"
 1010            "} ifelse\n"
 1011            "} loop\n"
 1012            "} bind def\n"
 1013            "0 %%The page number minus 1\n"
 1014            "setup printit\n"
 1015            );
 1016    return EXIT_SUCCESS;
 1017 }
 1018 
 1019 
 1020 int print_contacts(ContactList *contact_list, 
 1021                    struct ContactAppInfo *contact_app_info,
 1022                    address_schema_entry *schema, int schema_size)
 1023 {
 1024    long one_rec_per_page;
 1025    long lines_between_recs;
 1026    ContactList *temp_cl;
 1027    MyContact *mcont;
 1028    int show1, show2, show3;
 1029    int i;
 1030    int address_i, phone_i, IM_i;
 1031    char str[100];
 1032    char spaces[24];
 1033    char birthday_str[255];
 1034    const char *pref_date;
 1035    char *utf;
 1036    long char_set;
 1037 #ifdef HAVE_LOCALE_H
 1038    char *current_locale;
 1039 #endif
 1040 
 1041    out = print_open();
 1042    if (!out) {
 1043       return EXIT_FAILURE;
 1044    }
 1045 
 1046 #ifdef HAVE_LOCALE_H
 1047    current_locale = setlocale(LC_NUMERIC,"C");
 1048 #endif
 1049 
 1050    memset(spaces, ' ', sizeof(spaces));
 1051 
 1052    get_pref(PREF_CHAR_SET, &char_set, NULL);
 1053 
 1054    print_address_header();
 1055 
 1056    switch (addr_sort_order) {
 1057     case SORT_BY_LNAME:
 1058     default:
 1059       show1=contLastname;
 1060       show2=contFirstname;
 1061       show3=contCompany;
 1062       break;
 1063     case SORT_BY_FNAME:
 1064       show1=contFirstname;
 1065       show2=contLastname;
 1066       show3=contCompany;
 1067       break;
 1068     case SORT_BY_COMPANY:
 1069       show1=contCompany;
 1070       show2=contLastname;
 1071       show3=contFirstname;
 1072       break;
 1073    }
 1074 
 1075    get_pref(PREF_PRINT_ONE_PER_PAGE, &one_rec_per_page, NULL);
 1076    get_pref(PREF_NUM_BLANK_LINES, &lines_between_recs, NULL);
 1077 
 1078    for (temp_cl = contact_list; temp_cl; temp_cl=temp_cl->next) {
 1079 
 1080       fprintf(out, "%cHLINE\n", FLAG_CHAR);
 1081 
 1082       str[0]='\0';
 1083       if (temp_cl->mcont.cont.entry[show1] || temp_cl->mcont.cont.entry[show2]) {
 1084          if (temp_cl->mcont.cont.entry[show1] && temp_cl->mcont.cont.entry[show2]) {
 1085             g_snprintf(str, sizeof(str), "%s, %s", temp_cl->mcont.cont.entry[show1], temp_cl->mcont.cont.entry[show2]);
 1086          }
 1087          if (temp_cl->mcont.cont.entry[show1] && ! temp_cl->mcont.cont.entry[show2]) {
 1088             strncpy(str, temp_cl->mcont.cont.entry[show1], 48);
 1089          }
 1090          if (! temp_cl->mcont.cont.entry[show1] && temp_cl->mcont.cont.entry[show2]) {
 1091             strncpy(str, temp_cl->mcont.cont.entry[show2], 48);
 1092          }
 1093       } else if (temp_cl->mcont.cont.entry[show3]) {
 1094             strncpy(str, temp_cl->mcont.cont.entry[show3], 48);
 1095       } else {
 1096             strcpy(str, "-Unnamed-");
 1097       }
 1098 
 1099       courier_bold_12();
 1100       fprintf(out, "%s\n", str);
 1101       courier_12();
 1102 
 1103       mcont = &(temp_cl->mcont);
 1104       address_i=phone_i=IM_i=0;
 1105       for (i=0; i<schema_size; i++) {
 1106          /* Get the entry texts */
 1107          if (mcont->cont.entry[schema[i].record_field]) {
 1108             switch (schema[i].type) {
 1109              case ADDRESS_GUI_IM_MENU_TEXT:
 1110                g_snprintf(str, 18, "%s:%s", contact_app_info->IMLabels[mcont->cont.IMLabel[IM_i]], spaces);
 1111                fprintf(out, "%s", str);
 1112                IM_i++;
 1113                break;
 1114              case ADDRESS_GUI_DIAL_SHOW_PHONE_MENU_TEXT:
 1115                g_snprintf(str, 18, "%s:%s", contact_app_info->phoneLabels[mcont->cont.phoneLabel[phone_i]], spaces);
 1116                fprintf(out, "%s", str);
 1117                phone_i++;
 1118                break;
 1119              case ADDRESS_GUI_ADDR_MENU_TEXT:
 1120                g_snprintf(str, 18, "%s:%s", contact_app_info->addrLabels[mcont->cont.addressLabel[address_i]], spaces);
 1121                fprintf(out, "%s", str);
 1122                address_i++;
 1123                break;
 1124              default:
 1125                if (contact_app_info->labels[schema[i].record_field]) {
 1126                   utf = charset_p2newj(contact_app_info->labels[schema[i].record_field], 16, char_set);
 1127                   g_snprintf(str, 18, "%s:%s", utf, spaces);
 1128                   fprintf(out, "%s", str);
 1129                   g_free(utf);
 1130                }
 1131                else {
 1132                   g_snprintf(str, 18, ":%s", spaces);
 1133                   fprintf(out, "%s", str);
 1134                }
 1135             }
 1136             switch (schema[i].type) {
 1137              case ADDRESS_GUI_LABEL_TEXT:
 1138              case ADDRESS_GUI_DIAL_SHOW_PHONE_MENU_TEXT:
 1139              case ADDRESS_GUI_IM_MENU_TEXT:
 1140              case ADDRESS_GUI_ADDR_MENU_TEXT:
 1141              case ADDRESS_GUI_WEBSITE_TEXT:
 1142                f_indent_print(out, 17, mcont->cont.entry[schema[i].record_field]);
 1143                fprintf(out, "\n");
 1144                break;
 1145              case ADDRESS_GUI_BIRTHDAY:
 1146                if (mcont->cont.birthdayFlag) {
 1147                   birthday_str[0]='\0';
 1148                   get_pref(PREF_SHORTDATE, NULL, &pref_date);
 1149                   strftime(birthday_str, sizeof(birthday_str), pref_date, &(mcont->cont.birthday));
 1150                   g_snprintf(str, 18, "%s:%s", contact_app_info->labels[schema[i].record_field] ? contact_app_info->labels[schema[i].record_field] : "",
 1151                              spaces);
 1152                   fprintf(out, "%s", str);
 1153                   f_indent_print(out, 17, birthday_str);
 1154                   fprintf(out, "\n");
 1155                }
 1156                break;
 1157             }
 1158          }
 1159       }
 1160 
 1161       if (one_rec_per_page) {
 1162          fprintf(out, "%cLINEFEED\n", FLAG_CHAR);
 1163       } else {
 1164          for (i=lines_between_recs; i>0; i--) {
 1165             fprintf(out, "\n");
 1166          }
 1167       }
 1168    }
 1169 
 1170    print_close(out);
 1171 
 1172 #ifdef HAVE_LOCALE_H
 1173    setlocale(LC_ALL, current_locale);
 1174 #endif
 1175 
 1176    return EXIT_SUCCESS;
 1177 }
 1178 
 1179 /*
 1180  * ToDo code
 1181  */
 1182 int print_todos(ToDoList *todo_list, char *category_name)
 1183 {
 1184    long one_rec_per_page;
 1185    long lines_between_recs;
 1186    ToDoList *temp_l;
 1187    struct ToDo *todo;
 1188    int indent;
 1189    const char *datef;
 1190    char str[100];
 1191    time_t ltime;
 1192    struct tm *now;
 1193 #ifdef HAVE_LOCALE_H
 1194    char *current_locale;
 1195 #endif
 1196 
 1197    out = print_open();
 1198    if (!out) {
 1199       return EXIT_FAILURE;
 1200    }
 1201 
 1202 #ifdef HAVE_LOCALE_H
 1203    current_locale = setlocale(LC_NUMERIC,"C");
 1204 #endif
 1205 
 1206    fprintf(out, "%%!PS-Adobe-2.0\n\n"
 1207            "/PageSize (%s) def\n\n", PaperSizes[PAPER_Letter]);
 1208    print_common_prolog(out);
 1209    print_common_setup(out);
 1210    fprintf(out, "/CategoryName (%s) def\n", category_name);
 1211    print_todo_header(out);
 1212 
 1213    get_pref(PREF_PRINT_ONE_PER_PAGE, &one_rec_per_page, NULL);
 1214    get_pref(PREF_NUM_BLANK_LINES, &lines_between_recs, NULL);
 1215 
 1216    get_pref(PREF_SHORTDATE, NULL, &datef);
 1217    time(&ltime);
 1218    now = localtime(&ltime);
 1219    strftime(str, sizeof(str), datef, now);
 1220    indent=strlen(str) + 8;
 1221 
 1222    for (temp_l = todo_list; temp_l; temp_l=temp_l->next) {
 1223       todo = &(temp_l->mtodo.todo);
 1224 
 1225       fprintf(out, todo->complete ? "true  " : "false ");
 1226 
 1227       fprintf(out, "%d ", todo->priority);
 1228 
 1229       if (todo->indefinite) {
 1230          sprintf(str, "%s           ", "No Due");
 1231          str[indent-8]='\0';
 1232       } else {
 1233          strftime(str, sizeof(str), datef, &(todo->due));
 1234       }
 1235       fprintf(out, "(%s) ", str);
 1236 
 1237       if (todo->description) {
 1238          int len;
 1239          char *buf;
 1240 
 1241          len = strlen(todo->description);
 1242          buf = malloc(2 * len + 1);
 1243          memset(buf, 0, 2 * len + 1);
 1244          ps_strncat(buf, todo->description, 2 * len);
 1245 
 1246          fprintf(out, "(%s) ", buf);
 1247          free(buf);
 1248       } else {
 1249          fprintf(out, "() ");
 1250       }
 1251 
 1252       if ((todo->note) && todo->note[0]) {
 1253          int len;
 1254          char *buf;
 1255 
 1256          len = strlen(todo->note);
 1257          buf = malloc(2 * len + 1);
 1258          memset(buf, 0, 2 * len + 1);
 1259          ps_strncat(buf, todo->note, 2 * len);
 1260 
 1261          fprintf(out, "(%s) ", buf);
 1262          free(buf);
 1263       } else {
 1264          fprintf(out, "()");
 1265       }
 1266       fprintf(out, " Todo\n");
 1267 
 1268       if (one_rec_per_page) {
 1269          fprintf(out, "NewPage\n");
 1270       }
 1271    }
 1272    fprintf(out, "showpage\n");
 1273 
 1274    print_close(out);
 1275 
 1276 #ifdef HAVE_LOCALE_H
 1277    setlocale(LC_ALL, current_locale);
 1278 #endif
 1279 
 1280    return EXIT_SUCCESS;
 1281 }
 1282 /*
 1283  * Memo code
 1284  */
 1285 int print_memos(MemoList *memo_list)
 1286 {
 1287    long one_rec_per_page;
 1288    long lines_between_recs;
 1289    MemoList *temp_l;
 1290    struct Memo *memo;
 1291    int i;
 1292 #ifdef HAVE_LOCALE_H
 1293    char *current_locale;
 1294 #endif
 1295 
 1296    out = print_open();
 1297    if (!out) {
 1298       return EXIT_FAILURE;
 1299    }
 1300 
 1301 #ifdef HAVE_LOCALE_H
 1302    current_locale = setlocale(LC_NUMERIC,"C");
 1303 #endif
 1304 
 1305    print_address_header();
 1306 
 1307    get_pref(PREF_PRINT_ONE_PER_PAGE, &one_rec_per_page, NULL);
 1308    get_pref(PREF_NUM_BLANK_LINES, &lines_between_recs, NULL);
 1309 
 1310    courier_12();
 1311 
 1312    for (temp_l = memo_list; temp_l; temp_l=temp_l->next) {
 1313       memo = &(temp_l->mmemo.memo);
 1314 
 1315       if (memo->text) {
 1316          fprintf(out, "%cHLINE\n", FLAG_CHAR);
 1317          f_indent_print(out, 0, memo->text);
 1318          fprintf(out, "\n");
 1319       }
 1320 
 1321       if (one_rec_per_page) {
 1322          fprintf(out, "%cLINEFEED\n", FLAG_CHAR);
 1323       } else {
 1324          for (i=lines_between_recs; i>0; i--) {
 1325             fprintf(out, "\n");
 1326          }
 1327       }
 1328    }
 1329 
 1330    fprintf(out, "%cEND\n", FLAG_CHAR);
 1331 
 1332 #ifdef HAVE_LOCALE_H
 1333    setlocale(LC_ALL, current_locale);
 1334 #endif
 1335 
 1336    print_close(out);
 1337 
 1338    return EXIT_SUCCESS;
 1339 }
 1340