/*  ----------------------------------------------------------------------

    Copyright (C) 1998  Cesar Miquel  (miquel@df.uba.ar)

    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., 675 Mass Ave, Cambridge, MA 02139, USA.

    ---------------------------------------------------------------------- */


#include <time.h>
#include <config.h>
#include <gnome.h>
#include "gtk/gtk.h"
#include "logview.h"
#include "close.xpm"
#include "right.xpm"
#include "left.xpm"

#define CALENDAR_WIDTH           180
#define CALENDAR_HEIGHT          150

#define SUNDAY                   0
#define MONDAY                   1
#define FRIDAY                   5
#define SATURDAY                 6
#define FEBRUARY                 1
#define XSEP                     3
#define CALLEFTMARGIN            5
#define BASELINESKIP             4

#define THISMONTH                1
#define OTHERMONTH               2
#define MARKEDDATE               3

/*
 *    -------------------
 *    Function Prototypes
 *    -------------------
 */

void CalendarMenu (GtkWidget * widget, gpointer user_data);
void ShowErrMessage (char *);
void CloseCalendar (GtkWidget * widget, gpointer client_data);
void GotoPrevMonth (GtkWidget * widget, gpointer client_data);
void GotoNextMonth (GtkWidget * widget, gpointer client_data);
void MoveMark ();
void HandleMouseMotion (GtkWidget * cv, GdkEventMotion * event);
void HandleMouseButton( GtkWidget * cv, GdkEventButton * event);
void DrawCalCursor ();
void EraseCalCursor ();
void log_repaint (GtkWidget * cv, GdkRectangle * area);
void Draw3DBox (GdkDrawable *, GdkGC *, int , int , int , int, GdkColor color[3]);
int IsLeapYear (int year);
int GetDayOfWeek (int day, int month, int year);
void DrawGlassWin (GdkWindow *win, int xs, int ys, int w, int h);
void set_scrollbar_size (int num_lines);
GtkWidget *new_pixmap_from_data(char **xpm_data, GdkWindow *w, GdkColor *b);
DateMark *FindPrevMark ();
DateMark *FindNextMark ();

/*
 *       --------
 *       Typedefs
 *       --------
 */

typedef struct
{
   char day[5], type;
	DateMark *mark;
} CalDate;

/*
 *       ----------------
 *       Global variables
 *       ----------------
 */

extern ConfigData *cfg;
extern GdkGC *gc;
extern Log *curlog, *loglist[];
extern int numlogs, curlognum;
extern char *month[12];
extern GtkWidget *main_win_scrollbar;

GtkWidget *CalendarDialog = NULL;
GdkDrawable *CalendarCanvas;
GdkCursor *cross;
int calendarvisible;
int curday, curmonth, curyear;
DateMark *curmonthmark;
int daysinmonth[] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int calstarty, calnumrows;
int pointerrow, pointercol;
CalDate calendardata[6][7];

/* ----------------------------------------------------------------------
   NAME:          CalendarMenu
   DESCRIPTION:   Display the calendar.
   ---------------------------------------------------------------------- */

