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

fsd.c

#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "guiutils.h"
#include "fsd.h"

#include "images/icon_fonts_20x20.xpm"


typedef struct _fsd_data_struct           fsd_data_struct;
typedef struct _fsd_prompt_struct   fsd_prompt_struct;

/*
 *    Font Selection Dialog:
 */
struct _fsd_data_struct {

      gboolean    initialized,
                  map_state;
      GtkWidget   *fsd;       /* GtkFontSelectionDialog */

};
#define FSD_DATA(p)     ((fsd_data_struct *)(p))

/*
 *    Font Selection Dialog Prompt:
 */
struct _fsd_prompt_struct {

      GtkWidget   *toplevel,
                  *label,
                  *entry,
                  *button;

      gchar       *label_text;

};
#define FSD_PROMPT(p)   ((fsd_prompt_struct *)(p))
#define FSD_PROMPT_DATA_KEY   "fsd_prompt_data"


static void FSDOKCB(GtkWidget *widget, gpointer data);
static void FSDCancelCB(GtkWidget *widget, gpointer data);
static gint FSDDeleteEventCB(
      GtkWidget *widget, GdkEvent *event, gpointer data
);

gint FSDInit(void);
void FSDSetStyle(GtkRcStyle *rc_style);
void FSDSetTransientFor(GtkWidget *w);
gboolean FSDIsQuery(void);
void FSDBreakQuery(void);
gboolean FSDGetResponse(
      const gchar *title,
      const gchar *ok_label, const gchar *cancel_label,
      gchar *start_font_name,
      gchar **font_name_rtn
);
void FSDMap(void);
void FSDUnmap(void);
void FSDShutdown(void);

static void FSDPromptDataDestroyCB(gpointer data);
static void FSDPromptSelectCB(GtkWidget *widget, gpointer data);
GtkWidget *FSDPromptNew(
      const gchar *label, gint label_width,
      gint entry_width,
      gpointer client_data,
      void (*func_cb)(GtkWidget *, gpointer)
);
GtkWidget *FSDPromptNewSimple(
      const gchar *label, gint label_width,
      gint entry_width
);
GtkWidget *FSDPromptGetEntry(GtkWidget *w);
GtkWidget *FSDPromptGetButton(GtkWidget *w);
gchar *FSDPromptGetFontName(GtkWidget *w);
void FSDPromptSetFontName(GtkWidget *w, const gchar *font_name);


static gint block_loop_level;
static fsd_data_struct fsd_data;
static gboolean fsd_got_user_response;
static gchar *response_font_name;


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *    OK callback.
 */
static void FSDOKCB(GtkWidget *widget, gpointer data)
{
      gboolean font_loaded;
      GtkFontSelectionDialog *fsd;
      fsd_data_struct *fsdd = FSD_DATA(data);
      if(fsdd == NULL)
          return;

      if(!fsdd->initialized)
          return;

      fsd = GTK_FONT_SELECTION_DIALOG(fsdd->fsd);
      if(fsd == NULL)
          return;

      /* Set user response code to TRUE, indicating OK */
      fsd_got_user_response = TRUE;

      /* Check if the selected font was loaded properly */
      font_loaded = (gtk_font_selection_dialog_get_font(fsd) != NULL) ?
          TRUE : FALSE;

      /* Get font name, the font name returned by
       * gtk_font_selection_dialog_get_font_name() is a copy so we
       * need to delete the previous font name
       */
      g_free(response_font_name);
      response_font_name = gtk_font_selection_dialog_get_font_name(fsd);

      /* Unmap */
      FSDUnmap();

      /* Break out of blocking loop */
      gtk_main_quit();
      block_loop_level--;
}

/*
 *    Cancel callback.
 */
static void FSDCancelCB(GtkWidget *widget, gpointer data)
{
      fsd_data_struct *fsdd = FSD_DATA(data);
      if(fsdd == NULL)
          return;

      if(!fsdd->initialized)
          return;

      /* Set user response code to FALSE, indicating Cancel */
      fsd_got_user_response = FALSE;

      /* Unmap */
      FSDUnmap();

      /* Break out of blocking loop */
      gtk_main_quit();
      block_loop_level--;
}           

/*
 *    Font Selection Dialog toplevel GtkWindow "delete_event" signal
 *    callback.
 */
static gint FSDDeleteEventCB(
      GtkWidget *widget, GdkEvent *event, gpointer data
)
{
      FSDCancelCB(widget, data);
      return(TRUE);
}


/*
 *    Initializes Font Selection Dialog.
 */
