Logo Search packages:      
Sourcecode: calcurse version File versions  Download package

day.c

/*    $calcurse: day.c,v 1.9 2006/09/14 15:10:26 culot Exp $      */

/*
 * Calcurse - text-based organizer
 * Copyright (c) 2004-2006 Frederic Culot
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Send your feedback or comments to : calcurse@culot.org
 * Calcurse home page : http://culot.org/calcurse
 *
 */

#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <stdbool.h>
#include <time.h>

#include "i18n.h"
#include "utils.h"
#include "apoint.h"
#include "event.h"
#include "recur.h"
#include "day.h"
#include "vars.h"

static struct day_item_s *day_items_ptr;
static struct day_saved_item_s *day_saved_item = NULL;

/* 
 * Store all of the items to be displayed for the selected day.
 * Items are of four types: recursive events, normal events, 
 * recursive appointments and normal appointments.
 * The items are stored in the linked list pointed by *day_items_ptr
 * and the length of the new pad to write is returned.
 * The number of events and appointments in the current day are also updated.
 */
int day_store_items(long date, int *pnb_events, int *pnb_apoints)
{
      int pad_length;
      int nb_events, nb_recur_events;
      int nb_apoints, nb_recur_apoints;

      pad_length = nb_events = nb_apoints = 0;
      nb_recur_events = nb_recur_apoints = 0;

      if (day_items_ptr != 0)
            day_free_list();
      nb_recur_events = day_store_recur_events(date);
      nb_events = day_store_events(date);
      *pnb_events = nb_events;
      nb_recur_apoints = day_store_recur_apoints(date);
      nb_apoints = day_store_apoints(date);
      *pnb_apoints = nb_apoints;
      pad_length = nb_recur_events + nb_events + 1 + 
            3*(nb_recur_apoints + nb_apoints);
      *pnb_apoints += nb_recur_apoints;
      *pnb_events += nb_recur_events;

      return pad_length;
}

/* Free the current day linked list containing the events and appointments. */
void day_free_list(void)
{
      struct day_item_s *p, *q;

      for (p = day_items_ptr; p != 0; p = q) {
            q = p->next;
            free(p->mesg);
            free(p);
      }
      day_items_ptr = NULL;
}

/* 
 * Store the recurrent events for the selected day in structure pointed
 * by day_items_ptr. This is done by copying the recurrent events 
 * from the general structure pointed by recur_elist to the structure
 * dedicated to the selected day. 
 * Returns the number of recurrent events for the selected day.
 */
int day_store_recur_events(long date)
{
      struct recur_event_s *j;
      struct day_item_s *ptr;
      int e_nb = 0;

      for (j = recur_elist; j != 0; j = j->next) {
            if (recur_item_inday(j->day, j->exc, j->rpt->type, j->rpt->freq,
                  j->rpt->until, date)) {
                  e_nb++;
                  ptr = day_add_event(RECUR_EVNT, j->mesg, j->day, j->id);
            }     
      }

      return e_nb;
}

/* 
 * Store the events for the selected day in structure pointed
 * by day_items_ptr. This is done by copying the events 
 * from the general structure pointed by eventlist to the structure
 * dedicated to the selected day. 
 * Returns the number of events for the selected day.
 */
int day_store_events(long date)
{
      struct event_s *j;
      struct day_item_s *ptr;
      int e_nb = 0;

      for (j = eventlist; j != 0; j = j->next) {
            if (event_inday(j, date)) {
                  e_nb++;
                  ptr = day_add_event(EVNT, j->mesg, j->day, j->id);
            }     
      }

      return e_nb;
}

/* 
 * Store the recurrent apoints for the selected day in structure pointed
 * by day_items_ptr. This is done by copying the appointments
 * from the general structure pointed by recur_alist_p->root to the 
 * structure dedicated to the selected day. 
 * Returns the number of recurrent appointments for the selected day.
 */
int day_store_recur_apoints(long date)
{
      recur_apoint_llist_node_t *j;
      struct day_item_s *ptr;
      long real_start;
      int a_nb = 0, n = 0;

      pthread_mutex_lock(&(recur_alist_p->mutex));
      for (j = recur_alist_p->root; j != 0; j = j->next) {
            if (real_start = recur_item_inday(j->start, j->exc, 
                j->rpt->type, j->rpt->freq, j->rpt->until, date)) {
                  a_nb++;
                  ptr = day_add_apoint(
                      RECUR_APPT, j->mesg, real_start, j->dur, n);
                  n++;
            }     
      }
      pthread_mutex_unlock(&(recur_alist_p->mutex));

      return a_nb;
}

