Logo Search packages:      
Sourcecode: libjsw version File versions

pdialog.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "guiutils.h"

#include "pdialog.h"

#ifdef MEMWATCH
# include "memwatch.h"
#endif


/* Message icons. */
#include "images/icon_error_32x32.xpm"
#include "images/icon_info_32x32.xpm"
#include "images/icon_question_32x32.xpm"
#include "images/icon_warning_32x32.xpm"

/* Button icons. */
#include "images/icon_browse_20x20.xpm"
#include "images/icon_ok_20x20.xpm"
#include "images/icon_cancel_20x20.xpm"
#include "images/icon_help_20x20.xpm"


/* Prompt dialog's prompt structure. */
typedef struct {

        GtkWidget       *toplevel,      /* A table. */
                        *icon_pm,
                        *icon_fixed,
                        *label,
                        *entry,         /* Can be NULL. */
                        *browse_btn,    /* Can be NULL. */
                        *spin,          /* Can be NULL. */
                        *scale;         /* Can be NULL. */

        GtkAdjustment   *scale_adj;
  
      gpointer client_data;

        /* Args: prompt dialog, client data, prompt number. */
      gchar *(*browse_cb)(gpointer, gpointer, gint);

} pdialog_prompt_struct;

/* Prompt dialog structure. */
typedef struct {

        gbool initialized;
        gbool map_state;
        gint last_icon_code;

        GtkAccelGroup   *accelgrp;

        GtkWidget       *toplevel,
                        *main_vbox,     /* For holding the prompts. */
                        *icon_pm,
                        *icon_fixed;

        pdialog_prompt_struct **prompt;
        gint total_prompts;

        GtkWidget       *submit_btn,
                        *submit_btn_label,
                        *cancel_btn,
                        *cancel_btn_label,
                        *help_btn;

} pdialog_struct;


/* Callbacks. */
static void PDialogDestroyCB(GtkObject *object, gpointer data);
static gint PDialogCloseCB(
      GtkWidget *widget, GdkEvent *event, gpointer data
);
static void PDialogBrowseButtonCB(GtkWidget *widget, gpointer data);
static void PDialogButtonCB(GtkWidget *widget, gpointer data);

/* Private utils. */
static void PDialogSetIcon(pdialog_struct *d, u_int8_t **icon_data);
static pdialog_prompt_struct *PDialogPromptNew(
      const u_int8_t **icon_data,
      const gchar *label,
      const gchar *value,
      pdialog_struct *d
);
static pdialog_prompt_struct *PDialogPromptNewWithBrowse(
      const u_int8_t **icon_data,
      const gchar *label,
      const gchar *value,
      pdialog_struct *d,
      gpointer client_data,
        gchar *(*browse_cb)(gpointer, gpointer, gint)
);
static void PDialogPromptDelete(pdialog_prompt_struct *p);

/* Public. */
gint PDialogInit(void);
gbool PDialogIsQuery(void);
void PDialogBreakQuery(void);
void PDialogAddPrompt(
        const u_int8_t **icon_data, /* Can be NULL. */
        const gchar *label,         /* Can be NULL. */
        const gchar *value          /* Can be NULL. */
);
void PDialogAddPromptWithBrowse(
        const u_int8_t **icon_data, /* Can be NULL. */
        const gchar *label,         /* Can be NULL. */
        const gchar *value,         /* Can be NULL. */
        gpointer client_data,       /* Can be NULL. */
        gchar *(*browse_cb)(gpointer, gpointer, gint) /* Can be NULL. */
);
void PDialogSetPromptValue(
        gint prompt_num,
        const u_int8_t **icon_data,
        const gchar *label,
        const gchar *value
);
gchar *PDialogGetPromptValue(gint prompt_num);
void PDialogDeleteAllPrompts(void);
gchar **PDialogGetResponse(
      const gchar *title,
        const gchar *message,
        const gchar *explaination,
        gint icon_code,
        const gchar *submit_label,
        const gchar *cancel_label,
        guint show_buttons,   /* Any of PDIALOG_BTNFLAG_*. */
        guint default_button, /* One of PDIALOG_BTNFLAG_*. */
        gint *nvalues
);
void PDialogSetSize(gint width, gint height);
void PDialogMap(void);
void PDialogUnmap(void);
void PDialogShutdown(void);


#define PDIALOG_BTN_WIDTH     (100 + (2 * 3))
#define PDIALOG_BTN_HEIGHT    (30 + (2 * 3))

#define PDIALOG_ENTRY_MAX     256


static gint response_code = PDIALOG_RESPONSE_NOT_AVAILABLE;
static gint block_loop_level;
static gchar **response_val = NULL;
static gint response_nvals = 0;
static pdialog_struct pdialog;


/*
 *    Destroy callback.
 */
