/*
* simple.c: Simple dialog widgets
*
* Written by: Ullrich Hafner
*
* Copyright (C) 1999 Ullrich Hafner <hafner@bigfoot.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*/
/*
* $Date: 2000/09/03 19:22:05 $
* $Author: hafner $
* $Revision: 1.15 $
* $State: Exp $
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "proplist_t.h"
#include "simple.h"
#include "dialog.h"
#include "menu.h"
#include "texture.h"
#include "misc.h"
#include "window.h"
#include "themebrowser.h"
#include "error.h"
/*******************************************************************************
global variables
*******************************************************************************/
extern bool_t changed; /* window.c */
extern proplist_t windowmaker; /* window.c */
/*******************************************************************************
local variables
*******************************************************************************/
#ifdef HAVE_LIBWMFUN
static const char **color_types = NULL;
/*******************************************************************************
prototypes
*******************************************************************************/
static void
color_toggle (GtkWidget *widget, gpointer ptr);
static void
show_color_buttons (text_color_t *text_color);
static void
update_text_color (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
#endif /* HAVE_LIBWMFUN */
static void
set_bool (GtkWidget *widget, gpointer ptr);
static void
set_ibool (GtkWidget *widget, gpointer ptr);
static void
append_dialog (GtkWidget *container, GtkWidget *left, GtkWidget *right,
GtkAttachOptions attach);
static void
set_string (GtkWidget *widget, gpointer ptr);
static void
set_int (GtkWidget *widget, gpointer ptr);
static void
set_entry_text (GtkWidget *widget, gpointer ptr);
static void
convert_pango_to_fontconfig (const char *pangoname, char *fcname);
static void
convert_fontconfig_to_pango (const char *fcname, char *pangoname);
static void
set_fontname (GtkWidget *widget, gpointer ptr);
static void
fontsel_dialog (GtkWidget *widget, gpointer ptr);
static void
update_entry (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
static void
update_color (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
static void
update_boolean (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
static void
update_iboolean (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
static void
update_int (proplist_t key, gpointer ptr, proplist_t value,
const char *path);
/*******************************************************************************
public code
*******************************************************************************/
void
boolean_dialog (GtkWidget *table, proplist_t key, proplist_t value,
proplist_t info)
{
GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
GtkWidget *button = gtk_check_button_new ();
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
convert_bool (value));
gtk_signal_connect (GTK_OBJECT (button), "toggled",
GTK_SIGNAL_FUNC (set_bool), (gpointer) key);
append_dialog (table, label, button, GTK_SHRINK);
connect_update_function (key, button, update_boolean);
}
void
iboolean_dialog (GtkWidget *table, proplist_t key, proplist_t value,
proplist_t info)
{
GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
GtkWidget *button = gtk_check_button_new ();
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
convert_bool (value) ? FALSE : TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
GTK_SIGNAL_FUNC (set_ibool), (gpointer) key);
append_dialog (table, label, button, GTK_SHRINK);
connect_update_function (key, button, update_iboolean);
}
void
string_dialog (GtkWidget *table, proplist_t key, proplist_t value,
proplist_t range, proplist_t rinfo, proplist_t info)
{
GtkWidget *option_menu;
GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
const char **values;
unsigned n, current = 0;
values = Calloc (WMGetPropListItemCount (range) + 1, sizeof (char *));
for (n = 0; n < WMGetPropListItemCount (range); n++)
{
proplist_t element = WMGetFromPLArray (range, n);
if (strcaseeq (WMGetFromPLString (element), WMGetFromPLString (value)))
current = n;
values [n] = WMGetFromPLString (element);
}
values [n] = NULL;
option_menu = generate_option_menu (NULL, NULL, NULL, values,
values [current], rinfo, set_string, key);
append_dialog (table, option_menu, label, GTK_FILL | GTK_SHRINK);
{
omenudata_t *data = Calloc (1, sizeof (omenudata_t));
data->omenu = GTK_OPTION_MENU (option_menu);
data->values = values;
connect_update_function (key, data, update_optionmenu);
}
}
void
int_dialog (GtkWidget *table, proplist_t key, proplist_t value,
proplist_t range, proplist_t rinfo, proplist_t info)
{
GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
GtkEntry **array = Calloc (WMGetPropListItemCount (range) / 2 + 1,
sizeof (GtkEntry *));
unsigned n;
for (n = 0; n < WMGetPropListItemCount (range); n += 2)
{
GtkWidget *spinner;
GtkObject *adj;
char *m = WMGetFromPLString (WMGetFromPLArray (range, n));
char *M = WMGetFromPLString (WMGetFromPLArray (range, n + 1));
char *v;
if (WMIsPLArray (value))
v = WMGetFromPLString (WMGetFromPLArray (value, n / 2));
else
v = WMGetFromPLString (value);
adj = gtk_adjustment_new (strtod (v, NULL),
strtod (m, NULL), strtod (M, NULL),
1.0, 5.0, 0.0);
spinner = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 0, 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
gtk_widget_show_all (spinner);
gtk_object_set_user_data (GTK_OBJECT (adj), (gpointer) spinner);
gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (spinner),
(gpointer) (spinner + n / 2));
gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
GTK_SIGNAL_FUNC (set_int), (gpointer) key);
gtk_signal_connect (GTK_OBJECT (>K_SPIN_BUTTON (spinner)->entry),
"changed", GTK_SIGNAL_FUNC (set_entry_text),
(gpointer) key);
array [n / 2] = >K_SPIN_BUTTON (spinner)->entry;
}
array [n / 2] = NULL;
append_dialog (table, hbox, label, GTK_FILL | GTK_SHRINK);
connect_update_function (key, array, update_int);
}
void
text_dialog (GtkWidget *table, proplist_t key, proplist_t value,
proplist_t info)
{
GtkWidget *entry = gtk_entry_new ();
GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
gtk_widget_set_usize (entry, 100, 0);
gtk_entry_set_text (GTK_ENTRY (entry), WMGetFromPLString (value));
gtk_signal_connect (GTK_OBJECT (entry), "changed",
GTK_SIGNAL_FUNC (set_entry_text), key);
append_dialog (table, entry, label, GTK_FILL | GTK_SHRINK);
connect_update_function (key, entry, update_entry);
}
GtkWidget *
font_dialog (GtkWidget *page, proplist_t key, proplist_t value,
proplist_t info)
{
GtkWidget *entry = gtk_entry_new ();
GtkWidget *frame = gtk_frame_new (D_(WMGetFromPLString (info)));
GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
GtkWidget *bbox = gtk_hbutton_box_new ();
GtkWidget *button = gtk_button_new_with_label (_("Browse..."));
gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (frame), hbox);
gtk_entry_set_text (GTK_ENTRY (entry), WMGetFromPLString (value));
gtk_signal_connect (GTK_OBJECT (entry), "changed",
GTK_SIGNAL_FUNC (set_entry_text), key);
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), bbox, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (fontsel_dialog), (gpointer) entry);
gtk_box_pack_end (GTK_BOX (page), frame, TRUE, TRUE, 5);
gtk_widget_show_all (frame);
connect_update_function (key, entry, update_entry);
return frame;
}
GtkWidget *
color_dialog (GtkWidget *page, proplist_t key, proplist_t value,
GtkTooltips *tooltips, proplist_t info, proplist_t title)
{
GtkWidget *frame;
GtkWidget *button = color_button (NULL, key, value, tooltips,
D_(WMGetFromPLString (info)));
GtkWidget *hbox = gtk_hbox_new (TRUE, 0);
if (title)
frame = gtk_frame_new (D_(WMGetFromPLString (title)));
else
frame = gtk_frame_new (WMGetFromPLString (key));
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
gtk_container_add (GTK_CONTAINER (frame), hbox);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, TRUE, 5);
gtk_widget_show_all (frame);
connect_update_function (key,
gtk_object_get_user_data (GTK_OBJECT (button)),
update_color);
return frame;
}
#ifdef HAVE_LIBWMFUN
GtkWidget *
extended_color_dialog (GtkWidget *page, proplist_t key, proplist_t value,
GtkTooltips *tooltips, proplist_t info, proplist_t title)
{
GtkWidget *frame;
GtkWidget *option_menu;
text_color_t *text_color = Calloc (1, sizeof (text_color_t));
GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
frame = gtk_frame_new (_("Color of title text"));
text_color->key = key;
if (!color_types)
{
color_types = Calloc (TCOLOR_LAST, sizeof (char *));
color_types [TCOLOR_SIMPLE] = _("Solid color");
color_types [TCOLOR_COLORSET] = _("Drop shadow");
color_types [TCOLOR_LAST] = NULL;
}
option_menu = generate_option_menu (NULL, tooltips,
_("A solid color or a drop shadow."),
color_types, color_types [0], NULL,
color_toggle, text_color);
text_color->option_menu = option_menu;
gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
gtk_container_add (GTK_CONTAINER (frame), hbox);
gtk_box_pack_start (GTK_BOX (hbox), option_menu, FALSE, FALSE, 0);
text_color->solid_color = color_button (NULL, key, NULL, NULL, NULL);
gtk_box_pack_start (GTK_BOX (hbox), text_color->solid_color,
FALSE, TRUE, 0);
text_color->color_set [0] = color_button (NULL, key, NULL,
tooltips, _("Foreground"));
gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [0],
FALSE, TRUE, 0);
text_color->color_set [1] = color_button (NULL, key, NULL,
tooltips, _("Shadow 1"));
gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [1],
FALSE, TRUE, 0);
text_color->color_set [2] = color_button (NULL, key, NULL,
tooltips, _("Shadow 2"));
gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [2],
FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
gtk_widget_show_all (frame);
show_color_buttons (text_color);
connect_update_function (key, text_color, update_text_color);
return frame;
}
#endif /* HAVE_LIBWMFUN */
void
update_optionmenu (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
omenudata_t *data = (omenudata_t *) ptr;
if (WMIsPLString (value))
set_option_menu_default (data->omenu, data->values, WMGetFromPLString (value));
}
bool_t
convert_bool (proplist_t p)
/*
* Parse boolean values of WindowMaker file.
*
* Return value:
* converted value
*/
{
char *val;
assert (p && (WMIsPLString (p) || WMIsPLData (p)));
val = WMGetFromPLString (p);
if (strcaseeq (val, "y") || strcaseeq (val, "yes")
|| strcaseeq (val, "t") || strcaseeq (val, "true")
|| strcaseeq (val, "1"))
return TRUE;
else if (strcaseeq (val, "n") || strcaseeq (val, "no")
|| strcaseeq (val, "f") || strcaseeq (val, "false")
|| strcaseeq (val, "0"))
return FALSE;
else
{
warning (_("Undefined boolean value '%s' converted to true."), val);
return TRUE;
}
}
/*******************************************************************************
private code
*******************************************************************************/
#ifdef HAVE_LIBWMFUN
static void
color_toggle (GtkWidget *widget, gpointer ptr)
{
char *text = gtk_object_get_user_data (GTK_OBJECT (widget));
text_color_t *text_color = (text_color_t *) ptr;
proplist_t value = WMGetFromPLDictionary (windowmaker, text_color->key);
if (text == color_types [TCOLOR_SIMPLE])
{
if (!WMIsPLString (value))
{
WMPutInPLDictionary (windowmaker, text_color->key,
WMCreatePLString ("tan"));
toggle_save (changed = YES, text_color->key);
show_color_buttons (text_color);
}
}
else
{
if (!WMIsPLArray (value))
{
proplist_t pl;
pl = WMCreatePLArray (WMCreatePLString ("function"),
WMCreatePLString ("libwmfun.so"),
WMCreatePLString ("drawPlainString"),
WMCreatePLString ("white"),
WMCreatePLString ("black"),
WMCreatePLString ("red"), NULL);
WMPutInPLDictionary (windowmaker, text_color->key, pl);
toggle_save (changed = YES, text_color->key);
show_color_buttons (text_color);
}
}
}
static void
show_color_buttons (text_color_t *text_color)
{
proplist_t value = WMGetFromPLDictionary (windowmaker, text_color->key);
if (WMIsPLArray (value)) /* check syntax of value */
{
if (!(WMGetPropListItemCount (value) == 6
&& strcaseeq (WMGetFromPLString (WMGetFromPLArray (value, 0)),
"function")
&& strncaseeq (WMGetFromPLString (WMGetFromPLArray (value, 1)),
"libwmfun", strlen ("libwmfun"))
&& strcaseeq (WMGetFromPLString (WMGetFromPLArray (value, 2)),
"drawPlainString")))
{
proplist_t pl;
pl = WMCreatePLArray (WMCreatePLString ("function"),
WMCreatePLString ("libwmfun.so"),
WMCreatePLString ("drawPlainString"),
WMCreatePLString ("white"),
WMCreatePLString ("black"),
WMCreatePLString ("red"), NULL);
WMPutInPLDictionary (windowmaker, text_color->key, pl);
value = pl;
}
set_option_menu_default (GTK_OPTION_MENU (text_color->option_menu),
color_types, color_types [TCOLOR_COLORSET]);
/*
* Set colors
*/
{
GtkWidget *preview;
preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [0]));
fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 3)));
gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 3));
preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [1]));
fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 4)));
gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 4));
preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [2]));
fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 5)));
gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 5));
}
gtk_widget_show (text_color->color_set [0]);
gtk_widget_show (text_color->color_set [1]);
gtk_widget_show (text_color->color_set [2]);
gtk_widget_hide (text_color->solid_color);
}
else
{
gtk_widget_hide (text_color->color_set [0]);
gtk_widget_hide (text_color->color_set [1]);
gtk_widget_hide (text_color->color_set [2]);
gtk_widget_show (text_color->solid_color);
set_option_menu_default (GTK_OPTION_MENU (text_color->option_menu),
color_types, color_types [TCOLOR_SIMPLE]);
/*
* Set default color
*/
{
GtkWidget *preview;
preview = gtk_object_get_user_data (GTK_OBJECT (text_color->solid_color));
fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (value));
gtk_object_set_user_data (GTK_OBJECT (preview), value);
}
}
}
#endif /* HAVE_LIBWMFUN */
static void
append_dialog (GtkWidget *container, GtkWidget *left, GtkWidget *right,
GtkAttachOptions attach)
{
if (GTK_IS_TABLE (container))
{
unsigned *number = (unsigned *) gtk_object_get_user_data (GTK_OBJECT (container));
unsigned row, col;
row = ++*number;
col = (row % 2) * 2;
row /= 2;
gtk_table_attach (GTK_TABLE (container), left, col, col + 1, row, row + 1,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
gtk_table_attach (GTK_TABLE (container), right, col + 1, col + 2, row, row + 1,
attach, attach, 0, 0);
gtk_widget_show_all (left);
gtk_widget_show_all (right);
}
else if (GTK_IS_VBOX (container))
{
GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (container), 5);
gtk_box_pack_start (GTK_BOX (hbox), right, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), left, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (container), hbox, FALSE, FALSE, 0);
gtk_widget_show_all (hbox);
}
}
static void
set_bool (GtkWidget *widget, gpointer ptr)
/*
* Update boolean value.
*
* No return value.
*/
{
proplist_t key = (proplist_t) ptr;
char *text = GTK_TOGGLE_BUTTON (widget)->active ? "Yes" : "No";
proplist_t pl = WMCreatePLString (text);
WMPutInPLDictionary (windowmaker, key, pl);
WMReleasePropList (pl);
toggle_save (changed = YES, key);
if (strcaseeq (WMGetFromPLString (key), "NewStyle"))
check_widgetstyle ();
}
static void
set_ibool (GtkWidget *widget, gpointer ptr)
/*
* Update boolean value.
*
* No return value.
*/
{
proplist_t key = (proplist_t) ptr;
char *text = GTK_TOGGLE_BUTTON (widget)->active ? "No" : "Yes";
proplist_t pl = WMCreatePLString (text);
WMPutInPLDictionary (windowmaker, key, pl);
WMReleasePropList (pl);
toggle_save (changed = YES, key);
if (strcaseeq (WMGetFromPLString (key), "NewStyle"))
check_widgetstyle ();
}
static void
set_string (GtkWidget *widget, gpointer ptr)
/*
* Update string value.
*
* No return value.
*/
{
proplist_t key = (proplist_t) ptr;
char *text = gtk_object_get_user_data (GTK_OBJECT (widget));
proplist_t pl = WMCreatePLString (text);
WMPutInPLDictionary (windowmaker, key, pl);
WMReleasePropList (pl);
toggle_save (changed = YES, key);
}
static void
set_int (GtkWidget *widget, gpointer ptr)
/*
* Update unsigned value.
*
* No return value.
*/
{
proplist_t key = (proplist_t) ptr;
GtkSpinButton *spinner;
int val;
char tmp [MAXSTRLEN];
spinner = GTK_SPIN_BUTTON (gtk_object_get_user_data (GTK_OBJECT (widget)));
val = gtk_spin_button_get_value_as_int (spinner);
sprintf (tmp, "%d", val);
if (WMIsPLArray (WMGetFromPLDictionary (windowmaker, key)))
{
proplist_t array = WMGetFromPLDictionary (windowmaker, key);
unsigned n;
n = (GtkWidget *) gtk_object_get_user_data (GTK_OBJECT (spinner))
- GTK_WIDGET (spinner);
WMDeleteFromPLArray (array, n);
WMInsertInPLArray (array, n, WMCreatePLString (tmp));
}
else
{
proplist_t pl = WMCreatePLString (tmp);
WMPutInPLDictionary (windowmaker, key, pl);
WMReleasePropList (pl);
}
toggle_save (changed = YES, key);
}
static void
set_entry_text (GtkWidget *widget, gpointer ptr)
/*
* Update string value.
*
* No return value.
*/
{
proplist_t element;
proplist_t key = (proplist_t) ptr;
proplist_t array = WMGetFromPLDictionary (windowmaker, key);
element = WMCreatePLString ((char *) gtk_entry_get_text (GTK_ENTRY (widget)));
if (WMIsPLArray (array))
{
WMDeleteFromPLArray (array, 1); /* filename */
WMInsertInPLArray (array, 1, element);
}
else
{
WMPutInPLDictionary (windowmaker, key, element);
WMReleasePropList (element);
}
toggle_save (changed = YES, key);
}
static void
fontsel_dialog (GtkWidget *widget, gpointer ptr)
{
static GtkWidget *fontsel = NULL;
if (!fontsel)
{
GtkWidget *entry;
const char *text;
char *pangotext;
GtkFontSelectionDialog *fs;
entry = GTK_WIDGET (ptr);
text = gtk_entry_get_text (GTK_ENTRY (entry));
pangotext = malloc (strlen (text) + 1);
fontsel = gtk_font_selection_dialog_new (_("Font selection"));
fs = GTK_FONT_SELECTION_DIALOG (fontsel);
gtk_window_set_position (GTK_WINDOW (fontsel), GTK_WIN_POS_MOUSE);
gtk_object_set_user_data (GTK_OBJECT (fontsel), entry);
convert_fontconfig_to_pango (text, pangotext);
gtk_font_selection_dialog_set_font_name (fs, pangotext);
free (pangotext);
gtk_object_set_data (GTK_OBJECT (entry), "fontsel", fontsel);
gtk_signal_connect (GTK_OBJECT (fontsel), "destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
&fontsel);
gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked",
GTK_SIGNAL_FUNC (set_fontname), fontsel);
gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (fontsel));
gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (fontsel));
}
if (!GTK_WIDGET_VISIBLE (fontsel))
gtk_widget_show (fontsel);
else
gtk_widget_destroy (fontsel);
}
struct font_attr_t {
int slant;
int weight;
int width;
int size;
};
/* Function to convert from GTK+ 2's Pango font names to the slightly
* different format used by WindowMaker 0.90 (fontconfig?)
* fcname must already be allocated and have a length of at least
* strlen(pangoname) + 50. */
static void
convert_pango_to_fontconfig (const char *pangoname, char *fcname)
{
const char * posn;
char * base;
int size;
struct font_attr_t attr = { 0, 80, 100, 12 };
posn = pangoname + strlen(pangoname) - 1;
while (posn > pangoname && isdigit(*posn)) posn--;
size = atoi(posn);
if (size) attr.size = size;
/* check for italic */
if (posn - pangoname > 6 && strncmp(posn - 6, "Italic", 6) == 0) {
attr.slant = 100;
posn -= 7;
}
/* check for condensed */
if (posn - pangoname > 9 && strncmp(posn - 9, "Condensed", 9) == 0) {
attr.width = 75;
posn -= 10;
}
/* check for bold */
if (posn - pangoname > 9 && strncmp(posn - 9, "Semi-Bold", 9) == 0) {
attr.weight = 100;
posn -= 10;
}
else if (posn - pangoname > 4 && strncmp(posn - 4, "Bold", 4) == 0) {
attr.weight = 200;
posn -= 5;
}
if (posn > pangoname && *(posn - 1) == ',')
posn--;
base = malloc(posn - pangoname + 10);
strncpy(base, pangoname, posn - pangoname);
base[posn - pangoname] = 0;
/* Sans and Serif aliases are slightly different in Pango vs. fontconfig */
if (strcmp(base, "Sans") == 0)
strcpy(base, "sans serif");
else if (strcmp(base, "Serif") == 0)
strcpy(base, "serif");
sprintf(fcname, "%s:slant=%d:weight=%d:width=%d:pixelsize=%d",
base, attr.slant, attr.weight, attr.width, attr.size);
free(base);
}
/* Function to convert from WindowMaker 0.90's fontconfig font name format
* to that used by Pango in GTK+ 2.
* pangoname must already be allocated and have a length of at least
* strlen(fcname). */
static void
convert_fontconfig_to_pango (const char *fcname, char *pangoname)
{
char * base, * posn, * posn2;
char slant[8] = { 0 }, weight[11] = { 0 }, width[11] = { 0 };
int size = 12;
/* Find the first ':' or ',' and assume this is the end of the font name */
posn = strchr(fcname, ':');
posn2 = strchr(fcname, ',');
if (!posn || posn2 && posn2 < posn)
posn = posn2;
if (posn) {
base = malloc(posn - fcname + 1);
strncpy(base, fcname, posn - fcname);
base[posn - fcname] = 0;
}
else {
/* maybe XLFD, don't touch */
strcpy(pangoname, fcname);
return;
}
/* Sans and Serif aliases are slightly different in Pango vs. fontconfig */
if (strcmp(base, "sans serif") == 0)
strcpy(base, "Sans");
else if (strcmp(base, "serif") == 0)
strcpy(base, "Serif");
if ((posn = strstr(fcname, ":weight="))) {
int wt = atoi(posn + 8);
if (wt >= 150)
strcpy(weight, "Bold ");
else if (wt >= 90)
strcpy(weight, "Semi-Bold ");
}
if ((posn = strstr(fcname, ":bold")))
strcpy(weight, "Bold ");
if ((posn = strstr(fcname, ":width=")))
if (atoi(posn + 7) < 90)
strcpy(width, "Condensed ");
if ((posn = strstr(fcname, ":slant=")))
if (atoi(posn + 7))
strcpy(slant, "Italic ");
if ((posn = strstr(fcname, ":pixelsize="))) {
int sz = atoi(posn + 11);
if (sz) size = sz;
}
sprintf(pangoname, "%s, %s%s%s%d", base, weight, width, slant, size);
free(base);
}
static void
set_fontname (GtkWidget *widget, gpointer ptr)
{
GtkWidget *fontsel = GTK_WIDGET (ptr);
GtkWidget *entry = gtk_object_get_user_data (GTK_OBJECT (fontsel));
gchar *fontname;
gchar *fontconfigname;
fontname = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (fontsel));
fontconfigname = malloc(strlen(fontname) + 50);
convert_pango_to_fontconfig(fontname, fontconfigname);
gtk_entry_set_text (GTK_ENTRY (entry), fontconfigname);
free(fontconfigname);
}
static void
update_entry (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
if (WMIsPLString (value))
gtk_entry_set_text (GTK_ENTRY (ptr), WMGetFromPLString (value));
}
static void
update_color (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
if (WMIsPLString (value))
{
GtkWidget *preview = GTK_WIDGET (ptr);
//the below wasn't used; was it supposed to be?
//proplist_t oldvalue = gtk_object_get_user_data (GTK_OBJECT (preview));
WMRetainPropList (value);
gtk_object_set_user_data (GTK_OBJECT (preview), value);
fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (value));
WMPutInPLDictionary (windowmaker, key, value);
toggle_save (changed = YES, key);
}
}
#ifdef HAVE_LIBWMFUN
static void
update_text_color (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
if (WMIsPLString (value) || WMIsPLArray (value))
{
text_color_t *text_color = (text_color_t *) ptr;
WMPutInPLDictionary (windowmaker, key, value);
toggle_save (changed = YES, key);
show_color_buttons (text_color);
}
}
#endif /* HAVE_LIBWMFUN */
static void
update_boolean (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
if (WMIsPLString (value))
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr),
convert_bool (value));
set_bool (GTK_WIDGET (ptr), key);
}
}
static void
update_iboolean (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
if (WMIsPLString (value))
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr),
convert_bool (value) ? FALSE : TRUE);
set_bool (GTK_WIDGET (ptr), key);
}
}
static void
update_int (proplist_t key, gpointer ptr, proplist_t value,
const char *path)
{
GtkEntry **entry = (GtkEntry **) ptr;
if (WMIsPLString (value))
gtk_entry_set_text (entry [0], WMGetFromPLString (value));
else if (WMIsPLArray (value))
{
unsigned n;
for (n = 0; n < WMGetPropListItemCount (value); n++)
if (entry [n])
gtk_entry_set_text (entry [n],
WMGetFromPLString (WMGetFromPLArray (value, n)));
else
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1