home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / about_dialog.c next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  19.2 KB  |  720 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <time.h>
  25.  
  26. #include <gtk/gtk.h>
  27. #include <gdk/gdkkeysyms.h>
  28.  
  29. #include "apptypes.h"
  30.  
  31. #include "about_dialog.h"
  32. #include "appenv.h"
  33. #include "authors.h"
  34. #include "gimpdnd.h"
  35. #include "gimphelp.h"
  36.  
  37. #include "libgimp/gimpfeatures.h"
  38.  
  39. #include "libgimp/gimpenv.h"
  40. #include "libgimp/gimpintl.h"
  41. #include "libgimp/gimpmath.h"
  42.  
  43. #include "pixmaps/wilber2.xpm"
  44.  
  45.  
  46. #define ANIMATION_STEPS 16
  47. #define ANIMATION_SIZE   2
  48.  
  49. static gboolean  about_dialog_load_logo   (GtkWidget      *window);
  50. static void      about_dialog_destroy     (GtkObject      *object,
  51.                        gpointer        data);
  52. static void      about_dialog_unmap       (GtkWidget      *widget,
  53.                        GdkEvent       *event,
  54.                        gpointer        data);
  55. static gint      about_dialog_logo_expose (GtkWidget      *widget,
  56.                        GdkEventExpose *event,
  57.                        gpointer        data);
  58. static gint      about_dialog_button      (GtkWidget      *widget,
  59.                        GdkEventButton *event,
  60.                        gpointer        data);
  61. static gint      about_dialog_key         (GtkWidget      *widget,
  62.                        GdkEventKey    *event,
  63.                        gpointer        data);
  64. static void      about_dialog_tool_drop   (GtkWidget      *widget,
  65.                        ToolType        tool,
  66.                        gpointer        data);
  67. static gint      about_dialog_timer       (gpointer        data);
  68.  
  69.  
  70. static GtkWidget *about_dialog     = NULL;
  71. static GtkWidget *logo_area        = NULL;
  72. static GtkWidget *scroll_area      = NULL;
  73. static GdkPixmap *logo_pixmap      = NULL;
  74. static GdkPixmap *scroll_pixmap    = NULL;
  75. static guchar    *dissolve_map     = NULL;
  76. static gint       dissolve_width;
  77. static gint       dissolve_height;
  78. static gint       logo_width       = 0;
  79. static gint       logo_height      = 0;
  80. static gboolean   do_animation     = FALSE;
  81. static gboolean   do_scrolling     = FALSE;
  82. static gint       scroll_state     = 0;
  83. static gint       frame            = 0;
  84. static gint       offset           = 0;
  85. static gint       timer            = 0;
  86. static gint       hadja_state      = 0;
  87. static gchar    **scroll_text      = authors;
  88. static gint       nscroll_texts    = sizeof (authors) / sizeof (authors[0]);
  89. static gint       scroll_text_widths[sizeof (authors) / sizeof (authors[0])];
  90. static gint       cur_scroll_text  = 0;
  91. static gint       cur_scroll_index = 0;
  92. static gint       shuffle_array[sizeof (authors) / sizeof (authors[0])];
  93.  
  94. /*  dnd stuff  */
  95. static GtkTargetEntry tool_target_table[] =
  96. {
  97.   GIMP_TARGET_TOOL
  98. };
  99. static guint n_tool_targets = (sizeof (tool_target_table) /
  100.                                sizeof (tool_target_table[0]));
  101.  
  102. static gchar *drop_text[] = 
  103.   "We are The GIMP." ,
  104.   "Prepare to be manipulated.",
  105.   "Resistance is futile."
  106. };
  107.  
  108. static gchar *hadja_text[] =
  109. {
  110.   "Hadjaha!",
  111.   "Nej!",
  112. #ifndef GDK_USE_UTF8_MBS
  113.   "TvΣrtom!"
  114. #else
  115.   "Tv├ñrtom!"
  116. #endif
  117. };
  118.  
  119. void
  120. about_dialog_create (void)
  121. {
  122.   GtkWidget *vbox;
  123.   GtkWidget *aboutframe;
  124.   GtkWidget *label;
  125.   GtkWidget *alignment;
  126.   GtkStyle  *style;
  127.   GdkFont   *font;
  128.   gint       max_width;
  129.   gint       i;
  130.   gchar     *label_text;
  131.  
  132.   if (!about_dialog)
  133.     {
  134.       about_dialog = gtk_window_new (GTK_WINDOW_DIALOG);
  135.       gtk_window_set_wmclass (GTK_WINDOW (about_dialog), "about_dialog", "Gimp");
  136.       gtk_window_set_title (GTK_WINDOW (about_dialog), _("About the GIMP"));
  137.       gtk_window_set_policy (GTK_WINDOW (about_dialog), FALSE, FALSE, FALSE);
  138.       gtk_window_set_position (GTK_WINDOW (about_dialog), GTK_WIN_POS_CENTER);
  139.  
  140.       gimp_help_connect_help_accel (about_dialog, gimp_standard_help_func,
  141.                     "dialogs/about.html");
  142.  
  143.       gtk_signal_connect (GTK_OBJECT (about_dialog), "destroy",
  144.               GTK_SIGNAL_FUNC (about_dialog_destroy),
  145.               NULL);
  146.       gtk_signal_connect (GTK_OBJECT (about_dialog), "unmap_event",
  147.               GTK_SIGNAL_FUNC (about_dialog_unmap),
  148.               NULL);
  149.       gtk_signal_connect (GTK_OBJECT (about_dialog), "button_press_event",
  150.               GTK_SIGNAL_FUNC (about_dialog_button),
  151.               NULL);
  152.       gtk_signal_connect (GTK_OBJECT (about_dialog), "key_press_event",
  153.               GTK_SIGNAL_FUNC (about_dialog_key),
  154.               NULL);
  155.       
  156.       /*  dnd stuff  */
  157.       gtk_drag_dest_set (about_dialog,
  158.              GTK_DEST_DEFAULT_MOTION |
  159.              GTK_DEST_DEFAULT_DROP,
  160.              tool_target_table, n_tool_targets,
  161.              GDK_ACTION_COPY); 
  162.       gimp_dnd_tool_dest_set (about_dialog, about_dialog_tool_drop, NULL);
  163.  
  164.       gtk_widget_set_events (about_dialog, GDK_BUTTON_PRESS_MASK);
  165.  
  166.       if (!about_dialog_load_logo (about_dialog))
  167.     {
  168.       gtk_widget_destroy (about_dialog);
  169.       about_dialog = NULL;
  170.       return;
  171.     }
  172.  
  173.       vbox = gtk_vbox_new (FALSE, 1);
  174.       gtk_container_set_border_width (GTK_CONTAINER (vbox), 1);
  175.       gtk_container_add (GTK_CONTAINER (about_dialog), vbox);
  176.       gtk_widget_show (vbox);
  177.  
  178.       aboutframe = gtk_frame_new (NULL);
  179.       gtk_frame_set_shadow_type (GTK_FRAME (aboutframe), GTK_SHADOW_IN);
  180.       gtk_container_set_border_width (GTK_CONTAINER (aboutframe), 0);
  181.       gtk_box_pack_start (GTK_BOX (vbox), aboutframe, TRUE, TRUE, 0);
  182.       gtk_widget_show (aboutframe);
  183.  
  184.       logo_area = gtk_drawing_area_new ();
  185.       gtk_signal_connect (GTK_OBJECT (logo_area), "expose_event",
  186.               GTK_SIGNAL_FUNC (about_dialog_logo_expose),
  187.               NULL);
  188.       gtk_drawing_area_size (GTK_DRAWING_AREA (logo_area),
  189.                  logo_width, logo_height);
  190.       gtk_widget_set_events (logo_area, GDK_EXPOSURE_MASK);
  191.       gtk_container_add (GTK_CONTAINER (aboutframe), logo_area);
  192.       gtk_widget_show (logo_area);
  193.  
  194.       gtk_widget_realize (logo_area);
  195.       gdk_window_set_background (logo_area->window, &logo_area->style->black);
  196.  
  197.       /* this is a font, provide only one single font definition */
  198.       font = gdk_font_load (_("-*-helvetica-medium-r-normal--*-140-*-*-*-*-*-*"));
  199.       if (font)
  200.     {
  201.       style = gtk_style_new ();
  202.       gdk_font_unref (style->font);
  203.       style->font = font;
  204.       gdk_font_ref (style->font);
  205.       gtk_widget_push_style (style);
  206.       gtk_style_unref (style);
  207.     }
  208.       label_text = g_strdup_printf (_("Version %s brought to you by"),
  209.                     GIMP_VERSION);
  210.       label = gtk_label_new (label_text);
  211.       g_free (label_text);
  212.       label_text = NULL;
  213.       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
  214.       gtk_widget_show (label);
  215.  
  216.       label = gtk_label_new ("Spencer Kimball & Peter Mattis");
  217.       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
  218.       gtk_widget_show (label);
  219.  
  220.       gtk_widget_pop_style ();
  221.  
  222.       alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  223.       gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 0);
  224.       gtk_widget_show (alignment);
  225.  
  226.       aboutframe = gtk_frame_new (NULL);
  227.       gtk_frame_set_shadow_type (GTK_FRAME (aboutframe), GTK_SHADOW_IN);
  228.       gtk_container_set_border_width (GTK_CONTAINER (aboutframe), 0);
  229.       gtk_container_add (GTK_CONTAINER (alignment), aboutframe);
  230.       gtk_widget_show (aboutframe);
  231.  
  232.       max_width = 0;
  233.       for (i = 0; i < nscroll_texts; i++)
  234.     {
  235.       scroll_text_widths[i] = gdk_string_width (aboutframe->style->font,
  236.                             scroll_text[i]);
  237.       max_width = MAX (max_width, scroll_text_widths[i]);
  238.     }
  239.       for (i = 0; i < (sizeof (drop_text) / sizeof (drop_text[0])); i++)
  240.     {
  241.       max_width = MAX (max_width, 
  242.                gdk_string_width (aboutframe->style->font, drop_text[i]));
  243.     }
  244.       for (i = 0; i < (sizeof (hadja_text) / sizeof (hadja_text[0])); i++)
  245.     {
  246.       max_width = MAX (max_width,
  247.                gdk_string_width (aboutframe->style->font, hadja_text[i]));
  248.     }
  249.       scroll_area = gtk_drawing_area_new ();
  250.       gtk_drawing_area_size (GTK_DRAWING_AREA (scroll_area),
  251.                  max_width + 10,
  252.                  aboutframe->style->font->ascent +
  253.                  aboutframe->style->font->descent);
  254.       gtk_widget_set_events (scroll_area, GDK_BUTTON_PRESS_MASK);
  255.       gtk_container_add (GTK_CONTAINER (aboutframe), scroll_area);
  256.       gtk_widget_show (scroll_area);
  257.  
  258.       label = gtk_label_new (_("Please visit http://www.gimp.org/ for more info"));
  259.       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
  260.       gtk_widget_show (label);
  261.  
  262.       gtk_widget_realize (scroll_area);
  263.       gdk_window_set_background (scroll_area->window,
  264.                  &scroll_area->style->white);
  265.     }
  266.  
  267.   if (!GTK_WIDGET_VISIBLE (about_dialog))
  268.     {
  269.       gtk_widget_show (about_dialog);
  270.  
  271.       do_animation = TRUE;
  272.       do_scrolling = FALSE;
  273.       scroll_state = 0;
  274.       frame = 0;
  275.       offset = 0;
  276.       cur_scroll_text = 0;
  277.  
  278.       if (!double_speed && hadja_state != 7)
  279.     {
  280.       for (i = 0; i < nscroll_texts; i++) 
  281.         {
  282.           shuffle_array[i] = i;
  283.         }
  284.  
  285.       for (i = 0; i < nscroll_texts; i++) 
  286.         {
  287.           gint j;
  288.  
  289.           j = rand() % nscroll_texts;
  290.           if (i != j) 
  291.         {
  292.           gint t;
  293.  
  294.           t = shuffle_array[j];
  295.           shuffle_array[j] = shuffle_array[i];
  296.           shuffle_array[i] = t;
  297.         }
  298.         }
  299.       cur_scroll_text = rand() % nscroll_texts;
  300.     }
  301.     }
  302.   else 
  303.     {
  304.       gdk_window_raise (about_dialog->window);
  305.     }
  306. }
  307.  
  308. static gboolean
  309. about_dialog_load_logo (GtkWidget *window)
  310. {
  311.   GtkWidget *preview;
  312.   GdkGC     *gc;
  313.   gchar      buf[1024];
  314.   gchar     *filename;
  315.   guchar    *pixelrow;
  316.   FILE      *fp;
  317.   gint       count;
  318.   gint       i, j, k;
  319.  
  320.   if (logo_pixmap)
  321.     return TRUE;
  322.  
  323.   filename = g_strconcat (gimp_data_directory (),
  324.               G_DIR_SEPARATOR_S,
  325.               "gimp_logo.ppm",
  326.               NULL);
  327.   fp = fopen (filename, "rb");
  328.   g_free (filename);
  329.  
  330.   if (!fp)
  331.     return FALSE;
  332.  
  333.   fgets (buf, 1024, fp);
  334.  
  335.   if (strncmp (buf, "P6", 2) != 0)
  336.     {
  337.       fclose (fp);
  338.       return FALSE;
  339.     }
  340.  
  341.   fgets (buf, 1024, fp);
  342.   fgets (buf, 1024, fp);
  343.   sscanf (buf, "%d %d", &logo_width, &logo_height);
  344.  
  345.   fgets (buf, 1024, fp);
  346.   if (strncmp (buf, "255", 3) != 0)
  347.     {
  348.       fclose (fp);
  349.       return FALSE;
  350.     }
  351.  
  352.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  353.   gtk_preview_size (GTK_PREVIEW (preview), logo_width, logo_height);
  354.   pixelrow = g_new (guchar, logo_width * 3);
  355.  
  356.   for (i = 0; i < logo_height; i++)
  357.     {
  358.       count = fread (pixelrow, sizeof (guchar), logo_width * 3, fp);
  359.       if (count != (logo_width * 3))
  360.     {
  361.       gtk_widget_destroy (preview);
  362.       g_free (pixelrow);
  363.       fclose (fp);
  364.       return FALSE;
  365.     }
  366.  
  367.       gtk_preview_draw_row (GTK_PREVIEW (preview), pixelrow, 0, i, logo_width);
  368.     }
  369.  
  370.   gtk_widget_realize (window);
  371.   logo_pixmap = gdk_pixmap_new (window->window, logo_width, logo_height, 
  372.                 gtk_preview_get_visual ()->depth);
  373.   gc = gdk_gc_new (logo_pixmap);
  374.   gtk_preview_put (GTK_PREVIEW (preview),
  375.            logo_pixmap, gc,
  376.            0, 0, 0, 0, logo_width, logo_height);
  377.   gdk_gc_destroy (gc);
  378.  
  379.   gtk_widget_unref (preview);
  380.   g_free (pixelrow);
  381.  
  382.   fclose (fp);
  383.  
  384.   dissolve_width =
  385.     (logo_width / ANIMATION_SIZE) + (logo_width % ANIMATION_SIZE == 0 ? 0 : 1);
  386.   dissolve_height =
  387.     (logo_height / ANIMATION_SIZE) + (logo_height % ANIMATION_SIZE == 0 ? 0 : 1);
  388.  
  389.   dissolve_map = g_new (guchar, dissolve_width * dissolve_height);
  390.  
  391.   srand (time (NULL));
  392.  
  393.   for (i = 0, k = 0; i < dissolve_height; i++)
  394.     for (j = 0; j < dissolve_width; j++, k++)
  395.       dissolve_map[k] = rand () % ANIMATION_STEPS;
  396.  
  397.   return TRUE;
  398. }
  399.  
  400. static void
  401. about_dialog_destroy (GtkObject *object,
  402.               gpointer   data)
  403. {
  404.   about_dialog = NULL;
  405.   about_dialog_unmap (NULL, NULL, NULL);
  406. }
  407.  
  408. static void
  409. about_dialog_unmap (GtkWidget *widget,
  410.             GdkEvent  *event,
  411.             gpointer   data)
  412. {
  413.   if (timer)
  414.     {
  415.       gtk_timeout_remove (timer);
  416.       timer = 0;
  417.     }
  418. }
  419.  
  420. static gint
  421. about_dialog_logo_expose (GtkWidget      *widget,
  422.               GdkEventExpose *event,
  423.               gpointer        data)
  424. {
  425.   if (do_animation)
  426.     {
  427.       if (!timer)
  428.     {
  429.       about_dialog_timer (widget);
  430.       timer = gtk_timeout_add (75, about_dialog_timer, NULL);
  431.     }
  432.     }
  433.   else
  434.     {
  435.       /* If we draw beyond the boundaries of the pixmap, then X
  436.      will generate an expose area for those areas, starting
  437.      an infinite cycle. We now set allow_grow = FALSE, so
  438.      the drawing area can never be bigger than the preview.
  439.          Otherwise, it would be necessary to intersect event->area
  440.          with the pixmap boundary rectangle. */
  441.  
  442.       gdk_draw_pixmap (widget->window,
  443.                widget->style->black_gc,
  444.                logo_pixmap, 
  445.                event->area.x, event->area.y,
  446.                event->area.x, event->area.y,
  447.                event->area.width, event->area.height);
  448.     }
  449.  
  450.   return FALSE;
  451. }
  452.  
  453. static gint
  454. about_dialog_button (GtkWidget      *widget,
  455.              GdkEventButton *event,
  456.              gpointer        data)
  457. {
  458.   if (timer)
  459.     gtk_timeout_remove (timer);
  460.   timer = 0;
  461.   frame = 0;
  462.  
  463.   gtk_widget_hide (about_dialog);
  464.  
  465.   return FALSE;
  466. }
  467.  
  468. static gint
  469. about_dialog_key (GtkWidget      *widget,
  470.           GdkEventKey    *event,
  471.           gpointer        data)
  472. {
  473.   gint i;
  474.   
  475.   if (hadja_state == 7)
  476.     return FALSE;
  477.     
  478.   switch (event->keyval)
  479.     {
  480.     case GDK_h:
  481.     case GDK_H:
  482.       if (hadja_state == 0 || hadja_state == 5)
  483.     hadja_state++;
  484.       else
  485.     hadja_state = 1;
  486.       break;
  487.     case GDK_a:
  488.     case GDK_A:
  489.       if (hadja_state == 1 || hadja_state == 4 || hadja_state == 6)
  490.     hadja_state++;
  491.       else
  492.     hadja_state = 0;
  493.       break;
  494.     case GDK_d:
  495.     case GDK_D:
  496.       if (hadja_state == 2)
  497.     hadja_state++;
  498.       else
  499.     hadja_state = 0;
  500.       break;
  501.     case GDK_j:
  502.     case GDK_J:
  503.       if (hadja_state == 3)
  504.     hadja_state++;
  505.       else
  506.     hadja_state = 0;
  507.       break;
  508.     default:
  509.       hadja_state = 0;
  510.     }
  511.  
  512.   if (hadja_state == 7)
  513.     {
  514.       scroll_text = hadja_text;
  515.       nscroll_texts = sizeof (hadja_text) / sizeof (hadja_text[0]);
  516.       
  517.       for (i = 0; i < nscroll_texts; i++)
  518.     {
  519.       shuffle_array[i] = i;
  520.       scroll_text_widths[i] = gdk_string_width (scroll_area->style->font,
  521.                             scroll_text[i]);
  522.     }
  523.       
  524.       scroll_state = 0;
  525.       cur_scroll_index = 0;
  526.       cur_scroll_text = 0;
  527.       offset = 0;
  528.     }
  529.   
  530.   return FALSE;
  531. }
  532.  
  533. static void
  534. about_dialog_tool_drop (GtkWidget *widget,
  535.             ToolType   tool,
  536.             gpointer   data)
  537. {
  538.   GdkPixmap *pixmap = NULL;
  539.   GdkBitmap *mask   = NULL;
  540.   gint width  = 0;
  541.   gint height = 0;
  542.   gint i;
  543.   
  544.   if (do_animation)
  545.     return;
  546.  
  547.   if (timer)
  548.     gtk_timeout_remove (timer);
  549.  
  550.   timer = gtk_timeout_add (75, about_dialog_timer, NULL);
  551.  
  552.   frame = 0;
  553.   do_animation = TRUE;
  554.   do_scrolling = FALSE;
  555.  
  556.   gdk_draw_rectangle (logo_pixmap,
  557.               logo_area->style->white_gc,
  558.               TRUE,
  559.               0, 0,
  560.               logo_area->allocation.width,
  561.               logo_area->allocation.height);
  562.  
  563.   pixmap =
  564.     gdk_pixmap_create_from_xpm_d (widget->window,
  565.                                   &mask,
  566.                                   NULL,
  567.                                   wilber2_xpm);
  568.  
  569.   gdk_window_get_size (pixmap, &width, &height);
  570.  
  571.   if (logo_area->allocation.width  >= width &&
  572.       logo_area->allocation.height >= height)
  573.     {
  574.       gint x, y;
  575.  
  576.       x = (logo_area->allocation.width  - width) / 2;
  577.       y = (logo_area->allocation.height - height) / 2;
  578.  
  579.       gdk_gc_set_clip_mask (logo_area->style->black_gc, mask);
  580.       gdk_gc_set_clip_origin (logo_area->style->black_gc, x, y);
  581.  
  582.       gdk_draw_pixmap (logo_pixmap,
  583.                        logo_area->style->black_gc,
  584.                        pixmap, 0, 0,
  585.                        x, y,
  586.                        width, height);
  587.  
  588.       gdk_gc_set_clip_mask (logo_area->style->black_gc, NULL);
  589.       gdk_gc_set_clip_origin (logo_area->style->black_gc, 0, 0);
  590.     }
  591.  
  592.   gdk_pixmap_unref (pixmap);
  593.   gdk_bitmap_unref (mask);
  594.  
  595.   scroll_text = drop_text;
  596.   nscroll_texts = sizeof (drop_text) / sizeof (drop_text[0]);
  597.  
  598.   for (i = 0; i < nscroll_texts; i++)
  599.     {
  600.       shuffle_array[i] = i;
  601.       scroll_text_widths[i] = gdk_string_width (scroll_area->style->font,
  602.                         scroll_text[i]);
  603.     }
  604.  
  605.   scroll_state = 0;
  606.   cur_scroll_index = 0;
  607.   cur_scroll_text = 0;
  608.   offset = 0;
  609.  
  610.   double_speed = TRUE;
  611. }
  612.  
  613. static gint
  614. about_dialog_timer (gpointer data)
  615. {
  616.   gint i, j, k;
  617.   gint return_val;
  618.  
  619.   return_val = TRUE;
  620.  
  621.   if (do_animation)
  622.     {
  623.       if (logo_area->allocation.width != 1)
  624.     {
  625.       for (i = 0, k = 0; i < dissolve_height; i++)
  626.         for (j = 0; j < dissolve_width; j++, k++)
  627.           if (frame == dissolve_map[k])
  628.         {
  629.           gdk_draw_pixmap (logo_area->window,
  630.                    logo_area->style->black_gc,
  631.                    logo_pixmap,
  632.                    j * ANIMATION_SIZE, i * ANIMATION_SIZE,
  633.                    j * ANIMATION_SIZE, i * ANIMATION_SIZE,
  634.                    ANIMATION_SIZE, ANIMATION_SIZE);
  635.         }
  636.  
  637.       frame += 1;
  638.  
  639.       if (frame == ANIMATION_STEPS)
  640.         {
  641.           do_animation = FALSE;
  642.           do_scrolling = TRUE;
  643.           frame = 0;
  644.  
  645.           timer = gtk_timeout_add (75, about_dialog_timer, NULL);
  646.  
  647.           return FALSE;
  648.         }
  649.     }
  650.     }
  651.  
  652.   if (do_scrolling)
  653.     {
  654.       if (!scroll_pixmap)
  655.     scroll_pixmap = gdk_pixmap_new (scroll_area->window,
  656.                     scroll_area->allocation.width,
  657.                     scroll_area->allocation.height,
  658.                     -1);
  659.  
  660.       switch (scroll_state)
  661.     {
  662.     case 1:
  663.       scroll_state = 2;
  664.       timer = gtk_timeout_add (700, about_dialog_timer, NULL);
  665.       return_val = FALSE;
  666.       break;
  667.     case 2:
  668.       scroll_state = 3;
  669.       timer = gtk_timeout_add (75, about_dialog_timer, NULL);
  670.       return_val = FALSE;
  671.       break;
  672.     }
  673.  
  674.       if (offset > (scroll_text_widths[cur_scroll_text] +
  675.             scroll_area->allocation.width))
  676.     {
  677.       scroll_state = 0;
  678.       cur_scroll_index += 1;
  679.       if (cur_scroll_index == nscroll_texts)
  680.         cur_scroll_index = 0;
  681.       
  682.       cur_scroll_text = shuffle_array[cur_scroll_index];
  683.  
  684.       offset = 0;
  685.     }
  686.  
  687.       gdk_draw_rectangle (scroll_pixmap,
  688.               scroll_area->style->white_gc,
  689.               TRUE, 0, 0,
  690.               scroll_area->allocation.width,
  691.               scroll_area->allocation.height);
  692.       gdk_draw_string (scroll_pixmap,
  693.                scroll_area->style->font,
  694.                scroll_area->style->black_gc,
  695.                scroll_area->allocation.width - offset,
  696.                scroll_area->style->font->ascent,
  697.                scroll_text[cur_scroll_text]);
  698.       gdk_draw_pixmap (scroll_area->window,
  699.                scroll_area->style->black_gc,
  700.                scroll_pixmap, 0, 0, 0, 0,
  701.                scroll_area->allocation.width,
  702.                scroll_area->allocation.height);
  703.  
  704.       offset += 15;
  705.       if (scroll_state == 0)
  706.     {
  707.       if (offset > ((scroll_area->allocation.width +
  708.              scroll_text_widths[cur_scroll_text]) / 2))
  709.         {
  710.           scroll_state = 1;
  711.           offset = (scroll_area->allocation.width +
  712.             scroll_text_widths[cur_scroll_text]) / 2;
  713.         }
  714.     }
  715.     }
  716.  
  717.   return return_val;
  718. }
  719.