static void PDialogDestroyCB(GtkObject *object, gpointer data)
{
      return;
}

/*
 *    Dialog close callback.
 */
static gint PDialogCloseCB(
      GtkWidget *widget, GdkEvent *event, gpointer data
)
{
        pdialog_struct *d = (pdialog_struct *)data;
        if((widget == NULL) || (d == NULL))
            return(TRUE);

      response_code = PDIALOG_RESPONSE_CANCEL;
        gtk_main_quit();
      block_loop_level--;

      return(TRUE);
}

/*
 *    Dialog browse button callback.
 */
static void PDialogBrowseButtonCB(GtkWidget *widget, gpointer data)
{
      gint i;
      GtkWidget *w;
      const gchar *cstrptr;
      pdialog_prompt_struct *p;
        pdialog_struct *d = (pdialog_struct *)data;
        if((widget == NULL) || (d == NULL))
            return;

      /* Check which browse button was pressed. */
      for(i = 0; i < d->total_prompts; i++)
      {
          p = d->prompt[i];
          if(p == NULL)
            continue;

          if(widget != p->browse_btn)
              continue;

          if(p->browse_cb != NULL)
          {
            cstrptr = (const gchar *)p->browse_cb(
                d,                  /* Prompt dialog. */
                p->client_data,     /* Client data. */
                i             /* Prompt number. */
            );
            w = p->entry;
            if((w != NULL) && (cstrptr != NULL))
                gtk_entry_set_text(GTK_ENTRY(w), cstrptr);
          }
          break;
      }
}

/*
 *      Dialog prompt entry enter callback.
 */
static void PDialogEntryEnterCB(GtkWidget *widget, gpointer data)
{
        pdialog_struct *d = (pdialog_struct *)data;
        if((widget == NULL) || (d == NULL))
            return;

      /* Call button callback and pass submit button as the widget. */
      PDialogButtonCB(d->submit_btn, d);

      return;
}

/*
 *    Dialog button (not browse buttons) callback.
 */
static void PDialogButtonCB(GtkWidget *widget, gpointer data)
{
      pdialog_struct *d = (pdialog_struct *)data;
      if((widget == NULL) || (d == NULL))
          return;

      if(widget == d->submit_btn)
      {
          gint i;


          response_code = PDIALOG_RESPONSE_SUBMIT;

          /* Clear responses values list if any. */
          for(i = 0; i < response_nvals; i++)
            g_free(response_val[i]);
          g_free(response_val);
          response_val = NULL;
          response_nvals = 0;

          /* Fetch values from each prompt and copy them to local
             * global response_val. Number of response values is
           * the number of prompts on the dialog.
             */
          response_nvals = d->total_prompts;
          response_val = (gchar **)g_malloc0(
            response_nvals * sizeof(gchar *)
          );
          if(response_val == NULL)
          {
            response_nvals = 0;
          }
          else
          {
            pdialog_prompt_struct *p;

            /* Fetch values for each response value, thus going
             * through each prompt.
             */
            for(i = 0; i < response_nvals; i++)
            {
                p = d->prompt[i];
                if(p == NULL)
                {
                  response_val[i] = g_strdup("");
                }
                else
                {
                  const gchar *cstrptr = NULL;
                  GtkWidget *w = p->entry;

                  if(w != NULL)
                      cstrptr = (const gchar *)gtk_entry_get_text(GTK_ENTRY(w));
                  if(cstrptr == NULL)
                      cstrptr = "";

                  response_val[i] = g_strdup(cstrptr);
                }
            }
          }

      }
        else if(widget == d->cancel_btn)
      {
            response_code = PDIALOG_RESPONSE_CANCEL;
      }
        else if(widget == d->help_btn)
      {
          response_code = PDIALOG_RESPONSE_HELP;
          return; /* Return, do not break out of block loop. */
      }

      /* Need to break out of the blocked loop. */
      gtk_main_quit();
      block_loop_level--;
}


/*
 *    Updates the icon for the dialog. Updates the member icon_pm
 *    as needed.
 */