/* 
 * Store the apoints for the selected day in structure pointed
 * by day_items_ptr. This is done by copying the appointments
 * from the general structure pointed by alist_p->root to the 
 * structure dedicated to the selected day. 
 * Returns the number of appointments for the selected day.
 */
int day_store_apoints(long date)
{
      apoint_llist_node_t *j;
      struct day_item_s *ptr;
      int a_nb = 0;

      pthread_mutex_lock(&(alist_p->mutex));
      for (j = alist_p->root; j != 0; j = j->next) {
            if (apoint_inday(j, date)) {
                  a_nb++;
                  ptr = day_add_apoint(APPT, j->mesg, j->start, j->dur, 0);
            }     
      }
      pthread_mutex_unlock(&(alist_p->mutex));

      return a_nb;
}

/* Add an event in the current day list */
struct day_item_s *day_add_event(int type, char *mesg, long day, int id)
{
      struct day_item_s *o, **i;
      o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
      o->mesg = (char *) malloc(strlen(mesg) + 1);
      strcpy(o->mesg, mesg);
      o->type = type;
      o->appt_dur = 0;
      o->appt_pos = 0;
      o->start = day;
      o->evnt_id = id;
      i = &day_items_ptr;
      for (;;) {
            if (*i == 0) {
                  o->next = *i;
                  *i = o;
                  break;
            }
            i = &(*i)->next;
      }
      return o;
}

/* Add an appointment in the current day list. */
struct day_item_s *day_add_apoint(int type, char *mesg, long start, long dur, 
      int real_pos)
{
      struct day_item_s *o, **i;
      int insert_item = 0;

      o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
      o->mesg = (char *) malloc(strlen(mesg) + 1);
      strcpy(o->mesg, mesg);
      o->start = start;
      o->appt_dur = dur;
      o->appt_pos = real_pos;
      o->type = type;
      o->evnt_id = 0;
      i = &day_items_ptr;
      for (;;) {
            if (*i == 0) {
                  insert_item = 1;
            } else if ( ((*i)->start > start) && 
                ((*i)->type > EVNT) ) {
                  insert_item = 1;
            }     
            if (insert_item) {
                  o->next = *i;
                  *i = o;
                  break;
            }
            i = &(*i)->next;
      }
      return o;
}

/* 
 * Write the appointments and events for the selected day in a pad.
 * An horizontal line is drawn between events and appointments, and the
 * item selected by user is highlighted. This item is also saved inside
 * structure (pointed by day_saved_item), to be later displayed in a
 * popup window if requested.
 */
void day_write_pad(long date, int width, int length, int incolor, int colr)
{
      struct day_item_s *p;
      int line, item_number, max_pos;
      const int x_pos = 0;
      bool draw_line = false;

      line = item_number = 0;
      max_pos = length;

      /* Initialize the structure used to store highlited item. */
      if (day_saved_item == NULL) {
            day_saved_item = (struct day_saved_item_s *) 
                  malloc(sizeof(struct day_saved_item_s));  
            day_saved_item->mesg = (char *) malloc(sizeof(char));
      } 

      for (p = day_items_ptr; p != 0; p = p->next) {
            /* First print the events for current day. */
            if (p->type < RECUR_APPT) {
                  item_number++;          
                  if (item_number - incolor == 0) {
                        day_saved_item->type = p->type;
                        day_saved_item->mesg = p->mesg;
                  }
                  display_item(apad->ptrwin, item_number - incolor, p->mesg, 
                  width - 4, line, x_pos);
                  line++;
                  draw_line = true;
            } else {
                  /* Draw a line between events and appointments. */
                  if (line > 0 && draw_line){
                        wmove(apad->ptrwin, line, x_pos);
                        whline(apad->ptrwin, 0, width);
                        draw_line = false;
                  }

                  /* Last print the appointments for current day. */
                  item_number++;
                  if (item_number - incolor == 0) {
                        day_saved_item->type = p->type;
                        day_saved_item->mesg = p->mesg;
                        apoint_sec2str(day_item_s2apoint_s(p), 
                              p->type, date,
                              day_saved_item->start,
                              day_saved_item->end);
                  }
                  display_item_date(apad->ptrwin, item_number - incolor, 
                        day_item_s2apoint_s(p), p->type, date, 
                        line + 1, x_pos); 
                  display_item(apad->ptrwin, item_number - incolor, p->mesg,
                  width - 6, line + 2, x_pos + 2);
                  line = line + 3;
            }
      }
}

/*
 * Returns a structure of type apoint_llist_node_t given a structure of type 
 * day_item_s 
 */