void
CalendarMenu (GtkWidget * widget, gpointer user_data)
{
   GtkWidget *calarea;
   GtkWidget *frame;
   GtkWidget *vbox;
   GtkWidget *toolbar;
   GtkWidget *icon;
   int w,h;

   if (curlog == NULL || calendarvisible)
      return;

   if (CalendarDialog == NULL)
   {
      CalendarDialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_container_set_border_width (GTK_CONTAINER (CalendarDialog), 1);
      gtk_window_set_title (GTK_WINDOW (CalendarDialog), _("Calendar"));
      gtk_signal_connect (GTK_OBJECT (CalendarDialog), "destroy",
			  GTK_SIGNAL_FUNC (CloseCalendar),
			  &CalendarDialog);
      gtk_signal_connect (GTK_OBJECT (CalendarDialog), "delete_event",
			  GTK_SIGNAL_FUNC (CloseCalendar),
			  NULL);

      gtk_widget_set_style (CalendarDialog, cfg->main_style);
      vbox = gtk_vbox_new (FALSE, 2);
      gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
      gtk_container_add (GTK_CONTAINER (CalendarDialog), vbox);
      gtk_widget_show (vbox);

      /* Create toolbar */
      toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, 
				 GTK_TOOLBAR_ICONS);
      icon = new_pixmap_from_data (leftxpm, CalendarDialog->window, 
		   &CalendarDialog->style->bg[GTK_STATE_NORMAL]);
      gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                               "prev", _("Prev Month"), NULL,
			       icon,
                               (GtkSignalFunc) GotoPrevMonth, 
			       toolbar);
      icon = new_pixmap_from_data (rightxpm, CalendarDialog->window, 
		   &CalendarDialog->style->bg[GTK_STATE_NORMAL]);
      gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                               "next", _("Next Month"), NULL,
			       icon,
                               (GtkSignalFunc) GotoNextMonth, 
			       toolbar);

      icon = new_pixmap_from_data (closexpm, CalendarDialog->window, 
		   &CalendarDialog->style->bg[GTK_STATE_NORMAL]);
      gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                               NULL, _("Hide calendar"), NULL,
			       icon,
                               (GtkSignalFunc) CloseCalendar, 
			       toolbar);

      gtk_box_pack_start (GTK_BOX (vbox), toolbar, TRUE, TRUE, 0);
      gtk_widget_show (toolbar);

      frame = gtk_frame_new (NULL);
      gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
      gtk_container_set_border_width (GTK_CONTAINER (frame), 3);
      gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
      gtk_widget_set_style (frame, cfg->main_style);
      gtk_widget_show (frame);

      calarea = gtk_drawing_area_new ();
      gtk_widget_set_events (calarea, GDK_EXPOSURE_MASK | 
			     GDK_BUTTON_PRESS_MASK | 
			     GDK_POINTER_MOTION_MASK);
      gtk_signal_connect (GTK_OBJECT (calarea), "expose_event",
			  (GtkSignalFunc) RepaintCalendar, NULL);
      gtk_signal_connect (GTK_OBJECT (calarea), "motion_notify_event",
			  (GtkSignalFunc) HandleMouseMotion, NULL);
      gtk_signal_connect (GTK_OBJECT (calarea), "button_press_event",
			  (GtkSignalFunc) HandleMouseButton, NULL);

      /* Estimate size of window needed to display the calendar. */
      h = cfg->fixedb->ascent + cfg->fixedb->descent;
      w = gdk_string_measure (cfg->fixedb, "XXX") + XSEP;
      gtk_drawing_area_size (GTK_DRAWING_AREA (calarea), 8*w, (h+BASELINESKIP)*8 + 10);
      gtk_widget_set_style (calarea, cfg->white_bg_style);
      gtk_container_add (GTK_CONTAINER (frame), calarea);
      gtk_widget_show (calarea);

   }
   calendarvisible = TRUE;
   InitCalendarData ();

   gtk_widget_show (CalendarDialog);

   /* Create cursor for calendar */
   cross = gdk_cursor_new (GDK_PLUS);

}

/* ----------------------------------------------------------------------
   NAME:	new_pixmap_from_data
   DESCRIPTION:	
   ---------------------------------------------------------------------- */

GtkWidget *
new_pixmap_from_data (char      **xpm_data,
		      GdkWindow *window,
		      GdkColor  *background)
{
  GtkWidget *wpixmap;
  GdkPixmap *pixmap;
  GdkBitmap *mask;

  pixmap = gdk_pixmap_create_from_xpm_d (window, &mask,
					 background,
					 xpm_data);
  wpixmap = gtk_pixmap_new (pixmap, mask);

  return wpixmap;
}
        
/* ----------------------------------------------------------------------
   NAME:          InitCalendarData
   DESCRIPTION:   Sets up calendar data asociated with this log.
   ---------------------------------------------------------------------- */



void
InitCalendarData ()
{
   DateMark *mark;

   curmonth = curlog->curmark->fulldate.tm_mon;
   curday = curlog->curmark->fulldate.tm_mday;
   curyear = curlog->curmark->fulldate.tm_year;
   mark = curlog->lstats.firstmark;
   while (mark != NULL)
      if (mark->fulldate.tm_mon == curmonth &&
	  mark->fulldate.tm_year == curyear)
	 break;
      else
	 mark = mark->next;

   if (mark == NULL)
      ShowErrMessage (_("Program error: mark is NULL!"));

   curmonthmark = mark;
}