static void PDialogSetIcon(pdialog_struct *d, u_int8_t **icon_data)
{
        GdkGC *gc;
        GtkWidget *w, *window, *pixmap;
        GdkPixmap *gdk_pixmap;
        GdkBitmap *mask;
        GtkStyle *style;
        gint width, height;


        if((d == NULL) || (icon_data == NULL))
            return;

        w = d->icon_fixed;
        if(w == NULL)
            return;

        window = d->toplevel;
        if(window == NULL)
            return;

        style = gtk_widget_get_default_style();
        gc = style->black_gc;


        /* Create new pixmap. */
        gdk_pixmap = gdk_pixmap_create_from_xpm_d(
            window->window,
            &mask,
            &style->bg[GTK_STATE_NORMAL],
            (gchar **)icon_data
        );
        pixmap = gtk_pixmap_new(gdk_pixmap, mask);
        gdk_window_get_size((GdkWindow *)gdk_pixmap, &width, &height);

        /* Adjust size of fixed widget to fit pixmap. */
        gtk_widget_set_usize(w, width, height);

        /* Put pixmap into fixed widget. */
        gtk_fixed_put(GTK_FIXED(w), pixmap, 0, 0);
      gtk_widget_shape_combine_mask(w, mask, 0, 0);
        gtk_widget_show(pixmap);

      gdk_pixmap_unref(gdk_pixmap);
      if(mask != NULL)
          gdk_bitmap_unref(mask);
      /* From here on gdk_pixmap and mask are invalid. */

        /* Destroy the previous GtkPixmap icon. */
        if(d->icon_pm != NULL)
            gtk_widget_destroy(d->icon_pm);

      /* Record new GtkPixmap as the icon. */
        d->icon_pm = pixmap;


        /* Set new WM icon for toplevel. */
        GUISetWMIcon(window->window, icon_data);                    
}


/*
 *    Allocates and creates a new prompt structure, but does not
 *    add it to the prompt dialog.
 */
static pdialog_prompt_struct *PDialogPromptNew(
      const u_int8_t **icon_data,
      const gchar *label,
        const gchar *value,
        pdialog_struct *d
)
{
      return(
          PDialogPromptNewWithBrowse(
            icon_data, label, value, d, NULL, NULL
          )
      );
}

/*
 *    Allocates and creates a new prompt structure, but does not 
 *      add it to the prompt dialog.
 */
static pdialog_prompt_struct *PDialogPromptNewWithBrowse(
      const u_int8_t **icon_data,
        const gchar *label,
        const gchar *value,
      pdialog_struct *d,
      gpointer client_data,
        gchar *(*browse_cb)(gpointer, gpointer, gint)
)
{
        GtkWidget *w, *parent;
      GdkWindow *window = NULL;
        pdialog_prompt_struct *p = (pdialog_prompt_struct *)g_malloc0(
            sizeof(pdialog_prompt_struct)
        );
        if(p == NULL)
            return(p);

      /* Get window of dialog toplevel. */
      w = d->toplevel;
      if(w != NULL)
      {
          if(!GTK_WIDGET_NO_WINDOW(w))
            window = w->window;
      }

      /* Create main toplevel table, give the number of columns
       * depending on which widgets have been specified to be created.
       */
      w = gtk_table_new(
          1,
          MAX(
                ((icon_data == NULL) ? 0 : 1) +
            ((label == NULL) ? 0 : 1) +
            (1) +
                ((browse_cb == NULL) ? 0 : 1),
            1
          ),
          FALSE
      );
        p->toplevel = w;
      /* Do not show toplevel just yet. */
        parent = w;

      /* Create icon? */
      if(icon_data != NULL)
      {
            gint attach_x = 0;
            GdkGC *gc;
            GtkWidget *pixmap;
            GdkPixmap *gdk_pixmap;
            GdkBitmap *mask;
            GtkStyle *style;
            gint width, height;

          /* Create fixed widget. */
          w = gtk_fixed_new();
          p->icon_fixed = w;
            gtk_table_attach(GTK_TABLE(parent), w,
                attach_x, attach_x + 1,
                0, 1,
                0,
                0,
                2, 0
            );
            gtk_widget_show(w);

          /* Get style from dialog toplevel. */
          if(d->toplevel == NULL)
            style = gtk_widget_get_default_style();
          else
            style = gtk_widget_get_style(d->toplevel);

          if(style != NULL)
            gc = style->black_gc;

          /* Create the pixmap. */
          gdk_pixmap = gdk_pixmap_create_from_xpm_d(
            window,
            &mask,
            ((style == NULL) ? NULL : &style->bg[GTK_STATE_NORMAL]),
            (gchar **)icon_data  
          );
          pixmap = gtk_pixmap_new(gdk_pixmap, mask);
          gdk_window_get_size((GdkWindow *)gdk_pixmap, &width, &height);

          /* Adjust size of fixed widget to fit pixmap. */
          gtk_widget_set_usize(w, width, height);

          /* Put pixmap into fixed widget. */
          gtk_fixed_put(GTK_FIXED(w), pixmap, 0, 0);
            gtk_widget_shape_combine_mask(w, mask, 0, 0);
            gtk_widget_show(pixmap);

            gdk_pixmap_unref(gdk_pixmap);
            if(mask != NULL)
                gdk_bitmap_unref(mask);

          /* Record new pixmap. */
          p->icon_pm = pixmap;
      }

      /* Create label? */
        if(label != NULL)
        {
          gint attach_x = ((icon_data == NULL) ? 0 : 1);

            w = gtk_label_new(label);
            p->label = w; 
            gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT);
            gtk_table_attach(GTK_TABLE(parent), w,
                attach_x, attach_x + 1,
                0, 1,
                0,
                0,
                2, 0
            );
            gtk_widget_show(w);
        }
 
      /* Text entry. */
      if(1)
      {
          gint attach_x = ((icon_data == NULL) ? 0 : 1) +
                           ((label == NULL) ? 0 : 1);

            w = gtk_entry_new_with_max_length(PDIALOG_ENTRY_MAX);
            p->entry = w;
          if(value != NULL)
              gtk_entry_set_text(GTK_ENTRY(w), value);
            gtk_signal_connect(
                GTK_OBJECT(w), "activate",
                GTK_SIGNAL_FUNC(PDialogEntryEnterCB),
                d       /* Pass the dialog structure. */
            );
            gtk_table_attach(GTK_TABLE(parent), w,
                attach_x, attach_x + 1,
                0, 1,
                GTK_FILL | GTK_SHRINK | GTK_EXPAND,
                0,
                2, 0
            );
            gtk_widget_show(w);
      }

      /* Create browse button? */
      if(browse_cb != NULL)
      {
            gint attach_x = ((icon_data == NULL) ? 0 : 1) +
                           ((label == NULL) ? 0 : 1) +
                     (1);

          /* Set browse callback function and client data. */
          p->client_data = client_data;
          p->browse_cb = browse_cb;

          /* Create browse button. */
          w = GUIButtonPixmap((u_int8_t **)icon_browse_20x20_xpm);
          p->browse_btn = w;
            gtk_signal_connect(
                GTK_OBJECT(w), "clicked",
                GTK_SIGNAL_FUNC(PDialogBrowseButtonCB),
                d       /* Pass the dialog structure. */
            );
            gtk_table_attach(GTK_TABLE(parent), w,
                attach_x, attach_x + 1,
                0, 1,
                0,
                0,
                2, 0
            );
            gtk_widget_show(w);
      }

        return(p); 
}