apoint_llist_node_t *day_item_s2apoint_s(struct day_item_s *p)
{
      apoint_llist_node_t *a;

      a = (apoint_llist_node_t *) malloc(sizeof(apoint_llist_node_t));
      a->mesg = (char *) malloc(strlen(p->mesg) + 1);
      a->start = p->start;
      a->dur = p->appt_dur;
      a->mesg = p->mesg;
      return a;
}

/* Display an item inside a popup window. */
void day_popup_item(void)
{
      char *error = 
            _("FATAL ERROR in day_popup_item: unknown item type\n");

      if (day_saved_item->type == EVNT || day_saved_item->type == RECUR_EVNT)
            item_in_popup(NULL, NULL, day_saved_item->mesg, _("Event :"));
      else if (day_saved_item->type == APPT || 
            day_saved_item->type == RECUR_APPT)
            item_in_popup(day_saved_item->start, day_saved_item->end,
                  day_saved_item->mesg, _("Appointment :"));
      else { /* NOT REACHED */
            fputs(error, stderr);
            exit(EXIT_FAILURE);
      }
}

/* 
 * Need to know if there is an item for the current selected day inside
 * calendar. This is used to put the correct colors inside calendar panel.
 */
 int day_check_if_item(int year, int month, int day) {
      struct recur_event_s  *re;
      recur_apoint_llist_node_t *ra;
      struct event_s *e;
      apoint_llist_node_t *a;
      const long date = date2sec(year, month, day, 0, 0);

      for (re = recur_elist; re != 0; re = re->next)
            if (recur_item_inday(re->day, re->exc, re->rpt->type, 
                  re->rpt->freq, re->rpt->until, date))
                  return 1;
      
      pthread_mutex_lock(&(recur_alist_p->mutex));
      for (ra = recur_alist_p->root; ra != 0; ra = ra->next)
            if (recur_item_inday(ra->start, ra->exc, ra->rpt->type, 
                  ra->rpt->freq, ra->rpt->until, date)) {
                        pthread_mutex_unlock(
                              &(recur_alist_p->mutex));
                        return 1;
            }
      pthread_mutex_unlock(&(recur_alist_p->mutex));

      for (e = eventlist; e != 0; e = e->next)
            if (event_inday(e, date))
                  return 1;

      pthread_mutex_lock(&(alist_p->mutex));
      for (a = alist_p->root; a != 0; a = a->next)
            if (apoint_inday(a, date)) {
                  pthread_mutex_unlock(&(alist_p->mutex));
                  return 1;
            }
      pthread_mutex_unlock(&(alist_p->mutex));

      return 0;
}

/*
 * In order to erase an item, we need to count first the number of
 * items for each type (in order: recurrent events, events, 
 * recurrent appointments and appointments) and then to test the
 * type of the item to be deleted.
 */
int day_erase_item(long date, int item_number) {
      int i;
      int ch = 0;
      int nb_item[MAX_TYPES];
      unsigned delete_whole;
      struct day_item_s *p;
      char *erase_warning =
            _("This item is recurrent. "
              "Delete (a)ll occurences or just this (o)ne ?");
      char *erase_choice =
            _("[a/o] ");

      for (i = 0; i < MAX_TYPES; i++)
            nb_item[i] = 0;

      p = day_items_ptr;
      for (i = 1; i < item_number; i++) {
            nb_item[p->type - 1]++;
            p = p->next;
      }     

      if (p->type == EVNT) {
            event_delete_bynum(date, nb_item[EVNT - 1]);
      } else if (p->type == APPT) {
            apoint_delete_bynum(date, nb_item[APPT - 1]);
      } else {
            while ( (ch != 'a') && (ch != 'o') && (ch != ESCAPE)) {
                  status_mesg(erase_warning, erase_choice);
                  ch = wgetch(swin);
            }

            if (ch == 'a') {
                  delete_whole = 1;
            } else if (ch == 'o') {
                  delete_whole = 0;
            } else {
                  return 0;
            }
            
            if (p->type == RECUR_EVNT) {
                  recur_event_erase(date, nb_item[RECUR_EVNT - 1], 
                        delete_whole);
            } else {
                  recur_apoint_erase(date, p->appt_pos, delete_whole);
            }
      }

      return p->type;
}

/* Returns a structure containing the selected item. */
struct day_item_s *day_get_item(int item_number)
{
      struct day_item_s *o;
      int i;
      
      o = day_items_ptr;
      for (i = 1; i < item_number; i++) {
            o = o->next;
      }
      return o;
}

Generated by  Doxygen 1.6.0   Back to index