diff options
Diffstat (limited to 'app/wlib/gtklib')
49 files changed, 10530 insertions, 8883 deletions
diff --git a/app/wlib/gtklib/CMakeLists.txt b/app/wlib/gtklib/CMakeLists.txt index cce9866..a8cae9f 100644 --- a/app/wlib/gtklib/CMakeLists.txt +++ b/app/wlib/gtklib/CMakeLists.txt @@ -4,26 +4,51 @@ FILE(GLOB HEADERS *.h)  INCLUDE (FindGTKUnixPrint.cmake)  SET(SOURCES -	gtkbitmap.c -	gtkbutton.c -	gtkcolor.c -	gtkdraw-cairo.c +	bitmap.c +	boxes.c +	button.c +	color.c +	control.c +	droplist.c	  	filesel.c -	gtkfont.c -	gtkhelp.c -	gtklist.c -	gtkmenu.c -	gtkmisc.c -	gtksimple.c -	gtksingle.c -	gtksplash.c -	gtktext.c -	gtkwindow.c -	gtkxpm.c +	font.c +	help.c +	lines.c +	list.c +	liststore.c +	main.c +	menu.c	 +	message.c +	notice.c +	pixbuf.c +	png.c  	print.c +	single.c +	splash.c +	text.c +	timer.c +	tooltip.c	 +	treeview.c +	util.c +	window.c  	wpref.c +# cproto and cppcheck + +# end of refactored sources	 +	gtkdraw-cairo.c  	) +IF(APPLE) +	SET(SOURCES  +		${SOURCES} +		osxhelp.c) +	 +ELSE(APPLE) +	SET(SOURCES  +		${SOURCES} +		ixhelp.c) +ENDIF(APPLE) +  SET_SOURCE_FILES_PROPERTIES(wpref.c PROPERTIES COMPILE_FLAGS -DEXPORT=)  INCLUDE_DIRECTORIES(${XTrkCAD_BINARY_DIR}) @@ -35,3 +60,4 @@ ADD_LIBRARY(xtrkcad-wlib ${HEADERS} ${SOURCES})  TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_LIBRARIES})  TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_UNIX_PRINT_LIBRARIES})  TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_WEBKIT_LIBRARIES}) + diff --git a/app/wlib/gtklib/bitmap.c b/app/wlib/gtklib/bitmap.c new file mode 100644 index 0000000..dc7236b --- /dev/null +++ b/app/wlib/gtklib/bitmap.c @@ -0,0 +1,136 @@ +/** \file bitmap.c + * Bitmap creation + */ +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2009 Daniel Spagnol, 2013 Martin Fischer + * + *  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-1307, USA. + */ + +#include <stdlib.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +struct wBitmap_t { +	WOBJ_COMMON +}; + +/** + * Create a static control for displaying a bitmap. + * + * \param parent IN parent window + * \param x, y   IN position in parent window + * \param option IN ignored for now + * \param iconP  IN icon to use in XPM format + * \return    the control + */ + +wControl_p +wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP ) +{ +	wBitmap_p bt; +	GdkPixbuf *pixbuf; +	GtkWidget *image; +	 +	bt = wlibAlloc( parent, B_BITMAP, x, y, NULL, sizeof *bt, NULL ); +	bt->w = iconP->w; +	bt->h = iconP->h; +	bt->option = options; +	 +	/* +	 * Depending on the platform, parent->widget->window might still be null  +	 * at this point. The window allocation should be forced before creating +	 * the pixmap. +	 */ +	if ( gtk_widget_get_window( parent->widget ) == NULL ) +		gtk_widget_realize( parent->widget ); /* force allocation, if pending */ +	 +	/* create the bitmap from supplied xpm data */ +	pixbuf = gdk_pixbuf_new_from_xpm_data( (const char **)iconP->bits ); +	image = gtk_image_new_from_pixbuf( pixbuf ); +	gtk_widget_show( image ); +	g_object_unref( (gpointer)pixbuf ); +	 +	bt->widget = gtk_fixed_new(); +	gtk_widget_show( bt->widget ); +	gtk_container_add( GTK_CONTAINER(bt->widget), image ); +	 +	wlibComputePos( (wControl_p)bt ); +	wlibControlGetSize( (wControl_p)bt ); +	gtk_fixed_put( GTK_FIXED( parent->widget ), bt->widget, bt->realX, bt->realY ); +	 +	return( (wControl_p)bt ); +} + +/** + * Create a two-tone icon + *  + * \param w IN width of icon + * \param h IN height of icon + * \param bits IN bitmap + * \param color IN color  + * \returns icon handle + */ + +wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color ) +{ +	wIcon_p ip; +	ip = (wIcon_p)malloc( sizeof *ip ); +	ip->gtkIconType = gtkIcon_bitmap; +	ip->w = w; +	ip->h = h; +	ip->color = color; +	ip->bits = bits; +	return ip; +} + +/** + * Create an icon from a pixmap + * \param pm IN pixmap + * \returns icon handle + */ + +wIcon_p wIconCreatePixMap( char *pm[] ) +{ +	wIcon_p ip; +	ip = (wIcon_p)malloc( sizeof *ip ); +	ip->gtkIconType = gtkIcon_pixmap; +	ip->w = 0; +	ip->h = 0; +	ip->color = 0; +	ip->bits = pm; +	return ip; +} + +/** + * Set the color a two-tone icon + *  + * \param ip IN icon handle + * \param color IN color to use + */ + +void wIconSetColor( wIcon_p ip, wDrawColor color ) +{ +	ip->color = color; +} + diff --git a/app/wlib/gtklib/boxes.c b/app/wlib/gtklib/boxes.c new file mode 100644 index 0000000..cce6649 --- /dev/null +++ b/app/wlib/gtklib/boxes.c @@ -0,0 +1,203 @@ +/** \file boxes.c + * Window for drawing a rectangle + */ + +/* 	XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis, + *                2016 Martin Fischer <m_fischer@sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <cairo.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +struct wBox_t { +    WOBJ_COMMON +    wBoxType_e boxTyp; +}; + +#define B (1) +#define W (2) +#define SETCOLOR(ST, S, N ) \ +		if (colors[ST][S][N] == B ) { \ +			cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); \ +		} else {	\ +			cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); \ +		} + +/** + * Set size of box window + * + * \param b IN window handle + * \param w IN new width + * \param h IN new height + * \return + * + */ + +void wBoxSetSize( +    wBox_p b,	 +    wPos_t w,	 +    wPos_t h)	 +{ +    b->w = w; +    b->h = h; +} + +/** + * Draw the box + * \todo too many strokes, remove and test + * + * \param win IN window handle + * \param style IN frame style + * \param x IN x position + * \param y IN y position + * \param w IN width + * \param h IN height + * \return + */ + +void wlibDrawBox( +    wWin_p win, +    wBoxType_e style, +    wPos_t x, +    wPos_t y, +    wPos_t w, +    wPos_t h) +{ +    wPos_t x0, y0, x1, y1; +    GdkDrawable * window; +    cairo_t *cr; +    static char colors[8][4][2] = { +        { /* ThinB  */ {B,0}, {B,0}, {B,0}, {B,0} }, +        { /* ThinW  */ {W,0}, {W,0}, {W,0}, {W,0} }, +        { /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} }, +        { /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} }, +        { /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} }, +        { /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} }, +        { /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} }, +        { /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} } +    }; +    window = gtk_widget_get_window(win->widget); +    cr = gdk_cairo_create(window); +    cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); +    cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); +    cairo_set_line_width(cr, 1.0); +    x0 = x; +    x1 = x+w; +    y0 = y; +    y1 = y+h; +    SETCOLOR(style, 0, 0); +    cairo_move_to(cr, x0, y0); +    cairo_line_to(cr, x0, y1); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 1, 0); +    cairo_move_to(cr, x0, y0); +    cairo_line_to(cr, x1, y0); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 2, 0); +    cairo_move_to(cr, x1, y1); +    cairo_line_to(cr, x0+1, y1); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 3, 0); +    cairo_move_to(cr, x1, y1-1); +    cairo_line_to(cr, x1, y0+1); +    cairo_stroke_preserve(cr); + +    if (style < wBoxThickB) { +        return; +    } + +    x0++; +    y0++; +    x1--; +    y1--; +    SETCOLOR(style, 0, 1); +    cairo_move_to(cr, x0, y0); +    cairo_line_to(cr, x0, y1); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 1, 1); +    cairo_move_to(cr, x0+1, y0); +    cairo_line_to(cr, x1, y0); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 2, 1); +    cairo_move_to(cr, x1, y1); +    cairo_line_to(cr, x0+1, y1); +    cairo_stroke_preserve(cr); +    SETCOLOR(style, 3, 1); +    cairo_move_to(cr, x1, y1-1); +    cairo_line_to(cr, x1, y0+1); +    cairo_stroke_preserve(cr); +    cairo_destroy(cr); +} + +/** + * Force repainting of box window + * + * \param b IN box window + * \return + */ + +static void boxRepaint(wControl_p b) +{ +    wBox_p bb = (wBox_p)(b); +    wWin_p win = bb->parent; +    wlibDrawBox(win, bb->boxTyp, bb->realX, bb->realY, bb->w, bb->h); +} + +/** + * Create new box + * + * \param parent IN parent window + * \param bx IN x position + * \param by IN y position + * \param labelStr IN label text (ignored) + * \param boxTyp IN style + * \param bw IN x width + * \param by IN y width + * \return window handle for newly created box + */ + +wBox_p wBoxCreate( +    wWin_p	parent, +    wPos_t	bx, +    wPos_t	by, +    const char	* labelStr, +    wBoxType_e boxTyp, +    wPos_t	bw, +    wPos_t	bh) +{ +    wBox_p b; +    b = (wBox_p)wlibAlloc(parent, B_BOX, bx, by, labelStr, sizeof *b, NULL); +    wlibComputePos((wControl_p)b); +    b->boxTyp = boxTyp; +    b->w = bw; +    b->h = bh; +    b->repaintProc = boxRepaint; +    wlibAddButton((wControl_p)b); +    return b; +} diff --git a/app/wlib/gtklib/button.c b/app/wlib/gtklib/button.c new file mode 100644 index 0000000..d9f4880 --- /dev/null +++ b/app/wlib/gtklib/button.c @@ -0,0 +1,630 @@ +/** \file button.c + * Toolbar button creation and handling + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +#include "i18n.h" + +#define MIN_BUTTON_WIDTH (80) + +/* + ***************************************************************************** + * + * Simple Buttons + * + ***************************************************************************** + */ + +/** + * Set the state of the button + * + * \param bb IN the button + * \param value IN TRUE for active, FALSE for inactive + */ + +void wButtonSetBusy(wButton_p bb, int value) +{ +    bb->recursion++; +    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bb->widget), value); +    bb->recursion--; +    bb->busy = value; +} + +/** + * Set the label of a button, does also allow to set an icon + * + * \param widget IN + * \param option IN + * \param labelStr IN + * \param labelG IN + * \param imageG IN + */ + +void wlibSetLabel( +    GtkWidget *widget, +    long option, +    const char * labelStr, +    GtkLabel * * labelG, +    GtkWidget * * imageG) +{ +    wIcon_p bm; +    GdkBitmap * mask; + +    if (widget == 0) { +        abort(); +    } + +    if (labelStr) { +        if (option&BO_ICON) { +            GdkPixbuf *pixbuf; + +            bm = (wIcon_p)labelStr; + +            if (bm->gtkIconType == gtkIcon_pixmap) { +                pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)bm->bits); +            } else { +                pixbuf = wlibPixbufFromXBM( bm ); +            } +            if (*imageG==NULL) { +                *imageG = gtk_image_new_from_pixbuf(pixbuf); +                gtk_container_add(GTK_CONTAINER(widget), *imageG); +                gtk_widget_show(*imageG); +            } else { +                gtk_image_set_from_pixbuf(GTK_IMAGE(*imageG), pixbuf); +            } + +            g_object_unref(pixbuf); +        } else { +            if (*labelG==NULL) { +                *labelG = (GtkLabel*)gtk_label_new(wlibConvertInput(labelStr)); +                gtk_container_add(GTK_CONTAINER(widget), (GtkWidget*)*labelG); +                gtk_widget_show((GtkWidget*)*labelG); +            } else { +                gtk_label_set_text(*labelG, wlibConvertInput(labelStr)); +            } +        } +    } +} + +/** + * Change only the text label of a button + * \param bb IN button handle + * \param labelStr IN new label string + */ + +void wButtonSetLabel(wButton_p bb, const char * labelStr) +{ +    wlibSetLabel(bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG); +} + +/** + * Perform the user callback function + * + * \param bb IN button handle + */ + +void wlibButtonDoAction( +    wButton_p bb) +{ +    if (bb->action) { +        bb->action(bb->data); +    } +} + +/** + * Signal handler for button push + * \param widget IN the widget + * \param value IN the button handle (same as widget???) + */ + +static void pushButt( +    GtkWidget *widget, +    gpointer value) +{ +    wButton_p b = (wButton_p)value; + +    if (debugWindow >= 2) { +        printf("%s button pushed\n", b->labelStr?b->labelStr:"No label"); +    } + +    if (b->recursion) { +        return; +    } + +    if (b->action) { +        b->action(b->data); +    } + +    if (!b->busy) { +        b->recursion++; +        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->widget), FALSE); +        b->recursion--; +    } +} + +/** + * Create a button + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param width IN Width of button + * \param action IN Callback + * \param data IN User data as context + * \returns button widget + */ + +wButton_p wButtonCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long 	option, +    wPos_t 	width, +    wButtonCallBack_p action, +    void 	* data) +{ +    wButton_p b; +    b = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, data); +    b->option = option; +    b->action = action; +    wlibComputePos((wControl_p)b); + +    b->widget = gtk_toggle_button_new(); +    g_signal_connect(GTK_OBJECT(b->widget), "clicked", +                         G_CALLBACK(pushButt), b); +    if (width > 0) { +        gtk_widget_set_size_request(b->widget, width, -1); +    } +    if( labelStr ){ +        wButtonSetLabel(b, labelStr); +    } + +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); + +    if (option & BB_DEFAULT) { +        gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT); +        gtk_widget_grab_default(b->widget); +        gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget); +    } + +    wlibControlGetSize((wControl_p)b); + +    if (width == 0 && b->w < MIN_BUTTON_WIDTH && (b->option&BO_ICON)==0) { +        b->w = MIN_BUTTON_WIDTH; +        gtk_widget_set_size_request(b->widget, b->w, b->h); +    } + +    gtk_widget_show(b->widget); +    wlibAddButton((wControl_p)b); +    wlibAddHelpString(b->widget, helpStr); +    return b; +} + + +/* + ***************************************************************************** + * + * Choice Boxes + * + ***************************************************************************** + */ + +struct wChoice_t { +    WOBJ_COMMON +    long *valueP; +    wChoiceCallBack_p action; +    int recursion; +}; + + +/** + * Get the state of a group of buttons. If the group consists of + * radio buttons, the return value is the index of the selected button + * or -1 for none. If toggle buttons are checked, a bit is set for each + * button that is active. + * + * \param bc IN + * \returns state of group + */ + +static long choiceGetValue( +    wChoice_p bc) +{ +    GList * child, * children; +    long value, inx; + +    if (bc->type == B_TOGGLE) { +        value = 0; +    } else { +        value = -1; +    } + +    for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0; +            child; child=child->next,inx++) { +        if (gtk_toggle_button_get_active(child->data)) { +            if (bc->type == B_TOGGLE) { +                value |= (1<<inx); +            } else { +                value = inx; +            } +        } +    } + +    if (children) { +        g_list_free(children); +    } + +    return value; +} + +/** + * Set the active radio button in a group + * + * \param bc IN button group + * \param value IN index of active button + */ + +void wRadioSetValue( +    wChoice_p bc,		/* Radio box */ +    long value)		/* Value */ +{ +    GList * child, * children; +    long inx; + +    for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0; +            child; child=child->next,inx++) { +        if (inx == value) { +            bc->recursion++; +            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data), TRUE); +            bc->recursion--; +        } +    } + +    if (children) { +        g_list_free(children); +    } +} + +/** + * Get the active button from a group of radio buttons + * + * \param bc IN + * \returns + */ + +long wRadioGetValue( +    wChoice_p bc)		/* Radio box */ +{ +    return choiceGetValue(bc); +} + +/** + * Set a group of toggle buttons from a bitfield + * + * \param bc IN button group + * \param value IN bitfield + */ + +void wToggleSetValue( +    wChoice_p bc,		/* Toggle box */ +    long value)		/* Values */ +{ +    GList * child, * children; +    long inx; +    bc->recursion++; + +    for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0; +            child; child=child->next,inx++) { +        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data), +                                     (value&(1<<inx))!=0); +    } + +    if (children) { +        g_list_free(children); +    } + +    bc->recursion--; +} + + +/** + * Get the active buttons from a group of toggle buttons + * + * \param b IN + * \returns + */ + +long wToggleGetValue( +    wChoice_p b)		/* Toggle box */ +{ +    return choiceGetValue(b); +} + +/** + * Signal handler for button selection in radio buttons and toggle + * button group + * + * \param widget IN the button group + * \param b IN user data (button group????) + * \returns always 1 + */ + +static int pushChoice( +    GtkWidget *widget, +    gpointer b) +{ +    wChoice_p bc = (wChoice_p)b; +    long value = choiceGetValue(bc); + +    if (debugWindow >= 2) { +        printf("%s choice pushed = %ld\n", bc->labelStr?bc->labelStr:"No label", +               value); +    } + +    if (bc->type == B_RADIO && +            !(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))) { +        return 1; +    } + +    if (bc->recursion) { +        return 1; +    } + +    if (bc->valueP) { +        *bc->valueP = value; +    } + +    if (bc->action) { +        bc->action(value, bc->data); +    } + +    return 1; +} + +/** + * Signal handler used to draw a frame around a widget, used to visually + * group several buttons together + * + * \param b IN  widget + */ + +static void choiceRepaint( +    wControl_p b) +{ +    wChoice_p bc = (wChoice_p)b; + +    if (gtk_widget_get_visible(b->widget)) { +        wlibDrawBox(bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1); +    } +} + +/** + * Create a group of radio buttons. + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param labels IN Labels + * \param valueP IN Selected value + * \param action IN Callback + * \param data IN User data as context + * \returns radio button widget + */ + +wChoice_p wRadioCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long	option, +    const char	**labels, +    long	*valueP, +    wChoiceCallBack_p action, +    void 	*data) +{ +    wChoice_p b; +    const char ** label; +    GtkWidget *butt0=NULL, *butt; + +    if ((option & BC_NOBORDER)==0) { +        if (x>=0) { +            x++; +        } else { +            x--; +        } + +        if (y>=0) { +            y++; +        } else { +            y--; +        } +    } + +    b = wlibAlloc(parent, B_RADIO, x, y, labelStr, sizeof *b, data); +    b->option = option; +    b->action = action; +    b->valueP = valueP; +    wlibComputePos((wControl_p)b); + +    if (option&BC_HORZ) { +        b->widget = gtk_hbox_new(FALSE, 0); +    } else { +        b->widget = gtk_vbox_new(FALSE, 0); +    } + +    if (b->widget == 0) { +        abort(); +    } + +    for (label=labels; *label; label++) { +        butt = gtk_radio_button_new_with_label( +                   butt0?gtk_radio_button_get_group(GTK_RADIO_BUTTON(butt0)):NULL, _(*label)); + +        if (butt0==NULL) { +            butt0 = butt; +        } + +        gtk_box_pack_start(GTK_BOX(b->widget), butt, TRUE, TRUE, 0); +        gtk_widget_show(butt); +        g_signal_connect(GTK_OBJECT(butt), "toggled", +                         G_CALLBACK(pushChoice), b); +        wlibAddHelpString(butt, helpStr); +    } + +    if (option & BB_DEFAULT) { +        gtk_widget_set_can_default(b->widget, TRUE); +        gtk_widget_grab_default(b->widget); +    } + +    if (valueP) { +        wRadioSetValue(b, *valueP); +    } + +    if ((option & BC_NOBORDER)==0) { +        b->repaintProc = choiceRepaint; +        b->w += 2; +        b->h += 2; +    } + +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); +    wlibControlGetSize((wControl_p)b); + +    if (labelStr) { +        b->labelW = wlibAddLabel((wControl_p)b, labelStr); +    } + +    gtk_widget_show(b->widget); +    wlibAddButton((wControl_p)b); +    return b; +} + +/** + * Create a group of toggle buttons. + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param labels IN Labels + * \param valueP IN Selected value + * \param action IN Callback + * \param data IN User data as context + * \returns toggle button widget + */ + +wChoice_p wToggleCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long	option, +    const char	**labels, +    long	*valueP, +    wChoiceCallBack_p action, +    void 	*data) +{ +    wChoice_p b; +    const char ** label; + +    if ((option & BC_NOBORDER)==0) { +        if (x>=0) { +            x++; +        } else { +            x--; +        } + +        if (y>=0) { +            y++; +        } else { +            y--; +        } +    } + +    b = wlibAlloc(parent, B_TOGGLE, x, y, labelStr, sizeof *b, data); +    b->option = option; +    b->action = action; +    wlibComputePos((wControl_p)b); + +    if (option&BC_HORZ) { +        b->widget = gtk_hbox_new(FALSE, 0); +    } else { +        b->widget = gtk_vbox_new(FALSE, 0); +    } + +    if (b->widget == 0) { +        abort(); +    } + +    for (label=labels; *label; label++) { +        GtkWidget *butt; + +        butt = gtk_check_button_new_with_label(_(*label)); +        gtk_box_pack_start(GTK_BOX(b->widget), butt, TRUE, TRUE, 0); +        gtk_widget_show(butt); +        g_signal_connect(GTK_OBJECT(butt), "toggled", +                         G_CALLBACK(pushChoice), b); +        wlibAddHelpString(butt, helpStr); +    } + +    if (valueP) { +        wToggleSetValue(b, *valueP); +    } + +    if ((option & BC_NOBORDER)==0) { +        b->repaintProc = choiceRepaint; +        b->w += 2; +        b->h += 2; +    } + +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); +    wlibControlGetSize((wControl_p)b); + +    if (labelStr) { +        b->labelW = wlibAddLabel((wControl_p)b, labelStr); +    } + +    gtk_widget_show(b->widget); +    wlibAddButton((wControl_p)b); +    return b; +} diff --git a/app/wlib/gtklib/color.c b/app/wlib/gtklib/color.c new file mode 100644 index 0000000..64b96ef --- /dev/null +++ b/app/wlib/gtklib/color.c @@ -0,0 +1,466 @@ +/** \file color.c + * code for the color selection dialog and color button + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ +#include <assert.h> +#include <stdlib.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +wDrawColor wDrawColorWhite; +wDrawColor wDrawColorBlack; + +#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) ) + +#define MAX_COLOR_DISTANCE (3) + +static GArray *colorMap_garray = NULL; // Change to use glib array + +static colorMap_t colorMap[] = { +    { 255, 255, 255 },	/* White */ +    {   0,   0,   0 },	/* Black */ +    { 255,   0,   0 },	/* Red */ +    {   0, 255,   0 },	/* Green */ +    {   0,   0, 255 },	/* Blue */ +    { 255, 255,   0 },	/* Yellow */ +    { 255,   0, 255 },	/* Purple */ +    {   0, 255, 255 },	/* Aqua */ +    { 128,   0,   0 },	/* Dk. Red */ +    {   0, 128,   0 },	/* Dk. Green */ +    {   0,   0, 128 },	/* Dk. Blue */ +    { 128, 128,   0 },	/* Dk. Yellow */ +    { 128,   0, 128 },	/* Dk. Purple */ +    {   0, 128, 128 },	/* Dk. Aqua */ +    {  65, 105, 225 },      /* Royal Blue */ +    {   0, 191, 255 },	/* DeepSkyBlue */ +    { 125, 206, 250 },	/* LightSkyBlue */ +    {  70, 130, 180 },	/* Steel Blue */ +    { 176, 224, 230 },	/* Powder Blue */ +    { 127, 255, 212 },	/* Aquamarine */ +    {  46, 139,  87 },	/* SeaGreen */ +    { 152, 251, 152 },	/* PaleGreen */ +    { 124, 252,   0 },	/* LawnGreen */ +    {  50, 205,  50 },	/* LimeGreen */ +    {  34, 139,  34 },	/* ForestGreen */ +    { 255, 215,   0 },	/* Gold */ +    { 188, 143, 143 },	/* RosyBrown */ +    { 139, 69, 19 },	/* SaddleBrown */ +    { 245, 245, 220 },	/* Beige */ +    { 210, 180, 140 },	/* Tan */ +    { 210, 105, 30 },	/* Chocolate */ +    { 165, 42, 42 },	/* Brown */ +    { 255, 165, 0 },	/* Orange */ +    { 255, 127, 80 },	/* Coral */ +    { 255, 99, 71 },	/* Tomato */ +    { 255, 105, 180 },	/* HotPink */ +    { 255, 192, 203 },	/* Pink */ +    { 176, 48, 96 },	/* Maroon */ +    { 238, 130, 238 },	/* Violet */ +    { 160, 32, 240 },	/* Purple */ +    {  16,  16,  16 },	/* Gray */ +    {  32,  32,  32 },	/* Gray */ +    {  48,  48,  48 },	/* Gray */ +    {  64,  64,  64 },	/* Gray */ +    {  80,  80,  80 },	/* Gray */ +    {  96,  96,  96 },	/* Gray */ +    { 112, 112, 122 },	/* Gray */ +    { 128, 128, 128 },	/* Gray */ +    { 144, 144, 144 },	/* Gray */ +    { 160, 160, 160 },	/* Gray */ +    { 176, 176, 176 },	/* Gray */ +    { 192, 192, 192 },	/* Gray */ +    { 208, 208, 208 },	/* Gray */ +    { 224, 224, 224 },	/* Gray */ +    { 240, 240, 240 },	/* Gray */ +    {   0,   0,   0 }	/* BlackPixel */ +}; + +#define NUM_GRAYS (16) + +static GdkColormap * gtkColorMap; + +static char lastColorChar = '!'; + +/** + * Get a gray color + * + * \param percent IN gray value required + * \return definition for gray color + */ + +wDrawColor wDrawColorGray( +    int percent) +{ +    int n; +    long rgb; +    n = (percent * (NUM_GRAYS+1)) / 100; + +    if (n <= 0) { +        return wDrawColorBlack; +    } else if (n > NUM_GRAYS) { +        return wDrawColorWhite; +    } else { +        n = (n*256)/NUM_GRAYS; +        rgb = RGB(n, n, n); +        return wDrawFindColor(rgb); +    } +} + +/** + * Get the color map for the main window + * + * \return + */ + +void wlibGetColorMap(void) +{ +    if (gtkColorMap) { +        return; +    } + +    gtkColorMap = gtk_widget_get_colormap(gtkMainW->widget); +    return; +} + +/** + * Initialize a colorMap entry + * \todo no idea what this is required for + * + * \param t IN color code + * \return + */ + +static void init_colorMapValue(colorMap_t * t) +{ +    t->rgb = RGB(t->red, t->green, t->blue); +    t->normalColor.red = t->red*65535/255; +    t->normalColor.green = t->green*65535/255; +    t->normalColor.blue = t->blue*65535/255; +    gdk_colormap_alloc_color(gtkColorMap, &t->normalColor, FALSE, TRUE); +    t->invertColor = t->normalColor; +    t->invertColor.pixel ^= g_array_index(colorMap_garray, colorMap_t, +                                          wDrawColorWhite).normalColor.pixel; +    t->colorChar = lastColorChar++; + +    if (lastColorChar >= 0x7F) { +        lastColorChar = '!'+1; +    } else if (lastColorChar == '"') { +        lastColorChar++; +    } +} + +/** + * Allocate a color map and initialize with application default colors + * + * \return + */ + +static void init_colorMap(void) +{ +    int gint; +    colorMap_garray = g_array_sized_new(TRUE, TRUE, sizeof(colorMap_t), +                                        sizeof(colorMap)/sizeof(colorMap_t)); +    g_array_append_vals(colorMap_garray, &colorMap, +                        sizeof(colorMap)/sizeof(colorMap_t)); + +    for (gint=0; gint<colorMap_garray->len; gint++) { +        init_colorMapValue(&g_array_index(colorMap_garray, colorMap_t, gint)); +    } +} + +/** + * Find the closest color from the palette and add a new color if there + * is no close match + * \todo improve method for finding best match (squared distances) + * + * \param rgb0 IN desired color + * \return palette index of matching color + */ + +wDrawColor wDrawFindColor( +    long rgb0) +{ +    wDrawColor cc; +    int r0, g0, b0; +    int d0; +    int i; +    colorMap_t tempMapValue; +    wlibGetColorMap(); +    cc = wDrawColorBlack; +    r0 = (int)(rgb0>>16)&0xFF; +    g0 = (int)(rgb0>>8)&0xFF; +    b0 = (int)(rgb0)&0xFF; +    d0 = 256*3; + +    // Initialize garray if needed +    if (colorMap_garray == NULL) { +        init_colorMap(); +    } + +    // Iterate over entire garray +    for (i=0; i<colorMap_garray->len; i++) { +        int d1; +        colorMap_t * cm_p; + +        cm_p = &g_array_index(colorMap_garray, colorMap_t, i); +        d1 = abs(r0-cm_p->red) + abs(g0-cm_p->green) + abs(b0-cm_p->blue); + +        if (d1 == 0) { +            return i; +        } + +        if (d1 < d0) { +            d0 = d1; +            cc = i; +        } +    } + +    if (d0 <= MAX_COLOR_DISTANCE) { +        return cc; +    } + +    // No good value - so add one +    tempMapValue.red = r0; +    tempMapValue.green = g0; +    tempMapValue.blue = b0; +    init_colorMapValue(&tempMapValue); +    g_array_append_val(colorMap_garray,tempMapValue); +    return i; +} + +/** + * Get the RGB code for a palette entry + * + * \param color IN the palette index + * \return RGB code + */ + +long wDrawGetRGB( +    wDrawColor color) +{ +    colorMap_t * colorMap_e; +    wlibGetColorMap(); + +    if (colorMap_garray == NULL) { +        init_colorMap(); +    } + +    if (color < 0 || color > colorMap_garray->len) { +        abort(); +    } + +    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); +    return colorMap_e->rgb; +} + +/** + * Get the color definition from the palette index + * + * \param color IN index into palette + * \param normal IN normal or inverted color + * \return  the selected color definition + */ + +GdkColor* wlibGetColor( +    wDrawColor color, +    wBool_t normal) +{ +    colorMap_t * colorMap_e; +    wlibGetColorMap(); + +    if (colorMap_garray == NULL) { +        init_colorMap(); +    } + +    if (color < 0 || color > colorMap_garray->len) { +        abort(); +    } + +    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); + +    if (normal) { +        return &colorMap_e->normalColor; +    } else { +        return &colorMap_e->invertColor; +    } +} + + +/* + ***************************************************************************** + * + * Color Selection Button + * + ***************************************************************************** + */ + +typedef struct { +    wDrawColor * valueP; +    const char * labelStr; +    wColorSelectButtonCallBack_p action; +    void * data; +    wDrawColor color; +    wButton_p button; +} colorData_t; + +/** + * Handle the color-set signal. + * + * \param widget  color button + * \param user_data + */ + +static void +colorChange(GtkColorButton *widget, gpointer user_data) +{ +    colorData_t *cd = user_data; +    GdkColor newcolor; +    long rgb; + +    gtk_color_button_get_color(widget, &newcolor); + +    rgb = RGB((int)(newcolor.red/256), (int)(newcolor.green/256), +              (int)(newcolor.blue/256)); +    cd->color = wDrawFindColor(rgb); + +    if (cd->valueP) { +        *(cd->valueP) = cd->color; +    } + +    if (cd->action) { +        cd->action(cd->data, cd->color); +    } +} + +/** + * Set the color for a color button + * + * \param bb IN button + * \param color IN palette index for color to use + * \return    describe the return value + */ + +void wColorSelectButtonSetColor( +    wButton_p bb, +    wDrawColor color) +{ +    GdkColor *colorOfButton = wlibGetColor(color, TRUE); + +    gtk_color_button_set_color(GTK_COLOR_BUTTON(bb->widget), +                               colorOfButton); +    ((colorData_t*)((wControl_p)bb)->data)->color = color; +} + + +/** + * Get the current palette index for a color button + * + * \param bb IN button handle + * \return  palette index + */ + +wDrawColor wColorSelectButtonGetColor( +    wButton_p bb) +{ +    return ((colorData_t*)((wControl_p)bb)->data)->color; +} + +/** + * Create the button showing the current paint color and starting the color selection dialog. + * + * \param IN parent parent window + * \param IN x x coordinate + * \param IN Y y coordinate + * \param IN helpStr balloon help string + * \param IN labelStr Button label ??? + * \param IN option + * \param IN width + * \param IN valueP Current color ??? + * \param IN action Button callback procedure + * \param IN data ??? + * \return bb handle for created button + */ + +wButton_p wColorSelectButtonCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long 	option, +    wPos_t 	width, +    wDrawColor *valueP, +    wColorSelectButtonCallBack_p action, +    void 	* data) +{ +    wButton_p b; +    colorData_t * cd; +    cd = malloc(sizeof(colorData_t)); +    cd->valueP = valueP; +    cd->action = action; +    cd->data = data; +    cd->labelStr = labelStr; +    cd->color = (valueP?*valueP:0); + +    b = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, cd); +    b->option = option; +    wlibComputePos((wControl_p)b); + +    b->widget = gtk_color_button_new(); +    GtkStyle *style; +    style = gtk_widget_get_style(b->widget); +    style->xthickness = 1; +    style->ythickness = 1; +    gtk_widget_set_style(b->widget, style); +    gtk_widget_set_size_request(GTK_WIDGET(b->widget), 22, 22); +    g_signal_connect(GTK_OBJECT(b->widget), "color-set", +                     G_CALLBACK(colorChange), cd); + +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); + +    if (option & BB_DEFAULT) { +        gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT); +        gtk_widget_grab_default(b->widget); +        gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget); +    } + +    wlibControlGetSize((wControl_p)b); + +    gtk_widget_show(b->widget); +    wlibAddButton((wControl_p)b); +    wlibAddHelpString(b->widget, helpStr); +    wColorSelectButtonSetColor(b, (valueP?*valueP:0)); +     +    if (labelStr) { +        ((wControl_p)b)->labelW = wlibAddLabel((wControl_p)b, labelStr); +    } +    return b; +} diff --git a/app/wlib/gtklib/control.c b/app/wlib/gtklib/control.c new file mode 100644 index 0000000..e824c94 --- /dev/null +++ b/app/wlib/gtklib/control.c @@ -0,0 +1,283 @@ +/** \file control.c + * Control Utilities + */ +/*  + * Copyright 2016 Martin Fischer <m_fischer@sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <stdlib.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +#define  GTKCONTROLHILITEWIDTH (3) + +/** + * Cause the control <b> to be displayed or hidden. + * Used to hide control (such as a list) while it is being updated. + * + * \param b IN Control + * \param show IN TRUE for visible + */ + +void wControlShow( +    wControl_p b, +    wBool_t show) +{ +    if (b->type == B_LINES) { +        wlibLineShow((wLine_p)b, show); +        return; +    } + +    if (b->widget == NULL) { +        abort(); +    } + +    if (show) { +        gtk_widget_show(b->widget); + +        if (b->label) { +            gtk_widget_show(b->label); +        } +    } else { +        gtk_widget_hide(b->widget); + +        if (b->label) { +            gtk_widget_hide(b->label); +        } +    } +} + +/** + * Cause the control <b> to be marked active or inactive. + * Inactive controls donot respond to actions. + * + * \param b IN Control + * \param active IN TRUE for active + */ + +void wControlActive( +    wControl_p b, +    int active) +{ +    if (b->widget == NULL) { +        abort(); +    } + +    gtk_widget_set_sensitive(GTK_WIDGET(b->widget), active); +} + +/** + * Returns the width of <label>. + * This is used for computing window layout. + * Typically the width to the longest label is computed and used as + * the X-position for <controls>. + * + * \param label IN label + * \returns width of label including some space +*/ + +wPos_t wLabelWidth( +    const char * label) +{ +    GtkWidget * widget; +    GtkRequisition requisition; +    widget = gtk_label_new(wlibConvertInput(label)); +    gtk_widget_size_request(widget, &requisition); +    gtk_widget_destroy(widget); +    return requisition.width+8; +} + +/** + * Get width of a control + * + * \param b IN Control + * \returns width + */ + +wPos_t wControlGetWidth( +    wControl_p b) +{ +    return b->w; +} + +/** + * Get height of a control + * + * \param b IN Control + * \returns height + */ + +wPos_t wControlGetHeight( +    wControl_p b) +{ +    return b->h; +} + +/** + * Get x position of a control + * + * \param b IN Control + * \returns position + */ + +wPos_t wControlGetPosX( +    wControl_p b)		/* Control */ +{ +    return b->realX; +} + +/** + * Get y position of a control + * + * \param b IN Control + * \returns position + */ + +wPos_t wControlGetPosY( +    wControl_p b)		/* Control */ +{ +    return b->realY - BORDERSIZE - ((b->parent->option&F_MENUBAR)?MENUH:0); +} + +/** + * Set the fixed position of a control within its parent window + * + * \param b IN control + * \param x IN x position + * \param y IN y position + */ + +void wControlSetPos( +    wControl_p b, +    wPos_t x, +    wPos_t y) +{ +    b->realX = x; +    b->realY = y + BORDERSIZE + ((b->parent->option&F_MENUBAR)?MENUH:0); + +    if (b->widget) { +        gtk_fixed_move(GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY); +    } + +    if (b->label) { +        gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, +                       b->realY+LABEL_OFFSET); +    } +} + +/** + * Set the label for a control + * + * \param b IN control + * \param labelStr IN the new label + */ + +void wControlSetLabel( +    wControl_p b, +    const char * labelStr) +{ +    GtkRequisition requisition; + +    if (b->label) { +        gtk_label_set_text(GTK_LABEL(b->label), wlibConvertInput(labelStr)); +        gtk_widget_size_request(b->label, &requisition); +        b->labelW = requisition.width+8; +        gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, +                       b->realY+LABEL_OFFSET); +    } else { +        b->labelW = wlibAddLabel(b, labelStr); +    } +} + +/** + * Set the context ie. additional user data for a control + * + * \param b IN control + * \param context IN user date + */ + +void wControlSetContext( +    wControl_p b, +    void * context) +{ +    b->data = context; +} + +/** + * Not implemented + * + * \param b IN + */ + +void wControlSetFocus( +    wControl_p b) +{ +} + +/** + * Draw a rectangle around a control + * \param b IN the control + * \param hilite IN unused + * \returns + * + * + */ +void wControlHilite( +    wControl_p b, +    wBool_t hilite) +{ +    cairo_t *cr; +    int off = GTKCONTROLHILITEWIDTH/2+1; + +    if (b->widget == NULL) { +        return; +    } + +    if (! gtk_widget_get_visible(b->widget)) { +        return; +    } + +    if (! gtk_widget_get_visible(b->parent->widget)) { +        return; +    } + +    cr = gdk_cairo_create(gtk_widget_get_window(b->parent->gtkwin)); +    cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); +    cairo_set_operator(cr, CAIRO_OPERATOR_XOR); +    cairo_set_line_width(cr, GTKCONTROLHILITEWIDTH); +    cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); +    cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); +    cairo_rectangle(cr, +                    b->realX - GTKCONTROLHILITEWIDTH, +                    b->realY - off, +                    b->w + GTKCONTROLHILITEWIDTH, +                    b->h + off + 1); +    cairo_stroke(cr); +    cairo_destroy(cr); +} diff --git a/app/wlib/gtklib/droplist.c b/app/wlib/gtklib/droplist.c new file mode 100644 index 0000000..3252905 --- /dev/null +++ b/app/wlib/gtklib/droplist.c @@ -0,0 +1,456 @@ +/** \file droplist.c + * Dropdown list functions + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) Dave Bullis 2005, Martin Fischer 2016 + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include "gtkint.h" +#include "i18n.h" + +/* define the column count for the tree model */ +#define DROPLIST_TEXTCOLUMNS 1 + +/** + * Add the data columns to the droplist. If dropList has an entry field + * the first text column is not added here as this is done by GTK + * automatically. + * + * \param dropList IN + * \param columns IN + * \returns number of columns created + */ + +int +wlibDropListAddColumns(GtkWidget *dropList, int columns) +{ +    int i; +    int start = 0; +    GtkCellRenderer *cell; + +    if (gtk_combo_box_get_has_entry(GTK_COMBO_BOX(dropList))) { +        start = 1; +    } + +    /* Create cell renderer. */ +    cell = gtk_cell_renderer_text_new(); + +    for (i = start; i < columns; i++) { +        /* Pack it into the droplist */ +        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropList), cell, TRUE); + +        /* Connect renderer to data source */ +        gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropList), +                                       cell, +                                       "text", +                                       LISTCOL_TEXT + i, +                                       NULL); +    } + +    return (i); +} + +/** + * Get the number of rows in drop list + * + * \param b IN widget + * \return number of rows + */ + +wIndex_t wDropListGetCount(wList_p b) +{ +    return (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(b->listStore), NULL)); +} + +/** + * Clear the whole droplist + * + * \param b IN the droplist + * \return + */ + +void +wDropListClear(wList_p b) +{ +    wlibListStoreClear(b->listStore); +} + +/** + * Get the user data / context information for a row in the droplist + * \param b IN widget + * \param inx IN row + * \returns pointer to context information + */ + +void *wDropListGetItemContext(wList_p b, wIndex_t inx) +{ +    GtkTreeIter iter; +    wListItem_p data = NULL; + +    if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL, +                                      inx)) { +        gtk_tree_model_get(GTK_TREE_MODEL(b->listStore), +                           &iter, +                           LISTCOL_DATA, (void *)&data, +                           -1); +    } + +    if (data) { +        return (data->itemData); +    } else { +        return (NULL); +    } +} + +/** + * Add an entry to a dropdown list. Only single text entries are allowed + * + * \param b IN the widget + * \param text IN string to add + * \return    describe the return value + */ + +void wDropListAddValue( +    wList_p b, +    char *text, +    wListItem_p data) +{ +    GtkTreeIter iter; + +    assert(b != NULL); +    assert(text != NULL); + +    gtk_list_store_append(b->listStore, &iter);	// append new row to tree store + +    gtk_list_store_set(b->listStore, &iter, +                       LISTCOL_TEXT, text, +                       LISTCOL_DATA, (void *)data, +                       -1); +} + +/** + * Set the value to the entry field of a droplist + * \param bl IN + * \param val IN + */ + +void wListSetValue( +    wList_p bl, +    const char * val) +{ +    assert(bl->listStore!=NULL); + +    bl->recursion++; + +    if (bl->type == B_DROPLIST) { +        bl->editted = TRUE; +        gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(bl->widget))), val); + +        if (bl->action) { +            bl->action(-1, val, 0, bl->data, NULL); +        } +    } else { +        assert(FALSE); +    } + +    bl->recursion--; +} + +/** + * Makes the <val>th entry (0-origin) the current selection. + * If <val> if '-1' then no entry is selected. + * + * \param b IN the widget + * \param val IN the index + * + * \todo it seems BL_NONE is not used in current code, check and clean up + */ + +void wDropListSetIndex(wList_p b, int val) +{ +    if ((b->option&BL_NONE)!=0 && val < 0) { +        gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), -1); +    } else { +        gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), val); +    } +} + +/** + * Set the values for a row in the droplist + * + * \param b IN drop list widget + * \param row IN index + * \param labelStr IN new text + * \param bm IN ignored + * \param itemData IN ignored + * \return + */ + +wBool_t wDropListSetValues( +    wList_p b, +    wIndex_t row, +    const char * labelStr, +    wIcon_p bm, +    void *itemData) +{ +    GtkTreeIter iter; + +    if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL, +                                      row)) { +        gtk_list_store_set(b->listStore, +                           &iter, +                           LISTCOL_TEXT, labelStr, +                           -1); +        return (TRUE); +    } else { +        return (FALSE); +    } +} + +/** + * Signal handler for the "changed"-signal in drop list's entry field. + * Get the entered text and calls the 'action' for handling of entered + * value. + * * + * \param entry IN entry field of the droplist + * \param data IN the drop list handle + * \return + */ + +static void DropListEntryEntered( +    GtkEntry * entry, +    gpointer userData) +{ +    const gchar * text; + +    text = gtk_entry_get_text(entry); + +    if (text && *text != '\0') { +        gchar *copyOfText = g_strdup(text); +        ((wList_p)userData)->editted = TRUE; +        ((wList_p)userData)->action(-1, copyOfText, 1, ((wList_p)userData)->data, NULL); +        g_free((gpointer)copyOfText); +    } else { +        wBeep(); +    } +} + +/** + * Signal handler for the "changed"-signal in drop list. Gets the selected + * text and determines the selected row in the tree model. + * + * \param comboBox IN the combo_box + * \param data IN the drop list handle + * \return + */ + +static int DropListSelectChild( +    GtkComboBox * comboBox, +    gpointer data) +{ +    wList_p bl = (wList_p)data; +    GtkTreeIter iter; + +    wIndex_t inx = 0; +    gchar *string; +    wListItem_p addData; + +    if (bl->recursion) { +        return 0; +    } + +    bl->editted = FALSE; + +    /* Obtain currently selected item from combo box. +     * If nothing is selected, do nothing. */ +    if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(comboBox), &iter)) { +        GtkTreeModel *model; + +        /* Obtain data model from combo box. */ +        model = gtk_combo_box_get_model(comboBox); + +        /* get the selected row */ +        string = gtk_tree_model_get_string_from_iter(model, +                 &iter); +        inx = atoi(string); +        g_free(string); + +        /* Obtain string from model. */ +        gtk_tree_model_get(model, &iter, +                           LISTCOL_TEXT, &string, +                           LISTCOL_DATA, (void *)&addData, +                           -1); + +    } else { +        return 0; +    } + +    /* selection changed, store new selections and call back */ +    if (bl->last != inx) { + +        bl->last = inx; + +        if (bl->valueP) { +            *bl->valueP = inx; +        } + +        /* selection changed -> callback */ +        if (string && bl->action) { +            bl->action(inx, string, 1, bl->data, addData->itemData); +        } +    } + +    g_free(string); +    return 1; +} + +/** + * Create a droplist for a given liststore + * + * \param ls IN list store for dropbox + * \param editable IN droplist with entry field + * \returns the newly created widget + */ + +GtkWidget * +wlibNewDropList(GtkListStore *ls, int editable) +{ +    GtkWidget *widget; + +    if (editable) { +        widget = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(ls)); +    } else { +        widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(ls)); +    } + +    return (widget); +} + +/** + * Create a drop down list. The drop down is created and intialized with the supplied values. + * + *	\param IN parent Parent window + *	\param IN x, X-position + *	\param IN y	 Y-position + *	\param IN helpStr Help string + *	\param IN labelStr Label + *	\param IN option Options + *	\param IN number Number of displayed entries + *	\param IN width Width + *	\param IN valueP Selected index + *	\param IN action Callback + *	\param IN data Context + */ + +wList_p wDropListCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long	option, +    long	number, +    wPos_t	width, +    long	*valueP, +    wListCallBack_p action, +    void 	*data) +{ +    wList_p b; + +    b = (wList_p)wlibAlloc(parent, B_DROPLIST, x, y, labelStr, sizeof *b, data); +    b->option = option; +    b->number = number; +    b->count = 0; +    b->last = -1; +    b->valueP = valueP; +    b->action = action; +    b->listX = b->realX; +    b->colCnt = 0; +    b->colWidths = NULL; +    b->colRightJust = NULL; +    b->editable = ((option & BL_EDITABLE) != 0); + +    assert(width != 0); + +    wlibComputePos((wControl_p)b); + + +    // create tree store for storing the contents +    b->listStore = wlibNewListStore(DROPLIST_TEXTCOLUMNS); + +    if (!b->listStore) { +        abort(); +    } + +    // create the droplist +    b->widget = wlibNewDropList(b->listStore, +                                option & BL_EDITABLE); + +    if (b->widget == 0) { +        abort(); +    } + +    g_object_unref(G_OBJECT(b->listStore)); + +    wlibDropListAddColumns(b->widget, DROPLIST_TEXTCOLUMNS); + +    gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(b->widget), +                                        LISTCOL_TEXT); + +    // combo's style +    gtk_rc_parse_string("style \"my-style\" { GtkComboBox::appears-as-list = 1 } widget \"*.mycombo\" style \"my-style\"  "); +    gtk_widget_set_name(b->widget,"mycombo"); + +    g_signal_connect(GTK_OBJECT(b->widget), "changed", +                     G_CALLBACK(DropListSelectChild), b); + +    if (option & BL_EDITABLE) { +        g_signal_connect(gtk_bin_get_child(GTK_BIN(b->widget)), +                         "changed", +                         G_CALLBACK(DropListEntryEntered), +                         b); +    } + +    gtk_widget_set_size_request(b->widget, width, -1); + +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); +    wlibControlGetSize((wControl_p)b); + +    if (labelStr) { +        b->labelW = wlibAddLabel((wControl_p)b, labelStr); +    } + +    gtk_widget_show(b->widget); +    wlibAddButton((wControl_p)b); +    wlibAddHelpString(b->widget, helpStr); + +    return b; +} + diff --git a/app/wlib/gtklib/dynarr.h b/app/wlib/gtklib/dynarr.h index 13c0ede..2adf115 100644 --- a/app/wlib/gtklib/dynarr.h +++ b/app/wlib/gtklib/dynarr.h @@ -17,6 +17,10 @@   *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   */ + +#ifndef DYNARR_H_SEEN +#define DYNARR_H_SEEN +  typedef struct {  		int cnt;  		int max; @@ -47,3 +51,4 @@ typedef struct {  				abort(); \  		} \  		(DA).cnt = 0; } +#endif /* DYNARR_H_SEEN */ diff --git a/app/wlib/gtklib/filesel.c b/app/wlib/gtklib/filesel.c index 4b92389..ca30c7f 100644 --- a/app/wlib/gtklib/filesel.c +++ b/app/wlib/gtklib/filesel.c @@ -28,6 +28,12 @@  #include <unistd.h>  #include <string.h> +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h>  #include "gtkint.h"  #include "i18n.h" @@ -71,9 +77,6 @@ struct wFilSel_t * wFilSelCreate(  	void * data )  {  	struct wFilSel_t	*fs; -	int count; -	char * cp; -	GtkFileFilter *filter;  	fs = (struct wFilSel_t*)malloc(sizeof *fs);  	if (!fs) @@ -88,9 +91,10 @@ struct wFilSel_t * wFilSelCreate(  	fs->data = data;  	if (pattList) { +		char * cp = strdup(pattList); +		int count = 0; +  		//create filters for the passed filter list -		cp = strdup(pattList); -		count = 0;  		// names and patterns are separated by |  		cp = strtok( cp, "|" );		  		while ( cp  && count < (MAX_ALLOWEDFILTERS - 1)) { @@ -130,15 +134,9 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )  	char name[1024];  	char *host;  	char *file; -	char *namePart;  	int i; -	GSList *fileNameList;  	GError *err = NULL; -	GtkFileFilter *activeFilter; -	 -	char **fileNames; -	 -	char * cp; +  	if (fs->window == NULL) {  		fs->window = gtk_file_chooser_dialog_new( fs->title,   										   GTK_WINDOW( fs->parent->gtkwin ), @@ -164,20 +162,25 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )  	}  	strcpy( name, dirName ); -	cp = name+strlen(name); -	if (cp[-1] != '/') { -		*cp++ = '/'; -		*cp = 0; -	} -	if( fs->mode == FS_SAVE ) -		gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER(fs->window), name );  +	if( fs->mode == FS_SAVE ) +		gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(fs->window), name );  +    // Add a current folder and a shortcut to it for Load/import dialogs +    if( fs->mode == FS_LOAD ) { +        gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(fs->window), name ); +        gtk_file_chooser_add_shortcut_folder( GTK_FILE_CHOOSER(fs->window), name, NULL ); +    } +      	if( gtk_dialog_run( GTK_DIALOG( fs->window )) == GTK_RESPONSE_ACCEPT ) { +		char **fileNames;	 +		GSList *fileNameList;  		fileNameList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(fs->window) );  		fileNames = calloc( sizeof(char *), g_slist_length (fileNameList) );   		for (i=0; i < g_slist_length (fileNameList); i++ ) { +			char *namePart; +  			file = g_filename_from_uri( g_slist_nth_data( fileNameList, i ), &host, &err );  			// check for presence of file extension @@ -205,7 +208,7 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )  		}  		free( fileNames );  		g_slist_free (fileNameList);	 -	}	 +	}  	gtk_widget_hide( GTK_WIDGET( fs->window ));  	return 1; diff --git a/app/wlib/gtklib/font.c b/app/wlib/gtklib/font.c new file mode 100644 index 0000000..c54f7de --- /dev/null +++ b/app/wlib/gtklib/font.c @@ -0,0 +1,403 @@ +/** \file font.c + * Font selection and loading. + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdlib.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "wlib.h" +#include "gtkint.h" +#include "i18n.h" + +/* + * Macro for debug purposes. Possible debug macro values: + * + *   0 - no messages to console (use this value when building in release mode) + *   1 - send errors + *   2 - send details + *   3 - send more details + */ +#define WLIB_FONT_DEBUG 0 + +static gchar sampleText[] = "AbCdE0129!@$&()[]{}"; + +static GtkWidget *fontSelectionDialog; + + +/***************************************************************************** + * FONT HANDLERS + */ + +#define FW_MEDIUM	(0) +#define FW_BOLD		(1) +#define FS_REGULAR	(0) +#define FS_ITALIC	(1) + +/* absoluteFontSize was introduced to keep the font size information synchron + * between the Dt.size of ctext.c and it's drop list on the status bar and + * the font size coming from the gtk font dialog which is located in this file */ +int absoluteFontSize = 18; + +struct wFont_t { +    PangoFontDescription *fontDescription; +}; + +static wFont_p standardFonts[F_HELV-F_TIMES+1][2][2]; +static wFont_p curFont = NULL; + +/** + * Callback for font selection dialog + * + * \param fontSelectionDialog IN dialog + * \param response IN response code from dialog + * \param data IN unused + * \return + */ + +static void fontSelectionDialogCallback(GtkFontSelectionDialog +                                        *fontSelectionDialog, gint response, gpointer data) +{ +    if (response == GTK_RESPONSE_APPLY || response == GTK_RESPONSE_OK) { +		gchar *fontName; + +        fontName = gtk_font_selection_dialog_get_font_name(fontSelectionDialog); +        wPrefSetString("font", "name", fontName); +        pango_font_description_free(curFont->fontDescription); +        curFont->fontDescription = pango_font_description_from_string(fontName); +        absoluteFontSize = (pango_font_description_get_size( +                                curFont->fontDescription))/PANGO_SCALE; +#if WLIB_FONT_DEBUG >= 2 +        fprintf(stderr, "new font selection:\n"); +        fprintf(stderr, "  font name \"%s\"\n", fontName); +        fprintf(stderr, "  font size is %d\n", +                pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE); +        fprintf(stderr, "  font size is absolute %d\n", +                pango_font_description_get_size_is_absolute(curFont->fontDescription)); +#endif +        g_free(fontName); +    } + +    if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_CANCEL) { +        gtk_widget_hide(GTK_WIDGET(fontSelectionDialog)); +    } +} + +static wBool_t fontInitted = FALSE; + +static wBool_t fontInit() +{ +    const char *fontNames[] = { +        "times 18", +        "times italic 18", +        "times bold 18", +        "times bold italic 18", +        "helvetica 18", +        "helvetica oblique 18", +        "helvetica bold 18", +        "helvetica bold oblique 18", +    }; +    int s = 0; +    int i, j, k; + +    for (i = F_TIMES; i <= F_HELV; ++i) { +        for (j = FW_MEDIUM; j <= FW_BOLD; ++j) { +            for (k = FS_REGULAR; k <= FS_ITALIC; ++k) { +                PangoFontDescription *fontDescription = pango_font_description_from_string( +                        fontNames[s++]); +                wFont_p standardFont = (wFont_p) malloc(sizeof(struct wFont_t)); +                standardFont->fontDescription = fontDescription; +                standardFonts[i-F_TIMES][j][k] = standardFont; +            } +        } +    } + +    if (curFont == NULL) { +        curFont = (wFont_p) malloc(sizeof(struct wFont_t)); + +        if (curFont == NULL) { +            return FALSE; +        } + +        const char *fontName = wPrefGetString("font", "name"); +        curFont->fontDescription = pango_font_description_from_string( +                                       fontName ? fontName : "helvetica 18"); +        absoluteFontSize = (int) PANGO_PIXELS(pango_font_description_get_size( +                curFont->fontDescription)); +    } + +    fontInitted = TRUE; +    return TRUE; +} + + +static double fontFactor = 1.0; + +#define FONTSIZE_TO_PANGOSIZE(fs) ((gint) ((fs) * (fontFactor) + .5)) + +/** + * Create a Pango layout with a specified font and font size + * + * \param widget IN + * \param cairo IN cairo context + * \param fp IN font + * \param fs IN size + * \param s IN ??? + * \param width_p OUT width of layout + * \param height_p OUT height of layout + * \param ascent_p OUT ascent of layout + * \param descent_p OUT descent of layout + * \return    the created Pango layout + */ + +PangoLayout *wlibFontCreatePangoLayout(GtkWidget *widget, +                                       void *cairo, +                                       wFont_p fp, +                                       wFontSize_t fs, +                                       const char *s, +                                       int *width_p, +                                       int *height_p, +                                       int *ascent_p, +                                       int *descent_p) +{ +    if (!fontInitted) { +        fontInit(); +    } + +    PangoLayout *layout = NULL; +    gchar *utf8 = wlibConvertInput(s); +    /* RPH -- pango_cairo_create_layout() is missing in CentOS 4.8. +              CentOS 4.8 only has GTK 2.4.13 and Pango 1.6.0 and does not have +              libpangocairo at all. +              pango_cairo_create_layout() was introduced with Pango 1.10. */ +#if PANGO_VERSION_MAJOR >= 1 && PANGO_VERSION_MINOR >= 10 + +    if (cairo != NULL) { +        layout = pango_cairo_create_layout((cairo_t *) cairo); +        pango_layout_set_text(layout, utf8, -1); +    } else +#endif +        layout = gtk_widget_create_pango_layout(widget, utf8); + +    PangoFontDescription *fontDescription = (fp ? fp : curFont)->fontDescription; +    PangoContext *context; +    PangoFontMetrics *metrics; +    /* set attributes */ +    pango_font_description_set_size(fontDescription, +                                    FONTSIZE_TO_PANGOSIZE(fs) * PANGO_SCALE); +    pango_layout_set_font_description(layout, fontDescription); +    /* get layout measures */ +    pango_layout_get_pixel_size(layout, width_p, height_p); +    context = gtk_widget_get_pango_context(widget); +    metrics = pango_context_get_metrics(context, fontDescription, +                                        pango_context_get_language(context)); +    *ascent_p  = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); +    *descent_p = PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); +    pango_font_metrics_unref(metrics); +#if WLIB_FONT_DEBUG >= 3 +    fprintf(stderr, "font layout created:\n"); +    fprintf(stderr, "  widget:         %p\n", widget); +    //fprintf(stderr, "  font description:%p\n", fp); +    fprintf(stderr, "  font size:      %f\n", fs); +    fprintf(stderr, "  layout text:    \"%s\" (utf8)\n", utf8); +    fprintf(stderr, "  layout width:   %d\n", *width_p); +    fprintf(stderr, "  layout height:  %d\n", *height_p); +    fprintf(stderr, "  layout ascent:  %d (pixels)\n", *ascent_p); +    fprintf(stderr, "  layout descent: %d (pixels)\n", *descent_p); +#endif +    return layout; +} + +/** + * Destroy a previously allocated  Pango layout + * \return + */ + +void wlibFontDestroyPangoLayout(PangoLayout *layout) +{ +    g_object_unref(G_OBJECT(layout)); +} + +/** + * Initialize font data + * \return + */ + +void wInitializeFonts() +{ +    if (!fontInitted) { +        fontInit(); +    } +} + +/** + * Initialize and run the font dialog + * + * \param title IN dialog box title + * \return + */ + +void wSelectFont( +    const char * title) +{ +    if (!fontInitted) { +        fontInit(); +    } + +    if (fontSelectionDialog == NULL) { +        fontSelectionDialog = gtk_font_selection_dialog_new(_("Font Select")); +        gtk_window_set_position(GTK_WINDOW(fontSelectionDialog), GTK_WIN_POS_MOUSE); +        gtk_window_set_modal(GTK_WINDOW(fontSelectionDialog), TRUE); +        gtk_font_selection_dialog_set_preview_text(GTK_FONT_SELECTION_DIALOG( +                    fontSelectionDialog), sampleText); +        g_signal_connect(G_OBJECT(fontSelectionDialog), "response", +                         G_CALLBACK(fontSelectionDialogCallback), NULL); +        g_signal_connect(G_OBJECT(fontSelectionDialog), "destroy", +                         G_CALLBACK(gtk_widget_destroyed), &fontSelectionDialog); +    } + +    gtk_window_set_title(GTK_WINDOW(fontSelectionDialog), title); + +    if (curFont != NULL) { +		gchar *fontName; + +        /* the curFont description contains the latest font info +         * which is depended on the current scale +         * overwrite it with the absoluteFontSize */ +        pango_font_description_set_size(curFont->fontDescription, +                                        FONTSIZE_TO_PANGOSIZE(absoluteFontSize) * PANGO_SCALE); +        fontName = pango_font_description_to_string(curFont->fontDescription); +        gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG( +                fontSelectionDialog), fontName); +        g_free(fontName); +    } + +    gtk_widget_show(fontSelectionDialog); +} + +/** + * Get the current font + * + * \return    describe the return value + */ + +static wFont_p wlibSelectedFont(void) +{ +    if (!fontInitted) { +        fontInit(); +    } + +    return curFont; +} + +/** + * Get the default font size + * + * \return    describe the return value + */ + +wFontSize_t wSelectedFontSize(void) +{ +    if (!fontInitted) { +        fontInit(); +    } + +#if WLIB_FONT_DEBUG >= 3 +    fprintf(stderr, "the font size of current font description is: %d\n", +            pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE); +    fprintf(stderr, "the font size of absoluteFontSize is: %d\n",absoluteFontSize); +#endif +    return absoluteFontSize; +} + +/** + * Set the default font size + * + * \param size IN font size + * \return    describe the return value + */ + +void wSetSelectedFontSize(int size) +{ +    absoluteFontSize = (wFontSize_t)size; +} + +/** + * get the Pango font description as a string from a font definition. + * If the font definition is NULL, a default font is return. This is + * the current font if one is set. If not the first font from the font + * list is returned. + * + * \param fp IN the font definition + * \return    the font description + */ + +const char *wlibFontTranslate(wFont_p fp) +{ +    static gchar *fontName = NULL; + +    if (fontName != NULL) { +        g_free(fontName); +    } + +    if (!fontInitted) { +        fontInit(); +    } + +    if (fp == NULL) { +        fp = wlibSelectedFont(); +    } + +    if (fp == NULL) { +        fp = standardFonts[0][FW_MEDIUM][FS_REGULAR]; +    } + +    fontName = pango_font_description_to_string(fp->fontDescription); +#if WLIB_FONT_DEBUG >= 2 +    fprintf(stderr, "font translation: "); +    fprintf(stderr, "  \"%s\"\n", fontName); +#endif +    return (const char *) fontName; +} + +/** + * Return description for one of the standard fonts + * + * \return + */ + +wFont_p wStandardFont(int face, wBool_t bold, wBool_t italic) +{ +    if (!fontInitted) { +        fontInit(); +    } + +    return standardFonts[face-F_TIMES][bold][italic]; +} diff --git a/app/wlib/gtklib/gtkbitmap.c b/app/wlib/gtklib/gtkbitmap.c deleted file mode 100644 index 8f85951..0000000 --- a/app/wlib/gtklib/gtkbitmap.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkbitmap.c,v 1.5 2009-09-27 04:28:03 dspagnol Exp $ - */ -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2009 Daniel Spagnol - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif -#include <unistd.h> -#include <string.h> -#include <math.h> -#include <stdlib.h> - -#include "gtkint.h" - - -struct wBitmap_t { -	WOBJ_COMMON -}; - -/** - * Create a static control for displaying a bitmap. - * - * \param parent IN parent window - * \param x, y   IN position in parent window - * \param option IN ignored for now - * \param iconP  IN icon to use - * \return    the control - */ - -wControl_p -wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP ) -{ -	wBitmap_p bt; -	GdkPixbuf *pixbuf; -	 -	bt = gtkAlloc( parent, B_BITMAP, x, y, NULL, sizeof *bt, NULL ); -	bt->w = iconP->w; -	bt->h = iconP->h; -	bt->option = options; -	 -	/* -	 * Depending on the platform, parent->widget->window might still be null  -	 * at this point. The window allocation should be forced before creating -	 * the pixmap. -	 */ -	if ( parent->widget->window == NULL ) -		gtk_widget_realize( parent->widget ); /* force allocation, if pending */ - -	pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)iconP->bits ); -	GtkWidget *image = gtk_image_new_from_pixbuf( pixbuf ); -	 -   gtk_widget_show( image ); -	 -	bt->widget = gtk_fixed_new(); -	gtk_container_add( GTK_CONTAINER(bt->widget), image );	 -	gtk_widget_show( bt->widget ); -		 -	gtkComputePos( (wControl_p)bt ); -	gtkControlGetSize( (wControl_p)bt ); -	gtk_fixed_put( GTK_FIXED( parent->widget ), bt->widget, bt->realX, bt->realY ); -	 -	g_object_unref( pixbuf ); -	 -	return( (wControl_p)bt ); -} - diff --git a/app/wlib/gtklib/gtkbutton.c b/app/wlib/gtklib/gtkbutton.c deleted file mode 100644 index 7780535..0000000 --- a/app/wlib/gtklib/gtkbutton.c +++ /dev/null @@ -1,461 +0,0 @@ -/** \file gtkbutton.c - * Toolbar button creation and handling - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkbutton.c,v 1.8 2009-10-03 04:49:01 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> - -#include "gtkint.h" -#include "i18n.h" - -#define MIN_BUTTON_WIDTH (80) - -/* - ***************************************************************************** - * - * Simple Buttons - * - ***************************************************************************** - */ - -struct wButton_t { -		WOBJ_COMMON -		GtkLabel * labelG; -		GtkWidget * imageG; -		wButtonCallBack_p action; -		int busy; -		int recursion; -		}; - - -void wButtonSetBusy( wButton_p bb, int value ) { -	bb->recursion++; -	gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(bb->widget), value ); -	bb->recursion--; -	bb->busy = value; -} - - -void gtkSetLabel( -		GtkWidget *widget, -		long option, -		const char * labelStr, -		GtkLabel * * labelG, -		GtkWidget * * imageG ) -{ -	wIcon_p bm; -	GdkPixbuf *pixbuf; -	 -	GdkPixmap * pixmap; -	GdkBitmap * mask; -	 -	GtkWidget * hbox; -	if (widget == 0) abort(); -	if (labelStr){ -		if (option&BO_ICON) { -			bm = (wIcon_p)labelStr; -			 -			// for XPM files use the pixbuf functions -			if( bm->gtkIconType == gtkIcon_pixmap ) { -				pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)bm->bits ); -				if (*imageG==NULL) { -					*imageG = gtk_image_new_from_pixbuf( pixbuf ); -					gtk_container_add( GTK_CONTAINER( widget ), *imageG ); -					gtk_widget_show( *imageG ); -				} else { -					gtk_image_set_from_pixbuf( GTK_IMAGE(*imageG), pixbuf ); -				} -				g_object_unref( pixbuf ); -			} else { -				// otherwise use the conversion to XPM -				/** \todo { Should use the way via a pixbuf as well } */ -				pixmap = gtkMakeIcon( widget, bm, &mask ); -				if (*imageG==NULL) { -					*imageG = gtk_image_new_from_pixmap( pixmap, NULL ); -					gtk_widget_show( *imageG ); -					gtk_container_add( GTK_CONTAINER( widget ), *imageG ); -				} else { -					gtk_image_set_from_pixmap( GTK_IMAGE(*imageG), pixmap, NULL ); -				} -				gdk_pixmap_unref( pixmap ); -				gdk_bitmap_unref( mask ); -			} -		} else { -			if (*labelG==NULL) { -				*labelG = (GtkLabel*)gtk_label_new( gtkConvertInput(labelStr) ); -				gtk_container_add( GTK_CONTAINER(widget), (GtkWidget*)*labelG ); -				gtk_widget_show( (GtkWidget*)*labelG ); -			} else { -				gtk_label_set( *labelG, gtkConvertInput(labelStr) ); -			} -		} -	} -} - -void wButtonSetLabel( wButton_p bb, const char * labelStr) { -	gtkSetLabel( bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG ); -} - - - -void gtkButtonDoAction(  -		wButton_p bb ) -{ -	if (bb->action) -		bb->action( bb->data ); -} - - -static void pushButt( -		GtkWidget *widget, -		gpointer value ) -{ -	wButton_p b = (wButton_p)value; -	if (debugWindow >= 2) printf("%s button pushed\n", b->labelStr?b->labelStr:"No label" ); -	if (b->recursion) -		return; -	if (b->action) -		b->action(b->data); -	if (!b->busy) { -		b->recursion++; -		gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(b->widget), FALSE ); -		b->recursion--; -	} -} - -wButton_p wButtonCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long 	option, -		wPos_t 	width, -		wButtonCallBack_p action, -		void 	* data ) -{ -	wButton_p b; -	b = gtkAlloc( parent, B_BUTTON, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->action = action; -	gtkComputePos( (wControl_p)b ); - -	b->widget = gtk_toggle_button_new(); -				 -	gtk_signal_connect (GTK_OBJECT(b->widget), "clicked", -						GTK_SIGNAL_FUNC(pushButt), b ); -	if (width > 0) -		gtk_widget_set_size_request( b->widget, width, -1 ); -	wButtonSetLabel( b, labelStr ); - -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -	if (option & BB_DEFAULT) { -		GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT ); -		gtk_widget_grab_default( b->widget ); -		gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget ); -	} -	gtkControlGetSize( (wControl_p)b ); -	if (width == 0 && b->w < MIN_BUTTON_WIDTH && (b->option&BO_ICON)==0) { -		b->w = MIN_BUTTON_WIDTH; -		gtk_widget_set_size_request( b->widget, b->w, b->h ); -	} -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	return b; -} - - -/* - ***************************************************************************** - * - * Choice Boxes - * - ***************************************************************************** - */ - -struct wChoice_t { -		WOBJ_COMMON -		long *valueP; -		wChoiceCallBack_p action; -		int recursion; -		}; - - -static long choiceGetValue( -		wChoice_p bc ) -{ -	GList * child, * children; -	long value, inx; -	if (bc->type == B_TOGGLE) -		value = 0; -	else -		value = -1; -	for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) { -		if ( GTK_TOGGLE_BUTTON(child->data)->active ) { -			if (bc->type == B_TOGGLE) { -				value |= (1<<inx); -			} else { -				value = inx; -			} -		} -	} -	if ( children ) -		g_list_free( children ); -	return value; -} - -EXPORT void wRadioSetValue( -		wChoice_p bc,		/* Radio box */ -		long value )		/* Value */ -/* -*/ -{ -	GList * child, * children; -	long inx; -	for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) { -		if (inx == value) { -			bc->recursion++; -			gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), TRUE ); -			bc->recursion--; -		} -	} -	if ( children ) -		g_list_free( children ); -} - - -EXPORT long wRadioGetValue( -		wChoice_p bc )		/* Radio box */ -/* -*/ -{ -	return choiceGetValue(bc); -} - - -EXPORT void wToggleSetValue( -		wChoice_p bc,		/* Toggle box */ -		long value )		/* Values */ -/* -*/ -{ -	GList * child, * children; -	long inx; -	bc->recursion++; -	for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) { -		gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), (value&(1<<inx))!=0 );  -	} -	if ( children ) -		g_list_free( children ); -	bc->recursion--; -} - - -EXPORT long wToggleGetValue( -		wChoice_p b )		/* Toggle box */ -/* -*/ -{ -	return choiceGetValue(b); -} - - -static int pushChoice( -		GtkWidget *widget, -		gpointer b ) -{ -	wChoice_p bc = (wChoice_p)b; -	long value = choiceGetValue( bc ); -	if (debugWindow >= 2) printf("%s choice pushed = %ld\n", bc->labelStr?bc->labelStr:"No label", value ); -	if ( bc->type == B_RADIO && !(GTK_TOGGLE_BUTTON(widget))->active ) -		return 1; -	if (bc->recursion) -		return 1; -	if (bc->valueP) -		*bc->valueP = value; -	if (bc->action) -		bc->action( value, bc->data); -	return 1; -} - - -static void choiceRepaint( -		wControl_p b ) -{ -	wChoice_p bc = (wChoice_p)b; -	if ( GTK_WIDGET_VISIBLE( b->widget ) ) -		gtkDrawBox( bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1 ); -} - - -EXPORT wChoice_p wRadioCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		const char	**labels,	/* Labels */ -		long	*valueP,	/* Selected value */ -		wChoiceCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	wChoice_p b; -	const char ** label; -	GtkWidget *butt0=NULL, *butt; - -	if ((option & BC_NOBORDER)==0) { -		if (x>=0) -			x++; -		else -			x--; -		if (y>=0) -			y++; -		else -			y--; -	} -	b = gtkAlloc( parent, B_RADIO, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->action = action; -	b->valueP = valueP; -	gtkComputePos( (wControl_p)b ); - -	if (option&BC_HORZ) -		b->widget = gtk_hbox_new( FALSE, 0 ); -	else -		b->widget = gtk_vbox_new( FALSE, 0 ); -	if (b->widget == 0) abort(); -	for ( label=labels; *label; label++ ) { -		butt = gtk_radio_button_new_with_label(  -				butt0?gtk_radio_button_group(GTK_RADIO_BUTTON(butt0)):NULL, _(*label) ); -		if (butt0==NULL) -			butt0 = butt; -		gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 ); -		gtk_widget_show( butt ); -		gtk_signal_connect (GTK_OBJECT(butt), "toggled", -						GTK_SIGNAL_FUNC( pushChoice ), b ); -		gtkAddHelpString( butt, helpStr ); -	} -	if (option & BB_DEFAULT) { -		GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT ); -		gtk_widget_grab_default( b->widget ); -		/*gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget );*/ -	} -	if (valueP) -		wRadioSetValue( b, *valueP ); - -	if ((option & BC_NOBORDER)==0) { -		if (parent->gc == NULL) { -			parent->gc = gdk_gc_new( parent->gtkwin->window ); -			gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -			parent->gc_linewidth = 0; -			gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -		} -		b->repaintProc = choiceRepaint; -		b->w += 2; -		b->h += 2; -	} - -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	return b; -} - -wChoice_p wToggleCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		const char	**labels,	/* Labels */ -		long	*valueP,	/* Selected value */ -		wChoiceCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	wChoice_p b; -	const char ** label; -	GtkWidget *butt; - -	if ((option & BC_NOBORDER)==0) { -		if (x>=0) -			x++; -		else -			x--; -		if (y>=0) -			y++; -		else -			y--; -	} -	b = gtkAlloc( parent, B_TOGGLE, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->action = action; -	gtkComputePos( (wControl_p)b ); - -	if (option&BC_HORZ) -		b->widget = gtk_hbox_new( FALSE, 0 ); -	else -		b->widget = gtk_vbox_new( FALSE, 0 ); -	if (b->widget == 0) abort(); -	for ( label=labels; *label; label++ ) { -		butt = gtk_check_button_new_with_label(_(*label)); -		gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 ); -		gtk_widget_show( butt ); -		gtk_signal_connect (GTK_OBJECT(butt), "toggled", -						GTK_SIGNAL_FUNC( pushChoice ), b ); -		gtkAddHelpString( butt, helpStr ); -	} -	if (valueP) -		wToggleSetValue( b, *valueP ); - -	if ((option & BC_NOBORDER)==0) { -		if (parent->gc == NULL) { -			parent->gc = gdk_gc_new( parent->gtkwin->window ); -			gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -			parent->gc_linewidth = 0; -			gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -		} -		b->repaintProc = choiceRepaint; -		b->w += 2; -		b->h += 2; -	} - -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	return b; -} diff --git a/app/wlib/gtklib/gtkcolor.c b/app/wlib/gtklib/gtkcolor.c deleted file mode 100644 index cf17199..0000000 --- a/app/wlib/gtklib/gtkcolor.c +++ /dev/null @@ -1,476 +0,0 @@ -/** \file gtkcolor.c - * code for the color selection dialog and color button - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkcolor.c,v 1.3 2007-11-24 19:48:21 tshead Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif -#include <unistd.h> -#include <stdlib.h> - -#include "gtkint.h" - -#include "square10.bmp" - -EXPORT wDrawColor wDrawColorWhite; -EXPORT wDrawColor wDrawColorBlack; - -#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) ) - -#define MAX_COLOR_DISTANCE (3) - -typedef struct { -		unsigned char red; -		unsigned char green; -		unsigned char blue; -		GdkColor normalColor; -		GdkColor invertColor; -		long rgb; -		int colorChar; -		} colorMap_t; -static GArray *colorMap_garray = NULL; // Change to use glib array - -static colorMap_t colorMap[] = { -		{ 255, 255, 255 },	/* White */ -		{   0,   0,   0 },	/* Black */ -		{ 255,   0,   0 },	/* Red */ -		{   0, 255,   0 },	/* Green */ -		{   0,   0, 255 },	/* Blue */ -		{ 255, 255,   0 },	/* Yellow */ -		{ 255,   0, 255 },	/* Purple */ -		{   0, 255, 255 },	/* Aqua */ -		{ 128,   0,   0 },	/* Dk. Red */ -		{   0, 128,   0 },	/* Dk. Green */ -		{   0,   0, 128 },	/* Dk. Blue */ -		{ 128, 128,   0 },	/* Dk. Yellow */ -		{ 128,   0, 128 },	/* Dk. Purple */ -		{   0, 128, 128 },	/* Dk. Aqua */ -		{  65, 105, 225 },      /* Royal Blue */ -		{   0, 191, 255 },	/* DeepSkyBlue */ -		{ 125, 206, 250 },	/* LightSkyBlue */ -		{  70, 130, 180 },	/* Steel Blue */ -		{ 176, 224, 230 },	/* Powder Blue */ -		{ 127, 255, 212 },	/* Aquamarine */ -		{  46, 139,  87 },	/* SeaGreen */ -		{ 152, 251, 152 },	/* PaleGreen */ -		{ 124, 252,   0 },	/* LawnGreen */ -		{  50, 205,  50 },	/* LimeGreen */ -		{  34, 139,  34 },	/* ForestGreen */ -		{ 255, 215,   0 },	/* Gold */ -		{ 188, 143, 143 },	/* RosyBrown */ -		{ 139, 69, 19 },	/* SaddleBrown */ -		{ 245, 245, 220 },	/* Beige */ -		{ 210, 180, 140 },	/* Tan */ -		{ 210, 105, 30 },	/* Chocolate */ -		{ 165, 42, 42 },	/* Brown */ -		{ 255, 165, 0 },	/* Orange */ -		{ 255, 127, 80 },	/* Coral */ -		{ 255, 99, 71 },	/* Tomato */ -		{ 255, 105, 180 },	/* HotPink */ -		{ 255, 192, 203 },	/* Pink */ -		{ 176, 48, 96 },	/* Maroon */ -		{ 238, 130, 238 },	/* Violet */ -		{ 160, 32, 240 },	/* Purple */ -		{  16,  16,  16 },	/* Gray */ -		{  32,  32,  32 },	/* Gray */ -		{  48,  48,  48 },	/* Gray */ -		{  64,  64,  64 },	/* Gray */ -		{  80,  80,  80 },	/* Gray */ -		{  96,  96,  96 },	/* Gray */ - 	    { 112, 112, 122 },	/* Gray */ -		{ 128, 128, 128 },	/* Gray */ -		{ 144, 144, 144 },	/* Gray */ -		{ 160, 160, 160 },	/* Gray */ -		{ 176, 176, 176 },	/* Gray */ -		{ 192, 192, 192 },	/* Gray */ -		{ 208, 208, 208 },	/* Gray */ -		{ 224, 224, 224 },	/* Gray */ -		{ 240, 240, 240 },	/* Gray */ -		{   0,   0,   0 }	/* BlackPixel */ - 	}; - -#define NUM_GRAYS (16) - -static GdkColormap * gtkColorMap; - -static char lastColorChar = '!'; - -/***************************************************************************** - * - *  - * - */ - - -EXPORT wDrawColor wDrawColorGray( -		int percent ) -{ -	int n; -	long rgb; -	n = (percent * (NUM_GRAYS+1)) / 100; -	if ( n <= 0 ) -		return wDrawColorBlack; -	else if ( n > NUM_GRAYS ) -		return wDrawColorWhite; -	else { -		n = (n*256)/NUM_GRAYS; -		rgb = RGB( n, n, n ); -		return wDrawFindColor( rgb ); -	} -} - - -void gtkGetColorMap( void ) -{ -	if (gtkColorMap) -		return; -	gtkColorMap = gtk_widget_get_colormap( gtkMainW->widget ); -	return; -} - -void init_colorMapValue( colorMap_t * t) { -     -    t->rgb = RGB( t->red, t->green, t->blue ); -    t->normalColor.red = t->red*65535/255; -    t->normalColor.green = t->green*65535/255; -    t->normalColor.blue = t->blue*65535/255; -    gdk_color_alloc( gtkColorMap, &t->normalColor ); -    t->invertColor = t->normalColor; -    t->invertColor.pixel ^= g_array_index(colorMap_garray, colorMap_t, wDrawColorWhite).normalColor.pixel; -    t->colorChar = lastColorChar++; -    if (lastColorChar >= 0x7F) -        lastColorChar = '!'+1; -    else if (lastColorChar == '"') -        lastColorChar++; -     -} - - -void init_colorMap( void ) -{ -    colorMap_garray = g_array_sized_new(TRUE, TRUE, sizeof(colorMap_t), sizeof(colorMap)/sizeof(colorMap_t)); -    g_array_append_vals(colorMap_garray, &colorMap, sizeof(colorMap)/sizeof(colorMap_t)); -     -    int gint; -     -    for(gint=0; gint<colorMap_garray->len; gint++) { -        init_colorMapValue(&g_array_index(colorMap_garray, colorMap_t, gint)); -    } -} - - -EXPORT wDrawColor wDrawFindColor( -		long rgb0 ) -{ -	wDrawColor cc; -	int r0, g0, b0; -	int d0, d1; -	long rgb1; -	colorMap_t * cm_p; - -	gtkGetColorMap(); - -	cc = wDrawColorBlack; -	r0 = (int)(rgb0>>16)&0xFF; -	g0 = (int)(rgb0>>8)&0xFF; -	b0 = (int)(rgb0)&0xFF; -	d0 = 256*3; -     -    // Initialize garray if needed -    if (colorMap_garray == NULL) { -        init_colorMap(); -    } -     -    int gint; -     -    // Iterate over entire garray -    for (gint=0; gint<colorMap_garray->len; gint++) { -        cm_p = &g_array_index(colorMap_garray, colorMap_t, gint); -        rgb1 = cm_p->rgb; -        d1 = abs(r0-cm_p->red) + abs(g0-cm_p->green) + abs(b0-cm_p->blue); -        if (d1 == 0) -            return gint; -        if (d1 < d0) { -			d0 = d1; -		  	cc = gint; -        } -	  } -    if (d0 <= MAX_COLOR_DISTANCE) { -        return cc; -    } -    // No good value - so add one -    colorMap_t tempMapValue; -	//DYNARR_APPEND( colorMap_t, colorMap_da, 10 ); -	tempMapValue.red = r0; -	tempMapValue.green = g0; -	tempMapValue.blue = b0; -    init_colorMapValue(&tempMapValue); -    g_array_append_val(colorMap_garray,tempMapValue); -	return gint; -} - - -EXPORT long wDrawGetRGB( -		wDrawColor color ) -{ -	gtkGetColorMap(); -     -    if(colorMap_garray == NULL) -        init_colorMap(); - -	if (color < 0 || color > colorMap_garray->len) -		abort(); -    colorMap_t * colorMap_e; -    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); -	return colorMap_e->rgb; -} - - -EXPORT GdkColor* gtkGetColor( -		wDrawColor color, -		wBool_t normal ) -{ -	gtkGetColorMap(); -     -    if(colorMap_garray == NULL) -        init_colorMap(); - -	if (color < 0 || color > colorMap_garray->len) -		abort(); -    colorMap_t * colorMap_e; -    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); -	 -    if ( normal ) -		return &colorMap_e->normalColor; -	else -		return &colorMap_e->invertColor; -} - - -EXPORT int gtkGetColorChar( -		wDrawColor color ) -{ -	/*gtkGetColorMap();*/ -    if(colorMap_garray == NULL) -        init_colorMap(); - -	if (color < 0 || color > colorMap_garray->len) -		abort(); -    colorMap_t * colorMap_e; -    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); -	return colorMap_e->colorChar; -} - - -EXPORT int gtkMapPixel(  -		long pixel ) -{ -	colorMap_t * mapValue; -    int gint; -     -    if(colorMap_garray == NULL) -        init_colorMap(); -	 -	for (gint=0; gint<colorMap_garray->len; gint++ ) { -        mapValue = &g_array_index(colorMap_garray, colorMap_t, gint); -        if ( mapValue->normalColor.pixel == pixel ) { -			return mapValue->colorChar; -		} -	} -    mapValue = &g_array_index(colorMap_garray, colorMap_t, wDrawColorBlack); -	return mapValue->colorChar; -} - - -/* - ***************************************************************************** - * - * Color Selection Dialog - * - ***************************************************************************** - */ - - -static int colorSelectValid; -static int colorSelectOk( -		GtkWidget * widget, -		GtkWidget * * window ) -{ -	gtkDoModal( NULL, FALSE ); -	gtk_widget_hide( GTK_WIDGET(*window) ); -	colorSelectValid = TRUE; -	return FALSE; -} - - -static int colorSelectCancel( -		GtkWidget * widget, -		GtkWidget * * window ) -{ -	gtkDoModal( NULL, FALSE ); -	gtk_widget_hide( GTK_WIDGET(*window) ); -	colorSelectValid = FALSE; -	if (widget == *window) -		/* Called by destroy event, window is gone */ -		*window = NULL; -	return FALSE; -} - - -EXPORT wBool_t wColorSelect( -		const char * title, -		wDrawColor * color ) -{ -	static GtkWidget * colorSelectD = NULL; -	long rgb; -	gdouble colors[4];  // Remember opacity! - -	if (colorSelectD == NULL) { -		colorSelectD = gtk_color_selection_dialog_new( title ); -		gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->ok_button), "clicked", (GtkSignalFunc)colorSelectOk, (gpointer)&colorSelectD ); -		gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->cancel_button), "clicked", (GtkSignalFunc)colorSelectCancel, (gpointer)&colorSelectD ); -		gtk_signal_connect( GTK_OBJECT(colorSelectD), "destroy", (GtkSignalFunc)colorSelectCancel, (gpointer)&colorSelectD ); -	} else { -		gtk_window_set_title( GTK_WINDOW(colorSelectD), title ); -	} -     -    colorMap_t * colorMap_e; -     -    if (!colorMap_garray) { -        init_colorMap(); -    } -     -    colorMap_e = &g_array_index(colorMap_garray, colorMap_t, *color); -    colors[0] = colorMap_e->red/255.0; -	colors[1] = colorMap_e->green/255.0; -	colors[2] = colorMap_e->blue/255.0; -    colors[3] = 1.0;                   // Override to Fully opaque -	gtk_color_selection_set_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->colorsel), colors ); -	gtk_widget_show( colorSelectD ); -	gtkDoModal( NULL, TRUE ); -	if (colorSelectValid) { -		gtk_color_selection_get_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->colorsel), colors ); -		rgb = RGB( (int)(colors[0]*255), (int)(colors[1]*255), (int)(colors[2]*255) ); -        * color = wDrawFindColor( rgb ); -		return TRUE; -	} -	return FALSE; -} - - -/* - ***************************************************************************** - * - * Color Selection Button - * - ***************************************************************************** - */ - -typedef struct { -		wDrawColor * valueP; -		wColorSelectButtonCallBack_p action; -		const char * labelStr; -		void * data; -		wDrawColor color; -		wButton_p button; -		} colorData_t; - -static void doColorButton( -		void * data ) -{ -	colorData_t * cd = (colorData_t *)data;  -	wDrawColor newColor; - -	newColor = cd->color; -	if (wColorSelect( cd->labelStr, &newColor )) { -		cd->color = newColor;  -		wColorSelectButtonSetColor( cd->button, newColor ); -		if (cd->valueP) -			*(cd->valueP) = newColor; -		if (cd->action) -			cd->action( cd->data, newColor );  -	} -} - - -void wColorSelectButtonSetColor( -		wButton_p bb, -		wDrawColor color ) -{ -	wIcon_p bm; -	bm = wIconCreateBitMap( square10_width, square10_height, square10_bits, color ); -	wButtonSetLabel( bb, (const char*)bm ); -	((colorData_t*)((wControl_p)bb)->data)->color = color; -} - - -wDrawColor wColorSelectButtonGetColor( -		wButton_p bb ) -{ -	return ((colorData_t*)((wControl_p)bb)->data)->color; -} - -/** Create the button showing the current paint color and starting the color selection dialog.  - * \param IN parent parent window - * \param IN x x coordinate - * \param IN Y y coordinate - * \param IN helpStr balloon help string  - * \param IN labelStr Button label ??? - * \param IN option - * \param IN width - * \param IN valueP Current color ???  - * \param IN action Button callback procedure - * \param IN data ??? - * \return bb handle for created button - */ -  -wButton_p wColorSelectButtonCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long 	option, -		wPos_t 	width, -		wDrawColor *valueP, -		wColorSelectButtonCallBack_p action, -		void 	* data ) -{ -	wButton_p bb; -	wIcon_p bm; -	colorData_t * cd; -	bm = wIconCreateBitMap( square10_width, square10_height, square10_bits, (valueP?*valueP:0) ); -	cd = malloc( sizeof( colorData_t )); -	cd->valueP = valueP; -	cd->action = action; -	cd->data = data; -	cd->labelStr = labelStr; -	cd->color = (valueP?*valueP:0); -	bb = wButtonCreate( parent, x, y, helpStr, (const char*)bm, option|BO_ICON, width, doColorButton, cd ); -	cd->button = bb; -	if (labelStr) -		((wControl_p)bb)->labelW = gtkAddLabel( (wControl_p)bb, labelStr ); -	return bb; -} diff --git a/app/wlib/gtklib/gtkdraw-cairo.c b/app/wlib/gtklib/gtkdraw-cairo.c index 9fc7eab..a19eb2b 100644 --- a/app/wlib/gtklib/gtkdraw-cairo.c +++ b/app/wlib/gtklib/gtkdraw-cairo.c @@ -1,5 +1,5 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkdraw-cairo.c,v 1.11 2009-10-03 17:34:37 dspagnol Exp $ +/** \file gtkdraw-cairo.c + * Basic drawing functions   */  /*  XTrkCad - Model Railroad CAD @@ -29,9 +29,13 @@  #include <string.h>  #include <math.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +  #include "gtkint.h"  #include "gdk/gdkkeysyms.h" +#define gtkAddHelpString( a, b ) wlibAddHelpString( a, b )  #define CENTERMARK_LENGTH (6) @@ -116,7 +120,7 @@ static GdkGC * selectGC(  	{  		if(bd->lastColor != color || !bd->lastColorInverted)  		{ -			gdk_gc_set_foreground( bd->gc, gtkGetColor(color,FALSE) ); +			gdk_gc_set_foreground( bd->gc, wlibGetColor(color,FALSE) );  			bd->lastColor = color;  			bd->lastColorInverted = TRUE;  		} @@ -127,7 +131,7 @@ static GdkGC * selectGC(  	{  		if(bd->lastColor != color || bd->lastColorInverted)  		{ -			gdk_gc_set_foreground( bd->gc, gtkGetColor(color,TRUE) ); +			gdk_gc_set_foreground( bd->gc, wlibGetColor(color,TRUE) );  			bd->lastColor = color;  			bd->lastColorInverted = FALSE;  		} @@ -182,7 +186,7 @@ static cairo_t* gtkDrawCreateCairoContext(  	}  	else  	{ -		GdkColor* const gcolor = gtkGetColor(color, TRUE); +		GdkColor* const gcolor = wlibGetColor(color, TRUE);  		cairo_set_source_rgb(cairo, gcolor->red / 65535.0, gcolor->green / 65535.0, gcolor->blue / 65535.0);  		cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); @@ -195,7 +199,7 @@ static cairo_t* gtkDrawDestroyCairoContext(cairo_t *cairo) {  	cairo_destroy(cairo);  } -EXPORT void wDrawDelayUpdate( + void wDrawDelayUpdate(  		wDraw_p bd,  		wBool_t delay )  { @@ -212,7 +216,7 @@ EXPORT void wDrawDelayUpdate(  } -EXPORT void wDrawLine( + void wDrawLine(  		wDraw_p bd,  		wPos_t x0, wPos_t y0,  		wPos_t x1, wPos_t y1, @@ -275,7 +279,7 @@ EXPORT void wDrawLine(   */ -EXPORT void wDrawArc( + void wDrawArc(  		wDraw_p bd,  		wPos_t x0, wPos_t y0,  		wPos_t r, @@ -344,7 +348,7 @@ EXPORT void wDrawArc(  } -EXPORT void wDrawPoint( + void wDrawPoint(  		wDraw_p bd,  		wPos_t x0, wPos_t y0,  		wDrawColor color, @@ -380,7 +384,7 @@ EXPORT void wDrawPoint(   *   ******************************************************************************/ -EXPORT void wDrawString( + void wDrawString(  		wDraw_p bd,  		wPos_t x, wPos_t y,  		wAngle_t a, @@ -413,19 +417,19 @@ EXPORT void wDrawString(  	cairo_translate( cairo, x, y );  	cairo_rotate( cairo, angle ); -	layout = gtkFontCreatePangoLayout(bd->widget, cairo, fp, fs, s, +	layout = wlibFontCreatePangoLayout(bd->widget, cairo, fp, fs, s,  									  (int *) &w, (int *) &h,  									  (int *) &ascent, (int *) &descent);  	/* cairo does not support the old method of text removal by overwrite; force always write here and             refresh on cancel event */ -	GdkColor* const gcolor = gtkGetColor(color, TRUE); +	GdkColor* const gcolor = wlibGetColor(color, TRUE);  	cairo_set_source_rgb(cairo, gcolor->red / 65535.0, gcolor->green / 65535.0, gcolor->blue / 65535.0);  	cairo_move_to( cairo, 0, -ascent );  	pango_cairo_show_layout(cairo, layout); -	gtkFontDestroyPangoLayout(layout); +	wlibFontDestroyPangoLayout(layout);  	cairo_restore( cairo );  	gtkDrawDestroyCairoContext(cairo); @@ -442,7 +446,7 @@ EXPORT void wDrawString(  	gtk_widget_draw(bd->widget, &update_rect);  } -EXPORT void wDrawGetTextSize( + void wDrawGetTextSize(  		wPos_t *w,  		wPos_t *h,  		wPos_t *d, @@ -459,8 +463,8 @@ EXPORT void wDrawGetTextSize(  	*w = 0;  	*h = 0; -	gtkFontDestroyPangoLayout( -		gtkFontCreatePangoLayout(bd->widget, NULL, fp, fs, s, +	wlibFontDestroyPangoLayout( +		wlibFontCreatePangoLayout(bd->widget, NULL, fp, fs, s,  								 &textWidth, (int *) &textHeight,  								 (int *) &ascent, (int *) &descent)); @@ -479,7 +483,7 @@ EXPORT void wDrawGetTextSize(   *  *******************************************************************************/ -EXPORT void wDrawFilledRectangle( + void wDrawFilledRectangle(  		wDraw_p bd,  		wPos_t x,  		wPos_t y, @@ -518,7 +522,7 @@ EXPORT void wDrawFilledRectangle(  	gtk_widget_draw( bd->widget, &update_rect );  } -EXPORT void wDrawFilledPolygon( + void wDrawFilledPolygon(  		wDraw_p bd,  		wPos_t p[][2],  		int cnt, @@ -584,7 +588,7 @@ EXPORT void wDrawFilledPolygon(  	gtk_widget_draw( bd->widget, &update_rect );  } -EXPORT void wDrawFilledCircle( + void wDrawFilledCircle(  		wDraw_p bd,  		wPos_t x0,  		wPos_t y0, @@ -623,7 +627,7 @@ EXPORT void wDrawFilledCircle(  } -EXPORT void wDrawClear( + void wDrawClear(  		wDraw_p bd )  {  	GdkGC * gc; @@ -648,7 +652,7 @@ EXPORT void wDrawClear(  	gtk_widget_draw( bd->widget, &update_rect );  } -EXPORT void * wDrawGetContext( + void * wDrawGetContext(  		wDraw_p bd )  {  	return bd->context; @@ -661,7 +665,7 @@ EXPORT void * wDrawGetContext(  *******************************************************************************/ -EXPORT wDrawBitMap_p wDrawBitMapCreate( + wDrawBitMap_p wDrawBitMapCreate(  		wDraw_p bd,  		int w,  		int h, @@ -682,7 +686,7 @@ EXPORT wDrawBitMap_p wDrawBitMapCreate(  } -EXPORT void wDrawBitMap( + void wDrawBitMap(  		wDraw_p bd,  		wDrawBitMap_p bm,  		wPos_t x, wPos_t y, @@ -713,7 +717,7 @@ EXPORT void wDrawBitMap(  				} else if ( (opts&wDrawOptNoClip) != 0 ) {  					xx += bd->realX;  					yy += bd->realY; -					b = gtkGetControlFromPos( bd->parent, xx, yy ); +					b = wlibGetControlFromPos( bd->parent, xx, yy );  					if ( b ) {  						if ( b->type == B_DRAW )  							gdk_window = ((wDraw_p)b)->pixmap; @@ -762,7 +766,7 @@ EXPORT void wDrawBitMap( -EXPORT void wDrawSaveImage( + void wDrawSaveImage(  		wDraw_p bd )  {  	if ( bd->pixmapBackup ) { @@ -781,7 +785,7 @@ EXPORT void wDrawSaveImage(  } -EXPORT void wDrawRestoreImage( + void wDrawRestoreImage(  		wDraw_p bd )  {  	GdkRectangle update_rect; @@ -806,7 +810,7 @@ EXPORT void wDrawRestoreImage(  } -EXPORT void wDrawSetSize( + void wDrawSetSize(  		wDraw_p bd,  		wPos_t w,  		wPos_t h ) @@ -838,13 +842,13 @@ EXPORT void wDrawSetSize(  } -EXPORT void wDrawGetSize( + void wDrawGetSize(  		wDraw_p bd,  		wPos_t *w,  		wPos_t *h )  {  	if (bd->widget) -		gtkControlGetSize( (wControl_p)bd ); +		wlibControlGetSize( (wControl_p)bd );  	*w = bd->w-2;  	*h = bd->h-2;  } @@ -856,7 +860,7 @@ EXPORT void wDrawGetSize(   * \return    the resolution in dpi   */ -EXPORT double wDrawGetDPI( + double wDrawGetDPI(  		wDraw_p d )  {  	//if (d == &psPrint_d) @@ -866,7 +870,7 @@ EXPORT double wDrawGetDPI(  } -EXPORT double wDrawGetMaxRadius( + double wDrawGetMaxRadius(  		wDraw_p d )  {  	if (d == &psPrint_d) @@ -876,7 +880,7 @@ EXPORT double wDrawGetMaxRadius(  } -EXPORT void wDrawClip( + void wDrawClip(  		wDraw_p d,  		wPos_t x,  		wPos_t y, @@ -956,7 +960,7 @@ static gint draw_leave_event(  		GtkWidget *widget,  		GdkEvent * event )  { -	gtkHelpHideBalloon(); +	wlibHelpHideBalloon();  	return FALSE;  } @@ -1041,38 +1045,38 @@ static gint draw_char_event(  	guint key = event->keyval;  	wAccelKey_e extKey = wAccelKey_None;  	switch (key) { -	case GDK_Escape:	key = 0x1B; break; -	case GDK_Return:	key = 0x0D; break; -	case GDK_Linefeed:	key = 0x0A; break; -	case GDK_Tab:	key = 0x09; break; -	case GDK_BackSpace:	key = 0x08; break; -	case GDK_Delete:    extKey = wAccelKey_Del; break; -	case GDK_Insert:    extKey = wAccelKey_Ins; break; -	case GDK_Home:      extKey = wAccelKey_Home; break; -	case GDK_End:       extKey = wAccelKey_End; break; -	case GDK_Page_Up:   extKey = wAccelKey_Pgup; break; -	case GDK_Page_Down: extKey = wAccelKey_Pgdn; break; -	case GDK_Up:        extKey = wAccelKey_Up; break; -	case GDK_Down:      extKey = wAccelKey_Down; break; -	case GDK_Right:     extKey = wAccelKey_Right; break; -	case GDK_Left:      extKey = wAccelKey_Left; break; -	case GDK_F1:        extKey = wAccelKey_F1; break; -	case GDK_F2:        extKey = wAccelKey_F2; break; -	case GDK_F3:        extKey = wAccelKey_F3; break; -	case GDK_F4:        extKey = wAccelKey_F4; break; -	case GDK_F5:        extKey = wAccelKey_F5; break; -	case GDK_F6:        extKey = wAccelKey_F6; break; -	case GDK_F7:        extKey = wAccelKey_F7; break; -	case GDK_F8:        extKey = wAccelKey_F8; break; -	case GDK_F9:        extKey = wAccelKey_F9; break; -	case GDK_F10:       extKey = wAccelKey_F10; break; -	case GDK_F11:       extKey = wAccelKey_F11; break; -	case GDK_F12:       extKey = wAccelKey_F12; break; +	case GDK_KEY_Escape:	key = 0x1B; break; +	case GDK_KEY_Return:	key = 0x0D; break; +	case GDK_KEY_Linefeed:	key = 0x0A; break; +	case GDK_KEY_Tab:	key = 0x09; break; +	case GDK_KEY_BackSpace:	key = 0x08; break; +	case GDK_KEY_Delete:    extKey = wAccelKey_Del; break; +	case GDK_KEY_Insert:    extKey = wAccelKey_Ins; break; +	case GDK_KEY_Home:      extKey = wAccelKey_Home; break; +	case GDK_KEY_End:       extKey = wAccelKey_End; break; +	case GDK_KEY_Page_Up:   extKey = wAccelKey_Pgup; break; +	case GDK_KEY_Page_Down: extKey = wAccelKey_Pgdn; break; +	case GDK_KEY_Up:        extKey = wAccelKey_Up; break; +	case GDK_KEY_Down:      extKey = wAccelKey_Down; break; +	case GDK_KEY_Right:     extKey = wAccelKey_Right; break; +	case GDK_KEY_Left:      extKey = wAccelKey_Left; break; +	case GDK_KEY_F1:        extKey = wAccelKey_F1; break; +	case GDK_KEY_F2:        extKey = wAccelKey_F2; break; +	case GDK_KEY_F3:        extKey = wAccelKey_F3; break; +	case GDK_KEY_F4:        extKey = wAccelKey_F4; break; +	case GDK_KEY_F5:        extKey = wAccelKey_F5; break; +	case GDK_KEY_F6:        extKey = wAccelKey_F6; break; +	case GDK_KEY_F7:        extKey = wAccelKey_F7; break; +	case GDK_KEY_F8:        extKey = wAccelKey_F8; break; +	case GDK_KEY_F9:        extKey = wAccelKey_F9; break; +	case GDK_KEY_F10:       extKey = wAccelKey_F10; break; +	case GDK_KEY_F11:       extKey = wAccelKey_F11; break; +	case GDK_KEY_F12:       extKey = wAccelKey_F12; break;  	default: ;  	}  	if (extKey != wAccelKey_None) { -		if ( gtkFindAccelKey( event ) == NULL ) { +		if ( wlibFindAccelKey( event ) == NULL ) {  			bd->action( bd, bd->context, wActionExtKey + ((int)extKey<<8), bd->lastX, bd->lastY );  		}  		return TRUE; @@ -1097,7 +1101,7 @@ int XW = 0;  int XH = 0;  int xw, xh, cw, ch; -EXPORT wDraw_p wDrawCreate( + wDraw_p wDrawCreate(  		wWin_p	parent,  		wPos_t	x,  		wPos_t	y, @@ -1111,12 +1115,12 @@ EXPORT wDraw_p wDrawCreate(  {  	wDraw_p bd; -	bd = (wDraw_p)gtkAlloc( parent,  B_DRAW, x, y, NULL, sizeof *bd, NULL ); +	bd = (wDraw_p)wlibAlloc( parent,  B_DRAW, x, y, NULL, sizeof *bd, NULL );  	bd->option = option;  	bd->context = context;  	bd->redraw = redraw;  	bd->action = action; -	gtkComputePos( (wControl_p)bd ); +	wlibComputePos( (wControl_p)bd );  	bd->widget = gtk_drawing_area_new();  	gtk_drawing_area_size( GTK_DRAWING_AREA(bd->widget), width, height ); @@ -1153,7 +1157,7 @@ EXPORT wDraw_p wDrawCreate(  	bd->maxH = bd->h = height;  	gtk_fixed_put( GTK_FIXED(parent->widget), bd->widget, bd->realX, bd->realY ); -	gtkControlGetSize( (wControl_p)bd ); +	wlibControlGetSize( (wControl_p)bd );  	gtk_widget_realize( bd->widget );  	bd->pixmap = gdk_pixmap_new( bd->widget->window, width, height, -1 );  	bd->gc = gdk_gc_new( parent->gtkwin->window ); @@ -1169,7 +1173,7 @@ EXPORT wDraw_p wDrawCreate(  		bd->labelW = gtkAddLabel( (wControl_p)bd, labelStr );  #endif  	gtk_widget_show( bd->widget ); -	gtkAddButton( (wControl_p)bd ); +	wlibAddButton( (wControl_p)bd );  	gtkAddHelpString( bd->widget, helpStr );  	return bd; @@ -1185,7 +1189,7 @@ wDraw_p wBitMapCreate(          wPos_t w, wPos_t h, int arg )  {  	wDraw_p bd; -	bd = (wDraw_p)gtkAlloc( gtkMainW,  B_DRAW, 0, 0, NULL, sizeof *bd, NULL ); +	bd = (wDraw_p)wlibAlloc( gtkMainW,  B_DRAW, 0, 0, NULL, sizeof *bd, NULL );  	bd->lastColor = -1;  	bd->dpi = 75; diff --git a/app/wlib/gtklib/gtkfont.c b/app/wlib/gtklib/gtkfont.c deleted file mode 100644 index 89937d7..0000000 --- a/app/wlib/gtklib/gtkfont.c +++ /dev/null @@ -1,342 +0,0 @@ -/** \file gtkfont.c - * Font selection and loading. - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif -#include <unistd.h> -#include <string.h> -#include <math.h> -#include <stdlib.h> - -#include "wlib.h" -#include "gtkint.h" -#include "i18n.h" - -#ifndef TRUE -#define TRUE (1) -#define FALSE (0) -#endif - -/* - * Macro for debug purposes. Possible debug macro values: - * - *   0 - no messages to console (use this value when building in release mode) - *   1 - send errors - *   2 - send details - *   3 - send more details - */ -#define WLIB_FONT_DEBUG 0 - -static gchar sampleText[] = "AbCdE0129!@$&()[]{}"; - -static GtkWidget *fontSelectionDialog; - - -/***************************************************************************** - * FONT HANDLERS - */ - -#define FW_MEDIUM	(0) -#define FW_BOLD		(1) -#define FS_REGULAR	(0) -#define FS_ITALIC	(1) - -/* absoluteFontSize was introduced to keep the font size information synchron - * between the Dt.size of ctext.c and it's drop list on the status bar and - * the font size coming from the gtk font dialog which is located in this file */ -int absoluteFontSize = 18; - -struct wFont_t { -		PangoFontDescription *fontDescription; -		}; - -static wFont_p standardFonts[F_HELV-F_TIMES+1][2][2]; -static wFont_p curFont = NULL; - - -static void fontSelectionDialogCallback(GtkFontSelectionDialog *fontSelectionDialog, gint response, gpointer data) -{ -	gchar *fontName; - -	switch (response) -	{ -		case GTK_RESPONSE_APPLY: /* once the apply button is hidden, this should not be used */ -		case GTK_RESPONSE_OK: -			fontName = gtk_font_selection_dialog_get_font_name(fontSelectionDialog); -			wPrefSetString( "font", "name", fontName ); -			pango_font_description_free(curFont->fontDescription); -			curFont->fontDescription = pango_font_description_from_string(fontName); -			absoluteFontSize = (pango_font_description_get_size(curFont->fontDescription))/PANGO_SCALE; -#if WLIB_FONT_DEBUG >= 2 -			fprintf(stderr, "new font selection:\n"); -			fprintf(stderr, "  font name \"%s\"\n", fontName); -			fprintf(stderr, "  font size is %d\n",pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE); -			fprintf(stderr, "  font size is absolute %d\n", pango_font_description_get_size_is_absolute(curFont->fontDescription)); -#endif -			g_free(fontName); -			break; -		default: -			gtk_widget_hide(GTK_WIDGET(fontSelectionDialog)); -	} -	if (response == GTK_RESPONSE_OK) -		gtk_widget_hide(GTK_WIDGET(fontSelectionDialog)); -} - -static wBool_t fontInitted = FALSE; - -static wBool_t fontInit() -{ -	const char *fontNames[] = { -		"times 18", -		"times italic 18", -		"times bold 18", -		"times bold italic 18", -		"helvetica 18", -		"helvetica oblique 18", -		"helvetica bold 18", -		"helvetica bold oblique 18", -	}; - -	int s = 0; -	int i, j, k; - -	for (i = F_TIMES; i <= F_HELV; ++i) { -		for (j = FW_MEDIUM; j <= FW_BOLD; ++j) { -			for (k = FS_REGULAR; k <= FS_ITALIC; ++k) { -				PangoFontDescription *fontDescription = pango_font_description_from_string(fontNames[s++]); -				wFont_p standardFont = (wFont_p) malloc(sizeof(struct wFont_t)); -				standardFont->fontDescription = fontDescription; -				standardFonts[i-F_TIMES][j][k] = standardFont; -			} -		} -	} - -	if (curFont == NULL) { -		curFont = (wFont_p) malloc(sizeof(struct wFont_t)); -		if (curFont == NULL) -			return FALSE; -		const char *fontName = wPrefGetString("font", "name"); -		curFont->fontDescription = pango_font_description_from_string(fontName ? fontName : "helvetica 18"); -		absoluteFontSize = (int) PANGO_PIXELS(pango_font_description_get_size(curFont->fontDescription)); -	} - -	fontInitted = TRUE; -	return TRUE; -} - - -static double fontFactor = 1.0; - -#define FONTSIZE_TO_PANGOSIZE(fs) ((gint) ((fs) * (fontFactor) + .5)) - -/** - * Create a Pango layout with a specified font and font size - * - * \param widget IN - * \param cairo IN cairo context - * \param fp IN font - * \param fs IN size - * \param s IN ??? - * \param width_p OUT width of layout - * \param height_p OUT height of layout - * \param ascent_p OUT ascent of layout - * \param descent_p OUT descent of layout - * \return    the created Pango layout - */ - -PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, -                                      void *cairo, -                                      wFont_p fp, -                                      wFontSize_t fs, -                                      const char *s, -                                      int *width_p, -                                      int *height_p, -                                      int *ascent_p, -                                      int *descent_p) -{ -	if (!fontInitted) -		fontInit(); - -	PangoLayout *layout = NULL; - -	gchar *utf8 = gtkConvertInput(s); - -/* RPH -- pango_cairo_create_layout() is missing in CentOS 4.8. -          CentOS 4.8 only has GTK 2.4.13 and Pango 1.6.0 and does not have -          libpangocairo at all. -          pango_cairo_create_layout() was introduced with Pango 1.10. */ - -#if PANGO_VERSION_MAJOR >= 1 && PANGO_VERSION_MINOR >= 10 -	if (cairo != NULL) { -		layout = pango_cairo_create_layout((cairo_t *) cairo); -		pango_layout_set_text(layout, utf8, -1); -	} -	else -#endif -		layout = gtk_widget_create_pango_layout(widget, utf8); - -	PangoFontDescription *fontDescription = (fp ? fp : curFont)->fontDescription; - -	PangoContext *context; -	PangoFontMetrics *metrics; - -	/* set attributes */ -	pango_font_description_set_size(fontDescription, -									FONTSIZE_TO_PANGOSIZE(fs) * PANGO_SCALE); -	pango_layout_set_font_description(layout, fontDescription); - -	/* get layout measures */ -	pango_layout_get_pixel_size(layout, width_p, height_p); -	context = gtk_widget_get_pango_context(widget); -	metrics = pango_context_get_metrics(context, fontDescription, -										pango_context_get_language(context)); -	*ascent_p  = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); -	*descent_p = PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); -	pango_font_metrics_unref(metrics); - -#if WLIB_FONT_DEBUG >= 3 -	fprintf(stderr, "font layout created:\n"); -	fprintf(stderr, "  widget:         %p\n", widget); -	//fprintf(stderr, "  font description:%p\n", fp); -	fprintf(stderr, "  font size:      %f\n", fs); -	fprintf(stderr, "  layout text:    \"%s\" (utf8)\n", utf8); -	fprintf(stderr, "  layout width:   %d\n", *width_p); -	fprintf(stderr, "  layout height:  %d\n", *height_p); -	fprintf(stderr, "  layout ascent:  %d (pixels)\n", *ascent_p); -	fprintf(stderr, "  layout descent: %d (pixels)\n", *descent_p); -#endif - -	return layout; -} - -void gtkFontDestroyPangoLayout(PangoLayout *layout) -{ -	g_object_unref(G_OBJECT(layout)); -} - -void wInitializeFonts() -{ -	if (!fontInitted) -		fontInit(); -} - -void wSelectFont( -	const char * title ) -{ -	if (!fontInitted) -		fontInit(); - -	if (fontSelectionDialog == NULL) { -		fontSelectionDialog = gtk_font_selection_dialog_new(_("Font Select")); -		gtk_window_set_position(GTK_WINDOW(fontSelectionDialog), GTK_WIN_POS_MOUSE); -		gtk_window_set_modal(GTK_WINDOW(fontSelectionDialog), TRUE); -		gtk_font_selection_dialog_set_preview_text(GTK_FONT_SELECTION_DIALOG(fontSelectionDialog), sampleText); -		g_signal_connect(G_OBJECT(fontSelectionDialog), "response", G_CALLBACK(fontSelectionDialogCallback), NULL); -		gtk_signal_connect(GTK_OBJECT(fontSelectionDialog), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &fontSelectionDialog); -	} -	gtk_window_set_title(GTK_WINDOW(fontSelectionDialog), title); - -	if (curFont != NULL) { -		/* the curFont description contains the latest font info -		 * which is depended on the current scale -		 * overwrite it with the absoluteFontSize */ -		pango_font_description_set_size(curFont->fontDescription,FONTSIZE_TO_PANGOSIZE(absoluteFontSize) * PANGO_SCALE); -		gchar *fontName = pango_font_description_to_string(curFont->fontDescription); -		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(fontSelectionDialog), fontName); -		g_free(fontName); -	} - -	gtk_widget_show(fontSelectionDialog); -} - -static wFont_p gtkSelectedFont( void ) -{ -	if (!fontInitted) -		fontInit(); - -	return curFont; -} - -wFontSize_t wSelectedFontSize( void ) -{ -	if (!fontInitted) -		fontInit(); - -#if WLIB_FONT_DEBUG >= 3 -			fprintf(stderr, "the font size of current font description is: %d\n",pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE); -			fprintf(stderr, "the font size of absoluteFontSize is: %d\n",absoluteFontSize); -#endif - -	//return (wFontSize_t) PANGO_PIXELS(pango_font_description_get_size(curFont->fontDescription)); -	return absoluteFontSize; -} - -void wSetSelectedFontSize(int size){ -	absoluteFontSize = (wFontSize_t)size; -} - -/** - * get the Pango font description as a string from a font definition. - * If the font definition is NULL, a default font is return. This is - * the current font if one is set. If not the first font from the font - * list is returned. - * - * \param fp IN the font definition - * \return    the font description - */ - -const char *gtkFontTranslate( wFont_p fp ) -{ -	static gchar *fontName = NULL; - -	if (fontName != NULL) -		g_free(fontName); - -	if (!fontInitted) -		fontInit(); - -	if (fp == NULL) -		fp = gtkSelectedFont(); - -	if (fp == NULL) -		fp = standardFonts[0][FW_MEDIUM][FS_REGULAR]; - -	fontName = pango_font_description_to_string(fp->fontDescription); - -#if WLIB_FONT_DEBUG >= 2 -	fprintf(stderr, "font translation: "); -	fprintf(stderr, "  \"%s\"\n", fontName); -#endif - -	return (const char *) fontName; -} - -wFont_p wStandardFont( int face, wBool_t bold, wBool_t italic ) -{ -	if (!fontInitted) -		fontInit(); - -	return standardFonts[face-F_TIMES][bold][italic]; -} diff --git a/app/wlib/gtklib/gtkhelp.c b/app/wlib/gtklib/gtkhelp.c deleted file mode 100644 index b02f555..0000000 --- a/app/wlib/gtklib/gtkhelp.c +++ /dev/null @@ -1,733 +0,0 @@ -/** \file gtkhelp.c - * Balloon help ( tooltips) and main help functions. - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkhelp.c,v 1.12 2009-10-02 04:30:32 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis and (C) 2007 Martin Fischer - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <sys/time.h> -#include <signal.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <assert.h> -#include <errno.h> -#include <fcntl.h> - -#include <stdint.h> - -#include <gtk/gtk.h> -#include <gdk/gdk.h> - -#include <webkit/webkit.h> - -#include "gtkint.h" -#include "i18n.h" - -void load_into_view (char *file, int requested_view);	// Prototype to please clang. - -/* globals and defines related to the HTML help window */ - -#define  HTMLERRORTEXT "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=US-ASCII\">" \ -								"<title>Help Error</title><body><h1>Error - help information can not be found.</h1><p>" \ -								"The help information you requested cannot be found on this system.<br><pre>%s: %s</pre><p>" \ -								"Usually this is an installation problem, Make sure that XTrackCAD and the included " \ -								"HTML files are installed properly and can be found via the XTRKCADLIB environment " \ -								"variable. Also make sure that the user has sufficient access rights to read these" \ - 								"files.</p></body></html>"  - - -#define SLIDERPOSDEFAULT 180		/**< default value for slider position */ - -#define HTMLHELPSECTION    "gtklib html help" /**< section name for html help window preferences */ -#define SLIDERPREFNAME	   "sliderpos"    	 /**< name for the slider position preference */ -#define WINDOWPOSPREFNAME  "position"  		 /**< name for the window position preference */ -#define WINDOWSIZEPREFNAME "size"   			 /**< name for the window size preference */ - -#define BACKBUTTON "back" -#define FORWARDBUTTON "forward" -#define HOMEBUTTON "home" -#define CONTENTBUTTON "contents" -#define TOCDOC "tocDoc" -#define CONTENTSDOC "contentsDoc" -#define TOCVIEW "viewLeft" -#define CONTENTSVIEW "viewRight" -#define PANED "hpane" - -enum pane_views { MAIN_VIEW, CONTENTS_VIEW }; - -#define MAXHISTORYSIZE 20 - -/** \struct htmlHistory  - * for storing information about the browse history  - */ -struct htmlHistory {					 -	int curShownPage;					/**< index of page that is shown currently */ -	int newestPage;					/**< index of newest page loaded */ -	int oldestPage;					/**< index of earliest page loaded */ -	int bInUse;							/**< does buffer have at least one entry */ -	char *url[ MAXHISTORYSIZE ]; 	/**< array of pages in history */ -};	 - -static struct htmlHistory sHtmlHistory; - -#define INCBUFFERINDEX( x ) (((x) + 1 ) % MAXHISTORYSIZE ) -#define DECBUFFERINDEX( x ) ((x) == 0 ? MAXHISTORYSIZE - 1 : (x)-1) - -static char *directory;				/**< base directory for HTML files */ - -static GtkWidget *wHelpWindow;	/**< handle for the help window */ -static GtkWidget *main_view; /** handle for the help main data pane */ -static GtkWidget *contents_view; /** handle for the help contents pane */ - -#define GLADE_HOOKUP_OBJECT(component,widget,name) \ -  g_object_set_data_full (G_OBJECT (component), name, \ -    gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) - -#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ -  g_object_set_data (G_OBJECT (component), name, widget) - -static GtkWidget* -lookup_widget(GtkWidget *widget, const gchar *widget_name) -{ -  GtkWidget *parent, *found_widget; - -  for (;;) -    { -      if (GTK_IS_MENU (widget)) -        parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); -      else -        parent = widget->parent; -      if (!parent) -        parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); -      if (parent == NULL) -        break; -      widget = parent; -    } - -  found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), -                                                 widget_name); -  if (!found_widget) -    g_warning ("Widget not found: %s", widget_name); -  return found_widget; -} - - - -/* - ****************************************************************************** - * - * Help - * - ****************************************************************************** - */ - -wBool_t listHelpStrings = FALSE; -wBool_t listMissingHelpStrings = FALSE; -static char HelpDataKey[] = "HelpDataKey"; - -static GtkWidget * balloonF; -static GtkWidget * balloonPI; -static wBalloonHelp_t * balloonHelpStrings; -static int enableBalloonHelp = 1; -static const char * balloonMsg; -static wControl_p balloonB; -static wPos_t balloonDx, balloonDy; -static wBool_t balloonVisible = FALSE; -static wControl_p balloonHelpB; -static GtkTooltips * tooltips; - - -void wSetBalloonHelp( wBalloonHelp_t * bh ) -{ -	balloonHelpStrings = bh; -	if (!tooltips) -		tooltips = gtk_tooltips_new(); -} - -void wEnableBalloonHelp( int enable ) -{ -	enableBalloonHelp = enable; -	if (tooltips) { -		if (enable) -			gtk_tooltips_enable( tooltips ); -		else -			gtk_tooltips_disable( tooltips ); -	} -} - - -void wControlSetBalloon( wControl_p b, wPos_t dx, wPos_t dy, const char * msg ) -{ -	PangoLayout * layout; -	wPos_t x, y; -	wPos_t w, h; -	wPos_t xx, yy; -	const char * msgConverted;	 -	if (balloonVisible && balloonB == b && -		balloonDx == dx && balloonDy == dy && balloonMsg == msg ) -		return; - -	if ( msg == NULL ) { -		if ( balloonF != NULL ) { -			gtk_widget_hide( balloonF ); -			balloonVisible = FALSE; -		} -		balloonMsg = ""; -		return; -	} -	msgConverted = gtkConvertInput(msg); -	if ( balloonF == NULL ) { -		balloonF = gtk_window_new( GTK_WINDOW_POPUP ); -		gtk_window_set_policy( GTK_WINDOW (balloonF), FALSE, FALSE, TRUE ); -		gtk_widget_realize( balloonF ); -		balloonPI = gtk_label_new(msgConverted); -		gtk_container_add( GTK_CONTAINER(balloonF), balloonPI ); -		gtk_container_border_width( GTK_CONTAINER(balloonF), 1 ); -		gtk_widget_show( balloonPI ); -	} else { -		gtk_label_set( GTK_LABEL(balloonPI), msgConverted ); -	} -	balloonDx = dx; -	balloonDy = dy; -	balloonB = b; -	balloonMsg = msg; -	gtk_widget_hide( balloonF ); -    layout = gtk_widget_create_pango_layout( balloonPI, msgConverted ); -    pango_layout_get_pixel_size( layout, &w, &h ); -	g_object_unref(G_OBJECT(layout)); -	h = 16; -	gdk_window_get_position( GTK_WIDGET(b->parent->gtkwin)->window, &x, &y ); -	gdk_window_get_origin( GTK_WIDGET(b->parent->gtkwin)->window, &x, &y ); -	x += b->realX + dx; -	y += b->realY + b->h - dy; -	xx = gdk_screen_width(); -	yy = gdk_screen_height(); -	if ( x < 0 ) { -		x = 0; -	} else if ( x+w > xx ) { -		x = xx - w; -	} -	if ( y < 0 ) { -		y = 0; -	} else if ( y+h > yy ) { -		y = yy - h ; -	} -	gtk_widget_set_usize( balloonPI, w, h ); -	gtk_widget_set_usize( balloonF, w+2, h+2 ); -	gtk_widget_show( balloonF ); -	gtk_widget_set_uposition( balloonF, x, y ); -	/*gtk_widget_popup( balloonF, x, y );*/ -	gdk_draw_rectangle( balloonF->window, balloonF->style->fg_gc[GTK_STATE_NORMAL], FALSE, 0, 0, w+1, h+1 ); -	gtk_widget_queue_resize( GTK_WIDGET(balloonF) ); -	/*gtk_widget_set_uposition( balloonF, x, y );*/ -	balloonVisible = TRUE; -} - - -void wControlSetBalloonText( -		wControl_p b, -		const char * label ) -{ -	const char * helpStr; -	if ( b->widget == NULL) abort(); -	helpStr = (char*)gtk_object_get_data( GTK_OBJECT(b->widget), HelpDataKey ); -	if ( helpStr == NULL ) helpStr = "NoHelp"; -	if (tooltips) -		gtk_tooltips_set_tip( tooltips, b->widget, label, helpStr ); -} - - -EXPORT void gtkHelpHideBalloon( void ) -{ -	if (balloonF != NULL && balloonVisible) { -		gtk_widget_hide( balloonF ); -		balloonVisible = FALSE; -	} -} - -#ifdef XV_help -static Notify_value showBalloonHelp( Notify_client client, int which ) -{ -	wControlSetBalloon( balloonHelpB, 0, 0, balloonHelpString ); -	return NOTIFY_DONE; -} -#endif - -static wWin_p balloonHelp_w; -static wPos_t balloonHelp_x; -static wPos_t balloonHelp_y; -static void prepareBalloonHelp( wWin_p w, wPos_t x, wPos_t y ) -{ -#ifdef XV -	wControl_p b; -	char * hs; -	int appNameLen = strlen( wAppName ) + 1; -	if (w == NULL) -		return; -#ifdef LATER -	if (!enableBalloonHelp) -		return; -#endif -	if (!balloonHelpStrings) -		return; - -	balloonHelp_w = w; -	balloonHelp_x = x; -	balloonHelp_y = y; - -	for ( b=w->first; b; b=b->next ) { -		switch ( b->type ) { -		case B_BUTTON: -		case B_CANCEL: -		case B_TEXT: -		case B_INTEGER: -		case B_LIST: -		case B_DROPLIST: -		case B_COMBOLIST: -		case B_RADIO: -		case B_TOGGLE: -		case B_DRAW: -		case B_MULTITEXT: -			if (x >= b->realX && x < b->realX+b->w && -				y >= b->realY && y < b->realY+b->h ) { -				hs = (char*)gtk_get( b->panel_item, XV_HELP_DATA ); -				if ( hs ) { -					hs += appNameLen; -					for ( currBalloonHelp = balloonHelpStrings; currBalloonHelp->name && strcmp(currBalloonHelp->name,hs) != 0; currBalloonHelp++ ); -					if (currBalloonHelp->name && balloonHelpB != b && currBalloonHelp->value ) { -						balloonHelpB = b; -						balloonHelpString = currBalloonHelp->value; -						if (enableBalloonHelp) { -							wControlSetBalloon( balloonHelpB, 0, 0, balloonHelpString ); -							/*setTimer( balloonHelpTimeOut, showBalloonHelp );*/ -						} else { -							/*resetBalloonHelp();*/ -						} -					} -					return; -				} -			} -		default: -			; -		} -	} -	cancelTimer( showBalloonHelp ); -	resetBalloonHelp(); -#endif -} - - -void wBalloonHelpUpdate( void ) -{ -	balloonHelpB = NULL; -	balloonMsg = NULL; -	prepareBalloonHelp( balloonHelp_w, balloonHelp_x, balloonHelp_y ); -} - - -void gtkAddHelpString( -		GtkWidget * widget, -		const char * helpStr ) -{ -	int rc; -	char *string; -	wBalloonHelp_t * bhp; -	rc = 0; -	if (helpStr==NULL || *helpStr==0) -		return; -	if ( balloonHelpStrings == NULL ) -		return; -	for ( bhp = balloonHelpStrings; bhp->name && strcmp(bhp->name,helpStr) != 0; bhp++ ); -	if (listMissingHelpStrings && !bhp->name) { -		printf( "Missing Help String: %s\n", helpStr ); -		return; -	} -	string = malloc( strlen(wAppName) + 5 + strlen(helpStr) + 1 ); -	sprintf( string, "%sHelp/%s", wAppName, helpStr ); -	if (tooltips) -		gtk_tooltips_set_tip( tooltips, widget, _(bhp->value), string ); -	gtk_object_set_data( GTK_OBJECT( widget ), HelpDataKey, string ); -	if (listHelpStrings) -		printf( "HELPSTR - %s\n", string ); -} - - -EXPORT const char * wControlGetHelp( -		wControl_p b )		/* Control */ -/* -Returns the help topic string associated with <b>. -*/ -{ -	const char * helpStr; -	helpStr = (char*)gtk_object_get_data( GTK_OBJECT(b->widget), HelpDataKey ); -	return helpStr; -} - - -EXPORT void wControlSetHelp( -	 wControl_p b,		/* Control */ -	 const char * help )		/* topic string */ -/* -Set the help topic string for <b> to <help>. -*/ -{ -	const char * helpStr; -	if (b->widget == 0) abort(); -	helpStr = wControlGetHelp(b); -	if (tooltips) -		gtk_tooltips_set_tip( tooltips, b->widget, help, helpStr ); -} - - -/** - * create a new horizontal pane and place it into container.  - * The separator position is read from the resource configuration and set accordingly.  - * Also a callback is specified that will be executed when the slider has been moved. - * - * \PARAM container IN the container into which the pane will be stuffed. - * \PARAM property IN the name of the property for the slider position - * - * \return the HPaned handle - */ - -GtkWidget * -CreateHPaned( GtkBox *container, char *property ) -{ -	GtkWidget *hpaned; -	long posSlider; -		 -	/* the horizontal slider */ -	hpaned = gtk_hpaned_new (); -	gtk_container_set_border_width (GTK_CONTAINER (hpaned), 6);	 -	 -   wPrefGetInteger( HTMLHELPSECTION, SLIDERPREFNAME, &posSlider, SLIDERPOSDEFAULT ); - 	gtk_paned_set_position (GTK_PANED (hpaned), (int)posSlider);  -	 -   /* pack the horizontal slider into the main window */ -   gtk_box_pack_start( container, hpaned, TRUE, TRUE, 0 ); -	gtk_widget_show( hpaned ); -	 -	return( hpaned ); -}   - -/** - * Handler for the delete-event issued on the help window.We are saving window - * information (eg. position) and are hiding the window instead of closing it. - * - * \PARAM win IN the window to be destroyed - * \PARAM event IN unused - * \PARAM ptr IN unused  - * - * \RETURN FALSE - */ -  -static gboolean -DestroyHelpWindow( GtkWidget *win, GdkEvent *event, void *ptr ) -{ -	int i; -	GtkWidget *widget; -	char tmp[ 20 ]; -	 -	gint x, y; -	 -	/* get the slider position and save it */ -	widget = lookup_widget( win, PANED ); -	i = gtk_paned_get_position( GTK_PANED( widget )); -	wPrefSetInteger( HTMLHELPSECTION, SLIDERPREFNAME, i ); -	 -	/* get the window position */ -	gtk_window_get_position( (GtkWindow *)win, &x, &y );  -	sprintf( tmp, "%d %d", x, y ); -	wPrefSetString( HTMLHELPSECTION, WINDOWPOSPREFNAME, tmp ); -	 -	/* get the window size */	 -	gtk_window_get_size( (GtkWindow *)win , &x, &y ); -	sprintf( tmp, "%d %d", x, y ); -	wPrefSetString( HTMLHELPSECTION, WINDOWSIZEPREFNAME, tmp ); -	 -	gtk_widget_hide( win ); -	return TRUE; -} - -void back_button_clicked(GtkWidget *widget, gpointer data) { -        webkit_web_view_go_back(WEBKIT_WEB_VIEW(data)); -} - -void forward_button_clicked(GtkWidget *widget, gpointer data) { -        webkit_web_view_go_forward(WEBKIT_WEB_VIEW(data)); -} - -void home_button_clicked(GtkWidget *widget, gpointer data) { -        load_into_view("index.html", MAIN_VIEW); -} - -/* Toggles the contents pane */ -void contents_button_clicked(GtkWidget *widget, gpointer data) { -        if (gtk_paned_get_position(GTK_PANED(data)) < 50) { -                gtk_paned_set_position(GTK_PANED(data), 370); -        } -        else { -                gtk_paned_set_position(GTK_PANED(data), 0); -        } -} - -gboolean contents_click_handler( -                WebKitWebView *web_view,  -                WebKitWebFrame *frame,  -                WebKitNetworkRequest *request,  -                WebKitWebNavigationAction *navigation_action,  -                WebKitWebPolicyDecision *policy_decision,  -                gpointer data) { - -        webkit_web_view_load_uri(WEBKIT_WEB_VIEW(data), webkit_network_request_get_uri(request)); - -        return TRUE; -} - -/** - * Initialize the buttons for the help window - */ -void initialize_buttons (GtkWidget *main_vbox, GtkWidget *content_hpane) { -        GtkWidget *buttons_hbuttonbox; -        GtkWidget *back_button; -        GtkWidget *forward_button; -        GtkWidget *home_button; -        GtkWidget *contents_button; - -        // define and attach signals to buttons -        back_button = gtk_button_new_with_label(_("Back")); -        g_signal_connect(back_button, "clicked", G_CALLBACK(back_button_clicked), G_OBJECT(main_view)); - -        forward_button = gtk_button_new_with_label(_("Forward")); -        g_signal_connect(forward_button, "clicked", G_CALLBACK(forward_button_clicked), G_OBJECT(main_view)); - -        home_button = gtk_button_new_with_label(_("Home")); -        g_signal_connect(home_button, "clicked", G_CALLBACK(home_button_clicked), G_OBJECT(main_view)); - -        contents_button = gtk_button_new_with_label(_("Contents")); -        g_signal_connect(contents_button, "clicked", G_CALLBACK(contents_button_clicked), G_OBJECT(content_hpane)); - -        // button layout -        buttons_hbuttonbox = gtk_hbutton_box_new(); -        gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), back_button); -        gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), forward_button); -        gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), home_button); -        gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), contents_button); -        gtk_box_pack_start(GTK_BOX(main_vbox), buttons_hbuttonbox, FALSE, TRUE, 0); -        gtk_box_set_spacing(GTK_BOX(buttons_hbuttonbox), 6); -        gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_hbuttonbox), GTK_BUTTONBOX_START); - -	/* Store pointers to all widgets, for use by lookup_widget().  */ -	GLADE_HOOKUP_OBJECT (main_view, back_button, BACKBUTTON); -	GLADE_HOOKUP_OBJECT (main_view, forward_button, FORWARDBUTTON); -	GLADE_HOOKUP_OBJECT (main_view, home_button, HOMEBUTTON); -	GLADE_HOOKUP_OBJECT (main_view, contents_button, CONTENTBUTTON); -} - -/** - * Create the help windows including all contained widgets and the needed HTML documents. - *  - * \RETURN handle of the created window. - */ -  -GtkWidget* -CreateHelpWindow (void) -{ -        GtkWidget *main_vbox; -        GtkWidget *main_view_scroller; -        GtkWidget *contents_view_scroller; -        GtkWidget *content_hpane; -	 -	int width; -  	int height; -	int x, y; -	int w = 0, h = 0; -  	const char *pref; -	char title[100];  - - 	wHelpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); - -	width = gdk_screen_get_width( gtk_window_get_screen( (GtkWindow *)wHelpWindow )); -	height = gdk_screen_get_height( gtk_window_get_screen( (GtkWindow *)wHelpWindow )); - -	pref = wPrefGetString( HTMLHELPSECTION, WINDOWSIZEPREFNAME ); -	if( pref ) { -		sscanf( pref, "%d %d", &w, &h ); -		if( w > width ) -			w = width; -		if( h > height ) -			h = height;				 -	} -	else { -		w = ( width * 2 )/ 5; -		h = height - 100; -	} - -	pref = wPrefGetString( HTMLHELPSECTION, WINDOWPOSPREFNAME ); -	if( pref ) { -		sscanf( pref, "%d %d", &x, &y ); -		if( y > height - h ) -			y = height - h; -			 -		if( x > width - w ) -			x = width - w;		 -	} -	else { -		x = ( width * 3 ) / 5 - 10; -		y = 70; -	} -	 -	gtk_window_resize( (GtkWindow *)wHelpWindow, w, h ); -	gtk_window_move( (GtkWindow *)wHelpWindow, x, y ); - -	gtk_window_set_title (GTK_WINDOW (wHelpWindow), "XTrkCad Help"); - -	g_signal_connect( G_OBJECT( wHelpWindow ), "delete-event", G_CALLBACK( DestroyHelpWindow ), NULL ); - -	main_view_scroller = gtk_scrolled_window_new(NULL, NULL); -	contents_view_scroller = gtk_scrolled_window_new(NULL, NULL); -	main_view = webkit_web_view_new(); -	contents_view = webkit_web_view_new(); -	// must be done here as it gets locked down later -	load_into_view ("contents.html", CONTENTS_VIEW); -	gtk_widget_set_size_request(GTK_WIDGET(wHelpWindow), x, y); - -	main_vbox = gtk_vbox_new(FALSE, 5); -	gtk_container_add(GTK_CONTAINER(wHelpWindow), main_vbox); - -	gtk_container_add(GTK_CONTAINER(main_view_scroller), main_view); - -	gtk_container_add(GTK_CONTAINER(contents_view_scroller), contents_view); - -	content_hpane = gtk_hpaned_new(); -	initialize_buttons(main_vbox, content_hpane); -	gtk_container_add(GTK_CONTAINER(content_hpane), contents_view_scroller); -	gtk_container_add(GTK_CONTAINER(content_hpane), main_view_scroller); -	gtk_box_pack_start(GTK_BOX(main_vbox), content_hpane, TRUE, TRUE, 0); - -	gtk_paned_set_position(GTK_PANED(content_hpane), 370); - -	g_signal_connect(contents_view, "navigation-policy-decision-requested", G_CALLBACK(contents_click_handler), G_OBJECT(main_view)); - -	/* Store pointers to all widgets, for use by lookup_widget().  */ -	GLADE_HOOKUP_OBJECT_NO_REF (wHelpWindow, wHelpWindow, "wHelpWindow"); -	GLADE_HOOKUP_OBJECT (wHelpWindow, content_hpane, PANED ); -	GLADE_HOOKUP_OBJECT (wHelpWindow, contents_view, TOCVIEW ); -	GLADE_HOOKUP_OBJECT (wHelpWindow, main_view, CONTENTSVIEW ); - -	return wHelpWindow; -} - -void load_into_view (char *file, int requested_view) { -	GtkWidget *view; -  -	switch (requested_view) { -	       case MAIN_VIEW: -	               view = main_view; -	               break; -	       case CONTENTS_VIEW: -	               view = contents_view; -	               break; -	       default: -	               printf("*** error, could not find view"); -	               break; -	} - -	char fileToLoad[100] = "file://"; -	strcat(fileToLoad,directory); -	strcat(fileToLoad,file); - -	//debug printf("*** loading %s into pane %d.\n", fileToLoad, requested_view); -	webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view), fileToLoad); -} - -/** - * Invoke the help system to display help for <topic>. - * - * \param topic IN topic string - */ - -EXPORT void wHelp( const char * topic )		 -{ -	char *htmlFile; - -	if( !wHelpWindow ) -	{ -		directory = malloc( BUFSIZ ); -		assert( directory != NULL ); -			 -		sprintf( directory, "%s/html/", wGetAppLibDir()); -		 -		wHelpWindow = CreateHelpWindow(); -		/* load the default content */ -		load_into_view ("index.html", MAIN_VIEW); -	} - -	/* need space for the 'html' extension plus dot plus \0 */ -	htmlFile = malloc( strlen( topic ) + 6 ); -	assert( htmlFile != NULL ); -	 -	sprintf( htmlFile, "%s.html", topic ); -	 -	load_into_view (htmlFile, MAIN_VIEW); -	gtk_widget_show_all(wHelpWindow); -	gtk_window_present(GTK_WINDOW(wHelpWindow)); -} - -/** - * Handle the commands issued from the Help drop-down. Currently, we only have a table  - * of contents, but search etc. might be added in the future. - * - * \PARAM data IN command value  - * - */ -  -static void  -DoHelpMenu( void *data ) -{ -	int func = (intptr_t)data; -	 -	switch( func ) -	{ -		case 1: -			wHelp( "index" ); -			break; -		default: -			break; -	} -	 -	return;		 -} - -/** - * Add the entries for Help to the drop-down. - *  - * \PARAM m IN handle of drop-down - * - */ - -void wMenuAddHelp( wMenu_p m ) -{ -	wMenuPushCreate( m, NULL, _("&Contents"), 0, DoHelpMenu, (void*)1 ); -} diff --git a/app/wlib/gtklib/gtkint.h b/app/wlib/gtklib/gtkint.h index c27c70b..da0d9ae 100644 --- a/app/wlib/gtklib/gtkint.h +++ b/app/wlib/gtklib/gtkint.h @@ -1,5 +1,5 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkint.h,v 1.8 2009-12-12 17:16:08 m_fischer Exp $ +/** \file gtkint.h  + * Internal definitions for the gtk-library   */  /*  XTrkCad - Model Railroad CAD @@ -27,7 +27,6 @@  #include "gdk/gdk.h"  #include "gtk/gtk.h" -#define EXPORT  #ifdef WINDOWS  #define strcasecmp _stricmp @@ -35,6 +34,10 @@  #include "dynarr.h" +#define BORDERSIZE	(4) +#define LABEL_OFFSET	(3) +#define MENUH	(24) +  extern wWin_p gtkMainW;  typedef enum { @@ -84,6 +87,37 @@ struct wWin_t {  struct wControl_t {  		WOBJ_COMMON  		}; +		 +typedef struct wListItem_t * wListItem_p; + +struct wList_t { +		WOBJ_COMMON +//		GtkWidget *list; +		int count; +		int number; +		int colCnt; +		wPos_t *colWidths; +		wBool_t *colRightJust; +		GtkListStore *listStore; +		GtkWidget  *treeView; +		int last; +		wPos_t listX; +		long * valueP; +		wListCallBack_p action; +		int recursion; +		int editted; +		int editable; +		}; + + +struct wListItem_t { +		wBool_t active; +		void * itemData; +		const char * label; +		GtkLabel * labelG; +		wBool_t selected; +		wList_p listP; +		};		  #define gtkIcon_bitmap (1)  #define gtkIcon_pixmap (2) @@ -95,83 +129,118 @@ struct wIcon_t {  		const void * bits;  		}; -extern char wAppName[];  extern char wConfigName[];  extern wDrawColor wDrawColorWhite;  extern wDrawColor wDrawColorBlack; -/* gtkmisc.c */ -void * gtkAlloc( wWin_p, wType_e, wPos_t, wPos_t, const char *, int, void * ); -void gtkComputePos( wControl_p ); -void gtkAddButton( wControl_p ); -int gtkAddLabel( wControl_p, const char * ); -void gtkControlGetSize( wControl_p ); -struct accelData_t; -struct accelData_t * gtkFindAccelKey( GdkEventKey * event ); -wBool_t gtkHandleAccelKey( GdkEventKey * ); -wBool_t catch_shift_ctrl_alt_keys( GtkWidget *, GdkEventKey *, void * ); -void gtkSetReadonly( wControl_p, wBool_t ); -wControl_p gtkGetControlFromPos( wWin_p, wPos_t, wPos_t ); -void gtkSetTrigger( wControl_p, setTriggerCallback_p ); -GdkPixmap * gtkMakeIcon( GtkWidget *, wIcon_p, GdkBitmap ** ); -char * gtkConvertInput( const char * ); -char * gtkConvertOutput( const char * ); - -/* gtkwindow.c */ -void gtkDoModal( wWin_p, wBool_t ); - -/* gtkhelp.c */ -void load_into_view( char *, int ); -void gtkAddHelpString( GtkWidget *, const char * ); -void gtkHelpHideBalloon( void ); - -/* gtksimple.c */ -void gtkDrawBox( wWin_p, wBoxType_e, wPos_t, wPos_t, wPos_t, wPos_t ); -void gtkLineShow( wLine_p, wBool_t ); - -/* gktlist.c */ -void gtkListShow( wList_p, wBool_t ); -void gtkListSetPos( wList_p ); -void gtkListActive( wList_p, wBool_t ); -void gtkDropListPos( wList_p ); - -/* gtktext.c */ -void gtkTextFreeze( wText_p ); -void gtkTextThaw( wText_p ); - -/* gtkfont.c */ -const char * gtkFontTranslate( wFont_p ); -PangoLayout *gtkFontCreatePangoLayout( GtkWidget *, void *cairo, -									  wFont_p, wFontSize_t, const char *, -									  int *, int *, int *, int * ); - -/* gtkbutton.c */ -void gtkButtonDoAction( wButton_p ); -void gtkSetLabel( GtkWidget*, long, const char *, GtkLabel**, GtkWidget** ); - -/* gtkcolor.c */ -void gtkGetColorMap( void ); -GdkColor * gtkGetColor( wDrawColor, wBool_t ); -int gtkGetColorChar( wDrawColor ); -void gtkPrintColorMap( FILE *, int, int ); -int gtkMapPixel( long ); - -/* psprint.c */ - -void WlibApplySettings( GtkPrintOperation *op ); -void WlibSaveSettings( GtkPrintOperation *op ); - -void psPrintLine( wPos_t, wPos_t, wPos_t, wPos_t, -				wDrawWidth, wDrawLineType_e, wDrawColor, wDrawOpts ); -void psPrintArc( wPos_t, wPos_t, wPos_t, double, double, int, -				wDrawWidth, wDrawLineType_e, wDrawColor, wDrawOpts ); -void psPrintString( wPos_t x, wPos_t y, double a, char * s, -				wFont_p fp,	double fs,	wDrawColor color,	wDrawOpts opts ); - -void psPrintFillRectangle( wPos_t, wPos_t, wPos_t, wPos_t, wDrawColor, wDrawOpts ); -void psPrintFillPolygon( wPos_t [][2], int, wDrawColor, wDrawOpts ); -void psPrintFillCircle( wPos_t, wPos_t, wPos_t, wDrawColor, wDrawOpts ); + +/* boxes.c */ +void wlibDrawBox(wWin_p win, wBoxType_e style, wPos_t x, wPos_t y, wPos_t w, wPos_t h); + +/* button.c */ +void wlibSetLabel(GtkWidget *widget, long option, const char *labelStr, GtkLabel **labelG, GtkWidget **imageG); +void wlibButtonDoAction(wButton_p bb); + +struct wButton_t { +    WOBJ_COMMON +    GtkLabel * labelG; +    GtkWidget * imageG; +    wButtonCallBack_p action; +    int busy; +    int recursion; +}; + +/* color.c */ +typedef struct { +    unsigned char red; +    unsigned char green; +    unsigned char blue; +    GdkColor normalColor; +    GdkColor invertColor; +    long rgb; +    int colorChar; +} colorMap_t; + +GdkColor *wlibGetColor(wDrawColor color, wBool_t normal); + +/* control.c */ + +/* droplist.c */ +enum columns { +	LISTCOL_DATA,			/**< user data not for display */ +	LISTCOL_BITMAP,         /**< bitmap column */ +	LISTCOL_TEXT, 			/**< starting point for text columns */ +}; +GtkWidget *wlibNewDropList(GtkListStore *ls, int editable); + +wIndex_t wDropListGetCount(wList_p b); +void wDropListClear(wList_p b); +void *wDropListGetItemContext(wList_p b, wIndex_t inx); +void wDropListAddValue(wList_p b, char *text, wListItem_p data); +void wDropListSetIndex(wList_p b, int val); +wBool_t wDropListSetValues(wList_p b, wIndex_t row, const char *labelStr, wIcon_p bm, void *itemData); +wList_p wDropListCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, long number, wPos_t width, long *valueP, wListCallBack_p action, void *data); + +/* filesel.c */ + +/* font.c */ +PangoLayout *wlibFontCreatePangoLayout(GtkWidget *widget, void *cairo, wFont_p fp, wFontSize_t fs, const char *s, int *width_p, int *height_p, int *ascent_p, int *descent_p); +void wlibFontDestroyPangoLayout(PangoLayout *layout); +const char *wlibFontTranslate(wFont_p fp); + +/* help.c */ + +/* lines.c */ +void wlibLineShow(wLine_p bl, wBool_t visible); + +/* list.c */ +int CompareListData(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); + +/* liststore.c */ +wListItem_p wlibListItemGet(GtkListStore *ls, wIndex_t inx, GList **childR); +void *wlibListStoreGetContext(GtkListStore *ls, int inx); +void wlibListStoreClear(GtkListStore *listStore); +GtkListStore *wlibNewListStore(int colCnt); +void wlibListStoreSetPixbuf(GtkListStore *ls, GtkTreeIter *iter, GdkPixbuf *pixbuf); +int wlibListStoreAddData(GtkListStore *ls, GdkPixbuf *pixbuf, int cols, wListItem_p id); +int wlibListStoreUpdateValues(GtkListStore *ls, int row, int cols, char *labels, wIcon_p bm); + +/* main.c */ +char *wlibGetAppName(void); + +/* menu.c */ +int getMlistOrigin(wMenuList_p ml, GList **pChildren); + +/* misc.c */ +typedef struct accelData_t { +    wAccelKey_e key; +    int modifier; +    wAccelKeyCallBack_p action; +    void * data; +} accelData_t; + + +GdkPixbuf* wlibPixbufFromXBM(wIcon_p ip); +int wlibAddLabel(wControl_p b, const char *labelStr); +void *wlibAlloc(wWin_p parent, wType_e type, wPos_t origX, wPos_t origY, const char *labelStr, int size, void *data); +void wlibComputePos(wControl_p b); +void wlibControlGetSize(wControl_p b); +void wlibAddButton(wControl_p b); +wControl_p wlibGetControlFromPos(wWin_p win, wPos_t x, wPos_t y); +char *wlibConvertInput(const char *inString); +char *wlibConvertOutput(const char *inString); +struct accelData_t *wlibFindAccelKey(GdkEventKey *event); +wBool_t wlibHandleAccelKey(GdkEventKey *event); + +/* notice.c */ + +/* pixbuf.c */ +GdkPixbuf *wlibMakePixbuf(wIcon_p ip); + +/* png.c */ + +/* print.c */  struct wDraw_t {  		WOBJ_COMMON  		void * context; @@ -199,4 +268,48 @@ struct wDraw_t {  		cairo_t *printContext;  		cairo_surface_t *curPrintSurface;  		}; + +void WlibApplySettings(GtkPrintOperation *op); +void WlibSaveSettings(GtkPrintOperation *op); +void psPrintLine(wPos_t x0, wPos_t y0, wPos_t x1, wPos_t y1, wDrawWidth width, wDrawLineType_e lineType, wDrawColor color, wDrawOpts opts); +void psPrintArc(wPos_t x0, wPos_t y0, wPos_t r, double angle0, double angle1, wBool_t drawCenter, wDrawWidth width, wDrawLineType_e lineType, wDrawColor color, wDrawOpts opts); +void psPrintFillRectangle(wPos_t x0, wPos_t y0, wPos_t x1, wPos_t y1, wDrawColor color, wDrawOpts opts); +void psPrintFillPolygon(wPos_t p[][2], int cnt, wDrawColor color, wDrawOpts opts); +void psPrintFillCircle(wPos_t x0, wPos_t y0, wPos_t r, wDrawColor color, wDrawOpts opts); +void psPrintString(wPos_t x, wPos_t y, double a, char *s, wFont_p fp, double fs, wDrawColor color, wDrawOpts opts); +static void WlibGetPaperSize(void); + +/* single.c */ + +/* splash.c */ + +/* text.c */ + +/* timer.c */ +void wlibSetTrigger(wControl_p b, setTriggerCallback_p trigger); + +/* tooltip.c */ +#define HELPDATAKEY "HelpDataKey" +void wlibAddHelpString(GtkWidget *widget, const char *helpStr); +void wlibHelpHideBalloon(); + +/* treeview.c */ +void wlibTreeViewSetSelected(wList_p b, int index); +GtkWidget *wlibNewTreeView(GtkListStore *ls, int showTitles, int multiSelection); +int wlibTreeViewAddColumns(GtkWidget *tv, int count); +int wlibAddColumnTitles(GtkWidget *tv, const char **titles); +int wlibTreeViewAddData(GtkWidget *tv, int cols, char *label, GdkPixbuf *pixbuf, wListItem_p userData); +void wlibTreeViewAddRow(wList_p b, char *label, wIcon_p bm, wListItem_p id_p); +gboolean changeSelection(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data); + +int wTreeViewGetCount(wList_p b); +void wTreeViewClear(wList_p b); +void *wTreeViewGetItemContext(wList_p b, int row); + +/* window.c */ +void wlibDoModal(wWin_p win0, wBool_t modal); +wBool_t catch_shift_ctrl_alt_keys(GtkWidget *widget, GdkEventKey *event, void *data); + +/* wpref.c */ +  #endif diff --git a/app/wlib/gtklib/gtklist.c b/app/wlib/gtklib/gtklist.c deleted file mode 100644 index fb8afaa..0000000 --- a/app/wlib/gtklib/gtklist.c +++ /dev/null @@ -1,1131 +0,0 @@ -/** \file gtklist.c - * Listboxes, dropdown boxes, combo boxes - */ -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include "gtkint.h" -#include "i18n.h" - -#define ROW_HEIGHT (15) -#define PIX_TEXT_SEP (5) -static char ListItemDataKey[] = "ListItemDataKey"; - -/* - ***************************************************************************** - * - * List Boxes - * - ***************************************************************************** - */ - -typedef struct wListItem_t * wListItem_p; - -struct wList_t { -		WOBJ_COMMON -		GtkWidget *list; -		int count; -		int number; -		int colCnt; -		wPos_t *colWidths; -		wBool_t *colRightJust; -		int last; -		wPos_t listX; -		long * valueP; -		wListCallBack_p action; -		int recursion; -		int editted; -		int editable; -		}; - - -struct wListItem_t { -		wBool_t active; -		void * itemData; -		const char * label; -		GtkLabel * labelG; -		wBool_t selected; -		wList_p listP; -		}; - - -static wListItem_p getListItem( -		wList_p b, -		wIndex_t inx, -		GList ** childR ) -{ -	GList * child; -	GtkObject * listItem; -	wListItem_p id_p; -	if (childR) -		*childR = NULL; -	if (b->list == 0) abort(); -	if (inx < 0) -		return NULL; -	if ( b->type == B_LIST ) -		return (wListItem_p)gtk_clist_get_row_data( GTK_CLIST(b->list), inx ); - -	for ( child=GTK_LIST(b->list)->children; inx>0&&child; child=child->next,inx-- ); -	if (child==NULL) { -		fprintf( stderr, "wListGetValues - End Of List\n" ); -		return NULL; -	} -	listItem = GTK_OBJECT(child->data); -	id_p = (wListItem_p)gtk_object_get_data(listItem, ListItemDataKey ); -	if (id_p==NULL) { -		fprintf( stderr, "wListGetValues - id_p == NULL\n" ); -		return NULL; -	} -	if (childR) -		*childR = child; -	return id_p; -} - - -EXPORT void wListClear( -		wList_p b )		/* List */ -/* -Remove all entries from the list <b>. -*/ -{ -	if (b->list == 0) abort(); -	b->recursion++; -	if ( b->type == B_DROPLIST ) -		gtk_list_clear_items( GTK_LIST(b->list), 0, b->count ); -	else -		gtk_clist_clear( GTK_CLIST(b->list) ); -	b->recursion--; -	b->last = -1; -	b->count = 0; -} - - -EXPORT void wListSetIndex( -		wList_p b,		/* List */ -		int val )		/* Index */ -/* -Makes the <val>th entry (0-origin) the current selection. -If <val> if '-1' then no entry is selected. -*/ -{ -	int cur; -	wListItem_p id_p; - -	if (b->widget == 0) abort(); -	b->recursion++; -	cur = b->last; -	if ( b->type == B_DROPLIST ) { -	if ((b->option&BL_NONE)!=0 && val < 0) { -		if (cur != -1) { -			gtk_list_unselect_item( GTK_LIST(b->list), cur ); -		} -	} else { -		if (cur != -1) -			gtk_list_unselect_item( GTK_LIST(b->list), cur ); -		if (val != -1) -			gtk_list_select_item( GTK_LIST(b->list), val ); -	} -	} else { -		if (cur != -1) { -			gtk_clist_unselect_row( GTK_CLIST(b->list), cur, -1 ); -			id_p = getListItem( b, cur, NULL ); -			if ( id_p ) -				id_p->selected = FALSE; -		} -		if (val != -1) { -			gtk_clist_select_row( GTK_CLIST(b->list), val, -1 ); -			id_p = getListItem( b, val, NULL ); -			if ( id_p ) -				id_p->selected = TRUE; -		} -	} -	b->last = val; -	b->recursion--; -} - - -static void parseLabelStr( -		const char * labelStr, -		int count, -		char * * * texts ) -{ -	static char * labelBuffer; -	static int labelBufferLen = 0; -	static char * * textBuffer; -	static int textBufferCount = 0; -	char * cp; -	int col; -	int len; - -	labelStr = gtkConvertInput( labelStr ); -	len = strlen(labelStr)+1; -	if ( len > labelBufferLen ) { -		if ( labelBuffer ) -			labelBuffer = realloc( labelBuffer, len ); -		else -			labelBuffer = (char*)malloc( len ); -		labelBufferLen = len; -	} -	if ( count > textBufferCount ) { -		if ( textBuffer ) -			textBuffer = (char**)malloc( count * sizeof *textBuffer ); -		else -			textBuffer = (char**)realloc( textBuffer, count * sizeof *textBuffer ); -		textBufferCount = count; -	} - -	strcpy( labelBuffer, labelStr ); -	cp = labelBuffer; -	for ( col=0; cp && col<count; col++ ) { -		textBuffer[col] = cp; -		cp = strchr( cp, '\t' ); -		if ( cp != NULL ) -			*cp++ = '\0'; -	} -	for ( ; col<count; col++ ) -		textBuffer[col] = ""; -	*texts = textBuffer; -} - - -EXPORT void wListSetValue( -		wList_p bl, -		const char * val ) -{ -	if (bl->list==NULL) abort(); -	bl->recursion++; -	if (bl->type == B_DROPLIST) { -		bl->editted = TRUE; -		gtk_entry_set_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry), val ); -		if (bl->action) { -			bl->action( -1, val, 0, bl->data, NULL ); -		} -	} -	bl->recursion--; -} - - -EXPORT wIndex_t wListFindValue( -		wList_p b, -		const char * val ) -{ -	GList * child; -	GtkObject * listItem; -	wListItem_p id_p; -	wIndex_t inx; - -	if (b->list==NULL) abort(); -	if (b->type == B_DROPLIST) { -		for ( child=GTK_LIST(b->list)->children,inx=0; child; child=child->next,inx++ ) { -			listItem = GTK_OBJECT(child->data); -			id_p = (wListItem_p)gtk_object_get_data(listItem, ListItemDataKey ); -			if ( id_p && id_p->label && strcmp( id_p->label, val ) == 0 ) { -				return inx; -			} -		} -	} else { -		for ( inx=0; inx<b->count; inx++ ) { -			id_p = (wListItem_p)gtk_clist_get_row_data( GTK_CLIST(b->list), inx ); -			if ( id_p && id_p->label && strcmp( id_p->label, val ) == 0 ) -				return inx; -		} -	} -	return -1; -} - -EXPORT wIndex_t wListGetIndex( -		wList_p b )		/* List */ -/* -Returns the current selected list entry. -If <val> if '-1' then no entry is selected. -*/ -{ -	if (b->list == 0) abort(); -	return b->last; -} - -EXPORT wIndex_t wListGetValues( -		wList_p bl, -		char * labelStr, -		int labelSize, -		void * * listDataRet, -		void * * itemDataRet ) - -{ -	wListItem_p id_p; -	wIndex_t inx = bl->last; -	const char * entry_value = ""; -	void * item_data = NULL; - -	if ( bl->list == 0 ) abort(); -	if ( bl->type == B_DROPLIST && bl->editted ) { -		entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) ); -		inx = bl->last = -1; -	} else { -		inx = bl->last; -		if (inx >= 0) { -			id_p = getListItem( bl, inx, NULL ); -			if (id_p==NULL) { -				fprintf( stderr, "wListGetValues - id_p == NULL\n" ); -				inx = -1; -			} else { -				entry_value = id_p->label; -				item_data = id_p->itemData; -			} -		} -	} -	if ( labelStr ) { -		strncpy( labelStr, entry_value, labelSize ); -	} -	if ( listDataRet ) -		*listDataRet = bl->data; -	if ( itemDataRet ) -		*itemDataRet = item_data; -	return bl->last; -} - - -EXPORT wIndex_t wListGetCount( -		wList_p b ) -{ -	return b->count; -} - - -EXPORT void * wListGetItemContext( -		wList_p b, -		wIndex_t inx ) -{ -	wListItem_p id_p; -	if ( inx < 0 ) -		return NULL; -	id_p = getListItem( b, inx, NULL ); -	if ( id_p ) -		return id_p->itemData; -	else -		return NULL; -} - - -EXPORT wBool_t wListGetItemSelected( -		wList_p b, -		wIndex_t inx ) -{ -	wListItem_p id_p; -	if ( inx < 0 ) -		return FALSE; -	id_p = getListItem( b, inx, NULL ); -	if ( id_p ) -		return id_p->selected; -	else -		return FALSE; -} - - -EXPORT wIndex_t wListGetSelectedCount( -		wList_p b ) -{ -	wIndex_t selcnt, inx; -	for ( selcnt=inx=0; inx<b->count; inx++ ) -		if ( wListGetItemSelected( b, inx ) ) -			selcnt++; -	return selcnt; -} - -/** - * Select all items in list. - * - * \param bl IN list handle - * \return - */ - -void wListSelectAll( wList_p bl ) -{ -	wIndex_t inx; -	wListItem_p ldp; - -	// mark all items selected -	gtk_clist_select_all(GTK_CLIST(bl->list)); - -	// and synchronize the internal data structures -	wListGetCount(bl); -	for ( inx=0; inx<bl->count; inx++ ) { -		ldp = getListItem( bl, inx, NULL ); - -		ldp->selected = TRUE; -	} -} - -EXPORT wBool_t wListSetValues( -		wList_p b, -		wIndex_t row, -		const char * labelStr, -		wIcon_p bm, -		void *itemData ) - -{ -	wListItem_p id_p; -	GList * child; -	GdkPixmap *pixmap; -	GdkBitmap *bitmap = NULL; -	char ** texts; -	int col; - -	if (b->list == 0) abort(); -	b->recursion++; -	id_p = getListItem( b, row, &child ); -	if (id_p != NULL) { -		if ( b->type == B_DROPLIST ) { -			gtk_label_set( id_p->labelG, labelStr?gtkConvertInput(labelStr):"" ); -			id_p->label = strdup( labelStr?labelStr:"" ); -		} else { -			parseLabelStr( labelStr, b->colCnt, &texts ); -			for ( col=0; col<b->colCnt; col++ ) -				gtk_clist_set_text( GTK_CLIST(b->list), row, col, texts[col] ); -			if ( bm ) { -				pixmap = gtkMakeIcon( b->widget, bm, &bitmap ); -				gtk_clist_set_pixtext( GTK_CLIST(b->list), row, 0, texts[0], 5, pixmap, bitmap ); -				gdk_pixmap_unref( pixmap ); -				gdk_bitmap_unref( bitmap ); -			} -		} -		id_p->itemData = itemData; -	} -	b->recursion--; -	return TRUE; -} - - -EXPORT void wListDelete( -		wList_p b, -		wIndex_t inx ) - -{ -	wListItem_p id_p; -	GList * child; - -	if (b->list == 0) abort(); -	b->recursion++; -	if ( b->type == B_DROPLIST ) { -		id_p = getListItem( b, inx, &child ); -		if (id_p != NULL) { -			gtk_container_remove( GTK_CONTAINER(b->list), child->data ); -			b->count--; -		} -	} else { -		gtk_clist_remove( GTK_CLIST(b->list), inx ); -		b->count--; -	} -	b->recursion--; -	return; -} - - -int wListGetColumnWidths( -		wList_p bl, -		int colCnt, -		wPos_t * colWidths ) -{ -	int inx; - -	if ( bl->type != B_LIST ) -		return 0; -	if ( bl->colWidths == NULL ) -		return 0; -	for ( inx=0; inx<colCnt; inx++ ) { -		if ( inx < bl->colCnt ) { -			colWidths[inx] = bl->colWidths[inx]; -		} else { -			colWidths[inx] = 0; -		} -	} -	return bl->colCnt; -} - - -static void gtkDropListAddValue( -		wList_p b, -		wListItem_p id_p ) -{ -	GtkWidget * listItem; - -	if ( id_p == NULL ) -		return; -	id_p->labelG = (GtkLabel*)gtk_label_new( gtkConvertInput(id_p->label) ); -	/*gtk_misc_set_alignment( GTK_MISC(id_p->labelG), 0.0, 0.5 );*/ -	gtk_widget_show( GTK_WIDGET(id_p->labelG) ); - -	listItem = gtk_list_item_new(); -	gtk_object_set_data( GTK_OBJECT(listItem), ListItemDataKey, id_p ); -	gtk_container_add( GTK_CONTAINER(listItem), GTK_WIDGET(id_p->labelG) ); -	gtk_misc_set_alignment( GTK_MISC(id_p->labelG), 0.0, 0.5 ); -	gtk_container_add( GTK_CONTAINER(b->list), listItem ); -	gtk_widget_show( listItem ); -} - - -EXPORT wIndex_t wListAddValue( -		wList_p b,		/* List */ -		const char * labelStr,	/* Entry name */ -		wIcon_p bm,	/* Entry bitmap */ -		void * itemData )	/* User context */ -/* -Adds a entry to the list <b> with name <name>. -If list is created with 'BL_ -*/ -{ -	wListItem_p id_p; -	GdkPixmap * pixmap = NULL; -	GdkBitmap * bitmap; -	static char ** texts; -	GtkAdjustment *adj; - -	if (b->list == 0) abort(); -	b->recursion++; -	id_p = (wListItem_p)malloc( sizeof *id_p ); -	memset( id_p, 0, sizeof *id_p ); -	id_p->itemData = itemData; -	id_p->active = TRUE; -	if ( labelStr == NULL ) -		labelStr = ""; -	id_p->label = strdup( labelStr ); -	id_p->listP = b; -	if ( b->type == B_DROPLIST ) { -		gtkDropListAddValue( b, id_p ); -	} else { -		parseLabelStr( labelStr, b->colCnt, &texts ); -		gtk_clist_append( GTK_CLIST(b->list), texts ); - -		/* -		 * this has taken forever to find out: the adjustment has to be notified -		 * about the list change by the program. So we need to get the current alignment. -		 * increment the upper value and then inform the scrolled window about the update. -		 * The upper value is increased only if the current value is smaller than the size -		 * of the list box. -		 */ - -		adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(b->widget)); - -		if( adj->upper < adj->step_increment * (b->count+1)) { -			adj->upper += adj->step_increment; -			gtk_adjustment_changed( adj ); -		} -		if ( bm ) { -			pixmap = gtkMakeIcon( b->widget, bm, &bitmap ); -			gtk_clist_set_pixtext( GTK_CLIST(b->list), b->count, 0, texts[0], 5, pixmap, bitmap ); -			gdk_pixmap_unref( pixmap ); -			gdk_bitmap_unref( bitmap ); -		} -		gtk_clist_set_row_data( GTK_CLIST(b->list), b->count, id_p ); -	} - -	b->count++; -	b->recursion--; -	if ( b->count == 1 ) { -		b->last = 0; -	} -	return b->count-1; -} - - -void wListSetSize( wList_p bl, wPos_t w, wPos_t h ) -{ -	/*gtk_widget_set_usize( bl->list, w, h );*/ -	if (bl->type == B_DROPLIST) { -		/*gtk_widget_set_usize( GTK_COMBO(bl->widget)->entry, w, -1 ); -		gtk_widget_set_usize( GTK_COMBO(bl->widget)->list, w, -1 );*/ -#ifndef GTK1 -		gtk_widget_set_size_request( bl->widget, w, -1 ); -#else -		gtk_widget_set_usize( bl->widget, w, -1 ); -#endif -	} else { -#ifndef GTK1 -		gtk_widget_set_size_request( bl->widget, w, h ); -#else -		gtk_widget_set_usize( bl->widget, w, h ); -#endif -	} -	bl->w = w; -	bl->h = h; -} - - - - -EXPORT void wListSetActive( -		wList_p b,		/* List */ -		int inx,		/* Index */ -		wBool_t active )	/* Command */ -/* -*/ -{ -	wListItem_p id_p; -	GList * child; - -	if (b->list == 0) abort(); -	id_p = getListItem( b, inx, &child ); -	if (id_p == NULL) -		return; -	gtk_widget_set_sensitive( GTK_WIDGET(child->data), active ); -} - - -EXPORT void wListSetEditable( -		wList_p b, -		wBool_t editable ) -{ -	b->editable = editable; -	if ( b->type == B_DROPLIST ) -		gtk_widget_set_sensitive( GTK_WIDGET(GTK_COMBO(b->widget)->entry), b->editable ); -} - - -static int selectCList( -		GtkWidget * clist, -		int row, -		int col, -		GdkEventButton* event, -		gpointer data ) -{ -	wList_p bl = (wList_p)data; -	wListItem_p id_p; - -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -	wFlush(); -	if (bl->recursion) -		return 0; -	id_p = gtk_clist_get_row_data( GTK_CLIST(clist), row ); -	if ( id_p == NULL ) return 1; -	bl->editted = FALSE; -	if ( (bl->option&BL_MANY)==0 && bl->last == row ) -		return 1; -	bl->last = row; -	id_p->selected = TRUE; -	if (bl->valueP) -		*bl->valueP = row; -	if (bl->action) -		bl->action( row, id_p->label, 1, bl->data, id_p->itemData ); -	return 1; -} - - -static int unselectCList( -		GtkWidget * clist, -		int row, -		int col, -		GdkEventButton* event, -		gpointer data ) -{ -	wList_p bl = (wList_p)data; -	wListItem_p id_p; - -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -	wFlush(); -	if (bl->recursion) -		return 0; -	id_p = gtk_clist_get_row_data( GTK_CLIST(clist), row ); -	if ( id_p == NULL ) return 1; -	id_p->selected = FALSE; -	if (bl->action) -		bl->action( row, id_p->label, 2, bl->data, id_p->itemData ); -	return 1; -} - - -static int resizeColumnCList( -		GtkWidget * clist, -		int col, -		int width, -		gpointer data ) -{ -	wList_p bl = (wList_p)data; - -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -	wFlush(); -	if (bl->recursion) -		return 0; -	if ( col >= 0 && col < bl->colCnt ) -		bl->colWidths[col] = width; -	return 0; -} - - - -static int DropListSelectChild( -		GtkWidget * list, -		GtkWidget * listItem, -		gpointer data ) -{ -	wList_p bl = (wList_p)data; -	wListItem_p id_p=NULL; -	wIndex_t inx; -	GList * child; - -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -#ifdef LATER -	printf( "DropListSelectChild %p %p %p\n", list, listItem, data ); -	printf( "  b: recurs=%d widget=%p\n", bl->recursion, bl->list ); -#endif -	if (bl->recursion) -		return 0; -	wFlush(); -	id_p = gtk_object_get_data(GTK_OBJECT(listItem), ListItemDataKey ); -	if ( id_p == NULL ) { -		fprintf( stderr, "  id_p = NULL\n"); -		return 0; -	} -#ifdef LATER -	printf( "  id_p = %s %lx, %d %d\n", id_p->label, (long)id_p->itemData, id_p->active, id_p->selected ); -#endif -	if ( bl->type == B_DROPLIST && bl->editable ) { -		if ( bl->editted == FALSE ) -			return 0; -		gtkSetTrigger( NULL, NULL ); -	} -	bl->editted = FALSE; -	for ( inx=0,child=GTK_LIST(bl->list)->children,inx=0; child&&child->data!=listItem; child=child->next ) inx++; -	if ( bl->last == inx ) -		return 1; -	bl->last = inx; -	if (bl->valueP) -		*bl->valueP = inx; -	if (id_p && bl->action) -		bl->action( (wIndex_t)inx, id_p->label, 1, bl->data, id_p->itemData ); -	gtkSetTrigger( NULL, NULL ); -	return 1; -} - - -#ifdef LATER -static int DropListSelectionChanged( -		GtkWidget * list, -		gpointer data ) -{ -	wList_p bl = (wList_p)data; -	wListItem_p id_p=NULL; -	GList * child; -	GList * dlist; -	wIndex_t inx; -	GtkObject * listItem; -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -	if (bl->recursion) -		return 0; -	wFlush(); -	if ( bl->type == B_DROPLIST && bl->editable ) { -		if ( bl->editted == FALSE ) -			return 0; -		gtkSetTrigger( NULL, NULL ); -	} - -	dlist = GTK_LIST(bl->list)->selection; -	if (dlist == NULL) { -		return 0; -	} -	inx = 0; -	for ( child=GTK_LIST(bl->list)->children,inx=0; child&&child->data!=dlist->data; child=child->next ) inx++; -	while (dlist) { -		listItem = GTK_OBJECT(dlist->data); -		id_p = gtk_object_get_data(listItem, ListItemDataKey ); -		printf( "DropListSelectionChanged: id_p = %s %lx\n", id_p->label, (long)id_p->itemData ); -		dlist = dlist->next; -	} -	return 0; -#ifdef LATER -	bl->editted = FALSE; -	if ( bl->last == inx ) -		return 1; -	bl->last = inx; -	if (bl->valueP) -		*bl->valueP = inx; -	if (id_p && bl->action) -		bl->action( inx, id_p->label, 1, bl->data, id_p->itemData ); -	gtkSetTrigger( NULL, NULL ); -	return 1; -#endif -} - -#endif - - -static void triggerDListEntry( -		wControl_p b ) -{ -	wList_p bl = (wList_p)b; -	const char * entry_value; - -	if (bl == 0) -		return; -	if (bl->widget == 0) abort(); -	entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) ); -	if (entry_value == NULL) return; -	if (debugWindow >= 2) printf("triggerListEntry: %s text = %s\n", bl->labelStr?bl->labelStr:"No label", entry_value ); -	if (bl->action) { -		bl->recursion++; -		bl->action( -1, entry_value, 0, bl->data, NULL ); -		bl->recursion--; -	} -	gtkSetTrigger( NULL, NULL ); -	return; -} - - -static void updateDListEntry( -		GtkEntry * widget, -		wList_p bl ) -{ -	const char *entry_value; -	if (bl == 0) -		return; -	if (bl->recursion) -		return; -	if (!bl->editable) -		return; -	entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) ); -	bl->editted = TRUE; -	if (bl->valueP != NULL) -		*bl->valueP = -1; -	bl->last = -1; -	if (bl->action) -		gtkSetTrigger( (wControl_p)bl, triggerDListEntry ); -	return; -} - - - -#ifdef LATER -EXPORT wList_p wListCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		long	number,		/* Number of displayed entries */ -		wPos_t	width,		/* Width of list */ -		long	*valueP,	/* Selected index */ -		wListCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	wList_p b; - -	b = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->number = number; -	b->count = 0; -	b->last = -1; -	b->valueP = valueP; -	b->action = action; -	b->listX = b->realX; -	b->colCnt = 0; -	b->colWidths = NULL; -	b->colRightJust = NULL; -	gtkComputePos( (wControl_p)b ); - -	b->list = (GtkWidget*)gtk_clist_new(1); -	if (b->list == 0) abort(); -	b->widget = gtk_scrolled_window_new( NULL, NULL ); -	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (b->widget), -				GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); -	/*gtk_container_add( GTK_CONTAINER(b->widget), b->list );*/ -	gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(b->widget), b->list ); -	if (width == 0) -		width = 100; -	gtk_clist_set_column_width( GTK_CLIST(b->list), 0, width ); -#ifndef GTK1 -	gtk_widget_set_size_request( b->widget, width, (number+1)*ROW_HEIGHT ); -#else -	gtk_widget_set_usize( b->widget, width, (number+1)*ROW_HEIGHT ); -#endif -	gtk_signal_connect( GTK_OBJECT(b->list), "select_row", GTK_SIGNAL_FUNC(selectCList), b ); -	gtk_signal_connect( GTK_OBJECT(b->list), "unselect_row", GTK_SIGNAL_FUNC(unselectCList), b ); -	gtk_list_set_selection_mode( GTK_LIST(b->list), (option&BL_MANY)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE ); -/*	gtk_container_set_focus_vadjustment (GTK_CONTAINER (b->list), -				gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (b->widget))); */ -	gtk_widget_show( b->list ); - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	return b; -} -#endif - -/** Create a drop down list. The drop down is created and intialized with the supplied values. - * - *		\param IN parent Parent window - *		\param IN x, X-position - *		\param IN y	 Y-position - *		\param IN helpStr Help string - *		\param IN labelStr Label - *		\param IN option Options - *		\param IN number Number of displayed entries - *		\param IN width Width - *		\param IN valueP Selected index - *		\param IN action Callback - *		\param IN data Context - */ - -EXPORT wList_p wDropListCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		long	number,		/* Number of displayed entries */ -		wPos_t	width,		/* Width */ -		long	*valueP,	/* Selected index */ -		wListCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	wList_p b; -	b = (wList_p)gtkAlloc( parent, B_DROPLIST, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->number = number; -	b->count = 0; -	b->last = -1; -	b->valueP = valueP; -	b->action = action; -	b->listX = b->realX; -	b->colCnt = 0; -	b->colWidths = NULL; -	b->colRightJust = NULL; -	gtkComputePos( (wControl_p)b ); - -	b->widget = (GtkWidget*)gtk_combo_new(); -	if (b->widget == 0) abort(); -	b->list = GTK_COMBO(b->widget)->list; -#ifdef LATER -	gtk_signal_connect( GTK_OBJECT(b->list), "selection_changed", GTK_SIGNAL_FUNC(DropListSelectionChanged), b ); -#endif -	gtk_signal_connect( GTK_OBJECT(b->list), "select_child", GTK_SIGNAL_FUNC(DropListSelectChild), b ); -	if (width == 0) -		width = 100; -#ifndef GTK1 -	gtk_widget_set_size_request( b->widget, width, -1 ); -	gtk_widget_set_size_request( GTK_COMBO(b->widget)->entry, width, -1 ); -#else -	gtk_widget_set_usize( b->widget, width, -1 ); -	gtk_widget_set_usize( GTK_COMBO(b->widget)->entry, width, -1 ); -#endif - -	gtk_signal_connect( GTK_OBJECT(GTK_COMBO(b->widget)->entry), "changed", GTK_SIGNAL_FUNC(updateDListEntry), b ); -	if ( (option&BL_EDITABLE) == 0 ) -		gtk_widget_set_sensitive( GTK_WIDGET(GTK_COMBO(b->widget)->entry), FALSE ); -	else { -		b->editable = TRUE; -	} - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	return b; - -} - - -EXPORT wList_p wComboListCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		long	number,		/* Number of displayed list entries */ -		wPos_t	width,		/* Width */ -		long	*valueP,	/* Selected index */ -		wListCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	return wListCreate( parent, x, y, helpStr, labelStr, option, number, width, 0, NULL, NULL, NULL, valueP, action, data ); -#ifdef LATER -	wList_p b; - -	b = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *b, data ); -	b->option = option; -	b->number = number; -	b->count = 0; -	b->last = -1; -	b->valueP = valueP; -	b->action = action; -	b->listX = b->realX; -	gtkComputePos( (wControl_p)b ); - -	b->widget = (GtkWidget*)gtk_combo_new(); -	if (b->widget == 0) abort(); -	if (width == 0) -		width = 100; -	/*gtk_clist_set_column_width( GTK_CLIST(b->widget), 0, width );*/ -#ifndef GTK1 -	gtk_widget_set_size_request( b->widget, width, -1 ); -#else -	gtk_widget_set_usize( b->widget, width, -1 ); -#endif - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	return b; -#endif -} - - - -EXPORT wList_p wListCreate( -		wWin_p	parent,		/* Parent window */ -		wPos_t	x,		/* X-position */ -		wPos_t	y,		/* Y-position */ -		const char 	* helpStr,	/* Help string */ -		const char	* labelStr,	/* Label */ -		long	option,		/* Options */ -		long	number,		/* Number of displayed entries */ -		wPos_t	width,		/* Width of list */ -		int	colCnt,		/* Number of columns */ -		wPos_t	* colWidths,	/* Width of columns */ -		wBool_t * colRightJust,	/* justification of columns */ -		const char 	** colTitles,	/* Title of columns */ -		long	*valueP,	/* Selected index */ -		wListCallBack_p action,	/* Callback */ -		void 	*data )		/* Context */ -/* -*/ -{ -	wList_p bl; -	long col; -	static wPos_t zeroPos = 0; - -	bl = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *bl, data ); -	bl->option = option; -	bl->number = number; -	bl->count = 0; -	bl->last = -1; -	bl->valueP = valueP; -	bl->action = action; -	bl->listX = bl->realX; - -	if ( colCnt <= 0 ) { -		colCnt = 1; -		colWidths = &zeroPos; -	} -	bl->colCnt = colCnt; -	bl->colWidths = (wPos_t*)malloc( colCnt * sizeof *(wPos_t*)0 ); -	memcpy( bl->colWidths, colWidths, colCnt * sizeof *(wPos_t*)0 ); - -	gtkComputePos( (wControl_p)bl ); - -	bl->list = (GtkWidget*)gtk_clist_new( bl->colCnt ); -	if (bl->list == 0) abort(); -	if (colTitles) -	{ -		for (col = 0; col < colCnt; col++) -			gtk_clist_set_column_title(GTK_CLIST(bl->list), col, _(((char*)colTitles[col]))); -		gtk_clist_column_titles_show(GTK_CLIST(bl->list)); -	} - -	bl->widget = gtk_scrolled_window_new( NULL, NULL ); -	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bl->widget), -				GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); -	/* gtk_container_add( GTK_CONTAINER(bl->widget), bl->list ); */ -	gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(bl->widget), bl->list ); -	if (width == 0) -		width = 100; -	for ( col=0; col<colCnt; col++ ) { -		gtk_clist_set_column_auto_resize( GTK_CLIST(bl->list), col, TRUE ); -		gtk_clist_set_column_resizeable( GTK_CLIST(bl->list), col, TRUE ); -		gtk_clist_set_column_justification( GTK_CLIST(bl->list), col, -				(colRightJust==NULL||colRightJust[col]==FALSE)?GTK_JUSTIFY_LEFT:GTK_JUSTIFY_RIGHT ); -		gtk_clist_set_column_width( GTK_CLIST(bl->list), col, bl->colWidths[col] ); -	} -#ifndef GTK1 -	gtk_widget_set_size_request( bl->widget, width, (number+1)*ROW_HEIGHT ); -#else -	gtk_widget_set_usize( bl->widget, width, (number+1)*ROW_HEIGHT ); -#endif -	gtk_signal_connect( GTK_OBJECT(bl->list), "select_row", GTK_SIGNAL_FUNC(selectCList), bl ); -	gtk_signal_connect( GTK_OBJECT(bl->list), "unselect_row", GTK_SIGNAL_FUNC(unselectCList), bl ); -	gtk_signal_connect( GTK_OBJECT(bl->list), "resize_column", GTK_SIGNAL_FUNC(resizeColumnCList), bl ); -	gtk_clist_set_selection_mode( GTK_CLIST(bl->list), (option&BL_MANY)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE ); -	gtk_container_set_focus_vadjustment (GTK_CONTAINER (bl->list), -				gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bl->widget))); - -	gtk_widget_show( bl->list ); - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), bl->widget, bl->realX, bl->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), bl->widget ); -	gtk_widget_set_uposition( bl->widget, bl->realX, bl->realY ); -#endif -	gtkControlGetSize( (wControl_p)bl ); -	if (labelStr) -		bl->labelW = gtkAddLabel( (wControl_p)bl, labelStr ); -	gtk_widget_show( bl->widget ); -	gtkAddButton( (wControl_p)bl ); -	gtkAddHelpString( bl->widget, helpStr ); -	return bl; -} diff --git a/app/wlib/gtklib/gtkmenu.c b/app/wlib/gtklib/gtkmenu.c deleted file mode 100644 index d3258c4..0000000 --- a/app/wlib/gtklib/gtkmenu.c +++ /dev/null @@ -1,873 +0,0 @@ -/** \file gtkmenu.c - * Menu creation and handling stuff. - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkmenu.c,v 1.5 2009-10-03 04:49:01 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> -#include <ctype.h> - -#include "gtkint.h" - -int testMenuPopup = 1; - -static char MenuItemDataKey[] = "MenuItemDataKey"; - -extern char gtkAccelChar; - -/* - ***************************************************************************** - * - * Menus - * - ***************************************************************************** - */ - -typedef enum { M_MENU, M_SEPARATOR, M_PUSH, M_LIST, M_LISTITEM, M_TOGGLE, M_RADIO } mtype_e; -typedef enum { MM_BUTT, MM_MENU, MM_BAR, MM_POPUP } mmtype_e; - - -#define MOBJ_COMMON \ -	WOBJ_COMMON \ -	mtype_e mtype; \ -	GtkWidget * menu_item; \ -	wMenu_p parentMenu; \ -	int recursion; -	 -struct wMenuItem_t { -	MOBJ_COMMON -	}; -typedef struct wMenuItem_t * wMenuItem_p; - -struct wMenu_t { -	MOBJ_COMMON -	mmtype_e mmtype; -	wMenuItem_p first, last; -	GSList *radioGroup;			/* in case menu holds a radio button group */ -	GtkWidget * menu; -	wMenuTraceCallBack_p traceFunc; -	void * traceData; -	GtkLabel * labelG; -	GtkWidget * imageG; -	}; - -struct wMenuPush_t { -	MOBJ_COMMON -	wMenuCallBack_p action; -	wBool_t enabled; -	}; - -struct wMenuRadio_t { -	MOBJ_COMMON -	wMenuCallBack_p action; -	wBool_t enabled; -	}; - - -typedef struct wMenuListItem_t * wMenuListItem_p; - -struct wMenuList_t { -	MOBJ_COMMON -	int max; -	int count; -	wMenuListCallBack_p action; -	}; - -struct wMenuListItem_t { -	MOBJ_COMMON -	wMenuList_p mlist; -	}; - -struct wMenuToggle_t { -	MOBJ_COMMON -	wMenuToggleCallBack_p action; -	wBool_t enabled; -	wBool_t set; -	}; - - -/*-----------------------------------------------------------------*/ - -static void pushMenuItem( -	GtkWidget * widget, -	gpointer value ) -{ -	wMenuItem_p m = (wMenuItem_p)value; -	wMenuToggle_p mt; -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -/*	wFlush(); */ -	if (m->recursion) -		return; -	switch (m->mtype) { -	case M_PUSH: -		if ( ((wMenuPush_p)m)->enabled == FALSE ) -			wBeep(); -		else -			((wMenuPush_p)m)->action( ((wMenuPush_p)m)->data ); -		break; -	case M_TOGGLE: -		mt = (wMenuToggle_p)m; -		if ( mt->enabled == FALSE ) { -			wBeep(); -		} else { -			wMenuToggleSet( mt, !mt->set ); -			mt->action( mt->set, mt->data ); -		} -		break; -	case M_RADIO: -		/* NOTE: action is only called when radio button is activated, not when deactivated */ -		if ( ((wMenuRadio_p)m)->enabled == FALSE ) -			wBeep(); -		else -			if( ((GtkCheckMenuItem *)widget)->active == TRUE ) -				((wMenuRadio_p)m)->action( ((wMenuRadio_p)m)->data ); -		break;	 -	case M_MENU: -		return; -	default: -		/*fprintf(stderr," Oops menu\n");*/ -		return; -	} -	if ( (m->parentMenu)->traceFunc ) { -		(m->parentMenu)->traceFunc( m->parentMenu, m->labelStr,  ((wMenu_p)m->parentMenu)->traceData ); -	} -}  - -static wMenuItem_p createMenuItem( -	wMenu_p m, -	mtype_e mtype, -	const char * helpStr, -	const char * labelStr, -	int size ) -{ -	wMenuItem_p mi; -	mi = (wMenuItem_p)gtkAlloc( NULL, B_MENUITEM, 0, 0, labelStr, size, NULL ); -	mi->mtype = mtype; -	switch ( mtype ) { -	case M_LIST: -		m->menu_item = NULL; -		break; -	case M_SEPARATOR: -		mi->menu_item = gtk_separator_menu_item_new(); -		break; -	case M_TOGGLE: -		mi->menu_item = gtk_check_menu_item_new_with_mnemonic(gtkConvertInput(mi->labelStr)); -		break; -	case M_RADIO: -		mi->menu_item = gtk_radio_menu_item_new_with_mnemonic(m->radioGroup, gtkConvertInput(mi->labelStr)); -		m->radioGroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (mi->menu_item)); -		break;			 -	default: -		mi->menu_item = gtk_menu_item_new_with_mnemonic(gtkConvertInput(mi->labelStr)); -		break; -	} -	if (mi->menu_item) { -		if (m) -			gtk_menu_append( GTK_MENU(m->menu), mi->menu_item ); - -		gtk_signal_connect( GTK_OBJECT(mi->menu_item), "activate", -				GTK_SIGNAL_FUNC(pushMenuItem), mi ); - 		gtk_widget_show(mi->menu_item); -	} -	if (m) { -		if (m->first == NULL) { -			m->first = mi; -		} else { -			m->last->next = (wControl_p)mi; -		} -		m->last = mi; -	} -	mi->next = NULL; -	if (helpStr != NULL) { -		gtkAddHelpString( mi->menu_item, helpStr ); -	} -	mi->parentMenu = m; -	return mi; -} - - -static void setAcclKey( wWin_p w, GtkWidget * menu, GtkWidget * menu_item, int acclKey ) -{ -	char acclStr[40]; -	int len; -	int mask; -	static GtkAccelGroup * accel_alpha_group = NULL; -	static GtkAccelGroup * accel_nonalpha_group = NULL; -	guint oldmods; - - -	if (accel_alpha_group == NULL) { -		accel_alpha_group = gtk_accel_group_new(); -		/*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/ -		gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_alpha_group ); -	} -	if (accel_nonalpha_group == NULL) { -		oldmods = gtk_accelerator_get_default_mod_mask(); -		gtk_accelerator_set_default_mod_mask( GDK_CONTROL_MASK | GDK_MOD1_MASK ); -		accel_nonalpha_group = gtk_accel_group_new(); -		/*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/ -		gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_nonalpha_group ); -		gtk_accelerator_set_default_mod_mask( oldmods ); -	} -  -	mask = 0; -	if (acclKey) { -#ifdef LATER - 		switch ( (acclKey&0xFF) ) { -		case '+': acclKey = (acclKey&0xFF00) | WSHIFT | '='; break; -		case '?': acclKey = (acclKey&0xFF00) | WSHIFT | '/'; break; -		} -#endif -		len = 0; -		if (acclKey&WALT) { -			mask |= GDK_MOD1_MASK; -			strcpy( acclStr+len, "Meta+" ); -			len += 5; -		} -		if (acclKey&WSHIFT) { -			mask |= GDK_SHIFT_MASK; -			strcpy( acclStr+len, "Shift+" ); -			len += 6; -			switch ( (acclKey&0xFF) ) { -			case '0': acclKey += ')'-'0'; break; -			case '1': acclKey += '!'-'1'; break; -			case '2': acclKey += '@'-'2'; break; -			case '3': acclKey += '#'-'3'; break; -			case '4': acclKey += '$'-'4'; break; -			case '5': acclKey += '%'-'5'; break; -			case '6': acclKey += '^'-'6'; break; -			case '7': acclKey += '&'-'7'; break; -			case '8': acclKey += '*'-'8'; break; -			case '9': acclKey += '('-'9'; break; -			case '`': acclKey += '~'-'`'; break; -			case '-': acclKey += '_'-'-'; break; -			case '=': acclKey += '+'-'='; break; -			case '\\': acclKey += '|'-'\\'; break; -			case '[': acclKey += '{'-'['; break; -			case ']': acclKey += '}'-']'; break; -			case ';': acclKey += ':'-';'; break; -			case '\'': acclKey += '"'-'\''; break; -			case ',': acclKey += '<'-','; break; -			case '.': acclKey += '>'-'.'; break; -			case '/': acclKey += '?'-'/'; break; -			default: break; -			} -		} -		if (acclKey&WCTL) { -			mask |= GDK_CONTROL_MASK; -			strcpy( acclStr+len, "Ctrl+" ); -			len += 5; -		} -		acclStr[len++] = (acclKey & 0xFF); -		acclStr[len++] = '\0'; -		gtk_widget_add_accelerator( menu_item, "activate", -			(isalpha(acclKey&0xFF)?accel_alpha_group:accel_nonalpha_group), -			toupper(acclKey&0xFF), mask, GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED ); -	} -} - -/*-----------------------------------------------------------------*/ - -wMenuRadio_p wMenuRadioCreate( -	wMenu_p m,  -	const char * helpStr, -	const char * labelStr, -	long acclKey, -	wMenuCallBack_p action, -	void 	*data ) -{ -	wMenuRadio_p mi; - -	mi = (wMenuRadio_p)createMenuItem( m, M_RADIO, helpStr, labelStr, sizeof *mi ); -	if (m->mmtype == MM_POPUP && !testMenuPopup) -		return mi; -	setAcclKey( m->parent, m->menu, mi->menu_item, acclKey ); -	mi->action = action; -	mi->data = data; -	mi->enabled = TRUE; -	return mi; -} - -void wMenuRadioSetActive(  -	wMenuRadio_p mi ) -{ -	gtk_check_menu_item_set_active( (GtkCheckMenuItem *)mi->menu_item, TRUE );  -}	 		 - -/*-----------------------------------------------------------------*/ - -wMenuPush_p wMenuPushCreate( -	wMenu_p m,  -	const char * helpStr, -	const char * labelStr, -	long acclKey, -	wMenuCallBack_p action, -	void 	*data ) -{ -	wMenuPush_p mi; - -	mi = (wMenuPush_p)createMenuItem( m, M_PUSH, helpStr, labelStr, sizeof *mi ); -	if (m->mmtype == MM_POPUP && !testMenuPopup) -		return mi; -	setAcclKey( m->parent, m->menu, mi->menu_item, acclKey ); -	mi->action = action; -	mi->data = data; -	mi->enabled = TRUE; -	return mi; -} - - -void wMenuPushEnable( -	wMenuPush_p mi, -	wBool_t enable ) -{ -	mi->enabled = enable; -	gtk_widget_set_sensitive( GTK_WIDGET(mi->menu_item), enable ); -} - - -/*-----------------------------------------------------------------*/ - -wMenu_p wMenuMenuCreate( -	wMenu_p m,  -	const char * helpStr, -	const char * labelStr ) -{ -	wMenu_p mi; -	mi = (wMenu_p)createMenuItem( m, M_MENU, helpStr, labelStr, sizeof *mi ); -	mi->mmtype = MM_MENU; -	mi->menu = gtk_menu_new(); -	/*gtk_widget_set_sensitive( GTK_WIDGET(mi->menu_item), FALSE );*/ -	gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi->menu_item), mi->menu ); -	return mi; -} - - -/*-----------------------------------------------------------------*/ - -void wMenuSeparatorCreate( -	wMenu_p m )  -{ -	wMenuItem_p mi; -	mi = createMenuItem( m, M_SEPARATOR, NULL, "", sizeof *mi ); -} - - -/*-----------------------------------------------------------------*/ - -int getMlistOrigin( wMenu_p m, wMenuList_p ml ) -{ -	wMenuItem_p mi; -	int count; -	count = 0;	/* Menu counts as one */ -	for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) { -		switch( mi->mtype ) { -		case M_SEPARATOR: -		case M_PUSH: -		case M_MENU: -			count++; -			break; -		case M_LIST: -			if (mi == (wMenuItem_p)ml) -			return count; -			count += ((wMenuList_p)mi)->count; -			break; -		default: -			/*fprintf(stderr, "Oops: getMlistOrigin\n");*/ -			break; -		} -	} -	return count; -} - -wMenuList_p wMenuListCreate( -	wMenu_p m,  -	const char * helpStr, -	int max, -	wMenuListCallBack_p action ) -{ -	wMenuList_p mi; -	mi = (wMenuList_p)createMenuItem( m, M_LIST, NULL, NULL, sizeof *mi ); -	mi->next = NULL; -	mi->count = 0; -	mi->max = max; -	mi->parentMenu = m; -	mi->action = action; -	return (wMenuList_p)mi; -} - - -static void pushMenuList( -	GtkWidget * widget, -	gpointer value ) -{ -	wMenuListItem_p ml = (wMenuListItem_p)value; -	int i; -	int origin; -	GtkWidget * item; -	char * itemLabel; -	GList * children; -	GList * child; -	GtkWidget *label; - -	if (gdk_pointer_is_grabbed()) { -		gdk_pointer_ungrab(0); -	} -	wFlush(); - -	if (ml->recursion) -		return; -	if (ml->mlist->count <= 0) { -		fprintf( stderr, "pushMenuItem: empty list\n" ); -		return; -	} -	if (ml->mlist->action) { -		origin = getMlistOrigin(ml->mlist->parentMenu, ml->mlist); -		children = gtk_container_children( GTK_CONTAINER(ml->mlist->parentMenu->menu) ); -		if (children == NULL) abort(); -		child = g_list_nth( children, origin ); -		for (i=origin; i<origin+ml->mlist->count; i++, child=g_list_next(child) ) { -			if (child == NULL) abort(); -			item = (GtkWidget*)child->data; -			if (item == NULL) abort(); -			if (item == widget) { -				children = gtk_container_children(GTK_CONTAINER(item)); -				label = (GtkWidget*)children->data; -				gtk_label_get( GTK_LABEL(label), &itemLabel ); -				ml->mlist->action( i-origin, itemLabel, ml->data ); -				return; -			} -		} -	} -	fprintf( stderr, "pushMenuItem: item (%lx) not found\n", (long)widget ); -} - - -void wMenuListAdd( -	wMenuList_p ml, -	int index, -	const char * labelStr, -	const void * data ) -{ -	int i; -	int origin; -	GtkWidget * item; -	char * itemLabel; -	GList * children; -	GList * child; -	GList * itemList; -	GtkWidget * label; -	wMenuListItem_p mi; -	char * labelStrConverted; - -	origin = getMlistOrigin(ml->parentMenu, ml); -	if (ml->count > 0) { -		children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) ); -		if (children == NULL) abort(); -		child = g_list_nth( children, origin ); -		labelStrConverted = gtkConvertInput(labelStr); -		for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) { -			if (child == NULL) abort(); -			item = (GtkWidget*)child->data; -			if (item == NULL) abort(); -			itemList = gtk_container_children(GTK_CONTAINER(item)); -			label = (GtkWidget*)itemList->data; -			gtk_label_get( GTK_LABEL(label), &itemLabel ); -			if (strcmp( labelStrConverted, itemLabel ) == 0) { -				if (i != ml->count+index) { -					gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item ); -					ml->count--; -					break; -				} -				return; -			} -		} -		if (ml->max >= 0 && ml->count >= ml->max) { -			child = g_list_nth( children, origin+ml->count-1 ); -			if (child == NULL) abort(); -			item = (GtkWidget*)child->data; -			if (item == NULL) abort(); -			gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item ); -			ml->count--; -		} -	} -	mi = (wMenuListItem_p)gtkAlloc( NULL, B_MENUITEM, 0, 0, labelStr, sizeof *mi, NULL ); -	mi->mtype = M_LISTITEM; -	mi->menu_item = gtk_menu_item_new_with_label(gtkConvertInput(mi->labelStr)); -	mi->data = (void *)data; -	mi->mlist = ml; -	if (index < 0 || index > ml->count) -	index = ml->count; -	gtk_menu_insert( GTK_MENU(ml->parentMenu->menu), mi->menu_item, origin+index ); -	gtk_signal_connect( GTK_OBJECT(mi->menu_item), "activate", -				GTK_SIGNAL_FUNC(pushMenuList), mi ); -	gtk_object_set_data( GTK_OBJECT(mi->menu_item), MenuItemDataKey, mi ); -	gtk_widget_show(mi->menu_item); - -	ml->count++; -} - - -void wMenuListDelete( -	wMenuList_p ml, -	const char * labelStr ) -{ -	int i; -	int origin; -	GtkWidget * item; -	char * itemLabel; -	GList * children; -	GList * child; -	GtkWidget * label; -	char * labelStrConverted; - -	if (ml->count < 0) abort(); -	origin = getMlistOrigin(ml->parentMenu, ml); -	children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) ); -	if (children == NULL) abort(); -	child = g_list_nth( children, origin ); -	labelStrConverted = gtkConvertInput( labelStr ); -	for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) { -		if (child == NULL) abort(); -		item = (GtkWidget*)child->data; -		if (item == NULL) abort(); -		children = gtk_container_children(GTK_CONTAINER(item)); -		label = (GtkWidget*)children->data; -		gtk_label_get( GTK_LABEL(label), &itemLabel ); -		if (strcmp( labelStrConverted, itemLabel ) == 0) { -			gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item ); -			gtk_widget_queue_resize( GTK_WIDGET(ml->parentMenu->menu) ); -			ml->count--; -			return; -		} -	} -} - - -const char * wMenuListGet( wMenuList_p ml, int index, void ** data ) -{ -	int origin; -	GtkWidget * item; -	GList * children; -	GList * child; -	GtkWidget * label; -	char * itemLabel; -	wMenuListItem_p mi; - -	if (ml->count <= 0) -	return NULL; - -	if (index >= ml->count) { -		if (data) -			*data = NULL; -		return NULL; -	} -	origin = getMlistOrigin(ml->parentMenu, ml); -	children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) ); -	if (children == NULL) abort(); -	child = g_list_nth( children, origin+index ); -	if (child == NULL) abort(); -	item = (GtkWidget*)child->data; -	if (item == NULL) abort(); -	children = gtk_container_children(GTK_CONTAINER(item)); -	label = (GtkWidget*)children->data; -	gtk_label_get( GTK_LABEL(label), &itemLabel ); -	if (data) { -		mi = (wMenuListItem_p)gtk_object_get_data( GTK_OBJECT(item), MenuItemDataKey ); -		if (mi) -			*data = mi->data; -	} -	return itemLabel; -} - - -void wMenuListClear( -	wMenuList_p ml ) -{ -	int i; -	int origin; -	GtkWidget * item; -	GList * children; -	GList * child; - -	if (ml->count == 0) -		return; -	origin = getMlistOrigin(ml->parentMenu, ml); -	children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) ); -	if (children == NULL) abort(); -	child = g_list_nth( children, origin ); -	for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) { -		if (child == NULL) abort(); -		item = (GtkWidget*)child->data; -		if (item == NULL) abort(); -		gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item ); -	} -	ml->count = 0; -	gtk_widget_queue_resize( GTK_WIDGET(ml->parentMenu->menu) ); -} -/*-----------------------------------------------------------------*/ - -wMenuToggle_p wMenuToggleCreate( -	wMenu_p m,  -	const char * helpStr, -	const char * labelStr, -	long acclKey, -	wBool_t set, -	wMenuToggleCallBack_p action, -	void * data ) -{ -	wMenuToggle_p mt; - -	mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof *mt ); -	setAcclKey( m->parent, m->menu, mt->menu_item, acclKey ); -	mt->action = action; -	mt->data = data; -	mt->enabled = TRUE; -	mt->parentMenu = m; -	wMenuToggleSet( mt, set ); -	 -	return mt; -} - - -wBool_t wMenuToggleGet( -	wMenuToggle_p mt ) -{ -	return mt->set; -} - - -wBool_t wMenuToggleSet( -	wMenuToggle_p mt, -	wBool_t set ) -{ -	wBool_t rc; -	if (mt==NULL) return 0; -	mt->recursion++; -	gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM(mt->menu_item), set ); -	mt->recursion--; -	rc = mt->set; -	mt->set = set; -	return rc; -} - - -void wMenuToggleEnable( -	wMenuToggle_p mt, -	wBool_t enable ) -{ -	mt->enabled = enable; -} - - -/*-----------------------------------------------------------------*/ - -void wMenuSetLabel( wMenu_p m, const char * labelStr) { -	gtkSetLabel( m->widget, m->option, labelStr, &m->labelG, &m->imageG ); -} - - -static gint pushMenu( -	GtkWidget * widget, -	wMenu_p m ) -{ -	gtk_menu_popup( GTK_MENU(m->menu), NULL, NULL, NULL, NULL, 0, 0 ); -	/* Tell calling code that we have handled this event; the buck -	 * stops here. */ -	return TRUE; -} - - -wMenu_p wMenuCreate( -	wWin_p	parent, -	wPos_t	x, -	wPos_t	y, -	const char 	* helpStr, -	const char	* labelStr, -	long	option ) -{ -	wMenu_p m; -	m = gtkAlloc( parent, B_MENU, x, y, labelStr, sizeof *m, NULL ); -	m->mmtype = MM_BUTT; -	m->option = option; -	m->traceFunc = NULL; -	m->traceData = NULL; -	gtkComputePos( (wControl_p)m ); - -	m->widget = gtk_button_new(); -	gtk_signal_connect (GTK_OBJECT(m->widget), "clicked", -			GTK_SIGNAL_FUNC(pushMenu), m ); - -	m->menu = gtk_menu_new(); - -	wMenuSetLabel( m, labelStr ); -#ifdef MENUOPTION -	gtk_option_menu_set_menu( GTK_OPTION_MENU(m->widget), m->menu ); -	((GtkOptionMenu*)m->widget)->width = 25; -	((GtkOptionMenu*)m->widget)->height = 16; -#endif -	 -	gtk_fixed_put( GTK_FIXED(parent->widget), m->widget, m->realX, m->realY ); -	gtkControlGetSize( (wControl_p)m ); -	if ( m->w < 80 && (m->option&BO_ICON)==0) { -		m->w = 80; -		gtk_widget_set_usize( m->widget, m->w, m->h ); -	} -	gtk_widget_show( m->widget ); -	gtkAddButton( (wControl_p)m ); -	gtkAddHelpString( m->widget, helpStr ); -	return m; -} - -/** - * Add a drop-down menu to the menu bar.  - * - * \param[IN] w main window handle  - * \param[IN] helpStr unused (should be help topic ) - * \param[IN] labelStr label for the drop-down menu  - * \return    pointer to the created drop-down menu - */ - - -wMenu_p wMenuBarAdd( -	wWin_p w, -	const char * helpStr, -	const char * labelStr ) -{ -	wMenu_p m; -	GtkWidget * menuItem; -	static GtkAccelGroup * accel_group = NULL; -	 -	m = gtkAlloc( w, B_MENU, 0, 0, labelStr, sizeof *m, NULL ); -	m->mmtype = MM_BAR; -	m->realX = 0; -	m->realY = 0; -	 -	menuItem = gtk_menu_item_new_with_label( gtkConvertInput(m->labelStr) ); -	m->menu = gtk_menu_new(); -	gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), m->menu ); -	gtk_menu_bar_append( GTK_MENU_BAR(w->menubar), menuItem ); -	gtk_widget_show( menuItem ); - -	m->w = 0; -	m->h = 0; -	 -	/* TODO: why is help not supported here? */ -	/*gtkAddHelpString( m->panel_item, helpStr );*/ -	 -	if ( gtkAccelChar ) { -		if ( accel_group == NULL ) { -			accel_group = gtk_accel_group_new(); -			gtk_window_add_accel_group( GTK_WINDOW(w->gtkwin), accel_group ); -		} -		gtk_widget_add_accelerator( menuItem, "activate", accel_group, tolower(gtkAccelChar), GDK_MOD1_MASK, GTK_ACCEL_LOCKED ); -	} -	return m; -} - - -/*-----------------------------------------------------------------*/ - - -wMenu_p wMenuPopupCreate( -	wWin_p w, -	const char * labelStr ) -{ -	wMenu_p b; -	b = gtkAlloc( w, B_MENU, 0, 0, labelStr, sizeof *b, NULL ); -	b->mmtype = MM_POPUP; -	b->option = 0; - -	b->menu = gtk_menu_new(); -	b->w = 0; -	b->h = 0; -	gtk_signal_connect( GTK_OBJECT (b->menu), "key_press_event", -			GTK_SIGNAL_FUNC (catch_shift_ctrl_alt_keys), b); -	gtk_signal_connect( GTK_OBJECT (b->menu), "key_release_event", -			GTK_SIGNAL_FUNC (catch_shift_ctrl_alt_keys), b); -	gtk_widget_set_events ( GTK_WIDGET(b->menu), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK ); -	return b; -} - - -void wMenuPopupShow( wMenu_p mp ) -{ -	gtk_menu_popup( GTK_MENU(mp->menu), NULL, NULL, NULL, NULL, 0, 0 ); -} - - -/*-----------------------------------------------------------------*/ - -void wMenuSetTraceCallBack( -	wMenu_p m, -	wMenuTraceCallBack_p func, -	void * data ) -{ -	m->traceFunc = func; -	m->traceData = data; -} - -wBool_t wMenuAction( -	wMenu_p m, -	const char * label ) -{ -	wMenuItem_p mi; -	wMenuToggle_p mt; -	for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) { -		if ( strcmp( mi->labelStr, label ) == 0 ) { -			switch( mi->mtype ) { -			case M_SEPARATOR: -				break; -			case M_PUSH: -				if ( ((wMenuPush_p)mi)->enabled == FALSE ) -					wBeep(); -				else -					((wMenuPush_p)mi)->action( ((wMenuPush_p)mi)->data ); -				break; -			case M_TOGGLE: -				mt = (wMenuToggle_p)mi; -				if ( mt->enabled == FALSE ) { -					wBeep(); -				} else { -					wMenuToggleSet( mt, !mt->set ); -					mt->action( mt->set, mt->data ); -				} -				break; -			case M_MENU: -				break; -			case M_LIST: -				break; -			default: -				/*fprintf(stderr, "Oops: wMenuAction\n");*/ -			break; -			} -			return TRUE; -		} -	} -	return FALSE; -} diff --git a/app/wlib/gtklib/gtkmisc.c b/app/wlib/gtklib/gtkmisc.c deleted file mode 100644 index acc123a..0000000 --- a/app/wlib/gtklib/gtkmisc.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkmisc.c,v 1.15 2009-10-03 04:49:01 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <sys/time.h> -#include <signal.h> -#include <unistd.h> -#include <string.h> -#include <locale.h> - -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> - -#include "gtkint.h" -#include "i18n.h" - -wWin_p gtkMainW; - -long debugWindow = 0; - -char wAppName[256]; -char wConfigName[ 256 ]; - -#define FOUR		(4) -#ifndef GTK1 -#define MENUH		(24) -#else -#define MENUH		(24) -#endif -#define LABEL_OFFSET	(3) -		 -const char * wNames[] = { -		"MAIN", -		"POPUP", -		"BUTT", -		"CANCEL", -		"POPUP", -		"TEXT", -		"INTEGER", -		"FLOAT", -		"LIST", -		"DROPLIST", -		"COMBOLIST", -		"RADIO", -		"TOGGLE", -		"DRAW", -		"MENU" -		"MULTITEXT", -		"MESSAGE", -		"LINES", -		"MENUITEM", -		"BOX" -		}; - -static struct timeval startTime; - -static wBool_t reverseIcon = -#if defined(linux) -				FALSE; -#else -				TRUE; -#endif - -char gtkAccelChar; - - -/* - ***************************************************************************** - * - * Internal Utility functions - * - ***************************************************************************** - */ - -unsigned char gtkBitrotate( -		char v ) -{ -	unsigned char r = 0; -	int i; -	static unsigned char bits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; -	for (i=0;i<8;i++) -		if (v & bits[i]) -			r |= bits[7-i]; -	return r; -} - -GdkPixmap* gtkMakeIcon( -		GtkWidget * widget, -		wIcon_p ip, -		GdkBitmap ** mask ) -{ -	GdkPixmap * pixmap; -	char ** pixmapData; -	char * oldline1; -	static char newline1[] = " \tc None s None"; -	char line0[40]; -	char line2[40]; -	int row,col,wb; -	long rgb; -	const char * bits; -	GdkColor *transparent; -	 -	transparent = >k_widget_get_style( gtkMainW->gtkwin )->bg[GTK_WIDGET_STATE( gtkMainW->gtkwin )]; -	 -	if ( ip->gtkIconType == gtkIcon_pixmap ) { -		pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, (char**)ip->bits ); -	} -	else { -		wb = (ip->w+7)/8; -		pixmapData = (char**)malloc( (3+ip->h) * sizeof *pixmapData ); -		pixmapData[0] = line0; -		rgb = wDrawGetRGB(ip->color); -		sprintf( line0, " %d %d 2 1", ip->w, ip->h ); -		sprintf( line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF ); -		pixmapData[1] = ". c None s None"; -		pixmapData[2] = line2; -		bits = ip->bits; -		for (row = 0; row<ip->h; row++ ) { -			pixmapData[row+3] = (char*)malloc( (ip->w+1) * sizeof **pixmapData ); -			for (col = 0; col<ip->w; col++ ) { -				if ( bits[ row*wb+(col>>3) ] & (1<<(col&07)) ) { -					pixmapData[row+3][col] = '#'; -				} else { -					pixmapData[row+3][col] = '.'; -				} -			} -			pixmapData[row+3][ip->w] = 0; -		} -		pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, pixmapData ); -		for (row = 0; row<ip->h; row++ ) { -			free( pixmapData[row+3] ); -		} -	} -	return pixmap; -} - - -int gtkAddLabel( wControl_p b, const char * labelStr ) -{ -	GtkRequisition requisition; -	if (labelStr == NULL) -		return 0; -	b->label = gtk_label_new(gtkConvertInput(labelStr)); -	gtk_widget_size_request( b->label, &requisition ); -	gtk_container_add( GTK_CONTAINER(b->parent->widget), b->label ); -#ifndef GTK1 -	gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET ); -#else -	gtk_widget_set_uposition( b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET ); -#endif -	gtk_widget_show( b->label ); -	return requisition.width+8; -} - - -void * gtkAlloc( -		wWin_p parent, -		wType_e type, -		wPos_t origX, -		wPos_t origY, -		const char * labelStr, -		int size, -		void * data ) -{ -	wControl_p w = (wControl_p)malloc( size ); -	char * cp; -	memset( w, 0, size ); -	if (w == NULL) -		abort(); -	w->type = type; -	w->parent = parent; -	w->origX = origX; -	w->origY = origY; -	gtkAccelChar = 0; -	if (labelStr) { -		cp = (char*)malloc(strlen(labelStr)+1); -		w->labelStr = cp; -		for ( ; *labelStr; labelStr++ ) -			if ( *labelStr != '&' ) -				*cp++ = *labelStr; -			else { -/*				*cp++ = '_'; -				gtkAccelChar = labelStr[1]; */ -			}	 -		*cp = 0; -	} -	w->doneProc = NULL; -	w->data = data; -	return w; -} - - -void gtkComputePos( -		wControl_p b ) -{ -	wWin_p w = b->parent; - -	if (b->origX >= 0)  -		b->realX = b->origX; -	else -		b->realX = w->lastX + (-b->origX) - 1; -	if (b->origY >= 0)  -		b->realY = b->origY + FOUR + ((w->option&F_MENUBAR)?MENUH:0); -	else -		b->realY = w->lastY + (-b->origY) - 1; -} - - -void gtkControlGetSize( -		wControl_p b ) -{ -	GtkRequisition requisition; -	gtk_widget_size_request( b->widget, &requisition ); -	b->w = requisition.width; -	b->h = requisition.height; -} -	 - -void gtkAddButton( -		wControl_p b ) -{ -	wWin_p win = b->parent; -	wBool_t resize = FALSE; -	if (win->first == NULL) { -		win->first = b; -	} else { -		win->last->next = b; -	} -	win->last = b; -	b->next = NULL; -	b->parent = win; -	win->lastX = b->realX + b->w; -	win->lastY = b->realY + b->h; -	if (win->option&F_AUTOSIZE) { -		if (win->lastX > win->realX) { -			win->realX = win->lastX; -			if (win->w != (win->realX + win->origX)) { -				resize = TRUE; -				win->w = (win->realX + win->origX); -			} -		} -		if (win->lastY > win->realY) { -			win->realY = win->lastY; -			if (win->h != (win->realY + win->origY)) { -			resize = TRUE; -				win->h = (win->realY + win->origY); -			} -		} -		if (win->shown) { -			if ( resize ) { -#ifndef GTK1 -				gtk_widget_set_size_request( win->gtkwin, win->w, win->h ); -				gtk_widget_set_size_request( win->widget, win->w, win->h ); -#else -				gtk_widget_set_usize( win->gtkwin, win->w, win->h ); -				gtk_widget_set_usize( win->widget, win->w, win->h ); -#endif -			} -		} -	} -} - - -void gtkSetReadonly( wControl_p b, wBool_t ro ) -{ -	if (ro) -		b->option |= BO_READONLY; -	else -		b->option &= ~BO_READONLY; -} - - -wControl_p gtkGetControlFromPos( -		wWin_p win, -		wPos_t x, -		wPos_t y ) -{ -	wControl_p b; -	wPos_t xx, yy; -	for (b=win->first; b != NULL; b = b->next) { -		if ( b->widget && GTK_WIDGET_VISIBLE(b->widget) ) { -			xx = b->realX; -			yy = b->realY; -			if ( xx <= x && x < xx+b->w && -				 yy <= y && y < yy+b->h ) { -				return b; -			} -		} -	} -	return NULL; -} - -/* \brief Convert label string from Windows mnemonic to GTK - * - * The first occurence of '&' in the passed string is changed to '_' - * - * \param label the string to convert - * \return pointer to modified string, has to be free'd after usage - * - */ -static  -char * gtkChgMnemonic( char *label ) -{ -	char *ptr; -	char *cp; -	 -	cp = strdup( label ); -	 -	ptr = strchr( cp, '&' ); -	if( ptr ) -		*ptr = '_'; -		 -	return( cp );	 -} - - -/* - ***************************************************************************** - * - * Exported Utility Functions  - * - ***************************************************************************** - */ - -EXPORT void wBeep( -		void ) -/* -Beep! -*/ -{ -	gdk_display_beep(gdk_display_get_default()); -} - -typedef struct { -		GtkWidget * win; -		GtkWidget * label; -		GtkWidget * butt[3]; -		} notice_win; -static notice_win noticeW; -static long noticeValue; - -static void doNotice( -		GtkWidget * widget, -		long value ) -{ -	noticeValue = value; -	gtk_widget_destroy( noticeW.win ); -	gtkDoModal( NULL, FALSE ); -} - -/** - * Show a notification window with a yes/no reply and an icon. - * - * \param type IN type of message: Information, Warning, Error - * \param msg  IN message to display - * \param yes  IN text for accept button - * \param no   IN text for cancel button - * \return    True when accept was selected, false otherwise - */ - -int wNoticeEx( int type,  -       		const char * msg, -       		const char * yes, -       		const char * no ) -{ -	 -	int res; -	unsigned flag; -	char *headline; -	GtkWidget *dialog; -	GtkWindow *parent = GTK_WINDOW_TOPLEVEL; - -	switch( type ) { -		case NT_INFORMATION: -			flag = GTK_MESSAGE_INFO; -			headline = _("Information"); -			break; -		case NT_WARNING: -			flag = GTK_MESSAGE_WARNING; -			headline = _("Warning"); -			break; -		case NT_ERROR: -			flag = GTK_MESSAGE_ERROR; -			headline = _("Error"); -			break; -	} -	 -	if( gtkMainW ) -		parent = GTK_WINDOW( gtkMainW->gtkwin); -	 -	dialog = gtk_message_dialog_new( parent,   -					 GTK_DIALOG_DESTROY_WITH_PARENT, -					 flag, -      					 ((no==NULL)?GTK_BUTTONS_OK:GTK_BUTTONS_YES_NO), -					 "%s", msg ); -	gtk_window_set_title( GTK_WINDOW(dialog), headline ); -	   -	res = gtk_dialog_run( GTK_DIALOG(dialog)); -	gtk_widget_destroy( dialog ); -       -	return res == GTK_RESPONSE_OK  || res == GTK_RESPONSE_YES;  -} - - -EXPORT int wNotice( -		const char * msg,		/* Message */ -		const char * yes,		/* First button label */ -		const char * no )		/* Second label (or 'NULL') */ -/* -Popup up a notice box with one or two buttons. -When this notice box is displayed the application is paused and -will not response to other actions. - -Pushing the first button returns 'TRUE'. -Pushing the second button (if present) returns 'FALSE'. -*/ -{ -	return wNotice3( msg, yes, no, NULL ); -} - -/** \brief Popup a notice box with three buttons. - * - * Popup up a notice box with three buttons. - * When this notice box is displayed the application is paused and - * will not response to other actions. - * - * Pushing the first button returns 1 - * Pushing the second button returns 0 - * Pushing the third button returns -1 - * - * \param msg Text to display in message box - * \param yes First button label - * \param no  Second label (or 'NULL') - * \param cancel Third button label (or 'NULL')  - * - * \returns 1, 0 or -1 - */ -  -EXPORT int wNotice3( -		const char * msg,		/* Message */ -		const char * affirmative,		/* First button label */ -		const char * cancel,		/* Second label (or 'NULL') */ -		const char * alternate ) -{ -	notice_win *nw; -	GtkWidget * vbox; -	GtkWidget * hbox; -	GtkWidget * hbox1; -	GtkWidget * image; -	nw = ¬iceW; -	 -	char *aff = NULL; -	char *can = NULL; -	char *alt = NULL; -	 -#ifndef GTK1 -		nw->win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); -		/*gtk_window_set_decorated( GTK_WINDOW(nw->win), FALSE );*/ -#else -		nw->win = gtk_window_new( GTK_WINDOW_DIALOG ); -#endif -	gtk_window_position( GTK_WINDOW(nw->win), GTK_WIN_POS_CENTER ); -	gtk_container_set_border_width (GTK_CONTAINER (nw->win), 0); -	gtk_window_set_resizable (GTK_WINDOW (nw->win), FALSE); -	gtk_window_set_modal (GTK_WINDOW (nw->win), TRUE); -	gtk_window_set_type_hint (GTK_WINDOW (nw->win), GDK_WINDOW_TYPE_HINT_DIALOG); -		 -	vbox = gtk_vbox_new( FALSE, 12 ); -	gtk_widget_show( vbox ); -	gtk_container_add( GTK_CONTAINER(nw->win), vbox ); -	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); -		 -	hbox = gtk_hbox_new( FALSE, 12 ); -	gtk_box_pack_start( GTK_BOX(vbox), hbox, TRUE, TRUE, 0 ); -	gtk_widget_show(hbox); - - 	image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); -  gtk_widget_show (image); -  gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); -  gtk_misc_set_alignment (GTK_MISC (image), 0, 0); - -	/* create the text label, allow GTK to wrap and allow for markup (for future enhancements) */ -	nw->label = gtk_label_new(msg); -	gtk_widget_show( nw->label ); -	gtk_box_pack_end (GTK_BOX (hbox), nw->label, TRUE, TRUE, 0); -	gtk_label_set_use_markup (GTK_LABEL (nw->label), FALSE); -	gtk_label_set_line_wrap (GTK_LABEL (nw->label), TRUE); -	gtk_misc_set_alignment (GTK_MISC (nw->label), 0, 0); - -	/* this hbox will include the button bar */ -	hbox1 = gtk_hbox_new (TRUE, 0); -	gtk_widget_show (hbox1); -  gtk_box_pack_start (GTK_BOX (vbox), hbox1, FALSE, TRUE, 0); - -	/* add the respective buttons */ -	aff = gtkChgMnemonic( (char *) affirmative); -	nw->butt[ 0 ] = gtk_button_new_with_mnemonic (aff); -	gtk_widget_show (nw->butt[ 0 ]); -	gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 0 ], TRUE, TRUE, 0); - 	gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 0 ]), 3); -	gtk_signal_connect( GTK_OBJECT(nw->butt[0]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)1 ); -  GTK_WIDGET_SET_FLAGS (nw->butt[ 0 ], GTK_CAN_DEFAULT); - -	if( cancel ) { -		can = gtkChgMnemonic( (char *) cancel); -		nw->butt[ 1 ] = gtk_button_new_with_mnemonic (can); - 		gtk_widget_show (nw->butt[ 1 ]); -  	gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 1 ], TRUE, TRUE, 0); -	  gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 1 ]), 3); -		gtk_signal_connect( GTK_OBJECT(nw->butt[1]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)0 ); -	  GTK_WIDGET_SET_FLAGS (nw->butt[ 1 ], GTK_CAN_DEFAULT); - -		if( alternate ) { -			alt = gtkChgMnemonic( (char *) alternate); -			nw->butt[ 2 ] = gtk_button_new_with_mnemonic (alt); -			gtk_widget_show (nw->butt[ 2 ]); -			gtk_box_pack_start (GTK_BOX (hbox1), nw->butt[ 2 ], TRUE, TRUE, 0); -			gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 2 ]), 3); -			gtk_signal_connect( GTK_OBJECT(nw->butt[2]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)-1 ); -		  GTK_WIDGET_SET_FLAGS (nw->butt[ 2 ], GTK_CAN_DEFAULT); - 		} -	}	 - -  gtk_widget_grab_default (nw->butt[ 0 ]); -  gtk_widget_grab_focus (nw->butt[ 0 ]); - -	gtk_widget_show( nw->win ); - -	if ( gtkMainW ) { -		gtk_window_set_transient_for( GTK_WINDOW(nw->win), GTK_WINDOW( gtkMainW->gtkwin) ); -/*		gdk_window_set_group( nw->win->window, gtkMainW->gtkwin->window ); */ -	} -	gtkDoModal( NULL, TRUE ); -	 -	if( aff ) -		free( aff ); -		 -	if( can ) -		free( can ); -		 -	if( alt ) -		free( alt );		 -		 -	return noticeValue; -} - - -EXPORT void wFlush( -		void ) -/* -Flushs all commands to the Window. -*/ -{ -	while ( gtk_events_pending() ) -		gtk_main_iteration(); - -	gdk_display_sync(gdk_display_get_default()); -} - - -void wWinTop( wWin_p win ) -{ -} - - -void wSetCursor( wCursor_t cursor ) -{ -} - - -const char * wMemStats( void ) -{ -#ifdef LATER -	static char msg[80]; -	struct mstats stats; -	stats = mstats(); -	sprintf( msg, "Total %d, used %d(%d), free %d(%d)", -				stats.bytes_total, -				stats.bytes_used, stats.chunks_used, -				stats.bytes_free, stats.chunks_free ); -	return msg; -#else -	return "No stats available"; -#endif -} - - -wBool_t wCheckExecutable( void ) -{ -	return TRUE; -} - - -void wGetDisplaySize( wPos_t * w, wPos_t * h ) -{ - -	*w = gdk_screen_width(); -	*h = gdk_screen_height(); -} - - -wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color ) -{ -	wIcon_p ip; -	ip = (wIcon_p)malloc( sizeof *ip ); -	ip->gtkIconType = gtkIcon_bitmap; -	ip->w = w; -	ip->h = h; -	ip->color = color; -	ip->bits = bits; -	return ip; -} - -wIcon_p wIconCreatePixMap( char *pm[] ) -{ -	wIcon_p ip; -	ip = (wIcon_p)malloc( sizeof *ip ); -	ip->gtkIconType = gtkIcon_pixmap; -	ip->w = 0; -	ip->h = 0; -	ip->color = 0; -	ip->bits = pm; -	return ip; -} - - -void wIconSetColor( wIcon_p ip, wDrawColor color ) -{ -	ip->color = color; -} - -void wConvertToCharSet( char * buffPtr, int buffMax ) -{ -} - - -void wConvertFromCharSet( char * buffPtr, int buffMax ) -{ -} - -static dynArr_t conversionBuffer_da; -#define convesionBuffer(N) DYNARR_N( char, conversionBuffer_da, N ) - -char * gtkConvertInput( const char * inString ) -{ -#ifndef GTK1 -	const char * cp; -	char * cq; -	int extCharCnt, inCharCnt; - -	/* Already UTF-8 encoded? */ -	if (g_utf8_validate(inString, -1, NULL)) -		/* Yes, do not double-convert */ -		return (char*)inString; -#ifdef VERBOSE -	fprintf(stderr, "gtkConvertInput(%s): Invalid UTF-8, converting...\n", inString); -#endif - -	for ( cp=inString, extCharCnt=0; *cp; cp++ ) { -		if ( ((*cp)&0x80) != 0 ) -			extCharCnt++; -	} -	inCharCnt = cp-inString; -	if ( extCharCnt == 0 ) -		return (char*)inString; -	DYNARR_SET( char, conversionBuffer_da, inCharCnt+extCharCnt+1 ); -	for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) { -		if ( ((*cp)&0x80) != 0 ) { -			*cq++ = 0xC0+(((*cp)&0xC0)>>6); -			*cq++ = 0x80+((*cp)&0x3F); -		} else { -			*cq++ = *cp; -		} -	} -	*cq = 0; -	return (char*)conversionBuffer_da.ptr; -#else -	return (char*)inString; -#endif -} - - -char * gtkConvertOutput( const char * inString ) -{ -#ifndef GTK1 -	const char * cp; -	char * cq; -	int extCharCnt, inCharCnt; -	for ( cp=inString, extCharCnt=0; *cp; cp++ ) { -		if ( ((*cp)&0xC0) == 0x80 ) -			extCharCnt++; -	} -	inCharCnt = cp-inString; -	if ( extCharCnt == 0 ) -		return (char*)inString; -	DYNARR_SET( char, conversionBuffer_da, inCharCnt+1 ); -	for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) { -		if ( ((*cp)&0x80) != 0 ) { -			*cq++ = 0xC0+(((*cp)&0xC0)>>6); -			*cq++ = 0x80+((*cp)&0x3F); -		} else { -			*cq++ = *cp; -		} -	} -	*cq = 0; -	return (char*)conversionBuffer_da.ptr; -#else -	return (char*)inString; -#endif -} - -/*-----------------------------------------------------------------*/ - -typedef struct accelData_t { -		wAccelKey_e key; -		int modifier; -		wAccelKeyCallBack_p action; -		void * data; -		} accelData_t; -static dynArr_t accelData_da; -#define accelData(N) DYNARR_N( accelData_t, accelData_da, N ) - - -static guint accelKeyMap[] = { -			0,			/* wAccelKey_None, */ -			GDK_Delete,		/* wAccelKey_Del, */ -			GDK_Insert,		/* wAccelKey_Ins, */ -			GDK_Home,		/* wAccelKey_Home, */ -			GDK_End,		/* wAccelKey_End, */ -			GDK_Page_Up,	/* wAccelKey_Pgup, */ -			GDK_Page_Down,	/* wAccelKey_Pgdn, */ -			GDK_Up,		/* wAccelKey_Up, */ -			GDK_Down,		/* wAccelKey_Down, */ -			GDK_Right,		/* wAccelKey_Right, */ -			GDK_Left,		/* wAccelKey_Left, */ -			GDK_BackSpace,	/* wAccelKey_Back, */ -			GDK_F1,		/* wAccelKey_F1, */ -			GDK_F2,		/* wAccelKey_F2, */ -			GDK_F3,		/* wAccelKey_F3, */ -			GDK_F4,		/* wAccelKey_F4, */ -			GDK_F5,		/* wAccelKey_F5, */ -			GDK_F6,		/* wAccelKey_F6, */ -			GDK_F7,		/* wAccelKey_F7, */ -			GDK_F8,		/* wAccelKey_F8, */ -			GDK_F9,		/* wAccelKey_F9, */ -			GDK_F10,		/* wAccelKey_F10, */ -			GDK_F11,		/* wAccelKey_F11, */ -			GDK_F12		/* wAccelKey_F12, */ -		}; - - -EXPORT void wAttachAccelKey( -		wAccelKey_e key, -		int modifier, -		wAccelKeyCallBack_p action, -		void * data ) -{ -	accelData_t * ad; -	if ( key < 1 || key > wAccelKey_F12 ) { -		fprintf( stderr, "wAttachAccelKey(%d) out of range\n", (int)key ); -		return; -	} -	DYNARR_APPEND( accelData_t, accelData_da, 10 ); -	ad = &accelData(accelData_da.cnt-1); -	ad->key = key; -	ad->modifier = modifier; -	ad->action = action; -	ad->data = data; -} - - -EXPORT struct accelData_t * gtkFindAccelKey( -		GdkEventKey * event ) -{ -	accelData_t * ad; -	int modifier = 0; -	if ( ( event->state & GDK_SHIFT_MASK ) ) -		modifier |= WKEY_SHIFT; -	if ( ( event->state & GDK_CONTROL_MASK ) ) -		modifier |= WKEY_CTRL; -	if ( ( event->state & GDK_MOD1_MASK ) ) -		modifier |= WKEY_ALT; -	for ( ad=&accelData(0); ad<&accelData(accelData_da.cnt); ad++ ) -		if ( event->keyval == accelKeyMap[ad->key] && -			 modifier == ad->modifier ) -			return ad; -	return NULL; -} - - -EXPORT wBool_t gtkHandleAccelKey( -		GdkEventKey *event ) -{ -	accelData_t * ad = gtkFindAccelKey( event ); -	if ( ad ) { -		ad->action( ad->key, ad->data ); -		return TRUE; -	} -	return FALSE; -} - -/* - ***************************************************************************** - * - * Timer Functions  - * - ***************************************************************************** - */ - -static wBool_t gtkPaused = FALSE; -static int alarmTimer = 0; - -static gint doAlarm( -		gpointer data ) -{ -	wAlarmCallBack_p func = (wAlarmCallBack_p)data; -	if (alarmTimer) -		gtk_timeout_remove( alarmTimer ); -	func(); -	alarmTimer = 0; -	return 0; -} - - -EXPORT void wAlarm( -		long count, -		wAlarmCallBack_p func )		/* milliseconds */ -/* -Alarm for <count> milliseconds. -*/ -{ -	gtkPaused = TRUE; -	if (alarmTimer) -		gtk_timeout_remove( alarmTimer ); -	alarmTimer = gtk_timeout_add( count, doAlarm, (void *) (GtkFunction)func ); -} - - -static wControl_p triggerControl = NULL; -static setTriggerCallback_p triggerFunc = NULL; - -static void doTrigger( void ) -{ -	if (triggerControl && triggerFunc) { -		triggerFunc( triggerControl ); -		triggerFunc = NULL; -		triggerControl = NULL; -	} -} - -void gtkSetTrigger( -		wControl_p b, -		setTriggerCallback_p trigger ) -{ -	triggerControl = b; -	triggerFunc = trigger; -	wAlarm( 500, doTrigger ); -} - - -EXPORT void wPause( -		long count )		/* milliseconds */ -/* -Pause for <count> milliseconds. -*/ -{ -	struct timeval timeout; -	sigset_t signal_mask; -	sigset_t oldsignal_mask; -	 -	gdk_display_sync(gdk_display_get_default()); -	 -	timeout.tv_sec = count/1000; -	timeout.tv_usec = (count%1000)*1000; -	 -	sigemptyset( &signal_mask ); -	sigaddset( &signal_mask, SIGIO ); -	sigaddset( &signal_mask, SIGALRM );	 -	sigprocmask( SIG_BLOCK, &signal_mask, &oldsignal_mask ); -	 -	if (select( 0, NULL, NULL, NULL, &timeout ) == -1) { -		perror("wPause:select"); -	} -	sigprocmask( SIG_BLOCK, &oldsignal_mask, NULL ); -} - - -unsigned long wGetTimer( void ) -{ -	struct timeval tv; -	struct timezone tz; -	int rc; -	rc = gettimeofday( &tv, &tz ); -	return (tv.tv_sec-startTime.tv_sec+1) * 1000 + tv.tv_usec /1000; -} - - - -/** - * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by  - * calling wControlLinkedActive for one member of the list  - * - * \param b1 IN  first control - * \param b2 IN  second control - * \return    none - */ -  -EXPORT void wControlLinkedSet( wControl_p b1, wControl_p b2 ) -{ -	 -	b2->synonym = b1->synonym; -	if( b2->synonym == NULL ) -		b2->synonym = b1; -		 -	b1->synonym = b2; -} 	 - -/** - * Activate/deactivate a group of synonymous controls. - * - * \param b IN  control - * \param active IN  state - * \return    none - */ -  - -EXPORT void wControlLinkedActive( wControl_p b, int active ) -{ -	wControl_p savePtr = b; - -	if( savePtr->type == B_MENUITEM ) -		wMenuPushEnable( (wMenuPush_p)savePtr, active ); -	else 	 -		wControlActive( savePtr, active );		 - -	savePtr = savePtr->synonym; - -	while( savePtr && savePtr != b ) {	 - -		if( savePtr->type == B_MENUITEM ) -			wMenuPushEnable( (wMenuPush_p)savePtr, active ); -		else 	 -			wControlActive( savePtr, active );		 - -		savePtr = savePtr->synonym; -	}	 -} - -/* - ***************************************************************************** - * - * Control Utilities - * - ***************************************************************************** - */ - -EXPORT void wControlShow( -		wControl_p b,		/* Control */ -		wBool_t show )		/* Command */ -/* -Cause the control <b> to be displayed or hidden. -Used to hide control (such as a list) while it is being updated. -*/ -{ -	if ( b->type == B_LINES ) { -		gtkLineShow( (wLine_p)b, show ); -		return; -	} -	if (b->widget == 0) abort(); -	if (show) { -		gtk_widget_show( b->widget ); -		if (b->label) -			gtk_widget_show( b->label ); -	} else { -		gtk_widget_hide( b->widget ); -		if (b->label) -			gtk_widget_hide( b->label ); -	} -} - -EXPORT void wControlActive( -		wControl_p b,		/* Control */ -		int active )		/* Command */ -/* -Cause the control <b> to be marked active or inactive. -Inactive controls donot respond to actions. -*/ -{ -	if (b->widget == 0) abort(); -	gtk_widget_set_sensitive( GTK_WIDGET(b->widget), active ); -} - - -EXPORT wPos_t wLabelWidth( -		const char * label )		/* Label */ -/* -Returns the width of <label>. -This is used for computing window layout. -Typically the width to the longest label is computed and used as -the X-position for <controls>. -*/ -{ -	GtkWidget * widget; -	GtkRequisition requisition; -	widget = gtk_label_new( gtkConvertInput(label) ); -	gtk_widget_size_request( widget, &requisition ); -	gtk_widget_destroy( widget ); -	return requisition.width+8; -} - - -EXPORT wPos_t wControlGetWidth( -		wControl_p b)		/* Control */ -{ -	return b->w; -} - - -EXPORT wPos_t wControlGetHeight( -		wControl_p b)		/* Control */ -{ -	return b->h; -} - - -EXPORT wPos_t wControlGetPosX( -		wControl_p b)		/* Control */ -{ -	return b->realX; -} - - -EXPORT wPos_t wControlGetPosY( -		wControl_p b)		/* Control */ -{ -	return b->realY - FOUR - ((b->parent->option&F_MENUBAR)?MENUH:0); -} - - -EXPORT void wControlSetPos( -		wControl_p b,		/* Control */ -		wPos_t x,		/* X-position */ -		wPos_t y )		/* Y-position */ -{ -	b->realX = x; -	b->realY = y + FOUR + ((b->parent->option&F_MENUBAR)?MENUH:0); -#ifndef GTK1 -	if (b->widget) -		gtk_fixed_move( GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY ); -	if (b->label) -		gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); -#else -	if (b->widget) -		gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -	if (b->label) -		gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); -#endif -} - - -EXPORT void wControlSetLabel( -		wControl_p b, -		const char * labelStr ) -{ -	GtkRequisition requisition; -	if (b->label) { -		gtk_label_set( GTK_LABEL(b->label), gtkConvertInput(labelStr) ); -		gtk_widget_size_request( b->label, &requisition ); -		b->labelW = requisition.width+8; -#ifndef GTK1 -		gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); -#else -		gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); -#endif -	} else { -		b->labelW = gtkAddLabel( b, labelStr ); -	} -} - -EXPORT void wControlSetContext( -		wControl_p b, -		void * context ) -{ -	b->data = context; -} - - -EXPORT void wControlSetFocus( -		wControl_p b ) -{ -} - - -static int gtkControlHiliteWidth = 3; -EXPORT void wControlHilite( -		wControl_p b, -		wBool_t hilite ) -{ -	int off = gtkControlHiliteWidth/2+1; -	if ( b->parent->gc == NULL ) { -		b->parent->gc = gdk_gc_new( b->parent->gtkwin->window ); -		gdk_gc_copy( b->parent->gc, b->parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -		b->parent->gc_linewidth = 0; -		gdk_gc_set_line_attributes( b->parent->gc, b->parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -	} -	if ( b->widget == NULL ) -		return; -	if ( ! GTK_WIDGET_VISIBLE( b->widget ) ) -		return; -	if ( ! GTK_WIDGET_VISIBLE( b->parent->widget ) ) -		return; -	gdk_gc_set_foreground( b->parent->gc, gtkGetColor( wDrawColorBlack, FALSE ) ); -	gdk_gc_set_function( b->parent->gc, GDK_XOR ); -	gdk_gc_set_line_attributes( b->parent->gc, gtkControlHiliteWidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -	gdk_draw_line( b->parent->widget->window, b->parent->gc, -		b->realX - gtkControlHiliteWidth, -		b->realY - off, -		b->realX + b->w + gtkControlHiliteWidth, -		b->realY - off ); -	gdk_draw_line( b->parent->widget->window, b->parent->gc, -		b->realX - gtkControlHiliteWidth, -		b->realY + b->h + off - 1, -		b->realX + b->w + gtkControlHiliteWidth, -		b->realY + b->h + off - 1 ); -	gdk_draw_line( b->parent->widget->window, b->parent->gc, -		b->realX - off, -		b->realY, -		b->realX - off, -		b->realY + b->h ); -	gdk_draw_line( b->parent->widget->window, b->parent->gc, -		b->realX + b->w + off - 1, -		b->realY, -		b->realX + b->w + off - 1, -		b->realY + b->h ); -} - -/* - ******************************************************************************* - * - * Main - * - ******************************************************************************* - */ - -#ifdef GTK -static wBool_t wAbortOnErrors = FALSE; -#endif - -int do_rgb_init = 1; - -int main( int argc, char *argv[] ) -{ -	wWin_p win; -	wControl_p b; -	const char *ld, *hp; -	static char buff[BUFSIZ]; - -	if ( getenv( "GTKLIB_NOLOCALE" ) == 0 ) -		setlocale( LC_ALL, "en_US" ); -	gtk_init( &argc, &argv ); -	gettimeofday( &startTime, NULL ); - -	if ( getenv( "XVLIB_REVERSEICON" ) != 0 ) -		reverseIcon = !reverseIcon; - -	if ( do_rgb_init ) -		gdk_rgb_init();	/* before we try to draw */ - -	if ((win=wMain( argc, argv )) == (wWin_p)0) -		exit(1); - -	ld = wGetAppLibDir(); -	if (ld != NULL) { -		sprintf( buff, "HELPPATH=/usr/lib/help:%s:", ld ); -		if ( (hp = getenv("HELPPATH")) != NULL ) -			strcat( buff, hp ); -		putenv( buff ); -	} - -	if (!win->shown) -		wWinShow( win, TRUE ); -	for (b=win->first; b != NULL; b = b->next) { -		if (b->repaintProc) -			b->repaintProc( b ); -	} -	gtk_main(); -	exit(0); -} diff --git a/app/wlib/gtklib/gtksimple.c b/app/wlib/gtklib/gtksimple.c deleted file mode 100644 index 244c0a3..0000000 --- a/app/wlib/gtklib/gtksimple.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksimple.c,v 1.6 2009-09-25 05:38:15 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> - -#include "gtkint.h" - -static int windowxxx = 0; -/* - ***************************************************************************** - * - * Message Boxes - * - ***************************************************************************** - */ - -struct wMessage_t { -		WOBJ_COMMON -		GtkWidget * labelWidget; -		const char * message; -		wPos_t labelWidth; -		}; - -EXPORT void wMessageSetValue( -		wMessage_p b, -		const char * arg ) -{ -	if (b->widget == 0) abort(); -	gtk_label_set( GTK_LABEL( b->labelWidget ), gtkConvertInput(arg) ); -} - - -EXPORT void wMessageSetWidth( -		wMessage_p b, -		wPos_t width ) -{ -	b->labelWidth = width; -#ifndef GTK1 -	gtk_widget_set_size_request( b->widget, width, -1 ); -#else -	gtk_widget_set_usize( b->widget, width, -1 ); -#endif -} - - -EXPORT wPos_t wMessageGetHeight( -		long flags ) -{ -	return 14; -} - -/** - * Create a window for a simple text.  - * - * \param IN parent Handle of parent window - * \param IN x position in x direction - * \param IN y position in y direction - * \param IN labelStr ??? - * \param IN width horizontal size of window - * \param IN message message to display ( null terminated ) - * \param IN flags display options - * \return handle for created window - */ - -EXPORT wMessage_p wMessageCreateEx( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* labelStr, -		wPos_t	width, -		const char	*message,  -		long flags ) -{ -	wMessage_p b; -	GtkRequisition requisition; -	PangoFontDescription *fontDesc; -	int fontSize; - -	b = (wMessage_p)gtkAlloc( parent, B_MESSAGE, x, y, NULL, sizeof *b, NULL ); -	gtkComputePos( (wControl_p)b ); -	b->message = message; -	b->labelWidth = width; - -	b->labelWidget = gtk_label_new( message?gtkConvertInput(message):"" ); - -	/* do we need to set a special font? */ -	if( wMessageSetFont( flags ))	{ -		/* get the current font descriptor */ -		fontDesc = (b->labelWidget)->style->font_desc; -		 -		/* get the current font size */ -		fontSize = PANGO_PIXELS(pango_font_description_get_size( fontDesc )); -		 -		/* calculate the new font size */ -		if( flags & BM_LARGE ) { -			pango_font_description_set_size( fontDesc, fontSize * 1.4 * PANGO_SCALE ); -		} else { -			pango_font_description_set_size( fontDesc, fontSize * 0.7 * PANGO_SCALE ); -		}			 -		 -		/* set the new font size */ -		gtk_widget_modify_font( (GtkWidget *)b->labelWidget, fontDesc ); -	} - -	b->widget = gtk_fixed_new(); -	gtk_widget_size_request( GTK_WIDGET(b->labelWidget), &requisition ); -	gtk_container_add( GTK_CONTAINER(b->widget), b->labelWidget ); -	 -	gtk_widget_set_size_request( b->widget, width?width:requisition.width, requisition.height ); -	gtkControlGetSize( (wControl_p)b ); -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); - -	gtk_widget_show( b->widget ); -	gtk_widget_show( b->labelWidget ); -	gtkAddButton( (wControl_p)b ); - -	/* Reset font size to normal */ -	if( wMessageSetFont( flags ))	{ -		if( flags & BM_LARGE ) { -			pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE); -		} else { -			pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE); -		} -	} -	return b; -} - -/* - ***************************************************************************** - * - * Lines - * - ***************************************************************************** - */ - -struct wLine_t { -		WOBJ_COMMON -		wBool_t visible; -		int count; -		wLines_t * lines; -		}; - -static void linesRepaint( wControl_p b ) -{ -	wLine_p bl = (wLine_p)(b); -	int i; -	wWin_p win = (wWin_p)(bl->parent); -	GdkDrawable * window; -	GdkColor *black; - -	if (!bl->visible) -		return; -if (windowxxx) -	window = win->gtkwin->window; -else -	window = win->widget->window; - -	/* get the GC attached to the panel in main() */ -	black = gtkGetColor( wDrawColorBlack, TRUE ); -	gdk_gc_set_foreground( win->gc, black ); -	gdk_gc_set_function( win->gc, GDK_COPY ); -	for (i=0; i<bl->count; i++) { -		if (win->gc_linewidth != bl->lines[i].width) { -			win->gc_linewidth = bl->lines[i].width; -			gdk_gc_set_line_attributes( win->gc, win->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -		} -		gdk_draw_line( window, win->gc, -				bl->lines[i].x0, bl->lines[i].y0, -				bl->lines[i].x1, bl->lines[i].y1 ); -	} -} - - -void gtkLineShow( -		wLine_p bl, -		wBool_t visible ) -{ -	bl->visible = visible; -} - - -wLine_p wLineCreate( -		wWin_p	parent, -		const char	* labelStr, -		int	count, -		wLines_t * lines ) -{ -	wLine_p b; -	int i; -	b = (wLine_p)gtkAlloc( parent, B_LINES, 0, 0, labelStr, sizeof *b, NULL ); -	if (parent->gc == NULL) { -		parent->gc = gdk_gc_new( parent->gtkwin->window ); -		gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -		parent->gc_linewidth = 0; -		gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -	} -	b->visible = TRUE; -	b->count = count; -	b->lines = lines; - -	b->w = b->h = 0; -	for ( i=0; i<count; i++ ) { -		if (lines[i].x0 > b->w) -			b->w = lines[i].x0; -		if (lines[i].y0 > b->h) -			b->h = lines[i].y0; -		if (lines[i].x1 > b->w) -			b->w = lines[i].x1; -		if (lines[i].y1 > b->h) -			b->h = lines[i].y1; -	} -	b->repaintProc = linesRepaint; -	gtkAddButton( (wControl_p)b ); -	b->widget = 0; -	return b; -} - - -/* - ***************************************************************************** - * - * Boxes - * - ***************************************************************************** - */ - -struct wBox_t { -		WOBJ_COMMON -		wBoxType_e boxTyp; -		}; - -#define B (1) -#define W (2) -#define SETCOLOR( S, N ) \ -		if ( lastColor != colors[style][S][N] ) { \ -			lastColor = colors[style][S][N]; \ -			gdk_gc_set_foreground( win->gc, (lastColor==B)?black:white ); \ -		} - -EXPORT void wBoxSetSize( -		wBox_p b,	/* */ -		wPos_t w,	/* */ -		wPos_t h )	/* */ -{ -	b->w = w; -	b->h = h; -} - - -EXPORT void gtkDrawBox( -		wWin_p win, -		wBoxType_e style, -		wPos_t x, -		wPos_t y, -		wPos_t w, -		wPos_t h ) -{ -	wPos_t x0, y0, x1, y1; -	char lastColor; -	GdkColor *white; -	GdkColor *black; -	GdkDrawable * window; -	static char colors[8][4][2] = { -		{ /* ThinB  */ {B,0}, {B,0}, {B,0}, {B,0} }, -		{ /* ThinW  */ {W,0}, {W,0}, {W,0}, {W,0} }, -		{ /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} }, -		{ /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} }, -		{ /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} }, -		{ /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} }, -		{ /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} }, -		{ /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} } }; - -if (windowxxx) -	window = win->gtkwin->window; -else -	window = win->widget->window; -	white = gtkGetColor( wDrawColorWhite, TRUE ); -	black = gtkGetColor( wDrawColorBlack, TRUE ); -	win->gc_linewidth = 0; -	gdk_gc_set_line_attributes( win->gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -	gdk_gc_set_function( win->gc, GDK_COPY ); -	x0 = x; -	x1 = x+w; -	y0 = y; -	y1 = y+h; -	lastColor = colors[style][0][0]; -	gdk_gc_set_foreground( win->gc, (lastColor==B)?black:white ); -	gdk_draw_line( window, win->gc, x0, y0, x0, y1 ); -	SETCOLOR( 1, 0 ); -	gdk_draw_line( window, win->gc, x0+1, y0, x1, y0 ); -	SETCOLOR( 2, 0 ); -	gdk_draw_line( window, win->gc, x1, y1, x0+1, y1 ); -	SETCOLOR( 3, 0 ); -	gdk_draw_line( window, win->gc, x1, y1-1, x1, y0+1 ); -	if (style < wBoxThickB) -		return; -	x0++; y0++; x1--; y1--; -	SETCOLOR( 0, 1 ); -	gdk_draw_line( window, win->gc, x0, y0, x0, y1 ); -	SETCOLOR( 1, 1 ); -	gdk_draw_line( window, win->gc, x0+1, y0, x1, y0 ); -	SETCOLOR( 2, 1 ); -	gdk_draw_line( window, win->gc, x1, y1, x0+1, y1 ); -	SETCOLOR( 3, 1 ); -	gdk_draw_line( window, win->gc, x1, y1-1, x1, y0+1 ); -	gdk_gc_set_foreground( win->gc, black ); -} - - -static void boxRepaint( wControl_p b ) -{ -	wBox_p bb = (wBox_p)(b); -	wWin_p win = bb->parent; - -	gtkDrawBox( win, bb->boxTyp, bb->realX, bb->realY, bb->w, bb->h ); -} - - -wBox_p wBoxCreate( -		wWin_p	parent, -		wPos_t	bx, -		wPos_t	by, -		const char	* labelStr, -		wBoxType_e boxTyp, -		wPos_t	bw, -		wPos_t	bh ) -{ -	wBox_p b; -	b = (wBox_p)gtkAlloc( parent, B_BOX, bx, by, labelStr, sizeof *b, NULL ); -	gtkComputePos( (wControl_p)b ); -	b->boxTyp = boxTyp; -	b->w = bw; -	b->h = bh; -	if (parent->gc == NULL) { -		parent->gc = gdk_gc_new( parent->gtkwin->window ); -		gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -		parent->gc_linewidth = 0; -		gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); -	} -	b->repaintProc = boxRepaint; -	gtkAddButton( (wControl_p)b ); -	return b; -} - diff --git a/app/wlib/gtklib/gtksingle.c b/app/wlib/gtklib/gtksingle.c deleted file mode 100644 index d106e17..0000000 --- a/app/wlib/gtklib/gtksingle.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksingle.c,v 1.2 2009-05-15 18:54:20 m_fischer Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <gtk/gtk.h> - -#include "gtkint.h" - -/* - ***************************************************************************** - * - * Text Boxes - * - ***************************************************************************** - */ - -struct wString_t { -		WOBJ_COMMON -		char * valueP; -		wIndex_t valueL; -		wStringCallBack_p action; -		wBool_t busy; -		}; - -void wStringSetValue( -		wString_p b, -		const char * arg ) -{ -	wBool_t busy; -	if (b->widget == 0) abort(); -	busy = b->busy; -		b->busy = TRUE; -		gtk_entry_set_text( GTK_ENTRY(b->widget), arg ); -		b->busy = busy; -} - - -void wStringSetWidth( -		wString_p b, -		wPos_t w ) -{ -#ifndef GTK1 -	gtk_widget_set_size_request( b->widget, w, -1 ); -#else -	gtk_widget_set_usize( b->widget, w, -1 ); -#endif -	b->w = w; -} - - -const char * wStringGetValue( -		wString_p b ) -{ -	if (b->widget == 0) abort(); -	return gtk_entry_get_text( GTK_ENTRY(b->widget) ); -} - - -static void triggerString( -		wControl_p b ) -{ -	wString_p bs = (wString_p)b; -	const char * s; - -	if (b == 0) -		return; -	if (bs->widget == 0) abort(); -	s = gtk_entry_get_text( GTK_ENTRY(bs->widget) ); -	if (debugWindow >= 2) printf("%s text = %s\n", bs->labelStr?bs->labelStr:"No label", s ); -	if (s == NULL)  -		return; -	if (debugWindow >= 2) printf("triggerString( %s )\n", s ); -	if (bs->action) { -		bs->busy = TRUE; -		bs->action( s, bs->data ); -		bs->busy = FALSE; -	} -	gtkSetTrigger( NULL, NULL ); -	return; -} - - -static void stringActivated( -		GtkEntry * widget, -		wString_p b ) -{ -	const char * s; -	if (b == 0) -		return; -	s = wStringGetValue(b); - -	if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s ); -	if (b->valueP) -		strcpy( b->valueP, s ); -	if (b->action) { -		b->busy = TRUE; -		b->action( s, b->data ); -		b->busy = FALSE; -	} -} - -static void stringChanged( -		GtkEntry * widget, -		wString_p b ) -{ -	const char *new_value; -	if (b == 0) -		return; -	if (b->busy) -		return; -	new_value = wStringGetValue(b); -	if (b->valueP != NULL) -		strcpy( b->valueP, new_value ); -	if (b->action) -		gtkSetTrigger( (wControl_p)b, triggerString ); -	return; -} - -wString_p wStringCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long	option, -		wPos_t	width, -		char	*valueP, -		wIndex_t valueL, -		wStringCallBack_p action, -		void 	*data ) -{ -	wString_p b; - -	b = (wString_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data ); -	b->valueP = valueP; -	b->action = action; -	b->option = option; -	b->valueL = valueL; -	gtkComputePos( (wControl_p)b ); - -	if (valueL) { -		b->widget = (GtkWidget*)gtk_entry_new_with_max_length( valueL ); -	} else { -		b->widget = (GtkWidget*)gtk_entry_new(); -	} -	if (b->widget == 0) abort(); - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	if ( width ) -#ifndef GTK1 -		gtk_widget_set_size_request( b->widget, width, -1 ); -#else -		gtk_widget_set_usize( b->widget, width, -1 ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	/*b->w += 4;*/ -	/*b->h += 4;*/ -	if (b->valueP) -		wStringSetValue( b, b->valueP ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(stringChanged), b ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(stringActivated), b ); -	if (option & BO_READONLY) -		gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE ); -	return b; -} - -/* - ***************************************************************************** - * - * Floating Point Value Boxes - * - ***************************************************************************** - */ - - -struct wFloat_t { -		WOBJ_COMMON -		double low, high; -		double oldValue; -		double * valueP; -		wFloatCallBack_p action; -		wBool_t busy; -		}; - - -void wFloatSetValue( -		wFloat_p b, -		double arg ) -{ -	char message[80]; -	if (b->widget == 0) abort(); -	sprintf( message, "%0.3f", arg ); -	if (!b->busy) { -		b->busy = TRUE; -		gtk_entry_set_text( GTK_ENTRY(b->widget), message ); -		b->busy = FALSE; -	} -	if (b->valueP) -		*b->valueP = arg; -} - - -double wFloatGetValue( -		wFloat_p b ) -{ -	double ret; -	const char * cp; -	if (b->widget == 0) abort(); -	cp = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	ret = atof( cp ); -	return ret; -} - - -static void triggerFloat( -		wControl_p b ) -{ -	wFloat_p bf = (wFloat_p)b; -	const char * s; -	char * cp; -	double v; - -	if (b == 0) -		return; -	if (bf->widget == 0) abort(); -	s = gtk_entry_get_text( GTK_ENTRY(bf->widget) ); -	if (debugWindow >= 2) printf("%s text = %s\n", bf->labelStr?bf->labelStr:"No label", s ); -	if (s == NULL)  -		return; -	v = strtod( s, &cp ); -	if (*cp!=0 || v < bf->low || v > bf->high) -		return; -	/*if (bf->oldValue == v) -		return;*/ -	if (debugWindow >= 2) printf("triggerFloat( %0.3f )\n", v ); -	bf->oldValue = v; -	if (bf->valueP) -		*bf->valueP = v; -	if (bf->action) { -		bf->busy = TRUE; -		bf->action( v, bf->data ); -		bf->busy = FALSE; -	} -	gtkSetTrigger( NULL, NULL ); -	return; -} - - -static void floatActivated( -		GtkEntry *widget, -		wFloat_p b ) -{ -	const char * s; -	char * cp; -	double v; -	char val_s[80]; - -	if (b == 0) -		return; -	if (b->widget == 0) abort(); -	s = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s ); -	if (s != NULL) { -		v = strtod( s, &cp ); -		if (*cp != '\n' && *cp != '\0') { -			wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL ); -		} else if (v < b->low || v > b->high) { -			sprintf( val_s, "Please enter a value between %0.3f and %0.3f", b->low, b->high ); -			wNoticeEx( NT_ERROR, val_s, "Ok", NULL ); -		} else { -			if (debugWindow >= 2) printf("floatActivated( %0.3f )\n", v ); -			b->oldValue = v; -			if (b->valueP) -				*b->valueP = v; -			if (b->action) { -				gtkSetTrigger( NULL, NULL ); -				b->busy = TRUE; -				b->action( v, b->data ); -				b->busy = FALSE; -			} -			return; -		} -		sprintf( val_s, "%0.3f", b->oldValue); -		b->busy = TRUE; -		gtk_entry_set_text( GTK_ENTRY(b->widget), val_s ); -		b->busy = FALSE; -	} -	return; -} - -static void floatChanged( -		GtkEntry *widget, -		wFloat_p b ) -{ -	const char * s; -	char * cp; -	double v; - -	if (b == 0) -		return; -	if (b->widget == 0) abort(); -	if (b->busy) -		return; -	s = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	if (s == NULL) -		return; -	if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s ); -	if ( s[0] == '\0' || -		 strcmp( s, "-" ) == 0 || -		 strcmp( s, "." ) == 0 ) { -		v = 0; -	} else { -		v = strtod( s, &cp ); -		if (*cp != '\0' -#ifdef LATER -				 || v < b->low || v > b->high -#endif -						) { -			wBeep(); -			wFloatSetValue( b, b->oldValue ); -			return; -		} -	} -	b->oldValue = v; -	if (b->valueP != NULL) { -		*b->valueP = v; -	} -	if (b->action) -		gtkSetTrigger( (wControl_p)b, triggerFloat ); -	return; -} - -wFloat_p wFloatCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long	option, -		wPos_t	width, -		double	low, -		double	high, -		double	*valueP, -		wFloatCallBack_p action, -		void 	*data ) -{ -	wFloat_p b; - -	b = (wFloat_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data ); -	b->valueP =  valueP; -	b->action = action; -	b->option = option; -	b->low = low; -	b->high = high; -	gtkComputePos( (wControl_p)b ); - -	b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 ); -	if (b->widget == 0) abort(); - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	if ( width ) -#ifndef GTK1 -		gtk_widget_set_size_request( b->widget, width, -1 ); -#else -		gtk_widget_set_usize( b->widget, width, -1 ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	/*b->w += 4;*/ -	/*b->h += 4;*/ -	if (b->valueP) -		wFloatSetValue( b, *b->valueP ); -	else -		wFloatSetValue( b, b->low>0?b->low:0.0 ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(floatChanged), b ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(floatActivated), b ); -	if (option & BO_READONLY) -		gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE ); -	return b; -} - -/* - ***************************************************************************** - * - * Integer Value Boxes - * - ***************************************************************************** - */ - - -struct wInteger_t { -		WOBJ_COMMON -		long low, high; -		long oldValue; -		long * valueP; -		wIntegerCallBack_p action; -		wBool_t busy; -		}; - - -void wIntegerSetValue( -		wInteger_p b, -		long arg ) -{ -	char message[80]; -	if (b->widget == 0) abort(); -	sprintf( message, "%ld", arg ); -	if (!b->busy) { -		b->busy = TRUE; -		gtk_entry_set_text( GTK_ENTRY(b->widget), message ); -		b->busy = FALSE; -	} -	if (b->valueP) -		*b->valueP = arg; -} - - -long wIntegerGetValue( -		wInteger_p b ) -{ -	long ret; -	const char * cp; -	if (b->widget == 0) abort(); -	cp = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	ret = atol( cp ); -	return ret; -} - - -static void triggerInteger( -		wControl_p b ) -{ -	wInteger_p bi = (wInteger_p)b; -	const char * s; -	char * cp; -	long v; - -	if (b == 0) -		return; -	if (bi->widget == 0) abort(); -	s = gtk_entry_get_text( GTK_ENTRY(bi->widget) ); -	if (debugWindow >= 2) printf("%s text = %s\n", bi->labelStr?bi->labelStr:"No label", s ); -	if (s == NULL)  -		return; -	v = strtol( s, &cp, 10 ); -	if (*cp!=0 || v < bi->low || v > bi->high) -		return; -	/*if (bi->oldValue == v) -		return;*/ -	if (debugWindow >= 2) printf("triggerInteger( %ld )\n", v ); -	bi->oldValue = v; -	if (bi->valueP) -		*bi->valueP = v; -	if (bi->action) { -		bi->busy = TRUE; -		bi->action( v, bi->data ); -		bi->busy = FALSE; -	} -	gtkSetTrigger( NULL, NULL ); -	return; -} - - - -static void integerActivated( -		GtkEntry *widget, -		wInteger_p b ) -{ -	const char * s; -	char * cp; -	long v; -	char val_s[80]; - -	if (b == 0) -		return; -	if (b->widget == 0) abort(); -	s = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s ); -	if (s != NULL) { -		v = strtod( s, &cp ); -		if (*cp != '\n' && *cp != '\0') { -			wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL ); -		} else if (v < b->low || v > b->high) { -			sprintf( val_s, "Please enter a value between %ld and %ld", b->low, b->high ); -			wNoticeEx( NT_ERROR, val_s, "Ok", NULL ); -		} else { -			if (debugWindow >= 2) printf("integerActivated( %ld )\n", v ); -			b->oldValue = v; -			if (b->valueP) -				*b->valueP = v; -			if (b->action) { -				gtkSetTrigger( NULL, NULL ); -				b->busy = TRUE; -				b->action( v, b->data ); -				b->busy = FALSE; -			} -			return; -		} -		sprintf( val_s, "%ld", b->oldValue); -		b->busy = TRUE; -		gtk_entry_set_text( GTK_ENTRY(b->widget), val_s ); -		b->busy = FALSE; -	} -	return; -} - -static void integerChanged( -		GtkEntry *widget, -		wInteger_p b ) -{ -	const char * s; -	char * cp; -	long v; - -	if (b == 0) -		return; -	if (b->widget == 0) abort(); -	if (b->busy) -		return; -	s = gtk_entry_get_text( GTK_ENTRY(b->widget) ); -	if (s == NULL) -		return; -	if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s ); -	if ( s[0] == '\0' || -		 strcmp( s, "-" ) == 0 ) { -		v = 0; -	} else { -		v = strtol( s, &cp, 10 ); -		if (*cp != '\0' -#ifdef LATER -				 || v < b->low || v > b->high -#endif -						) { -			wBeep(); -			wIntegerSetValue( b, b->oldValue ); -			return; -		} -	} -	b->oldValue = v; -	if (b->valueP != NULL) { -		*b->valueP = v; -	} -	if (b->action) -		gtkSetTrigger( (wControl_p)b, triggerInteger ); -	return; -} - -wInteger_p wIntegerCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long	option, -		wPos_t	width, -		long	low, -		long	high, -		long	*valueP, -		wIntegerCallBack_p action, -		void 	*data ) -{ -	wInteger_p b; - -	b = (wInteger_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data ); -	b->valueP =  valueP; -	b->action = action; -	b->option = option; -	b->low = low; -	b->high = high; -	gtkComputePos( (wControl_p)b ); - -	b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 ); -	if (b->widget == 0) abort(); - -#ifndef GTK1 -	gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), b->widget ); -	gtk_widget_set_uposition( b->widget, b->realX, b->realY ); -#endif -	if ( width ) -#ifndef GTK1 -		gtk_widget_set_size_request( b->widget, width, -1 ); -#else -		gtk_widget_set_usize( b->widget, width, -1 ); -#endif -	gtkControlGetSize( (wControl_p)b ); -	if (labelStr) -		b->labelW = gtkAddLabel( (wControl_p)b, labelStr ); -	/*b->w += 4;*/ -	/*b->h += 4;*/ -	if (b->valueP) -		wIntegerSetValue( b, *b->valueP ); -	else -		wIntegerSetValue( b, b->low>0?b->low:0.0 ); -	gtk_widget_show( b->widget ); -	gtkAddButton( (wControl_p)b ); -	gtkAddHelpString( b->widget, helpStr ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(integerChanged), b ); -	gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(integerActivated), b ); -	if (option & BO_READONLY) -		gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE ); -	return b; -} diff --git a/app/wlib/gtklib/gtksplash.c b/app/wlib/gtklib/gtksplash.c deleted file mode 100644 index 0f49774..0000000 --- a/app/wlib/gtklib/gtksplash.c +++ /dev/null @@ -1,142 +0,0 @@ -/** \file gtksplash.c - * Handling of the Splash Window functions - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksplash.c,v 1.5 2009-05-31 14:48:58 m_fischer Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2007 Martin Fischer - * - *  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-1307, USA. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include "gtkint.h" - -#define LOGOFILENAME "logo.bmp" - -static GtkWidget *window;	/** splash window handle */ -static GtkWidget *message;	/** window handle for progress message */ - -/** - * Create the splash window shown during startup. The function loads the logo  - * bitmap and displays the program name and version as passed.  - * - * \param IN  appName the product name to be shown - * \param IN  appVer  the product version to be shown - * \return    TRUE if window was created, FALSE if an error occured - */ - -int -wCreateSplash( char *appName, char *appVer ) -{ -   GtkWidget *vbox; -   GtkWidget *image; -   GtkWidget *label; -	char *temp; -	char logoPath[BUFSIZ]; - -	/* create the basic window */ -   window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -	gtk_window_set_decorated( GTK_WINDOW (window), FALSE ); -   gtk_window_set_title (GTK_WINDOW (window), appName);  -   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); -   gtk_window_set_resizable (GTK_WINDOW (window), FALSE); -   gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); -#if GTK_MINOR_VERSION > 5 -   gtk_window_set_focus_on_map (GTK_WINDOW (window), FALSE); -#endif - -   vbox = gtk_vbox_new (FALSE, 0); -   gtk_widget_show (vbox); -   gtk_container_add (GTK_CONTAINER (window), vbox); - -   /* add the logo image to the top of the splash window */ -   sprintf( logoPath, "%s/" LOGOFILENAME, wGetAppLibDir()); -   image = gtk_image_new_from_file ( logoPath ); -   gtk_widget_show (image); -   gtk_box_pack_start (GTK_BOX (vbox), image, TRUE, TRUE, 0); -   gtk_misc_set_alignment (GTK_MISC (image), 0, 0); - -   /* put the product name into the window */ -	 -	temp = malloc( strlen( appName ) + strlen( appVer ) + 2 ); -	if( !temp ) -		return( FALSE ); -		 -	sprintf( temp, "%s %s", appName, appVer );	 -	 -   label = gtk_label_new ( temp ); -   gtk_widget_show (label); -   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); -   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL); -   gtk_label_set_selectable (GTK_LABEL (label), FALSE); -   gtk_misc_set_padding (GTK_MISC (label), 6, 2); - -	free( temp ); - -   label = gtk_label_new ("Application is starting..."); -   gtk_widget_show (label); -   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); -   gtk_label_set_line_wrap (GTK_LABEL (label), FALSE); -   gtk_misc_set_padding (GTK_MISC (label), 6, 2); -#if GTK_MINOR_VERSION > 5    -   gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START); -#endif    -   message = label;	 - -	gtk_widget_show( window ); -	 -   return( TRUE ); -} - -/** - * Update the progress message inside the splash window - * msg	text message to display - * return nonzero if ok - */  - -int  -wSetSplashInfo( char *msg ) -{ -	if( msg ) { -		gtk_label_set_text( (GtkLabel *)message, msg ); -		wFlush(); -		return TRUE; -	} -	return FALSE; -} - -/** - * Destroy the splash window. - * - */ - -void  -wDestroySplash( void ) -{ -	/* kill window */ -	gtk_widget_destroy( window ); -	return; -} diff --git a/app/wlib/gtklib/gtktext.c b/app/wlib/gtklib/gtktext.c deleted file mode 100644 index e067f43..0000000 --- a/app/wlib/gtklib/gtktext.c +++ /dev/null @@ -1,670 +0,0 @@ -/** \file gtktext.c - * Multi-line Text Boxes - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#define GTK_ENABLE_BROKEN -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include "i18n.h" -#include "gtkint.h" - -/* - * Disable USE_TEXTVIEW to use the deprecated gtk_text - */ -#define USE_TEXTVIEW - - -struct PrintData { -	wText_p	tb; -	gint lines_per_page; -	gdouble font_size;  -	gchar **lines; -	gint total_lines; -	gint total_pages; -}; - -#define HEADER_HEIGHT 20.0 -#define HEADER_GAP 8.5 - -struct wText_t { -		WOBJ_COMMON -		wPos_t width, height; -		int changed; -		GtkWidget * text; -		GtkWidget * vscroll; -		}; - -EXPORT void wTextClear( -		wText_p bt ) -{ -#ifdef USE_TEXTVIEW -	GtkTextBuffer * tb; -#endif -	if (bt->text == 0) abort(); -#ifdef USE_TEXTVIEW -	tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); -	gtk_text_buffer_set_text( tb, "", -1 ); -	if (bt->option & BO_READONLY) -		gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); -#else -	gtk_text_set_point( GTK_TEXT(bt->text), 0 ); -	gtk_text_forward_delete( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) ) ); -	if (bt->option & BO_READONLY) -		gtk_text_set_editable( GTK_TEXT(bt->text), FALSE ); -#endif -	bt->changed = FALSE; -} - -EXPORT void wTextAppend( -		wText_p bt, -		const char * text ) -{ -#ifdef USE_TEXTVIEW -	GtkTextBuffer * tb; -	GtkTextIter ti1, ti2; -#else -	static GdkFont * fixedRegularFont = NULL; -	static GdkFont * fixedBoldFont = NULL; -	static GdkFont * variableRegularFont = NULL; -	static GdkFont * variableBoldFont = NULL; -	GdkFont * regularFont = NULL; -	GdkFont * boldFont = NULL; -#endif -	wBool_t doBold; -	char * cp; -	int len; - -	if (bt->text == 0) abort(); -#ifdef USE_TEXTVIEW -	tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); -#else -	if ((bt->option&BT_FIXEDFONT)) { -		if (fixedRegularFont==NULL) -			fixedRegularFont = gdk_font_load( "-*-courier-medium-r-*-*-12-*-*-*-*-*-iso8859-*" ); -		if (fixedBoldFont==NULL) -			fixedBoldFont = gdk_font_load( "-*-courier-bold-r-*-*-12-*-*-*-*-*-iso8859-*" ); -		regularFont = fixedRegularFont; -		boldFont = fixedBoldFont; -	} else { -		if (variableRegularFont==NULL) -			variableRegularFont = gdk_font_load( "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-*" ); -		if (variableBoldFont==NULL) -			variableBoldFont = gdk_font_load( "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-*" ); -		regularFont = variableRegularFont; -		boldFont = variableBoldFont; -	} -#endif -	/*gtk_text_freeze( GTK_TEXT (bt->text) );*/ -	doBold = FALSE; -	text = gtkConvertInput( text ); -	while ( text && *text ) { -		if ( (bt->option & BT_DOBOLD) != 0 && -			 ( cp = strchr( text, doBold?'>':'<' ) ) != NULL ) { -			len = cp-text; -			cp++; -		} else { -			len = -1; -			cp = NULL; -		} -		if ( len != 0 ) { -#ifdef USE_TEXTVIEW -			gtk_text_buffer_get_bounds( tb, &ti1, &ti2 ); -			if ( !doBold ) -				gtk_text_buffer_insert( tb, &ti2, text, len ); -			else -				gtk_text_buffer_insert_with_tags_by_name( tb, &ti2, text, len, "bold", NULL ); -#else -			gtk_text_insert( GTK_TEXT(bt->text), doBold?boldFont:regularFont, &bt->text->style->black, NULL, text, len ); -#endif -		} -		text = cp; -		doBold = !doBold; -	} -	/*gtk_text_set_point( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) )-1 );*/ -	/*gtk_text_thaw( GTK_TEXT (bt->text) );*/ -	bt->changed = FALSE; -} - -EXPORT void gtkTextFreeze( -		wText_p bt ) -{ -#ifdef USE_TEXTVIEW -	gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); -#else -	gtk_text_freeze( GTK_TEXT (bt->text) ); -#endif -} - -EXPORT void gtkTextThaw( -		wText_p bt ) -{ -#ifdef USE_TEXTVIEW -	gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), TRUE ); -#else -	gtk_text_thaw( GTK_TEXT (bt->text) ); -#endif -} - -EXPORT void wTextReadFile( -		wText_p bt, -		const char * fileName ) -{ -	FILE * f; -	char buff[BUFSIZ+1]; -	if (fileName) { -		f = fopen( fileName, "r" ); -		if (f == NULL) { -			perror( fileName ); -			return; -		} -		while (fgets( buff, sizeof buff, f ) != NULL ) { -			wTextAppend( bt, buff ); -		} -	} -} - - -#ifdef USE_TEXTVIEW -static char * gtkGetText( -		wText_p bt ) -{ -	GtkTextBuffer * tb; -	GtkTextIter ti1, ti2; -	char * cp; -	if (bt->text == 0) abort(); -	tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); -	gtk_text_buffer_get_bounds( tb, &ti1, &ti2 ); -	cp = gtk_text_buffer_get_text( tb, &ti1, &ti2, FALSE ); -	cp = gtkConvertOutput( cp ); -	return cp; -} -#endif - - -EXPORT wBool_t wTextSave( -		wText_p bt, -		const char * fileName ) -{ -#ifndef USE_TEXTVIEW -	int siz, pos, cnt; -#endif -	FILE * f; -	char * cp; - -	f = fopen( fileName, "w" ); -	if (f==NULL) { -		wNoticeEx( NT_ERROR, fileName, "Ok", NULL ); -		return FALSE; -	} -#ifdef USE_TEXTVIEW -	cp = gtkGetText( bt ); -	fwrite( cp, 1, strlen(cp), f ); -	free(cp); -#else -	siz = gtk_text_get_length( GTK_TEXT(bt->text) ); -	pos = 0; -	cnt = BUFSIZ; -	while (pos<siz) { -		if (pos+cnt>siz) -			 cnt = siz-pos; -		cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), pos, pos+cnt ); -		if (cp == NULL) -			break; -		fwrite( cp, 1, cnt, f ); -		free(cp); -		pos += cnt; -	} -#endif -	fclose(f); -	return TRUE; -} -/** - * Begin the printing by retrieving the contents of the text box and - * count the lines of text.  - *  - * \param operation IN the GTK print operation - * \param context IN print context - * \param pd IN data structure for user data - *  - */ -  -static void -begin_print (GtkPrintOperation *operation,  -             GtkPrintContext *context, -             struct PrintData *pd) -{ -	gchar *contents; -	gdouble height; -		 -	contents =  gtkGetText( pd->tb ); -	pd->lines = g_strsplit (contents, "\n", 0); - -	/* Count the total number of lines in the file. */ -	/* ignore the header lines */ -	pd->total_lines = 6; -	while (pd->lines[pd->total_lines] != NULL) -		pd->total_lines++; -   -	/* Based on the height of the page and font size, calculate how many lines can be  -	* rendered on a single page. A padding of 3 is placed between lines as well. -	* Space for page header, table header and footer lines is subtracted from the total size -	*/ -	height = gtk_print_context_get_height (context) - (pd->font_size + 3) - 2 * ( HEADER_HEIGHT + HEADER_GAP ); -	pd->lines_per_page = floor (height / (pd->font_size + 3)); -	pd->total_pages = (pd->total_lines - 1) / pd->lines_per_page + 1; -	gtk_print_operation_set_n_pages (operation, pd->total_pages); -	 -	free( contents ); -} - -/** - * Draw the page, which includes a header with the file name and page number along - * with one page of text with a font of "Monospace 10".  - *  - * \param operation IN the GTK print operation - * \param context IN print context - * \param page_nr IN page to print - * \param pd IN data structure for user data - *  - *  - */ -  -static void -draw_page (GtkPrintOperation *operation, -           GtkPrintContext *context, -           gint page_nr, -           struct PrintData *pd ) -{ -	cairo_t *cr; -	PangoLayout *layout; -	gdouble width, text_height, height; -	gint line, i, text_width, layout_height; -	PangoFontDescription *desc; -	gchar *page_str; - -	cr = gtk_print_context_get_cairo_context (context); -	width = gtk_print_context_get_width (context); -	 -	layout = gtk_print_context_create_pango_layout (context); -	desc = pango_font_description_from_string ("Monospace"); -	pango_font_description_set_size (desc, pd->font_size * PANGO_SCALE); - -	/*  -	 * render the header line with document type parts list on left and -	 * first line of layout title on right  -	 */  -	  -	pango_layout_set_font_description (layout, desc); -	pango_layout_set_text (layout, pd->lines[ 0 ], -1); 	// document type -	pango_layout_set_width (layout, -1); -	pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); -	pango_layout_get_size (layout, NULL, &layout_height); -	text_height = (gdouble) layout_height / PANGO_SCALE; - -	cairo_move_to (cr, 0, (HEADER_HEIGHT - text_height) / 2); -	pango_cairo_show_layout (cr, layout); - -	pango_layout_set_text (layout, pd->lines[ 2 ], -1);		// layout title  -	pango_layout_get_size (layout, &text_width, NULL); -	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); - -	cairo_move_to (cr, width - (text_width / PANGO_SCALE),  -                 (HEADER_HEIGHT - text_height) / 2); -	pango_cairo_show_layout (cr, layout); - -	/* Render the column header */ -	cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP + pd->font_size + 3 ); -	pango_layout_set_text (layout, pd->lines[ 6 ], -1); -	pango_cairo_show_layout (cr, layout); -	cairo_rel_move_to (cr, 0, pd->font_size + 3 ); -	pango_layout_set_text (layout, pd->lines[ 7 ], -1); -	pango_cairo_show_layout (cr, layout); -	 -	/* Render the page text with the specified font and size. */   -	cairo_rel_move_to (cr, 0, pd->font_size + 3 ); -	line = page_nr * pd->lines_per_page + 8; -	for (i = 0; i < pd->lines_per_page && line < pd->total_lines; i++)  -	{ -		pango_layout_set_text (layout, pd->lines[line], -1); -		pango_cairo_show_layout (cr, layout); -		cairo_rel_move_to (cr, 0, pd->font_size + 3); -		line++; -	} - -	/*  -	 * Render the footer line with date on the left and page number  -	 * on the right -	 */ -	pango_layout_set_text (layout, pd->lines[ 5 ], -1); 	// date -	pango_layout_set_width (layout, -1); -	pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); -	pango_layout_get_size (layout, NULL, &layout_height); -	text_height = (gdouble) layout_height / PANGO_SCALE; - -	height = gtk_print_context_get_height (context); -	cairo_move_to (cr, 0, height - ((HEADER_HEIGHT - text_height) / 2)); -	pango_cairo_show_layout (cr, layout); - -	page_str = g_strdup_printf (_("%d of %d"), page_nr + 1, pd->total_pages); // page number -	pango_layout_set_text( layout, page_str, -1 ); -	pango_layout_get_size (layout, &text_width, NULL); -	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); - -	cairo_move_to (cr, width - (text_width / PANGO_SCALE),  -                 height - ((HEADER_HEIGHT - text_height) / 2)); -	pango_cairo_show_layout (cr, layout); - -	g_free (page_str); -	g_object_unref (layout); -	pango_font_description_free (desc); -} - -/** - * Clean up after the printing operation since it is done.  - * - * \param operation IN the GTK print operation - * \param context IN print context - * \param pd IN data structure for user data - *  - *  - */ -static void -end_print (GtkPrintOperation *operation,  -           GtkPrintContext *context, -           struct PrintData *pd) -{ -	g_strfreev (pd->lines); -	free( pd ); -} - -/** - * Print the content of a multi line text box. This function is only used - * for printing the parts list. So it makes some assumptions on the structure - * and the content. Change if the multi line entry is changed. - * The deprecated gtk_text is not supported by this function.  - *  - * Thanks to Andrew Krause's book for a good starting point. - * - * \param bt IN the text field - * \return    TRUE on success, FALSE on error - */ - -EXPORT wBool_t wTextPrint( -		wText_p bt ) -{ -	GtkPrintOperation *operation; -	GtkWidget *dialog; -	GError *error = NULL; -	gint res; -	struct PrintData *data; - -	/* Create a new print operation, applying saved print settings if they exist. */ -	operation = gtk_print_operation_new (); -	WlibApplySettings( operation ); -   -	data = malloc(sizeof( struct PrintData)); -	data->font_size = 10.0; -	data->tb = bt; - -	g_signal_connect (G_OBJECT (operation), "begin_print",  -		                G_CALLBACK (begin_print), (gpointer) data); -	g_signal_connect (G_OBJECT (operation), "draw_page",  -		                G_CALLBACK (draw_page), (gpointer) data); -	g_signal_connect (G_OBJECT (operation), "end_print",  -		                G_CALLBACK (end_print), (gpointer) data); - -	/* Run the default print operation that will print the selected file. */ -	res = gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,  -									GTK_WINDOW(gtkMainW->gtkwin), &error); - -	/* If the print operation was accepted, save the new print settings. */ -	if (res == GTK_PRINT_OPERATION_RESULT_APPLY) -	{ -		WlibSaveSettings( operation ); -	} -	/* Otherwise, report that the print operation has failed. */ -	else if (error) -	{ -		dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),  -                                     GTK_DIALOG_DESTROY_WITH_PARENT, -                                     GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -				                             error->message); -     -		g_error_free (error); -		gtk_dialog_run (GTK_DIALOG (dialog)); -		gtk_widget_destroy (dialog);      -	} -	g_object_unref (operation); -   -	return TRUE; -} - - -EXPORT int wTextGetSize( -		wText_p bt ) -{ -#ifdef USE_TEXTVIEW -	char * cp = gtkGetText( bt ); -	int len = strlen( cp ); -	free( cp ); -	return len; -#else -	return (int)gtk_text_get_length( GTK_TEXT(bt->text) ); -#endif -} - - -EXPORT void wTextGetText( -		wText_p bt, -		char * text, -		int len ) -{ -	char * cp; -#ifdef USE_TEXTVIEW -	cp = gtkGetText(bt); -	strncpy( text, cp, len ); -	free( cp ); -#else -	cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), 0, len ); -	strncpy( text, cp, len ); -#endif -} - - -EXPORT void wTextSetReadonly ( -		wText_p bt, -		wBool_t ro ) -{ -#ifdef USE_TEXTVIEW -	gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), !ro ); -#else -	gtk_text_set_editable( GTK_TEXT(bt->text), !ro ); -#endif -	if (ro) { -		bt->option |= BO_READONLY; -	} else { -		bt->option &= ~BO_READONLY; -	} -} - - -EXPORT wBool_t wTextGetModified( -		wText_p bt ) -{ -	return bt->changed; -} - - -EXPORT void wTextSetSize(  -		wText_p bt, -		wPos_t w, -		wPos_t h ) -{ -#ifdef USE_TEXTVIEW -	gtk_widget_set_size_request( bt->widget, w, h ); -//	gtk_widget_set_size_request( bt->text, w-15, h ); -//	gtk_widget_set_size_request( bt->vscroll, 15, h ); -#else -	gtk_widget_set_usize( bt->widget, w, h ); -	gtk_widget_set_usize( bt->text, w-15, h ); -	gtk_widget_set_usize( bt->vscroll, 15, h ); -	gtk_widget_queue_resize( GTK_WIDGET(bt->widget) ); -	gtk_widget_queue_resize( GTK_WIDGET(bt->text) ); -	gtk_widget_queue_resize( GTK_WIDGET(bt->vscroll) ); -#endif -	bt->w = w; -	bt->h = h; -} - - -EXPORT void wTextComputeSize( -		wText_p bt, -		int rows, -		int cols, -		wPos_t *width, -		wPos_t *height ) -{ -	*width = rows * 7; -	*height = cols * 14; -} - - -EXPORT void wTextSetPosition( -		wText_p bt, -		int pos ) -{ -#ifdef USE_TEXTVIEW -	/* TODO */ -#else -	GTK_TEXT(bt->text)->first_line_start_index = pos; -	gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE ); -	gtk_text_set_point( GTK_TEXT(bt->text), pos ); -#endif -} - -static void textChanged( -		GtkWidget * widget, -		wText_p bt ) -{ -	if (bt == 0) -		return; -	bt->changed = TRUE; -} - - -EXPORT wText_p wTextCreate( -		wWin_p	parent, -		wPos_t	x, -		wPos_t	y, -		const char 	* helpStr, -		const char	* labelStr, -		long	option, -		wPos_t	width, -		wPos_t	height ) -{ -	wText_p bt; -#ifdef USE_TEXTVIEW -	GtkTextBuffer * tb; -#else -	GtkRequisition requisition; -#endif -	bt = gtkAlloc( parent, B_MULTITEXT, x, y, labelStr, sizeof *bt, NULL ); -	gtkComputePos( (wControl_p)bt ); -	bt->width = width; -	bt->height = height; -	bt->option = option; -	gtkComputePos( (wControl_p)bt ); - -#ifdef USE_TEXTVIEW -	bt->widget = gtk_scrolled_window_new (NULL, NULL); -	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bt->widget), -		   	           GTK_POLICY_AUTOMATIC, -				   GTK_POLICY_AUTOMATIC); -	bt->text = gtk_text_view_new(); -	if (bt->text == 0) abort(); -	gtk_container_add (GTK_CONTAINER (bt->widget), bt->text); -	tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); -	gtk_text_buffer_create_tag( tb, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); -/*	gtk_text_buffer_create_tag( tb, "italic", "style", PANGO_STYLE_ITALIC, NULL); */ -/*	gtk_text_buffer_create_tag( tb, "bolditalic", "weight", PANGO_WEIGHT_BOLD, "style", PANGO_STYLE_ITALIC, NULL); */ -	bt->vscroll = gtk_vscrollbar_new( GTK_TEXT_VIEW(bt->text)->vadjustment ); -	if (bt->vscroll == 0) abort(); -#else -	bt->widget = gtk_hbox_new( FALSE, 0 ); -	bt->text = gtk_text_new( NULL, NULL ); -	if (bt->text == 0) abort(); -	gtk_box_pack_start( GTK_BOX(bt->widget), bt->text, FALSE, FALSE, 0 ); -	bt->vscroll = gtk_vscrollbar_new( GTK_TEXT(bt->text)->vadj ); -	if (bt->vscroll == 0) abort(); -	gtk_box_pack_start( GTK_BOX(bt->widget), bt->vscroll, FALSE, FALSE, 0 ); -#endif -	if (option&BT_CHARUNITS) { -		width *= 7; -		height *= 14; -	} -	gtk_widget_show( bt->text ); -	gtk_widget_show( bt->vscroll ); -	gtk_widget_show( bt->widget ); -#ifdef USE_TEXTVIEW -//	gtk_widget_set_size_request( GTK_WIDGET(bt->text), width, height ); -//	gtk_widget_set_size_request( GTK_WIDGET(bt->vscroll), -1, height ); -	gtk_widget_set_size_request( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height ); -#else -	gtk_widget_set_usize( GTK_WIDGET(bt->text), width, height ); -	gtk_widget_set_usize( GTK_WIDGET(bt->vscroll), -1, height ); -	gtk_widget_size_request( GTK_WIDGET(bt->vscroll), &requisition ); -	gtk_widget_set_usize( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height ); -#endif -	if (bt->option&BO_READONLY) { -#ifdef USE_TEXTVIEW -		gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); -		gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(bt->text), FALSE); -#else -		gtk_text_set_editable( GTK_TEXT(bt->text), FALSE ); -#endif -	} - -#ifdef USE_TEXTVIEW -	gtk_fixed_put( GTK_FIXED(parent->widget), bt->widget, bt->realX, bt->realY ); -#else -	gtk_container_add( GTK_CONTAINER(parent->widget), bt->widget ); -	gtk_widget_set_uposition( bt->widget, bt->realX, bt->realY ); -#endif -	gtkControlGetSize( (wControl_p)bt ); -	if (labelStr) -		bt->labelW = gtkAddLabel( (wControl_p)bt, labelStr ); -#ifdef USE_TEXTVIEW -	gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(bt->text), GTK_WRAP_WORD ); -#else -	gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE ); -#endif -	gtk_widget_realize( bt->text ); -	gtkAddButton( (wControl_p)bt ); -	gtkAddHelpString( bt->widget, helpStr ); -#ifdef USE_TEXTVIEW -	g_signal_connect( G_OBJECT(tb), "changed", GTK_SIGNAL_FUNC(textChanged), bt ); -#else -	gtk_signal_connect( GTK_OBJECT(bt->text), "changed", GTK_SIGNAL_FUNC(textChanged), bt ); -#endif -	return bt; -} diff --git a/app/wlib/gtklib/gtkwindow.c b/app/wlib/gtklib/gtkwindow.c deleted file mode 100644 index b86b173..0000000 --- a/app/wlib/gtklib/gtkwindow.c +++ /dev/null @@ -1,856 +0,0 @@ -/** \file gtkwindow.c - * Basic window handling stuff. - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkwindow.c,v 1.12 2010-04-28 04:04:38 dspagnol Exp $ - */ - -/*  XTrkCad - Model Railroad CAD - *  Copyright (C) 2005 Dave Bullis - * - *  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-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <sys/time.h> -#include <signal.h> -#include <unistd.h> -#include <string.h> - -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> - -#include "gtkint.h" - -wWin_p gtkMainW; - -#define FOUR	(4) -#define MENUH	(24) - -#define MIN_WIN_WIDTH (50) -#define MIN_WIN_HEIGHT (50) - -#define SECTIONWINDOWSIZE  "gtklib window size" -#define SECTIONWINDOWPOS   "gtklib window pos" - -extern wBool_t listHelpStrings; -		 -static wControl_p firstWin = NULL, lastWin; -static int keyState; -static wBool_t gtkBlockEnabled = TRUE; - -/* - ***************************************************************************** - * - * Window Utilities - * - ***************************************************************************** - */ - -/** - * Get the window size from the resource (.rc) file.  The size is saved under the key  - * SECTIONWINDOWSIZE.window name - * - * \param win IN window - * \param nameStr IN window name - */ - -static void getWinSize( wWin_p win, const char * nameStr ) -{ -	int w, h; -	const char *cp; -    char *cp1, *cp2; - -	if ( (win->option&F_RESIZE) && -		 (win->option&F_RECALLPOS) && -		 (cp = wPrefGetString( SECTIONWINDOWSIZE, nameStr)) && -		 (w = strtod( cp, &cp1 ), cp != cp1) && -		 (h = strtod( cp1, &cp2 ), cp1 != cp2) ) { -		if (w < 10) -			w = 10; -		if (h < 10) -			h = 10; -		win->w = win->origX = w; -		win->h = win->origY = h; -		win->option &= ~F_AUTOSIZE; -	} -} - -/** - * Save the window size to the resource (.rc) file.  The size is saved under the key  - * SECTIONWINDOWSIZE.window name - * - * \param win IN window - */ - -static void saveSize( wWin_p win ) -{ -	char pos_s[20]; -	if ( (win->option&F_RESIZE) && -		 (win->option&F_RECALLPOS) && -		 GTK_WIDGET_VISIBLE( GTK_WIDGET(win->gtkwin) ) ) { -		sprintf( pos_s, "%d %d", win->w, win->h-(FOUR + ((win->option&F_MENUBAR)?MENUH:0) ) ); -		wPrefSetString( SECTIONWINDOWSIZE, win->nameStr, pos_s ); -	} -} - -/** - * Get the window position from the resource (.rc) file.  The position is saved under the key  - * SECTIONWINDOWPOS.window name - * - * \param win IN window - */ - -static void getPos( wWin_p win ) -{ -	int x, y; -	const char *cp; -    char *cp1, *cp2; -	wPos_t gtkDisplayWidth = gdk_screen_width(); -	wPos_t gtkDisplayHeight = gdk_screen_height(); - -	if ( (win->option&F_RECALLPOS) && -			(!win->shown) ) { -		if ((cp = wPrefGetString( SECTIONWINDOWPOS, win->nameStr))) { -			x = strtod( cp, &cp1 ); -			if (cp == cp1) -				return; -			y = strtod( cp1, &cp2 ); -			if (cp2 == cp1) -				return; -			if ( y > gtkDisplayHeight-win->h ) -				y = gtkDisplayHeight-win->h; -			if ( x > gtkDisplayWidth-win->w ) -				x = gtkDisplayWidth-win->w; -			if ( x <= 0 ) -				x = 1; -			if ( y <= 0 ) -				y = 1; -			gtk_window_move( GTK_WINDOW(win->gtkwin), x, y ); -			gtk_window_resize( GTK_WINDOW(win->gtkwin), win->w, win->h ); -		} -	} -} - -/** - * Save the window position to the resource (.rc) file.  The position is saved under the key  - * SECTIONWINDOWPOS.window name - * - * \param win IN window - */ - -static void savePos( wWin_p win ) -{ -	int x, y; -	char pos_s[20]; -	if ( (win->option&F_RECALLPOS) ) { -		gdk_window_get_position( GTK_WIDGET(win->gtkwin)->window, &x, &y ); -		x -= 5; -		y -= 25; -		sprintf( pos_s, "%d %d", x, y ); -		wPrefSetString( SECTIONWINDOWPOS, win->nameStr, pos_s ); -	} -} - -/** - * Returns the dimensions of <win>. - * - * \param win IN window handle - * \param width OUT width of window - * \param height OUT height of window minus menu bar size - */ - -EXPORT void wWinGetSize( -		wWin_p win,		/* Window */ -		wPos_t * width,		/* Returned window width */ -		wPos_t * height )	/* Returned window height */ -{ -	GtkRequisition requisition; -	wPos_t w, h; -	gtk_widget_size_request( win->gtkwin, &requisition ); -	w = win->w; -	h = win->h; -	if ( win->option&F_AUTOSIZE ) { -		if ( win->realX > w ) -			w = win->realX; -		if ( win->realY > h ) -			h = win->realY; -	} -	*width = w; -	*height = h - FOUR - ((win->option&F_MENUBAR)?MENUH:0); -} - -/** - * Sets the dimensions of <w> to <widht> and <height>. - * - * \param win IN window - * \param width IN new width - * \param height IN new height - */ - -EXPORT void wWinSetSize( -		wWin_p win,		/* Window */ -		wPos_t width,		/* Window width */ -		wPos_t height )		/* Window height */ -{ -	win->busy = TRUE; -	win->w = width; -	win->h = height + FOUR + ((win->option&F_MENUBAR)?MENUH:0); -	gtk_widget_set_size_request( win->gtkwin, win->w, win->h ); -	gtk_widget_set_size_request( win->widget, win->w, win->h );  -	win->busy = FALSE; - -} - -/** - * Shows or hides window <win>. If <win> is created with 'F_BLOCK' option then the applications other - * windows are disabled and 'wWinShow' doesnot return until the window <win> is closed by calling  - * 'wWinShow(<win>,FALSE)'. - * - * \param win IN window - * \param show IN visibility state - */ - -EXPORT void wWinShow( -		wWin_p win,		/* Window */ -		wBool_t show )		/* Command */ -{ -	GtkRequisition requisition; -	if (debugWindow >= 2) printf("Set Show %s\n", win->labelStr?win->labelStr:"No label" ); -	if (win->widget == 0) abort(); -	if (show) { -		keyState = 0; -		getPos( win ); -		if ( win->option & F_AUTOSIZE ) { -			gtk_widget_size_request( win->gtkwin, &requisition ); -			if ( requisition.width != win->w || requisition.height != win->h ) { -				gtk_widget_set_size_request( win->gtkwin, win->w, win->h ); -				gtk_widget_set_size_request( win->widget, win->w, win->h ); -				if (win->option&F_MENUBAR) { -					gtk_widget_set_size_request( win->menubar, win->w, MENUH ); -				} -			} -		} -		if ( !win->shown ) { -			gtk_widget_show( win->gtkwin ); -			gtk_widget_show( win->widget ); -		} -		gdk_window_raise( win->gtkwin->window ); -		if ( win->shown && win->modalLevel > 0 ) -			gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), TRUE ); -		win->shown = show; -		win->modalLevel = 0; - -		if ( (!gtkBlockEnabled) || (win->option & F_BLOCK) == 0) { -			wFlush(); -		} else { -			gtkDoModal( win, TRUE ); -		} -	} else { -		wFlush(); -		saveSize( win ); -		savePos( win ); -		win->shown = show; -		if ( gtkBlockEnabled && (win->option & F_BLOCK) != 0) { -			gtkDoModal( win, FALSE ); -		} -		gtk_widget_hide( win->gtkwin ); -		gtk_widget_hide( win->widget ); -	} -} - -/** - * Block windows against user interactions. Done during demo mode etc. - * - * \param enabled IN blocked if TRUE - */ - -EXPORT void wWinBlockEnable( -		wBool_t enabled ) -{ -	gtkBlockEnabled = enabled; -} - -/** - * Returns whether the window is visible. - * - * \param win IN window - * \return    TRUE if visible, FALSE otherwise - */ - -EXPORT wBool_t wWinIsVisible( -		wWin_p win ) -{ -	return win->shown; -} - -/** - * Sets the title of <win> to <title>. - * - * \param varname1 IN window - * \param varname2 IN new title - */ - -EXPORT void wWinSetTitle( -		wWin_p win,		/* Window */ -		const char * title )		/* New title */ -{ -	gtk_window_set_title( GTK_WINDOW(win->gtkwin), title ); -} - -/** - * Sets the window <win> to busy or not busy. Sets the cursor accordingly - * - * \param varname1 IN window - * \param varname2 IN TRUE if busy, FALSE otherwise - */ - -EXPORT void wWinSetBusy( -		wWin_p win,		/* Window */ -		wBool_t busy )		/* Command */ -{ -	GdkCursor * cursor; -	if (win->gtkwin == 0) abort(); -	if ( busy ) -		cursor = gdk_cursor_new ( GDK_WATCH ); -	else -		cursor = NULL; -	gdk_window_set_cursor (win->gtkwin->window, cursor); -	if ( cursor ) -		gdk_cursor_destroy (cursor);    -	gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), busy==0 ); -} - - -EXPORT void gtkDoModal( -		wWin_p win0, -		wBool_t modal ) -{ -	wWin_p win; -	for ( win=(wWin_p)firstWin; win; win=(wWin_p)win->next ) { -		if ( win->shown && win != win0 ) { -			if ( modal ) { -				if ( win->modalLevel == 0 ) -					gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), FALSE ); -				win->modalLevel++; -			} else { -				if ( win->modalLevel > 0 ) { -					win->modalLevel--; -					if ( win->modalLevel == 0 ) -						gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), TRUE ); -				} -			} -			if ( win->modalLevel < 0 ) { -				fprintf( stderr, "DoModal: %s modalLevel < 0", win->nameStr?win->nameStr:"<NULL>" ); -				abort(); -			} -		} -	} -	if ( modal ) { -		gtk_main(); -	} else { -		gtk_main_quit(); -	} -} - -/** - * Returns the Title of <win>. - * - * \param win IN window - * \return    pointer to window title - */ - -EXPORT const char * wWinGetTitle( -	 wWin_p win )			/* Window */ -{ -	return win->labelStr; -} - - -EXPORT void wWinClear( -		wWin_p win, -		wPos_t x, -		wPos_t y, -		wPos_t width, -		wPos_t height ) -{ -} - - -EXPORT void wWinDoCancel( -		wWin_p win ) -{ -	wControl_p b; -	for (b=win->first; b; b=b->next) { -		if ((b->type == B_BUTTON) && (b->option & BB_CANCEL) ) { -			gtkButtonDoAction( (wButton_p)b ); -		} -	} -} - -/* - ****************************************************************************** - * - * Call Backs - * - ****************************************************************************** - */ - -static gint window_delete_event( -		GtkWidget *widget, -		GdkEvent *event, -		wWin_p win ) -{ -	wControl_p b; -	/* if you return FALSE in the "delete_event" signal handler, -	 * GTK will emit the "destroy" signal.  Returning TRUE means -	 * you don't want the window to be destroyed. -	 * This is useful for popping up 'are you sure you want to quit ?' -	 * type dialogs. */ - -	/* Change TRUE to FALSE and the main window will be destroyed with -	 * a "delete_event". */ - -	for ( b = win->first; b; b=b->next ) -		if (b->doneProc) -			b->doneProc( b ); -	if (win->winProc) { -		win->winProc( win, wClose_e, win->data ); -		if (win != gtkMainW) -			wWinShow( win, FALSE ); -	} -	return (TRUE); -} - -static int window_redraw( -		wWin_p win, -		wBool_t doWinProc ) -{ -	wControl_p b; - -	if (win==NULL) -		return FALSE; - -	for (b=win->first; b != NULL; b = b->next) { -		if (b->repaintProc) -			b->repaintProc( b ); -	} - -	return FALSE; -} - -static int fixed_expose_event( -		GtkWidget * widget, -		GdkEventExpose * event, -		wWin_p win ) -{ -	if (event->count==0) -		return window_redraw( win, TRUE ); -	else -		return FALSE; -} - -static int window_configure_event( -		GtkWidget * widget, -		GdkEventConfigure * event, -		wWin_p win ) -{ -	wPos_t h; - -	if (win==NULL) -		return FALSE; - -	h = event->height - FOUR; -	if (win->option&F_MENUBAR) -		h -= MENUH; -	if (win->option&F_RESIZE) { -		if ( event->width < 10 || event->height < 10 ) -			return TRUE; -		if (win->w != event->width || win->h != event->height) { -			win->w = event->width; -			win->h = event->height; -			if ( win->w < MIN_WIN_WIDTH ) -				win->w = MIN_WIN_WIDTH; -			if ( win->h < MIN_WIN_HEIGHT ) -				win->h = MIN_WIN_HEIGHT; -			if (win->option&F_MENUBAR) -				gtk_widget_set_size_request( win->menubar, win->w, MENUH );  - -			if (win->busy==FALSE && win->winProc) { -				win->winProc( win, wResize_e, win->data ); -			} -		} -	}  -	return FALSE; -} - -/** - * Get current state of shift, ctrl or alt keys. - * - * \return    or'ed value of WKEY_SHIFT, WKEY_CTRL and WKEY_ALT depending on state - */ - -int wGetKeyState( void ) -{ -	return keyState; -} - -wBool_t catch_shift_ctrl_alt_keys( -		GtkWidget * widget, -		GdkEventKey *event, -		void * data ) -{ -	int state; - -	state = 0; -	switch (event->keyval) { -	case GDK_Shift_L: -	case GDK_Shift_R: -		state |= WKEY_SHIFT; -		break; -	case GDK_Control_L: -	case GDK_Control_R: -		state |= WKEY_CTRL; -		break; -	case GDK_Alt_L: -	case GDK_Alt_R: -		state |= WKEY_ALT; -		break; -	} -	if ( state != 0 ) { -		if (event->type == GDK_KEY_PRESS) -			keyState |= state; -		else -			keyState &= ~state; -		return TRUE; -	} -	return FALSE; -} -		 -static gint window_char_event( -		GtkWidget * widget, -		GdkEventKey *event, -		wWin_p win ) -{ -	wControl_p bb; -	if ( catch_shift_ctrl_alt_keys( widget, event, win ) ) -		return FALSE; -	if (event->type == GDK_KEY_RELEASE) -		return FALSE; - -	if ( event->state == 0 ) { -		if ( event->keyval == GDK_Escape ) { -			for ( bb=win->first; bb; bb=bb->next ) { -				if ( bb->type == B_BUTTON && (bb->option&BB_CANCEL) ) { -					gtkButtonDoAction( (wButton_p)bb ); -					return TRUE; -				} -			} -		} -	} -	if ( gtkHandleAccelKey( event ) ) { -		return TRUE; -	} else { -		return FALSE; -	} -} - - -/* - ******************************************************************************* - * - * Main and Popup Windows - * - ******************************************************************************* - */ - - - -static wWin_p wWinCommonCreate( -		wWin_p parent, -		int winType, -		wPos_t x, -		wPos_t y, -		const char * labelStr, -		const char * nameStr, -		long option, -		wWinCallBack_p winProc, -		void * data ) -{ -	wWin_p w; -	int h; - -	w = gtkAlloc( NULL, winType, x, y, labelStr, sizeof *w, data ); -	w->busy = TRUE; -	w->option = option; -	getWinSize( w, nameStr ); - -	h = FOUR; -	if (w->option&F_MENUBAR) -		h += MENUH; - -	if ( winType == W_MAIN ) { -		w->gtkwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); -	} else { -		w->gtkwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); -		if ( gtkMainW ) -			gtk_window_set_transient_for( GTK_WINDOW(w->gtkwin), GTK_WINDOW(gtkMainW->gtkwin) ); -	} -	 -	if( option & F_HIDE ) -		gtk_widget_hide( w->gtkwin ); - -	/* center window on top of parent window */ -	if( option & F_CENTER ) -		gtk_window_set_position(GTK_WINDOW(w->gtkwin), GTK_WIN_POS_CENTER_ON_PARENT ); -				 -	w->widget = gtk_fixed_new(); -	if (w->widget == 0) abort(); - -	if (w->option&F_MENUBAR) { -		w->menubar = gtk_menu_bar_new(); -		gtk_container_add( GTK_CONTAINER(w->widget), w->menubar ); -		gtk_widget_show( w->menubar ); -		gtk_widget_set_size_request( w->menubar, -1, MENUH ); -	} - -	gtk_container_add( GTK_CONTAINER(w->gtkwin), w->widget ); - -	if (w->option&F_AUTOSIZE) { -		w->realX = 0; -		w->w = 0; -		w->realY = h; -		w->h = 0; -	} else { -		w->w = w->realX = w->origX; -		w->h = w->realY = w->origY+h; -		gtk_widget_set_size_request( w->gtkwin, w->w, w->h ); -		gtk_widget_set_size_request( w->widget, w->w, w->h ); -		if (w->option&F_MENUBAR) { -			gtk_widget_set_size_request( w->menubar, w->w, MENUH ); -		} -	} - -	w->first = w->last = NULL; - -	w->winProc = winProc; - -	gtk_signal_connect (GTK_OBJECT (w->gtkwin), "delete_event", -						GTK_SIGNAL_FUNC (window_delete_event), w); -	gtk_signal_connect (GTK_OBJECT (w->widget), "expose_event", -						GTK_SIGNAL_FUNC (fixed_expose_event), w); -	gtk_signal_connect (GTK_OBJECT (w->gtkwin), "configure_event", -						GTK_SIGNAL_FUNC (window_configure_event), w);  -	gtk_signal_connect (GTK_OBJECT (w->gtkwin), "key_press_event", -						GTK_SIGNAL_FUNC (window_char_event), w); -	gtk_signal_connect (GTK_OBJECT (w->gtkwin), "key_release_event", -						GTK_SIGNAL_FUNC (window_char_event), w); -	gtk_widget_set_events (w->widget, GDK_EXPOSURE_MASK ); -	gtk_widget_set_events ( GTK_WIDGET(w->gtkwin), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK ); - -	/** -     * \todo { set_policy is deprecated and should be replaced by set_resizable. In order to do that -     * the library has to be cleared up from calls to set_size_request as these set the minimum widget size  -     * to the current size preventing the user from re-sizing the window to a smaller size. At least this -     * is my current assumption ;-) } -     */ -	if (w->option & F_RESIZE) { -		gtk_window_set_policy( GTK_WINDOW(w->gtkwin), TRUE, TRUE, TRUE ); -//		gtk_window_set_resizable( GTK_WINDOW(w->gtkwin), TRUE ); -	} else { -//		gtk_window_set_resizable( GTK_WINDOW(w->gtkwin), FALSE ); -		gtk_window_set_policy( GTK_WINDOW(w->gtkwin), FALSE, FALSE, TRUE ); -	} -	 -	w->lastX = 0; -	w->lastY = h; -	w->shown = FALSE; -	w->nameStr = nameStr?strdup( nameStr ):NULL; -	if (labelStr) -		gtk_window_set_title( GTK_WINDOW(w->gtkwin), labelStr ); -	if (listHelpStrings) -		printf( "WINDOW - %s\n", nameStr?nameStr:"<NULL>" ); - -	if (firstWin) { -		lastWin->next = (wControl_p)w; -	} else { -		firstWin = (wControl_p)w; -	} -	lastWin = (wControl_p)w; -	gtk_widget_show( w->widget ); -	gtk_widget_realize( w->gtkwin ); - -	w->busy = FALSE; -	return w; -} - -/** - * \todo { investigate and implement this function for setting the correct icon as necessary. - * It looks like these functions are never called at the moment. } - */ - -EXPORT void wWinSetBigIcon( -		wWin_p win,		/* Main window */ -		wIcon_p ip )		/* The icon */ -/* -Create an Icon from a X-bitmap. -*/ -{ -#ifdef LATER -	GdkPixmap * pixmap; -	GdkBitmap * mask; -	pixmap = gtkMakeIcon( win->gtkwin, ip, &mask ); -	gdk_window_set_icon( win->gtkwin->window, NULL, pixmap, mask ); -	gdk_pixmap_unref( pixmap ); -	gdk_bitmap_unref( mask ); -#endif -} - - -/** - * \todo { investigate and implement this function for setting the correct icon as necessary. - * It looks like these functions are never called at the moment. } - */ - - -EXPORT void wWinSetSmallIcon( -		wWin_p win,		/* Main window */ -		wIcon_p ip )		/* The icon */ -/* -Create an Icon from a X-bitmap. -*/ -{ -	GdkBitmap * mask; -	if ( ip->gtkIconType == gtkIcon_bitmap ) { -		mask = gdk_bitmap_create_from_data( win->gtkwin->window, ip->bits, ip->w, ip->h ); -		gdk_window_set_icon( win->gtkwin->window, NULL, mask, mask ); -		/*gdk_bitmap_unref( mask );*/ -	} -} - -/** - * Initialize the application's main window. This function does the necessary initialization  - * of the application including creation of the main window. - * - * \param name IN internal name of the application. Used for filenames etc.  - * \param x    IN Initial window width - * \param y    IN Initial window height - * \param helpStr IN Help topic string - * \param labelStr IN window title - * \param nameStr IN Window name - * \param option IN options for window creation - * \param winProc IN pointer to main window procedure - * \param data IN User context - * \return    window handle or NULL on error - */ - -EXPORT wWin_p wWinMainCreate( -		const char * name,		/* Application name */ -		wPos_t x,				/* Initial window width */ -		wPos_t y,				/* Initial window height */ -		const char * helpStr,	/* Help topic string */ -		const char * labelStr,	/* Window title */ -		const char * nameStr,	/* Window name */ -		long option,			/* Options */ -		wWinCallBack_p winProc,	/* Call back function */ -		void * data )			/* User context */ -{ -	char *pos; - -	if( pos = strchr( name, ';' )) { -		/* if found, split application name and configuration name */ -		strcpy( wConfigName, pos + 1 ); -	} else { -		/* if not found, application name and configuration name are same */ -		strcpy( wConfigName, name ); -	} - -	gtkMainW = wWinCommonCreate( NULL, W_MAIN, x, y, labelStr, nameStr, option, winProc, data ); - -	wDrawColorWhite = wDrawFindColor( 0xFFFFFF ); -	wDrawColorBlack = wDrawFindColor( 0x000000 ); - -	gdk_window_set_group( gtkMainW->gtkwin->window, gtkMainW->gtkwin->window ); -	return gtkMainW; -} - -/** - * Create a new popup window. - * - * \param parent IN Parent window (may be NULL) - * \param x IN Initial window width - * \param y IN Initial window height - * \param helpStr IN Help topic string - * \param labelStr IN Window title - * \param nameStr IN Window name - * \param option IN Options - * \param winProc IN call back function - * \param data IN User context information - * \return    handle for new window - */ - -EXPORT wWin_p wWinPopupCreate( -		wWin_p parent,		 -		wPos_t x,		 -		wPos_t y,		 -		const char * helpStr, -		const char * labelStr, -		const char * nameStr, -		long option,	 -		wWinCallBack_p winProc, -		void * data )		 -{ -	wWin_p win; - -	if (parent == NULL) { -		if (gtkMainW == NULL) -			abort(); -		parent = gtkMainW; -	} -	win = wWinCommonCreate( parent, W_POPUP, x, y, labelStr, nameStr, option, winProc, data ); -	gdk_window_set_group( win->gtkwin->window, gtkMainW->gtkwin->window ); - -	return win; -} - - -/** - * Terminates the applicaton with code <rc>. Before closing the main window - * call back is called with wQuit_e. The program is terminated without exiting - * the main message loop. - * - * \param rc IN exit code - * \return    never returns - */ - - -EXPORT void wExit( -		int rc )		/* Application return code */ -{ -	wWin_p win; -	for ( win = (wWin_p)firstWin; win; win = (wWin_p)win->next ) { -		if ( GTK_WIDGET_VISIBLE( GTK_WIDGET(win->gtkwin) ) ) { -			saveSize( win ); -			savePos( win ); -		} -	} -	wPrefFlush(); -	if (gtkMainW && gtkMainW->winProc != NULL) -		gtkMainW->winProc( gtkMainW, wQuit_e, gtkMainW->data ); -	 -	exit( rc ); -} diff --git a/app/wlib/gtklib/gtkxpm.c b/app/wlib/gtklib/gtkxpm.c deleted file mode 100644 index 54ce5a6..0000000 --- a/app/wlib/gtklib/gtkxpm.c +++ /dev/null @@ -1,173 +0,0 @@ -/** \file gtkxpm.c - * XPM creation functions - */ - -/*  XTrackCad - Model Railroad CAD - *  Copyright (C) 2015 Martin Fischer - * - *  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-1307, USA. - */ - - #include <stdio.h> -#include <stdlib.h> -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif -#include <string.h> - -#include <gtk/gtk.h> -#include "gtkint.h" - - #include "uthash.h" - -struct xpmColTable { -		int color; 	          	/* color value (rgb) */ -		char name[ 5 ];       	/* corresponding character representation */ -		UT_hash_handle hh; 	/* makes this structure hashable */ -}; - -static struct xpmColTable *colTable = NULL; - -// must be 64 chars long -static char colVal[] = ".*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -//struct wDraw_t { -		//WOBJ_COMMON -		//void * context; -		//wDrawActionCallBack_p action; -		//wDrawRedrawCallBack_p redraw; - -		//double dpi; - -		//GdkGC * gc; -		//wDrawWidth lineWidth; -		//wDrawOpts opts; -		//wPos_t maxW; -		//wPos_t maxH; -		//unsigned long lastColor; -		//wBool_t lastColorInverted; -		//const char * helpStr; - -		//wPos_t lastX; -		//wPos_t lastY; - -		//wBool_t delayUpdate; -		//}; - - /** - * Export as XPM bitmap file. During creation of the color table, a 4 byte color - * encoding is assumed and a table created accordingly. Once the whole picture has been scanned - * the correct number ist known. When writing to disk only the needed number of bytes per entry - * is written. - * This routine was heavily inspired by on implementation for TK written by Jan Nijtmans. - * - * \param d IN the drawing area ? - * \param fileName IN  fully qualified filename for the bitmap file. - * \return    TRUE on success, FALSE on error - */ - -wBool_t wBitMapWriteFile(       wDraw_p d, const char * fileName ) -{ -	GdkImage * image; -	gint x, y; -	guint32 pixel; -	FILE * f; -	int cc = 0; -	struct xpmColTable	 *ct,  *tmp; -	int numChars; - -	image = gdk_image_get( (GdkWindow*)d->pixmap, 0, 0, d->w, d->h ); -	if (!image) { -		wNoticeEx( NT_ERROR, "WriteBitMap: image_get failed", "Ok", NULL ); -		return FALSE; -	} - -	f = fopen( fileName, "w" ); -	if (!f) { -		perror( fileName ); -		return FALSE; -	} -	fprintf( f, "/* XPM */\n" ); -	fprintf( f, "static char * xtrkcad_bitmap[] = {\n" ); -	fprintf( f, "/* width height num_colors chars_per_pixel */\n" ); - -	// count colors used and create the color table in the same pass -	for( y = 0; y < d->h;y ++ ) { -		for (x = 0; x < d->w; x++ ) { - -			pixel = gdk_image_get_pixel( image, x, y ); -			//check whether color is new - -			HASH_FIND(hh, colTable, &pixel, sizeof( guint32 ), ct); -			if( !ct ) { -				// not found previously, so add a new color table entry -				int i; -				int c; - -				ct = malloc( sizeof( struct xpmColTable ) ); -				ct->name[ 4 ] = '\0'; -				for( i = 3, c = cc; i >= 0; i--, c>>=6 ) { -					(ct->name)[ i ] = colVal[ c &  0x3F ]; -				} -				ct->color = pixel; - -				HASH_ADD(hh, colTable, color, sizeof( guint32 ), ct); -				cc++; -			} -		} -	} - -	// calculate how many characters are needed for the color table -	numChars = 1; -	if( cc > 0x3ffff ) { -		numChars = 4; -	} else { -		if( cc > 0xfff ) { -			numChars = 3; -		} else { -			if( cc > 0x3f ) { -				numChars = 2; -			} -		} -	} -	// print color table -	fprintf( f, "\"%d %d %d %d\"\n", d->w, d->h, cc, numChars ); -	fprintf( f, "/* colors */\n" ); -	for( ct = colTable; ct != NULL; ct = ct->hh.next ) -		fprintf( f, "\"%s c #%6.6x\",\n", (ct->name) + (4 - numChars ), ct->color ); - -	// print the pixels -	fprintf( f, "/* pixels */\n" ); -	for ( y=0; y<d->h; y++ ) { -		fprintf( f, "\"" ); -		for ( x=0; x<d->w; x++ ) { -			pixel = gdk_image_get_pixel( image, x, y ); -			HASH_FIND( hh, colTable, &pixel, sizeof(guint32), ct ); -			fputs( (ct->name) + (4 - numChars ), f ); -		} -		fprintf( f, "\"%s\n", (y<d->h-1)?",":"" ); -	} - -	// delete the hash and free the content -	HASH_ITER(hh, colTable, ct, tmp) { -		HASH_DEL(colTable,ct); -		free(ct); -	} - -	gdk_image_destroy( image ); -	fprintf( f, "};\n" ); -	fclose( f ); -	return TRUE; -} diff --git a/app/wlib/gtklib/help.c b/app/wlib/gtklib/help.c new file mode 100644 index 0000000..dbb69f6 --- /dev/null +++ b/app/wlib/gtklib/help.c @@ -0,0 +1,69 @@ +/** \file help.c + * main help function + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis and (C) 2007 Martin Fischer + * + *  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-1307, USA. + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +#include "i18n.h" + +/** + * Handle the commands issued from the Help drop-down. Currently, we only have a table + * of contents, but search etc. might be added in the future. + * + * \param data IN command value + * + */ + +static void +DoHelpMenu(void *data) +{ +    int func = (intptr_t)data; + +    switch (func) { +    case 1: +        wHelp("index"); +        break; + +    default: +        break; +    } + +    return; +} + +/** + * Add the entries for Help to the drop-down. + * + * \param m IN handle of drop-down + * + */ + +void wMenuAddHelp(wMenu_p m) +{ +    wMenuPushCreate(m, NULL, _("&Contents"), 0, DoHelpMenu, (void*)1); +} diff --git a/app/wlib/gtklib/ixhelp.c b/app/wlib/gtklib/ixhelp.c new file mode 100644 index 0000000..6d85b2b --- /dev/null +++ b/app/wlib/gtklib/ixhelp.c @@ -0,0 +1,441 @@ +/** \file ixhelp.c + * use the Webkit2-based help system + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2015 Martin Fischer + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <dirent.h> +#include <sys/time.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> + +#include <stdint.h> + +#include "gtkint.h" +#include "i18n.h" + +#include <webkit/webkit.h> + +#include "gtkint.h" +#include "i18n.h" + +void load_into_view(char *file, +                    int requested_view);	// Prototype to please clang. + +/* globals and defines related to the HTML help window */ + +#define  HTMLERRORTEXT "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=US-ASCII\">" \ +								"<title>Help Error</title><body><h1>Error - help information can not be found.</h1><p>" \ +								"The help information you requested cannot be found on this system.<br><pre>%s: %s</pre><p>" \ +								"Usually this is an installation problem, Make sure that XTrackCAD and the included " \ +								"HTML files are installed properly and can be found via the XTRKCADLIB environment " \ +								"variable. Also make sure that the user has sufficient access rights to read these" \ + 								"files.</p></body></html>" + + +#define SLIDERPOSDEFAULT 180		/**< default value for slider position */ + +#define HTMLHELPSECTION    "gtklib html help" /**< section name for html help window preferences */ +#define SLIDERPREFNAME	   "sliderpos"    	 /**< name for the slider position preference */ +#define WINDOWPOSPREFNAME  "position"  		 /**< name for the window position preference */ +#define WINDOWSIZEPREFNAME "size"   			 /**< name for the window size preference */ + +#define BACKBUTTON "back" +#define FORWARDBUTTON "forward" +#define HOMEBUTTON "home" +#define CONTENTBUTTON "contents" +#define TOCDOC "tocDoc" +#define CONTENTSDOC "contentsDoc" +#define TOCVIEW "viewLeft" +#define CONTENTSVIEW "viewRight" +#define PANED "hpane" + +enum pane_views { MAIN_VIEW, CONTENTS_VIEW }; + +static char *directory;				/**< base directory for HTML files */ + +static GtkWidget *wHelpWindow;	/**< handle for the help window */ +static GtkWidget *main_view; /** handle for the help main data pane */ +static GtkWidget *contents_view; /** handle for the help contents pane */ + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ +  g_object_set_data_full (G_OBJECT (component), name, \ +    gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ +  g_object_set_data (G_OBJECT (component), name, widget) + +static GtkWidget* +lookup_widget(GtkWidget *widget, const gchar *widget_name) +{ +    GtkWidget *parent, *found_widget; + +    for (;;) { +        if (GTK_IS_MENU(widget)) { +            parent = gtk_menu_get_attach_widget(GTK_MENU(widget)); +        } else { +            parent = widget->parent; +        } + +        if (!parent) { +            parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey"); +        } + +        if (parent == NULL) { +            break; +        } + +        widget = parent; +    } + +    found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget), +                   widget_name); + +    if (!found_widget) { +        g_warning("Widget not found: %s", widget_name); +    } + +    return found_widget; +} + + + + +/** + * create a new horizontal pane and place it into container. + * The separator position is read from the resource configuration and set accordingly. + * Also a callback is specified that will be executed when the slider has been moved. + * + * \PARAM container IN the container into which the pane will be stuffed. + * \PARAM property IN the name of the property for the slider position + * + * \return the HPaned handle + */ + +GtkWidget * +CreateHPaned(GtkBox *container, char *property) +{ +    GtkWidget *hpaned; +    long posSlider; + +    /* the horizontal slider */ +    hpaned = gtk_hpaned_new(); +    gtk_container_set_border_width(GTK_CONTAINER(hpaned), 6); + +    wPrefGetInteger(HTMLHELPSECTION, SLIDERPREFNAME, &posSlider, SLIDERPOSDEFAULT); +    gtk_paned_set_position(GTK_PANED(hpaned), (int)posSlider); + +    /* pack the horizontal slider into the main window */ +    gtk_box_pack_start(container, hpaned, TRUE, TRUE, 0); +    gtk_widget_show(hpaned); + +    return (hpaned); +} + +/** + * Handler for the delete-event issued on the help window.We are saving window + * information (eg. position) and are hiding the window instead of closing it. + * + * \PARAM win IN the window to be destroyed + * \PARAM event IN unused + * \PARAM ptr IN unused + * + * \RETURN FALSE + */ + +static gboolean +DestroyHelpWindow(GtkWidget *win, GdkEvent *event, void *ptr) +{ +    int i; +    GtkWidget *widget; +    char tmp[ 20 ]; + +    gint x, y; + +    /* get the slider position and save it */ +    widget = lookup_widget(win, PANED); +    i = gtk_paned_get_position(GTK_PANED(widget)); +    wPrefSetInteger(HTMLHELPSECTION, SLIDERPREFNAME, i); + +    /* get the window position */ +    gtk_window_get_position((GtkWindow *)win, &x, &y); +    sprintf(tmp, "%d %d", x, y); +    wPrefSetString(HTMLHELPSECTION, WINDOWPOSPREFNAME, tmp); + +    /* get the window size */ +    gtk_window_get_size((GtkWindow *)win , &x, &y); +    sprintf(tmp, "%d %d", x, y); +    wPrefSetString(HTMLHELPSECTION, WINDOWSIZEPREFNAME, tmp); + +    gtk_widget_hide(win); +    return TRUE; +} + +void back_button_clicked(GtkWidget *widget, gpointer data) +{ +    webkit_web_view_go_back(WEBKIT_WEB_VIEW(data)); +} + +void forward_button_clicked(GtkWidget *widget, gpointer data) +{ +    webkit_web_view_go_forward(WEBKIT_WEB_VIEW(data)); +} + +void home_button_clicked(GtkWidget *widget, gpointer data) +{ +    load_into_view("index.html", MAIN_VIEW); +} + +/* Toggles the contents pane */ +void contents_button_clicked(GtkWidget *widget, gpointer data) +{ +    if (gtk_paned_get_position(GTK_PANED(data)) < 50) { +        gtk_paned_set_position(GTK_PANED(data), 370); +    } else { +        gtk_paned_set_position(GTK_PANED(data), 0); +    } +} + +gboolean contents_click_handler( +    WebKitWebView *web_view, +    WebKitWebFrame *frame, +    WebKitNetworkRequest *request, +    WebKitWebNavigationAction *navigation_action, +    WebKitWebPolicyDecision *policy_decision, +    gpointer data) +{ + +    webkit_web_view_load_uri(WEBKIT_WEB_VIEW(data), +                             webkit_network_request_get_uri(request)); + +    return TRUE; +} + +/** + * Initialize the buttons for the help window + */ +void initialize_buttons(GtkWidget *main_vbox, GtkWidget *content_hpane) +{ +    GtkWidget *buttons_hbuttonbox; +    GtkWidget *back_button; +    GtkWidget *forward_button; +    GtkWidget *home_button; +    GtkWidget *contents_button; + +    // define and attach signals to buttons +    back_button = gtk_button_new_with_label(_("Back")); +    g_signal_connect(back_button, "clicked", G_CALLBACK(back_button_clicked), +                     G_OBJECT(main_view)); + +    forward_button = gtk_button_new_with_label(_("Forward")); +    g_signal_connect(forward_button, "clicked", G_CALLBACK(forward_button_clicked), +                     G_OBJECT(main_view)); + +    home_button = gtk_button_new_with_label(_("Home")); +    g_signal_connect(home_button, "clicked", G_CALLBACK(home_button_clicked), +                     G_OBJECT(main_view)); + +    contents_button = gtk_button_new_with_label(_("Contents")); +    g_signal_connect(contents_button, "clicked", +                     G_CALLBACK(contents_button_clicked), G_OBJECT(content_hpane)); + +    // button layout +    buttons_hbuttonbox = gtk_hbutton_box_new(); +    gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), back_button); +    gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), forward_button); +    gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), home_button); +    gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), contents_button); +    gtk_box_pack_start(GTK_BOX(main_vbox), buttons_hbuttonbox, FALSE, TRUE, 0); +    gtk_box_set_spacing(GTK_BOX(buttons_hbuttonbox), 6); +    gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_hbuttonbox), +                              GTK_BUTTONBOX_START); + +    /* Store pointers to all widgets, for use by lookup_widget().  */ +    GLADE_HOOKUP_OBJECT(main_view, back_button, BACKBUTTON); +    GLADE_HOOKUP_OBJECT(main_view, forward_button, FORWARDBUTTON); +    GLADE_HOOKUP_OBJECT(main_view, home_button, HOMEBUTTON); +    GLADE_HOOKUP_OBJECT(main_view, contents_button, CONTENTBUTTON); +} + +/** + * Create the help windows including all contained widgets and the needed HTML documents. + * + * \RETURN handle of the created window. + */ + +GtkWidget* +CreateHelpWindow(void) +{ +    GtkWidget *main_vbox; +    GtkWidget *main_view_scroller; +    GtkWidget *contents_view_scroller; +    GtkWidget *content_hpane; + +    int width; +    int height; +    int x, y; +    int w = 0, h = 0; +    const char *pref; + +    wHelpWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + +    width = gdk_screen_get_width(gtk_window_get_screen((GtkWindow *)wHelpWindow)); +    height = gdk_screen_get_height(gtk_window_get_screen((GtkWindow *)wHelpWindow)); + +    pref = wPrefGetString(HTMLHELPSECTION, WINDOWSIZEPREFNAME); + +    if (pref) { +        sscanf(pref, "%d %d", &w, &h); + +        if (w > width) { +            w = width; +        } + +        if (h > height) { +            h = height; +        } +    } else { +        w = (width * 2)/ 5; +        h = height - 100; +    } + +    pref = wPrefGetString(HTMLHELPSECTION, WINDOWPOSPREFNAME); + +    if (pref) { +        sscanf(pref, "%d %d", &x, &y); + +        if (y > height - h) { +            y = height - h; +        } + +        if (x > width - w) { +            x = width - w; +        } +    } else { +        x = (width * 3) / 5 - 10; +        y = 70; +    } + +    gtk_window_resize((GtkWindow *)wHelpWindow, w, h); +    gtk_window_move((GtkWindow *)wHelpWindow, x, y); + +    gtk_window_set_title(GTK_WINDOW(wHelpWindow), "XTrkCad Help"); + +    g_signal_connect(G_OBJECT(wHelpWindow), "delete-event", +                     G_CALLBACK(DestroyHelpWindow), NULL); + +    main_view_scroller = gtk_scrolled_window_new(NULL, NULL); +    contents_view_scroller = gtk_scrolled_window_new(NULL, NULL); +    main_view = webkit_web_view_new(); +    contents_view = webkit_web_view_new(); +    // must be done here as it gets locked down later +    load_into_view("contents.html", CONTENTS_VIEW); +    gtk_widget_set_size_request(GTK_WIDGET(wHelpWindow), x, y); + +    main_vbox = gtk_vbox_new(FALSE, 5); +    gtk_container_add(GTK_CONTAINER(wHelpWindow), main_vbox); + +    gtk_container_add(GTK_CONTAINER(main_view_scroller), main_view); + +    gtk_container_add(GTK_CONTAINER(contents_view_scroller), contents_view); + +    content_hpane = gtk_hpaned_new(); +    initialize_buttons(main_vbox, content_hpane); +    gtk_container_add(GTK_CONTAINER(content_hpane), contents_view_scroller); +    gtk_container_add(GTK_CONTAINER(content_hpane), main_view_scroller); +    gtk_box_pack_start(GTK_BOX(main_vbox), content_hpane, TRUE, TRUE, 0); + +    gtk_paned_set_position(GTK_PANED(content_hpane), 370); + +    g_signal_connect(contents_view, "navigation-policy-decision-requested", +                     G_CALLBACK(contents_click_handler), G_OBJECT(main_view)); + +    /* Store pointers to all widgets, for use by lookup_widget().  */ +    GLADE_HOOKUP_OBJECT_NO_REF(wHelpWindow, wHelpWindow, "wHelpWindow"); +    GLADE_HOOKUP_OBJECT(wHelpWindow, content_hpane, PANED); +    GLADE_HOOKUP_OBJECT(wHelpWindow, contents_view, TOCVIEW); +    GLADE_HOOKUP_OBJECT(wHelpWindow, main_view, CONTENTSVIEW); + +    return wHelpWindow; +} + +void load_into_view(char *file, int requested_view) +{ +    GtkWidget *view; + +    switch (requested_view) { +    case MAIN_VIEW: +        view = main_view; +        break; + +    case CONTENTS_VIEW: +        view = contents_view; +        break; + +    default: +        printf("*** error, could not find view"); +        break; +    } + +    char fileToLoad[250] = "file://"; +    strcat(fileToLoad,directory); +    strcat(fileToLoad,file); + +    //debug printf("*** loading %s into pane %d.\n", fileToLoad, requested_view); +    webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view), fileToLoad); +} + +/** + * Invoke the help system to display help for <topic>. + * + * \param topic IN topic string + */ + +void wHelp(const char * topic) +{ +    char *htmlFile; + +    if (!wHelpWindow) { +        directory = malloc(BUFSIZ); +        assert(directory != NULL); + +        sprintf(directory, "%s/html/", wGetAppLibDir()); + +        wHelpWindow = CreateHelpWindow(); +        /* load the default content */ +        load_into_view("index.html", MAIN_VIEW); +    } + +    /* need space for the 'html' extension plus dot plus \0 */ +    htmlFile = malloc(strlen(topic) + 6); +    assert(htmlFile != NULL); + +    sprintf(htmlFile, "%s.html", topic); + +    load_into_view(htmlFile, MAIN_VIEW); +    gtk_widget_show_all(wHelpWindow); +    gtk_window_present(GTK_WINDOW(wHelpWindow)); +} diff --git a/app/wlib/gtklib/lines.c b/app/wlib/gtklib/lines.c new file mode 100644 index 0000000..bd787a6 --- /dev/null +++ b/app/wlib/gtklib/lines.c @@ -0,0 +1,150 @@ +/** \file lines.c + * Window for drawing simple line drawing + */ + +/* 	XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis, + *                2016 Martin Fischer <m_fischer@sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <cairo.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +/* + ***************************************************************************** + * + * Lines + * + ***************************************************************************** + */ + +struct wLine_t { +    WOBJ_COMMON +    wBool_t visible; +    int count; +    wLines_t * lines; +}; + +/** + * Perform redrawing of the lines window + * + * \param b IN window handle + * \return + */ + +static void linesRepaint(wControl_p b) +{ +    wLine_p bl = (wLine_p)(b); +    int i; +    wWin_p win = (wWin_p)(bl->parent); +    GdkDrawable * window; +    cairo_t *cr; + +    if (!bl->visible) { +        return; +    } + +    window = gtk_widget_get_window(win->widget); +    cr = gdk_cairo_create(window); +    cairo_set_source_rgb(cr, 0, 0, 0); +    cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); +    cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); + +    for (i=0; i<bl->count; i++) { +        cairo_set_line_width(cr, bl->lines[i].width); +        cairo_move_to(cr, bl->lines[i].x0, bl->lines[i].y0); +        cairo_line_to(cr, bl->lines[i].x1, bl->lines[i].y1); +        cairo_stroke(cr); +    } + +    cairo_destroy(cr); +} + +/** + * Set visibility state of lines window + * + * \param bl IN window + * \param visible IN new visibility state + * \return + */ + +void wlibLineShow( +    wLine_p bl, +    wBool_t visible) +{ +    bl->visible = visible; +} + +/** + * Create a window consisting of several lines + * + * \param parent IN parent window + * \param labelStr IN  label - unused + * \param count IN number of lines + * \param lines IN list of line coordinates + * \return handle of new window + */ + +wLine_p wLineCreate( +    wWin_p	parent, +    const char	* labelStr, +    int	count, +    wLines_t * lines) +{ +    wLine_p linesWindow; +    int i; +    linesWindow = (wLine_p)wlibAlloc(parent, B_LINES, 0, 0, labelStr, +                                    sizeof *linesWindow, NULL); +    linesWindow->visible = TRUE; +    linesWindow->count = count; +    linesWindow->lines = lines; +    linesWindow->w = linesWindow->h = 0; + +    for (i=0; i<count; i++) { +        if (lines[i].x0 > linesWindow->w) { +            linesWindow->w = lines[i].x0; +        } + +        if (lines[i].y0 > linesWindow->h) { +            linesWindow->h = lines[i].y0; +        } + +        if (lines[i].x1 > linesWindow->w) { +            linesWindow->w = lines[i].x1; +        } + +        if (lines[i].y1 > linesWindow->h) { +            linesWindow->h = lines[i].y1; +        } +    } + +    linesWindow->repaintProc = linesRepaint; +    wlibAddButton((wControl_p)linesWindow); +    linesWindow->widget = NULL; +    return linesWindow; +} diff --git a/app/wlib/gtklib/list.c b/app/wlib/gtklib/list.c new file mode 100644 index 0000000..bf3a56e --- /dev/null +++ b/app/wlib/gtklib/list.c @@ -0,0 +1,547 @@ +/** \file list.c + * Listboxes, dropdown boxes, combo boxes + */ +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <glib-object.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include "wlib.h" +#include "gtkint.h" +#include "i18n.h" + +struct listSearch { +    const char *search; +    char *result; +    int row; +}; + + +/* + ***************************************************************************** + * + * List Boxes + * + ***************************************************************************** + */ + +/** + * Remove all entries from the list + * + * \param b IN list + * \return + */ + +void wListClear( +    wList_p b) +{ +    assert(b!= NULL); + +    b->recursion++; + +    if (b->type == B_DROPLIST) { +        wDropListClear(b); +    } else { +        wTreeViewClear(b); +    } + +    b->recursion--; +    b->last = -1; +    b->count = 0; +} + +/** + * Makes the <val>th entry (0-origin) the current selection. + * If <val> if '-1' then no entry is selected. + * \param b IN List + * \param element IN Index + */ + +void wListSetIndex( +    wList_p b, +    int element) +{ +    if (b->widget == 0) { +        abort(); +    } + +    b->recursion++; + +    if (b->type == B_DROPLIST) { +        wDropListSetIndex(b, element); +    } else { +        wlibTreeViewSetSelected(b, element); +    } + +    b->last = element; +    b->recursion--; +} + +/** + * CompareListData is called when a list is searched for a specific + * data entry. It is called in sequence and does a string compare + * between the label of the current row and the search argument. If + * identical the label is placed in the search argument. + * It is a GTK foreach() function. + * + * \param model IN searched model + * \param path IN unused + * \param iter IN current iterator + * \param data IN/OUT pointer to data structure with search criteria + * \return TRUE if identical, FALSE otherwise + */ + +int +CompareListData(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, +                gpointer data) +{ +    wListItem_p id_p; +    struct listSearch *search = (struct listSearch *)data; + +    gtk_tree_model_get(model, +                       iter, +                       LISTCOL_DATA, +                       &id_p, +                       -1); + +    if (id_p && id_p->label && !strcmp(id_p->label, search->search)) { +        search->result = (char *)id_p->label; +        return TRUE; +    } else { +        search->result = NULL; +        search->row++; +        return FALSE; +    } +} + +/** + * Find the row which contains the specified text. + * + * \param b IN + * \param val IN + * \returns found row or -1 if not found + */ + +wIndex_t wListFindValue( +    wList_p b, +    const char * val) +{ +    struct listSearch thisSearch; + +    assert(b!=NULL); +    assert(b->listStore!=NULL); + +    thisSearch.search = val; +    thisSearch.row = 0; + +    gtk_tree_model_foreach(GTK_TREE_MODEL(b->listStore), CompareListData, +                           (void *)&thisSearch); + +    if (!thisSearch.result) { +        return -1; +    } else { +        return thisSearch.row; +    } +} + +/** + * Return the number of rows in the list + * + * \param b IN widget + * \returns number of rows + */ + +wIndex_t wListGetCount( +    wList_p b) +{ +    if (b->type == B_DROPLIST) { +        return wDropListGetCount(b); +    } else { +        return wTreeViewGetCount(b); +    } +} + +/** + * Get the user data for a list element + * + * \param b IN widget + * \param inx IN row + * \returns the user data for the specified row + */ + +void * wListGetItemContext( +    wList_p b, +    wIndex_t inx) +{ +    if (inx < 0) { +        return NULL; +    } + +    if (b->type == B_DROPLIST) { +        return wDropListGetItemContext(b, inx); +    } else { +        return wTreeViewGetItemContext(b, inx); +    } +} + +/** + * + * \param bl IN widget + * \param labelStr IN ? + * \param labelSize IN ? + * \param listDataRet IN + * \param itemDataRet IN + * \returns + */ + +wIndex_t wListGetValues( +    wList_p bl, +    char * labelStr, +    int labelSize, +    void * * listDataRet, +    void * * itemDataRet) +{ +    wListItem_p id_p; +    wIndex_t inx = bl->last; +    const char * entry_value = ""; +    void * item_data = NULL; + +    assert(bl != NULL); +    assert(bl->listStore != NULL); + +    if (bl->type == B_DROPLIST && bl->editted) { +        entry_value = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN( +                                             bl->widget)))); +        inx = bl->last = -1; +    } else { +        inx = bl->last; + +        if (inx >= 0) { +            id_p = wlibListStoreGetContext(bl->listStore, inx); + +            if (id_p==NULL) { +                fprintf(stderr, "wListGetValues - id_p == NULL\n"); +            } else { +                entry_value = id_p->label; +                item_data = id_p->itemData; +            } +        } +    } + +    if (labelStr) { +        strncpy(labelStr, entry_value, labelSize); +    } + +    if (listDataRet) { +        *listDataRet = bl->data; +    } + +    if (itemDataRet) { +        *itemDataRet = item_data; +    } + +    return bl->last; +} + +/** + * Check whether row is selected + * \param b IN widget + * \param inx IN row + * \returns TRUE if selected, FALSE if not existant or unselected + */ + +wBool_t wListGetItemSelected( +    wList_p b, +    wIndex_t inx) +{ +    wListItem_p id_p; + +    if (inx < 0) { +        return FALSE; +    } + +    id_p = wlibListStoreGetContext(b->listStore, inx); + +    if (id_p) { +        return id_p->selected; +    } else { +        return FALSE; +    } +} + +/** + * Count the number of selected rows in list + * + * \param b IN widget + * \returns count of selected rows + */ + +wIndex_t wListGetSelectedCount( +    wList_p b) +{ +    wIndex_t selcnt, inx; + +    for (selcnt=inx=0; inx<b->count; inx++) +        if (wListGetItemSelected(b, inx)) { +            selcnt++; +        } + +    return selcnt; +} + +/** + * Select all items in list. + * + * \param bl IN list handle + * \return + */ + +void wListSelectAll(wList_p bl) +{ +    wIndex_t inx; +    GtkTreeSelection *selection; + +    assert(bl != NULL); +    // mark all items selected +    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(bl->treeView)); +    gtk_tree_selection_select_all(selection); + +    // and synchronize the internal data structures +    wListGetCount(bl); + +    for (inx=0; inx<bl->count; inx++) { +        wListItem_p ldp; + +        ldp = wlibListStoreGetContext(bl->listStore, inx); + +        if (ldp) { +            ldp->selected = TRUE; +        } +    } +} + +/** + * Set the value for a row in the listbox + * + * \param b IN widget + * \param row IN row to change + * \param labelStr IN string with new tab separated values + * \param bm IN icon + * \param itemData IN data for row + * \returns TRUE + */ + +wBool_t wListSetValues( +    wList_p b, +    wIndex_t row, +    const char * labelStr, +    wIcon_p bm, +    void *itemData) + +{ +    assert(b->listStore != NULL); + +    b->recursion++; + +    if (b->type == B_DROPLIST) { +        wDropListSetValues(b, row, labelStr, bm, itemData); +    } else { +        wlibListStoreUpdateValues(b->listStore, row, b->colCnt, (char *)labelStr, bm); +    } + +    b->recursion--; +    return TRUE; +} + +/** + * Remove a line from the list + * \param b IN widget + * \param inx IN row + */ + +void wListDelete( +    wList_p b, +    wIndex_t inx) + +{ +    GtkTreeIter iter; + +    assert(b->listStore != 0); +    assert(b->type != B_DROPLIST); +    b->recursion++; + +    if (b->type == B_DROPLIST) { +        wNotice("Deleting from dropboxes is not implemented!", "Continue", NULL); +    } else { +        gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), +                                      &iter, +                                      NULL, +                                      inx); +        gtk_list_store_remove(b->listStore, &iter); +        b->count--; +    } + +    b->recursion--; +    return; +} + +/** + * Get the widths of the columns + * + * \param bl IN widget + * \param colCnt IN number of columns + * \param colWidths OUT array for widths + * \returns + */ + +int wListGetColumnWidths( +    wList_p bl, +    int colCnt, +    wPos_t * colWidths) +{ +    int inx; + +    if (bl->type != B_LIST) { +        return 0; +    } + +    if (bl->colWidths == NULL) { +        return 0; +    } + +    for (inx=0; inx<colCnt; inx++) { +        if (inx < bl->colCnt) { +            colWidths[inx] = bl->colWidths[inx]; +        } else { +            colWidths[inx] = 0; +        } +    } + +    return bl->colCnt; +} + +/** + * Adds a entry to the list <b> with name <name>. + * + * \param b IN widget + * \param labelStr IN Entry name + * \param bm IN Entry bitmap + * \param itemData IN User context + * \returns + */ + +wIndex_t wListAddValue( +    wList_p b, +    const char * labelStr, +    wIcon_p bm, +    void * itemData) +{ +    wListItem_p id_p; + +    assert(b != NULL); + +    b->recursion++; + +    id_p = (wListItem_p)g_malloc(sizeof *id_p); +    memset(id_p, 0, sizeof *id_p); +    id_p->itemData = itemData; +    id_p->active = TRUE; + +    if (labelStr == NULL) { +        labelStr = ""; +    } + +    id_p->label = strdup(labelStr); +    id_p->listP = b; + +    if (b->type == B_DROPLIST) { +        wDropListAddValue(b, (char *)labelStr, id_p); +    } else { +        wlibTreeViewAddRow(b, (char *)labelStr, bm, id_p); +    } + +    b->count++; +    b->recursion--; + +    if (b->count == 1) { +        b->last = 0; +    } + +    return b->count-1; +} + + +/** + * Set the size of the list + * + * \param bl IN widget + * \param w IN width + * \param h IN height (ignored for droplist) + */ + +void wListSetSize(wList_p bl, wPos_t w, wPos_t h) +{ +    if (bl->type == B_DROPLIST) { +        gtk_widget_set_size_request(bl->widget, w, -1); +    } else { +        gtk_widget_set_size_request(bl->widget, w, h); +    } + +    bl->w = w; +    bl->h = h; +} + +/** + * Create a single column list box (not what the names suggests!) + * \todo Improve or discard totally, in this case, remove from param.c \ + * as well. + * + * \param varname1 IN this is a variable + * \param varname2 OUT and another one that is modified + * \return    describe the return value + */ + +wList_p wComboListCreate( +    wWin_p	parent,		/* Parent window */ +    wPos_t	x,		/* X-position */ +    wPos_t	y,		/* Y-position */ +    const char 	* helpStr,	/* Help string */ +    const char	* labelStr,	/* Label */ +    long	option,		/* Options */ +    long	number,		/* Number of displayed list entries */ +    wPos_t	width,		/* Width */ +    long	*valueP,	/* Selected index */ +    wListCallBack_p action,	/* Callback */ +    void 	*data)		/* Context */ +{ +    wNotice("ComboLists are not implemented!", "Abort", NULL); +    abort(); +} + + diff --git a/app/wlib/gtklib/liststore.c b/app/wlib/gtklib/liststore.c new file mode 100644 index 0000000..eb53ea7 --- /dev/null +++ b/app/wlib/gtklib/liststore.c @@ -0,0 +1,267 @@ +/** \file liststore.c + * Handling of the list store used for tree views and drop boxes + */ + +/* + * + * Copyright 2016 Martin Fischer <m_fischer@users.sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include "gtkint.h" + +/** + * Get data of one row in a list + * \param b IN list widget + * \param inx IN row to retrieve + * \param childR IN list for data (?) + * \returns + */ + +wListItem_p wlibListItemGet( +    GtkListStore *ls, +    wIndex_t inx, +    GList ** childR) +{ +    wListItem_p id_p; + +    assert(ls != NULL); + +    if (childR) { +        *childR = NULL; +    } + +    if (inx < 0) { +        return NULL; +    } + +    id_p = wlibListStoreGetContext(ls, inx); + +    return id_p; +} + +/** + * Get the context (user data) for a row in the list store + * + * \param ls IN list store + * \param inx IN row + * \returns pointer to data + */ + +void * +wlibListStoreGetContext(GtkListStore *ls, int inx) +{ +    GtkTreeIter iter; +    gchar *string = NULL; +    gboolean result; +    gint childs; + +    childs = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(ls), +                                            NULL); + +    if (inx < childs) { +        result = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(ls), +                                               &iter, +                                               NULL, +                                               inx); + +        if (result) { +            gtk_tree_model_get(GTK_TREE_MODEL(ls), +                               &iter, +                               LISTCOL_DATA, +                               &string, +                               -1); +        } else { +            printf("Invalid index %d for list!\n", inx); + +        } +    } + +    return (string); +} + + +/** + * Clear the list store + * + * \param listStore IN + */ + +void +wlibListStoreClear(GtkListStore *listStore) +{ +    assert(listStore != NULL); + +    /** \todo this looks like a memory leak. should probably free the id's */ +    gtk_list_store_clear(listStore); +} + +/** + * Create a list store. The list store will have one column for user + * data that will not be displayed, a column for a bitmap and <cnt> + * colors for data. + * + * \param colCnt IN number of additional columns + * \returns the list store + */ + +GtkListStore * +wlibNewListStore(int colCnt) +{ +    GtkListStore *ls; +    GType *colTypes; +    int i; + +    /* create the list store, using strings for all columns */ +    colTypes = g_malloc(sizeof(GType) * (colCnt + LISTCOL_TEXT)); +    colTypes[ LISTCOL_BITMAP ] = GDK_TYPE_PIXBUF; +    colTypes[ LISTCOL_DATA ] = G_TYPE_POINTER; + +    for (i = 0; i < colCnt; i++) { +        colTypes[ LISTCOL_TEXT + i ] = G_TYPE_STRING; +    } + +    ls = gtk_list_store_newv(colCnt + LISTCOL_TEXT, colTypes); +    g_free(colTypes); + +    return (ls); +} + +/** + * Update the list store at the iter's position + * + * \param ls IN list store + * \param iter IN iterator into list store + * \param labels IN tab separated label string + * \returns number of updated columns + */ + +static int +wlibListStoreUpdateIter(GtkListStore *ls, GtkTreeIter *iter, char *labels) +{ +    char *convertedLabels; +    char *text; +    char *start; +    int current = 0; + +    convertedLabels = strdup(wlibConvertInput(labels)); +    start = convertedLabels; + +    while ((text = strchr(start, '\t')) != NULL) { +        *text = '\0'; +        gtk_list_store_set(ls, iter, LISTCOL_TEXT + current, start, -1); +        start = text + 1; +        current++; +    } + +    /* add the last piece of the string */ +    gtk_list_store_set(ls, iter, LISTCOL_TEXT + current, start, -1); + +    free(convertedLabels); +    return (current+1); +} + +/** + * Add a pixbuf to the list store + * \param ls IN list store + * \param iter IN position + * \param pixbuf IN pixbuf to add + */ + +void +wlibListStoreSetPixbuf(GtkListStore *ls, GtkTreeIter *iter, GdkPixbuf *pixbuf) +{ +    gtk_list_store_set(ls, iter, LISTCOL_BITMAP, pixbuf, -1); +} +/** + * Add a row to the list store + * + * \param ls IN the list store + * \param cols IN columns in list store + * \param id IN id + * \returns number columns added + */ + +int +wlibListStoreAddData(GtkListStore *ls, GdkPixbuf *pixbuf, int cols, +                     wListItem_p id) +{ +    GtkTreeIter iter; +    int count; + +    gtk_list_store_append(ls, &iter); +    gtk_list_store_set(ls, &iter, LISTCOL_DATA, id, -1); + +    if (pixbuf) { +        wlibListStoreSetPixbuf(ls, &iter, pixbuf); +    } + +    count = wlibListStoreUpdateIter(ls, &iter, (char *)id->label); + +    return (count); +} + +/** + * Change a row in the list store. The passed strings are placed + * in the first cols text columns of the list store. + * + * \param ls IN list store + * \param row IN row in list store + * \param cols IN number of columns to set + * \param labels IN tab separated list of texts + * \param bm IN bitmap + * \return count of updated text fields + */ + +int +wlibListStoreUpdateValues(GtkListStore *ls, int row, int cols, char *labels, +                          wIcon_p bm) +{ +    GtkTreeIter iter; +    int count; + +    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(ls), +                                  &iter, +                                  NULL, +                                  row); + +    count = wlibListStoreUpdateIter(ls, &iter, labels); + +    if (bm) { +        GdkPixbuf *pixbuf; + +        pixbuf = wlibMakePixbuf(bm); +        wlibListStoreSetPixbuf(ls, &iter, pixbuf); +    } + +    return (count); +} + diff --git a/app/wlib/gtklib/main.c b/app/wlib/gtklib/main.c new file mode 100644 index 0000000..9075687 --- /dev/null +++ b/app/wlib/gtklib/main.c @@ -0,0 +1,107 @@ +/** \file main.c
 + * Main function and initialization stuff
 + *
 + */
 +
 +/*  XTrkCad - Model Railroad CAD
 + *  Copyright (C) 2005,2012 Dave Bullis Martin Fischer
 + *
 + *  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-1307, USA.
 + */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <locale.h>
 +
 +#define GTK_DISABLE_SINGLE_INCLUDES
 +#define GDK_DISABLE_DEPRECATED
 +#define GTK_DISABLE_DEPRECATED
 +#define GSEAL_ENABLE
 +
 +#include <gtk/gtk.h>
 +#include <gdk/gdk.h>
 +
 +#include "gtkint.h"
 +#include "i18n.h"
 +
 +
 +static char *appName;		/**< application name */
 +char *wExecutableName;
 +
 +
 +/**
 + * Initialize the application name for later use
 + *
 + * \param _appName IN Name of application
 + * \return   
 + */
 + 
 +void 
 +wInitAppName(char *_appName)
 +{
 +	appName = g_strdup( _appName );
 +}
 +
 +char *
 +wlibGetAppName()
 +{
 +	return( appName );
 +}	
 +
 +/*
 + *******************************************************************************
 + *
 + * Main
 + *
 + *******************************************************************************
 + */
 +
 +
 +
 +int main( int argc, char *argv[] )
 +{
 +	wWin_p win;
 +	const char *ld;
 +
 +	if ( getenv( "GTKLIB_NOLOCALE" ) == 0 )
 +		setlocale( LC_ALL, "en_US" );
 +	gtk_init( &argc, &argv );
 +
 +	if ((win=wMain( argc, argv )) == NULL)
 +		exit(1);
 +    wExecutableName = argv[ 0 ];
 +	ld = wGetAppLibDir();
 +	
 +#ifdef WINDOWS
 +	
 +#else
 +	// set up help search path on unix boxes
 +	if (ld != NULL) {
 +		static char buff[BUFSIZ];
 +		const char *hp;
 +
 +		sprintf( buff, "HELPPATH=/usr/lib/help:%s:", ld );
 +		if ( (hp = getenv("HELPPATH")) != NULL )
 +			strcat( buff, hp );
 +		putenv( buff );
 +	}
 +#endif
 +	
 +	if (!win->shown)
 +		wWinShow( win, TRUE );
 +
 +	gtk_main();
 +	exit(0);
 +}
 diff --git a/app/wlib/gtklib/menu.c b/app/wlib/gtklib/menu.c new file mode 100644 index 0000000..fb115a3 --- /dev/null +++ b/app/wlib/gtklib/menu.c @@ -0,0 +1,1084 @@ +/** \file menu.c + * Menu creation and handling. + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis, 2012 Martin Fischer + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +#include "i18n.h" + +#define WLISTITEM	"wListItem"		/**< id for object data */ + +/* + ***************************************************************************** + * + * Menus + * + ***************************************************************************** + */ + +typedef enum { M_MENU, M_SEPARATOR, M_PUSH, M_LIST, M_LISTITEM, M_TOGGLE, M_RADIO } mtype_e; +typedef enum { MM_BUTT, MM_MENU, MM_BAR, MM_POPUP } mmtype_e; + +typedef struct{	mtype_e mtype;			/**< menu entry type */ +				GtkWidget *menu_item; +				wMenu_p parentMenu; +				int recursion; 			/**< recursion counter */ +		} MOBJ_COMMON; 					/**< menu item specific data */ +							 +	 +struct wMenuItem_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	}; + +typedef struct wMenuItem_t * wMenuItem_p; + +// a few macros to make access to members easier	 +//#define PTR2M( ptr ) ((ptr)->m)	 +#define MMENUITEM( ptr ) 	(((ptr)->m).menu_item)	 +#define MPARENT( ptr ) 	(((ptr)->m).parentMenu) +#define MITEMTYPE( ptr )	(((ptr)->m).mtype) +#define MRECURSION( ptr ) (((ptr)->m).recursion)	 +	 +	 +struct wMenu_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	mmtype_e mmtype; +	wMenuItem_p first, last; +	GtkWidget * menu; +	GSList *radioGroup;			/* radio button group */ +	wMenuTraceCallBack_p traceFunc; +	void * traceData; +	GtkLabel * labelG; +	GtkWidget * imageG; +	}; + +struct wMenuPush_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	wMenuCallBack_p action; +	wBool_t enabled; +	}; + +struct wMenuRadio_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	wMenuCallBack_p action; +	wBool_t enabled; +	}; + +struct wMenuList_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	int max; +	int count; +	wMenuListCallBack_p action; +	}; + +struct wMenuListItem_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	wMenuList_p mlist; +	}; + +typedef struct wMenuListItem_t * wMenuListItem_p; +	 +struct wMenuToggle_t { +	WOBJ_COMMON +	MOBJ_COMMON m; +	wMenuToggleCallBack_p action; +	wBool_t enabled; +	wBool_t set; +	}; + + +/*-----------------------------------------------------------------*/ +	 +/** + * Handle activate event for menu items. + * + * \param widget IN widget that emitted the signal + * \param value  IN application data + * \return  + */ +	 +static void pushMenuItem( +	GtkWidget * widget, +	gpointer value ) +{ +	wMenuItem_p m = (wMenuItem_p)value; +	wMenuToggle_p mt; + +	if (MRECURSION( m )) +		return; + +	switch MITEMTYPE( m ) { +	case M_PUSH: +		((wMenuPush_p)m)->action( ((wMenuPush_p)m)->data ); +		break; +	case M_TOGGLE: +		mt = (wMenuToggle_p)m; +		wMenuToggleSet( mt, !mt->set ); +		mt->action( mt->set, mt->data ); +		break; +	case M_RADIO: +		/* NOTE: action is only called when radio button is activated, not when deactivated */ +		if( gtk_check_menu_item_get_active((GtkCheckMenuItem *)widget ) == TRUE ) +			((wMenuRadio_p)m)->action( ((wMenuRadio_p)m)->data ); +		break;	 +	case M_MENU: +		return; +	default: +		/*fprintf(stderr," Oops menu\n");*/ +		return; +	} +	if( MPARENT(m)->traceFunc ) { +		MPARENT(m)->traceFunc( MPARENT( m ), m->labelStr,  MPARENT(m)->traceData ); +	} +}  + +/** + * Create a new menu element, add to the parent menu and to help + * + * \param m 		IN parent menu + * \param mtype 	IN type of new entry + * \param helpStr 	IN help topic  + * \param labelStr 	IN display label + * \param size 		IN size of additional data? + * \return    the newly created menu element + */ + +static wMenuItem_p createMenuItem( +	wMenu_p m, +	mtype_e mtype, +	const char * helpStr, +	const char * labelStr, +	int size ) +{ +	wMenuItem_p mi; +	mi = (wMenuItem_p)wlibAlloc( NULL, B_MENUITEM, 0, 0, labelStr, size, NULL ); +	MITEMTYPE( mi )= mtype; +	 +	switch ( mtype ) { +	case M_LIST: +		MMENUITEM( mi ) = gtk_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr)); // NULL;  //PTR2M(m).menu_item +		break; +	case M_SEPARATOR: +		MMENUITEM( mi ) = gtk_separator_menu_item_new(); +		break; +	case M_TOGGLE: +		MMENUITEM( mi ) = gtk_check_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr)); +		break; +	case M_RADIO: +		MMENUITEM( mi ) = gtk_radio_menu_item_new_with_mnemonic(m->radioGroup, wlibConvertInput(mi->labelStr)); +		m->radioGroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (MMENUITEM( mi ))); +		break;			 +	default: +		MMENUITEM( mi ) = gtk_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr)); +		break; +	} +	if (MMENUITEM( mi )) { +		if (m) +			gtk_menu_shell_append( (GtkMenuShell *)(m->menu), MMENUITEM( mi ) ); + +		g_signal_connect( GTK_OBJECT(MMENUITEM( mi )), "activate", +				G_CALLBACK(pushMenuItem), mi ); + 		gtk_widget_show(MMENUITEM( mi )); +	} +	 +	// this is  a link list of all menu items belonging to a specific menu +	// is used in automatic processing (macro)?? +	if (m) { +		if (m->first == NULL) { +			m->first = mi; +		} else { +			m->last->next = (wControl_p)mi; +		} +		m->last = mi; +	} +	mi->next = NULL; +	 +	 +	if (helpStr != NULL) { +		wlibAddHelpString( MMENUITEM( mi ), helpStr ); +	} +	MPARENT( mi ) = m; +	return mi; +} + + +static void setAcclKey( wWin_p w, GtkWidget * menu, GtkWidget * menu_item, int acclKey ) +{ +	int mask; +	static GtkAccelGroup * accel_alpha_group = NULL; +	static GtkAccelGroup * accel_nonalpha_group = NULL; +	guint oldmods; + + +	if (accel_alpha_group == NULL) { +		accel_alpha_group = gtk_accel_group_new(); +		/*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/ +		gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_alpha_group ); +	} +	if (accel_nonalpha_group == NULL) { +		oldmods = gtk_accelerator_get_default_mod_mask(); +		gtk_accelerator_set_default_mod_mask( GDK_CONTROL_MASK | GDK_MOD1_MASK ); +		accel_nonalpha_group = gtk_accel_group_new(); +		/*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/ +		gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_nonalpha_group ); +		gtk_accelerator_set_default_mod_mask( oldmods ); +	} +  +	mask = 0; +	if (acclKey) { +		int len; +		char acclStr[40]; +		 +		len = 0; +		if (acclKey&WALT) { +			mask |= GDK_MOD1_MASK; +			strcpy( acclStr+len, "Meta+" ); +			len += 5; +		} +		if (acclKey&WSHIFT) { +			mask |= GDK_SHIFT_MASK; +			strcpy( acclStr+len, "Shift+" ); +			len += 6; +			switch ( (acclKey&0xFF) ) { +			case '0': acclKey += ')'-'0'; break; +			case '1': acclKey += '!'-'1'; break; +			case '2': acclKey += '@'-'2'; break; +			case '3': acclKey += '#'-'3'; break; +			case '4': acclKey += '$'-'4'; break; +			case '5': acclKey += '%'-'5'; break; +			case '6': acclKey += '^'-'6'; break; +			case '7': acclKey += '&'-'7'; break; +			case '8': acclKey += '*'-'8'; break; +			case '9': acclKey += '('-'9'; break; +			case '`': acclKey += '~'-'`'; break; +			case '-': acclKey += '_'-'-'; break; +			case '=': acclKey += '+'-'='; break; +			case '\\': acclKey += '|'-'\\'; break; +			case '[': acclKey += '{'-'['; break; +			case ']': acclKey += '}'-']'; break; +			case ';': acclKey += ':'-';'; break; +			case '\'': acclKey += '"'-'\''; break; +			case ',': acclKey += '<'-','; break; +			case '.': acclKey += '>'-'.'; break; +			case '/': acclKey += '?'-'/'; break; +			default: break; +			} +		} +		if (acclKey&WCTL) { +			mask |= GDK_CONTROL_MASK; +			strcpy( acclStr+len, "Ctrl+" ); +			len += 5; +		} +		acclStr[len++] = (acclKey & 0xFF); +		acclStr[len++] = '\0'; +		gtk_widget_add_accelerator( menu_item, "activate", +			(isalpha(acclKey&0xFF)?accel_alpha_group:accel_nonalpha_group), +			toupper(acclKey&0xFF), mask, GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED ); +	} +} + +/*-----------------------------------------------------------------*/ +/** + * Create a radio button as a menu entry  + * + * \param m 		IN menu to be extended + * \param helpStr 	IN reference into help + * \param labelStr 	IN text for entry + * \param acclKey 	IN accelerator key to add + * \param action 	IN callback function  + * \param data 		IN application data + * \param helpStr 	IN + * \return menu entry + */ + +wMenuRadio_p wMenuRadioCreate( +	wMenu_p m,  +	const char * helpStr, +	const char * labelStr, +	long acclKey, +	wMenuCallBack_p action, +	void 	*data ) +{ +	wMenuRadio_p mi; + +	mi = (wMenuRadio_p)createMenuItem( m, M_RADIO, helpStr, labelStr, sizeof *mi ); +	//~ if (m->mmtype == MM_POPUP && !testMenuPopup) +		//~ return mi; +	setAcclKey( m->parent, m->menu, MMENUITEM( mi ), acclKey ); +	mi->action = action; +	mi->data = data; +	mi->enabled = TRUE; +	return mi; +} + +/** + * Set radio button active + * + * \param mi 		IN menu entry for radio button + * \return + */ + +void wMenuRadioSetActive(  +	wMenuRadio_p mi ) +{ +	gtk_check_menu_item_set_active( (GtkCheckMenuItem *)MMENUITEM(mi), TRUE );  +}	 		 + +/*-----------------------------------------------------------------*/ + +/** + * Create a menu entry  + * + * \param m 		IN menu to be extended + * \param helpStr 	IN reference into help + * \param labelStr 	IN text for entry + * \param acclKey 	IN acceleratoor key to add + * \param action 	IN callback function  + * \param data 		IN application data + * \return menu entry + */ + +wMenuPush_p wMenuPushCreate( +	wMenu_p m,  +	const char * helpStr, +	const char * labelStr, +	long acclKey, +	wMenuCallBack_p action, +	void 	*data ) +{ +	wMenuPush_p mi; + +	mi = (wMenuPush_p)createMenuItem( m, M_PUSH, helpStr, labelStr, sizeof( struct wMenuPush_t )); + +	setAcclKey( m->parent, m->menu, MMENUITEM( mi ), acclKey ); + +	mi->action = action; +	mi->data = data; +	mi->enabled = TRUE; +	return mi; +} + +/** + * Enable menu entry + * + * \param mi 		IN menu entry + * \param enable 	IN new state  + * \return + */ + +void wMenuPushEnable( +	wMenuPush_p mi, +	wBool_t enable ) +{ +	mi->enabled = enable; +	gtk_widget_set_sensitive( GTK_WIDGET(MMENUITEM( mi )), enable ); +} + + +/*-----------------------------------------------------------------*/ +/** + * Create a submenu + * + * \param m 		IN menu to be extended + * \param helpStr 	IN reference into help + * \param labelStr 	IN text for entry + * \return menu entry + */ + +wMenu_p wMenuMenuCreate( +	wMenu_p m,  +	const char * helpStr, +	const char * labelStr ) +{ +	wMenu_p mi; +	mi = (wMenu_p)createMenuItem( m, M_MENU, helpStr, labelStr, sizeof( struct wMenu_t )); +	mi->mmtype = MM_MENU; +	mi->menu = gtk_menu_new(); + +	gtk_menu_item_set_submenu( GTK_MENU_ITEM(MMENUITEM( mi )), mi->menu ); +	return mi; +} + + +/*-----------------------------------------------------------------*/ +/** + * Create a menu separator + * + * \param mi 		IN menu entry + * \return + */ + +void wMenuSeparatorCreate( +	wMenu_p m )  +{ +	createMenuItem( m, M_SEPARATOR, NULL, "", sizeof( struct wMenuItem_t )); +} + + +/*-----------------------------------------------------------------*/ + +/** + * Find the start of a menu item list in a menu +  * + * \param ml 		IN menu list to be searched + * \param pChildren OUT list of children in menu container + * \return -1 if not found, index in children list otherwise + */ + +int getMlistOrigin( wMenuList_p ml, GList **pChildren ) +{ +	GtkWidget *mi; +	int count = 0; +	int found = -1; +	GtkWidget *mitem = MMENUITEM( ml ); +	 +	*pChildren = gtk_container_get_children( GTK_CONTAINER( MPARENT( ml )->menu )); +	if( !*pChildren ) +		return( -1 ); +	 +	while( (mi = g_list_nth_data( *pChildren, count ))) { +		if( mi == mitem ) { +			found = TRUE; +			break; +		}	 +		else { +			count++; +		}	 +	} +	 +	if( found ) +		return( count ); +	else  +		return( -1 ); +} + +/** + * Signal handler for clicking onto a menu list item.  + * Parameters are the GtkWidget as expected and the pointer to the MenuListItem + * + * \param widget IN the GtkWidget + * \param value  IN the menu list item  + * \return + */ + +static void pushMenuList( +	GtkWidget * widget, +	gpointer value ) +{ +	// pointer to the list item +	wMenuListItem_p ml = (wMenuListItem_p)value; + +	if (MRECURSION( ml )) +		return; +	 +	if (ml->mlist->count <= 0) { +		// this should never happen +		fprintf( stderr, "pushMenuItem: empty list\n" ); +		return; +	} +	// this is the applications callback routine +	if (ml->mlist->action) { +		const char * itemLabel; + +		itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( widget )); +		 +		ml->mlist->action( 0, itemLabel, ml->data );	 +		return; +	} +	fprintf( stderr, "pushMenuItem: item (%lx) not found\n", (long)widget ); +} + +/** + * Create a list menu entry  + * + * \param m 		IN menu to be extended + * \param helpStr 	IN reference into help + * \param max 		IN maximum number of elements + * \param action 	IN callback function  + * \return menu entry + */ + +wMenuList_p wMenuListCreate( +	wMenu_p m,  +	const char * helpStr, +	int max, +	wMenuListCallBack_p action ) +{ +	wMenuList_p mi; +	mi = (wMenuList_p)createMenuItem( m, M_LIST, NULL, _("<Empty List>"), sizeof( struct wMenuList_t )); +	gtk_widget_set_sensitive( GTK_WIDGET(MMENUITEM( mi )), FALSE ); +	mi->next = NULL; +	mi->count = 0; +	mi->max = max; +	MPARENT( mi ) = m; +	mi->action = action; +	return (wMenuList_p)mi; +} + + +/** + * Add a new item to a list of menu entries + * The placeholder for the list is looked up. Then the new item is added immediately  + * behind it. In case the maximum number of items is reached the last item is removed. + * + * \param ml 		IN handle for the menu list - the placeholder item + * \param index 	IN currently ignored + * \param labelStr 	IN the menu label for the new item  + * \param data 		IN application data for the new item + * \return     + */ + +void wMenuListAdd( +	wMenuList_p ml, +	int index, +	const char * labelStr, +	const void * data ) +{ +	int i = 0; +	GList * children; + +	i = getMlistOrigin( ml, &children ); +	 +	if( i > -1 ) { +		wMenuListItem_p mi; + +		// we're adding an item, so hide the default placeholder +		gtk_widget_hide( MMENUITEM( ml )); +		 +		// delete an earlier entry with the same label +		wMenuListDelete( ml, labelStr );		 + +		// a new item +		ml->count ++; +		 +		// is there a maximum number of items set and reached with the new item? +		if(( ml->max != -1 ) && ( ml->count > ml-> max )) { +			wMenuListItem_p mold; +			GtkWidget * item; +	 +			// get the last item in the list +			item = g_list_nth_data( children, i + ml->max ); +			// get the pointer to the data structure +			mold = g_object_get_data( G_OBJECT( item ), WLISTITEM ); +			// kill the menu entry +			gtk_widget_destroy( item ); +			// free the data  +			free( (void *)mold->labelStr ); +			free( (void *)mold ); + +			ml->count--; +		}	 +		 +		// create the new menu item and initialize the data fields +		mi = (wMenuListItem_p)wlibAlloc( NULL, B_MENUITEM, 0, 0, labelStr, sizeof( struct wMenuListItem_t ), NULL ); +		MITEMTYPE( mi ) = M_LISTITEM; +		MMENUITEM( mi ) = gtk_menu_item_new_with_label(wlibConvertInput(mi->labelStr)); +		mi->data = (void *)data; +		mi->mlist = ml; +		g_object_set_data( G_OBJECT(MMENUITEM( mi )), WLISTITEM,  mi ); +		 +		// add the item to the menu +		gtk_menu_shell_insert((GtkMenuShell *)(MPARENT( ml )->menu), MMENUITEM( mi ), i + 1 ); +		g_signal_connect( GTK_OBJECT(MMENUITEM( mi )), "activate", G_CALLBACK(pushMenuList), mi ); +	 +		gtk_widget_show(MMENUITEM( mi )); +	} +	 +	if( children ) +		g_list_free( children ); +} + +/** + * Remove the menu entry identified by a given label. + * + * \param ml IN menu list + * \param labelStr IN label string of item  + */ + +void wMenuListDelete( +	wMenuList_p ml, +	const char * labelStr ) +{ +	int i; +	int found = FALSE; +	GList * children; + +	// find the placeholder for the list in the menu +	i = getMlistOrigin( ml, &children ); +	 +	if( i > -1 ) { +		int origin; +		GtkWidget * item;			 +		char * labelStrConverted; +		 +		// starting from the placeholder, find the menu item with the correct text +		found = FALSE; +		labelStrConverted = wlibConvertInput( labelStr ); +		origin = i; +		 +		// get menu item +		// get label of item +		// compare items +		//    if identical, leave loop +		while( i <= origin + ml->count && !found ) { +			const char * itemLabel; +			 +			item = g_list_nth_data( children, i ); +			itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( item )); +			if( !g_utf8_collate (itemLabel, labelStrConverted )) +				found = TRUE; +			else +				i++; +		} +		if( found ) { +			wMenuListItem_p mold; + +			mold = g_object_get_data( G_OBJECT( item ), WLISTITEM ); +			// kill the menu entry +			gtk_widget_destroy( item ); +			// free the data  +			free( (void *)mold->labelStr ); +			free( (void *)mold ); + +			ml->count--;	 +		} +	}	 +	 +	if( children ) +		g_list_free( children ); +} + +/** + * Get the label and the application data of a specific menu list item + * + * \param ml 	IN menu list  + * \param index IN item within list + * \param data	OUT	application data + * \return    item label + */ + +const char *  +wMenuListGet( wMenuList_p ml, int index, void ** data ) +{ +	int i; + +	GList * children; +	const char * itemLabel = NULL; +	 +	// check whether index is in range, if not return immediately +	if ( index >= ml->count || ml->count <= 0 ) { +		if (data) +			*data = NULL; +		return NULL; +	} +	 +	// find the placeholder for the list in the menu +	i = getMlistOrigin( ml, &children ); +	 +	if( i > -1 ) { +		GtkWidget * item; +		wMenuListItem_p mold; + +		item = g_list_nth_data( children, i + index + 1 ); +		itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( item )); +		mold = g_object_get_data( G_OBJECT( GTK_MENU_ITEM( item ) ), WLISTITEM ); +		*data = mold->data; +	} +	 +	if( children ) +		g_list_free( children ); +	 +	return itemLabel; +} + +/** + * Remove all items from menu list + * + * \param ml 	IN menu item list + */ + +void wMenuListClear( +	wMenuList_p ml ) +{ +	int origin; +	GList * children; + +	if (ml->count == 0) +		return; + +	origin = getMlistOrigin( ml, &children ); +		 +	if( origin > -1 ) { +		int i; + +		i = origin; +		while( i < origin + ml->count ) { +			wMenuListItem_p mold; +			GtkWidget * item; +			 +			item = g_list_nth_data( children, i + 1 ); +			mold = g_object_get_data( G_OBJECT( item ), WLISTITEM ); +			// kill the menu entry +			gtk_widget_destroy( item ); +			// free the data  +			free( (void *)mold->labelStr ); +			free( (void *)mold ); +			i++; +		}	 +	}	 + +	ml->count = 0; +	gtk_widget_show( MMENUITEM( ml )); +	 +	if( children ) +		g_list_free( children ); +} +/*-----------------------------------------------------------------*/ +/** + * Create a check box as part of a menu + * + * \param m 		IN menu to be extended + * \param helpStr 	IN reference into help + * \param labelStr 	IN text for entry + * \param acclKey 	IN acceleratoor key to add + * \param set 		IN initial state + * \param action 	IN callback function   + * \param data 		IN application data + * \return menu entry + */ + +wMenuToggle_p wMenuToggleCreate( +	wMenu_p m,  +	const char * helpStr, +	const char * labelStr, +	long acclKey, +	wBool_t set, +	wMenuToggleCallBack_p action, +	void * data ) +{ +	wMenuToggle_p mt; + +	mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof( struct wMenuToggle_t )); +	setAcclKey( m->parent, m->menu, MMENUITEM( mt ), acclKey ); +	mt->action = action; +	mt->data = data; +	mt->enabled = TRUE; +	MPARENT( mt ) = m; +	wMenuToggleSet( mt, set ); +	 +	return mt; +} + +/** + * Get the state of a menu check box + * + * \param mt 		IN menu to be extended + * \return current state + */ + +wBool_t wMenuToggleGet( +	wMenuToggle_p mt ) +{ +	return mt->set; +} + +/** + * Set a menu check box active / inactive + * + * \param mt 		IN menu to be extended + * \param set 		IN new state + * \return previous state + */ + +wBool_t wMenuToggleSet( +	wMenuToggle_p mt, +	wBool_t set ) +{ +	wBool_t rc; +	if (mt==NULL) return 0; +	MRECURSION( mt )++; +	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(MMENUITEM( mt )), set ); +	MRECURSION( mt )--; +	rc = mt->set; +	mt->set = set; +	return rc; +} + +/** + * Enable menu entry containing a check box + * + * \param mi 		IN menu entry + * \param enable 	IN new state  + * \return + */ + +void wMenuToggleEnable( +	wMenuToggle_p mt, +	wBool_t enable ) +{ +	mt->enabled = enable; +} + + +/*-----------------------------------------------------------------*/ + +/** + * Set the text for a menu  + * + * \param m 		IN menu entry + * \param labelStr 	IN new text + * \return + */ + +void wMenuSetLabel( wMenu_p m, const char * labelStr) { +	wlibSetLabel( m->widget, m->option, labelStr, &m->labelG, &m->imageG ); +} + +/** + * Signal handler for menu items. Parameters are the GtkWidget as  + * expected and the pointer to the MenuListItem + * + * \param widget IN the GtkWidget + * \param value  IN the menu list item  + * \return + */ + +static gint pushMenu( +	GtkWidget * widget, +	wMenu_p m ) +{ +	gtk_menu_popup( GTK_MENU(m->menu), NULL, NULL, NULL, NULL, 0, 0 ); +	/* Tell calling code that we have handled this event; the buck +	 * stops here. */ +	return TRUE; +} + +/** + * Create a button with a drop down menu + * + * \param parent 	IN parent window + * \param x 		IN x position + * \param y 		IN y position + * \param helpStr 	IN help anchor string + * \param labelStr  IN label for menu + * \param option    IN options (Whatever they are) + * \return pointer to the created menu + */ + +wMenu_p wMenuCreate( +	wWin_p	parent, +	wPos_t	x, +	wPos_t	y, +	const char 	* helpStr, +	const char	* labelStr, +	long	option ) +{ +	wMenu_p m; +	m = wlibAlloc( parent, B_MENU, x, y, labelStr, sizeof( struct wMenu_t ), NULL ); +	m->mmtype = MM_BUTT; +	m->option = option; +	m->traceFunc = NULL; +	m->traceData = NULL; +	wlibComputePos( (wControl_p)m ); + +	m->widget = gtk_button_new(); +	g_signal_connect (GTK_OBJECT(m->widget), "clicked", +			G_CALLBACK(pushMenu), m ); + +	m->menu = gtk_menu_new(); + +	wMenuSetLabel( m, labelStr ); +	 +	gtk_fixed_put( GTK_FIXED(parent->widget), m->widget, m->realX, m->realY ); +	wlibControlGetSize( (wControl_p)m ); +	if ( m->w < 80 && (m->option&BO_ICON)==0) { +		m->w = 80; +		gtk_widget_set_size_request( m->widget, m->w, m->h ); +	} +	gtk_widget_show( m->widget ); +	wlibAddButton( (wControl_p)m ); +	wlibAddHelpString( m->widget, helpStr ); +	return m; +} + +/** + * Add a drop-down menu to the menu bar.  + * + * \param w 		IN main window handle  + * \param helpStr 	IN unused (should be help topic ) + * \param labelStr 	IN label for the drop-down menu  + * \return    pointer to the created drop-down menu + */ + +wMenu_p wMenuBarAdd( +	wWin_p w, +	const char * helpStr, +	const char * labelStr ) +{ +	wMenu_p m; +	GtkWidget * menuItem; +	 +	m = wlibAlloc( w, B_MENU, 0, 0, labelStr, sizeof( struct wMenu_t ), NULL ); +	m->mmtype = MM_BAR; +	m->realX = 0; +	m->realY = 0; +	 +	menuItem = gtk_menu_item_new_with_mnemonic( wlibConvertInput(m->labelStr) ); +	m->menu = gtk_menu_new(); +	gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), m->menu ); +	gtk_menu_shell_append( GTK_MENU_SHELL(w->menubar), menuItem ); +	gtk_widget_show( menuItem ); + +	m->w = 0; +	m->h = 0; +	 +	/* TODO: why is help not supported here? */ +	/*gtkAddHelpString( m->panel_item, helpStr );*/ +	 +	return m; +} + + +/*-----------------------------------------------------------------*/ + +/** + * Create a popup menu (context menu) + * + * \param w 		IN parent window + * \param labelStr 	IN label  + * \return    the created menu + */ + +wMenu_p wMenuPopupCreate( +	wWin_p w, +	const char * labelStr ) +{ +	wMenu_p b; +	b = wlibAlloc( w, B_MENU, 0, 0, labelStr, sizeof *b, NULL ); +	b->mmtype = MM_POPUP; +	b->option = 0; + +	b->menu = gtk_menu_new(); +	b->w = 0; +	b->h = 0; +	g_signal_connect( GTK_OBJECT (b->menu), "key_press_event", +			G_CALLBACK(catch_shift_ctrl_alt_keys), b); +	g_signal_connect( GTK_OBJECT (b->menu), "key_release_event", +			G_CALLBACK (catch_shift_ctrl_alt_keys), b); +	gtk_widget_set_events ( GTK_WIDGET(b->menu), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK ); +	return b; +} + +/** + * Show a context menu + * + * \param mp IN the context menu + */ + +void wMenuPopupShow( wMenu_p mp ) +{ +	gtk_menu_popup( GTK_MENU(mp->menu), NULL, NULL, NULL, NULL, 0, 0 ); +} + + +/*-----------------------------------------------------------------*/ + +/** + * ?? Seems to be related to macro / automatic playback functionality + * + * \param m 	IN  + * \param func 	IN  + * \param data 	IN  + */ + +void wMenuSetTraceCallBack( +	wMenu_p m, +	wMenuTraceCallBack_p func, +	void * data ) +{ +	m->traceFunc = func; +	m->traceData = data; +} + +/** + * ??? same as above  + * \param m 	IN  + * \param label IN  + * \return    describe the return value + */ + +wBool_t wMenuAction( +	wMenu_p m, +	const char * label ) +{ +	wMenuItem_p mi; +	wMenuToggle_p mt; +	for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) { +		if ( strcmp( mi->labelStr, label ) == 0 ) { +			switch( MITEMTYPE( mi )) { +			case M_SEPARATOR: +				break; +			case M_PUSH: +				if ( ((wMenuPush_p)mi)->enabled == FALSE ) +					wBeep(); +				else +					((wMenuPush_p)mi)->action( ((wMenuPush_p)mi)->data ); +				break; +			case M_TOGGLE: +				mt = (wMenuToggle_p)mi; +				if ( mt->enabled == FALSE ) { +					wBeep(); +				} else { +					wMenuToggleSet( mt, !mt->set ); +					mt->action( mt->set, mt->data ); +				} +				break; +			case M_MENU: +				break; +			case M_LIST: +				break; +			default: +				/*fprintf(stderr, "Oops: wMenuAction\n");*/ +			break; +			} +			return TRUE; +		} +	} +	return FALSE; +} diff --git a/app/wlib/gtklib/message.c b/app/wlib/gtklib/message.c new file mode 100644 index 0000000..396b696 --- /dev/null +++ b/app/wlib/gtklib/message.c @@ -0,0 +1,168 @@ +/** \file message.c + * Message line + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdlib.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +/* + ***************************************************************************** + * + * Message Boxes + * + ***************************************************************************** + */ + +struct wMessage_t { +    WOBJ_COMMON +    GtkWidget * labelWidget; +    const char * message; +    wPos_t labelWidth; +}; + +/** + * Set the message text + * + * \param b IN widget + * \param arg IN new text + * \return + */ + +void wMessageSetValue( +    wMessage_p b, +    const char * arg) +{ +    if (b->widget == 0) { +        abort(); +    } + +    gtk_label_set_text(GTK_LABEL(b->labelWidget), wlibConvertInput(arg)); +} + +/** + * Set the width of the widget + * + * \param b IN widget + * \param width IN  new width + * \return + */ + +void wMessageSetWidth( +    wMessage_p b, +    wPos_t width) +{ +    b->labelWidth = width; +    gtk_widget_set_size_request(b->widget, width, -1); +} + +/** + * Get height of message text + * \todo Constant height doesn't make sense, change to use the window's properties and retrieve the real font size + * + * \param flags IN text properties (large or small size) + * \return text height + */ + +wPos_t wMessageGetHeight( +    long flags) +{ +    return 14; +} + +/** + * Create a window for a simple text. + * + * \param IN parent Handle of parent window + * \param IN x position in x direction + * \param IN y position in y direction + * \param IN labelStr ??? + * \param IN width horizontal size of window + * \param IN message message to display ( null terminated ) + * \param IN flags display options + * \return handle for created window + */ + + wMessage_p wMessageCreateEx( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* labelStr, +    wPos_t	width, +    const char	*message, +    long flags) +{ +    wMessage_p b; +    GtkRequisition requisition; +    GtkStyle *style; +    PangoFontDescription *fontDesc; +    int fontSize; +    b = (wMessage_p)wlibAlloc(parent, B_MESSAGE, x, y, NULL, sizeof *b, NULL); +    wlibComputePos((wControl_p)b); +    b->message = message; +    b->labelWidth = width; +    b->labelWidget = gtk_label_new(message?wlibConvertInput(message):""); + +    /* do we need to set a special font? */ +    if (wMessageSetFont(flags))	{ +        /* get the current font descriptor */ +        style = gtk_widget_get_style(GTK_WIDGET(b->labelWidget)); +        fontDesc = style->font_desc; +        /* get the current font size */ +        fontSize = PANGO_PIXELS(pango_font_description_get_size(fontDesc)); + +        /* calculate the new font size */ +        if (flags & BM_LARGE) { +            pango_font_description_set_size(fontDesc, fontSize * 1.4 * PANGO_SCALE); +        } else { +            pango_font_description_set_size(fontDesc, fontSize * 0.7 * PANGO_SCALE); +        } + +        /* set the new font size */ +        gtk_widget_modify_font((GtkWidget *)b->labelWidget, fontDesc); +    } + +    b->widget = gtk_fixed_new(); +    gtk_widget_size_request(GTK_WIDGET(b->labelWidget), &requisition); +    gtk_container_add(GTK_CONTAINER(b->widget), b->labelWidget); +    gtk_widget_set_size_request(b->widget, width?width:requisition.width, +                                requisition.height); +    wlibControlGetSize((wControl_p)b); +    gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); +    gtk_widget_show(b->widget); +    gtk_widget_show(b->labelWidget); +    wlibAddButton((wControl_p)b); + +    /* Reset font size to normal */ +    if (wMessageSetFont(flags))	{ +        pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE); +    } + +    return b; +} diff --git a/app/wlib/gtklib/notice.c b/app/wlib/gtklib/notice.c new file mode 100644 index 0000000..cf4b59f --- /dev/null +++ b/app/wlib/gtklib/notice.c @@ -0,0 +1,297 @@ +/** \file notice.c + * Misc. message type windows + * + * Copyright 2016 Martin Fischer <m_fischer@sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <signal.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +#include "i18n.h" + +static char * wlibChgMnemonic(char *label); + +typedef struct { +    GtkWidget * win; +    GtkWidget * label; +    GtkWidget * butt[3]; +} notice_win; +static notice_win noticeW; +static long noticeValue; + +/** + * + * @param widget IN + * @param value IN + */ + +static void doNotice( +    GtkWidget * widget, +    long value) +{ +    noticeValue = value; +    gtk_widget_destroy(noticeW.win); +    wlibDoModal(NULL, FALSE); +} + +/** + * Show a notification window with a yes/no reply and an icon. + * + * \param type IN type of message: Information, Warning, Error + * \param msg  IN message to display + * \param yes  IN text for accept button + * \param no   IN text for cancel button + * \return    True when accept was selected, false otherwise + */ + +int wNoticeEx(int type, +              const char * msg, +              const char * yes, +              const char * no) +{ + +    int res; +    unsigned flag; +    char *headline; +    GtkWidget *dialog; +    GtkWindow *parent = GTK_WINDOW_TOPLEVEL; + +    switch (type) { +    case NT_INFORMATION: +        flag = GTK_MESSAGE_INFO; +        headline = _("Information"); +        break; + +    case NT_WARNING: +        flag = GTK_MESSAGE_WARNING; +        headline = _("Warning"); +        break; + +    case NT_ERROR: +        flag = GTK_MESSAGE_ERROR; +        headline = _("Error"); +        break; +    } + +    if (gtkMainW) { +        parent = GTK_WINDOW(gtkMainW->gtkwin); +    } + +    dialog = gtk_message_dialog_new(parent, +                                    GTK_DIALOG_DESTROY_WITH_PARENT, +                                    flag, +                                    ((no==NULL)?GTK_BUTTONS_OK:GTK_BUTTONS_YES_NO), +                                    "%s", msg); +    gtk_window_set_title(GTK_WINDOW(dialog), headline); + +    res = gtk_dialog_run(GTK_DIALOG(dialog)); +    gtk_widget_destroy(dialog); + +    return res == GTK_RESPONSE_OK  || res == GTK_RESPONSE_YES; +} + + +/** + * Popup up a notice box with one or two buttons. + * When this notice box is displayed the application is paused and + * will not response to other actions. + * + * @param msg IN message + * @param yes IN first button label + * @param no IN second button label (or NULL) + * @returns TRUE for first FALSE for second button + */ + +int wNotice( +    const char * msg,		/* Message */ +    const char * yes,		/* First button label */ +    const char * no)		/* Second label (or 'NULL') */ +{ +    return wNotice3(msg, yes, no, NULL); +} + +/** \brief Popup a notice box with three buttons. + * + * Popup up a notice box with three buttons. + * When this notice box is displayed the application is paused and + * will not response to other actions. + * + * Pushing the first button returns 1 + * Pushing the second button returns 0 + * Pushing the third button returns -1 + * + * \param msg Text to display in message box + * \param yes First button label + * \param no  Second label (or 'NULL') + * \param cancel Third button label (or 'NULL') + * + * \returns 1, 0 or -1 + */ + +int wNotice3( +    const char * msg,		/* Message */ +    const char * affirmative,		/* First button label */ +    const char * cancel,		/* Second label (or 'NULL') */ +    const char * alternate) +{ +    notice_win *nw; +    GtkWidget * vbox; +    GtkWidget * hbox; +    GtkWidget * hbox1; +    GtkWidget * image; +    nw = ¬iceW; + +    char *aff = NULL; +    char *can = NULL; +    char *alt = NULL; + + +    nw->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + +    gtk_window_set_position(GTK_WINDOW(nw->win), GTK_WIN_POS_CENTER); +    gtk_container_set_border_width(GTK_CONTAINER(nw->win), 0); +    gtk_window_set_resizable(GTK_WINDOW(nw->win), FALSE); +    gtk_window_set_modal(GTK_WINDOW(nw->win), TRUE); +    gtk_window_set_type_hint(GTK_WINDOW(nw->win), GDK_WINDOW_TYPE_HINT_DIALOG); + +    vbox = gtk_vbox_new(FALSE, 12); +    gtk_widget_show(vbox); +    gtk_container_add(GTK_CONTAINER(nw->win), vbox); +    gtk_container_set_border_width(GTK_CONTAINER(vbox), 12); + +    hbox = gtk_hbox_new(FALSE, 12); +    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); +    gtk_widget_show(hbox); + +    image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING, +                                     GTK_ICON_SIZE_DIALOG); +    gtk_widget_show(image); +    gtk_box_pack_start(GTK_BOX(hbox), image, TRUE, TRUE, 0); +    gtk_misc_set_alignment(GTK_MISC(image), 0, 0); + +    /* create the text label, allow GTK to wrap and allow for markup (for future enhancements) */ +    nw->label = gtk_label_new(msg); +    gtk_widget_show(nw->label); +    gtk_box_pack_end(GTK_BOX(hbox), nw->label, TRUE, TRUE, 0); +    gtk_label_set_use_markup(GTK_LABEL(nw->label), FALSE); +    gtk_label_set_line_wrap(GTK_LABEL(nw->label), TRUE); +    gtk_misc_set_alignment(GTK_MISC(nw->label), 0, 0); + +    /* this hbox will include the button bar */ +    hbox1 = gtk_hbox_new(TRUE, 0); +    gtk_widget_show(hbox1); +    gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, TRUE, 0); + +    /* add the respective buttons */ +    aff = wlibChgMnemonic((char *) affirmative); +    nw->butt[ 0 ] = gtk_button_new_with_mnemonic(aff); +    gtk_widget_show(nw->butt[ 0 ]); +    gtk_box_pack_end(GTK_BOX(hbox1), nw->butt[ 0 ], TRUE, TRUE, 0); +    gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 0 ]), 3); +    g_signal_connect(GTK_OBJECT(nw->butt[0]), "clicked", G_CALLBACK(doNotice), +                     (void*)1); +    gtk_widget_set_can_default(nw->butt[ 0 ], TRUE); + +    if (cancel) { +        can = wlibChgMnemonic((char *) cancel); +        nw->butt[ 1 ] = gtk_button_new_with_mnemonic(can); +        gtk_widget_show(nw->butt[ 1 ]); +        gtk_box_pack_end(GTK_BOX(hbox1), nw->butt[ 1 ], TRUE, TRUE, 0); +        gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 1 ]), 3); +        g_signal_connect(GTK_OBJECT(nw->butt[1]), "clicked", G_CALLBACK(doNotice), +                         (void*)0); +        gtk_widget_set_can_default(nw->butt[ 1 ], TRUE); + +        if (alternate) { +            alt = wlibChgMnemonic((char *) alternate); +            nw->butt[ 2 ] = gtk_button_new_with_mnemonic(alt); +            gtk_widget_show(nw->butt[ 2 ]); +            gtk_box_pack_start(GTK_BOX(hbox1), nw->butt[ 2 ], TRUE, TRUE, 0); +            gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 2 ]), 3); +            g_signal_connect(GTK_OBJECT(nw->butt[2]), "clicked", G_CALLBACK(doNotice), +                             (void*)-1); +            gtk_widget_set_can_default(nw->butt[ 2 ], TRUE); +        } +    } + +    gtk_widget_grab_default(nw->butt[ 0 ]); +    gtk_widget_grab_focus(nw->butt[ 0 ]); + +    gtk_widget_show(nw->win); + +    if (gtkMainW) { +        gtk_window_set_transient_for(GTK_WINDOW(nw->win), GTK_WINDOW(gtkMainW->gtkwin)); +        /*		gdk_window_set_group( nw->win->window, gtkMainW->gtkwin->window ); */ +    } + +    wlibDoModal(NULL, TRUE); + +    if (aff) { +        free(aff); +    } + +    if (can) { +        free(can); +    } + +    if (alt) { +        free(alt); +    } + +    return noticeValue; +} + +/* \brief Convert label string from Windows mnemonic to GTK + * + * The first occurence of '&' in the passed string is changed to '_' + * + * \param label the string to convert + * \return pointer to modified string, has to be free'd after usage + * + */ +static +char * wlibChgMnemonic(char *label) +{ +    char *ptr; +    char *cp; + +    cp = strdup(label); + +    ptr = strchr(cp, '&'); + +    if (ptr) { +        *ptr = '_'; +    } + +    return (cp); +} + + diff --git a/app/wlib/gtklib/osxhelp.c b/app/wlib/gtklib/osxhelp.c new file mode 100644 index 0000000..829ec94 --- /dev/null +++ b/app/wlib/gtklib/osxhelp.c @@ -0,0 +1,133 @@ +/** \file osxhelp.c + * use OSX Help system + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2015 Martin Fischer + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#include "gtkint.h" +#include "i18n.h" + +#define HELPCOMMANDPIPE "/tmp/helppipe" +#define EXITCOMMAND "##exit##" +#define HELPERPROGRAM "helphelper" + +static pid_t pidOfChild; +static int handleOfPipe; +extern char *wExecutableName; + +/** + * Create the fully qualified filename for the help helper + * + * \param parent IN path and filename of parent process + * \return filename for the child process + */ + +static +char *ChildProgramFile(char *parentProgram) +{ +    char *startOfFilename; +    char *childProgram; + +    childProgram = malloc(strlen(parentProgram)+ sizeof(HELPERPROGRAM) + 1); +    strcpy(childProgram, parentProgram); +    startOfFilename = strrchr(childProgram, '/'); +    strcpy(startOfFilename + 1, HELPERPROGRAM); + +    return (childProgram); +} + + +/** + * Invoke the help system to display help for <topic>. + * + * \param topic IN topic string + */ + +void wHelp(const char * topic) +{ +    pid_t newPid; +    int len; +    int status; +    const char html[] = ".html"; +    char *page; +     +    // check whether child already exists +    if (pidOfChild != 0) { +        if (waitpid(pidOfChild, &status, WNOHANG) > 0) { +            // child exited -> clean up +            close(handleOfPipe); +            unlink(HELPCOMMANDPIPE); +            handleOfPipe = 0; +            pidOfChild = 0;		// child exited +        } +    } + +    // (re)start child +    if (pidOfChild == 0) { +        mkfifo(HELPCOMMANDPIPE, 0666); +        newPid = fork();  /* New process starts here */ + +        if (newPid > 0) { +            pidOfChild = newPid; +        } else if (newPid == 0) { +			char *child = ChildProgramFile(wExecutableName); +             +            if (execlp(child, child, NULL) < 0) {   /* never normally returns */ +                exit(8); +            } +             +            free(child); +        } else { /* -1 signifies fork failure */ +            pidOfChild = 0; +            return; +        } +    } + +    if (!handleOfPipe) { +        handleOfPipe = open(HELPCOMMANDPIPE, O_WRONLY); + +        if (handleOfPipe < 0) { +            kill(pidOfChild, SIGKILL);  /* tidy up on next call */ +        } + +    } + +    page = malloc(strlen(topic) + strlen(html) + 1); + +    if (!page) { +        return; +    } + +    strcpy(page, topic); +    strcat(page, html); +    len = strlen(page); + +    write(handleOfPipe, &len, sizeof(int)); +    write(handleOfPipe, page, strlen(page)+1); + +    free(page); +} diff --git a/app/wlib/gtklib/pixbuf.c b/app/wlib/gtklib/pixbuf.c new file mode 100644 index 0000000..7b8d7d1 --- /dev/null +++ b/app/wlib/gtklib/pixbuf.c @@ -0,0 +1,99 @@ +/** \file pixbuf.c + * Create pixbuf from various bitmap formats + */ + +/* + * + * Copyright 2016 Martin Fischer <m_fischer@users.sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <assert.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" + +/** + * Create a pixbuf from a wIcon + * + * \param ip IN widget + * \returns a valid pixbuf + */ + +GdkPixbuf* wlibMakePixbuf( +    wIcon_p ip) +{ +    GdkPixbuf * pixbuf; +    char line0[40]; +    char line2[40]; + +    assert(ip != NULL); + +    if (ip->gtkIconType == gtkIcon_pixmap) { +        pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)ip->bits); +    } else { +	    const char * bits; +	    long rgb; +        int row,col,wb; +	    char ** pixmapData; + +        wb = (ip->w+7)/8; +        pixmapData = (char**)g_malloc((3+ip->h) * sizeof *pixmapData); +        pixmapData[0] = line0; +        rgb = wDrawGetRGB(ip->color); +        sprintf(line0, " %d %d 2 1", ip->w, ip->h); +        sprintf(line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF, +                rgb&0xFF); +        pixmapData[1] = ". c None s None"; +        pixmapData[2] = line2; +        bits = ip->bits; + +        for (row = 0; row<ip->h; row++) { +            pixmapData[row+3] = (char*)g_malloc((ip->w+1) * sizeof **pixmapData); + +            for (col = 0; col<ip->w; col++) { +                if (bits[ row*wb+(col>>3) ] & (1<<(col&07))) { +                    pixmapData[row+3][col] = '#'; +                } else { +                    pixmapData[row+3][col] = '.'; +                } +            } + +            pixmapData[row+3][ip->w] = 0; +        } + +        pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)pixmapData); + +        for (row = 0; row<ip->h; row++) { +            g_free(pixmapData[row+3]); +        } +    } + +    return pixbuf; +} + + diff --git a/app/wlib/gtklib/png.c b/app/wlib/gtklib/png.c new file mode 100644 index 0000000..e11869e --- /dev/null +++ b/app/wlib/gtklib/png.c @@ -0,0 +1,64 @@ +/** \file png.c + * PNG creation  + */ + +/*  XTrackCad - Model Railroad CAD + *  Copyright (C) 2015 Martin Fischer + * + *  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-1307, USA. + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include "gtkint.h" + +#define BITMAPFILEFORMAT "png" + +/** +* Export as bitmap file. +* +* \param d IN the drawing area ? +* \param fileName IN  fully qualified filename for the bitmap file. +* \return    TRUE on success, FALSE on error +*/ + +wBool_t wBitMapWriteFile(wDraw_p d, const char * fileName) +{ +    GdkPixbuf *pixbuf; +    GError *error; +    gboolean res; +    pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkWindow*)d->pixmap, NULL, 0, 0, +                                          0, 0, d->w, d->h); + +    if (!pixbuf) { +        wNoticeEx(NT_ERROR, "WriteBitMap: pixbuf_get failed", "Ok", NULL); +        return FALSE; +    } + +    error = NULL; +    res = gdk_pixbuf_save(pixbuf, fileName, BITMAPFILEFORMAT, &error, NULL); + +    if (res == FALSE) { +        wNoticeEx(NT_ERROR, "WriteBitMap: pixbuf_save failed", "Ok", NULL); +        return FALSE; +    } + +    g_object_unref(pixbuf); +    return TRUE; +} diff --git a/app/wlib/gtklib/print.c b/app/wlib/gtklib/print.c index 9f4a4a8..c0993f4 100644 --- a/app/wlib/gtklib/print.c +++ b/app/wlib/gtklib/print.c @@ -20,25 +20,22 @@   *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   */ -#include <sys/types.h> -#include <stdio.h>  #include <stdlib.h> -#include <time.h> -#include <pwd.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h>  #ifdef HAVE_MALLOC_H  #include <malloc.h>  #endif  #include <math.h> -#include <locale.h> -#include <stdint.h> +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h>  #include "gtkint.h" -#include <gtk/gtkprintunixdialog.h> -#include <gtk/gtkprintjob.h> +#include <gtk/gtkunixprint.h>  #include "wlib.h"  #include "i18n.h" @@ -79,7 +76,8 @@ extern struct wDraw_t psPrint_d;  static wBool_t printContinue;	/**< control print job, FALSE for cancelling */  static wIndex_t pageCount;		/**< unused, could be used for progress indicator */ -static wIndex_t totalPageCount; /**< unused, could be used for progress indicator */ +static wIndex_t +totalPageCount; /**< unused, could be used for progress indicator */  static double paperWidth;		/**< physical paper width */  static double paperHeight;		/**< physical paper height */ @@ -96,7 +94,7 @@ static long printFormat = PRINT_LANDSCAPE;   *   */ -static void WlibGetPaperSize( void ); +static void WlibGetPaperSize(void);  /**   * Initialize printer und paper selection using the saved settings @@ -106,57 +104,64 @@ static void WlibGetPaperSize( void );   */  void -WlibApplySettings( GtkPrintOperation *op ) +WlibApplySettings(GtkPrintOperation *op)  { -	gchar *filename; -	GError *err = NULL; -	GtkWidget *dialog; - -	filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL ); - -	if( !(settings = gtk_print_settings_new_from_file( filename, &err ))) { -		if( err->code != G_FILE_ERROR_NOENT ) { -			// ignore file not found error as defaults will be used -			dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin), -											 GTK_DIALOG_DESTROY_WITH_PARENT, -											 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -				                             err->message); -			gtk_dialog_run (GTK_DIALOG (dialog)); -			gtk_widget_destroy (dialog); -		} else { -			// create  default print settings -			settings = gtk_print_settings_new(); -		}	 -		g_error_free (err); -	} -	g_free( filename ); - -	if (settings && op ) -			gtk_print_operation_set_print_settings (op, settings); - -	err = NULL; -	filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL ); -	if( !(page_setup = gtk_page_setup_new_from_file( filename, &err ))) { -		// ignore file not found error as defaults will be used -		if( err->code != G_FILE_ERROR_NOENT ) { -			dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin), -											 GTK_DIALOG_DESTROY_WITH_PARENT, -											 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -				                             err->message); -			gtk_dialog_run (GTK_DIALOG (dialog)); -			gtk_widget_destroy (dialog); -		} else { -			page_setup = gtk_page_setup_new(); -		}	 -		g_error_free (err); -	} else { -		// on success get the paper dimensions -		WlibGetPaperSize(); -	} -	g_free( filename ); - -	if( page_setup && op ) -		gtk_print_operation_set_default_page_setup (op, page_setup); +    gchar *filename; +    GError *err = NULL; +    GtkWidget *dialog; + +    filename = g_build_filename(wGetAppWorkDir(), PRINTSETTINGS, NULL); + +    if (!(settings = gtk_print_settings_new_from_file(filename, &err))) { +        if (err->code != G_FILE_ERROR_NOENT) { +            // ignore file not found error as defaults will be used +            dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                            GTK_DIALOG_DESTROY_WITH_PARENT, +                                            GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                            err->message); +            gtk_dialog_run(GTK_DIALOG(dialog)); +            gtk_widget_destroy(dialog); +        } else { +            // create  default print settings +            settings = gtk_print_settings_new(); +        } + +        g_error_free(err); +    } + +    g_free(filename); + +    if (settings && op) { +        gtk_print_operation_set_print_settings(op, settings); +    } + +    err = NULL; +    filename = g_build_filename(wGetAppWorkDir(), PAGESETTINGS, NULL); + +    if (!(page_setup = gtk_page_setup_new_from_file(filename, &err))) { +        // ignore file not found error as defaults will be used +        if (err->code != G_FILE_ERROR_NOENT) { +            dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                            GTK_DIALOG_DESTROY_WITH_PARENT, +                                            GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                            err->message); +            gtk_dialog_run(GTK_DIALOG(dialog)); +            gtk_widget_destroy(dialog); +        } else { +            page_setup = gtk_page_setup_new(); +        } + +        g_error_free(err); +    } else { +        // on success get the paper dimensions +        WlibGetPaperSize(); +    } + +    g_free(filename); + +    if (page_setup && op) { +        gtk_print_operation_set_default_page_setup(op, page_setup); +    }  } @@ -168,75 +173,87 @@ WlibApplySettings( GtkPrintOperation *op )   */  void -WlibSaveSettings( GtkPrintOperation *op ) +WlibSaveSettings(GtkPrintOperation *op)  { -	GError *err = NULL; -	gchar *filename; -	GtkWidget *dialog; - -	if( op ) { -		if (settings != NULL) -			g_object_unref (settings); -		settings = g_object_ref (gtk_print_operation_get_print_settings (op)); -	} -    filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL ); -    if( !gtk_print_settings_to_file( settings, filename, &err )) { -		dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin), -                                     GTK_DIALOG_DESTROY_WITH_PARENT, -                                     GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -				                             err->message); - -		g_error_free (err); -		gtk_dialog_run (GTK_DIALOG (dialog)); -		gtk_widget_destroy (dialog); -	} -	g_free( filename ); - -	if( op ) { -		if (page_setup != NULL) -			g_object_unref (page_setup); -		page_setup = g_object_ref (gtk_print_operation_get_default_page_setup (op)); -	} -    filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL ); -    if( !gtk_page_setup_to_file( page_setup, filename, &err )) { -		dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin), -                                     GTK_DIALOG_DESTROY_WITH_PARENT, -                                     GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -				                             err->message); - -		g_error_free (err); -		gtk_dialog_run (GTK_DIALOG (dialog)); -		gtk_widget_destroy (dialog); -	} -	g_free( filename ); +    GError *err = NULL; +    gchar *filename; +    GtkWidget *dialog; + +    if (op) { +        if (settings != NULL) { +            g_object_unref(settings); +        } + +        settings = g_object_ref(gtk_print_operation_get_print_settings(op)); +    } + +    filename = g_build_filename(wGetAppWorkDir(), PRINTSETTINGS, NULL); + +    if (!gtk_print_settings_to_file(settings, filename, &err)) { +        dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                        GTK_DIALOG_DESTROY_WITH_PARENT, +                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                        err->message); + +        g_error_free(err); +        gtk_dialog_run(GTK_DIALOG(dialog)); +        gtk_widget_destroy(dialog); +    } + +    g_free(filename); + +    if (op) { +        if (page_setup != NULL) { +            g_object_unref(page_setup); +        } + +        page_setup = g_object_ref(gtk_print_operation_get_default_page_setup(op)); +    } + +    filename = g_build_filename(wGetAppWorkDir(), PAGESETTINGS, NULL); + +    if (!gtk_page_setup_to_file(page_setup, filename, &err)) { +        dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                        GTK_DIALOG_DESTROY_WITH_PARENT, +                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                        err->message); + +        g_error_free(err); +        gtk_dialog_run(GTK_DIALOG(dialog)); +        gtk_widget_destroy(dialog); +    } + +    g_free(filename);  }  /** - * Page setup function. Previous settings are loaded and the setup  + * Page setup function. Previous settings are loaded and the setup   * dialog is shown. The settings are saved after the dialog ends.   *   * \param callback IN unused   */ -void wPrintSetup( wPrintSetupCallBack_p callback ) +void wPrintSetup(wPrintSetupCallBack_p callback)  { -	GtkPageSetup *new_page_setup; -	gchar *filename; -	GError *err; -	GtkWidget *dialog; - -	WlibApplySettings( NULL ); - -	new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (gtkMainW->gtkwin), -														page_setup, settings); -	if (page_setup) -		g_object_unref (page_setup); - -	page_setup = new_page_setup; -	 -	WlibGetPaperSize(); -	WlibSaveSettings( NULL ); +    GtkPageSetup *new_page_setup; +    gchar *filename; +    GError *err; +    GtkWidget *dialog; + +    WlibApplySettings(NULL); + +    new_page_setup = gtk_print_run_page_setup_dialog(GTK_WINDOW(gtkMainW->gtkwin), +                     page_setup, settings); + +    if (page_setup) { +        g_object_unref(page_setup); +    } + +    page_setup = new_page_setup; + +    WlibGetPaperSize(); +    WlibSaveSettings(NULL);  }  /***************************************************************************** @@ -257,27 +274,29 @@ void wPrintSetup( wPrintSetupCallBack_p callback )  static void setLineType( -		double lineWidth, -		wDrawLineType_e lineType, -		wDrawOpts opts ) +    double lineWidth, +    wDrawLineType_e lineType, +    wDrawOpts opts)  { -	cairo_t *cr = psPrint_d.printContext; -	double dashLength = DASH_LENGTH; -	 -	if (lineWidth < 0.0) { -		lineWidth = P2I(-lineWidth)*2.0; -	} - -	// make sure that there is a minimum line width used -	if ( lineWidth == 0.0 ) -		lineWidth = 0.1; -	 -	cairo_set_line_width( cr, lineWidth ); - -	if (lineType == wDrawLineDash) -		cairo_set_dash( cr, &dashLength, 1, 0.0 ); -	else	 -		cairo_set_dash( cr, NULL, 0, 0.0 ); +    cairo_t *cr = psPrint_d.printContext; +    double dashLength = DASH_LENGTH; + +    if (lineWidth < 0.0) { +        lineWidth = P2I(-lineWidth)*2.0; +    } + +    // make sure that there is a minimum line width used +    if (lineWidth == 0.0) { +        lineWidth = 0.1; +    } + +    cairo_set_line_width(cr, lineWidth); + +    if (lineType == wDrawLineDash) { +        cairo_set_dash(cr, &dashLength, 1, 0.0); +    } else { +        cairo_set_dash(cr, NULL, 0, 0.0); +    }  }  /** @@ -288,14 +307,14 @@ static void setLineType(   */  static void psSetColor( -		wDrawColor color ) +    wDrawColor color)  { -	cairo_t *cr = psPrint_d.printContext; -	GdkColor* const gcolor = gtkGetColor(color, TRUE); +    cairo_t *cr = psPrint_d.printContext; +    GdkColor* const gcolor = wlibGetColor(color, TRUE); -	cairo_set_source_rgb(cr, gcolor->red / 65535.0, -							 gcolor->green / 65535.0, -							 gcolor->blue / 65535.0); +    cairo_set_source_rgb(cr, gcolor->red / 65535.0, +                         gcolor->green / 65535.0, +                         gcolor->blue / 65535.0);  }  /** @@ -310,26 +329,29 @@ static void psSetColor(   */  void psPrintLine( -		wPos_t x0, wPos_t y0, -		wPos_t x1, wPos_t y1, -		wDrawWidth width, -		wDrawLineType_e lineType, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t x0, wPos_t y0, +    wPos_t x1, wPos_t y1, +    wDrawWidth width, +    wDrawLineType_e lineType, +    wDrawColor color, +    wDrawOpts opts)  { -	if (color == wDrawColorWhite) -		return; -	if (opts&wDrawOptTemp) -		return; - -	psSetColor(color); -	setLineType( width, lineType, opts ); - -	cairo_move_to( psPrint_d.printContext, -					x0, y0 ); -	cairo_line_to( psPrint_d.printContext, -					x1, y1 ); -	cairo_stroke( psPrint_d.printContext ); +    if (color == wDrawColorWhite) { +        return; +    } + +    if (opts&wDrawOptTemp) { +        return; +    } + +    psSetColor(color); +    setLineType(width, lineType, opts); + +    cairo_move_to(psPrint_d.printContext, +                  x0, y0); +    cairo_line_to(psPrint_d.printContext, +                  x1, y1); +    cairo_stroke(psPrint_d.printContext);  }  /** @@ -346,46 +368,65 @@ void psPrintLine(   */  void psPrintArc( -		wPos_t x0, wPos_t y0, -		wPos_t r, -		double angle0, -		double angle1, -		wBool_t drawCenter, -		wDrawWidth width, -		wDrawLineType_e lineType, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t x0, wPos_t y0, +    wPos_t r, +    double angle0, +    double angle1, +    wBool_t drawCenter, +    wDrawWidth width, +    wDrawLineType_e lineType, +    wDrawColor color, +    wDrawOpts opts)  { -	cairo_t *cr = psPrint_d.printContext; - -	if (color == wDrawColorWhite) -		return; -	if (opts&wDrawOptTemp) -		return; - -	psSetColor(color); -	setLineType(width, lineType, opts); - -	if (angle1 >= 360.0) -		angle1 = 359.999; -	angle1 = 90.0-(angle0+angle1); -	while (angle1 < 0.0) angle1 += 360.0; -	while (angle1 >= 360.0) angle1 -= 360.0; -	angle0 = 90.0-angle0; -	while (angle0 < 0.0) angle0 += 360.0; -	while (angle0 >= 360.0) angle0 -= 360.0; - -	// draw the curve -	cairo_arc( cr, x0, y0, r, angle1 * M_PI / 180.0, angle0 * M_PI / 180.0 ); - -	if( drawCenter ) { -		// draw crosshair for center of curve -		cairo_move_to( cr, x0 - CENTERMARK_LENGTH / 2, y0 ); -		cairo_line_to( cr, x0 + CENTERMARK_LENGTH / 2, y0 ); -		cairo_move_to( cr, x0, y0 - CENTERMARK_LENGTH / 2 ); -		cairo_line_to( cr, x0, y0 + CENTERMARK_LENGTH / 2 ); -	} -	cairo_stroke( psPrint_d.printContext ); +    cairo_t *cr = psPrint_d.printContext; + +    if (color == wDrawColorWhite) { +        return; +    } + +    if (opts&wDrawOptTemp) { +        return; +    } + +    psSetColor(color); +    setLineType(width, lineType, opts); + +    if (angle1 >= 360.0) { +        angle1 = 359.999; +    } + +    angle1 = 90.0-(angle0+angle1); + +    while (angle1 < 0.0) { +        angle1 += 360.0; +    } + +    while (angle1 >= 360.0) { +        angle1 -= 360.0; +    } + +    angle0 = 90.0-angle0; + +    while (angle0 < 0.0) { +        angle0 += 360.0; +    } + +    while (angle0 >= 360.0) { +        angle0 -= 360.0; +    } + +    // draw the curve +    cairo_arc(cr, x0, y0, r, angle1 * M_PI / 180.0, angle0 * M_PI / 180.0); + +    if (drawCenter) { +        // draw crosshair for center of curve +        cairo_move_to(cr, x0 - CENTERMARK_LENGTH / 2, y0); +        cairo_line_to(cr, x0 + CENTERMARK_LENGTH / 2, y0); +        cairo_move_to(cr, x0, y0 - CENTERMARK_LENGTH / 2); +        cairo_line_to(cr, x0, y0 + CENTERMARK_LENGTH / 2); +    } + +    cairo_stroke(psPrint_d.printContext);  }  /** @@ -399,24 +440,28 @@ void psPrintArc(   */  void psPrintFillRectangle( -		wPos_t x0, wPos_t y0, -		wPos_t x1, wPos_t y1, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t x0, wPos_t y0, +    wPos_t x1, wPos_t y1, +    wDrawColor color, +    wDrawOpts opts)  { -	cairo_t *cr = psPrint_d.printContext; -	double width = x0 - x1; -	double height = y0 - y1; +    cairo_t *cr = psPrint_d.printContext; +    double width = x0 - x1; +    double height = y0 - y1; + +    if (color == wDrawColorWhite) { +        return; +    } -	if (color == wDrawColorWhite) -		return; -	if (opts&wDrawOptTemp) -		return; -	psSetColor(color); +    if (opts&wDrawOptTemp) { +        return; +    } -	cairo_rectangle( cr, x0, y0, width, height ); +    psSetColor(color); -	cairo_fill( cr ); +    cairo_rectangle(cr, x0, y0, width, height); + +    cairo_fill(cr);  }  /** @@ -430,25 +475,31 @@ void psPrintFillRectangle(   */  void psPrintFillPolygon( -		wPos_t p[][2], -		int cnt, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t p[][2], +    int cnt, +    wDrawColor color, +    wDrawOpts opts)  { -	int inx; -	cairo_t *cr = psPrint_d.printContext; +    int inx; +    cairo_t *cr = psPrint_d.printContext; + +    if (color == wDrawColorWhite) { +        return; +    } -	if (color == wDrawColorWhite) -		return; -	if (opts&wDrawOptTemp) -		return; +    if (opts&wDrawOptTemp) { +        return; +    } -	psSetColor(color); +    psSetColor(color); -	cairo_move_to( cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ] ); -	for (inx=0; inx<cnt; inx++) -		cairo_line_to( cr, p[ inx ][ 0 ], p[ inx ][ 1 ] ); -	cairo_fill( cr ); +    cairo_move_to(cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ]); + +    for (inx=0; inx<cnt; inx++) { +        cairo_line_to(cr, p[ inx ][ 0 ], p[ inx ][ 1 ]); +    } + +    cairo_fill(cr);  }  /** @@ -462,21 +513,25 @@ void psPrintFillPolygon(   */  void psPrintFillCircle( -		wPos_t x0, wPos_t y0, -		wPos_t r, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t x0, wPos_t y0, +    wPos_t r, +    wDrawColor color, +    wDrawOpts opts)  { -	if (color == wDrawColorWhite) -		return; -	if (opts&wDrawOptTemp) -		return; -	psSetColor(color); +    if (color == wDrawColorWhite) { +        return; +    } + +    if (opts&wDrawOptTemp) { +        return; +    } -	cairo_arc( psPrint_d.printContext, -				x0, y0, r, 0.0, 2 * M_PI ); +    psSetColor(color); -	cairo_fill( psPrint_d.printContext ); +    cairo_arc(psPrint_d.printContext, +              x0, y0, r, 0.0, 2 * M_PI); + +    cairo_fill(psPrint_d.printContext);  } @@ -503,75 +558,78 @@ void psPrintFillCircle(   */  void psPrintString( -		wPos_t x, wPos_t y, -		double a, -		char * s, -		wFont_p fp, -		double fs, -		wDrawColor color, -		wDrawOpts opts ) +    wPos_t x, wPos_t y, +    double a, +    char * s, +    wFont_p fp, +    double fs, +    wDrawColor color, +    wDrawOpts opts)  { -	char * cp; -	double x0 = (double)x, y0 = (double)y; -	double text_height; - -	cairo_t *cr; -	cairo_matrix_t matrix; - -	PangoLayout *layout; -	PangoFontDescription *desc; -	PangoFontMetrics *metrics; -	PangoContext *pcontext; - -	if (color == wDrawColorWhite) -		return; - -	cr = psPrint_d.printContext; - -	// get the current transformation matrix and transform the starting -	// point of the string -	cairo_get_matrix( cr, &matrix ); -	cairo_matrix_transform_point( &matrix, &x0, &y0 ); - -	cairo_save( cr ); - -	layout = pango_cairo_create_layout( cr ); - -	// set the correct font and size -	/** \todo use a getter function instead of double conversion */ -	desc = pango_font_description_from_string (gtkFontTranslate( fp )); - -	//don't know why the size has to be reduced to 75% :-( -	pango_font_description_set_size(desc, fs * PANGO_SCALE *0.75 ); - -	// render the string to a Pango layout -	pango_layout_set_font_description (layout, desc); -	pango_layout_set_text (layout, s, -1); -	pango_layout_set_width (layout, -1); -	pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); - -	// get the height of the string -	pcontext = pango_cairo_create_context( cr ); -	metrics = pango_context_get_metrics(pcontext, desc, pango_context_get_language(pcontext)); -	text_height = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; -	 -	// transform the string to the correct position -	cairo_identity_matrix( cr ); -	 -	cairo_translate( cr, x0 + text_height * sin ( -a * M_PI / 180.0) , y0 - text_height * cos ( a * M_PI / 180.0) ); -	cairo_rotate( cr, -a * M_PI / 180.0  ); -	 -	// set the color -	psSetColor( color ); - -	// and show the string -	pango_cairo_show_layout (cr, layout); - -	// free unused objects -	g_object_unref( layout ); -	g_object_unref( pcontext ); - -	cairo_restore( cr ); +    char * cp; +    double x0 = (double)x, y0 = (double)y; +    double text_height; + +    cairo_t *cr; +    cairo_matrix_t matrix; + +    PangoLayout *layout; +    PangoFontDescription *desc; +    PangoFontMetrics *metrics; +    PangoContext *pcontext; + +    if (color == wDrawColorWhite) { +        return; +    } + +    cr = psPrint_d.printContext; + +    // get the current transformation matrix and transform the starting +    // point of the string +    cairo_get_matrix(cr, &matrix); +    cairo_matrix_transform_point(&matrix, &x0, &y0); + +    cairo_save(cr); + +    layout = pango_cairo_create_layout(cr); + +    // set the correct font and size +    /** \todo use a getter function instead of double conversion */ +    desc = pango_font_description_from_string(wlibFontTranslate(fp)); + +    //don't know why the size has to be reduced to 75% :-( +    pango_font_description_set_size(desc, fs * PANGO_SCALE *0.75); + +    // render the string to a Pango layout +    pango_layout_set_font_description(layout, desc); +    pango_layout_set_text(layout, s, -1); +    pango_layout_set_width(layout, -1); +    pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); + +    // get the height of the string +    pcontext = pango_cairo_create_context(cr); +    metrics = pango_context_get_metrics(pcontext, desc, +                                        pango_context_get_language(pcontext)); +    text_height = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; + +    // transform the string to the correct position +    cairo_identity_matrix(cr); + +    cairo_translate(cr, x0 + text_height * sin(-a * M_PI / 180.0) , +                    y0 - text_height * cos(a * M_PI / 180.0)); +    cairo_rotate(cr, -a * M_PI / 180.0); + +    // set the color +    psSetColor(color); + +    // and show the string +    pango_cairo_show_layout(cr, layout); + +    // free unused objects +    g_object_unref(layout); +    g_object_unref(pcontext); + +    cairo_restore(cr);  }  /** @@ -579,17 +637,17 @@ void psPrintString(   *   * \param x, y IN starting position   * \param w, h IN width and height of rectangle - * \return     + * \return   */ -void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h ) +void wPrintClip(wPos_t x, wPos_t y, wPos_t w, wPos_t h)  { -	cairo_move_to( psPrint_d.printContext, x, y ); -	cairo_rel_line_to( psPrint_d.printContext, w, 0 ); -	cairo_rel_line_to( psPrint_d.printContext, 0, h ); -	cairo_rel_line_to( psPrint_d.printContext, -w, 0 ); -	cairo_close_path( psPrint_d.printContext ); -	cairo_clip( psPrint_d.printContext ); +    cairo_move_to(psPrint_d.printContext, x, y); +    cairo_rel_line_to(psPrint_d.printContext, w, 0); +    cairo_rel_line_to(psPrint_d.printContext, 0, h); +    cairo_rel_line_to(psPrint_d.printContext, -w, 0); +    cairo_close_path(psPrint_d.printContext); +    cairo_clip(psPrint_d.printContext);  }  /***************************************************************************** @@ -604,24 +662,24 @@ void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h )   */  static void -WlibGetPaperSize( void ) +WlibGetPaperSize(void)  { -	double temp; -	 -	bBorder = gtk_page_setup_get_bottom_margin( page_setup, GTK_UNIT_INCH ); -	tBorder = gtk_page_setup_get_top_margin( page_setup, GTK_UNIT_INCH ); -	lBorder = gtk_page_setup_get_left_margin( page_setup, GTK_UNIT_INCH ); -	rBorder = gtk_page_setup_get_right_margin( page_setup, GTK_UNIT_INCH ); -	paperHeight = gtk_page_setup_get_paper_height( page_setup, GTK_UNIT_INCH ); -	paperWidth = gtk_page_setup_get_paper_width( page_setup, GTK_UNIT_INCH ); -	 -	// XTrackCAD does page orientation itself. Basic assumption is that the -	// paper is always oriented in portrait mode. Ignore settings by user -	if( paperHeight < paperWidth ) { -		temp = paperHeight; -		paperHeight = paperWidth; -		paperWidth = temp; -	}	 +    double temp; + +    bBorder = gtk_page_setup_get_bottom_margin(page_setup, GTK_UNIT_INCH); +    tBorder = gtk_page_setup_get_top_margin(page_setup, GTK_UNIT_INCH); +    lBorder = gtk_page_setup_get_left_margin(page_setup, GTK_UNIT_INCH); +    rBorder = gtk_page_setup_get_right_margin(page_setup, GTK_UNIT_INCH); +    paperHeight = gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH); +    paperWidth = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH); + +    // XTrackCAD does page orientation itself. Basic assumption is that the +    // paper is always oriented in portrait mode. Ignore settings by user +    if (paperHeight < paperWidth) { +        temp = paperHeight; +        paperHeight = paperWidth; +        paperWidth = temp; +    }  }  /** @@ -633,17 +691,18 @@ WlibGetPaperSize( void )   */  void wPrintGetPageSize( -		double * w, -		double * h ) +    double * w, +    double * h)  { -	// if necessary load the settings -	if( !settings ) -		WlibApplySettings( NULL ); +    // if necessary load the settings +    if (!settings) { +        WlibApplySettings(NULL); +    } -	WlibGetPaperSize(); +    WlibGetPaperSize(); -	*w = paperWidth -lBorder - rBorder; -	*h = paperHeight - tBorder - bBorder; +    *w = paperWidth -lBorder - rBorder; +    *h = paperHeight - tBorder - bBorder;  }  /** @@ -655,52 +714,53 @@ void wPrintGetPageSize(   */  void wPrintGetPhysSize( -		double * w, -		double * h ) +    double * w, +    double * h)  { -	// if necessary load the settings -	if( !settings ) -		WlibApplySettings( NULL ); +    // if necessary load the settings +    if (!settings) { +        WlibApplySettings(NULL); +    } -	WlibGetPaperSize(); +    WlibGetPaperSize(); -	*w = paperWidth; -	*h = paperHeight; +    *w = paperWidth; +    *h = paperHeight;  }  /** - * Cancel the current print job. This function is preserved here for  - * reference in case the function should be implemented again.  + * Cancel the current print job. This function is preserved here for + * reference in case the function should be implemented again.   * \param context IN unused   * \return   */ -static void printAbort( void * context ) +static void printAbort(void * context)  { -	printContinue = FALSE; +    printContinue = FALSE;  //	wWinShow( printAbortW, FALSE );  }  /**   * Initialize new page.   * The cairo_save() / cairo_restore() cycle was added to solve problems - * with a multi page print operation. This might actually be a bug in  + * with a multi page print operation. This might actually be a bug in   * cairo but I didn't examine that any further.   *   * \return   print context for the print operation   */ -wDraw_p wPrintPageStart( void ) +wDraw_p wPrintPageStart(void)  { -	pageCount++; +    pageCount++; -	cairo_save( psPrint_d.printContext ); -	 -	return &psPrint_d; +    cairo_save(psPrint_d.printContext); + +    return &psPrint_d;  }  /**   * End of page. This function returns the contents of printContinue. The - * caller continues printing as long as TRUE is returned. Setting  - * printContinue to FALSE in an asynchronous handler therefore cleanly  + * caller continues printing as long as TRUE is returned. Setting + * printContinue to FALSE in an asynchronous handler therefore cleanly   * terminates a print job at the end of the page.   *   * \param p IN ignored @@ -708,13 +768,13 @@ wDraw_p wPrintPageStart( void )   */ -wBool_t wPrintPageEnd( wDraw_p p ) +wBool_t wPrintPageEnd(wDraw_p p)  { -	cairo_show_page( psPrint_d.printContext ); -	 -	cairo_restore( psPrint_d.printContext ); -	 -	return printContinue; +    cairo_show_page(psPrint_d.printContext); + +    cairo_restore(psPrint_d.printContext); + +    return printContinue;  }  /***************************************************************************** @@ -733,76 +793,91 @@ wBool_t wPrintPageEnd( wDraw_p p )   * \return TRUE if successful, FALSE if cancelled by user   */ -wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP ) +wBool_t wPrintDocStart(const char * title, int fTotalPageCount, int * copiesP)  { -	GtkWidget *printDialog; -	gint res; -	cairo_surface_type_t surface_type; -	cairo_matrix_t matrix; - -	printDialog = gtk_print_unix_dialog_new( title, GTK_WINDOW(gtkMainW->gtkwin)); - -	// load the settings -	WlibApplySettings( NULL ); - -	// and apply them to the printer dialog -	gtk_print_unix_dialog_set_settings( (GtkPrintUnixDialog *)printDialog, settings ); -	gtk_print_unix_dialog_set_page_setup( (GtkPrintUnixDialog *)printDialog, page_setup ); - -	res = gtk_dialog_run( (GtkDialog *)printDialog ); -	if( res == GTK_RESPONSE_OK ) { -		selPrinter = gtk_print_unix_dialog_get_selected_printer( (GtkPrintUnixDialog *)printDialog ); - -		if( settings ) -			g_object_unref (settings); -		settings = gtk_print_unix_dialog_get_settings( (GtkPrintUnixDialog *)printDialog ); - -		if( page_setup ) -			g_object_unref( page_setup ); -		page_setup = gtk_print_unix_dialog_get_page_setup( (GtkPrintUnixDialog *)printDialog ); - -		curPrintJob = gtk_print_job_new( title, -							 selPrinter, -							 settings, -							 page_setup ); - -		psPrint_d.curPrintSurface = gtk_print_job_get_surface( curPrintJob, -								   NULL ); -		psPrint_d.printContext = cairo_create( psPrint_d.curPrintSurface ); - -		//update the paper dimensions -		WlibGetPaperSize(); - -		/* for the file based surfaces the resolution is 72 dpi (see documentation) */ -		surface_type = cairo_surface_get_type( psPrint_d.curPrintSurface ); -		if( surface_type == CAIRO_SURFACE_TYPE_PDF || -			surface_type == CAIRO_SURFACE_TYPE_PS  || -			surface_type == CAIRO_SURFACE_TYPE_SVG ) -			psPrint_d.dpi = 72; -		else -			psPrint_d.dpi = (double)gtk_print_settings_get_resolution( settings ); -		 -		// in XTrackCAD 0,0 is top left, in cairo bottom left. This is  -		// corrected via the following transformations.  -		// also the translate makes sure that the drawing is rendered -		// within the paper margins -		 -		cairo_scale( psPrint_d.printContext, 1.0, -1.0 ); -		cairo_translate( psPrint_d.printContext, lBorder * psPrint_d.dpi, -(paperHeight-bBorder) *psPrint_d.dpi ); - -		WlibSaveSettings( NULL ); -	} -	gtk_widget_destroy (printDialog); - -	if (copiesP) -		*copiesP = 1; - -	printContinue = TRUE; -	 -	if( res != GTK_RESPONSE_OK ) -		return FALSE; -	else -		return TRUE; +    GtkWidget *printDialog; +    gint res; +    cairo_surface_type_t surface_type; +    cairo_matrix_t matrix; + +    printDialog = gtk_print_unix_dialog_new(title, GTK_WINDOW(gtkMainW->gtkwin)); + +    // load the settings +    WlibApplySettings(NULL); + +    // and apply them to the printer dialog +    gtk_print_unix_dialog_set_settings((GtkPrintUnixDialog *)printDialog, settings); +    gtk_print_unix_dialog_set_page_setup((GtkPrintUnixDialog *)printDialog, +                                         page_setup); + +    res = gtk_dialog_run((GtkDialog *)printDialog); + +    if (res == GTK_RESPONSE_OK) { +        selPrinter = gtk_print_unix_dialog_get_selected_printer(( +                         GtkPrintUnixDialog *)printDialog); + +        if (settings) { +            g_object_unref(settings); +        } + +        settings = gtk_print_unix_dialog_get_settings((GtkPrintUnixDialog *) +                   printDialog); + +        if (page_setup) { +            g_object_unref(page_setup); +        } + +        page_setup = gtk_print_unix_dialog_get_page_setup((GtkPrintUnixDialog *) +                     printDialog); + +        curPrintJob = gtk_print_job_new(title, +                                        selPrinter, +                                        settings, +                                        page_setup); + +        psPrint_d.curPrintSurface = gtk_print_job_get_surface(curPrintJob, +                                    NULL); +        psPrint_d.printContext = cairo_create(psPrint_d.curPrintSurface); + +        //update the paper dimensions +        WlibGetPaperSize(); + +        /* for the file based surfaces the resolution is 72 dpi (see documentation) */ +        surface_type = cairo_surface_get_type(psPrint_d.curPrintSurface); + +        if (surface_type == CAIRO_SURFACE_TYPE_PDF || +                surface_type == CAIRO_SURFACE_TYPE_PS  || +                surface_type == CAIRO_SURFACE_TYPE_SVG) { +            psPrint_d.dpi = 72; +        } else { +            psPrint_d.dpi = (double)gtk_print_settings_get_resolution(settings); +        } + +        // in XTrackCAD 0,0 is top left, in cairo bottom left. This is +        // corrected via the following transformations. +        // also the translate makes sure that the drawing is rendered +        // within the paper margins + +        cairo_scale(psPrint_d.printContext, 1.0, -1.0); +        cairo_translate(psPrint_d.printContext, lBorder * psPrint_d.dpi, +                        -(paperHeight-bBorder) *psPrint_d.dpi); + +        WlibSaveSettings(NULL); +    } + +    gtk_widget_destroy(printDialog); + +    if (copiesP) { +        *copiesP = 1; +    } + +    printContinue = TRUE; + +    if (res != GTK_RESPONSE_OK) { +        return FALSE; +    } else { +        return TRUE; +    }  }  /** @@ -815,17 +890,18 @@ wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP )   */  void -doPrintJobFinished( GtkPrintJob *job, void *data, GError *err ) +doPrintJobFinished(GtkPrintJob *job, void *data, GError *err)  { -	GtkWidget *dialog; - -	cairo_destroy( psPrint_d.printContext ); -	if( err ) { -		dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin), -                                     GTK_DIALOG_DESTROY_WITH_PARENT, -                                     GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -                                     err->message); -	} +    GtkWidget *dialog; + +    cairo_destroy(psPrint_d.printContext); + +    if (err) { +        dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                        GTK_DIALOG_DESTROY_WITH_PARENT, +                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                        err->message); +    }  }  /** @@ -833,26 +909,26 @@ doPrintJobFinished( GtkPrintJob *job, void *data, GError *err )   * \return   */ -void wPrintDocEnd( void ) +void wPrintDocEnd(void)  { -	cairo_surface_finish( psPrint_d.curPrintSurface ); +    cairo_surface_finish(psPrint_d.curPrintSurface); -	gtk_print_job_send( curPrintJob, -						doPrintJobFinished, -						NULL, -						NULL ); +    gtk_print_job_send(curPrintJob, +                       doPrintJobFinished, +                       NULL, +                       NULL);  //	wWinShow( printAbortW, FALSE );  } -wBool_t wPrintQuit( void ) +wBool_t wPrintQuit(void)  { -	return FALSE; +    return FALSE;  } -wBool_t wPrintInit( void ) +wBool_t wPrintInit(void)  { -	return TRUE; +    return TRUE;  } diff --git a/app/wlib/gtklib/single.c b/app/wlib/gtklib/single.c new file mode 100644 index 0000000..45ed6e4 --- /dev/null +++ b/app/wlib/gtklib/single.c @@ -0,0 +1,335 @@ +/** \file single.c + * Single line entry field for text + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis, 2012 Martin Fischer + * + *  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-1307, USA. + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +// #define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <gtk/gtk.h> +#include <glib-object.h> + +#include "gtkint.h" + +#define TIMEOUT_INACTIVITY (500)  	/**< timeout for entry fields in millisecs */ + +/* + ***************************************************************************** + * + * Text Boxes + * + ***************************************************************************** + */ + +struct wString_t { +	WOBJ_COMMON +	char *valueP;			/**< pointer to result buffer */ +	wIndex_t valueL;	 	/**< maximum length */ +	wStringCallBack_p action;  	/**< callback for changes */ +	wBool_t busy;		 	/**< busy flag to prevent re-entry problems? */	 +	wBool_t hasSignal;		/** needs signal to be suppressed */ +	guint	timer;			/**< timer source for inactivity timer */ +}; + +/** + * Set the string value in a string entry field + * + * \param b 	IN widget to be updated + * \param arg 	IN new string value + * \return  + */ + +void wStringSetValue( +    wString_p b, +    const char *arg)  +{ +	if (b->widget == NULL) +		abort(); +	 +	// the contents should not be changed programatically while +	// the user is editing it +	if( !(gtk_widget_has_focus(b->widget))) { +		if (b->hasSignal)  +	    	gtk_signal_handler_block_by_data(GTK_OBJECT(b->widget), b); +		gtk_entry_set_text(GTK_ENTRY(b->widget), arg); +		if (b->hasSignal) +			gtk_signal_handler_unblock_by_data(GTK_OBJECT(b->widget), b); +	} +} + +/** + * Set the width of the entry field + * + * \param b 	IN widget to be updated + * \param w 	IN new width + * \return  + */ + +void wStringSetWidth( +    wString_p b, +    wPos_t w)  +{ +	gtk_widget_set_size_request(b->widget, w, -1); +	b->w = w; +} + +/** + * Return the entered value + * + * \param b IN entry field + * \return   the entered text + */ + +const char *wStringGetValue( +    wString_p b)  +{ +	if ( !b->widget )  +		abort(); +	 +	return gtk_entry_get_text(GTK_ENTRY(b->widget)); +} + +/** + * Kill an active timer + * + * \param b IN entry field + * \return   the entered text + */ + +static gboolean killTimer( +    GtkEntry *widget, +	GdkEvent *event, +    wString_p b)  +{ + +	// remove all timers related to this widget	 +	while( g_source_remove_by_user_data( b )) +		; +	b->timer = 0; +	 +	if (b->action) { +		const char *s; +		 +		s = gtk_entry_get_text(GTK_ENTRY(b->widget)); +		b->action(s, b->data); +	} +	gtk_editable_select_region( GTK_EDITABLE( widget ), 0, 0 ); +	return( FALSE ); +}	 + +/** + *	Timer handler for string activity. This timer expires if the user + * 	doesn't change an entry value within the preset time.  + */ + +static gboolean +timeoutString( wString_p bs )  +{ + +	if ( !bs ) +		return( FALSE ); +	if (bs->widget == 0)  +		abort(); +	 +	if (bs->action) { +		const char *s; +		 +		s = gtk_entry_get_text(GTK_ENTRY(bs->widget)); +		if ( s ) +			bs->action(s, bs->data); +	} + +	bs->timer = 0; +	return( FALSE ); +} + +/** + * Signal handler for 'activate' signal: callback with the current value and then  + * select the whole default value + * + * \param widget 	IN the edit field + * \param b 		IN the widget data structure + * \return  + */ + +static gboolean stringActivated( +    GtkEntry *widget, +    wString_p b)  +{ +	const char *s; + +	if ( !b ) +		return( FALSE ); +	 +	s = wStringGetValue(b); + +	if (b->valueP) +		strcpy(b->valueP, s); + +	if (b->action) { +		b->action(s, b->data); +	} +	 +	// select the complete default value to make editing it easier +	gtk_editable_select_region( GTK_EDITABLE( widget ), 0, -1 ); +	return( FALSE ); +} + +/** + * Signal handler for changes in an entry field + * + * \param widget 		IN + * \param entry field 	IN + * \return  + */ + +static void stringChanged( +    GtkEntry *widget, +    wString_p b)  +{ +	const char *new_value; + +	if ( !b || b->busy ) +		return; + +	// get the entered value +	new_value = wStringGetValue(b); +	if (b->valueP != NULL) +		strcpy(b->valueP, new_value); +	 +	//  +	if (b->action){ +		// if one exists, remove the inactivity timer +		if( b->timer ) +			g_source_remove( b->timer ); +		 +		// create a new timer +		b->timer = g_timeout_add( TIMEOUT_INACTIVITY, +								  (GSourceFunc)timeoutString,  +								  b ); +		 +	}	 +	return; +} + +/** + * Create a single line entry field for a string value + * + * \param 	parent	IN	parent widget + * \param 	x		IN	x position + * \param 	y		IN	y position + * \param 	helpStr	IN	help anchor + * \param 	labelStr IN label + * \param	option	IN	option (supported BO_READONLY ) + * \param	width	IN	width of entry field	 + * \param	valueP	IN	default value + * \param	valueL	IN 	maximum length of entry  + * \param	action	IN	application callback function + * \param 	data	IN	application data + * \return  the created widget + */ + +wString_p wStringCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	 *helpStr, +    const char	 *labelStr, +    long	option, +    wPos_t	width, +    char	*valueP, +    wIndex_t valueL, +    wStringCallBack_p action, +    void 	*data)  +{ +	wString_p b; + +	// create and initialize the widget	 +	b = (wString_p)wlibAlloc(parent, B_TEXT, x, y, labelStr, sizeof *b, data); +	b->valueP = valueP; +	b->action = action; +	b->option = option; +	b->valueL = valueL; +	b->timer = 0; +	b->hasSignal = 0; +	wlibComputePos((wControl_p)b); + +	// create the gtk entry field and set maximum length if desired	 +	b->widget = (GtkWidget *)gtk_entry_new(); +	if (b->widget == NULL) abort(); + +	if( valueL ) +		gtk_entry_set_max_length( GTK_ENTRY( b->widget ), valueL ); +	 +	// it is assumed that the parent is a fixed layout widget and the entry can +	// be placed at a specific position +	gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); +	 +	// set minimum size for widget	 +	if (width) +		gtk_widget_set_size_request(b->widget, width, -1); +	 +	// get the resulting size +	wlibControlGetSize((wControl_p)b); + +	// if desired, place a label in front of the created widget +	if (labelStr) +		b->labelW = wlibAddLabel((wControl_p)b, labelStr); +	 +	if (option & BO_READONLY) +		gtk_editable_set_editable(GTK_EDITABLE(b->widget), FALSE); +	 +	// set the default text	and select it to make replacing it easier +	if (b->valueP) { +		wStringSetValue(b, b->valueP); +		// select the text only if text is editable +	} +	 +	// show +	gtk_widget_show(b->widget); +	 +	// add the new widget to the list of created widgets +	wlibAddButton((wControl_p)b); +	 +	// link into help  +	wlibAddHelpString(b->widget, helpStr); +	 +	g_signal_connect(GTK_OBJECT(b->widget), "changed", G_CALLBACK(stringChanged), b); +	//g_signal_connect(GTK_OBJECT(b->widget), "activate", G_CALLBACK(stringActivated), b); +	b->hasSignal = 1; +	 +	// set the default text	and select it to make replacing it easier +	if (b->valueP) { +		wStringSetValue(b, b->valueP); +		// select the text only if text is editable +	} + +	gtk_widget_add_events( b->widget, GDK_FOCUS_CHANGE_MASK ); +	g_signal_connect(GTK_OBJECT(b->widget), "focus-out-event", G_CALLBACK(killTimer), b); +	 +	return b; +} diff --git a/app/wlib/gtklib/splash.c b/app/wlib/gtklib/splash.c new file mode 100644 index 0000000..0d5be50 --- /dev/null +++ b/app/wlib/gtklib/splash.c @@ -0,0 +1,144 @@ +/** \file splash.c + * Handling of the Splash Window functions + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2007 Martin Fischer + * + *  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-1307, USA. + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> + +#include "gtkint.h" + +#define LOGOFILENAME "logo.bmp" + +static GtkWidget *window;	/**< splash window handle */ +static GtkWidget *message;	/**< window handle for progress message */ + +/** + * Create the splash window shown during startup. The function loads the logo + * bitmap and displays the program name and version as passed. + * + * \param IN  appName the product name to be shown + * \param IN  appVer  the product version to be shown + * \return    TRUE if window was created, FALSE if an error occured + */ + +int +wCreateSplash(char *appName, char *appVer) +{ +    GtkWidget *vbox; +    GtkWidget *image; +    GtkWidget *label; +    char *temp; +    char logoPath[BUFSIZ]; + +    /* create the basic window */ +    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +    gtk_window_set_decorated(GTK_WINDOW(window), FALSE); +    gtk_window_set_title(GTK_WINDOW(window), appName); +    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); +    gtk_window_set_resizable(GTK_WINDOW(window), FALSE); +    gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); +#if GTK_MINOR_VERSION > 5 +    gtk_window_set_focus_on_map(GTK_WINDOW(window), FALSE); +#endif + +    vbox = gtk_vbox_new(FALSE, 0); +    gtk_widget_show(vbox); +    gtk_container_add(GTK_CONTAINER(window), vbox); + +    /* add the logo image to the top of the splash window */ +    sprintf(logoPath, "%s/" LOGOFILENAME, wGetAppLibDir()); +    image = gtk_image_new_from_file(logoPath); +    gtk_widget_show(image); +    gtk_box_pack_start(GTK_BOX(vbox), image, TRUE, TRUE, 0); +    gtk_misc_set_alignment(GTK_MISC(image), 0, 0); + +    /* put the product name into the window */ + +    temp = malloc(strlen(appName) + strlen(appVer) + 2); + +    if (!temp) { +        return (FALSE); +    } + +    sprintf(temp, "%s %s", appName, appVer); + +    label = gtk_label_new(temp); +    gtk_widget_show(label); +    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); +    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_FILL); +    gtk_label_set_selectable(GTK_LABEL(label), FALSE); +    gtk_misc_set_padding(GTK_MISC(label), 6, 2); + +    free(temp); + +    label = gtk_label_new("Application is starting..."); +    gtk_widget_show(label); +    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); +    gtk_label_set_line_wrap(GTK_LABEL(label), FALSE); +    gtk_misc_set_padding(GTK_MISC(label), 6, 2); +#if GTK_MINOR_VERSION > 5 +    gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START); +#endif +    message = label; + +    gtk_widget_show(window); + +    return (TRUE); +} + +/** + * Update the progress message inside the splash window + * msg	text message to display + * return nonzero if ok + */ + +int +wSetSplashInfo(char *msg) +{ +    if (msg) { +        gtk_label_set_text((GtkLabel *)message, msg); +        wFlush(); +        return TRUE; +    } + +    return FALSE; +} + +/** + * Destroy the splash window. + * + */ + +void +wDestroySplash(void) +{ +    /* kill window */ +    gtk_widget_destroy(window); +    return; +} diff --git a/app/wlib/gtklib/square10.bmp b/app/wlib/gtklib/square10.bmp deleted file mode 100644 index b2eee6e..0000000 --- a/app/wlib/gtklib/square10.bmp +++ /dev/null @@ -1,8 +0,0 @@ -#define square10_width 14 -#define square10_height 14 -// Changed to eliminate compile-time warning -//static unsigned char square10_bits[] = { -static char square10_bits[] = { -   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -   0xff, 0xff, 0xff, 0xff}; diff --git a/app/wlib/gtklib/text.c b/app/wlib/gtklib/text.c new file mode 100644 index 0000000..5445984 --- /dev/null +++ b/app/wlib/gtklib/text.c @@ -0,0 +1,590 @@ +/** \file text.c + * multi line text entry widget + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "i18n.h" +#include "gtkint.h" + +struct PrintData { +    wText_p	tb; +    gint lines_per_page; +    gdouble font_size; +    gchar **lines; +    gint total_lines; +    gint total_pages; +}; + +#define HEADER_HEIGHT 20.0 +#define HEADER_GAP 8.5 + + +/* + ***************************************************************************** + * + * Multi-line Text Boxes + * + ***************************************************************************** + */ + +struct wText_t { +    WOBJ_COMMON +    wPos_t width, height; +    int changed; +    GtkWidget *text; +}; + +/** + * Reset a text entry by clearing text and resetting the readonly and the + * change flag. + * + * \param bt IN text entry + * \return + */ + +void wTextClear(wText_p bt) +{ +    GtkTextBuffer *tb; +    tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text)); +    gtk_text_buffer_set_text(tb, "", -1); + +    if (bt->option & BO_READONLY) { +        gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), FALSE); +    } + +    bt->changed = FALSE; +} + +/** + * Append text to the end of the entry field's text buffer. + * + * \param bt IN text buffer + * \param text IN text to append + * \return + */ + +void wTextAppend(wText_p bt, +                 const char *text) +{ +    GtkTextBuffer *tb; +    GtkTextIter ti1; + +    if (bt->text == 0) { +        abort(); +    } + +    tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text)); +    // convert to utf-8 +    text = wlibConvertInput(text); +    // append to end of buffer +    gtk_text_buffer_get_end_iter(tb, &ti1); +    gtk_text_buffer_insert(tb, &ti1, text, -1); +    bt->changed = FALSE; +} + +/** + * Get the text from a text buffer in system codepage + * The caller is responsible for free'ing the allocated storage. + * + * \todo handling of return from gtkConvertOutput can be improved + * + * \param bt IN the text widget + * \return    pointer to the converted text + */ + +static char *wlibGetText(wText_p bt) +{ +    GtkTextBuffer *tb; +    GtkTextIter ti1, ti2; +    char *cp, *cp1, *res; + +    if (bt->text == 0) { +        abort(); +    } + +    tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text)); +    gtk_text_buffer_get_bounds(tb, &ti1, &ti2); +    cp = gtk_text_buffer_get_text(tb, &ti1, &ti2, FALSE); +    cp1 = wlibConvertOutput(cp); +    res = strdup(cp1); +    g_free(cp); +    return res; +} + +/** + * Save the text from the widget to a file + * + * \param bt IN the text widget + * \param fileName IN name of save file + * \return    TRUE is success, FALSE if not + */ + +wBool_t wTextSave(wText_p bt, const char *fileName) +{ +    FILE *f; +    char *cp; +    f = fopen(fileName, "w"); + +    if (f==NULL) { +        wNoticeEx(NT_ERROR, fileName, "Ok", NULL); +        return FALSE; +    } + +    cp = wlibGetText(bt); +    fwrite(cp, 1, strlen(cp), f); +    free(cp); +    fclose(f); +    return TRUE; +} + +/** + * Begin the printing by retrieving the contents of the text box and + * count the lines of text. + * + * \param operation IN the GTK print operation + * \param context IN print context + * \param pd IN data structure for user data + * + */ + +static void +begin_print(GtkPrintOperation *operation, +            GtkPrintContext *context, +            struct PrintData *pd) +{ +    gchar *contents; +    gdouble height; +    contents =  wlibGetText(pd->tb); +    pd->lines = g_strsplit(contents, "\n", 0); +    /* Count the total number of lines in the file. */ +    /* ignore the header lines */ +    pd->total_lines = 6; + +    while (pd->lines[pd->total_lines] != NULL) { +        pd->total_lines++; +    } + +    /* Based on the height of the page and font size, calculate how many lines can be +    * rendered on a single page. A padding of 3 is placed between lines as well. +    * Space for page header, table header and footer lines is subtracted from the total size +    */ +    height = gtk_print_context_get_height(context) - (pd->font_size + 3) - 2 * +             (HEADER_HEIGHT + HEADER_GAP); +    pd->lines_per_page = floor(height / (pd->font_size + 3)); +    pd->total_pages = (pd->total_lines - 1) / pd->lines_per_page + 1; +    gtk_print_operation_set_n_pages(operation, pd->total_pages); +    free(contents); +} + +/** + * Draw the page, which includes a header with the file name and page number along + * with one page of text with a font of "Monospace 10". + * + * \param operation IN the GTK print operation + * \param context IN print context + * \param page_nr IN page to print + * \param pd IN data structure for user data + * + * + */ + +static void +draw_page(GtkPrintOperation *operation, +          GtkPrintContext *context, +          gint page_nr, +          struct PrintData *pd) +{ +    cairo_t *cr; +    PangoLayout *layout; +    gdouble width, text_height, height; +    gint line, i, text_width, layout_height; +    PangoFontDescription *desc; +    gchar *page_str; +    cr = gtk_print_context_get_cairo_context(context); +    width = gtk_print_context_get_width(context); +    layout = gtk_print_context_create_pango_layout(context); +    desc = pango_font_description_from_string("Monospace"); +    pango_font_description_set_size(desc, pd->font_size * PANGO_SCALE); +    /* +     * render the header line with document type parts list on left and +     * first line of layout title on right +     */ +    pango_layout_set_font_description(layout, desc); +    pango_layout_set_text(layout, pd->lines[ 0 ], -1); 	// document type +    pango_layout_set_width(layout, -1); +    pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); +    pango_layout_get_size(layout, NULL, &layout_height); +    text_height = (gdouble) layout_height / PANGO_SCALE; +    cairo_move_to(cr, 0, (HEADER_HEIGHT - text_height) / 2); +    pango_cairo_show_layout(cr, layout); +    pango_layout_set_text(layout, pd->lines[ 2 ], -1);		// layout title +    pango_layout_get_size(layout, &text_width, NULL); +    pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); +    cairo_move_to(cr, width - (text_width / PANGO_SCALE), +                  (HEADER_HEIGHT - text_height) / 2); +    pango_cairo_show_layout(cr, layout); +    /* Render the column header */ +    cairo_move_to(cr, 0, HEADER_HEIGHT + HEADER_GAP + pd->font_size + 3); +    pango_layout_set_text(layout, pd->lines[ 6 ], -1); +    pango_cairo_show_layout(cr, layout); +    cairo_rel_move_to(cr, 0, pd->font_size + 3); +    pango_layout_set_text(layout, pd->lines[ 7 ], -1); +    pango_cairo_show_layout(cr, layout); +    /* Render the page text with the specified font and size. */ +    cairo_rel_move_to(cr, 0, pd->font_size + 3); +    line = page_nr * pd->lines_per_page + 8; + +    for (i = 0; i < pd->lines_per_page && line < pd->total_lines; i++) { +        pango_layout_set_text(layout, pd->lines[line], -1); +        pango_cairo_show_layout(cr, layout); +        cairo_rel_move_to(cr, 0, pd->font_size + 3); +        line++; +    } + +    /* +     * Render the footer line with date on the left and page number +     * on the right +     */ +    pango_layout_set_text(layout, pd->lines[ 5 ], -1); 	// date +    pango_layout_set_width(layout, -1); +    pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); +    pango_layout_get_size(layout, NULL, &layout_height); +    text_height = (gdouble) layout_height / PANGO_SCALE; +    height = gtk_print_context_get_height(context); +    cairo_move_to(cr, 0, height - ((HEADER_HEIGHT - text_height) / 2)); +    pango_cairo_show_layout(cr, layout); +    page_str = g_strdup_printf(_("%d of %d"), page_nr + 1, +                               pd->total_pages);  // page number +    pango_layout_set_text(layout, page_str, -1); +    pango_layout_get_size(layout, &text_width, NULL); +    pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); +    cairo_move_to(cr, width - (text_width / PANGO_SCALE), +                  height - ((HEADER_HEIGHT - text_height) / 2)); +    pango_cairo_show_layout(cr, layout); +    g_free(page_str); +    g_object_unref(layout); +    pango_font_description_free(desc); +} + +/** + * Clean up after the printing operation since it is done. + * + * \param operation IN the GTK print operation + * \param context IN print context + * \param pd IN data structure for user data + * + * + */ +static void +end_print(GtkPrintOperation *operation, +          GtkPrintContext *context, +          struct PrintData *pd) +{ +    g_strfreev(pd->lines); +    free(pd); +} + +/** + * Print the content of a multi line text box. This function is only used + * for printing the parts list. So it makes some assumptions on the structure + * and the content. Change if the multi line entry is changed. + * The deprecated gtk_text is not supported by this function. + * + * Thanks to Andrew Krause's book for a good starting point. + * + * \param bt IN the text field + * \return    TRUE on success, FALSE on error + */ + +wBool_t wTextPrint( +    wText_p bt) +{ +    GtkPrintOperation *operation; +    GtkWidget *dialog; +    GError *error = NULL; +    gint res; +    struct PrintData *data; +    /* Create a new print operation, applying saved print settings if they exist. */ +    operation = gtk_print_operation_new(); +    WlibApplySettings(operation); +    data = malloc(sizeof(struct PrintData)); +    data->font_size = 10.0; +    data->tb = bt; +    g_signal_connect(G_OBJECT(operation), "begin_print", +                     G_CALLBACK(begin_print), (gpointer) data); +    g_signal_connect(G_OBJECT(operation), "draw_page", +                     G_CALLBACK(draw_page), (gpointer) data); +    g_signal_connect(G_OBJECT(operation), "end_print", +                     G_CALLBACK(end_print), (gpointer) data); +    /* Run the default print operation that will print the selected file. */ +    res = gtk_print_operation_run(operation, +                                  GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, +                                  GTK_WINDOW(gtkMainW->gtkwin), &error); + +    /* If the print operation was accepted, save the new print settings. */ +    if (res == GTK_PRINT_OPERATION_RESULT_APPLY) { +        WlibSaveSettings(operation); +    } +    /* Otherwise, report that the print operation has failed. */ +    else if (error) { +        dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin), +                                        GTK_DIALOG_DESTROY_WITH_PARENT, +                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, +                                        error->message); +        g_error_free(error); +        gtk_dialog_run(GTK_DIALOG(dialog)); +        gtk_widget_destroy(dialog); +    } + +    g_object_unref(operation); +    return TRUE; +} + + +/** + * Get the length of text + * + * \param bt IN the text widget + * \return    length of string + */ + +int wTextGetSize(wText_p bt) +{ +    char *cp = wlibGetText(bt); +    int len = strlen(cp); +    free(cp); +    return len; +} + +/** + * Get the  text + * + * \param bt IN the text widget + * \param text IN the buffer + * \param len IN maximum number of bytes to return + * \return + */ + +void wTextGetText(wText_p bt, char *text, int len) +{ +    char *cp; +    cp = wlibGetText(bt); +    strncpy(text, cp, len); + +    if (len > 0) { +        text[len - 1] = '\0'; +    } + +    free(cp); +} + +/** + * Get the  read-only state of the text entry + * + * \param bt IN the text widget + * \param ro IN read only flag + * \return + */ + +void wTextSetReadonly(wText_p bt, wBool_t ro) +{ +    gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), !ro); + +    if (ro) { +        bt->option |= BO_READONLY; +    } else { +        bt->option &= ~BO_READONLY; +    } +} + +/** + * check whether text has been modified + * + * \param bt IN the text widget + * \return    TRUE of changed, FALSE otherwise + */ + +wBool_t wTextGetModified(wText_p bt) +{ +    return bt->changed; +} + +/** + * set the size of the text widget + * + * \param bt IN the text widget + * \param w IN width + * \param h IN height + * \return + */ + +void wTextSetSize(wText_p bt, wPos_t w, wPos_t h) +{ +    gtk_widget_set_size_request(bt->widget, w, h); +    bt->w = w; +    bt->h = h; +} + +/** + * calculate the required size of the widget based on number of lines and columns + * \todo this calculation is based on a fixed size font and is not useful in a generic setup + * + * \param bt IN the text widget + * \param rows IN text rows + * \param cols IN text columns + * \param width OUT width in pixel + * \param height OUT height in pixel + * \return + */ + +void wTextComputeSize(wText_p bt, int rows, int cols, wPos_t *width, +                      wPos_t *height) +{ +    *width = rows * 7; +    *height = cols * 14; +} + +/** + * set the position of the text widget ???? + * + * \param bt IN the text widget + * \param pos IN position + * \return + */ + +void wTextSetPosition(wText_p bt, int pos) +{ +    /* TODO */ +} + +/** + * signal handler for changed signal + * + * \param widget IN + * \param bt IN text entry field + * \return + */ + +static void textChanged(GtkWidget *widget, wText_p bt) +{ +    if (bt == 0) { +        return; +    } + +    bt->changed = TRUE; +} + +/** + * Create a multiline text entry field + * + * \param parent IN parent window + * \param x IN x position + * \param Y IN y position + * \param helpStr IN balloon help string + * \param labelStr IN Button label ??? + * \param option IN + * \param width IN + * \param valueP IN Current color ??? + * \param action IN Button callback procedure + * \param data IN ??? + * \return 	bb handle for created text widget + */ + +wText_p +wTextCreate(wWin_p	parent, +            wPos_t	x, +            wPos_t	y, +            const char 	 *helpStr, +            const char	 *labelStr, +            long	option, +            wPos_t	width, +            wPos_t	height) +{ +    wText_p bt; +    GtkTextBuffer *tb; +    // create the widget +    bt = wlibAlloc(parent, B_MULTITEXT, x, y, labelStr, sizeof *bt, NULL); +    bt->width = width; +    bt->height = height; +    bt->option = option; +    wlibComputePos((wControl_p)bt); +    // create a scroll window with scroll bars that are automatically created +    bt->widget = gtk_scrolled_window_new(NULL, NULL); +    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(bt->widget), +                                   GTK_POLICY_AUTOMATIC, +                                   GTK_POLICY_AUTOMATIC); +    // create a text view and place it inside the scroll widget +    bt->text = gtk_text_view_new(); + +    if (bt->text == 0) { +        abort(); +    } + +    gtk_container_add(GTK_CONTAINER(bt->widget), bt->text); +    // get the text buffer and add a bold tag to it +    tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text)); +    gtk_text_buffer_create_tag(tb, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); + +    // this seems to assume some fixed size fonts, not really helpful +    if (option&BT_CHARUNITS) { +        width *= 7; +        height *= 14; +    } + +    // show the widgets +    gtk_widget_show(bt->text); +    gtk_widget_show(bt->widget); +    // set the size??? +    gtk_widget_set_size_request(GTK_WIDGET(bt->widget), +                                width+15/*requisition.width*/, height); + +    // configure read-only mode +    if (bt->option&BO_READONLY) { +        gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), FALSE); +        gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(bt->text), FALSE); +    } + +    if (labelStr) { +        bt->labelW = wlibAddLabel((wControl_p)bt, labelStr); +    } + +    wlibAddHelpString(bt->widget, helpStr); +    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(bt->text), GTK_WRAP_WORD); +    g_signal_connect(G_OBJECT(tb), "changed", G_CALLBACK(textChanged), bt); +    // place the widget in a fixed position of the parent +    gtk_fixed_put(GTK_FIXED(parent->widget), bt->widget, bt->realX, bt->realY); +    wlibControlGetSize((wControl_p)bt); +    wlibAddButton((wControl_p)bt); +    // done, return the finished widget +    return bt; +} diff --git a/app/wlib/gtklib/timer.c b/app/wlib/gtklib/timer.c new file mode 100644 index 0000000..812908f --- /dev/null +++ b/app/wlib/gtklib/timer.c @@ -0,0 +1,144 @@ +/** \file timer.c + * Timer Functions + * + * Copyright 2016 Martin Fischer <m_fischer@sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <sys/time.h> +#include <signal.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +//#include "i18n.h" + +static wBool_t gtkPaused = FALSE; +static int alarmTimer = 0; +static struct timeval startTime; + +static wControl_p triggerControl = NULL; +static setTriggerCallback_p triggerFunc = NULL; + +/** + * Signal handler for alarm timer - executes the defined function when + * timer expires + * + * \param data IN callback function + * \returns alwys 0 + */ + +static gint doAlarm( +    gpointer data) +{ +    wAlarmCallBack_p func = (wAlarmCallBack_p)data; + +    func(); + +    alarmTimer = 0; +    return FALSE; +} + +/** + * Alarm for <count> milliseconds. + * + * \param count IN time to wait + * \param func IN function called when timer expires + */ + +void wAlarm( +    long count, +    wAlarmCallBack_p func)		/* milliseconds */ +{ +    gtkPaused = TRUE; + +    if (alarmTimer) { +        g_source_remove(alarmTimer); +    } + +    alarmTimer = g_timeout_add(count, doAlarm, (void *)(GSourceFunc)func); +} + +static void doTrigger(void) +{ +    if (triggerControl && triggerFunc) { +        triggerFunc(triggerControl); +        triggerFunc = NULL; +        triggerControl = NULL; +    } +} + +void wlibSetTrigger( +    wControl_p b, +    setTriggerCallback_p trigger) +{ +    triggerControl = b; +    triggerFunc = trigger; +    wAlarm(500, doTrigger); +} + +/** + * Pause for <count> milliseconds. + * + * \param count IN + */ + +void wPause( +    long count)		/* milliseconds */ +{ +    struct timeval timeout; +    sigset_t signal_mask; +    sigset_t oldsignal_mask; +    gdk_display_sync(gdk_display_get_default()); +    timeout.tv_sec = count/1000; +    timeout.tv_usec = (count%1000)*1000; +    sigemptyset(&signal_mask); +    sigaddset(&signal_mask, SIGIO); +    sigaddset(&signal_mask, SIGALRM); +    sigprocmask(SIG_BLOCK, &signal_mask, &oldsignal_mask); + +    if (select(0, NULL, NULL, NULL, &timeout) == -1) { +        perror("wPause:select"); +    } + +    sigprocmask(SIG_BLOCK, &oldsignal_mask, NULL); +} + +/** + * Get time expired since start??? + * \todo Check where start time is initialized!!! + * + * \returns time in seconds + */ + +unsigned long wGetTimer(void) +{ +    struct timeval tv; +    struct timezone tz; +     +    gettimeofday(&tv, &tz); +    return (tv.tv_sec-startTime.tv_sec+1) * 1000 + tv.tv_usec /1000; +} diff --git a/app/wlib/gtklib/tooltip.c b/app/wlib/gtklib/tooltip.c new file mode 100644 index 0000000..15b46d2 --- /dev/null +++ b/app/wlib/gtklib/tooltip.c @@ -0,0 +1,255 @@ +/** \file tooltip.c
 + * Code for tooltip / balloon help functions
 + */
 +
 +/*  XTrkCad - Model Railroad CAD
 + *  Copyright (C)  2012 Martin Fischer
 + *
 + *  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-1307, USA.
 + */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <assert.h>
 +
 +#define GTK_DISABLE_SINGLE_INCLUDES
 +#define GDK_DISABLE_DEPRECATED
 +#define GTK_DISABLE_DEPRECATED
 +#define GSEAL_ENABLE
 +
 +#include <gtk/gtk.h>
 +#include <gdk/gdk.h>
 +
 +#include "gtkint.h"
 +#include "i18n.h"
 +
 +wBool_t listHelpStrings = FALSE;
 +wBool_t listMissingHelpStrings = FALSE;
 +
 +static wBalloonHelp_t * balloonHelpStrings;
 +static int enableBalloonHelp = TRUE;
 +
 +static GtkWidget * balloonF; 	/**< balloon help control for hotbar item */
 +static GtkWidget * balloonPI;
 +
 +static const char * balloonMsg = NULL;
 +static wControl_p balloonB;
 +static wPos_t balloonDx, balloonDy;
 +static wBool_t balloonVisible = FALSE;
 +
 +
 +/**
 + * Hide the currently displayed Balloon Help.
 + */
 + 
 +void
 +wlibHelpHideBalloon()
 +{
 +    wControlSetBalloon( balloonB, 0, 0, NULL );
 +}
 +
 +/**
 + * Initialize tooltip array
 + *
 + * \param bh IN pointer to list of tooltips
 + * \return
 + */
 +
 +void wSetBalloonHelp( wBalloonHelp_t * bh )
 +{
 +    balloonHelpStrings = bh;
 +}
 +
 +/**
 + * Switch tooltips on and off
 + *
 + * \param enable IN desired state (TRUE or FALSE )
 + * \return
 + */
 +
 +void wEnableBalloonHelp( int enable )
 +{
 +    enableBalloonHelp = enable;
 +}
 +
 +/**
 + * Set the help topic string for <b> to <help>.
 + *
 + * \param b IN control
 + * \param help IN tip
 + */
 +
 +void wControlSetHelp(
 +    wControl_p b,
 +    const char * help )
 +{
 +    wControlSetBalloonText( b, help );
 +}
 +
 +/**
 + * Set the help topic string for <b> to <help>.
 + *
 + * \param b IN control
 + * \param help IN tip
 + */
 +
 +void wControlSetBalloonText(
 +    wControl_p b,
 +    const char * label )
 +{
 +    assert(b->widget != NULL);
 +
 +
 +    gtk_widget_set_tooltip_text( b->widget, label );
 +}
 +
 +/**
 + * Display some help text for a widget. This is a way to create
 + * some custom tooltips for error messages and the hotbar part desc
 + * \todo Replace with standard tooltip handling and custom window
 + *
 + * \param b IN widget
 + * \param dx IN dx offset in x-direction
 + * \param dy IN dy offset in y direction
 + * \param msg IN text to display, if NULL tootip is hidden
 + * \return
 + */
 +
 +void wControlSetBalloon( wControl_p b, wPos_t dx, wPos_t dy, const char * msg )
 +{
 +    PangoLayout * layout;
 +
 +    wPos_t x, y;
 +    wPos_t w, h;
 +    wPos_t xx, yy;
 +    const char * msgConverted;
 +    GtkAllocation size;
 +
 +    /* return if there is nothing to do */
 +    if (balloonVisible && balloonB == b &&
 +            balloonDx == dx && balloonDy == dy && msg != NULL && balloonMsg != NULL)
 +           if (strcmp(msg,balloonMsg)==0)
 +      		return;
 +
 +    /* hide the tooltip */
 +    if ( msg == NULL ) {
 +        if ( balloonF != NULL ) {
 +            gtk_widget_hide( balloonF );
 +            balloonVisible = FALSE;
 +        }
 +        balloonMsg = "";
 +        return;
 +    }
 +    msgConverted = wlibConvertInput(msg);
 +
 +    if ( balloonF == NULL ) {
 +		GtkWidget *alignment;
 +		
 +        balloonF = gtk_window_new( GTK_WINDOW_TOPLEVEL );
 +        gtk_window_set_type_hint( GTK_WINDOW( balloonF), GDK_WINDOW_TYPE_HINT_TOOLTIP );
 +        gtk_window_set_decorated (GTK_WINDOW (balloonF), FALSE );
 +        gtk_window_set_resizable( GTK_WINDOW (balloonF), FALSE );
 +            
 +		alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
 +		gtk_alignment_set_padding( GTK_ALIGNMENT(alignment), 6, 6, 6, 6 );
 +		
 +		gtk_container_add (GTK_CONTAINER (balloonF), alignment);
 +		gtk_widget_show (alignment);
 +        
 +        balloonPI = gtk_label_new(msgConverted);
 +        gtk_container_add( GTK_CONTAINER(alignment), balloonPI );
 +        gtk_widget_show( balloonPI );
 +    }
 +    gtk_label_set_text( GTK_LABEL(balloonPI), msgConverted );
 +
 +    balloonDx = dx;
 +    balloonDy = dy;
 +    balloonB = b;
 +    balloonMsg = msg;
 +    gtk_widget_get_allocation(balloonPI, &size );
 +    w = size.width;
 +    h = size.height;
 +
 +    gdk_window_get_origin( gtk_widget_get_window( GTK_WIDGET(b->parent->gtkwin)), &x, &y );
 +
 +    x += b->realX + dx;
 +    y += b->realY + b->h - dy;
 +    xx = gdk_screen_width();
 +    yy = gdk_screen_height();
 +    if ( x < 0 ) {
 +        x = 0;
 +    } else if ( x+w > xx ) {
 +        x = xx - w;
 +    }
 +    if ( y < 0 ) {
 +        y = 0;
 +    } else if ( y+h > yy ) {
 +        y = yy - h ;
 +    }
 +    gtk_window_move( GTK_WINDOW( balloonF ), x, y );
 +    gtk_widget_show( balloonF );
 +
 +    balloonVisible = TRUE;
 +}
 +
 +/**
 +*	still referenced but not needed any more
 +*/
 +void wBalloonHelpUpdate( void )
 +{
 +}
 +
 +/**
 + * Add tooltip and reference into help system to a widget
 + *
 + * \param widget IN widget
 + * \param helpStr IN symbolic link into help system
 + */
 +
 +void wlibAddHelpString(
 +    GtkWidget * widget,
 +    const char * helpStr )
 +{
 +    char *string;
 +    char *wAppName = wlibGetAppName();
 +    wBalloonHelp_t * bhp;
 +
 +    if (helpStr==NULL || *helpStr==0)
 +        return;
 +    if ( balloonHelpStrings == NULL )
 +        return;
 +
 +    // search for the helpStr, bhp points to the entry when found
 +    for ( bhp = balloonHelpStrings; bhp->name && strcmp(bhp->name,helpStr) != 0; bhp++ )
 +        ;
 +
 +    if (listMissingHelpStrings && !bhp->name) {
 +        printf( "Missing Help String: %s\n", helpStr );
 +        return;
 +    }
 +
 +    string = malloc( strlen(wAppName) + 5 + strlen(helpStr) + 1 );
 +    sprintf( string, "%sHelp/%s", wAppName, helpStr );
 +
 +	if(bhp->value)
 +		gtk_widget_set_tooltip_text( widget, wlibConvertInput(_(bhp->value)) );
 +
 +    g_object_set_data( G_OBJECT( widget ), HELPDATAKEY, string );
 +
 +    if (listHelpStrings)
 +        printf( "HELPSTR - %s\n", string );
 +
 +}
 diff --git a/app/wlib/gtklib/treeview.c b/app/wlib/gtklib/treeview.c new file mode 100644 index 0000000..e2f2259 --- /dev/null +++ b/app/wlib/gtklib/treeview.c @@ -0,0 +1,530 @@ +/** \file treeview.c + * Basic treeview functionality for dropbox and listbox + */ + +/* XTrkCad - Model Railroad CAD + * + * Copyright 2016 Martin Fischer <m_fischer@users.sf.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <glib-object.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "gtkint.h" +//#include "i18n.h" + +#define ROW_HEIGHT (15) + +/** + * Get the count of columns in list + * + * \param b IN widget + * \returns count row + */ + +int +wTreeViewGetCount(wList_p b) +{ +    return b->count; +} + +/** + * Clear the list + * + * \param b IN widget + */ + +void +wTreeViewClear(wList_p b) +{ +    assert(b != NULL); + +    wlibListStoreClear(b->listStore); +} + +/** + * Get the user data for a list element + * + * \param b IN widget + * \param inx IN row + * \returns the user data for the specified row + */ + +void * +wTreeViewGetItemContext(wList_p b, int row) +{ +    wListItem_p id_p; + +    id_p = wlibListItemGet(b->listStore, row, NULL); + +    if (id_p) { +        return id_p->itemData; +    } else { +        return NULL; +    } +} + +/** + * Returns the current selected list entry. + * If <val> if '-1' then no entry is selected. + * + * \param b IN widget + * \returns row of selected entry or -1 if none is selected + */ + +wIndex_t wListGetIndex( +    wList_p b) +{ +    assert(b!=NULL); + +    return b->last; +} + +/** + * Set an entry in the list to selected. + * + * \param b IN widget + * \param index IN entry if -1 the current selection is cleared + * + */ + +void +wlibTreeViewSetSelected(wList_p b, int index) +{ +    GtkTreeSelection *sel; +    GtkTreeIter iter; + +    wListItem_p id_p; + +    sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(b->treeView)); + +    if (gtk_tree_selection_count_selected_rows(sel)) { +		int inx; +         +        gtk_tree_selection_unselect_all(sel); + +        // and synchronize the internal data structures +        wTreeViewGetCount(b); + +        for (inx=0; inx<b->count; inx++) { +            id_p = wlibListItemGet(b->listStore, inx, NULL); +            id_p->selected = FALSE; +        } +    } + +    if (index != -1) { +		gint childs; +		 +		childs = gtk_tree_model_iter_n_children (GTK_TREE_MODEL(b->listStore), +											NULL ); + +		if(index < childs) { +			gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), +										&iter, +										NULL, +										index); +			gtk_tree_selection_select_iter(sel, +										&iter); + +			id_p = wlibListItemGet(b->listStore, index, NULL); +	 +			if (id_p) { +				id_p->selected = TRUE; +			} +		}	 +    } +} + +/** + * Create a new tree view for a list store. Titles are enabled optionally. + * + * \param ls IN list store + * \param showTitles IN add column titles + * \param multiSelection IN enable selecting multiple rows + * \returns + */ + +GtkWidget * +wlibNewTreeView(GtkListStore *ls, int showTitles, int multiSelection) +{ +    GtkWidget *treeView; +    GtkTreeSelection *sel; +    assert(ls != NULL); + +    /* create and configure the tree view */ +    treeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); +    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeView), showTitles); + +    /* set up selection handling */ +    sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView)); +    gtk_tree_selection_set_mode(sel, +                                (multiSelection)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE); + +    return (treeView); +} + + +static int changeListColumnWidth( +    GtkTreeViewColumn * column, +    void * width) +{ +    //wList_p bl = (wList_p)data; + +    //if (bl->recursion) +    //return 0; +    //if ( col >= 0 && col < bl->colCnt ) +    //bl->colWidths[col] = width; +    return 0; +} + +/** + * Create and initialize a column in treeview. Initially all columns are + * invisible. Visibility is set when values are added to the specific + * column + * + * \param tv IN treeview + * \param renderer IN renderer to use + * \param attribute IN attribute for column + * \param value IN value to set + */ + +static void +wlibAddColumn(GtkWidget *tv, int visibility, GtkCellRenderer *renderer, +              char *attribute, int value) +{ +    GtkTreeViewColumn *column; + +    column = gtk_tree_view_column_new(); +    gtk_tree_view_column_pack_start(column, +                                    renderer, +                                    TRUE); +    gtk_tree_view_column_add_attribute(column, renderer, attribute, value); +    gtk_tree_view_column_set_visible(column, visibility); +    gtk_tree_view_column_set_resizable(column, TRUE); + +    gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column); + +//	g_signal_connect( column, "notify::width", G_CALLBACK(changeListColumnWidth), tv ); +} + +/** + * Add a number of columns to the text view. This includes the bitmap + * columns and a given number of text columns. + * + * \param tv IN tree view + * \param count IN number of text columns + * \returns number of columns + */ + +int +wlibTreeViewAddColumns(GtkWidget *tv, int count) +{ +    GtkCellRenderer *renderer; +    int i; + +    assert(tv != NULL); +    renderer = gtk_cell_renderer_pixbuf_new(); +    /* first visible column is used for bitmaps */ +    wlibAddColumn(tv, FALSE, renderer, "pixbuf", LISTCOL_BITMAP); + +    renderer = gtk_cell_renderer_text_new(); + +    /* add renderers to all columns */ +    for (i = 0; i < count; i++) { +        wlibAddColumn(tv, TRUE, renderer, "text", i + LISTCOL_TEXT); +    } + +    return i; +} + +/** + * Add the titles to all columns in a tree view. + * + * \param tv IN treeview + * \param titles IN titles + * \returns number of titles set + */ + +int +wlibAddColumnTitles(GtkWidget *tv, const char **titles) +{ +    int i = 0; + +    assert(tv != NULL); + +    if (titles) { +        while (*titles) { +		    GtkTreeViewColumn *column; +		     +            column = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), i + 1); + +            if (column) { +                gtk_tree_view_column_set_title(column, titles[ i ]); +                i++; +            } else { +                break; +            } +        } +    } + +    return i; +} + +/** + * Add text to the text columns of the tree view and update the context + * information + * + * \param tv IN treeview + * \param cols IN number of cols to change + * \param label IN tab separated string of values + * \param userData IN additional context information + * \returns + */ + +int +wlibTreeViewAddData(GtkWidget *tv, int cols, char *label, GdkPixbuf *pixbuf, +                    wListItem_p userData) +{ +    GtkListStore *listStore = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW( +                                  tv))); + +    wlibListStoreAddData(listStore, pixbuf, cols, userData); + +    if (pixbuf) { +	    GtkTreeViewColumn *column; +	     +        // first column in list store has pixbuf +        column = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), 0); +        gtk_tree_view_column_set_visible(column, +                                         TRUE); +    } + +} + +/** + * Add a row to the tree view. As necessary the adjustment is update in + * order to make sure, that the list box is fully visible or has a + * scrollbar. + * + * \param b IN the list box + * \param label IN the text labels + * \param bm IN bitmap to show at start + * \param id_p IN user data + */ + +void +wlibTreeViewAddRow(wList_p b, char *label, wIcon_p bm, wListItem_p id_p) +{ +    GtkAdjustment *adj; +    GdkPixbuf *pixbuf = NULL; + +    if (bm) { +        pixbuf = wlibMakePixbuf(bm); +    } + +    wlibTreeViewAddData(b->treeView, b->colCnt, (char *)label, pixbuf, id_p); + +    adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(b->widget)); + +    if (gtk_adjustment_get_upper(adj) < gtk_adjustment_get_step_increment(adj) * +            (b->count+1)) { +        gtk_adjustment_set_upper(adj, +                                 gtk_adjustment_get_upper(adj) + +                                 gtk_adjustment_get_step_increment(adj)); +        gtk_adjustment_changed(adj); +    } + +    b->last = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(GTK_TREE_VIEW( +                  b->treeView)), +              NULL); + +} + +/** + * Function for handling a selection change. The internal data structure + * for the changed row is updated. If a handler function for the list + * is given, the data for the row are retrieved and passed to that + * function. This is used to update other fields in a dialog (see Price + * List for an example). + * + * \param selection IN current selection + * \param model IN + * \param path IN + * \param path_currently_selected IN + * \param data IN the list widget + */ + +gboolean +changeSelection(GtkTreeSelection *selection, +                GtkTreeModel *model, +                GtkTreePath *path, +                gboolean path_currently_selected, +                gpointer data) +{ +    GtkTreeIter iter; +    GValue value = { 0 }; +    wListItem_p id_p = NULL; +    wList_p bl = (wList_p)data; +    int row; +    char *text; + +    text = gtk_tree_path_to_string(path); +    row = atoi(text); +    g_free(text); + +    gtk_tree_model_get_iter(model, &iter, path); +    gtk_tree_model_get_value(model, &iter, LISTCOL_DATA, &value); + +    id_p = g_value_get_pointer(&value); +    id_p->selected = !path_currently_selected; + +    if (id_p->selected) { +        bl->last = row; + +        if (bl->valueP) { +            *bl->valueP = row; +        } + +        if (bl->action) { +            bl->action(row, id_p->label, 1, bl->data, id_p->itemData); +        } +    } + +    return TRUE; +} + +/** + * Create a multi column list box. + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param number IN Number of displayed entries + * \param width IN Width of list + * \param colCnt IN Number of columns + * \param colWidths IN Width of columns + * \param colRightJust IN justification of columns + * \param colTitles IN array of titles for columns + * \param valueP IN Selected index + * \param action IN Callback + * \param data IN Context + * \returns created list box + */ + +wList_p wListCreate( +    wWin_p	parent, +    wPos_t	x, +    wPos_t	y, +    const char 	* helpStr, +    const char	* labelStr, +    long	option, +    long	number, +    wPos_t	width, +    int	colCnt, +    wPos_t	* colWidths, +    wBool_t * colRightJust, +    const char 	** colTitles, +    long	*valueP, +    wListCallBack_p action, +    void 	*data) +{ +    GtkTreeSelection *sel; +    wList_p bl; +    static wPos_t zeroPos = 0; + +    assert(width != 0); + +    bl = (wList_p)wlibAlloc(parent, B_LIST, x, y, labelStr, sizeof *bl, data); +    bl->option = option; +    bl->number = number; +    bl->count = 0; +    bl->last = -1; +    bl->valueP = valueP; +    bl->action = action; +    bl->listX = bl->realX; + +    if (colCnt <= 0) { +        colCnt = 1; +        colWidths = &zeroPos; +    } + +    bl->colCnt = colCnt; +    bl->colWidths = (wPos_t*)malloc(colCnt * sizeof *(wPos_t*)0); +    memcpy(bl->colWidths, colWidths, colCnt * sizeof *(wPos_t*)0); + +    /* create the data structure for data */ +    bl->listStore = wlibNewListStore(colCnt); +    /* create the widget for the list store */ +    bl->treeView = wlibNewTreeView(bl->listStore, +                                   colTitles != NULL, +                                   option & BL_MANY); + + +    sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(bl->treeView)); + +    gtk_tree_selection_set_select_function(sel, +                                           changeSelection, +                                           bl, +                                           NULL); + +    wlibTreeViewAddColumns(bl->treeView, colCnt); + +    wlibAddColumnTitles(bl->treeView, colTitles); + +    wlibComputePos((wControl_p)bl); + +    bl->widget = gtk_scrolled_window_new(NULL, NULL); +    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(bl->widget), +                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); +    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(bl->widget), +                                          bl->treeView); + +    gtk_widget_set_size_request(bl->widget, width, (number+1)*ROW_HEIGHT); + +///	g_signal_connect( GTK_OBJECT(bl->list), "resize_column", G_CALLBACK(changeListColumnWidth), bl ); + +    gtk_widget_show_all(bl->widget); + +    gtk_fixed_put(GTK_FIXED(parent->widget), bl->widget, bl->realX, bl->realY); +    wlibControlGetSize((wControl_p)bl); + +    if (labelStr) { +        bl->labelW = wlibAddLabel((wControl_p)bl, labelStr); +    } + +    wlibAddButton((wControl_p)bl); +    wlibAddHelpString(bl->widget, helpStr); + +    return bl; +} diff --git a/app/wlib/gtklib/util.c b/app/wlib/gtklib/util.c new file mode 100644 index 0000000..61b5b95 --- /dev/null +++ b/app/wlib/gtklib/util.c @@ -0,0 +1,672 @@ +/** \file util.c + * Some basic window functions + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> + +#include "gtkint.h" +#include "i18n.h" + +wWin_p gtkMainW; + +long debugWindow = 0; + +char wConfigName[ 256 ]; + +const char * wNames[] = { +    "MAIN", +    "POPUP", +    "BUTT", +    "CANCEL", +    "POPUP", +    "TEXT", +    "INTEGER", +    "FLOAT", +    "LIST", +    "DROPLIST", +    "COMBOLIST", +    "RADIO", +    "TOGGLE", +    "DRAW", +    "MENU" +    "MULTITEXT", +    "MESSAGE", +    "LINES", +    "MENUITEM", +    "BOX" +}; + + +static wBool_t reverseIcon = +#if defined(linux) +    FALSE; +#else +    TRUE; +#endif + + + +/* + ***************************************************************************** + * + * Internal Utility functions + * + ***************************************************************************** + */ + +/** + * Create a pixbuf from a two colored bitmap in XBM format. + * + * \param ip the XBM data + * \returns the pixbuf + */ + +GdkPixbuf* wlibPixbufFromXBM( +    wIcon_p ip ) +{ +    GdkPixbuf * pixbuf; + +    char line0[40]; +    char line2[40]; + +    char ** pixmapData; +    int row,col,wb; +    long rgb; +    const char * bits; + +    wb = (ip->w+7)/8; +    pixmapData = (char**)malloc((3+ip->h) * sizeof *pixmapData); +    pixmapData[0] = line0; +    rgb = wDrawGetRGB(ip->color); +    sprintf(line0, " %d %d 2 1", ip->w, ip->h); +    sprintf(line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF, +            rgb&0xFF); +    pixmapData[1] = ". c None s None"; +    pixmapData[2] = line2; +    bits = ip->bits; + +    for (row = 0; row<ip->h; row++) { +        pixmapData[row+3] = (char*)malloc((ip->w+1) * sizeof **pixmapData); + +        for (col = 0; col<ip->w; col++) { +            if (bits[ row*wb+(col>>3) ] & (1<<(col&07))) { +                pixmapData[row+3][col] = '#'; +            } else { +                pixmapData[row+3][col] = '.'; +            } +        } +        pixmapData[row+3][ip->w] = 0; +    } + +    pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)pixmapData); + +    for (row = 0; row<ip->h; row++) { +        free(pixmapData[row+3]); +    } +    return pixbuf; +} + +/** + * Add a label to an existing widget + * + * \param b IN widget + * \param labelStr IN label to add + * \returns size of label + */ + +int wlibAddLabel(wControl_p b, const char * labelStr) +{ +    GtkRequisition requisition; + +    if (labelStr == NULL) { +        return 0; +    } + +    b->label = gtk_label_new(wlibConvertInput(labelStr)); +    gtk_widget_size_request(b->label, &requisition); +    gtk_container_add(GTK_CONTAINER(b->parent->widget), b->label); +    gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, +                   b->realX-requisition.width-8, b->realY+LABEL_OFFSET); + +    gtk_widget_show(b->label); +    return requisition.width+8; +} + +/** + * Allocate and initialize the data structure for a new widget + * + * \param parent IN parent window + * \param type IN type of new widget + * \param origX IN x position + * \param origY IN y position + * \param labelStr IN text label + * \param size IN size + * \param data IN user data to keep with widget + * \returns + */ + +void * wlibAlloc( +    wWin_p parent, +    wType_e type, +    wPos_t origX, +    wPos_t origY, +    const char * labelStr, +    int size, +    void * data) +{ +    wControl_p w = (wControl_p)malloc(size); +    char * cp; +    memset(w, 0, size); + +    if (w == NULL) { +        abort(); +    } + +    w->type = type; +    w->parent = parent; +    w->origX = origX; +    w->origY = origY; + +    if (labelStr) { +        cp = (char*)malloc(strlen(labelStr)+1); +        w->labelStr = cp; + +        for (; *labelStr; labelStr++) +            if (*labelStr != '&') { +                *cp++ = *labelStr; +            } + +        *cp = 0; +    } + +    w->doneProc = NULL; +    w->data = data; +    return w; +} + +/** + * Calculate the position for a widget + * + * \param b IN widget + */ + +void wlibComputePos( +    wControl_p b) +{ +    wWin_p w = b->parent; + +    if (b->origX >= 0) { +        b->realX = b->origX; +    } else { +        b->realX = w->lastX + (-b->origX) - 1; +    } + +    if (b->origY >= 0) { +        b->realY = b->origY + BORDERSIZE + ((w->option&F_MENUBAR)?MENUH:0); +    } else { +        b->realY = w->lastY + (-b->origY) - 1; +    } +} + +/** + * Initialize the internal structure with the size of the widget + * + * \param b IN widget + */ + +void wlibControlGetSize( +    wControl_p b) +{ +    GtkRequisition requisition; +    gtk_widget_size_request(b->widget, &requisition); +    b->w = requisition.width; +    b->h = requisition.height; +} + +/** + * ??? + * \param b IN widget + */ + +void wlibAddButton( +    wControl_p b) +{ +    wWin_p win = b->parent; +    wBool_t resize = FALSE; + +    if (win->first == NULL) { +        win->first = b; +    } else { +        win->last->next = b; +    } + +    win->last = b; +    b->next = NULL; +    b->parent = win; +    win->lastX = b->realX + b->w; +    win->lastY = b->realY + b->h; + +    if (win->option&F_AUTOSIZE) { +        if (win->lastX > win->realX) { +            win->realX = win->lastX; + +            if (win->w != (win->realX + win->origX)) { +                resize = TRUE; +                win->w = (win->realX + win->origX); +            } +        } + +        if (win->lastY > win->realY) { +            win->realY = win->lastY; + +            if (win->h != (win->realY + win->origY)) { +                resize = TRUE; +                win->h = (win->realY + win->origY); +            } +        } + +        if (win->shown) { +            if (resize) { +                gtk_widget_set_size_request(win->gtkwin, win->w, win->h); +                gtk_widget_set_size_request(win->widget, win->w, win->h); +            } +        } +    } +} + +/** + * Find the widget at a position + * \param win IN searched widget's parent window + * \param x IN x position inside parent + * \param y IN y position inside parent + * \returns the widget, NULL if none at the position + */ + +wControl_p wlibGetControlFromPos( +    wWin_p win, +    wPos_t x, +    wPos_t y) +{ +    wControl_p b; +    wPos_t xx, yy; + +    for (b=win->first; b != NULL; b = b->next) { +        if (b->widget && gtk_widget_get_visible(b->widget)) { +            xx = b->realX; +            yy = b->realY; + +            if (xx <= x && x < xx+b->w && +                    yy <= y && y < yy+b->h) { +                return b; +            } +        } +    } + +    return NULL; +} + + +/* + ***************************************************************************** + * + * Exported Utility Functions + * + ***************************************************************************** + */ + +/** + * Beep! + * \return + */ +void wBeep(void) +{ +    gdk_display_beep(gdk_display_get_default()); +} + + +/** + * Flushs all commands to the Window. + */ + +void wFlush( +    void) +{ +    while (gtk_events_pending()) { +        gtk_main_iteration(); +    } + +    gdk_display_sync(gdk_display_get_default()); +} + +/** + * Not implemented + * \returns + */ + +void wWinTop(wWin_p win) +{ +} + +/** + * Not implemented + * + * \param cursor IN + */ + +void wSetCursor(wCursor_t cursor) +{ +} + +/** + * Not implemented + * \returns + */ + +const char * wMemStats(void) +{ +    return "No stats available"; +} + +/** + * Get the size of the screen + * + * \param w IN pointer to width + * \param h IN pointer to height + */ + +void wGetDisplaySize(wPos_t * w, wPos_t * h) +{ + +    *w = gdk_screen_width(); +    *h = gdk_screen_height(); +} + +static dynArr_t conversionBuffer_da; + +/** + * Convert a string to UTF-8 + * + * \param inString IN string to convert + * \returns pointer to converted string, valid until next call to conversion function + */ + +char * wlibConvertInput(const char * inString) +{ +    const char * cp; +    char * cq; +    int extCharCnt, inCharCnt; + +    /* Already UTF-8 encoded? */ +    if (g_utf8_validate(inString, -1, NULL)) +        /* Yes, do not double-convert */ +    { +        return (char*)inString; +    } + +    for (cp=inString, extCharCnt=0; *cp; cp++) { +        if (((*cp)&0x80) != '\0') { +            extCharCnt++; +        } +    } + +    inCharCnt = cp-inString; + +    if (extCharCnt == '\0') { +        return (char*)inString; +    } + +    DYNARR_SET(char, conversionBuffer_da, inCharCnt+extCharCnt+1); + +    for (cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++) { +        if (((*cp)&0x80) != 0) { +            *cq++ = 0xC0+(((*cp)&0xC0)>>6); +            *cq++ = 0x80+((*cp)&0x3F); +        } else { +            *cq++ = *cp; +        } +    } + +    *cq = 0; +    return (char*)conversionBuffer_da.ptr; +} + +/** + * Convert a string from UTF-8 to system codepage + * + * \param inString IN string to convert + * \returns pointer to converted string, valid until next call to conversion function + */ + +char * wlibConvertOutput(const char * inString) +{ +    const char * cp; +    char * cq; +    int extCharCnt, inCharCnt; + +    for (cp=inString, extCharCnt=0; *cp; cp++) { +        if (((*cp)&0xC0) == 0x80) { +            extCharCnt++; +        } +    } + +    inCharCnt = cp-inString; + +    if (extCharCnt == '\0') { +        return (char*)inString; +    } + +    DYNARR_SET(char, conversionBuffer_da, inCharCnt+1); + +    for (cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++) { +        if (((*cp)&0x80) != 0) { +            *cq++ = 0xC0+(((*cp)&0xC0)>>6); +            *cq++ = 0x80+((*cp)&0x3F); +        } else { +            *cq++ = *cp; +        } +    } + +    *cq = '\0'; +    return (char*)conversionBuffer_da.ptr; +} + +/*-----------------------------------------------------------------*/ + + +static dynArr_t accelData_da; +#define accelData(N) DYNARR_N( accelData_t, accelData_da, N ) + +static guint accelKeyMap[] = { +    0,			/* wAccelKey_None, */ +    GDK_KEY_Delete,		/* wAccelKey_Del, */ +    GDK_KEY_Insert,		/* wAccelKey_Ins, */ +    GDK_KEY_Home,		/* wAccelKey_Home, */ +    GDK_KEY_End,		/* wAccelKey_End, */ +    GDK_KEY_Page_Up,	/* wAccelKey_Pgup, */ +    GDK_KEY_Page_Down,	/* wAccelKey_Pgdn, */ +    GDK_KEY_Up,		/* wAccelKey_Up, */ +    GDK_KEY_Down,		/* wAccelKey_Down, */ +    GDK_KEY_Right,		/* wAccelKey_Right, */ +    GDK_KEY_Left,		/* wAccelKey_Left, */ +    GDK_KEY_BackSpace,	/* wAccelKey_Back, */ +    GDK_KEY_F1,		/* wAccelKey_F1, */ +    GDK_KEY_F2,		/* wAccelKey_F2, */ +    GDK_KEY_F3,		/* wAccelKey_F3, */ +    GDK_KEY_F4,		/* wAccelKey_F4, */ +    GDK_KEY_F5,		/* wAccelKey_F5, */ +    GDK_KEY_F6,		/* wAccelKey_F6, */ +    GDK_KEY_F7,		/* wAccelKey_F7, */ +    GDK_KEY_F8,		/* wAccelKey_F8, */ +    GDK_KEY_F9,		/* wAccelKey_F9, */ +    GDK_KEY_F10,		/* wAccelKey_F10, */ +    GDK_KEY_F11,		/* wAccelKey_F11, */ +    GDK_KEY_F12		/* wAccelKey_F12, */ +}; + +/** + * Create an accelerator key + * + * \param key IN primary key stroke + * \param modifier IN modifier (shift, ctrl, etc.) + * \param action IN function to call + * \param data IN data to pass to function + */ + +void wAttachAccelKey( +    wAccelKey_e key, +    int modifier, +    wAccelKeyCallBack_p action, +    void * data) +{ +    accelData_t * ad; + +    if (key < 1 || key > wAccelKey_F12) { +        fprintf(stderr, "wAttachAccelKey(%d) out of range\n", (int)key); +        return; +    } + +    DYNARR_APPEND(accelData_t, accelData_da, 10); +    ad = &accelData(accelData_da.cnt-1); +    ad->key = key; +    ad->modifier = modifier; +    ad->action = action; +    ad->data = data; +} + +/** + * Check for accelerator definition a pressed key + * + * \param event IN key press event + * \returns pointer to accel key structure, NULL if not existing + */ + +struct accelData_t * wlibFindAccelKey( +    GdkEventKey * event) +{ +    accelData_t * ad; +    int modifier = 0; + +    if ((event->state & GDK_SHIFT_MASK)) { +        modifier |= WKEY_SHIFT; +    } + +    if ((event->state & GDK_CONTROL_MASK)) { +        modifier |= WKEY_CTRL; +    } + +    if ((event->state & GDK_MOD1_MASK)) { +        modifier |= WKEY_ALT; +    } + +    for (ad=&accelData(0); ad<&accelData(accelData_da.cnt); ad++) +        if (event->keyval == accelKeyMap[ad->key] && +                modifier == ad->modifier) { +            return ad; +        } + +    return NULL; +} + +/** + * Perform action when an accelerator key was pressed + * + * \param event IN key press event + * \returns  TRUE if valid accelerator, FALSE if not + */ + +wBool_t wlibHandleAccelKey( +    GdkEventKey *event) +{ +    accelData_t * ad = wlibFindAccelKey(event); + +    if (ad) { +        ad->action(ad->key, ad->data); +        return TRUE; +    } + +    return FALSE; +} + +/** + * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by + * calling wControlLinkedActive for one member of the list + * \todo This is similar to the concept of action in gtk/glib \ + * Maybe this would be easier to use + * + * \param b1 IN  first control + * \param b2 IN  second control + * \return    none + */ + +void wControlLinkedSet(wControl_p b1, wControl_p b2) +{ + +    b2->synonym = b1->synonym; + +    if (b2->synonym == NULL) { +        b2->synonym = b1; +    } + +    b1->synonym = b2; +} + +/** + * Activate/deactivate a group of synonymous controls. + * + * \param b IN  control + * \param active IN  state + * \return    none + */ + +void wControlLinkedActive(wControl_p b, int active) +{ +    wControl_p savePtr = b; + +    if (savePtr->type == B_MENUITEM) { +        wMenuPushEnable((wMenuPush_p)savePtr, active); +    } else { +        wControlActive(savePtr, active); +    } + +    savePtr = savePtr->synonym; + +    while (savePtr && savePtr != b) { + +        if (savePtr->type == B_MENUITEM) { +            wMenuPushEnable((wMenuPush_p)savePtr, active); +        } else { +            wControlActive(savePtr, active); +        } + +        savePtr = savePtr->synonym; +    } +} diff --git a/app/wlib/gtklib/window.c b/app/wlib/gtklib/window.c new file mode 100644 index 0000000..489f35e --- /dev/null +++ b/app/wlib/gtklib/window.c @@ -0,0 +1,936 @@ +/** \file window.c + * Basic window handling stuff. + */ + +/*  XTrkCad - Model Railroad CAD + *  Copyright (C) 2005 Dave Bullis + * + *  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-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> + +#include "gtkint.h" + +wWin_p gtkMainW; + +#define MIN_WIN_WIDTH (50) +#define MIN_WIN_HEIGHT (50) + +#define SECTIONWINDOWSIZE  "gtklib window size" +#define SECTIONWINDOWPOS   "gtklib window pos" + +extern wBool_t listHelpStrings; + +static wControl_p firstWin = NULL, lastWin; +static int keyState; +static wBool_t gtkBlockEnabled = TRUE; + +/* + ***************************************************************************** + * + * Window Utilities + * + ***************************************************************************** + */ + +/** + * Get the window size from the resource (.rc) file.  The size is saved under the key + * SECTIONWINDOWSIZE.window name + * + * \param win IN window + * \param nameStr IN window name + */ + +static void getWinSize(wWin_p win, const char * nameStr) +{ +    int w, h; +    const char *cp; +    char *cp1, *cp2; + +    if ((win->option&F_RESIZE) && +            (win->option&F_RECALLPOS) && +            (cp = wPrefGetString(SECTIONWINDOWSIZE, nameStr)) && +            (w = strtod(cp, &cp1), cp != cp1) && +            (h = strtod(cp1, &cp2), cp1 != cp2)) { +        if (w < 10) { +            w = 10; +        } + +        if (h < 10) { +            h = 10; +        } + +        win->w = win->origX = w; +        win->h = win->origY = h; +        win->option &= ~F_AUTOSIZE; +    } +} + +/** + * Save the window size to the resource (.rc) file.  The size is saved under the key + * SECTIONWINDOWSIZE.window name + * + * \param win IN window + */ + +static void saveSize(wWin_p win) +{ + +    if ((win->option&F_RESIZE) && +            (win->option&F_RECALLPOS) && +            gtk_widget_get_visible(GTK_WIDGET(win->gtkwin))) { +	    char pos_s[20]; + +        sprintf(pos_s, "%d %d", win->w, +                win->h-(BORDERSIZE + ((win->option&F_MENUBAR)?MENUH:0))); +        wPrefSetString(SECTIONWINDOWSIZE, win->nameStr, pos_s); +    } +} + +/** + * Get the window position from the resource (.rc) file.  The position is saved under the key + * SECTIONWINDOWPOS.window name + * + * \param win IN window + */ + +static void getPos(wWin_p win) +{ +    char *cp1, *cp2; +    wPos_t gtkDisplayWidth = gdk_screen_width(); +    wPos_t gtkDisplayHeight = gdk_screen_height(); + +    if ((win->option&F_RECALLPOS) && (!win->shown)) { +		const char *cp; + +        if ((cp = wPrefGetString(SECTIONWINDOWPOS, win->nameStr))) { +			int x, y; + +            x = strtod(cp, &cp1); + +            if (cp == cp1) { +                return; +            } + +            y = strtod(cp1, &cp2); + +            if (cp2 == cp1) { +                return; +            } + +            if (y > gtkDisplayHeight-win->h) { +                y = gtkDisplayHeight-win->h; +            } + +            if (x > gtkDisplayWidth-win->w) { +                x = gtkDisplayWidth-win->w; +            } + +            if (x <= 0) { +                x = 1; +            } + +            if (y <= 0) { +                y = 1; +            } + +            gtk_window_move(GTK_WINDOW(win->gtkwin), x, y); +            gtk_window_resize(GTK_WINDOW(win->gtkwin), win->w, win->h); +        } +    } +} + +/** + * Save the window position to the resource (.rc) file.  The position is saved under the key + * SECTIONWINDOWPOS.window name + * + * \param win IN window + */ + +static void savePos(wWin_p win) +{ +    int x, y; + +    if ((win->option&F_RECALLPOS)) { +		char pos_s[20]; + +        gdk_window_get_position(gtk_widget_get_window(GTK_WIDGET(win->gtkwin)), &x, &y); +        x -= 5; +        y -= 25; +        sprintf(pos_s, "%d %d", x, y); +        wPrefSetString(SECTIONWINDOWPOS, win->nameStr, pos_s); +    } +} + +/** + * Returns the dimensions of <win>. + * + * \param win IN window handle + * \param width OUT width of window + * \param height OUT height of window minus menu bar size + */ + +void wWinGetSize( +    wWin_p win,		/* Window */ +    wPos_t * width,		/* Returned window width */ +    wPos_t * height)	/* Returned window height */ +{ +    GtkRequisition requisition; +    wPos_t w, h; +    gtk_widget_size_request(win->gtkwin, &requisition); +    w = win->w; +    h = win->h; + +    if (win->option&F_AUTOSIZE) { +        if (win->realX > w) { +            w = win->realX; +        } + +        if (win->realY > h) { +            h = win->realY; +        } +    } + +    *width = w; +    *height = h - BORDERSIZE - ((win->option&F_MENUBAR)?MENUH:0); +} + +/** + * Sets the dimensions of window + * + * \param win IN window + * \param width IN new width + * \param height IN new height + */ + +void wWinSetSize( +    wWin_p win,		/* Window */ +    wPos_t width,		/* Window width */ +    wPos_t height)		/* Window height */ +{ +    win->busy = TRUE; +    win->w = width; +    win->h = height + BORDERSIZE + ((win->option&F_MENUBAR)?MENUH:0); +    gtk_widget_set_size_request(win->gtkwin, win->w, win->h); +    gtk_widget_set_size_request(win->widget, win->w, win->h); +    win->busy = FALSE; +} + +/** + * Shows or hides window <win>. If <win> is created with 'F_BLOCK' option then the applications other + * windows are disabled and 'wWinShow' doesnot return until the window <win> is closed by calling + * 'wWinShow(<win>,FALSE)'. + * + * \param win IN window + * \param show IN visibility state + */ + +void wWinShow( +    wWin_p win,		/* Window */ +    wBool_t show)		/* Command */ +{ +    GtkRequisition requisition; + +    if (debugWindow >= 2) { +        printf("Set Show %s\n", win->labelStr?win->labelStr:"No label"); +    } + +    if (win->widget == 0) { +        abort(); +    } + +    if (show) { +        keyState = 0; +        getPos(win); + +        if (win->option & F_AUTOSIZE) { +            gtk_widget_size_request(win->gtkwin, &requisition); + +            if (requisition.width != win->w || requisition.height != win->h) { +                gtk_widget_set_size_request(win->gtkwin, win->w, win->h); +                gtk_widget_set_size_request(win->widget, win->w, win->h); + +                if (win->option&F_MENUBAR) { +                    gtk_widget_set_size_request(win->menubar, win->w, MENUH); +                } +            } +        } + +        if (!win->shown) { +            gtk_widget_show(win->gtkwin); +            gtk_widget_show(win->widget); +        } + +        gdk_window_raise(gtk_widget_get_window(win->gtkwin)); + +        if (win->shown && win->modalLevel > 0) { +            gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), TRUE); +        } + +        win->shown = show; +        win->modalLevel = 0; + +        if ((!gtkBlockEnabled) || (win->option & F_BLOCK) == 0) { +            wFlush(); +        } else { +            wlibDoModal(win, TRUE); +        } +    } else { +        wFlush(); +        saveSize(win); +        savePos(win); +        win->shown = show; + +        if (gtkBlockEnabled && (win->option & F_BLOCK) != 0) { +            wlibDoModal(win, FALSE); +        } + +        gtk_widget_hide(win->gtkwin); +        gtk_widget_hide(win->widget); +    } +} + +/** + * Block windows against user interactions. Done during demo mode etc. + * + * \param enabled IN blocked if TRUE + */ + +void wWinBlockEnable( +    wBool_t enabled) +{ +    gtkBlockEnabled = enabled; +} + +/** + * Returns whether the window is visible. + * + * \param win IN window + * \return    TRUE if visible, FALSE otherwise + */ + +wBool_t wWinIsVisible( +    wWin_p win) +{ +    return win->shown; +} + +/** + * Sets the title of <win> to <title>. + * + * \param varname1 IN window + * \param varname2 IN new title + */ + +void wWinSetTitle( +    wWin_p win,		/* Window */ +    const char * title)		/* New title */ +{ +    gtk_window_set_title(GTK_WINDOW(win->gtkwin), title); +} + +/** + * Sets the window <win> to busy or not busy. Sets the cursor accordingly + * + * \param varname1 IN window + * \param varname2 IN TRUE if busy, FALSE otherwise + */ + +void wWinSetBusy( +    wWin_p win,		/* Window */ +    wBool_t busy)		/* Command */ +{ +    GdkCursor * cursor; + +    if (win->gtkwin == 0) { +        abort(); +    } + +    if (busy) { +        cursor = gdk_cursor_new(GDK_WATCH); +    } else { +        cursor = NULL; +    } + +    gdk_window_set_cursor(gtk_widget_get_window(win->gtkwin), cursor); + +    if (cursor) { +        gdk_cursor_unref(cursor); +    } + +    gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), busy==0); +} + +/** + * Set the modality of window. All visible windows are disabled when + * the window is modal. These windows are enabled again, when window + * is not modal. Disabling can be performed several times and enabling + * has to be repeated as well to re-enable a window. + * \todo Give this recursive enabling/disabling some thought and remove + * + * \param win0 IN window + * \param modal IN TRUE if window is application modal, FALSE otherwise + * \return + */ + +void wlibDoModal( +    wWin_p win0, +    wBool_t modal) +{ +    wWin_p win; + +    for (win=(wWin_p)firstWin; win; win=(wWin_p)win->next) { +        if (win->shown && win != win0) { +            if (modal) { +                if (win->modalLevel == 0) { +                    gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), FALSE); +                } + +                win->modalLevel++; +            } else { +                if (win->modalLevel > 0) { +                    win->modalLevel--; + +                    if (win->modalLevel == 0) { +                        gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), TRUE); +                    } +                } +            } + +            if (win->modalLevel < 0) { +                fprintf(stderr, "DoModal: %s modalLevel < 0", +                        win->nameStr?win->nameStr:"<NULL>"); +                abort(); +            } +        } +    } + +    if (modal) { +        gtk_main(); +    } else { +        gtk_main_quit(); +    } +} + +/** + * Returns the Title of <win>. + * + * \param win IN window + * \return    pointer to window title + */ + +const char * wWinGetTitle( +    wWin_p win)			/* Window */ +{ +    return win->labelStr; +} + + +void wWinClear( +    wWin_p win, +    wPos_t x, +    wPos_t y, +    wPos_t width, +    wPos_t height) +{ +} + + +void wWinDoCancel( +    wWin_p win) +{ +    wControl_p b; + +    for (b=win->first; b; b=b->next) { +        if ((b->type == B_BUTTON) && (b->option & BB_CANCEL)) { +            wlibButtonDoAction((wButton_p)b); +        } +    } +} + +/* + ****************************************************************************** + * + * Call Backs + * + ****************************************************************************** + */ + +static gint window_delete_event( +    GtkWidget *widget, +    GdkEvent *event, +    wWin_p win) +{ +    wControl_p b; +    /* if you return FALSE in the "delete_event" signal handler, +     * GTK will emit the "destroy" signal.  Returning TRUE means +     * you don't want the window to be destroyed. +     * This is useful for popping up 'are you sure you want to quit ?' +     * type dialogs. */ + +    /* Change TRUE to FALSE and the main window will be destroyed with +     * a "delete_event". */ + +    for (b = win->first; b; b=b->next) +        if (b->doneProc) { +            b->doneProc(b); +        } + +    if (win->winProc) { +        win->winProc(win, wClose_e, win->data); + +        if (win != gtkMainW) { +            wWinShow(win, FALSE); +        } +    } + +    return (TRUE); +} + +static int window_redraw( +    wWin_p win, +    wBool_t doWinProc) +{ +    wControl_p b; + +    if (win==NULL) { +        return FALSE; +    } + +    for (b=win->first; b != NULL; b = b->next) { +        if (b->repaintProc) { +            b->repaintProc(b); +        } +    } + +    return FALSE; +} + +static int fixed_expose_event( +    GtkWidget * widget, +    GdkEventExpose * event, +    wWin_p win) +{ +    if (event->count==0) { +        return window_redraw(win, TRUE); +    } else { +        return FALSE; +    } +} + +static int window_configure_event( +    GtkWidget * widget, +    GdkEventConfigure * event, +    wWin_p win) +{ +//    wPos_t h; + +    if (win==NULL) { +        return FALSE; +    } + +    //h = event->height - BORDERSIZE; + +    //if (win->option&F_MENUBAR) { +        //h -= MENUH; +    //} + +    if (win->option&F_RESIZE) { +        if (event->width < 10 || event->height < 10) { +            return TRUE; +        } + +        if (win->w != event->width || win->h != event->height) { +            win->w = event->width; +            win->h = event->height; + +            if (win->w < MIN_WIN_WIDTH) { +                win->w = MIN_WIN_WIDTH; +            } + +            if (win->h < MIN_WIN_HEIGHT) { +                win->h = MIN_WIN_HEIGHT; +            } + +            if (win->option&F_MENUBAR) { +                gtk_widget_set_size_request(win->menubar, win->w, MENUH); +            } + +            if (win->busy==FALSE && win->winProc) { +                win->winProc(win, wResize_e, win->data); +            } +        } +    } + +    return FALSE; +} + +/** + * Get current state of shift, ctrl or alt keys. + * + * \return    or'ed value of WKEY_SHIFT, WKEY_CTRL and WKEY_ALT depending on state + */ + +int wGetKeyState(void) +{ +    return keyState; +} + +wBool_t catch_shift_ctrl_alt_keys( +    GtkWidget * widget, +    GdkEventKey *event, +    void * data) +{ +    int state; +    state = 0; + +    switch (event->keyval) { +    case GDK_KEY_Shift_L: +    case GDK_KEY_Shift_R: +        state |= WKEY_SHIFT; +        break; + +    case GDK_KEY_Control_L: +    case GDK_KEY_Control_R: +        state |= WKEY_CTRL; +        break; + +    case GDK_KEY_Alt_L: +    case GDK_KEY_Alt_R: +        state |= WKEY_ALT; +        break; +    } + +    if (state != 0) { +        if (event->type == GDK_KEY_PRESS) { +            keyState |= state; +        } else { +            keyState &= ~state; +        } + +        return TRUE; +    } + +    return FALSE; +} + +static gint window_char_event( +    GtkWidget * widget, +    GdkEventKey *event, +    wWin_p win) +{ +    wControl_p bb; + +    if (catch_shift_ctrl_alt_keys(widget, event, win)) { +        return FALSE; +    } + +    if (event->type == GDK_KEY_RELEASE) { +        return FALSE; +    } + +    if (event->state == 0) { +        if (event->keyval == GDK_KEY_Escape) { +            for (bb=win->first; bb; bb=bb->next) { +                if (bb->type == B_BUTTON && (bb->option&BB_CANCEL)) { +                    wlibButtonDoAction((wButton_p)bb); +                    return TRUE; +                } +            } +        } +    } + +    if (wlibHandleAccelKey(event)) { +        return TRUE; +    } else { +        return FALSE; +    } +} + + +/* + ******************************************************************************* + * + * Main and Popup Windows + * + ******************************************************************************* + */ + +/** + * Create a window + * + * \param parent IN parent window + * \param winType IN type of window + * \param x IN x position + * \param y IN y position + * \param labelStr IN window title + * \param nameStr IN + * \param option IN + * \param winProc IN window procedure + * \param data IN additional data to pass to the window procedure + * \return    describe the return value + */ + +static wWin_p wWinCommonCreate( +    wWin_p parent, +    int winType, +    wPos_t x, +    wPos_t y, +    const char * labelStr, +    const char * nameStr, +    long option, +    wWinCallBack_p winProc, +    void * data) +{ +    wWin_p w; +    int h; +    w = wlibAlloc(NULL, winType, x, y, labelStr, sizeof *w, data); +    w->busy = TRUE; +    w->option = option; +    getWinSize(w, nameStr); +    h = BORDERSIZE; + +    if (w->option&F_MENUBAR) { +        h += MENUH; +    } + +    if (winType == W_MAIN) { +        w->gtkwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); +    } else { +        w->gtkwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); + +        if (gtkMainW) { +            gtk_window_set_transient_for(GTK_WINDOW(w->gtkwin), +                                         GTK_WINDOW(gtkMainW->gtkwin)); +        } +    } + +    if (option & F_HIDE) { +        gtk_widget_hide(w->gtkwin); +    } + +    /* center window on top of parent window */ +    if (option & F_CENTER) { +        gtk_window_set_position(GTK_WINDOW(w->gtkwin), GTK_WIN_POS_CENTER_ON_PARENT); +    } + +    w->widget = gtk_fixed_new(); + +    if (w->widget == 0) { +        abort(); +    } + +    if (w->option&F_MENUBAR) { +        w->menubar = gtk_menu_bar_new(); +        gtk_container_add(GTK_CONTAINER(w->widget), w->menubar); +        gtk_widget_show(w->menubar); +        gtk_widget_set_size_request(w->menubar, -1, MENUH); +    } + +    gtk_container_add(GTK_CONTAINER(w->gtkwin), w->widget); + +    if (w->option&F_AUTOSIZE) { +        w->realX = 0; +        w->w = 0; +        w->realY = h; +        w->h = 0; +    } else { +        w->w = w->realX = w->origX; +        w->h = w->realY = w->origY+h; +        gtk_widget_set_size_request(w->gtkwin, w->w, w->h); +        gtk_widget_set_size_request(w->widget, w->w, w->h); + +        if (w->option&F_MENUBAR) { +            gtk_widget_set_size_request(w->menubar, w->w, MENUH); +        } +    } + +    w->first = w->last = NULL; +    w->winProc = winProc; +    g_signal_connect(GTK_OBJECT(w->gtkwin), "delete_event", +                     G_CALLBACK(window_delete_event), w); +    g_signal_connect(GTK_OBJECT(w->widget), "expose_event", +                     G_CALLBACK(fixed_expose_event), w); +    g_signal_connect(GTK_OBJECT(w->gtkwin), "configure_event", +                     G_CALLBACK(window_configure_event), w); +    g_signal_connect(GTK_OBJECT(w->gtkwin), "key_press_event", +                     G_CALLBACK(window_char_event), w); +    g_signal_connect(GTK_OBJECT(w->gtkwin), "key_release_event", +                     G_CALLBACK(window_char_event), w); +    gtk_widget_set_events(w->widget, GDK_EXPOSURE_MASK); +    gtk_widget_set_events(GTK_WIDGET(w->gtkwin), +                          GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + +    if (w->option & F_RESIZE) { +        gtk_window_set_resizable(GTK_WINDOW(w->gtkwin), TRUE); +    } else { +        gtk_window_set_resizable(GTK_WINDOW(w->gtkwin), FALSE); +    } + +    w->lastX = 0; +    w->lastY = h; +    w->shown = FALSE; +    w->nameStr = nameStr?strdup(nameStr):NULL; + +    if (labelStr) { +        gtk_window_set_title(GTK_WINDOW(w->gtkwin), labelStr); +    } + +    if (listHelpStrings) { +        printf("WINDOW - %s\n", nameStr?nameStr:"<NULL>"); +    } + +    if (firstWin) { +        lastWin->next = (wControl_p)w; +    } else { +        firstWin = (wControl_p)w; +    } + +    lastWin = (wControl_p)w; +    gtk_widget_show(w->widget); +    gtk_widget_realize(w->gtkwin); +    w->busy = FALSE; +    return w; +} + + +/** + * Initialize the application's main window. This function does the necessary initialization + * of the application including creation of the main window. + * + * \param name IN internal name of the application. Used for filenames etc. + * \param x    IN Initial window width + * \param y    IN Initial window height + * \param helpStr IN Help topic string + * \param labelStr IN window title + * \param nameStr IN Window name + * \param option IN options for window creation + * \param winProc IN pointer to main window procedure + * \param data IN User context + * \return    window handle or NULL on error + */ + +wWin_p wWinMainCreate( +    const char * name,		/* Application name */ +    wPos_t x,				/* Initial window width */ +    wPos_t y,				/* Initial window height */ +    const char * helpStr,	/* Help topic string */ +    const char * labelStr,	/* Window title */ +    const char * nameStr,	/* Window name */ +    long option,			/* Options */ +    wWinCallBack_p winProc,	/* Call back function */ +    void * data)			/* User context */ +{ +    char *pos; + +    if (pos = strchr(name, ';')) { +        /* if found, split application name and configuration name */ +        strcpy(wConfigName, pos + 1); +    } else { +        /* if not found, application name and configuration name are same */ +        strcpy(wConfigName, name); +    } + +    gtkMainW = wWinCommonCreate(NULL, W_MAIN, x, y, labelStr, nameStr, option, +                                winProc, data); +    wDrawColorWhite = wDrawFindColor(0xFFFFFF); +    wDrawColorBlack = wDrawFindColor(0x000000); +    return gtkMainW; +} + +/** + * Create a new popup window. + * + * \param parent IN Parent window (may be NULL) + * \param x IN Initial window width + * \param y IN Initial window height + * \param helpStr IN Help topic string + * \param labelStr IN Window title + * \param nameStr IN Window name + * \param option IN Options + * \param winProc IN call back function + * \param data IN User context information + * \return    handle for new window + */ + +wWin_p wWinPopupCreate( +    wWin_p parent, +    wPos_t x, +    wPos_t y, +    const char * helpStr, +    const char * labelStr, +    const char * nameStr, +    long option, +    wWinCallBack_p winProc, +    void * data) +{ +    wWin_p win; + +    if (parent == NULL) { +        if (gtkMainW == NULL) { +            abort(); +        } + +        parent = gtkMainW; +    } + +    win = wWinCommonCreate(parent, W_POPUP, x, y, labelStr, nameStr, option, +                           winProc, data); +    return win; +} + + +/** + * Terminates the applicaton with code <rc>. Before closing the main window + * call back is called with wQuit_e. The program is terminated without exiting + * the main message loop. + * + * \param rc IN exit code + * \return    never returns + */ + + +void wExit( +    int rc)		/* Application return code */ +{ +    wWin_p win; + +    for (win = (wWin_p)firstWin; win; win = (wWin_p)win->next) { +        if (gtk_widget_get_visible(GTK_WIDGET(win->gtkwin))) { +            saveSize(win); +            savePos(win); +        } +    } + +    wPrefFlush(); + +    if (gtkMainW && gtkMainW->winProc != NULL) { +        gtkMainW->winProc(gtkMainW, wQuit_e, gtkMainW->data); +    } + +    exit(rc); +} diff --git a/app/wlib/gtklib/wpref.c b/app/wlib/gtklib/wpref.c index 4df3de9..effc2a5 100644 --- a/app/wlib/gtklib/wpref.c +++ b/app/wlib/gtklib/wpref.c @@ -1,6 +1,5 @@ -/** \file wpref.c Handle loading and saving preferences. - *  - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/wpref.c,v 1.15 2010-04-28 04:04:38 dspagnol Exp $ +/** \file wpref.c + * Handle loading and saving preferences.   */  /*  XTrkCad - Model Railroad CAD @@ -24,33 +23,31 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> -#include <dirent.h>  #include <ctype.h> +#include <dirent.h>  #include <sys/stat.h> +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +  #include "wlib.h" +#include "gtkint.h"  #include "dynarr.h"  #include "i18n.h" -#ifndef TRUE -#define TRUE	(1) -#define FALSE	(0) -#endif - -#ifdef XTRKCAD_CMAKE_BUILD  #include "xtrkcad-config.h" -#endif -extern char wAppName[];  extern char wConfigName[];  static char appLibDir[BUFSIZ];  static char appWorkDir[BUFSIZ];  static char userHomeDir[BUFSIZ]; -EXPORT void wInitAppName(char *appName) -{ -	strcpy(wAppName, appName); -}  /*   ******************************************************************************* @@ -61,16 +58,17 @@ EXPORT void wInitAppName(char *appName)   */ -EXPORT const char * wGetAppLibDir( void )  /** Find the directory where configuration files, help, demos etc are installed.    *  The search order is:   *  1. Directory specified by the XTRKCADLIB environment variable   *  2. Directory specified by XTRKCAD_INSTALL_PREFIX/share/xtrkcad - *  3. /usr/share/xtrkcad - *  4. /usr/local/share/xtrkcad + *  3. /usr/lib/xtrkcad + *  4. /usr/local/lib/xtrkcad   *     *  \return pointer to directory name   */ + +const char * wGetAppLibDir( void )  {  	char * cp, *ep;  	char msg[BUFSIZ*2]; @@ -81,7 +79,7 @@ EXPORT const char * wGetAppLibDir( void )  		return appLibDir;  	} -	for (cp=wAppName,ep=envvar; *cp; cp++,ep++) +	for (cp=wlibGetAppName(),ep=envvar; *cp; cp++,ep++)  		*ep = toupper(*cp);  	strcpy( ep, "LIB" );  	ep = getenv( envvar ); @@ -92,24 +90,22 @@ EXPORT const char * wGetAppLibDir( void )  		}  	} -#ifdef XTRKCAD_CMAKE_BUILD  	strcpy(appLibDir, XTRKCAD_INSTALL_PREFIX);  	strcat(appLibDir, "/share/"); -	strcat(appLibDir, wAppName); +	strcat(appLibDir, wlibGetAppName());  	if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {  		return appLibDir;  	} -#endif -	strcpy( appLibDir, "/usr/share/" ); -	strcat( appLibDir, wAppName ); +	strcpy( appLibDir, "/usr/lib/" ); +	strcat( appLibDir, wlibGetAppName() );  	if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {  		return appLibDir;  	} -	strcpy( appLibDir, "/usr/local/share/" ); -	strcat( appLibDir, wAppName ); +	strcpy( appLibDir, "/usr/local/lib/" ); +	strcat( appLibDir, wlibGetAppName() );  	if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {  		return appLibDir;  	} @@ -118,11 +114,11 @@ EXPORT const char * wGetAppLibDir( void )  		_("The required configuration files could not be located in the expected location.\n\n"  		"Usually this is an installation problem. Make sure that these files are installed in either \n"  		"  %s/share/xtrkcad or\n" -		"  /usr/share/%s or\n" -		"  /usr/local/share/%s\n" +		"  /usr/lib/%s or\n" +		"  /usr/local/lib/%s\n"  		"If this is not possible, the environment variable %s must contain "  		"the name of the correct directory."), -		XTRKCAD_INSTALL_PREFIX, wAppName, wAppName, envvar ); +		XTRKCAD_INSTALL_PREFIX, wlibGetAppName(), wlibGetAppName(), envvar );  	wNoticeEx( NT_ERROR, msg, _("Ok"), NULL );  	appLibDir[0] = '\0';  	wExit(0); @@ -138,7 +134,7 @@ EXPORT const char * wGetAppLibDir( void )   */ -EXPORT const char * wGetAppWorkDir( +const char * wGetAppWorkDir(  		void )  {  	char tmp[BUFSIZ+20]; @@ -152,7 +148,7 @@ EXPORT const char * wGetAppWorkDir(  		wNoticeEx( NT_ERROR, _("HOME is not set"), _("Exit"), NULL);  		wExit(0);  	} -	sprintf( appWorkDir, "%s/.%s", homeDir, wAppName ); +	sprintf( appWorkDir, "%s/.%s", homeDir, wlibGetAppName() );  	if ( (dirp = opendir(appWorkDir)) != NULL ) {  		closedir(dirp);  	} else { @@ -167,7 +163,7 @@ EXPORT const char * wGetAppWorkDir(  			 */  			struct stat stFileInfo;  			char appEtcConfig[BUFSIZ]; -			sprintf( appEtcConfig, "/etc/%s.rc", wAppName ); +			sprintf( appEtcConfig, "/etc/%s.rc", wlibGetAppName());  			if ( stat( appEtcConfig, &stFileInfo ) == 0 ) {  				char copyConfigCmd[(BUFSIZ * 2) + 3]; @@ -186,7 +182,7 @@ EXPORT const char * wGetAppWorkDir(   * \return    pointer to the user's home directory   */ -EXPORT const char *wGetUserHomeDir( void ) +const char *wGetUserHomeDir( void )  {  	char *homeDir; @@ -223,9 +219,13 @@ dynArr_t prefs_da;  #define prefs(N) DYNARR_N(prefs_t,prefs_da,N)  wBool_t prefInitted = FALSE; +/** + * Read the configuration file into memory + */ +  static void readPrefs( void )  { -	char tmp[BUFSIZ], *sp, *np, *vp, *cp; +	char tmp[BUFSIZ], *np, *vp, *cp;  	const char * workDir;  	FILE * prefFile;  	prefs_t * p; @@ -237,6 +237,8 @@ static void readPrefs( void )  	if (prefFile == NULL)  		return;  	while ( ( fgets(tmp, sizeof tmp, prefFile) ) != NULL ) { +		char *sp; +		  		sp = tmp;  		while ( *sp==' ' || *sp=='\t' ) sp++;  		if ( *sp == '\n' || *sp == '#' ) @@ -276,7 +278,7 @@ static void readPrefs( void )   * \param sval IN value to save   */ -EXPORT void wPrefSetString( +void wPrefSetString(  		const char * section,		/* Section */  		const char * name,		/* Name */  		const char * sval )		/* Value */ @@ -303,12 +305,16 @@ EXPORT void wPrefSetString(  	p->val = strdup(sval);  } +/** + * Get a string from the user preferences. + * + * \param section IN section in preferences file + * \param name IN name of parameter + */ -EXPORT const char * wPrefGetString(	 +const char * wPrefGetString(	  		const char * section,			/* Section */  		const char * name )			/* Name */ -/* -*/  {  	prefs_t * p; @@ -331,7 +337,7 @@ EXPORT const char * wPrefGetString(   * \param lval IN value to save   */ -EXPORT void wPrefSetInteger( + void wPrefSetInteger(  		const char * section,		/* Section */  		const char * name,		/* Name */  		long lval )		/* Value */ @@ -352,7 +358,7 @@ EXPORT void wPrefSetInteger(   * \return TRUE if value differs from default, FALSE if the same   */ -EXPORT wBool_t wPrefGetInteger( +wBool_t wPrefGetInteger(  		const char * section,		/* Section */  		const char * name,		/* Name */  		long * res,		/* Address of result */ @@ -382,7 +388,7 @@ EXPORT wBool_t wPrefGetInteger(   * \param lval IN the value   */ -EXPORT void wPrefSetFloat( + void wPrefSetFloat(  		const char * section,		/* Section */  		const char * name,		/* Name */  		double lval )		/* Value */ @@ -404,7 +410,7 @@ EXPORT void wPrefSetFloat(   */ -EXPORT wBool_t wPrefGetFloat( +wBool_t wPrefGetFloat(  		const char * section,		/* Section */  		const char * name,		/* Name */  		double * res,		/* Address of result */ @@ -426,40 +432,14 @@ EXPORT wBool_t wPrefGetFloat(  	return TRUE;  } - -EXPORT const char * wPrefGetSectionItem( -		const char * sectionName, -		wIndex_t * index, -		const char ** name ) -{ -	prefs_t * p; - -	if (!prefInitted) -		readPrefs(); -	 -	if ( *index >= prefs_da.cnt ) -		return NULL; - -	for (p=&prefs((*index)++); p<&prefs(prefs_da.cnt); p++,(*index)++) { -		if ( strcmp( p->section, sectionName ) == 0 ) { -			if ( name ) -				*name = p->name; -			return p->val; -		} -	} -	return NULL; -} -  /**   * Save the configuration to a file. The config parameters are held and updated in an array.   * To make the settings persistant, this function has to be called.    *   */ -EXPORT void wPrefFlush( +void wPrefFlush(  		void ) -/* -*/  {  	prefs_t * p;  	char tmp[BUFSIZ]; @@ -481,11 +461,13 @@ EXPORT void wPrefFlush(  	fclose( prefFile );  } +/** + * Clear the preferences from memory + * \return   + */ -EXPORT void wPrefReset( +void wPrefReset(  		void ) -/* -*/  {  	prefs_t * p;  | 