/* ----------------------------------------------------------------------
   NAME:          RepaintCalendar
   DESCRIPTION:   
   ---------------------------------------------------------------------- */

int
RepaintCalendar (GtkWidget * widget, GdkEventExpose * event)
{
   char buffer[255];
   int y, h, w, lm;
   int dayofweek, day, prevmonth;
   static char *dayinletters[] =
   {N_("SUN"), N_("MON"), N_("TUE"), N_("WED"),
    N_("THU"), N_("FRI"), N_("SAT")};
   DateMark *mark;

   if (widget != NULL)
      CalendarCanvas = widget->window;

   /* Change cursor in drawing area */
   gdk_window_set_cursor (CalendarCanvas, cross);

   /* Erase page */
   gdk_window_clear (CalendarCanvas);

   /* Check that there is at least one log */
   if (curlog == NULL)
      return -1;

   /* Draw title */
   y = LOG_LINESEP;
   lm = CALLEFTMARGIN;
   sprintf (buffer, "%s   %d", _(month[curmonth]), (1900 + curyear));
   gdk_gc_set_foreground (gc, &cfg->green);
   gdk_draw_string (CalendarCanvas, cfg->headingb, gc, lm, y, buffer);
   y += 5;

   /* Draw day headers */
   h = cfg->fixedb->ascent;
   w = gdk_string_measure (cfg->fixedb, "XXX") + XSEP;
   gdk_draw_line (CalendarCanvas, gc, lm, y, lm + w * 7, y);
   y += h + 3;
   for (day = 0; day <= SATURDAY; day++)
   {
      sprintf (buffer, "%s", _(dayinletters[day]));
      gdk_draw_string (CalendarCanvas, cfg->fixedb, gc, lm + w * day + XSEP, y, buffer);
   }
   gdk_draw_line (CalendarCanvas, gc, lm, y + 3, lm + w * 7, y + 3);
   y += 2 * h + 3;
   calstarty = y;
   calnumrows = 0;

   /* Draw calendar */
   mark = curmonthmark;
   prevmonth = (curmonth > 0) ? curmonth - 1 : 11;
   dayofweek = SUNDAY;
   if (curmonth == FEBRUARY && IsLeapYear(curyear))
      daysinmonth[FEBRUARY] = 29;
   else
      daysinmonth[FEBRUARY] = 28;

   for (day =  1 - GetDayOfWeek (1, curmonth, curyear);; day++)
   {
      if (day < 1 || day > daysinmonth[curmonth])
	{
	 calendardata[calnumrows][dayofweek].type = OTHERMONTH;
	 gdk_gc_set_foreground (gc, &cfg->gray50);
	}
      else
	{
	 gdk_gc_set_foreground (gc, &cfg->black);
	 calendardata[calnumrows][dayofweek].type = THISMONTH;
	}

      if (mark != NULL && day == mark->fulldate.tm_mday &&
	  curmonth == mark->fulldate.tm_mon
	  && curyear == mark->fulldate.tm_year)
      {
	 gdk_gc_set_foreground (gc, &cfg->blue);
	 calendardata[calnumrows][dayofweek].type = MARKEDDATE;
	 calendardata[calnumrows][dayofweek].mark = mark;
	 mark = mark->next;
      }
      if (day < 1)
	 sprintf (buffer, "%3d", day + daysinmonth[prevmonth]);
      else if (day > daysinmonth[curmonth])
	 sprintf (buffer, "%3d", day - daysinmonth[curmonth]);
      else
	 sprintf (buffer, "%3d", day);
      sprintf (calendardata[calnumrows][dayofweek].day, "%s", buffer);

      gdk_draw_string (CalendarCanvas, cfg->fixed, gc, lm + w * dayofweek, y, buffer);
      dayofweek++;
      if (dayofweek > SATURDAY)
      {
	 dayofweek = SUNDAY;
	 y += h + BASELINESKIP;
	 if (day > daysinmonth[curmonth])
	    break;
	 calnumrows++;
      }
   }

   return TRUE;
}


