font selecter with real time update and sample with gtk

Hi,

FVWM is very good at using true type font. However, in order to find out the name of the font, it could be a game of guess and error.

The good thing is, gtk already has a gtkFontSelectDialog defined, which can display and give the font name that is selected.

The only thing left is to convert the name to fvwm font name and let fvwm change to the font dynamically.

I wrote a small c program that do the task.

It will write to $HOME/.fvwm/font.config like this:

#Bradley Hand ITC Bold 16
DefaultFont "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=16"
MenuStyle * Font "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=16"
*FvwmPager: Font "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=12"
*FvwmIconMan: Font "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=12"
*FvwmIconMan: TipsFont "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=12"
*FvwmScript: DefaultFont "Shadow=1 0 C:xft:Bradley Hand ITC:Bold:antialias=True:pixelsize=12"

and in config, I simply “read font.config”.

This make sure next time when fvwm starts, it will use the selected fonts.

In order to dynamically change the fonts, I use a fvwmCommand module to receive commands. The commands are generated by the c program. It basically ask fvwm to read the font.config, restart FvwmPager and FvwmButtons.

The c code is here:

/**
 * 
 * A Simple Gtk Select Font Dialog for FVWM font selection.
 * 
 * To compile:
 * gcc fontselect.c -o fontselect `pkg-config --cflags --libs gtk+-2.0`
 *
 * Written by Jingshao Chen
 */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>

static gboolean delete_event( 
        GtkWidget *widget,
        GdkEvent  *event,
        gpointer   data )
{
    /* Let delete equals to destroy, emit destroy event */
    return FALSE; 
}

static void destroy( 
        GtkWidget *widget,
        gpointer   data )
{
    gtk_main_quit();
}

static gboolean select_font_apply(
        GtkWidget *widget,
        gpointer   data )
{
    char buffer[1024];
    char fontConfigFileName[1024];
    FILE *fontConfigFile;
    int found;
    gchar *fontname;
    char *fontdup;

    char *fontsize = NULL;
    int i, j;

    int word_count;
    char **ap, *wordp[20];

    char *deco[] = {
        "Semi-Bold", "Bold", 
        "Italic", 
        "Semi-Expanded", "Expanded", 
        "Extra-Condensed", "Semi-Condensed", "Condensed", 
        "Ultra-Light", "Light", 
        "Oblique", NULL };

    int deco_len;

    char *FVWMCMD = "/usr/local/bin/FvwmCommand"; 
    int size;
    deco_len = 0;
    while (deco[deco_len] != NULL) deco_len++;

    fontname = 
        gtk_font_selection_dialog_get_font_name((GtkFontSelectionDialog *)data);
    
    snprintf(fontConfigFileName, 1024, "%s/.fvwm/font.config", getenv("HOME"));
    fontConfigFile = fopen(fontConfigFileName, "w");
    /* keep a record */
    fprintf(fontConfigFile, "#%s\n", fontname);

    fontdup = strdup(fontname);

    word_count = 0;
    for (ap = wordp; (*ap = strsep(&fontname, " ")) != NULL; word_count++)
      if (**ap != '\0')
        if (++ap >= &wordp[20])
          break;

    fontsize = wordp[--word_count];
    size=atoi(fontsize);

    *(fontdup + (fontsize - wordp[0] - 1)) = '\0';

    for (i = word_count-1; i>=0; i--) {
      found = 0;
      for (j = 0; j < deco_len; j++) {
        if (strcmp(wordp[i], deco[j]) == 0) {
          *(fontdup + (wordp[i] -wordp[0] - 1)) = ':';
          found = 1;
          break;
        }
      }
      if (found == 0) 
        break;
    }
    
    /* save it to a file */
    snprintf(buffer, 1024, 
             "Shadow=1 0 C:xft:%s:antialias=True:pixelsize=", 
             fontdup); 
    
    fprintf(fontConfigFile, "DefaultFont \"%s%d\"\n", 
            buffer, size);
    fprintf(fontConfigFile, "MenuStyle * Font \"%s%d\"\n", 
            buffer, size);
    size -= 4;
    fprintf(fontConfigFile, "*FvwmPager: Font \"%s%d\"\n", 
            buffer, size);
    fprintf(fontConfigFile, "*FvwmIconMan: Font \"%s%d\"\n", 
            buffer, size);
    fprintf(fontConfigFile, "*FvwmIconMan: TipsFont \"%s%d\"\n", 
            buffer, size);
    fprintf(fontConfigFile, "*FvwmScript: DefaultFont \"%s%d\"\n", 
            buffer, size);

    fclose(fontConfigFile);
    /* change configure using FvwmCommand */
    snprintf(buffer, 1024, "%s -r \"read %s\"",
             FVWMCMD, fontConfigFileName); 
    system(buffer);
    snprintf(buffer, 1024, "%s -r \"KillModule FvwmPager\"", FVWMCMD);
    system(buffer); 
    snprintf(buffer, 1024, "%s -r \"KillModule FvwmButtons\"", FVWMCMD);
    system(buffer); 
    snprintf(buffer, 1024, "%s -r \"Module FvwmPager 0 1\"", FVWMCMD); 
    system(buffer); 
    snprintf(buffer, 1024, "%s -r \"Module FvwmButtons\"", FVWMCMD);
    system(buffer); 
  
    return FALSE;
}

static gboolean select_font_ok( 
        GtkWidget *widget,
        gpointer   data )
{
  (void) select_font_apply(widget, data);
  gtk_main_quit();
}

int main( int   argc,
          char *argv[] )
{
  GtkWidget *fontSelectDialog;
  GtkFontSelectionDialog *d;
    
  char buffer[1024];
  FILE *fontConfigFile;

  gtk_init (&argc, &argv);
    
  fontSelectDialog = gtk_font_selection_dialog_new ("Fvwm Font Chooser!");
  d = (GtkFontSelectionDialog *)fontSelectDialog;
  
  gtk_widget_show(d->apply_button);

  g_signal_connect (G_OBJECT (fontSelectDialog), "delete_event",
                    G_CALLBACK (delete_event), NULL);
  g_signal_connect (G_OBJECT (fontSelectDialog), "destroy",
                    G_CALLBACK (destroy), NULL);

  g_signal_connect (G_OBJECT (d->ok_button), "clicked",
                    G_CALLBACK (select_font_ok), (gpointer)d);
  g_signal_connect (G_OBJECT (d->apply_button), "clicked",
                    G_CALLBACK (select_font_apply), (gpointer)d);
  g_signal_connect (G_OBJECT (d->cancel_button), "clicked",
                    G_CALLBACK (destroy), NULL);

  snprintf(buffer, 1024, "%s/.fvwm/font.config", getenv("HOME"));
  
  if ((fontConfigFile = fopen(buffer, "r")) != NULL ) {
    if (fgets(buffer, 1024, fontConfigFile) != NULL) {
      gtk_font_selection_dialog_set_font_name(d, buffer+1);
    }    
    fclose(fontConfigFile);
  }

  gtk_widget_show  (fontSelectDialog);
    
  gtk_main ();
    
  return 0;
}

Last, some screen shots]http://farm3.static.flickr.com/2114/2168395358_1eeebb8191_m.jpg[/img]
Full size]http://www.flickr.com/photo_zoom.gne?id=2168395358&size=o[/url]

Full size]http://www.flickr.com/photo_zoom.gne?id=2168395352&size=o[/url]