diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-04-29 12:11:08 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-04-29 12:11:08 +0200 |
commit | 16e9630b79f0a7a90c6cedb6781175bb8b337dc1 (patch) | |
tree | e1b09d277dec2057e6b995ec099dd2b1f2129b35 /app/wlib/gtklib | |
parent | 09795a01ef859f072920de9df974d1b03b9ab9a4 (diff) |
New upstream version 4.3.0upstream/4.3.0
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; |