/* ----------------------------------------------------------------------
   NAME:	HandleMouseMotion
   DESCRIPTION:	Handle all mouse events inside calendar.
   ---------------------------------------------------------------------- */

void
HandleMouseMotion (GtkWidget * cv, GdkEventMotion * event)
{
   int cursory, cursorx;
   int newrow, newcol, h, w;

   /* Check that there is at least one log */
   if (curlog == NULL)
      return;
   
   /* Calculate on what day the cursor is on */
   cursory = event->y;
   cursorx = event->x;
   h = cfg->fixedb->ascent + BASELINESKIP;
   w = gdk_string_measure (cfg->fixedb, "XXX") + XSEP;

   /* Draw cursor */
   newrow = (cursory - calstarty + h) / h;
   newcol = (cursorx - CALLEFTMARGIN) / w;
   if (newrow >= 0 && newrow <= calnumrows &&
       newcol >= 0 && newcol < 7)
   {
      EraseCalCursor ();
      pointerrow = newrow;
      pointercol = newcol;
      gdk_gc_set_foreground (gc, &cfg->gray75);
      DrawCalCursor ();
   }

}

/* ----------------------------------------------------------------------
   NAME:			 HandleMouseButton
   DESCRIPTION:	
   ---------------------------------------------------------------------- */

void
HandleMouseButton( GtkWidget * cv, GdkEventButton * event)
{
	CalDate *thisdate;

   /* Check that there is at least one log */
   if (curlog == NULL)
      return;
   
   thisdate = &calendardata[pointerrow][pointercol];

   if (thisdate->type == MARKEDDATE)
     {
       curlog->curmark = thisdate->mark;
       MoveToMark (curlog);
       curlog->firstline = 0;
       curlog->ln = curlog->curmark->ln;
       gtk_adjustment_set_value ( GTK_RANGE(main_win_scrollbar)->adjustment, 
				  curlog->ln);
       /* set_scrollbar_size (curlog->lstats.numlines); */
       log_repaint(NULL, NULL);
     }
}

/* ----------------------------------------------------------------------
   NAME:	EraseCalCursor
   DESCRIPTION:	
   ---------------------------------------------------------------------- */

void
EraseCalCursor ()
{
   int h, w, cx, cy;
   CalDate *thisdate;

   h = cfg->fixedb->ascent + BASELINESKIP;
   w = gdk_string_measure (cfg->fixedb, "XXX") + XSEP;
   cx = (w - (gdk_string_measure (cfg->fixedb, "XX") + XSEP)) >> 1;
   cy = BASELINESKIP >> 1;

   gdk_window_clear_area (CalendarCanvas, 
			  CALLEFTMARGIN + pointercol * w + cx, 
			  calstarty + (pointerrow - 1) * h + cy, w,h);

   thisdate = &calendardata[pointerrow][pointercol];
   switch(thisdate->type)
     {
     case THISMONTH:
       gdk_gc_set_foreground (gc, &cfg->black);
       break;
     case OTHERMONTH:
       gdk_gc_set_foreground (gc, &cfg->gray50);
       break;
     case MARKEDDATE:
       gdk_gc_set_foreground (gc, &cfg->blue);
       break;
     }
   
   gdk_draw_string (CalendarCanvas, cfg->fixed, gc, 
		    CALLEFTMARGIN + w * pointercol, 
		    calstarty + pointerrow * h, thisdate->day);
			  
}

/* ----------------------------------------------------------------------
   NAME:	DrawCalCursor
   DESCRIPTION:	Draw a cursor on the date pointed to by the pointer.
   ---------------------------------------------------------------------- */