/*
 *    Deletes all widgets in the prompt structure and deallocates
 *    the prompt structure itself.
 */
static void PDialogPromptDelete(pdialog_prompt_struct *p)
{
      GtkWidget **w;


      if(p == NULL)
          return;

#define DO_DESTROY_WIDGET     \
{ \
 if((*w) != NULL) \
 { \
  gtk_widget_destroy(*w); \
  (*w) = NULL; \
 } \
}

        w = &p->scale;
        DO_DESTROY_WIDGET

        w = &p->spin;
        DO_DESTROY_WIDGET

        w = &p->browse_btn;
      DO_DESTROY_WIDGET

        w = &p->entry;
        DO_DESTROY_WIDGET  

        w = &p->label;
        DO_DESTROY_WIDGET  

        w = &p->icon_pm;
        DO_DESTROY_WIDGET

        w = &p->icon_fixed;
        DO_DESTROY_WIDGET

        w = &p->toplevel;
        DO_DESTROY_WIDGET

#undef DO_DESTROY_WIDGET

      g_free(p);
}


/*
 *    Initializes the prompt dialog.
 */
gint PDialogInit(void)
{
      gint border_major = 2;
      gpointer label_rtn;
      GtkWidget *w, *parent, *parent2, *parent3;
      GdkWindow *window;
        GtkAccelGroup *accelgrp;
        pdialog_struct *d = &pdialog;


        /* Reset globals. */
      response_code = PDIALOG_RESPONSE_NOT_AVAILABLE;
      block_loop_level = 0;
      response_val = NULL;
      response_nvals = 0;


      /* Reset values. */
      memset(d, 0x00, sizeof(pdialog_struct));

      d->initialized = TRUE;
      d->map_state = FALSE;
      d->last_icon_code = PDIALOG_ICON_QUESTION;

        /* Keyboard accelerator group. */
        d->accelgrp = accelgrp = gtk_accel_group_new();

        /* Toplevel. */
      d->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
        gtk_widget_realize(w);
        window = w->window;
        if(window != NULL)
        {
            gdk_window_set_decorations(
                window,
                GDK_DECOR_TITLE | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE
            );
            gdk_window_set_functions(
                window,
                GDK_FUNC_MOVE | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE
            );
        }
        gtk_signal_connect(
            GTK_OBJECT(w), "destroy",
            GTK_SIGNAL_FUNC(PDialogDestroyCB),
            (gpointer)d
        );
      gtk_signal_connect(
            GTK_OBJECT(w), "delete_event",
            GTK_SIGNAL_FUNC(PDialogCloseCB),
            (gpointer)d
        );
        gtk_container_set_border_width(GTK_CONTAINER(w), 0);
        gtk_accel_group_attach(accelgrp, GTK_OBJECT(w));
        parent = w;


      /* Vbox. */
      w = gtk_vbox_new(FALSE, 0);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
        parent = w;


      /* Hbox for holding the vboxes of icon and prompts. */
      w = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, border_major);
      gtk_widget_show(w);
      parent2 = w;

      /* Vbox for icon. */
      w = gtk_vbox_new(TRUE, 0);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, border_major);
        gtk_widget_show(w);
        parent3 = w;
      /* Fixed widget for holding icon pixmap. */
        d->icon_fixed = w = gtk_fixed_new();
        d->icon_pm = NULL;
      gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, FALSE, 0);
        gtk_widget_realize(w);
        gtk_widget_show(w);


      /* Vbox for prompt widgets. */
      d->main_vbox = w = gtk_vbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, border_major);
      gtk_widget_show(w);


      /* Separator. */
      w = gtk_hseparator_new();
        gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
        gtk_widget_show(w);


      /* Hbox for buttons. */
      w = gtk_hbox_new(TRUE, border_major);
        gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, border_major);
        gtk_widget_show(w);
        parent2 = w;

      /* Submit button. */
      d->submit_btn = w = GUIButtonPixmapLabelH(
          (u_int8_t **)icon_ok_20x20_xpm, "Submit", &label_rtn
      );
      d->submit_btn_label = GTK_WIDGET(label_rtn);
        gtk_widget_set_usize(w, PDIALOG_BTN_WIDTH, PDIALOG_BTN_HEIGHT);
      GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
      gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(PDialogButtonCB), d
        );
        gtk_accel_group_add(
            accelgrp, GDK_Return, 0, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );
        gtk_accel_group_add(
            accelgrp, GDK_3270_Enter, 0, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );
        gtk_accel_group_add(
            accelgrp, GDK_KP_Enter, 0, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );
        gtk_accel_group_add(
            accelgrp, GDK_ISO_Enter, 0, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );

      /* Cancel button. */
        d->cancel_btn = w = GUIButtonPixmapLabelH(
            (u_int8_t **)icon_cancel_20x20_xpm, "Cancel", &label_rtn
        );
        d->cancel_btn_label = GTK_WIDGET(label_rtn);
        gtk_widget_set_usize(w, PDIALOG_BTN_WIDTH, PDIALOG_BTN_HEIGHT);
        GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
      gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(PDialogButtonCB), d
        );
        gtk_accel_group_add(
            accelgrp, GDK_Escape, 0, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );

        /* Help button. */
      d->help_btn = w = GUIButtonPixmapLabelH(
            (u_int8_t **)icon_help_20x20_xpm, "Help", NULL
        );
        gtk_widget_set_usize(w, PDIALOG_BTN_WIDTH, PDIALOG_BTN_HEIGHT);
        GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
        gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(PDialogButtonCB), d
        );

      /* Set default icon. */
      PDialogSetIcon(d, (u_int8_t **)icon_question_32x32_xpm);

      return(0);
}

