summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2017-04-29 12:11:08 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2017-04-29 12:11:08 +0200
commit16e9630b79f0a7a90c6cedb6781175bb8b337dc1 (patch)
treee1b09d277dec2057e6b995ec099dd2b1f2129b35 /app/wlib/gtklib
parent09795a01ef859f072920de9df974d1b03b9ab9a4 (diff)
New upstream version 4.3.0upstream/4.3.0
Diffstat (limited to 'app/wlib/gtklib')
-rw-r--r--app/wlib/gtklib/CMakeLists.txt56
-rw-r--r--app/wlib/gtklib/bitmap.c136
-rw-r--r--app/wlib/gtklib/boxes.c203
-rw-r--r--app/wlib/gtklib/button.c630
-rw-r--r--app/wlib/gtklib/color.c466
-rw-r--r--app/wlib/gtklib/control.c283
-rw-r--r--app/wlib/gtklib/droplist.c456
-rw-r--r--app/wlib/gtklib/dynarr.h5
-rw-r--r--app/wlib/gtklib/filesel.c43
-rw-r--r--app/wlib/gtklib/font.c403
-rw-r--r--app/wlib/gtklib/gtkbitmap.c85
-rw-r--r--app/wlib/gtklib/gtkbutton.c461
-rw-r--r--app/wlib/gtklib/gtkcolor.c476
-rw-r--r--app/wlib/gtklib/gtkdraw-cairo.c138
-rw-r--r--app/wlib/gtklib/gtkfont.c342
-rw-r--r--app/wlib/gtklib/gtkhelp.c733
-rw-r--r--app/wlib/gtklib/gtkint.h263
-rw-r--r--app/wlib/gtklib/gtklist.c1131
-rw-r--r--app/wlib/gtklib/gtkmenu.c873
-rw-r--r--app/wlib/gtklib/gtkmisc.c1210
-rw-r--r--app/wlib/gtklib/gtksimple.c366
-rw-r--r--app/wlib/gtklib/gtksingle.c645
-rw-r--r--app/wlib/gtklib/gtksplash.c142
-rw-r--r--app/wlib/gtklib/gtktext.c670
-rw-r--r--app/wlib/gtklib/gtkwindow.c856
-rw-r--r--app/wlib/gtklib/gtkxpm.c173
-rw-r--r--app/wlib/gtklib/help.c69
-rw-r--r--app/wlib/gtklib/ixhelp.c441
-rw-r--r--app/wlib/gtklib/lines.c150
-rw-r--r--app/wlib/gtklib/list.c547
-rw-r--r--app/wlib/gtklib/liststore.c267
-rw-r--r--app/wlib/gtklib/main.c107
-rw-r--r--app/wlib/gtklib/menu.c1084
-rw-r--r--app/wlib/gtklib/message.c168
-rw-r--r--app/wlib/gtklib/notice.c297
-rw-r--r--app/wlib/gtklib/osxhelp.c133
-rw-r--r--app/wlib/gtklib/pixbuf.c99
-rw-r--r--app/wlib/gtklib/png.c64
-rw-r--r--app/wlib/gtklib/print.c1000
-rw-r--r--app/wlib/gtklib/single.c335
-rw-r--r--app/wlib/gtklib/splash.c144
-rw-r--r--app/wlib/gtklib/square10.bmp8
-rw-r--r--app/wlib/gtklib/text.c590
-rw-r--r--app/wlib/gtklib/timer.c144
-rw-r--r--app/wlib/gtklib/tooltip.c255
-rw-r--r--app/wlib/gtklib/treeview.c530
-rw-r--r--app/wlib/gtklib/util.c672
-rw-r--r--app/wlib/gtklib/window.c936
-rw-r--r--app/wlib/gtklib/wpref.c128
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 = &gtk_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 = &noticeW;
-
- 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 = &noticeW;
+
+ 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;