int FSDInit(void)
{
      GtkWidget *w;
      GtkFontSelectionDialog *fsd;
      fsd_data_struct *fsdd = &fsd_data;


      /* Reset local globals */
      block_loop_level = 0;
      fsd_got_user_response = FALSE;

      g_free(response_font_name);
      response_font_name = NULL;

      memset(fsdd, 0x00, sizeof(fsd_data_struct));

      /* Reset values */
      fsdd->initialized = TRUE;
      fsdd->map_state = FALSE;

      /* Create the font selection dialog */
      fsdd->fsd = w = gtk_font_selection_dialog_new("Select Font");
      fsd = GTK_FONT_SELECTION_DIALOG(w);
      gtk_signal_connect(
          GTK_OBJECT(w), "delete_event",
          GTK_SIGNAL_FUNC(FSDDeleteEventCB), fsdd
      );

      /* Get GtkFontSelection widget */
      w = fsd->fontsel;

/* Connect some signals to the GtkFontSelection widget? */

      /* OK Button */
      gtk_signal_connect(
          GTK_OBJECT(fsd->ok_button), "clicked",
          GTK_SIGNAL_FUNC(FSDOKCB), fsdd
      );
      gtk_widget_show(fsd->ok_button);

      /* Hide apply button */
      if(fsd->apply_button != NULL)
          gtk_widget_hide(fsd->apply_button);

      /* Cancel Button */
      gtk_signal_connect(
          GTK_OBJECT(fsd->cancel_button), "clicked",
          GTK_SIGNAL_FUNC(FSDCancelCB), fsdd
      );
      gtk_widget_show(fsd->cancel_button);

      return(0);
}

/*
 *    Sets the Font Selection Dialog's style.
 */
void FSDSetStyle(GtkRcStyle *rc_style)
{
      GtkWidget *w;
      fsd_data_struct *fsdd = &fsd_data;

      if(!fsdd->initialized)
          return;

      w = fsdd->fsd;
      if(w != NULL)
      {
          if(rc_style != NULL)
          {
            gtk_widget_modify_style(w, rc_style);
          }
          else
          {
            rc_style = gtk_rc_style_new();
            gtk_widget_modify_style_recursive(w, rc_style);
            GTK_RC_STYLE_UNREF(rc_style)
          }
      }
}

/*
 *    Sets the Font Selection Dialog to be a transient for the
 *    specified GtkWindow.
 *
 *    If w is NULL then transient for will be unset.
 */
void FSDSetTransientFor(GtkWidget *w)
{
      fsd_data_struct *fsdd = &fsd_data;

      if(!fsdd->initialized)
          return;

      if(fsdd->fsd != NULL)
      {
          if(w != NULL)
          {
            /* Given widget if not NULL, must be a window */
            if(!GTK_IS_WINDOW(GTK_OBJECT(w)))
                return;

            gtk_window_set_modal(
                GTK_WINDOW(fsdd->fsd), TRUE
            );
            gtk_window_set_transient_for(
                GTK_WINDOW(fsdd->fsd), GTK_WINDOW(w)
            );
          }
          else
          {
            gtk_window_set_modal(
                GTK_WINDOW(fsdd->fsd), FALSE
            );
            gtk_window_set_transient_for(
                GTK_WINDOW(fsdd->fsd), NULL
            );
          }
      }
}

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

/*
 *    Ends query if any and returns a not available response.
 */
void FSDBreakQuery(void)
{
      fsd_got_user_response = FALSE;

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

/*
 *    Maps the Font Selection Dialog and sets up the inital values.
 *
 *    Returns TRUE if a font was selected or FALSE if user canceled.
 *
 *    For most values that are set NULL, the value is left unchanged.
 *    All given values are coppied.
 *
 *    All returned pointer values should be considered statically
 *    allocated, do not deallocate them.
 */
gboolean FSDGetResponse(
      const gchar *title,
      const gchar *ok_label, const gchar *cancel_label,
      gchar *start_font_name,
      gchar **font_name_rtn
)
{
      GtkWidget *w;
      fsd_data_struct *fsdd = &fsd_data;


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

          return(FALSE);
      }

      /* Reset global responses values */
      fsd_got_user_response = FALSE;

      g_free(response_font_name);
      response_font_name = NULL;

      /* Reset returns */
      if(font_name_rtn != NULL)
          (*font_name_rtn) = NULL;


      /* Font selection dialog must be initialized */
      if(!fsdd->initialized)
          return(fsd_got_user_response);

      /* Get pointer to font selection dialog widget */
      w = fsdd->fsd;
      if(w == NULL)
          return(fsd_got_user_response);

      /* Update title if specified */
      if(title != NULL)
          gtk_window_set_title(GTK_WINDOW(w), title);

      /* Update initial start font name if specified */
      if(start_font_name != NULL)
          gtk_font_selection_dialog_set_font_name(
            GTK_FONT_SELECTION_DIALOG(w),
            start_font_name
          );

      /* Map font selection dialog as needed */
      FSDMap();

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

      /* Unmap font selection dialog just in case it was not unmapped
       * from any of the callbacks
       */
      FSDUnmap();

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


      /* Begin setting returns */

      /* Font name return */
      if(font_name_rtn != NULL)
          *font_name_rtn = response_font_name;

      return(fsd_got_user_response);
}