void
DrawCalCursor ()
{
   int h, w, cx, cy;
   CalDate *thisdate;

   h = cfg->fixedb->ascent + BASELINESKIP;
   w = gdk_string_measure (cfg->fixedb, "XXX") + XSEP;
   cx = (w - (gdk_string_measure (cfg->fixedb, "XX") + XSEP)) >> 1;
   cy = BASELINESKIP >> 1;

   DrawGlassWin (CalendarCanvas, 
		 CALLEFTMARGIN + pointercol * w + cx, 
		 calstarty + (pointerrow - 1) * h + cy, 
		 w, h);

   thisdate = &calendardata[pointerrow][pointercol];
   switch(thisdate->type)
     {
     case THISMONTH:
        gdk_gc_set_foreground (gc, &cfg->white);
	break;
     case OTHERMONTH:
	  gdk_gc_set_foreground (gc, &cfg->gray75);
	break;
     case MARKEDDATE:
        gdk_gc_set_foreground (gc, &cfg->blue);
	break;
     }
   
   gdk_draw_string (CalendarCanvas, cfg->fixed, gc, 
		    CALLEFTMARGIN + w * pointercol, 
		    calstarty + pointerrow * h, thisdate->day);

}


/* ----------------------------------------------------------------------
   NAME:          GetDayOfWeek
   DESCRIPTION:   Given day, month and year returns de weekday.
   0 = sunday, 1 = monday, ... 6 = saturday.
   ---------------------------------------------------------------------- */

int
GetDayOfWeek (int day, int month, int year)
{
   struct tm footm;

   footm.tm_mday = day;
   footm.tm_mon = month;
   footm.tm_year = year;
   footm.tm_hour = 12;
   footm.tm_sec = footm.tm_min = 0;

   mktime (&footm);

   return footm.tm_wday;
}

/* ----------------------------------------------------------------------
   NAME:          IsLeapYear
   DESCRIPTION:   Return TRUE if year is a leap year.
   ---------------------------------------------------------------------- */
int
IsLeapYear (int year)
{
   if ((1900 + year) % 4 == 0)
      return TRUE;
   else
      return FALSE;
}

/* ----------------------------------------------------------------------
   NAME:          GotoPrevMonth
   DESCRIPTION:   Show previous month on calendar.
   ---------------------------------------------------------------------- */
void
GotoPrevMonth (GtkWidget * widget, gpointer client_data)
{
   curmonth--;
   if (curmonth < 0)
   {
      curmonth = 11;
      curyear--;
   }
   MoveMark ();
   RepaintCalendar (NULL, NULL);
   return;
}

/* ----------------------------------------------------------------------
   NAME:          GotoNextMonth
   DESCRIPTION:   Show next month on calendar.
   ---------------------------------------------------------------------- */
void
GotoNextMonth (GtkWidget * widget, gpointer client_data)
{
   curmonth++;
   if (curmonth > 11)
   {
      curmonth = 0;
      curyear++;
   }
   MoveMark ();
   RepaintCalendar (NULL, NULL);
   return;
}

/* ----------------------------------------------------------------------
   NAME:          MoveMark
   DESCRIPTION:   Move curmonthmark to current month if there is a log 
   entry that month.
   ---------------------------------------------------------------------- */

void
MoveMark ()
{
   DateMark *mark = curmonthmark;

   if (mark == NULL)
      return;

   /* Are we on top of the mark: return if so      */
   if (curmonth == mark->fulldate.tm_mon &&
       curyear == mark->fulldate.tm_year)
      return;

   /* Check if we are on the next or previous mark */
   if (curyear > mark->fulldate.tm_year)
      mark = FindNextMark ();
   else if (curyear < mark->fulldate.tm_year)
      mark = FindPrevMark ();
   else if (curyear == mark->fulldate.tm_year) {
      if (curmonth > mark->fulldate.tm_mon)
	 mark = FindNextMark ();
      else
	 mark = FindPrevMark ();
   }

   if (mark == NULL)
      return;

   if (curmonth == mark->fulldate.tm_mon && curyear == mark->fulldate.tm_year)
      curmonthmark = mark;

   return;
}

/* ----------------------------------------------------------------------
   NAME:          FindPrevMark
   DESCRIPTION:   Returns the previous mark with a different month.
   ---------------------------------------------------------------------- */

DateMark *
FindPrevMark ()
{
   DateMark *mark = curmonthmark;

   if (mark->prev == NULL)
      return NULL;
   mark = mark->prev;
   while (TRUE)
   {
      if (mark->prev == NULL)
	 break;
      mark = mark->prev;
      if (mark->fulldate.tm_mon != mark->next->fulldate.tm_mon ||
	  mark->fulldate.tm_year != mark->next->fulldate.tm_year)
      {
	 mark = mark->next;
	 break;
      }
   }

   return mark;
}

