home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / unofficial-plug-ins / DigitalSignature / DigitalSignature.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-23  |  29.3 KB  |  988 lines

  1. /**********************************************************************
  2.  *  Digital Signature Plug-In (Version 1.00)
  3.  *  Daniel Cotting (cotting@mygale.org)
  4.  **********************************************************************
  5.  *  Official homepages: http://www.mygale.org/~cotting
  6.  *                      http://cotting.citeweb.net
  7.  *                      http://village.cyberbrain.com/cotting
  8.  **********************************************************************    
  9.  */
  10.  
  11.  
  12. /* The GIMP -- an image manipulation program
  13.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  14.  *
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2 of the License, or
  18.  * (at your option) any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; if not, write to the Free Software
  27.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <math.h>
  33.  
  34. #include "libgimp/gimp.h"
  35. #include "gtk/gtk.h"
  36. #include "logo.h"
  37.  
  38. #define ENTRY_WIDTH 200
  39.  
  40. typedef struct {
  41.     gint mode;
  42.     gint licence;
  43.     gint contents;
  44.     char signature[50];
  45.     char email[30];
  46.     char homepage[50];
  47.     char date[20];
  48.     gint warningmessage;
  49. } signatureValues;
  50.  
  51. typedef struct {
  52.   gint run;
  53. } signatureInterface;
  54.  
  55.  
  56. /* Declare local functions.
  57.  */
  58. static void query(void);
  59. static void run(char *name, int nparams,
  60.         GParam *param,
  61.         int *nreturn_vals,
  62.         GParam **return_vals);
  63. static void drawsignature(GDrawable *drawable);
  64. static void readsignature(GDrawable *drawable);
  65. static gint signature_dialog(void);
  66. static gint signature_warning_dialog(void);
  67. static gint message_dialog(char *, char *, char *);
  68. GtkWidget * signature_logo_dialog(void);
  69.  
  70.  
  71.  
  72.  
  73. GtkWidget *maindlg;
  74. GtkWidget *logodlg;
  75. GtkTooltips *tips;
  76.  
  77. GPlugInInfo PLUG_IN_INFO =
  78. {
  79.   NULL, /* init_proc */
  80.   NULL, /* quit_proc */
  81.   query, /* query_proc */
  82.   run, /* run_proc */
  83. };
  84.  
  85. static signatureValues wvals = {
  86.         1,0,0,"","","","",1
  87. }; /* wvals */
  88.  
  89. static signatureInterface bint =
  90. {
  91.   FALSE  /*  run  */
  92. };
  93.  
  94.  
  95. MAIN()
  96.  
  97. static void
  98. query(void)
  99. {
  100.   static GParamDef args[] =
  101.   {
  102.     { PARAM_INT32, "run_mode", "Interactive, non-interactive" },
  103.     { PARAM_IMAGE, "image", "Input image (unused)" },
  104.     { PARAM_DRAWABLE, "drawable", "Input drawable" },
  105.     { PARAM_STRING, "signature[50]", "Signature (Name of author, company etc.)" },
  106.     { PARAM_STRING, "e-mail[30]", "e-mail address" },
  107.     { PARAM_STRING, "homepage[50]", "Address of the homepage" },
  108.     { PARAM_STRING, "date[20]", "Date of creation" },
  109.     { PARAM_INT8, "mode", "FALSE: Write signature; TRUE: Read signature" },
  110.     { PARAM_INT8, "licence", "FALSE: Freely distributable; TRUE: Restricted distribution" },
  111.     { PARAM_INT8, "contents", "TRUE: Adult only contents" },
  112.   };
  113.  
  114.   static GParamDef *return_vals = NULL;
  115.   static int nargs = sizeof(args)/ sizeof(args[0]);
  116.   static int nreturn_vals = 0;
  117.  
  118.   gimp_install_procedure("plug_in_signature",
  119.              "Puts a hidden signature on your images.",
  120.              "",
  121.              "Daniel Cotting (cotting@mygale.org, http://www.mygale.org/~cotting)",
  122.              "Daniel Cotting (cotting@mygale.org, http://www.mygale.org/~cotting)",
  123.              "December, 1997",
  124.              "<Image>/Filters/Image/Digital Signature",
  125.              "RGB*, GRAY*, INDEXED*",
  126.              PROC_PLUG_IN,
  127.              nargs, nreturn_vals,
  128.              args, return_vals);
  129. }
  130.  
  131. static void
  132. run(char *name,
  133.     int nparams,
  134.     GParam *param,
  135.     int *nreturn_vals,
  136.     GParam **return_vals)
  137. {
  138.   static GParam values[1];
  139.   GDrawable *drawable;
  140.   GRunModeType run_mode;
  141.   GStatusType status = STATUS_SUCCESS;
  142.   gchar **argv;
  143.   gint argc;
  144.   gint ending=FALSE;
  145.  
  146.   run_mode = param[0].data.d_int32;
  147.  
  148.   values[0].type = PARAM_STATUS;
  149.   values[0].data.d_status = status;
  150.   
  151.   *nreturn_vals = 1;
  152.   *return_vals = values;
  153.   
  154.   drawable = gimp_drawable_get(param[2].data.d_drawable);
  155.  
  156.   switch(run_mode) {
  157.   case RUN_INTERACTIVE:
  158.     /* Possibly retrieve data */
  159.     gimp_get_data("plug_in_signature", &wvals);
  160.     /* Get information from the dialog */
  161.         argc = 1;
  162.         argv = g_new(gchar *, 1);
  163.         argv[0] = g_strdup("apply_signature");
  164.         gtk_init(&argc, &argv);
  165.         gtk_rc_parse(gimp_gtkrc());
  166.     
  167.     ending=signature_dialog();
  168.     
  169.         if (ending==FALSE) return;
  170.         if ((wvals.warningmessage) && (ending!=100))
  171.            if (!signature_warning_dialog())
  172.                return;
  173.            
  174.         if (ending==100) {wvals.mode=1;} else {wvals.mode=0;}
  175.     break;
  176.  
  177.   case RUN_NONINTERACTIVE:
  178.     /* Make sure all the arguments are present */
  179.     if (nparams != 10)
  180.            status = STATUS_CALLING_ERROR;
  181.     if (status == STATUS_SUCCESS)
  182.            wvals.mode = param[3].data.d_int8;
  183.        strncpy (wvals.signature,param[4].data.d_string, 50);
  184.        strncpy (wvals.email,param[5].data.d_string, 30);
  185.        strncpy (wvals.homepage,param[6].data.d_string, 50);
  186.        strncpy (wvals.date,param[7].data.d_string, 20);
  187.        wvals.signature[49]='\0';
  188.            wvals.email[29]='\0';
  189.            wvals.homepage[49]='\0';
  190.            wvals.date[19]='\0';
  191.  
  192.            wvals.licence = param[8].data.d_int8;
  193.            wvals.contents = param[9].data.d_int8;
  194.        argc = 1;
  195.            argv = g_new(gchar *, 1);
  196.            argv[0] = g_strdup("apply_signature");
  197.            gtk_init(&argc, &argv);
  198.            gtk_rc_parse(gimp_gtkrc());
  199.            tips = gtk_tooltips_new ();
  200.  
  201.     break;
  202.   case RUN_WITH_LAST_VALS:
  203.     /* Possibly retrieve data */
  204.        argc = 1;
  205.            argv = g_new(gchar *, 1);
  206.            argv[0] = g_strdup("apply_signature");
  207.            gtk_init(&argc, &argv);
  208.            gtk_rc_parse(gimp_gtkrc());
  209.            tips = gtk_tooltips_new ();
  210.            gimp_get_data("plug_in_signature", &wvals);
  211.     
  212.     break;
  213.   default:
  214.     break;
  215.   }
  216.   if (status == STATUS_SUCCESS) {
  217.     if (!wvals.mode) {
  218.         gimp_tile_cache_ntiles(2 *(drawable->width / gimp_tile_width() + 1));
  219.         gimp_progress_init("Writing signature. Please wait...");
  220.         drawsignature(drawable);
  221.         if(run_mode != RUN_NONINTERACTIVE)
  222.           gimp_displays_flush();
  223.         if(run_mode == RUN_INTERACTIVE)
  224.           gimp_set_data("plug_in_signature", &wvals, sizeof(signatureValues));
  225.         values[0].data.d_status = status;
  226.         gimp_drawable_detach(drawable);
  227.     } else {
  228.         readsignature(drawable);
  229.         if(run_mode == RUN_INTERACTIVE)
  230.           gimp_set_data("plug_in_signature", &wvals, sizeof(signatureValues));
  231.         values[0].data.d_status = status;
  232.         gimp_drawable_detach(drawable);
  233.     }
  234.   }    
  235. }
  236.  
  237. static void
  238. drawsignature(GDrawable *drawable)
  239. {
  240.   GPixelRgn srcPR, destPR;
  241.   gint width, height;
  242.   gint bytes;
  243.   gint row;
  244.   gint x1, y1, x2, y2, ix, iy;
  245.   guchar *src, *dest;
  246.   gint i, col;
  247.   gint value;
  248.   long count=1,smallcount=0;
  249.   gfloat regionwidth, regionheight, dx, dy;
  250.   gfloat a, b, x, y;
  251.   glong pixelpos, pos;
  252.   guchar bgr_red, bgr_blue, bgr_green;
  253.   char *point;
  254.   char *point2;
  255.   int finished_atleast_once=0;
  256.   
  257.   
  258.   typedef struct {
  259.     char header[3];
  260.     char signature[50];
  261.     char email[30];
  262.     char homepage[50];
  263.     char date[20];
  264.     char flags[1];
  265.     char reserved[45];
  266.   } _wholedata;
  267.  
  268.   _wholedata wholedata;
  269.   wvals.signature[49]='\0';
  270.   wvals.email[29]='\0';
  271.   wvals.homepage[49]='\0';
  272.   wvals.date[19]='\0';
  273.   point2=(char*) &wholedata;
  274.   for (i=0;i<200; i++)
  275.   {
  276.     point2[i]='\0';
  277.   }
  278.   strncpy(wholedata.header,"SIG",3);
  279.   strncpy(wholedata.signature,wvals.signature,50);  
  280.   strncpy(wholedata.email,wvals.email,30);  
  281.   strncpy(wholedata.homepage,wvals.homepage,50);  
  282.   strncpy(wholedata.date,wvals.date,20);  
  283.   if (wvals.contents) wholedata.flags[1]|=1;
  284.   if (wvals.licence) wholedata.flags[1]|=2;
  285.     
  286.   gimp_palette_get_background(&bgr_red, &bgr_green, &bgr_blue);
  287.  
  288.   gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
  289.   
  290.   
  291.   regionwidth = x2-x1;
  292.   a = regionwidth/2;
  293.   regionheight = y2-y1;
  294.   b = regionheight/2;
  295.   
  296.   width = drawable->width;
  297.   height = drawable->height;
  298.   bytes = drawable->bpp;
  299.  
  300.   gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  301.   gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
  302.  
  303.   src = g_malloc((x2-x1)*(y2-y1)*bytes);
  304.   dest = g_malloc((x2-x1)*(y2-y1)*bytes);
  305.   gimp_pixel_rgn_get_rect(&srcPR, src, x1, y1, regionwidth, regionheight);
  306.   
  307.   point=(char *)&wholedata;  
  308.   
  309.   
  310.   for(col = 0; col < regionwidth; col++) {
  311.     dx = (gfloat)col - a;
  312.     for(row = 0; row < regionheight; row++) {
  313.           pixelpos = (col+row*regionwidth)*bytes;
  314.           dy = -((gfloat)row - b);
  315.           x = dx+a;
  316.       y = -dy+b;
  317.       ix=(int)x;
  318.       iy=(int)y;
  319.       smallcount++;
  320.       if (smallcount==9) {
  321.          count++;
  322.          point++;
  323.          smallcount=1;
  324.       }
  325.       if ((count % 200)==0)  { point=(char *)&wholedata; finished_atleast_once=1;}
  326.           pos = ((gint)(iy)*regionwidth + (gint)(ix)) * bytes;
  327.           for(i = 0; i < bytes; i++) {
  328.           value = src[pos+i];
  329.           if (point[0]&(1<<(smallcount-1))){
  330.              if (((int)((float)value/2.0))*2==value){
  331.             value+=1;
  332.             if (value==257) { value=255; }
  333.                  }            
  334.           } else {
  335.              if (!(((int)((float)value/2.0))*2==value)){
  336.             value+=1;
  337.             if (value==256) { value=254; }
  338.                  }            
  339.           } 
  340.           dest[pixelpos+i] = value; }    }
  341.     if(((gint)(regionwidth-col) % 5) == 0)
  342.     gimp_progress_update((gdouble)col/(gdouble)regionwidth);
  343.   }
  344.  
  345.   gimp_pixel_rgn_set_rect(&destPR, dest, x1, y1, regionwidth, regionheight);
  346.   g_free(src);
  347.   g_free(dest);
  348.  
  349.   if (!finished_atleast_once) {
  350.      message_dialog("Error", "Could not write signature", "The picture you wanted to process is to small\n"
  351.                                                          "to contain the whole signature information.\n"
  352.                              "Use an image with larger dimensions.");
  353.   } else {
  354.      message_dialog("Signature written successfully", NULL, "\nYour signature has been written\n"
  355.                                                        "successfully! Start the Digital\n"
  356.                                "Signature plug-in once again and\n"
  357.                                "select 'read' to view the hidden\n"
  358.                                "information included in the image.\n");
  359.   }
  360.   gimp_drawable_flush(drawable);
  361.   gimp_drawable_merge_shadow(drawable->id, TRUE);
  362.   gimp_drawable_update(drawable->id, x1, y1,(x2 - x1),(y2 - y1));
  363. }
  364.  
  365. static void
  366. readsignature(GDrawable *drawable)
  367. {
  368.   GPixelRgn srcPR;
  369.   gint width, height;
  370.   gint bytes;
  371.   gint row, value;
  372.   gint x1, y1, x2, y2, ix, iy, i;
  373.   guchar *src;
  374.   gint col, finished_atleast_once=FALSE;
  375.   gfloat regionwidth, regionheight, dx, dy;
  376.   gfloat a, b, x, y;
  377.   glong pixelpos, pos;
  378.   guchar bgr_red, bgr_blue, bgr_green;
  379.   long count=1,smallcount=0;
  380.   char  displaystring[500];
  381.   char * point;
  382.   char *point2;
  383.   typedef struct {
  384.     char header[3];
  385.     char signature[50];
  386.     char email[30];
  387.     char homepage[50];
  388.     char date[20];
  389.     char flags[1];
  390.     char reserved[45];
  391.   } _wholedata;
  392.  
  393.   _wholedata wholedata;
  394.   point2=(char*) &wholedata;
  395.   for (i=0;i<200; i++)
  396.   {
  397.     point2[i]='\0';
  398.   }
  399.  
  400.   gimp_palette_get_background(&bgr_red, &bgr_green, &bgr_blue);
  401.  
  402.   gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
  403.   regionwidth = x2-x1;
  404.   a = regionwidth/2;
  405.   regionheight = y2-y1;
  406.   b = regionheight/2;
  407.   
  408.   width = drawable->width;
  409.   height = drawable->height;
  410.   bytes = drawable->bpp;
  411.  
  412.   gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  413.  
  414.   src = g_malloc((x2-x1)*(y2-y1)*bytes);
  415.   gimp_pixel_rgn_get_rect(&srcPR, src, x1, y1, regionwidth, regionheight);
  416.  
  417.   point=(char *)&wholedata;  
  418.     
  419.   for(col = 0; col < regionwidth; col++) {
  420.     dx = (gfloat)col - a;
  421.     for(row = 0; row < regionheight; row++) {
  422.           pixelpos = (col+row*regionwidth)*bytes;
  423.           dy = -((gfloat)row - b);
  424.           x = dx+a;
  425.       y = -dy+b;
  426.       ix=(int)x;
  427.       iy=(int)y;
  428.           pos = ((gint)(iy)*regionwidth + (gint)(ix)) * bytes;
  429.     
  430.       smallcount++;
  431.       if (smallcount==9) {
  432.          count++;
  433.          point++;
  434.          smallcount=1;
  435.       }
  436.       if ((count % 200)==0) {finished_atleast_once=1; goto fin;}
  437.   
  438.       
  439.           value = src[pos];
  440.               if (!(((int)((float)value/2.0))*2==value)){
  441.                     point[0]|=(1<<(smallcount-1));
  442.              } 
  443.     }
  444.   }
  445. fin:
  446.   g_free(src);
  447.  
  448.   if (!finished_atleast_once) {
  449.      message_dialog("Error", "Could not read signature", "The picture you wanted to process is to small\n"
  450.                                                          "to contain the whole signature information.\n"
  451.                              "Use an image with larger dimensions.");
  452.      return;
  453.   }
  454.   if (strncmp("SIG",wholedata.header,3)) {
  455.      message_dialog("Error", "No signature", "The picture you wanted to process contains\n"
  456.                                              "no signature or the signature has been destroyed\n"
  457.                          "with some image manipulation.");
  458.      return;
  459.   }
  460.   sprintf(displaystring, "----------------------------------\nImage creator:\n%s\n\n"
  461.                          "E-mail address:\n%s\n\n"
  462.              "Internet homepage:\n%s\n\n"
  463.              "Date of creation:\n%s\n\n"
  464.              "Freely distributable:\n%s\n\n"
  465.              "Adult contents:\n%s\n----------------------------------"
  466.                , wholedata.signature
  467.                , wholedata.email
  468.                , wholedata.homepage
  469.                , wholedata.date
  470.                , (wholedata.flags[1] & 2) ? "Yes" : "No"
  471.                , (wholedata.flags[1] & 1) ? "Yes" : "No"
  472.                );   
  473.   
  474.  message_dialog("Signature read successfully", "Image information", displaystring );
  475. }
  476.  
  477. void
  478. signature_close_callback(GtkWidget *widget,  gpointer   data)
  479.   gtk_widget_destroy(maindlg);
  480.   gtk_main_quit();
  481. }
  482.  
  483.  
  484. void
  485. signature_logo_close_callback(GtkWidget *widget,  gpointer   data)
  486.   gtk_main_quit();
  487. }
  488.  
  489. void
  490. signature_ok_callback(GtkWidget *widget, gpointer   data)
  491. {
  492.   bint.run = TRUE;
  493.   gtk_widget_destroy(GTK_WIDGET(data));
  494. }
  495.  
  496. void
  497. signature_ok2_callback(GtkWidget *widget, gpointer   data)
  498. {
  499.   bint.run = 100;
  500.   gtk_widget_destroy(GTK_WIDGET(data));
  501. }
  502.  
  503. void
  504. signature_logo_ok_callback(GtkWidget *widget, gpointer   data)
  505. {
  506.   gtk_widget_set_sensitive (maindlg, TRUE); 
  507.   gtk_widget_destroy(logodlg);
  508. }
  509.  
  510. void
  511. signature_about_callback(GtkWidget *widget, gpointer   data)
  512. {
  513.   gtk_widget_set_sensitive (maindlg, FALSE); 
  514.   signature_logo_dialog();
  515. }
  516.  
  517. static void
  518. toggle_update (GtkWidget *widget,
  519.                gpointer   data)
  520. {
  521.   int *toggle_val;
  522.  
  523.   toggle_val = (int *) data;
  524.  
  525.   if (GTK_TOGGLE_BUTTON (widget)->active)
  526.     *toggle_val = TRUE;
  527.   else
  528.     *toggle_val = FALSE;
  529. }
  530.  
  531. static void
  532. signature_entry1_callback (GtkWidget * widget, gpointer data)
  533. {
  534.   strncpy (wvals.signature, gtk_entry_get_text (GTK_ENTRY (widget)), 50);
  535. }
  536.  
  537. static void
  538. signature_entry2_callback (GtkWidget * widget, gpointer data)
  539. {
  540.   strncpy (wvals.email, gtk_entry_get_text (GTK_ENTRY (widget)), 30);
  541. }
  542. static void
  543. signature_entry3_callback (GtkWidget * widget, gpointer data)
  544. {
  545.   strncpy (wvals.homepage, gtk_entry_get_text (GTK_ENTRY (widget)), 50);
  546. }
  547. static void
  548. signature_entry4_callback (GtkWidget * widget, gpointer data)
  549. {
  550.   strncpy (wvals.date, gtk_entry_get_text (GTK_ENTRY (widget)), 20);
  551. }
  552.  
  553. static void
  554. set_tooltip (GtkTooltips *tooltips, GtkWidget *widget, const char *desc)
  555. {
  556.   if (desc && desc[0])
  557.     gtk_tooltips_set_tip (tooltips, widget, (char *) desc, NULL);
  558. }
  559.  
  560. static gint
  561. signature_dialog()
  562. {
  563.   GtkWidget *dlg;
  564.   GtkWidget *label;
  565.   GtkWidget *entry;
  566.   GtkWidget *button;
  567.   GtkWidget *toggle;
  568.   GtkWidget *frame;
  569.   GtkWidget *vbox;
  570.   GtkWidget *hbox;
  571.   gchar buffer[100];
  572.   
  573.   
  574.   bint.run=FALSE;
  575.   
  576.   dlg = maindlg = gtk_dialog_new();
  577.   gtk_window_set_title(GTK_WINDOW(dlg), "Digital Signature <cotting@mygale.org>");
  578.   gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
  579.   gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  580.                      (GtkSignalFunc)signature_close_callback,
  581.              NULL);
  582.              
  583.              
  584.              
  585.   frame = gtk_frame_new("Settings");
  586.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  587.   gtk_container_border_width(GTK_CONTAINER(frame), 10);
  588.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
  589.   vbox = gtk_vbox_new(FALSE, 5);
  590.   gtk_container_border_width(GTK_CONTAINER(vbox), 10);
  591.   gtk_container_add(GTK_CONTAINER(frame), vbox);
  592.  
  593.   tips = gtk_tooltips_new ();
  594.   
  595.   hbox = gtk_hbox_new(FALSE, 5);
  596.   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  597.  
  598.   
  599.   label = gtk_label_new("Signature: ");
  600.   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  601.   gtk_widget_show(label);
  602.  
  603.   entry = gtk_entry_new();
  604.   gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
  605.   gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
  606.   sprintf(buffer, "%s", wvals.signature);
  607.   gtk_entry_set_text(GTK_ENTRY(entry), buffer);
  608.   
  609.   gtk_signal_connect(GTK_OBJECT(entry), "changed",
  610.              (GtkSignalFunc)signature_entry1_callback,
  611.              NULL); 
  612.   gtk_widget_show(entry);
  613.   set_tooltip(tips,entry,"Here you can specify your signature (name of author, company etc.)");
  614.  
  615.   gtk_widget_show(hbox);
  616.   
  617.   hbox = gtk_hbox_new(FALSE, 5);
  618.   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  619.  
  620.   label = gtk_label_new("E-mail: ");
  621.   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  622.   gtk_widget_show(label);
  623.  
  624.   entry = gtk_entry_new();
  625.   gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
  626.   gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
  627.   sprintf(buffer, "%s", wvals.email);
  628.   gtk_entry_set_text(GTK_ENTRY(entry), buffer);
  629.   gtk_signal_connect(GTK_OBJECT(entry), "changed",
  630.               (GtkSignalFunc)signature_entry2_callback,
  631.              NULL); 
  632.   gtk_widget_show(entry);
  633.   set_tooltip(tips,entry,"Here you can specify an e-mail address, where the author/company can be contacted.");
  634.  
  635.   gtk_widget_show(hbox);
  636.   
  637.   hbox = gtk_hbox_new(FALSE, 5);
  638.   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  639.  
  640.   label = gtk_label_new("Internet address: ");
  641.   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  642.   gtk_widget_show(label);
  643.  
  644.   entry = gtk_entry_new();
  645.   gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
  646.   gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
  647.   sprintf(buffer, "%s", wvals.homepage);
  648.   gtk_entry_set_text(GTK_ENTRY(entry), buffer);
  649.   gtk_signal_connect(GTK_OBJECT(entry), "changed",
  650.               (GtkSignalFunc)signature_entry3_callback,
  651.              NULL); 
  652.   gtk_widget_show(entry);
  653.   set_tooltip(tips,entry,"Here you can specify an internet address, where the homepage of the author/company can be found.");
  654.  
  655.   gtk_widget_show(hbox);
  656.   
  657.   hbox = gtk_hbox_new(FALSE, 5);
  658.   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
  659.  
  660.   label = gtk_label_new("Date of creation: ");
  661.   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
  662.   gtk_widget_show(label);
  663.  
  664.   entry = gtk_entry_new();
  665.   gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
  666.   gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
  667.   sprintf(buffer, "%s", wvals.date);
  668.   gtk_entry_set_text(GTK_ENTRY(entry), buffer);
  669.   gtk_signal_connect(GTK_OBJECT(entry), "changed",
  670.               (GtkSignalFunc)signature_entry4_callback,
  671.              NULL); 
  672.   gtk_widget_show(entry);
  673.   set_tooltip(tips,entry,"Here you can specify the date, when the image was created.");
  674.  
  675.   gtk_widget_show(hbox);
  676.  
  677.   toggle = gtk_check_button_new_with_label ("Restricted image distribution");
  678.   gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
  679.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  680.               (GtkSignalFunc) toggle_update,
  681.               &wvals.licence);
  682.   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (toggle), wvals.licence);
  683.   gtk_widget_show (toggle);
  684.   set_tooltip(tips,toggle,"If this option is enabled, a flag will be set, that the image is not freely distributable.");
  685.  
  686.   toggle = gtk_check_button_new_with_label ("Adult contents");
  687.   gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
  688.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  689.               (GtkSignalFunc) toggle_update,
  690.               &wvals.contents);
  691.   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (toggle), wvals.contents);
  692.   gtk_widget_show (toggle);
  693.   set_tooltip(tips,toggle,"If this option is enabled, a flag will be set, that the contents of the image should only be accessible to adults.");
  694.  
  695.   gtk_widget_show(vbox);
  696.   gtk_widget_show(frame);
  697.  
  698.   button = gtk_button_new_with_label("Write");
  699.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  700.   gtk_signal_connect(GTK_OBJECT(button), "clicked",
  701.                      (GtkSignalFunc)signature_ok_callback,
  702.              dlg);
  703.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  704.              button, TRUE, TRUE, 0);
  705.   gtk_widget_grab_default(button);
  706.   gtk_widget_show(button);
  707.  
  708.   set_tooltip(tips,button,"Close the dialog box and write signature.");
  709.   
  710.   button = gtk_button_new_with_label("Read");
  711.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  712.   gtk_signal_connect(GTK_OBJECT(button), "clicked",
  713.                      (GtkSignalFunc)signature_ok2_callback,
  714.              dlg);
  715.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  716.              button, TRUE, TRUE, 0);
  717.   gtk_widget_show(button);
  718.  
  719.   set_tooltip(tips,button,"Close the dialog box and read signature.");
  720.  
  721.   button = gtk_button_new_with_label("Cancel");
  722.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  723.   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
  724.                             (GtkSignalFunc)gtk_widget_destroy,
  725.                 GTK_OBJECT(dlg));
  726.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  727.              button, TRUE, TRUE, 0);
  728.   gtk_widget_show(button);
  729.   set_tooltip(tips,button,"Close the dialog box without reading or writing a signature.");
  730.  
  731.   button = gtk_button_new_with_label("About...");
  732.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  733.   gtk_signal_connect(GTK_OBJECT(button), "clicked",
  734.                      (GtkSignalFunc)signature_about_callback,button);
  735.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  736.              button, TRUE, TRUE, 0);
  737.   gtk_widget_show(button);
  738.   set_tooltip(tips,button,"Show information about the author and the plug-in.");
  739.  
  740.   gtk_widget_show(dlg);
  741.  
  742.   gtk_main();
  743.   gdk_flush(); 
  744.  
  745.   return bint.run;
  746. }
  747.  
  748. static gint
  749. message_dialog(char * title, char *title2, char * text)
  750. {
  751.   GtkWidget *dlg;
  752.   GtkWidget *label;
  753.   GtkWidget *button;
  754.   GtkWidget *frame;
  755.   GtkWidget *vbox;
  756.   GtkWidget *hbox;
  757.   bint.run=FALSE;
  758.  
  759.   dlg = gtk_dialog_new();
  760.  
  761.   gtk_window_set_title(GTK_WINDOW(dlg), title);
  762.   gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
  763.   gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  764.                      (GtkSignalFunc)signature_close_callback,
  765.              NULL);
  766.  
  767.  
  768.   button = gtk_button_new_with_label("OK");
  769.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  770.   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
  771.                             (GtkSignalFunc)gtk_widget_destroy,
  772.                 GTK_OBJECT(dlg));
  773.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  774.              button, TRUE, TRUE, 0);
  775.   gtk_widget_show(button);
  776.   set_tooltip(tips,button,"Close this message box and continue");
  777.  
  778.   frame = gtk_frame_new(title2);
  779.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  780.   gtk_container_border_width(GTK_CONTAINER(frame), 10);
  781.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
  782.   vbox = gtk_vbox_new(FALSE, 5);
  783.   gtk_container_border_width(GTK_CONTAINER(vbox), 10);
  784.   gtk_container_add(GTK_CONTAINER(frame), vbox);
  785.  
  786.  
  787.   hbox = gtk_hbox_new(FALSE, 5);
  788.   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  789.  
  790.   label = gtk_label_new(text);
  791.   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
  792.   gtk_widget_show(label);
  793.  
  794.   gtk_widget_show(hbox);
  795.  
  796.   gtk_widget_show(vbox);
  797.   gtk_widget_show(frame);
  798.   gtk_widget_show(dlg);
  799.  
  800.   gtk_main();
  801.   gdk_flush();
  802.   return 0;
  803. }
  804.  
  805.  
  806.  
  807. static gint
  808. signature_warning_dialog()
  809. {
  810.   GtkWidget *dlg;
  811.   GtkWidget *label;
  812.   GtkWidget *button;
  813.   GtkWidget *toggle;
  814.   GtkWidget *frame;
  815.   GtkWidget *vbox;
  816.   GtkWidget *hbox;
  817.   bint.run=FALSE;
  818.  
  819.   dlg = gtk_dialog_new();
  820.   gtk_window_set_title(GTK_WINDOW(dlg), "Warning");
  821.   gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
  822.   gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  823.                      (GtkSignalFunc)signature_close_callback,
  824.              NULL);
  825.  
  826.   button = gtk_button_new_with_label("OK");
  827.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  828.   gtk_signal_connect(GTK_OBJECT(button), "clicked",
  829.                      (GtkSignalFunc)signature_ok_callback,
  830.              dlg);
  831.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  832.              button, TRUE, TRUE, 0);
  833.   gtk_widget_grab_default(button);
  834.   gtk_widget_show(button);
  835.   set_tooltip(tips,button,"Proceed with writing the signature.");
  836.  
  837.   button = gtk_button_new_with_label("Cancel");
  838.   GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  839.   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
  840.                             (GtkSignalFunc)gtk_widget_destroy,
  841.                 GTK_OBJECT(dlg));
  842.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
  843.              button, TRUE, TRUE, 0);
  844.   gtk_widget_show(button);
  845.   set_tooltip(tips,button,"Cancel the writing of signature.");
  846.  
  847.   frame = gtk_frame_new("Please note:");
  848.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  849.   gtk_container_border_width(GTK_CONTAINER(frame), 10);
  850.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
  851.   vbox = gtk_vbox_new(FALSE, 5);
  852.   gtk_container_border_width(GTK_CONTAINER(vbox), 10);
  853.   gtk_container_add(GTK_CONTAINER(frame), vbox);
  854.  
  855.  
  856.   hbox = gtk_hbox_new(FALSE, 5);
  857.   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  858.  
  859.   label = gtk_label_new("Sensitive Signature Warning:\n\n"
  860.                         "Remember to save your image in a non-destructive format!\n"
  861.             "For indexed images GIF could be a good choice, for RGB\n"
  862.             "use BMP/TIFF/TGA etc. Never use a JPEG-compression!\n\n"
  863.             "You shouldn't apply any filter to the image after the\n"
  864.             "signature has been written. No blur/constrast etc.\n\n"
  865.             "This restriction will hopefully be removed in a future\n"
  866.             "version of the plug-in (available at cotting.citeweb.net)\n");
  867.   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
  868.   gtk_widget_show(label);
  869.  
  870.   toggle = gtk_check_button_new_with_label ("Show warning message every time");
  871.   gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
  872.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  873.               (GtkSignalFunc) toggle_update,
  874.               &wvals.warningmessage);
  875.   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (toggle), wvals.warningmessage);
  876.   gtk_widget_show (toggle);
  877.   set_tooltip(tips,toggle,"If you want this message to be displayed every time you write a signature, then check this box.");
  878.  
  879.   gtk_widget_show(hbox);
  880.  
  881.   gtk_widget_show(vbox);
  882.   gtk_widget_show(frame);
  883.   gtk_widget_show(dlg);
  884.  
  885.   gtk_main();
  886.   gdk_flush();
  887.  
  888.   return bint.run;
  889. }
  890.  
  891. GtkWidget * 
  892. signature_logo_dialog()
  893. {
  894.   GtkWidget *xdlg;
  895.   GtkWidget *xlabel;
  896.   GtkWidget *xbutton;
  897.   GtkWidget *xlogo_box;
  898.   GtkWidget *xpreview;
  899.   GtkWidget *xframe,*xframe2;
  900.   GtkWidget *xvbox;
  901.   GtkWidget *xhbox;
  902.   char *text;
  903.   guchar *temp,*temp2;
  904.   guchar *datapointer;
  905.   gint y,x;
  906.   xdlg = logodlg = gtk_dialog_new();
  907.   gtk_window_set_title(GTK_WINDOW(xdlg), "About");
  908.   gtk_window_position(GTK_WINDOW(xdlg), GTK_WIN_POS_MOUSE);
  909.   
  910.   gtk_signal_connect(GTK_OBJECT(xdlg), "destroy",
  911.                      (GtkSignalFunc)signature_logo_close_callback,
  912.              NULL);
  913.  
  914.   xbutton = gtk_button_new_with_label("OK");
  915.   GTK_WIDGET_SET_FLAGS(xbutton, GTK_CAN_DEFAULT);
  916.   gtk_signal_connect(GTK_OBJECT(xbutton), "clicked",
  917.                      (GtkSignalFunc)signature_logo_ok_callback,
  918.              xdlg);
  919.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(xdlg)->action_area),
  920.              xbutton, TRUE, TRUE, 0);
  921.   gtk_widget_grab_default(xbutton);
  922.   gtk_widget_show(xbutton);
  923.   set_tooltip(tips,xbutton,"Click here to close the information box.");
  924.  
  925.   xframe = gtk_frame_new(NULL);
  926.   gtk_frame_set_shadow_type(GTK_FRAME(xframe), GTK_SHADOW_ETCHED_IN);
  927.   gtk_container_border_width(GTK_CONTAINER(xframe), 10);
  928.   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(xdlg)->vbox), xframe, TRUE, TRUE, 0);
  929.   xvbox = gtk_vbox_new(FALSE, 5);
  930.   gtk_container_border_width(GTK_CONTAINER(xvbox), 10);
  931.   gtk_container_add(GTK_CONTAINER(xframe), xvbox);
  932.  
  933.   /*  The logo frame & drawing area  */
  934.   xhbox = gtk_hbox_new (FALSE, 5);
  935.   gtk_box_pack_start (GTK_BOX (xvbox), xhbox, FALSE, TRUE, 0);
  936.  
  937.   xlogo_box = gtk_vbox_new (FALSE, 0);
  938.   gtk_box_pack_start (GTK_BOX (xhbox), xlogo_box, FALSE, FALSE, 0);
  939.  
  940.   xframe2 = gtk_frame_new (NULL);
  941.   gtk_frame_set_shadow_type (GTK_FRAME (xframe2), GTK_SHADOW_IN);
  942.   gtk_box_pack_start (GTK_BOX (xlogo_box), xframe2, FALSE, FALSE, 0);
  943.  
  944.   xpreview = gtk_preview_new (GTK_PREVIEW_COLOR);
  945.   gtk_preview_size (GTK_PREVIEW (xpreview), logo_width, logo_height);
  946.   temp = g_malloc((logo_width+10)*3);
  947.   datapointer=header_data+logo_width*logo_height-1;
  948.   for (y = 0; y < logo_height; y++){
  949.     temp2=temp;
  950.     for (x = 0; x< logo_width; x++) {
  951.       HEADER_PIXEL(datapointer,temp2); temp2+=3;}
  952.     gtk_preview_draw_row (GTK_PREVIEW (xpreview),
  953.               temp,
  954.               0, y, logo_width); 
  955.   }              
  956.   g_free(temp);
  957.   gtk_container_add (GTK_CONTAINER (xframe2), xpreview);
  958.   gtk_widget_show (xpreview);
  959.   gtk_widget_show (xframe2);
  960.   gtk_widget_show (xlogo_box);
  961.   gtk_widget_show (xhbox);
  962.  
  963.   xhbox = gtk_hbox_new(FALSE, 5);
  964.   gtk_box_pack_start(GTK_BOX(xvbox), xhbox, TRUE, TRUE, 0);
  965.   text = "\nCotting Software Productions\n"
  966.          "Bahnhofstrasse 31\n"
  967.        "CH-3066 Stettlen (Switzerland)\n\n"
  968.      "cotting@mygale.org\n"
  969.      "http://www.mygale.org/~cotting\n\n"
  970.           "Digital Signature\n Plug-In for the GIMP\n"
  971.           "Version 1.00\n";
  972.   xlabel = gtk_label_new(text);
  973.   gtk_box_pack_start(GTK_BOX(xhbox), xlabel, TRUE, FALSE, 0);
  974.   gtk_widget_show(xlabel);
  975.  
  976.   gtk_widget_show(xhbox);
  977.  
  978.   gtk_widget_show(xvbox);
  979.   gtk_widget_show(xframe);
  980.   gtk_widget_show(xdlg);
  981.  
  982.   gtk_main();
  983.   gdk_flush();
  984.   return xdlg;
  985. }
  986.