/*
 *    Maps the Font Selection Dialog.
 */
void FSDMap(void)
{
      GtkWidget *w;
      fsd_data_struct *fsdd = &fsd_data;

      if(!fsdd->initialized)
          return;

      w = fsdd->fsd;
      gtk_widget_show_raise(w);
      fsdd->map_state = TRUE;
}

/*
 *    Unmaps the Font Selection Dialog.
 */
void FSDUnmap(void)
{
      fsd_data_struct *fsdd = &fsd_data;

      if(!fsdd->initialized)
          return;

      if(fsdd->map_state)
      {
          GtkWidget *w = fsdd->fsd;

          if(w != NULL)
            gtk_widget_hide(w);

          fsdd->map_state = FALSE;
      }
}

/*
 *    Shuts down the Font Selection Dialog.
 */
void FSDShutdown(void)
{
      GtkWidget **w;
      fsd_data_struct *fsdd = &fsd_data;


      /* Reset local globals */
      fsd_got_user_response = FALSE;

      g_free(response_font_name);
      response_font_name = NULL;

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


      /* Is color selection dialog initialized? */
      if(fsdd->initialized)
      {
#define DO_DESTROY_WIDGET     \
{ if(*w != NULL) { gtk_widget_destroy(*w); *w = NULL; } }

          /* Begin destroying widgets */

          w = &fsdd->fsd;
          DO_DESTROY_WIDGET

#undef DO_DESTROY_WIDGET
      }

      /* Clear font selection dialog structure */
      memset(fsdd, 0x00, sizeof(fsd_data_struct));
}


/*
 *    FSD Prompt GtkObject data "destroy" signal callback.
 */
static void FSDPromptDataDestroyCB(gpointer data)
{
      fsd_prompt_struct *p = FSD_PROMPT(data);
      if(p == NULL)
          return;

      g_free(p->label_text);
      g_free(p);
}

/*
 *    FSD Prompt select callback.
 */
static void FSDPromptSelectCB(GtkWidget *widget, gpointer data)
{
      gboolean status;
      gchar *cur_font_name, *font_name;
      GtkWidget *w, *toplevel;
      fsd_prompt_struct *p = FSD_PROMPT(data);
      if((p == NULL) || FSDIsQuery())
          return;

      w = p->entry;
      toplevel = gtk_widget_get_toplevel(p->toplevel);

      cur_font_name = STRDUP(
          gtk_entry_get_text(GTK_ENTRY(w))
      );

      FSDSetTransientFor(toplevel);
      status = FSDGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"El Tipo De Letra Selecto",
"Selecto",
"Cancele",
#elif defined(PROG_LANGUAGE_FRENCH)
"Jeu De Caractères Privilégié",
"Privilégié",
"Annuler",
#elif defined(PROG_LANGUAGE_GERMAN)
"Erlesene Schriftart",
"Erlesen",
"Heben",
#elif defined(PROG_LANGUAGE_ITALIAN)
"Scegliere Font",
"Scegliere",
"Annullare",
#elif defined(PROG_LANGUAGE_DUTCH)
"Uitgezocht Lettertype",
"Uitgezocht",
"Annuleer",
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Selecione Fonte",
"Selecione",
"Cancelamento",
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Utvalgt Font",
"Utvalgt",
"Kanseller",
#else
"Select Font",
"Select",
"Cancel",
#endif
          cur_font_name,
          &font_name
      );
      FSDSetTransientFor(NULL);
      if(status && !STRISEMPTY(font_name))
      {
          gtk_entry_set_text(GTK_ENTRY(w), font_name);
          gtk_entry_set_position(GTK_ENTRY(w), -1);
      }

      g_free(cur_font_name);
}

/*
 *    Creates a new FSD Prompt.
 */