/*
 *      Returns TRUE if currently blocking for query.
 */
gbool PDialogIsQuery(void)
{
        if(block_loop_level > 0)
            return(TRUE);
        else
            return(FALSE);
}

/*
 *      Ends query if any and returns a not available response.
 */
void PDialogBreakQuery(void)
{
        response_code = PDIALOG_RESPONSE_NOT_AVAILABLE;

        /* Break out of an additional blocking loops. */
        while(block_loop_level > 0)
        {
            gtk_main_quit();
            block_loop_level--;
        }
        block_loop_level = 0;
  
        return;
}

/*
 *    Adds a prompt to the dialog.
 */
void PDialogAddPrompt(
      const u_int8_t **icon_data,
        const gchar *label,
        const gchar *value
)
{
        GtkWidget *w, *parent;
        gint n;
        pdialog_prompt_struct *p;
        pdialog_struct *d = &pdialog;


        p = PDialogPromptNew(
            icon_data, label, value, d
        );
        if(p == NULL)
            return;

        if(d->total_prompts < 0)
            d->total_prompts = 0;

        for(n = 0; n < d->total_prompts; n++)
        {
            if(d->prompt[n] == NULL) 
                break; 
        }
        if(n < d->total_prompts)
        {
            d->prompt[n] = p;
        } 
        else
        {
            n = d->total_prompts;
            d->total_prompts++;
            d->prompt = (pdialog_prompt_struct **)g_realloc(
                d->prompt,
                d->total_prompts * sizeof(pdialog_prompt_struct *)
            );
            if(d->prompt == NULL)
            {
                PDialogPromptDelete(p);
                d->total_prompts = 0;
                return;
            }

            d->prompt[n] = p;
        }

        parent = d->main_vbox;
        w = p->toplevel;
        if((parent != NULL) && (w != NULL))
        {
            gtk_box_pack_start(GTK_BOX(parent), w, TRUE, FALSE, 2);
            gtk_widget_show(w);
        }

      return;
}