/* ----------------------------------------------------------------------
   NAME:          FindNextMark
   DESCRIPTION:   Returns the next mark with a different month.
   ---------------------------------------------------------------------- */

DateMark *
FindNextMark ()
{
   DateMark *mark = curmonthmark;

   while (TRUE)
   {
      if (mark->next == NULL)
	 return NULL;
      mark = mark->next;
      if (mark->fulldate.tm_mon != mark->prev->fulldate.tm_mon ||
	  mark->fulldate.tm_year != mark->prev->fulldate.tm_year)
	 break;
   }

   return mark;
}


/* ----------------------------------------------------------------------
   NAME:          CloseCalendar
   DESCRIPTION:   Callback called when the log info window is closed.
   ---------------------------------------------------------------------- */

void
CloseCalendar (GtkWidget * widget, gpointer client_data)
{
   if (calendarvisible)
      gtk_widget_hide (CalendarDialog);
   CalendarDialog = NULL;
   calendarvisible = FALSE;
}

/* ----------------------------------------------------------------------
   NAME:	DrawGlassWin
   DESCRIPTION:	
   ---------------------------------------------------------------------- */

void InitGlassColormap (GdkColor *gray_colormap, 
			int numcolors);

void
DrawGlassWin (GdkWindow *win, int xs, int ys, int w, int h)
{
  GdkColor private_colormap[11] = {
    {0,0,0,0},
    {0,2,2,2},
    {0,5,5,5},
    {0,7,7,7},
    {0,10,10,10},
    {0,12,12,12},
    {0,15,15,15},
    {0,17,17,17},
    {0,20,20,20},
    {0,22,22,22},
    {0,25,25,25}
  };
  GdkImage *background;
  GdkVisual *sys_visual;
  GdkGC *gc;
  static int first_time = TRUE;
  int index, x, y, pixel, red, green, blue;
  float average;

  /* Add colors necessary for us. */
  if (first_time)
    InitGlassColormap (private_colormap, 11);

  /* Create image */
  background = gdk_image_get (win, xs, ys, w, h);


  /* Make background into shades of one color */

  /* Get the system visual, colormap and window gc. */
  sys_visual = gdk_visual_get_system ();
  gc = gdk_gc_new (win);

  for(x=0;x<w;x++)
    {
    for(y=0;y<h;y++)
      {
	pixel = gdk_image_get_pixel (background, x,y);
	switch (sys_visual->type)
	  {
	  case GDK_VISUAL_TRUE_COLOR:
	    red   = ((pixel & sys_visual->red_mask) >> 
		     sys_visual->red_shift);
	    green = ((pixel & sys_visual->green_mask) >> 
		     sys_visual->green_shift);
	    blue  = ((pixel & sys_visual->blue_mask) >> 
		     sys_visual->blue_shift);
	    average = ((float) red+green+blue)/3.0;
	    index = (int) ((average / 70.0) * (float) 11);
	    break;
	  default:
	    index = 0;
	    break;
	  }
	gdk_image_put_pixel (background,x,y,private_colormap[index].pixel);
      }
    }

  gdk_draw_image (win, gc, background, 0, 0, xs, ys, w, h);

  return;
}

/* ----------------------------------------------------------------------
   NAME:	InitGlassColormap
   DESCRIPTION:	
   ---------------------------------------------------------------------- */

void
InitGlassColormap (GdkColor *gray_colormap, int numcolors)
{
  
  GdkColor color;
  GdkColormap *colormap;
  int i;

  colormap = gdk_colormap_get_system ();
  
  for (i=0;i<numcolors;i++)
    {
    gray_colormap[i].red *= 1300;
    gray_colormap[i].green *= 1300;
    gray_colormap[i].blue *= 2000;
    memcpy (&color, &gray_colormap[i], sizeof (GdkColor));
    gdk_color_alloc (colormap, &color);
    gray_colormap[i].pixel = color.pixel;
    }

  return;
}