GtkWidget *FSDPromptNew(
      const gchar *label, gint label_width,
      gint entry_width,
      gpointer client_data,
      void (*func_cb)(GtkWidget *, gpointer)
)
{
      const gint border_minor = 2;
      GtkWidget *w;
      fsd_prompt_struct *p = FSD_PROMPT(
          g_malloc0(sizeof(fsd_prompt_struct))
      );

      /* Toplevel */
      p->toplevel = w = gtk_hbox_new(FALSE, border_minor);
      gtk_object_set_data_full(
          GTK_OBJECT(w), FSD_PROMPT_DATA_KEY,
          p, FSDPromptDataDestroyCB
      );

      /* Label */
      if(!STRISEMPTY(label))
      {
          GtkWidget *parent = w = gtk_alignment_new(1.0f, 0.5f, 0.0f, 0.0f);
          gtk_widget_set_usize(w, label_width, -1);
          gtk_box_pack_start(GTK_BOX(p->toplevel), w, FALSE, FALSE, 0);
          gtk_widget_show(w);

          p->label = w = gtk_label_new(label);
          p->label_text = STRDUP(label);
          gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT);
          gtk_container_add(GTK_CONTAINER(parent), w);
          gtk_widget_show(w);
      }

      /* Entry */
      p->entry = w = gtk_entry_new();
      gtk_entry_set_editable(GTK_ENTRY(w), FALSE);
      if(entry_width > 0)
      {
          gtk_widget_set_usize(w, entry_width, -1);
          gtk_box_pack_start(GTK_BOX(p->toplevel), w, FALSE, FALSE, 0);
      }
      else
      {
          gtk_box_pack_start(GTK_BOX(p->toplevel), w, TRUE, TRUE, 0);
      }
      gtk_widget_show(w);

      /* Button */
      p->button = w = GUIButtonPixmap(
          (guint8 **)icon_fonts_20x20_xpm
      );
      gtk_box_pack_start(GTK_BOX(p->toplevel), w, FALSE, FALSE, 0);
      GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"El clic para escoger el tipo de letra"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le déclic pour choisir le jeu de caractères"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klicken, schriftart auszuwählen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Lo scatto di scegliere il font"
#elif defined(PROG_LANGUAGE_DUTCH)
"Klik lettertype te selecteren"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O estalido selecionar fonte"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klikk velge ut font"
#else
"Click to select font"
#endif
      );
      gtk_widget_show(w);

      if(func_cb != NULL)
          gtk_signal_connect(
            GTK_OBJECT(p->button), "clicked",
            GTK_SIGNAL_FUNC(func_cb), client_data
          );

      return(p->toplevel);
}

/*
 *    Creates a new FSD Prompt with the default select signal
 *    connected to the default handler.
 */
GtkWidget *FSDPromptNewSimple(
      const gchar *label, gint label_width,
      gint entry_width
)
{
      GtkWidget *w = FSDPromptNew(
          label, label_width, entry_width, NULL, NULL
      );
      fsd_prompt_struct *p = FSD_PROMPT(
          GTK_OBJECT_GET_DATA(w, FSD_PROMPT_DATA_KEY)
      );
      if(p->button != NULL)
          gtk_signal_connect(
            GTK_OBJECT(p->button), "clicked",
            GTK_SIGNAL_FUNC(FSDPromptSelectCB), p
          );
      return(w);
}

/*
 *    Gets the FSD Prompt's entry widget.
 */
GtkWidget *FSDPromptGetEntry(GtkWidget *w)
{
      fsd_prompt_struct *p = FSD_PROMPT(
          GTK_OBJECT_GET_DATA(w, FSD_PROMPT_DATA_KEY)
      );
      return((p != NULL) ? p->entry : NULL);
}

/*
 *    Gets the FSD Prompt's button widget.
 */
GtkWidget *FSDPromptGetButton(GtkWidget *w)
{
      fsd_prompt_struct *p = FSD_PROMPT(
          GTK_OBJECT_GET_DATA(w, FSD_PROMPT_DATA_KEY)
      );
      return((p != NULL) ? p->button : NULL);
}

/*
 *    Gets the FSD Prompt's currently selected font name.
 */
gchar *FSDPromptGetFontName(GtkWidget *w)
{
      fsd_prompt_struct *p = FSD_PROMPT(
          GTK_OBJECT_GET_DATA(w, FSD_PROMPT_DATA_KEY)
      );
      return((p != NULL) ?
          gtk_entry_get_text(GTK_ENTRY(p->entry)) : NULL
      );
}

/*
 *    Sets the FSD Prompts font name.
 */
void FSDPromptSetFontName(GtkWidget *w, const gchar *font_name)
{
      fsd_prompt_struct *p = FSD_PROMPT(
          GTK_OBJECT_GET_DATA(w, FSD_PROMPT_DATA_KEY)
      );
      GtkEntry *entry = (GtkEntry *)((p != NULL) ?
          p->entry : NULL
      );
      if(entry != NULL)
      {
          gtk_entry_set_text(entry, (font_name != NULL) ? font_name : "");
          gtk_entry_set_position(entry, -1);
      }
}

Generated by  Doxygen 1.6.0   Back to index