/*
 *    Adds a prompt with browse to the dialog.
 */
void PDialogAddPromptWithBrowse(
      const u_int8_t **icon_data,
        const gchar *label,
        const gchar *value,
        gpointer client_data,
        gchar *(*browse_cb)(gpointer, gpointer, gint)
)
{
      GtkWidget *w, *parent;
      gint n;
      pdialog_prompt_struct *p;
      pdialog_struct *d = &pdialog;


      p = PDialogPromptNewWithBrowse(
          icon_data, label, value, d, client_data, browse_cb
      );
      if(p == NULL)
          return;

      if(d->total_prompts < 0)
          d->total_prompts = 0;

      for(n = 0; n < d->total_prompts; n++)
      {
          if(d->prompt[n] == NULL)
            break;
      }
      if(n < d->total_prompts)
      {
          d->prompt[n] = p;
      }
      else
      {
          n = d->total_prompts;
          d->total_prompts++;
          d->prompt = (pdialog_prompt_struct **)g_realloc(
            d->prompt,
            d->total_prompts * sizeof(pdialog_prompt_struct *)
          );
          if(d->prompt == NULL)
          {
            PDialogPromptDelete(p);
            d->total_prompts = 0;
            return;
          }

          d->prompt[n] = p;
      }

      parent = d->main_vbox;
      w = p->toplevel;
      if((parent != NULL) && (w != NULL))
      {
          gtk_box_pack_start(GTK_BOX(parent), w, TRUE, FALSE, 2);
          gtk_widget_show(w);
      }

      return;
}

/*
 *    Changes the value in the prompt's text or spin widget, changes
 *    the prompt's icon and changes the label. If any input is NULL
 *    then that value will be left unchanged.
 *
 *    If prompt_num is invalid (ie unallocated), then no operation
 *    will be performed.
 */
void PDialogSetPromptValue(
        gint prompt_num,
        const u_int8_t **icon_data,
        const gchar *label,
        const gchar *value 
)
{
        GtkWidget *w, *parent;
      GdkWindow *window = NULL;
        pdialog_prompt_struct *p;
        pdialog_struct *d = &pdialog;
            

      /* Prompt number valid on prompt dialog? */
      if((prompt_num < 0) || (prompt_num >= d->total_prompts))
          return;
      else
          p = d->prompt[prompt_num];

      if(p == NULL)
          return;

        /* Get window of dialog toplevel. */
        w = d->toplevel;
        if(w != NULL)
        {   
            if(!GTK_WIDGET_NO_WINDOW(w))
                window = w->window;
        }

      /* Change icon? */
      parent = p->icon_fixed;
      if((icon_data != NULL) && (parent != NULL))
      {
            GtkWidget *pixmap;
            GdkPixmap *gdk_pixmap;
            GdkBitmap *mask;
            GtkStyle *style;
            gint width, height;


            /* Get style from dialog toplevel. */
            if(d->toplevel == NULL)
                style = gtk_widget_get_default_style();
            else
                style = gtk_widget_get_style(d->toplevel);

            /* Create the pixmap. */
            gdk_pixmap = gdk_pixmap_create_from_xpm_d(
                window,
                &mask,
                ((style == NULL) ? NULL : &style->bg[GTK_STATE_NORMAL]),
                (gchar **)icon_data
            );
            pixmap = gtk_pixmap_new(gdk_pixmap, mask);
            gdk_window_get_size((GdkWindow *)gdk_pixmap, &width, &height);

            /* Adjust size of fixed widget to fit pixmap. */
            gtk_widget_set_usize(parent, width, height);

            /* Put pixmap into fixed widget. */
            gtk_fixed_put(GTK_FIXED(parent), pixmap, 0, 0);
            gtk_widget_shape_combine_mask(parent, mask, 0, 0);
            gtk_widget_show(pixmap);

          gdk_pixmap_unref(gdk_pixmap);
          if(mask != NULL)
            gdk_bitmap_unref(mask);


          /* Destroy the previous pixmap. */
          if(p->icon_pm != NULL)
            gtk_widget_destroy(p->icon_pm);

          /* Record new icon. */
          p->icon_pm = pixmap;
      }

      /* Change label? */
      w = p->label;
      if((label != NULL) && (w != NULL))
      {
          gtk_label_set_text(GTK_LABEL(w), label);
          gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT);
      }

      /* Change entry text? */
      w = p->entry;
      if((value != NULL) && (w != NULL))
      {
          gtk_entry_set_text(GTK_ENTRY(w), value);
          gtk_entry_set_position(GTK_ENTRY(w), 0);
      }

      return;
}

/*
 *    Fetches the value of the specified prompt as a string.
 *    Can return NULL on error or if the prompt does not have
 *    a text entry. The returned string must not be
 *    g_free()'ed by the calling function.
 */
gchar *PDialogGetPromptValue(gint prompt_num)
{
        GtkWidget *w;
        pdialog_prompt_struct *p;
        pdialog_struct *d = &pdialog;


        /* Prompt number valid on prompt dialog? */
        if((prompt_num < 0) || (prompt_num >= d->total_prompts))
            return(NULL);
        else
            p = d->prompt[prompt_num];

        if(p == NULL)
            return(NULL);

      w = p->entry;
      if(w != NULL)
      {
          /* Fetch value from entry. */
          return(gtk_entry_get_text(GTK_ENTRY(w)));
      }

      return(NULL);
}


/*
 *    Destroys all prompts on prompt dialog.
 */
void PDialogDeleteAllPrompts(void)
{
      gint i;
        pdialog_struct *d = &pdialog;


      for(i = 0; i < d->total_prompts; i++)
          PDialogPromptDelete(d->prompt[i]);
      g_free(d->prompt);
      d->prompt = NULL;
      d->total_prompts = 0;

      return;
}


/*
 *    Block input and wait for a response.
 *
 *    Returns an array of string values from the given prompts
 *    which must not be free'ed. If NULL is returned then it should
 *    be considered that the user clicked on cancel.
 *
 *    If any values are set NULL then that value will not be modified
 *    from since the last usage.
 */
gchar **PDialogGetResponse(
        const gchar *title,         /* Can be NULL. */
        const gchar *message,       /* Can be NULL. */
        const gchar *explaination,  /* Can be NULL. */
        gint icon_code,             /* One of PDIALOG_ICON_*. */
        const gchar *submit_label,  /* Can be NULL. */
        const gchar *cancel_label,  /* Can be NULL. */
        guint show_buttons,         /* Any of PDIALOG_FLAG_*. */
        guint default_button,       /* One of PDIALOG_FLAG_*. */
        gint *nvalues               /* Number of string values return. */
)
{
      gint i;
      GtkWidget *w;
      pdialog_struct *d = &pdialog;


        /* Do not handle response if already waiting for a response,
         * return with a not available response code.
         */
        if(block_loop_level > 0)
      {
          if(nvalues != NULL)
            (*nvalues) = 0;

            return(NULL);
      }

      /* Reset responses. */
      response_code = PDIALOG_RESPONSE_NOT_AVAILABLE;
      for(i = 0; i < response_nvals; i++)
          g_free(response_val[i]);
      g_free(response_val);
      response_val = NULL;
      response_nvals = 0;


      /* Reset number of values return. */
      if(nvalues != NULL)
          (*nvalues) = response_nvals;

      /* Is dialog initialized? */
        if(!d->initialized)
            return(response_val);

      /* Change title. */
      if(title != NULL)
      {
          w = d->toplevel;
          if(w != NULL)
            gtk_window_set_title(GTK_WINDOW(w), title);
      }

      /* Set message label text. */
      if(message != NULL)
      {

      }

      /* Update icon. */
      if(icon_code != d->last_icon_code)
      {
          d->last_icon_code = icon_code;
          switch(icon_code)
          {
            case PDIALOG_ICON_ERROR:
            PDialogSetIcon(d, (u_int8_t **)icon_error_32x32_xpm);
            break;

              case PDIALOG_ICON_QUESTION:
                PDialogSetIcon(d, (u_int8_t **)icon_question_32x32_xpm);
                break;

              case PDIALOG_ICON_WARNING:
                PDialogSetIcon(d, (u_int8_t **)icon_warning_32x32_xpm);
                break;

              default:
                PDialogSetIcon(d, (u_int8_t **)icon_info_32x32_xpm);
                break;
          }
      }

      /* Change button labels. */
      if(submit_label != NULL)
      {
          w = d->submit_btn_label;
          if(w != NULL)
            gtk_label_set_text(GTK_LABEL(w), submit_label);
      }
        if(cancel_label != NULL)
        {
            w = d->cancel_btn_label;
            if(w != NULL)
                gtk_label_set_text(GTK_LABEL(w), cancel_label);
        }


      /* Show/hide buttons. */
#define DO_MAP_BUTTON   \
{ \
 if(w != NULL) \
  gtk_widget_show(w); \
}
#define DO_UNMAP_BUTTON \
{ \
 if(w != NULL) \
  gtk_widget_hide(w); \
}
#define DO_DEFAULT_BUTTON     \
{ \
 if(w != NULL) \
 { \
  gtk_widget_grab_focus(w); \
  gtk_widget_grab_default(w); \
 } \
}
#define DO_UNDEFAULT_BUTTON   \
{ \
 if(w != NULL) \
 { \
/*  GTK_WIDGET_UNSET_FLAGS(w, GTK_HAS_DEFAULT); \
  GTK_WIDGET_UNSET_FLAGS(w, GTK_RECEIVES_DEFAULT); */ \
 } \
}       

      w = d->submit_btn;
      if(show_buttons & PDIALOG_BTNFLAG_SUBMIT)
          DO_MAP_BUTTON
      else
          DO_UNMAP_BUTTON
      if(default_button & PDIALOG_BTNFLAG_SUBMIT)
          DO_DEFAULT_BUTTON
      else
          DO_UNDEFAULT_BUTTON

      w = d->cancel_btn;
        if(show_buttons & PDIALOG_BTNFLAG_CANCEL)
            DO_MAP_BUTTON
      else
          DO_UNMAP_BUTTON
        if(default_button & PDIALOG_BTNFLAG_CANCEL)
            DO_DEFAULT_BUTTON
        else
            DO_UNDEFAULT_BUTTON

      w = d->help_btn;
        if(show_buttons & PDIALOG_BTNFLAG_HELP)
            DO_MAP_BUTTON
        else
            DO_UNMAP_BUTTON
        if(default_button & PDIALOG_BTNFLAG_HELP)
            DO_DEFAULT_BUTTON
        else
            DO_UNDEFAULT_BUTTON

#undef DO_MAP_BUTTON
#undef DO_UNMAP_BUTTON
#undef DO_DEFAULT_BUTTON
#undef DO_UNDEFAULT_BUTTON

      /* Map dialog. */
      PDialogMap();

      /* Block GUI untill response. */
      block_loop_level++;
      gtk_main();

      /* Unmap dialog. */
      PDialogUnmap();

        /* Break out of an additional blocking loops. */
        while(block_loop_level > 0)
        {
            gtk_main_quit();
            block_loop_level--;
        }
        block_loop_level = 0;


      /* Update number of values return. */
      if(nvalues != NULL)
          (*nvalues) = response_nvals;

      return(response_val);
}


/*
 *    Sets the size of the toplevel window of the prompt dialog.
 */
void PDialogSetSize(gint width, gint height)
{
        pdialog_struct *d = &pdialog;
        GtkWidget *w;


        if(!d->initialized)
            return;

      w = d->toplevel;
      if(w != NULL)
          gtk_widget_set_usize(w, width, height);
}

/*
 *    Maps the prompt dialog.
 */
void PDialogMap(void)
{
      pdialog_struct *d = &pdialog;
        GtkWidget *w;


        if(!d->initialized)
            return;

        if(!d->map_state)
        {
            w = d->toplevel;
            if(w != NULL)
                gtk_widget_show(w);

            d->map_state = TRUE;
        }
}

/*
 *    Unmaps the prompt dialog.
 */
void PDialogUnmap(void)
{
      pdialog_struct *d = &pdialog;
      GtkWidget *w;


      if(!d->initialized)
          return;

      if(d->map_state)
      {
          w = d->toplevel;
          if(w != NULL)
            gtk_widget_hide(w);

          d->map_state = FALSE;
      }
}

/*
 *    Shuts down the prompt dialog.
 */
void PDialogShutdown(void)
{
      gint i;
      GtkWidget **w;
      pdialog_struct *d = &pdialog;


        /* Reset globals. */
        response_code = PDIALOG_RESPONSE_NOT_AVAILABLE;
        for(i = 0; i < response_nvals; i++)
            g_free(response_val[i]);
        g_free(response_val);
        response_val = NULL;
        response_nvals = 0;

        /* Break out of an additional blocking loops. */
        while(block_loop_level > 0) 
        {
            gtk_main_quit();
            block_loop_level--;
        }
        block_loop_level = 0;

      /* Unmap dialog. */
        PDialogUnmap();

      /* Delete all prompts on dialog. */
        PDialogDeleteAllPrompts();

      if(d->initialized)
      {
#define DO_DESTROY_WIDGET       \
{ \
 if((*w) != NULL) \
 { \
  GtkWidget *tmp_w = *w; \
  (*w) = NULL; \
  gtk_widget_destroy(tmp_w); \
 } \
}
          /* Begin destroying widgets. */

            w = &d->icon_pm;
            DO_DESTROY_WIDGET

            w = &d->toplevel;
          DO_DESTROY_WIDGET

            if(d->accelgrp != NULL)
            {
                gtk_accel_group_unref(d->accelgrp);
                d->accelgrp = NULL;
            }

#undef DO_DESTROY_WIDGET
        }

      /* Clear prompt dialog structure. */
        memset(d, 0x00, sizeof(pdialog_struct));
}

Generated by  Doxygen 1.6.0   Back to index