From 09795a01ef859f072920de9df974d1b03b9ab9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 28 Dec 2016 20:24:50 +0100 Subject: New upstream version 4.2.4a --- app/wlib/gtklib/.directory | 7 - app/wlib/gtklib/CMakeLists.txt | 14 +- app/wlib/gtklib/FindGTKUnixPrint.cmake | 49 + app/wlib/gtklib/filesel.c | 64 +- app/wlib/gtklib/gtkcolor.c | 2 +- app/wlib/gtklib/gtkdraw-cairo.c | 118 +-- app/wlib/gtklib/gtkdraw.c | 1044 --------------------- app/wlib/gtklib/gtkfont.c | 88 +- app/wlib/gtklib/gtkint.h | 42 +- app/wlib/gtklib/gtklist.c | 70 +- app/wlib/gtklib/gtkmenu.c | 2 +- app/wlib/gtklib/gtktext.c | 308 ++++-- app/wlib/gtklib/gtkxpm.c | 90 +- app/wlib/gtklib/print.c | 858 +++++++++++++++++ app/wlib/gtklib/psprint.c | 1599 -------------------------------- app/wlib/gtklib/wpref.c | 12 +- app/wlib/include/wlib.h | 16 +- app/wlib/mswlib/mswbutt.c | 14 +- app/wlib/mswlib/mswlist.c | 35 + app/wlib/mswlib/mswmenu.c | 71 +- app/wlib/mswlib/mswmisc.c | 62 +- app/wlib/mswlib/simple-gettext.c | 7 +- 22 files changed, 1616 insertions(+), 2956 deletions(-) delete mode 100644 app/wlib/gtklib/.directory create mode 100644 app/wlib/gtklib/FindGTKUnixPrint.cmake delete mode 100644 app/wlib/gtklib/gtkdraw.c create mode 100644 app/wlib/gtklib/print.c delete mode 100644 app/wlib/gtklib/psprint.c (limited to 'app/wlib') diff --git a/app/wlib/gtklib/.directory b/app/wlib/gtklib/.directory deleted file mode 100644 index 2482e35..0000000 --- a/app/wlib/gtklib/.directory +++ /dev/null @@ -1,7 +0,0 @@ -[Dolphin] -HeaderColumnWidths=500,64,124 -SortOrder=1 -SortRole=date -Timestamp=2015,10,6,20,51,0 -Version=3 -ViewMode=1 diff --git a/app/wlib/gtklib/CMakeLists.txt b/app/wlib/gtklib/CMakeLists.txt index fabc5d8..cce9866 100644 --- a/app/wlib/gtklib/CMakeLists.txt +++ b/app/wlib/gtklib/CMakeLists.txt @@ -1,9 +1,13 @@ + FILE(GLOB HEADERS *.h) +INCLUDE (FindGTKUnixPrint.cmake) + SET(SOURCES gtkbitmap.c gtkbutton.c gtkcolor.c + gtkdraw-cairo.c filesel.c gtkfont.c gtkhelp.c @@ -16,22 +20,18 @@ SET(SOURCES gtktext.c gtkwindow.c gtkxpm.c - psprint.c + print.c wpref.c ) -IF(XTRKCAD_USE_GTK_CAIRO) - SET(SOURCES ${SOURCES} gtkdraw-cairo.c) -ELSE(XTRKCAD_USE_GTK_CAIRO) - SET(SOURCES ${SOURCES} gtkdraw.c) -ENDIF(XTRKCAD_USE_GTK_CAIRO) - SET_SOURCE_FILES_PROPERTIES(wpref.c PROPERTIES COMPILE_FLAGS -DEXPORT=) INCLUDE_DIRECTORIES(${XTrkCAD_BINARY_DIR}) INCLUDE_DIRECTORIES(${GTK_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${GTK_UNIX_PRINT_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${GTK_WEBKIT_INCLUDE_DIRS}) 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/FindGTKUnixPrint.cmake b/app/wlib/gtklib/FindGTKUnixPrint.cmake new file mode 100644 index 0000000..06bc548 --- /dev/null +++ b/app/wlib/gtklib/FindGTKUnixPrint.cmake @@ -0,0 +1,49 @@ +# - Try to find gtk-unix-print +# Once done, this will define +# +# GTK_UNIX_PRINT_FOUND - system has gtk-unix-print +# GTK_UNIX_PRINT_INCLUDE_DIRS - the gtk-unix-print include directories +# GTK_UNIX_PRINT_LIBRARIES - link these to use gtk-unix-print +# +# Copyright (C) 2012 Raphael Kubo da Costa +# Copyright (C) 2014 Igalia S.L. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +find_package(PkgConfig) +pkg_check_modules(GTK_UNIX_PRINT gtk+-unix-print-2.0) +set(VERSION_OK TRUE) + +if (GTK_UNIX_PRINT_VERSION) + if (GTK_UNIX_PRINT_FIND_VERSION_EXACT) + if (NOT("${GTK_UNIX_PRINT_FIND_VERSION}" VERSION_EQUAL "${GTK_UNIX_PRINT_VERSION}")) + set(VERSION_OK FALSE) + endif () + else () + if ("${GTK_UNIX_PRINT_VERSION}" VERSION_LESS "${GTK_UNIX_PRINT_FIND_VERSION}") + set(VERSION_OK FALSE) + endif () + endif () +endif () + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK_UNIX_PRINT DEFAULT_MSG GTK_UNIX_PRINT_INCLUDE_DIRS GTK_UNIX_PRINT_LIBRARIES VERSION_OK) diff --git a/app/wlib/gtklib/filesel.c b/app/wlib/gtklib/filesel.c index 4c737ae..4b92389 100644 --- a/app/wlib/gtklib/filesel.c +++ b/app/wlib/gtklib/filesel.c @@ -31,16 +31,19 @@ #include "gtkint.h" #include "i18n.h" +#define MAX_ALLOWEDFILTERS 10 + struct wFilSel_t { GtkWidget * window; wFilSelCallBack_p action; void * data; int pattCount; - GtkFileFilter *filter[ 10 ]; + GtkFileFilter *filter[ MAX_ALLOWEDFILTERS ]; wFilSelMode_e mode; int opt; const char * title; wWin_p parent; + char *defaultExtension; }; @@ -90,11 +93,15 @@ struct wFilSel_t * wFilSelCreate( count = 0; // names and patterns are separated by | cp = strtok( cp, "|" ); - while ( cp && count < 9 ) { + while ( cp && count < (MAX_ALLOWEDFILTERS - 1)) { fs->filter[ count ] = gtk_file_filter_new (); gtk_file_filter_set_name ( fs->filter[ count ], cp ); cp = strtok( NULL, "|" ); gtk_file_filter_add_pattern (fs->filter[ count ], cp ); + // the first pattern is considered to match the default extension + if( count == 0 ) { + fs->defaultExtension = strdup( cp ); + } cp = strtok( NULL, "|" ); count++; } @@ -121,9 +128,15 @@ struct wFilSel_t * wFilSelCreate( int wFilSelect( struct wFilSel_t * fs, const char * dirName ) { char name[1024]; - char *fileName; - const char *base; + char *host; + char *file; + char *namePart; int i; + GSList *fileNameList; + GError *err = NULL; + GtkFileFilter *activeFilter; + + char **fileNames; char * cp; if (fs->window == NULL) { @@ -137,6 +150,10 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName ) // get confirmation before overwritting an existing file gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(fs->window), TRUE ); + // allow selecting multiple files + if( fs->opt & FS_MULTIPLEFILES ) { + gtk_file_chooser_set_select_multiple ( GTK_FILE_CHOOSER(fs->window), TRUE); + } // add the file filters to the dialog box if( fs->pattCount ) { for( i = 0; i <= fs->pattCount; i++ ) { @@ -156,17 +173,38 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName ) gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER(fs->window), name ); if( gtk_dialog_run( GTK_DIALOG( fs->window )) == GTK_RESPONSE_ACCEPT ) { - fileName = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(fs->window) ); - if (fs->data) - strcpy( fs->data, fileName ); + + 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++ ) { + file = g_filename_from_uri( g_slist_nth_data( fileNameList, i ), &host, &err ); + + // check for presence of file extension + // jump behind tha last directory delimiter + namePart = strrchr( file, '/' ) + 1; + // is there a dot in the last part, yes->extension present + if( !strchr( namePart, '.' ) ){ + // make room for the extension + file = g_realloc( file, strlen(file)+strlen(fs->defaultExtension)); + strcat( file, fs->defaultExtension + 1 ); + } + fileNames[ i ] = file; + g_free( g_slist_nth_data ( fileNameList, i)); + } + + if (fs->data) + strcpy( fs->data, fileNames[ 0 ] ); + if (fs->action) { - base = strrchr( fileName, '/' ); - if (base==0) { - fprintf(stderr,"no / in %s\n", fileName ); - return 1; - } - fs->action( fileName, base+1, fs->data ); + fs->action( g_slist_length(fileNameList), fileNames, fs->data ); + } + + for(i=0; i < g_slist_length(fileNameList); i++) { + g_free( fileNames[ i ]); } + free( fileNames ); + g_slist_free (fileNameList); } gtk_widget_hide( GTK_WIDGET( fs->window )); diff --git a/app/wlib/gtklib/gtkcolor.c b/app/wlib/gtklib/gtkcolor.c index 3856f2a..cf17199 100644 --- a/app/wlib/gtklib/gtkcolor.c +++ b/app/wlib/gtklib/gtkcolor.c @@ -37,7 +37,7 @@ EXPORT wDrawColor wDrawColorWhite; EXPORT wDrawColor wDrawColorBlack; -#define RGB(R,G,B) ( ((long)(255&0xFF))<<24 | (((long)((R)&0xFF))<<16) | (((long)((G)&0xFF))<<8) | ((long)((B)&0xFF)) ) +#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) ) #define MAX_COLOR_DISTANCE (3) diff --git a/app/wlib/gtklib/gtkdraw-cairo.c b/app/wlib/gtklib/gtkdraw-cairo.c index e9b6447..9fc7eab 100644 --- a/app/wlib/gtklib/gtkdraw-cairo.c +++ b/app/wlib/gtklib/gtkdraw-cairo.c @@ -47,31 +47,31 @@ struct wDrawBitMap_t { GdkBitmap * mask; }; -struct wDraw_t { - WOBJ_COMMON - void * context; - wDrawActionCallBack_p action; - wDrawRedrawCallBack_p redraw; +//struct wDraw_t { + //WOBJ_COMMON + //void * context; + //wDrawActionCallBack_p action; + //wDrawRedrawCallBack_p redraw; - GdkPixmap * pixmap; - GdkPixmap * pixmapBackup; + //GdkPixmap * pixmap; + //GdkPixmap * pixmapBackup; - double dpi; + //double dpi; - GdkGC * gc; - wDrawWidth lineWidth; - wDrawOpts opts; - wPos_t maxW; - wPos_t maxH; - unsigned long lastColor; - wBool_t lastColorInverted; - const char * helpStr; + //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; + //wPos_t lastX; + //wPos_t lastY; - wBool_t delayUpdate; - }; + //wBool_t delayUpdate; + //}; struct wDraw_t psPrint_d; @@ -98,7 +98,7 @@ struct wDraw_t psPrint_d; * *******************************************************************************/ - + static GdkGC * selectGC( wDraw_p bd, @@ -301,10 +301,10 @@ EXPORT void wDrawArc( y = INMAPY(bd,y0+r); w = 2*r; h = 2*r; - + // remove the old arc gdk_draw_arc( bd->pixmap, gc, FALSE, x, y, w, h, (int)((-angle0 + 90)*64.0), (int)(-angle1*64.0) ); - + // and its center point if (drawCenter) { x = INMAPX(bd,x0); @@ -312,7 +312,7 @@ EXPORT void wDrawArc( gdk_draw_line( bd->pixmap, gc, x - ( CENTERMARK_LENGTH/2), y, x + ( CENTERMARK_LENGTH/2), y ); gdk_draw_line( bd->pixmap, gc, x, y - ( CENTERMARK_LENGTH/2), x, y + ( CENTERMARK_LENGTH/2)); } - + // now create the new arc cairo_t* cairo = gtkDrawCreateCairoContext(bd, width, lineType, color, opts); cairo_new_path(cairo); @@ -331,7 +331,7 @@ EXPORT void wDrawArc( // draw the curve itself cairo_arc_negative(cairo, INMAPX(bd, x0), INMAPY(bd, y0), r, (angle0 - 90 + angle1) * (M_PI / 180.0), (angle0 - 90) * (M_PI / 180.0)); cairo_stroke(cairo); - + gtkDrawDestroyCairoContext(cairo); if ( bd->delayUpdate || bd->widget == NULL) return; @@ -341,7 +341,7 @@ EXPORT void wDrawArc( update_rect.width = w+2+width+width; update_rect.height = h+2+width+width; gtk_widget_draw( bd->widget, &update_rect ); - + } EXPORT void wDrawPoint( @@ -397,18 +397,18 @@ EXPORT void wDrawString( gint ascent; gint descent; double angle = -M_PI * a / 180.0; - + if ( bd == &psPrint_d ) { psPrintString( x, y, a, (char *) s, fp, fs, color, opts ); return; } - + x = INMAPX(bd,x); y = INMAPY(bd,y); - + /* draw text */ cairo_t* cairo = gtkDrawCreateCairoContext(bd, 0, wDrawLineSolid, color, opts); - + cairo_save( cairo ); cairo_translate( cairo, x, y ); cairo_rotate( cairo, angle ); @@ -423,18 +423,18 @@ EXPORT void wDrawString( 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); cairo_restore( cairo ); gtkDrawDestroyCairoContext(cairo); - + if (bd->delayUpdate || bd->widget == NULL) return; - - /* recalculate the area to be updated + + /* recalculate the area to be updated * for simplicity sake I added plain text height ascent and descent, - * mathematically correct would be to use the trigonometrical functions as well - */ + * mathematically correct would be to use the trigonometrical functions as well + */ update_rect.x = (gint) x - ascent - descent - 1; update_rect.y = (gint) y - (gint) ascent - 1; update_rect.width = (gint) (w * cos( angle ) + 2 + ascent + descent); @@ -455,19 +455,19 @@ EXPORT void wDrawGetTextSize( int textHeight; int ascent; int descent; - + *w = 0; *h = 0; - + gtkFontDestroyPangoLayout( gtkFontCreatePangoLayout(bd->widget, NULL, fp, fs, s, &textWidth, (int *) &textHeight, (int *) &ascent, (int *) &descent)); - + *w = (wPos_t) textWidth; *h = (wPos_t) ascent; *d = (wPos_t) descent; - + if (debugWindow >= 3) fprintf(stderr, "text metrics: w=%d, h=%d, d=%d\n", *w, *h, *d); } @@ -670,7 +670,7 @@ EXPORT wDrawBitMap_p wDrawBitMapCreate( const char * fbits ) { wDrawBitMap_p bm; - + bm = (wDrawBitMap_p)malloc( sizeof *bm ); bm->w = w; bm->h = h; @@ -738,7 +738,7 @@ EXPORT void wDrawBitMap( } } #ifdef LATER - gdk_draw_pixmap(bd->pixmap, gc, + gdk_draw_pixmap(bd->pixmap, gc, bm->pixmap, 0, 0, x, y, @@ -752,7 +752,7 @@ EXPORT void wDrawBitMap( update_rect.height = bm->h; gtk_widget_draw( bd->widget, &update_rect ); } - + /******************************************************************************* * @@ -760,7 +760,7 @@ EXPORT void wDrawBitMap( * *******************************************************************************/ - + EXPORT void wDrawSaveImage( wDraw_p bd ) @@ -795,7 +795,7 @@ EXPORT void wDrawRestoreImage( 0, 0, 0, 0, bd->w, bd->h ); - + if ( bd->delayUpdate || bd->widget == NULL ) return; update_rect.x = 0; update_rect.y = 0; @@ -849,13 +849,19 @@ EXPORT void wDrawGetSize( *h = bd->h-2; } +/** + * Return the resolution of a device in dpi + * + * \param d IN the device + * \return the resolution in dpi + */ EXPORT double wDrawGetDPI( wDraw_p d ) { - if (d == &psPrint_d) - return 1440.0; - else + //if (d == &psPrint_d) + //return 1440.0; + //else return d->dpi; } @@ -927,20 +933,20 @@ static gint draw_scroll_event( case GDK_SCROLL_UP: action = wActionWheelUp; break; - case GDK_SCROLL_DOWN: + case GDK_SCROLL_DOWN: action = wActionWheelDown; - break; + break; default: action = 0; break; - } + } if (action != 0) { if (drawVerbose >= 2) printf( "%s[%dx%d]\n", actionNames[action], bd->lastX, bd->lastY ); bd->action( bd, bd->context, action, bd->lastX, bd->lastY ); } - + return TRUE; } @@ -979,7 +985,7 @@ static gint draw_button_event( case 3: /* right mouse button */ action = event->type==GDK_BUTTON_PRESS?wActionRDown:wActionRUp; /*bd->action( bd, bd->context, event->type==GDK_BUTTON_PRESS?wActionRDown:wActionRUp, bd->lastX, bd->lastY );*/ - break; + break; } if (action != 0) { if (drawVerbose >= 2) @@ -1009,7 +1015,7 @@ static gint draw_motion_event( y = event->y; state = event->state; } - + if (state & GDK_BUTTON1_MASK) { action = wActionLDrag; } else if (state & GDK_BUTTON3_MASK) { @@ -1062,9 +1068,9 @@ static gint draw_char_event( case GDK_F10: extKey = wAccelKey_F10; break; case GDK_F11: extKey = wAccelKey_F11; break; case GDK_F12: extKey = wAccelKey_F12; break; - default: ; + default: ; } - + if (extKey != wAccelKey_None) { if ( gtkFindAccelKey( event ) == NULL ) { bd->action( bd, bd->context, wActionExtKey + ((int)extKey<<8), bd->lastX, bd->lastY ); diff --git a/app/wlib/gtklib/gtkdraw.c b/app/wlib/gtklib/gtkdraw.c deleted file mode 100644 index b8f07ef..0000000 --- a/app/wlib/gtklib/gtkdraw.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkdraw.c,v 1.9 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 -#include -#ifdef HAVE_MALLOC_H -#include -#endif -#include -#include -#include -#include - -#include "gtkint.h" -#include "gdk/gdkkeysyms.h" - -static long drawVerbose = 0; - -struct wDrawBitMap_t { - int w; - int h; - int x; - int y; - const char * bits; - GdkPixmap * pixmap; - GdkBitmap * mask; - }; - -struct wDraw_t { - WOBJ_COMMON - void * context; - wDrawActionCallBack_p action; - wDrawRedrawCallBack_p redraw; - - GdkPixmap * pixmap; - GdkPixmap * pixmapBackup; - - 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; - }; - -struct wDraw_t psPrint_d; - -/***************************************************************************** - * - * MACROS - * - */ - -#define LBORDER (22) -#define RBORDER (6) -#define TBORDER (6) -#define BBORDER (20) - -#define INMAPX(D,X) (X) -#define INMAPY(D,Y) (((D)->h-1) - (Y)) -#define OUTMAPX(D,X) (X) -#define OUTMAPY(D,Y) (((D)->h-1) - (Y)) - - -/******************************************************************************* - * - * Basic Drawing Functions - * -*******************************************************************************/ - - - -static GdkGC * selectGC( - wDraw_p bd, - wDrawWidth width, - wDrawLineType_e lineType, - wDrawColor color, - wDrawOpts opts ) -{ - if (width < 0.0) { - width = - width; - } -/* - if ( color != bd->lastColor ) { - unsigned long pixColor; - unsigned long black, white; - white = WhitePixel(bd->display,DefaultScreen(bd->display)); - black = BlackPixel(bd->display,DefaultScreen(bd->display)); - pixColor = bd->colors[color] ^ white; - XSetForeground( bd->display, bd->normGc, pixColor ); - bd->lastColor = color; - } -*/ - if (opts&wDrawOptTemp) { - if (bd->lastColor != color || !bd->lastColorInverted) { - gdk_gc_set_foreground( bd->gc, gtkGetColor(color,FALSE) ); - bd->lastColor = color; - bd->lastColorInverted = TRUE; - } - gdk_gc_set_function( bd->gc, GDK_XOR ); - gdk_gc_set_line_attributes( bd->gc, width, - GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); - } else { - if (bd->lastColor != color || bd->lastColorInverted) { - gdk_gc_set_foreground( bd->gc, gtkGetColor(color,TRUE) ); - bd->lastColor = color; - bd->lastColorInverted = FALSE; - } - gdk_gc_set_function( bd->gc, GDK_COPY ); - if (lineType==wDrawLineDash) { - gdk_gc_set_line_attributes( bd->gc, width, - GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER ); - /*XSetDashes( bd->display, bd->normGc, 0, "\003\003", 2 );*/ - } else { - gdk_gc_set_line_attributes( bd->gc, width, - GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); - } - } - return bd->gc; -} - - -EXPORT void wDrawDelayUpdate( - wDraw_p bd, - wBool_t delay ) -{ - GdkRectangle update_rect; - - if ( (!delay) && bd->delayUpdate ) { - update_rect.x = 0; - update_rect.y = 0; - update_rect.width = bd->w; - update_rect.height = bd->h; - gtk_widget_draw( bd->widget, &update_rect ); - } - bd->delayUpdate = delay; -} - - -EXPORT void wDrawLine( - wDraw_p bd, - wPos_t x0, wPos_t y0, - wPos_t x1, wPos_t y1, - wDrawWidth width, - wDrawLineType_e lineType, - wDrawColor color, - wDrawOpts opts ) -{ - GdkGC * gc; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - psPrintLine( x0, y0, x1, y1, width, lineType, color, opts ); - return; - } - gc = selectGC( bd, width, lineType, color, opts ); - x0 = INMAPX(bd,x0); - y0 = INMAPY(bd,y0); - x1 = INMAPX(bd,x1); - y1 = INMAPY(bd,y1); - gdk_draw_line( bd->pixmap, gc, x0, y0, x1, y1 ); - if ( bd->delayUpdate || bd->widget == NULL ) return; - width /= 2; - if (x0 < x1) { - update_rect.x = x0-1-width; - update_rect.width = x1-x0+2+width+width; - } else { - update_rect.x = x1-1-width; - update_rect.width = x0-x1+2+width+width; - } - if (y0 < y1) { - update_rect.y = y0-1-width; - update_rect.height = y1-y0+2+width+width; - } else { - update_rect.y = y1-1-width; - update_rect.height = y0-y1+2+width+width; - } - gtk_widget_draw( bd->widget, &update_rect ); -} - -EXPORT void wDrawArc( - wDraw_p bd, - wPos_t x0, wPos_t y0, - wPos_t r, - wAngle_t angle0, - wAngle_t angle1, - int drawCenter, - wDrawWidth width, - wDrawLineType_e lineType, - wDrawColor color, - wDrawOpts opts ) -{ - int x, y, w, h; - GdkGC * gc; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - psPrintArc( x0, y0, r, angle0, angle1, drawCenter, width, lineType, color, opts ); - return; - } - gc = selectGC( bd, width, lineType, color, opts ); - if (r < 6.0/75.0) return; - x = INMAPX(bd,x0-r); - y = INMAPY(bd,y0+r); - w = 2*r; - h = 2*r; - if (drawCenter) - gdk_draw_point( bd->pixmap, gc, - INMAPX(bd, x0 ), INMAPY(bd, y0 ) ); - angle1 = -angle1; - angle0 = (-angle0) + 90.0; - gdk_draw_arc( bd->pixmap, gc, FALSE, x, y, w, h, - (int)(angle0*64.0), (int)(angle1*64.0) ); - if ( bd->delayUpdate || bd->widget == NULL) return; - width /= 2; - update_rect.x = x-1-width; - update_rect.y = y-1-width; - update_rect.width = w+2+width+width; - update_rect.height = h+2+width+width; - gtk_widget_draw( bd->widget, &update_rect ); - -} - -EXPORT void wDrawPoint( - wDraw_p bd, - wPos_t x0, wPos_t y0, - wDrawColor color, - wDrawOpts opts ) -{ - GdkGC * gc; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - /*psPrintArc( x0, y0, r, angle0, angle1, drawCenter, width, lineType, color, opts );*/ - return; - } - gc = selectGC( bd, 0, wDrawLineSolid, color, opts ); - gdk_draw_point( bd->pixmap, gc, - INMAPX(bd, x0 ), INMAPY(bd, y0 ) ); - if ( bd->delayUpdate || bd->widget == NULL) return; - update_rect.x = INMAPX(bd, x0 )-1; - update_rect.y = INMAPY(bd, y0 )-1; - update_rect.width = 2; - update_rect.height = 2; - gtk_widget_draw( bd->widget, &update_rect ); -} - -/******************************************************************************* - * - * Strings - * - ******************************************************************************/ - -EXPORT void wDrawString( - wDraw_p bd, - wPos_t x, wPos_t y, - wAngle_t a, - const char * s, - wFont_p fp, - wFontSize_t fs, - wDrawColor color, - wDrawOpts opts ) -{ - GdkGC * gc; - PangoLayout *layout; - GdkRectangle update_rect; - int w; - int h; - gint ascent; - gint descent; - - if ( bd == &psPrint_d ) { - psPrintString( x, y, a, (char *)s, fp, fs, color, opts ); - return; - } - - x = INMAPX(bd,x); - y = INMAPY(bd,y); - - gc = selectGC( bd, 0, wDrawLineSolid, color, opts ); - - layout = gtkFontCreatePangoLayout(bd->widget, NULL, fp, fs, s, - (int *) &w, (int *) &h, - (int *) &ascent, (int *) &descent); - - gdk_draw_layout(bd->pixmap, gc, x, y - ascent, layout); - gtkFontDestroyPangoLayout(layout); - - if (bd->delayUpdate || bd->widget == NULL) return; - update_rect.x = (gint) x - 1; - update_rect.y = (gint) y - ascent - 1; - update_rect.width = (gint) w + 2; - update_rect.height = (gint) ascent + (gint) descent + 2; - gtk_widget_draw(bd->widget, &update_rect); -} - -EXPORT void wDrawGetTextSize( - wPos_t *w, - wPos_t *h, - wPos_t *d, - wDraw_p bd, - const char * s, - wFont_p fp, - wFontSize_t fs ) -{ - int textWidth; - int textHeight; - int ascent; - int descent; - - *w = 0; - *h = 0; - - gtkFontDestroyPangoLayout( - gtkFontCreatePangoLayout(bd->widget, NULL, fp, fs, s, - &textWidth, (int *) &textHeight, - (int *) &ascent, (int *) &descent)); - - *w = (wPos_t) textWidth; - *h = (wPos_t) ascent; - *d = (wPos_t) descent; - - if (debugWindow >= 3) - fprintf(stderr, "text metrics: w=%d, h=%d, d=%d\n", *w, *h, *d); -} - - -/******************************************************************************* - * - * Basic Drawing Functions - * -*******************************************************************************/ - -EXPORT void wDrawFilledRectangle( - wDraw_p bd, - wPos_t x, - wPos_t y, - wPos_t w, - wPos_t h, - wDrawColor color, - wDrawOpts opt ) -{ - GdkGC * gc; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - psPrintFillRectangle( x, y, w, h, color, opt ); - return; - } - - gc = selectGC( bd, 0, wDrawLineSolid, color, opt ); - x = INMAPX(bd,x); - y = INMAPY(bd,y)-h; - gdk_draw_rectangle( bd->pixmap, gc, TRUE, x, y, w, h ); - if ( bd->delayUpdate || bd->widget == NULL) return; - update_rect.x = x-1; - update_rect.y = y-1; - update_rect.width = w+2; - update_rect.height = h+2; - gtk_widget_draw( bd->widget, &update_rect ); -} - -EXPORT void wDrawFilledPolygon( - wDraw_p bd, - wPos_t p[][2], - int cnt, - wDrawColor color, - wDrawOpts opt ) -{ - GdkGC * gc; - static int maxCnt = 0; - static GdkPoint *points; - int i; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - psPrintFillPolygon( p, cnt, color, opt ); - return; - } - - if (cnt > maxCnt) { - if (points == NULL) - points = (GdkPoint*)malloc( cnt*sizeof *points ); - else - points = (GdkPoint*)realloc( points, cnt*sizeof *points ); - if (points == NULL) - abort(); - maxCnt = cnt; - } - - update_rect.x = bd->w; - update_rect.y = bd->h; - update_rect.width = 0; - update_rect.height = 0; - for (i=0; i points[i].x) - update_rect.x = points[i].x; - if (update_rect.width < points[i].x) - update_rect.width = points[i].x; - if (update_rect.y > points[i].y) - update_rect.y = points[i].y; - if (update_rect.height < points[i].y) - update_rect.height = points[i].y; - } - update_rect.x -= 1; - update_rect.y -= 1; - update_rect.width -= update_rect.x-2; - update_rect.height -= update_rect.y-2; - gc = selectGC( bd, 0, wDrawLineSolid, color, opt ); - gdk_draw_polygon( bd->pixmap, gc, TRUE, - points, cnt ); - if ( bd->delayUpdate || bd->widget == NULL) return; - gtk_widget_draw( bd->widget, &update_rect ); -} - -EXPORT void wDrawFilledCircle( - wDraw_p bd, - wPos_t x0, - wPos_t y0, - wPos_t r, - wDrawColor color, - wDrawOpts opt ) -{ - GdkGC * gc; - int x, y, w, h; - GdkRectangle update_rect; - - if ( bd == &psPrint_d ) { - psPrintFillCircle( x0, y0, r, color, opt ); - return; - } - - gc = selectGC( bd, 0, wDrawLineSolid, color, opt ); - x = INMAPX(bd,x0-r); - y = INMAPY(bd,y0+r); - w = 2*r; - h = 2*r; - gdk_draw_arc( bd->pixmap, gc, TRUE, x, y, w, h, 0, 360*64 ); - if ( bd->delayUpdate || bd->widget == NULL) return; - update_rect.x = x-1; - update_rect.y = y-1; - update_rect.width = w+2; - update_rect.height = h+2; - gtk_widget_draw( bd->widget, &update_rect ); - -} - - -EXPORT void wDrawClear( - wDraw_p bd ) -{ - GdkGC * gc; - GdkRectangle update_rect; - - gc = selectGC( bd, 0, wDrawLineSolid, wDrawColorWhite, 0 ); - gdk_draw_rectangle(bd->pixmap, gc, TRUE, 0, 0, - bd->w, bd->h); - if ( bd->delayUpdate || bd->widget == NULL) return; - update_rect.x = 0; - update_rect.y = 0; - update_rect.width = bd->w; - update_rect.height = bd->h; - gtk_widget_draw( bd->widget, &update_rect ); -} - -EXPORT void * wDrawGetContext( - wDraw_p bd ) -{ - return bd->context; -} - -/******************************************************************************* - * - * Bit Maps - * -*******************************************************************************/ - - -EXPORT wDrawBitMap_p wDrawBitMapCreate( - wDraw_p bd, - int w, - int h, - int x, - int y, - const char * fbits ) -{ - wDrawBitMap_p bm; - - bm = (wDrawBitMap_p)malloc( sizeof *bm ); - bm->w = w; - bm->h = h; - /*bm->pixmap = gtkMakeIcon( NULL, fbits, w, h, wDrawColorBlack, &bm->mask );*/ - bm->bits = fbits; - bm->x = x; - bm->y = y; - return bm; -} - - -EXPORT void wDrawBitMap( - wDraw_p bd, - wDrawBitMap_p bm, - wPos_t x, wPos_t y, - wDrawColor color, - wDrawOpts opts ) -{ - GdkGC * gc; - GdkRectangle update_rect; - int i, j, wb; - wPos_t xx, yy; - wControl_p b; - GdkDrawable * gdk_window; - - x = INMAPX( bd, x-bm->x ); - y = INMAPY( bd, y-bm->y )-bm->h; - wb = (bm->w+7)/8; - gc = selectGC( bd, 0, wDrawLineSolid, color, opts ); - for ( i=0; iw; i++ ) - for ( j=0; jh; j++ ) - if ( bm->bits[ j*wb+(i>>3) ] & (1<<(i&07)) ) { - xx = x+i; - yy = y+j; - if ( 0 <= xx && xx < bd->w && - 0 <= yy && yy < bd->h ) { - gdk_window = bd->pixmap; - b = (wControl_p)bd; - } else if ( (opts&wDrawOptNoClip) != 0 ) { - xx += bd->realX; - yy += bd->realY; - b = gtkGetControlFromPos( bd->parent, xx, yy ); - if ( b ) { - if ( b->type == B_DRAW ) - gdk_window = ((wDraw_p)b)->pixmap; - else - gdk_window = b->widget->window; - xx -= b->realX; - yy -= b->realY; - } else { - gdk_window = bd->parent->widget->window; - } - } else { - continue; - } -/*printf( "gdk_draw_point( %ld, gc, %d, %d )\n", (long)gdk_window, xx, yy );*/ - gdk_draw_point( gdk_window, gc, xx, yy ); - if ( b && b->type == B_DRAW ) { - update_rect.x = xx-1; - update_rect.y = yy-1; - update_rect.width = 3; - update_rect.height = 3; - gtk_widget_draw( b->widget, &update_rect ); - } - } -#ifdef LATER - gdk_draw_pixmap(bd->pixmap, gc, - bm->pixmap, - 0, 0, - x, y, - bm->w, bm->h ); -#endif - if ( bd->delayUpdate || bd->widget == NULL) return; - - update_rect.x = x; - update_rect.y = y; - update_rect.width = bm->w; - update_rect.height = bm->h; - gtk_widget_draw( bd->widget, &update_rect ); -} - - -/******************************************************************************* - * - * Event Handlers - * -*******************************************************************************/ - - - -EXPORT void wDrawSaveImage( - wDraw_p bd ) -{ - if ( bd->pixmapBackup ) { - gdk_pixmap_unref( bd->pixmapBackup ); - } - bd->pixmapBackup = gdk_pixmap_new( bd->widget->window, bd->w, bd->h, -1 ); - selectGC( bd, 0, wDrawLineSolid, bd->lastColor, 0 ); - gdk_draw_pixmap( bd->pixmapBackup, bd->gc, - bd->pixmap, - 0, 0, - 0, 0, - bd->w, bd->h ); -} - - -EXPORT void wDrawRestoreImage( - wDraw_p bd ) -{ - GdkRectangle update_rect; - if ( bd->pixmapBackup ) { - selectGC( bd, 0, wDrawLineSolid, bd->lastColor, 0 ); - gdk_draw_pixmap( bd->pixmap, bd->gc, - bd->pixmapBackup, - 0, 0, - 0, 0, - bd->w, bd->h ); - if ( bd->delayUpdate || bd->widget == NULL ) return; - update_rect.x = 0; - update_rect.y = 0; - update_rect.width = bd->w; - update_rect.height = bd->h; - gtk_widget_draw( bd->widget, &update_rect ); - } -} - - -EXPORT void wDrawSetSize( - wDraw_p bd, - wPos_t w, - wPos_t h ) -{ - wBool_t repaint; - if (bd == NULL) { - fprintf(stderr,"resizeDraw: no client data\n"); - return; - } - - /* Negative values crashes the program */ - if (w < 0 || h < 0) - return; - - repaint = (w != bd->w || h != bd->h); - bd->w = w; - bd->h = h; - gtk_widget_set_size_request( bd->widget, w, h ); - if (repaint) { - if (bd->pixmap) - gdk_pixmap_unref( bd->pixmap ); - bd->pixmap = gdk_pixmap_new( bd->widget->window, w, h, -1 ); - wDrawClear( bd ); - /*bd->redraw( bd, bd->context, w, h );*/ - } - /*wRedraw( bd );*/ -} - - -EXPORT void wDrawGetSize( - wDraw_p bd, - wPos_t *w, - wPos_t *h ) -{ - if (bd->widget) - gtkControlGetSize( (wControl_p)bd ); - *w = bd->w-2; - *h = bd->h-2; -} - - -EXPORT double wDrawGetDPI( - wDraw_p d ) -{ - if (d == &psPrint_d) - return 1440.0; - else - return d->dpi; -} - - -EXPORT double wDrawGetMaxRadius( - wDraw_p d ) -{ - if (d == &psPrint_d) - return 10e9; - else - return 32767.0; -} - - -EXPORT void wDrawClip( - wDraw_p d, - wPos_t x, - wPos_t y, - wPos_t w, - wPos_t h ) -{ - GdkRectangle rect; - rect.width = w; - rect.height = h; - rect.x = INMAPX( d, x ); - rect.y = INMAPY( d, y ) - rect.height; - gdk_gc_set_clip_rectangle( d->gc, &rect ); - -} - - -static gint draw_expose_event( - GtkWidget *widget, - GdkEventExpose *event, - wDraw_p bd) -{ - gdk_draw_pixmap(widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - bd->pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, event->area.height); - return FALSE; -} - - -static gint draw_configure_event( - GtkWidget *widget, - GdkEventConfigure *event, - wDraw_p bd) -{ - return FALSE; -} - -static const char * actionNames[] = { "None", "Move", "LDown", "LDrag", "LUp", "RDown", "RDrag", "RUp", "Text", "ExtKey", "WUp", "WDown" }; - -/** - * Handler for scroll events, ie mouse wheel activity - */ - -static gint draw_scroll_event( - GtkWidget *widget, - GdkEventScroll *event, - wDraw_p bd) -{ - wAction_t action; - - switch( event->direction ) { - case GDK_SCROLL_UP: - action = wActionWheelUp; - break; - case GDK_SCROLL_DOWN: - action = wActionWheelDown; - break; - default: - action = 0; - break; - } - - if (action != 0) { - if (drawVerbose >= 2) - printf( "%s[%dx%d]\n", actionNames[action], bd->lastX, bd->lastY ); - bd->action( bd, bd->context, action, bd->lastX, bd->lastY ); - } - - return TRUE; -} - - - -static gint draw_leave_event( - GtkWidget *widget, - GdkEvent * event ) -{ - gtkHelpHideBalloon(); - return FALSE; -} - - -/** - * Handler for mouse button clicks. - */ - -static gint draw_button_event( - GtkWidget *widget, - GdkEventButton *event, - wDraw_p bd ) -{ - wAction_t action = 0; - if (bd->action == NULL) - return TRUE; - - bd->lastX = OUTMAPX(bd, event->x); - bd->lastY = OUTMAPY(bd, event->y); - - switch ( event->button ) { - case 1: /* left mouse button */ - action = event->type==GDK_BUTTON_PRESS?wActionLDown:wActionLUp; - /*bd->action( bd, bd->context, event->type==GDK_BUTTON_PRESS?wActionLDown:wActionLUp, bd->lastX, bd->lastY );*/ - break; - case 3: /* right mouse button */ - action = event->type==GDK_BUTTON_PRESS?wActionRDown:wActionRUp; - /*bd->action( bd, bd->context, event->type==GDK_BUTTON_PRESS?wActionRDown:wActionRUp, bd->lastX, bd->lastY );*/ - break; - } - if (action != 0) { - if (drawVerbose >= 2) - printf( "%s[%dx%d]\n", actionNames[action], bd->lastX, bd->lastY ); - bd->action( bd, bd->context, action, bd->lastX, bd->lastY ); - } - gtk_widget_grab_focus( bd->widget ); - return TRUE; -} - -static gint draw_motion_event( - GtkWidget *widget, - GdkEventMotion *event, - wDraw_p bd ) -{ - int x, y; - GdkModifierType state; - wAction_t action; - - if (bd->action == NULL) - return TRUE; - - if (event->is_hint) { - gdk_window_get_pointer (event->window, &x, &y, &state); - } else { - x = event->x; - y = event->y; - state = event->state; - } - - if (state & GDK_BUTTON1_MASK) { - action = wActionLDrag; - } else if (state & GDK_BUTTON3_MASK) { - action = wActionRDrag; - } else { - action = wActionMove; - } - bd->lastX = OUTMAPX(bd, x); - bd->lastY = OUTMAPY(bd, y); - if (drawVerbose >= 2) - printf( "%lx: %s[%dx%d] %s\n", (long)bd, actionNames[action], bd->lastX, bd->lastY, event->is_hint?"":"<>" ); - bd->action( bd, bd->context, action, bd->lastX, bd->lastY ); - gtk_widget_grab_focus( bd->widget ); - return TRUE; -} - - -static gint draw_char_event( - GtkWidget * widget, - GdkEventKey *event, - wDraw_p bd ) -{ - 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; - default: ; - } - - if (extKey != wAccelKey_None) { - if ( gtkFindAccelKey( event ) == NULL ) { - bd->action( bd, bd->context, wActionExtKey + ((int)extKey<<8), bd->lastX, bd->lastY ); - } - return TRUE; - } else if (key <= 0xFF && (event->state&(GDK_CONTROL_MASK|GDK_MOD1_MASK)) == 0 && bd->action) { - bd->action( bd, bd->context, wActionText+(key<<8), bd->lastX, bd->lastY ); - return TRUE; - } else { - return FALSE; - } -} - - -/******************************************************************************* - * - * Create - * -*******************************************************************************/ - - - -int XW = 0; -int XH = 0; -int xw, xh, cw, ch; - -EXPORT wDraw_p wDrawCreate( - wWin_p parent, - wPos_t x, - wPos_t y, - const char * helpStr, - long option, - wPos_t width, - wPos_t height, - void * context, - wDrawRedrawCallBack_p redraw, - wDrawActionCallBack_p action ) -{ - wDraw_p bd; - - bd = (wDraw_p)gtkAlloc( 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 ); - - bd->widget = gtk_drawing_area_new(); - gtk_drawing_area_size( GTK_DRAWING_AREA(bd->widget), width, height ); - gtk_widget_set_size_request( GTK_WIDGET(bd->widget), width, height ); - gtk_signal_connect (GTK_OBJECT (bd->widget), "expose_event", - (GtkSignalFunc) draw_expose_event, bd); - gtk_signal_connect (GTK_OBJECT(bd->widget),"configure_event", - (GtkSignalFunc) draw_configure_event, bd); - gtk_signal_connect (GTK_OBJECT (bd->widget), "motion_notify_event", - (GtkSignalFunc) draw_motion_event, bd); - gtk_signal_connect (GTK_OBJECT (bd->widget), "button_press_event", - (GtkSignalFunc) draw_button_event, bd); - gtk_signal_connect (GTK_OBJECT (bd->widget), "button_release_event", - (GtkSignalFunc) draw_button_event, bd); - gtk_signal_connect (GTK_OBJECT (bd->widget), "scroll_event", - (GtkSignalFunc) draw_scroll_event, bd); - gtk_signal_connect_after (GTK_OBJECT (bd->widget), "key_press_event", - (GtkSignalFunc) draw_char_event, bd); - gtk_signal_connect (GTK_OBJECT (bd->widget), "leave_notify_event", - (GtkSignalFunc) draw_leave_event, bd); - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(bd->widget), GTK_CAN_FOCUS); - gtk_widget_set_events (bd->widget, GDK_EXPOSURE_MASK - | GDK_LEAVE_NOTIFY_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK -/* | GDK_SCROLL_MASK */ - | GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_KEY_PRESS_MASK - | GDK_KEY_RELEASE_MASK ); - bd->lastColor = -1; - bd->dpi = 75; - bd->maxW = bd->w = width; - bd->maxH = bd->h = height; - - gtk_fixed_put( GTK_FIXED(parent->widget), bd->widget, bd->realX, bd->realY ); - gtkControlGetSize( (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 ); - gdk_gc_copy( bd->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); -{ - GdkCursor * cursor; - cursor = gdk_cursor_new ( GDK_TCROSS ); - gdk_window_set_cursor ( bd->widget->window, cursor); - gdk_cursor_destroy (cursor); -} -#ifdef LATER - if (labelStr) - bd->labelW = gtkAddLabel( (wControl_p)bd, labelStr ); -#endif - gtk_widget_show( bd->widget ); - gtkAddButton( (wControl_p)bd ); - gtkAddHelpString( bd->widget, helpStr ); - return bd; -} - -/******************************************************************************* - * - * BitMaps - * -*******************************************************************************/ - -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->lastColor = -1; - bd->dpi = 75; - bd->maxW = bd->w = w; - bd->maxH = bd->h = h; - - bd->pixmap = gdk_pixmap_new( gtkMainW->widget->window, w, h, -1 ); - if ( bd->pixmap == NULL ) { - wNoticeEx( NT_ERROR, "CreateBitMap: pixmap_new failed", "Ok", NULL ); - return FALSE; - } - bd->gc = gdk_gc_new( gtkMainW->gtkwin->window ); - if ( bd->gc == NULL ) { - wNoticeEx( NT_ERROR, "CreateBitMap: gc_new failed", "Ok", NULL ); - return FALSE; - } - gdk_gc_copy( bd->gc, gtkMainW->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); - wDrawClear( bd ); - return bd; -} - - -wBool_t wBitMapDelete( wDraw_p d ) -{ - gdk_pixmap_unref( d->pixmap ); - d->pixmap = NULL; - return TRUE; -} diff --git a/app/wlib/gtklib/gtkfont.c b/app/wlib/gtklib/gtkfont.c index 1a707f8..89937d7 100644 --- a/app/wlib/gtklib/gtkfont.c +++ b/app/wlib/gtklib/gtkfont.c @@ -1,7 +1,5 @@ /** \file gtkfont.c * Font selection and loading. - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkfont.c,v 1.12 2009-12-07 19:31:31 m_fischer Exp $ */ /* XTrkCad - Model Railroad CAD @@ -81,7 +79,7 @@ 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 */ @@ -120,10 +118,10 @@ static wBool_t fontInit() "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) { @@ -134,7 +132,7 @@ static wBool_t fontInit() } } } - + if (curFont == NULL) { curFont = (wFont_p) malloc(sizeof(struct wFont_t)); if (curFont == NULL) @@ -143,7 +141,7 @@ static wBool_t fontInit() 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; } @@ -153,6 +151,21 @@ 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, @@ -165,9 +178,9 @@ PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, { if (!fontInitted) fontInit(); - + PangoLayout *layout = NULL; - + gchar *utf8 = gtkConvertInput(s); /* RPH -- pango_cairo_create_layout() is missing in CentOS 4.8. @@ -175,7 +188,7 @@ PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, libpangocairo at all. pango_cairo_create_layout() was introduced with Pango 1.10. */ -#if PANGO_VERSION_MAJOR >= 1 && PANGO_VERSION_MINOR >= 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); @@ -183,17 +196,17 @@ PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, 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); @@ -202,7 +215,7 @@ PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, *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); @@ -214,7 +227,7 @@ PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget, fprintf(stderr, " layout ascent: %d (pixels)\n", *ascent_p); fprintf(stderr, " layout descent: %d (pixels)\n", *descent_p); #endif - + return layout; } @@ -234,7 +247,7 @@ void wSelectFont( { 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); @@ -244,17 +257,17 @@ void wSelectFont( 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 + /* the curFont description contains the latest font info * which is depended on the current scale - * overwrite it with the absoluteFontSize */ + * 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); } @@ -262,7 +275,7 @@ static wFont_p gtkSelectedFont( void ) { if (!fontInitted) fontInit(); - + return curFont; } @@ -270,12 +283,12 @@ 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); + 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; } @@ -283,26 +296,35 @@ wFontSize_t wSelectedFontSize( void ) 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); @@ -315,6 +337,6 @@ 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/gtkint.h b/app/wlib/gtklib/gtkint.h index 4cbeace..c27c70b 100644 --- a/app/wlib/gtklib/gtkint.h +++ b/app/wlib/gtklib/gtkint.h @@ -68,7 +68,7 @@ typedef void (*setTriggerCallback_p)( wControl_p b ); struct wWin_t { WOBJ_COMMON - GtkWidget *gtkwin; /**< GTK window */ + GtkWidget *gtkwin; /**< GTK window */ wPos_t lastX, lastY; wControl_p first, last; wWinCallBack_p winProc; /**< window procedure */ @@ -157,15 +157,10 @@ void gtkPrintColorMap( FILE *, int, int ); int gtkMapPixel( long ); /* psprint.c */ -typedef struct { - wIndex_t cmdOrFile; - FILE * f; - } wPrinterStream_t; -typedef wPrinterStream_t * wPrinterStream_p; - -wPrinterStream_p wPrinterOpen( void ); -void wPrinterWrite( wPrinterStream_p p, char * buff, int siz ); -void wPrinterClose( wPrinterStream_p ); + +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, @@ -177,4 +172,31 @@ 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 ); +struct wDraw_t { + WOBJ_COMMON + void * context; + wDrawActionCallBack_p action; + wDrawRedrawCallBack_p redraw; + + GdkPixmap * pixmap; + GdkPixmap * pixmapBackup; + + 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; + cairo_t *printContext; + cairo_surface_t *curPrintSurface; + }; #endif diff --git a/app/wlib/gtklib/gtklist.c b/app/wlib/gtklib/gtklist.c index b2c9799..fb8afaa 100644 --- a/app/wlib/gtklib/gtklist.c +++ b/app/wlib/gtklib/gtklist.c @@ -1,7 +1,6 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtklist.c,v 1.4 2009-05-30 11:11:26 m_fischer Exp $ +/** \file gtklist.c + * Listboxes, dropdown boxes, combo boxes */ - /* XTrkCad - Model Railroad CAD * Copyright (C) 2005 Dave Bullis * @@ -42,7 +41,7 @@ static char ListItemDataKey[] = "ListItemDataKey"; */ typedef struct wListItem_t * wListItem_p; - + struct wList_t { WOBJ_COMMON GtkWidget *list; @@ -73,7 +72,7 @@ struct wListItem_t { static wListItem_p getListItem( wList_p b, - wIndex_t inx, + wIndex_t inx, GList ** childR ) { GList * child; @@ -86,7 +85,7 @@ static wListItem_p getListItem( 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" ); @@ -195,7 +194,7 @@ static void parseLabelStr( textBuffer = (char**)realloc( textBuffer, count * sizeof *textBuffer ); textBufferCount = count; } - + strcpy( labelBuffer, labelStr ); cp = labelBuffer; for ( col=0; cp && collist)); + + // and synchronize the internal data structures + wListGetCount(bl); + for ( inx=0; inxcount; inx++ ) { + ldp = getListItem( bl, inx, NULL ); + + ldp->selected = TRUE; + } +} EXPORT wBool_t wListSetValues( wList_p b, @@ -494,21 +516,21 @@ If list is created with 'BL_ } 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 + + /* + * 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. + * 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 ); @@ -609,7 +631,7 @@ static int selectCList( bl->action( row, id_p->label, 1, bl->data, id_p->itemData ); return 1; } - + static int unselectCList( GtkWidget * clist, @@ -753,7 +775,7 @@ static int DropListSelectionChanged( return 1; #endif } - + #endif @@ -817,7 +839,7 @@ EXPORT wList_p wListCreate( void *data ) /* Context */ /* */ -{ +{ wList_p b; b = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *b, data ); @@ -873,17 +895,17 @@ EXPORT wList_p wListCreate( /** Create a drop down list. The drop down is created and intialized with the supplied values. * - * \param IN parent Parent window + * \param IN parent Parent window * \param IN x, X-position * \param IN y Y-position - * \param IN helpStr Help string + * \param IN helpStr Help string * \param IN labelStr Label - * \param IN option Options + * \param IN option Options * \param IN number Number of displayed entries - * \param IN width Width + * \param IN width Width * \param IN valueP Selected index * \param IN action Callback - * \param IN data Context + * \param IN data Context */ EXPORT wList_p wDropListCreate( @@ -1032,7 +1054,7 @@ EXPORT wList_p wListCreate( void *data ) /* Context */ /* */ -{ +{ wList_p bl; long col; static wPos_t zeroPos = 0; @@ -1069,7 +1091,7 @@ EXPORT wList_p wListCreate( 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 ); + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(bl->widget), bl->list ); if (width == 0) width = 100; for ( col=0; colcount <= 0) abort(); + if (ml->count < 0) abort(); origin = getMlistOrigin(ml->parentMenu, ml); children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) ); if (children == NULL) abort(); diff --git a/app/wlib/gtklib/gtktext.c b/app/wlib/gtklib/gtktext.c index 8da31d3..e067f43 100644 --- a/app/wlib/gtklib/gtktext.c +++ b/app/wlib/gtklib/gtktext.c @@ -1,5 +1,5 @@ /** \file gtktext.c - * Multi line text entry + * Multi-line Text Boxes */ /* XTrkCad - Model Railroad CAD @@ -24,7 +24,8 @@ #include #include #include - +#include +#include "i18n.h" #include "gtkint.h" /* @@ -32,13 +33,18 @@ */ #define USE_TEXTVIEW -/* - ***************************************************************************** - * - * Multi-line Text Boxes - * - ***************************************************************************** - */ + +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 @@ -69,16 +75,6 @@ EXPORT void wTextClear( bt->changed = FALSE; } -/** - * Add text to a multiline text field. Font is selected as requested. - * Bold is supported if the flags BT_BOLD is set as flags for the entry - * field. For bold, pango text markup is used - * - * - * \param bt IN the text field - * \param text IN text to add - */ - EXPORT void wTextAppend( wText_p bt, const char * text ) @@ -86,7 +82,6 @@ EXPORT void wTextAppend( #ifdef USE_TEXTVIEW GtkTextBuffer * tb; GtkTextIter ti1, ti2; -// PangoFontDescription *pfd; #else static GdkFont * fixedRegularFont = NULL; static GdkFont * fixedBoldFont = NULL; @@ -102,14 +97,6 @@ EXPORT void wTextAppend( if (bt->text == 0) abort(); #ifdef USE_TEXTVIEW tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); - //if ((bt->option&BT_FIXEDFONT)) { - ///* creating PangoFontDescription from string, specified in entry */ - //pfd = pango_font_description_from_string("Monospace"); - ///* setting label's font */ - //gtk_widget_modify_font(GTK_WIDGET(tb), pfd); - ///* freeing PangoFontDescription, cause it has been copied by prev. call */ - //pango_font_description_free(pfd); - //} #else if ((bt->option&BT_FIXEDFONT)) { if (fixedRegularFont==NULL) @@ -251,42 +238,224 @@ EXPORT wBool_t wTextSave( 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 ) { - wPrinterStream_p f; -#ifndef USE_TEXTVIEW - int siz, pos, cnt; -#endif - char * cp; - - f = wPrinterOpen(); - if (f==NULL) { - return FALSE; + 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 ); } -#ifdef USE_TEXTVIEW - cp = gtkGetText( bt ); - wPrinterWrite( f, cp, strlen(cp) ); - free(cp); - -#else - siz = gtk_text_get_length( GTK_TEXT(bt->text) ); - pos = 0; - cnt = BUFSIZ; - while (possiz) - cnt = siz-pos; - cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), pos, pos+cnt ); - if (cp == NULL) - break; - wPrinterWrite( f, cp, cnt ); - free(cp); - pos += cnt; + /* 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); } -#endif - wPrinterClose(f); + g_object_unref (operation); + return TRUE; } @@ -402,21 +571,7 @@ static void textChanged( bt->changed = TRUE; } -/** - * Create a multi line text entry widget. The created widget is - * configured as requested by the BT_* flags. This includes Monospaced - * font for BT_FIXEDFONT, readonly for BT_READONLY and a markup for - * bold when setup via BT_BOLD. - * - * \param parent IN parent window - * \param x,y IN position - * \param helpstr IN label for linking into help system - * \param labelStr IN label - * \param option IN widget options - * \param width, height IN size of widget - * \return handle for new widget - */ - + EXPORT wText_p wTextCreate( wWin_p parent, wPos_t x, @@ -430,7 +585,6 @@ EXPORT wText_p wTextCreate( wText_p bt; #ifdef USE_TEXTVIEW GtkTextBuffer * tb; - PangoFontDescription *pfd; #else GtkRequisition requisition; #endif @@ -453,14 +607,6 @@ EXPORT wText_p wTextCreate( 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); */ - if ((bt->option & BT_FIXEDFONT)) { - /* creating PangoFontDescription from string, specified in entry */ - pfd = pango_font_description_from_string("Monospace"); - /* setting label's font */ - gtk_widget_modify_font(GTK_WIDGET(bt->text), pfd); - /* freeing PangoFontDescription, cause it has been copied by prev. call */ - pango_font_description_free(pfd); - } bt->vscroll = gtk_vscrollbar_new( GTK_TEXT_VIEW(bt->text)->vadjustment ); if (bt->vscroll == 0) abort(); #else diff --git a/app/wlib/gtklib/gtkxpm.c b/app/wlib/gtklib/gtkxpm.c index 022c973..54ce5a6 100644 --- a/app/wlib/gtklib/gtkxpm.c +++ b/app/wlib/gtklib/gtkxpm.c @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #include #include #ifdef HAVE_MALLOC_H @@ -34,7 +34,7 @@ struct xpmColTable { int color; /* color value (rgb) */ - char name[ 5 ]; /* corresponding character representation */ + char name[ 5 ]; /* corresponding character representation */ UT_hash_handle hh; /* makes this structure hashable */ }; @@ -42,34 +42,30 @@ 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; - - GdkPixmap * pixmap; - GdkPixmap * pixmapBackup; - - 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; - }; - + +//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 @@ -78,7 +74,7 @@ struct wDraw_t { * 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. + * \param fileName IN fully qualified filename for the bitmap file. * \return TRUE on success, FALSE on error */ @@ -88,7 +84,7 @@ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) gint x, y; guint32 pixel; FILE * f; - int cc = 0; + int cc = 0; struct xpmColTable *ct, *tmp; int numChars; @@ -106,11 +102,11 @@ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) 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 @@ -119,18 +115,18 @@ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) // 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 @@ -143,15 +139,15 @@ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) } else { if( cc > 0x3f ) { numChars = 2; - } + } } - } - // print color table + } + // 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; yh; y++ ) { @@ -159,17 +155,17 @@ wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName ) for ( x=0; xw; x++ ) { pixel = gdk_image_get_pixel( image, x, y ); HASH_FIND( hh, colTable, &pixel, sizeof(guint32), ct ); - fputs( (ct->name) + (4 - numChars ), f ); + fputs( (ct->name) + (4 - numChars ), f ); } fprintf( f, "\"%s\n", (yh-1)?",":"" ); } // delete the hash and free the content HASH_ITER(hh, colTable, ct, tmp) { - HASH_DEL(colTable,ct); - free(ct); + HASH_DEL(colTable,ct); + free(ct); } - + gdk_image_destroy( image ); fprintf( f, "};\n" ); fclose( f ); diff --git a/app/wlib/gtklib/print.c b/app/wlib/gtklib/print.c new file mode 100644 index 0000000..9f4a4a8 --- /dev/null +++ b/app/wlib/gtklib/print.c @@ -0,0 +1,858 @@ +/** \file print.c + * Printing functions using GTK's print API + */ + +/* 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 +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#include +#include + +#include + +#include "gtkint.h" +#include +#include + +#include "wlib.h" +#include "i18n.h" + +extern wDrawColor wDrawColorWhite; +extern wDrawColor wDrawColorBlack; + +/***************************************************************************** + * + * MACROS + * + */ + +#define PRINT_PORTRAIT (0) +#define PRINT_LANDSCAPE (1) + +#define PPI (72.0) +#define P2I( P ) ((P)/PPI) + +#define CENTERMARK_LENGTH (60) /**< size of cross marking center of circles */ +#define DASH_LENGTH (8.0) /**< length of single dash */ + +#define PAGESETTINGS "xtrkcad.page" /**< filename for page settings */ +#define PRINTSETTINGS "xtrkcad.printer" /**< filename for printer settings */ + +/***************************************************************************** + * + * VARIABLES + * + */ + +static GtkPrintSettings *settings; /**< current printer settings */ +static GtkPageSetup *page_setup; /**< current paper settings */ +static GtkPrinter *selPrinter; /**< printer selected by user */ +static GtkPrintJob *curPrintJob; /**< currently active print job */ +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 double paperWidth; /**< physical paper width */ +static double paperHeight; /**< physical paper height */ +static double tBorder; /**< top margin */ +static double rBorder; /**< right margin */ +static double lBorder; /**< left margin */ +static double bBorder; /**< bottom margin */ + +static long printFormat = PRINT_LANDSCAPE; + +/***************************************************************************** + * + * FUNCTIONS + * + */ + +static void WlibGetPaperSize( void ); + +/** + * Initialize printer und paper selection using the saved settings + * + * \param op IN print operation to initialize. If NULL only the global + * settings are loaded. + */ + +void +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); + +} + +/** + * Save the printer settings. If op is not NULL the settings are retrieved + * from the print operation. Otherwise the state of the globals is saved. + * + * \param op IN printer operation. If NULL the glabal variables are used + */ + +void +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 ); + +} + +/** + * 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 ) +{ + 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 ); +} + +/***************************************************************************** + * + * BASIC PRINTING + * + */ + + +/** + * set the current line type for printing operations + * + * \param lineWidth IN new line width + * \param lineType IN flag for line type (dashed or full) + * \param opts IN unused + * \return + */ + + +static void setLineType( + 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 ); +} + +/** + * set the color for the following print operations + * + * \param color IN the new color + * \return + */ + +static void psSetColor( + wDrawColor color ) +{ + cairo_t *cr = psPrint_d.printContext; + GdkColor* const gcolor = gtkGetColor(color, TRUE); + + cairo_set_source_rgb(cr, gcolor->red / 65535.0, + gcolor->green / 65535.0, + gcolor->blue / 65535.0); +} + +/** + * Print a straight line + * + * \param x0, y0 IN starting point in pixels + * \param x1, y1 IN ending point in pixels + * \param width line width + * \param lineType + * \param color color + * \param opts ? + */ + +void psPrintLine( + 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 ); +} + +/** + * Print an arc around a specified center + * + * \param x0, y0 IN center of arc + * \param r IN radius + * \param angle0, angle1 IN start and end angle + * \param drawCenter draw marking for center + * \param width line width + * \param lineType + * \param color color + * \param 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 ) +{ + 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 ); +} + +/** + * Print a filled rectangle + * + * \param x0, y0 IN top left corner + * \param x1, y1 IN bottom right corner + * \param color IN fill color + * \param opts IN options + * \return + */ + +void psPrintFillRectangle( + 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; + + if (color == wDrawColorWhite) + return; + if (opts&wDrawOptTemp) + return; + psSetColor(color); + + cairo_rectangle( cr, x0, y0, width, height ); + + cairo_fill( cr ); +} + +/** + * Print a filled polygon + * + * \param p IN a list of x and y coordinates + * \param cnt IN the number of points + * \param color IN fill color + * \param opts IN options + * \return + */ + +void psPrintFillPolygon( + wPos_t p[][2], + int cnt, + wDrawColor color, + wDrawOpts opts ) +{ + int inx; + cairo_t *cr = psPrint_d.printContext; + + if (color == wDrawColorWhite) + return; + if (opts&wDrawOptTemp) + return; + + psSetColor(color); + + cairo_move_to( cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ] ); + for (inx=0; inxgtkwin)); + + // 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; +} + +/** + * Callback for job finished event. Destroys the cairo context. + * + * \param job IN unused + * \param data IN unused + * \param err IN if != NULL, an error dialog ist displayed + * \return + */ + +void +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); + } +} + +/** + * Finish the print operation + * \return + */ + +void wPrintDocEnd( void ) +{ + cairo_surface_finish( psPrint_d.curPrintSurface ); + + gtk_print_job_send( curPrintJob, + doPrintJobFinished, + NULL, + NULL ); + +// wWinShow( printAbortW, FALSE ); +} + + +wBool_t wPrintQuit( void ) +{ + return FALSE; +} + + +wBool_t wPrintInit( void ) +{ + return TRUE; +} diff --git a/app/wlib/gtklib/psprint.c b/app/wlib/gtklib/psprint.c deleted file mode 100644 index 8e7cbe6..0000000 --- a/app/wlib/gtklib/psprint.c +++ /dev/null @@ -1,1599 +0,0 @@ -/* - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/psprint.c,v 1.5 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 -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_MALLOC_H -#include -#endif -#include -#include - -#include - -#include - -#include "gtkint.h" -#include "wlib.h" -/* #include "dynarr.h" */ -#include "i18n.h" - -#ifndef TRUE -#define TRUE (1) -#define FALSE (0) -#endif - -#define MM(m) ((m)/25.4) - -/* char * gtkFontTranslate( wFont_p ); */ -extern wDrawColor wDrawColorWhite; -extern wDrawColor wDrawColorBlack; - -/***************************************************************************** - * - * MACROS - * - */ - -#define PRINT_COMMAND (0) -#define PRINT_FILE (1) - -#define PRINT_PORTRAIT (0) -#define PRINT_LANDSCAPE (1) - -/* #define MAXIMUM(a,b) ((a)>(b) ? (a) : (b)) */ -#define min(a,b) ((a)<(b) ? (a) : (b)) -#define PPI (72.0) -#define P2I( P ) ((P)/PPI) - -#define DPI (1440.0) -#define D2I( D ) (((double)(D))/DPI) - -#define CENTERMARK_LENGTH 60 - -#define WFONT "WFONT" -#define WPRINTER "WPRINTER" -#define WMARGIN "WMARGIN" -#define WMARGINMAP "WMARGINMAP" -#define WPRINTFONT "WPRINTFONT" - -/***************************************************************************** - * - * VARIABLES - * - */ - -extern struct wDraw_t psPrint_d; - -/* -typedef struct { - wIndex_t cmdOrFile; - FILE * f; - } wPrinterStream_t; -typedef wPrinterStream_t * wPrinterStream_p; -*/ -static wBool_t printContinue; -static wWin_p printAbortW; -static wMessage_p printAbortT; -static wMessage_p printAbortM; - -static wWin_p printFileW; -static wWin_p newFontAliasW; -static wWin_p printSetupW; -static wList_p optPrinterB; -static wList_p optPaperSizeB; -static wMessage_p newFontAliasXFntB; -static wList_p optMarginB; -static wButton_p optMarginDelB; -static wFloat_p optTopMargin; -static wFloat_p optBottomMargin; -static wFloat_p optRightMargin; -static wFloat_p optLeftMargin; -static wChoice_p optFormat; -static wList_p optXFontL; -static wString_p optPSFontS; -static wFloat_p optFontSizeFactor; -static long optXFontX; -static const char * optXFont; -static char optPSFont[200]; - -#ifdef LATER -static char addPrinterName[80]; -static char addPrinterCommand[80]; -static wWin_p addPrinterW; -static wString_p addPrinterN; -static wString_p addPrinterC; -static char addMarginName[80]; -static wWin_p addMarginW; -static wString_p addMarginN; -#endif - -static FILE * psFile; -static wPrinterStream_p psFileStream; -static wIndex_t pageCount; -static wIndex_t totalPageCount; - -static long newPPrinter; -static long newPPaper; -static wPrintSetupCallBack_p printSetupCallBack; - -static double tBorder; -static double rBorder; -static double lBorder; -static double bBorder; - -static long printFormat = PRINT_LANDSCAPE; -static double currLineWidth = 0; - -static long curPrinter = 0; -static char *sPrintFileName; -static long curMargin = 0; - -static const char * prefName; -static const char * prefPaper; -static const char * prefMargin; -static const char * prefFormat; - -static char newMarginName[256]; - -typedef enum { PS_LT_SOLID, PS_LT_DASH } PS_LT_E; -static PS_LT_E currentLT = PS_LT_SOLID; - -static double fontSizeFactor = 1.0; - -static struct { - const char * name; - double w, h; - } papers[] = { - { "Letter", 8.5, 11.0 }, - { "Legal", 8.5, 14.0 }, - { "Tabloid", 11.0, 17.0 }, - { "Ledger", 17.0, 11.0 }, - { "Fan Fold", 13.2, 11.0 }, - { "Statement", 5.5, 8.5 }, - { "Executive", 7.5, 10.0 }, - { "Folio", 8.27, 13 }, - { "A0", MM(841), MM(1189) }, - { "A1", MM(594), MM(841) }, - { "A2", MM(420), MM(594) }, - { "A3", MM(297), MM(420) }, - { "A4", MM(210), MM(297) }, - { "A5", MM(148), MM(210) }, - { "A6", MM(105), MM(148) }, - { "A7", MM(74), MM(105) }, - { "A8", MM(52), MM(74) }, - { "A9", MM(37), MM(52) }, - { "A10", MM(26), MM(37) }, - { "B0", MM(1000), MM(1414) }, - { "B1", MM(707), MM(1000) }, - { "B2", MM(500), MM(707) }, - { "B3", MM(353), MM(500) }, - { "B4", MM(250), MM(353) }, - { "B5", MM(176), MM(250) }, - { "B6", MM(125), MM(176) }, - { "B7", MM(88), MM(125) }, - { "B8", MM(62), MM(88) }, - { "B9", MM(44), MM(62) }, - { "B10", MM(31), MM(44) }, - { "C0", MM(917), MM(1297) }, - { "C1", MM(648), MM(917) }, - { "C2", MM(458), MM(648) }, - { "C3", MM(324), MM(458) }, - { "C4", MM(229), MM(324) }, - { "C5", MM(162), MM(229) }, - { "C6", MM(114), MM(162) }, - { "C7", MM(81), MM(114) }, - { "DL", MM(110), MM(220) }, - { NULL } }; -wIndex_t curPaper = 0; - -typedef struct { - const char * name; - const char * cmd; - wIndex_t class; - } printers_t; -dynArr_t printers_da; -#define printers(N) DYNARR_N(printers_t,printers_da,N) - -typedef struct { - const char * name; - double t, b, r, l; - } margins_t; -dynArr_t margins_da; -#define margins(N) DYNARR_N(margins_t,margins_da,N) - -static void printFileNameSel( void * junk ); -static void printInit( void ); - -/* - * Stuff related to determining the list of fonts used in the - * Postscript file. A simple linked-list is used to implement a - * stack. Everything is specialized to this application. - */ - -/** - * Nodes of the \a fontsUsed list. - */ -struct list_node { - struct list_node *next; - char *data; -} ; - -/** - * Pointer to the \a fontsUsed list. - */ -static struct list_node *fontsUsed = NULL; - - -/** - * Pushes its argument on to the \a fontsUsed list. - * \param item - IN pointer to a string to put on the list - * \return nothing - */ -void fontsUsedPush( const char *item) { - struct list_node *newitem; - newitem = malloc(sizeof(struct list_node)); - if (newitem == NULL) exit (2); - newitem->next=fontsUsed; - newitem->data = strdup(item); - if (newitem->data == NULL) exit(3); - fontsUsed=newitem; -} - -/** - * Pops the top node from the \a fontsUsed list. - * Note that a pointer to the complete node is returned. The - * caller is responsible for freeing both the data and the list - * node when it is finished using them. - * \return pointer to the list node. - */ -struct list_node * fontsUsedPop() { - struct list_node *item; - if (fontsUsed == NULL) return NULL; - item = fontsUsed; - fontsUsed = item->next; - return item ; -} - -/** - * \a fontsUsed list (re-)initializer. - */ -void fontsUsedInit() { - struct list_node *p; - while ((p=fontsUsedPop()) != NULL) { - free(p->data); - free(p); - } - fontsUsed=NULL; -} - -/** - * Checks if \a s is already in \a fontsUsed list. - * \param s - IN string to be checked. - * \return TRUE if found, FALSE if not. - */ -int fontsUsedContains( const char *s ) { - struct list_node *ptr; - ptr = fontsUsed; - while ( ptr != NULL ) { - if ( strcmp(s, ptr->data) == 0 ) return TRUE; - ptr= ptr->next; - } - return FALSE ; -} - -/** - * Adds the \a fontName to the list of fonts being used. - * Only if it is not already in the list. - * - * This function should be called anywhere the string "findfont" - * is being emitted to the Postscript file. - * \param \a fontName IN - string contaning the name to add. - */ -void addFontName( const char * fontName){ - if (fontsUsedContains(fontName)) return; - fontsUsedPush(fontName); -} - -/* ***************************************** */ - -/** - * This function does a normal printf but uses the default C - * locale as decimal separator. - * - * \param template IN printf-like format string - * ... IN parameters according to format string - * \return describe the return value - */ - -static void -psPrintf (FILE *ps, const char *template, ...) -{ - va_list ap; - - setlocale( LC_NUMERIC, "C" ); - - va_start( ap, template ); - vfprintf( ps, template, ap ); - va_end( ap ); - - setlocale( LC_NUMERIC, "" ); -} - -void wPrintSetup( wPrintSetupCallBack_p callback ) -{ - printInit(); - newPPrinter = curPrinter; - newPPaper = curPaper; - printSetupCallBack = callback; - wListSetIndex( optPrinterB, newPPrinter ); - wListSetIndex( optPaperSizeB, newPPaper ); - wWinShow( printSetupW, TRUE ); -} - -static void pSetupOk( void ) -{ - curPrinter = newPPrinter; - curPaper = newPPaper; - wWinShow( printSetupW, FALSE ); - wPrefSetString( "printer", "name", printers(curPrinter).name ); - wPrefSetString( "printer", "paper", papers[curPaper].name ); - if ( curMargin < margins_da.cnt ) - wPrefSetString( "printer", "margin", margins(curMargin).name ); - wPrefSetString( "printer", "format", (printFormat==PRINT_LANDSCAPE?"landscape":"portrait") ); - if (printSetupCallBack) - printSetupCallBack( TRUE ); - wPrefSetFloat( WPRINTFONT, "factor", fontSizeFactor ); -} - -static void pSetupCancel( void ) -{ - wWinShow( printSetupW, FALSE ); - if (printSetupCallBack) - printSetupCallBack( FALSE ); -} - - -/***************************************************************************** - * - * PRINTER LIST MANAGEMENT - * - */ - - -static wBool_t wPrintNewPrinter( - const char * name ) -{ - char * cp; - const char *cpEqual; - - printInit(); - DYNARR_APPEND( printers_t, printers_da, 10 ); - cpEqual = strchr( name, '=' ); - if (cpEqual == NULL) { - printers(printers_da.cnt-1).cmd = strdup( "lpr -P%s" ); - printers(printers_da.cnt-1).name = name; - } else { - cp = strdup( name ); - cp[cpEqual-name] = 0; - printers(printers_da.cnt-1).name = cp; - printers(printers_da.cnt-1).cmd = cp+(cpEqual-name+1); - name = cp; - } - if (optPrinterB) { - wListAddValue( optPrinterB, printers(printers_da.cnt-1).name, NULL, (void*)(intptr_t)(printers_da.cnt-1) ); - if ( prefName && strcasecmp( prefName, name ) == 0 ) { - curPrinter = printers_da.cnt-1; - wListSetIndex( optPrinterB, curPrinter ); - } - } - return TRUE; -} - - -static void doMarginSel( - wIndex_t inx, - const char * name, - wIndex_t op, - void * listData, - void * itemData ) -{ - margins_t * p; - static margins_t dummy = { "", 0, 0, 0, 0 }; - if ( inx < 0 ) { - for ( inx=0,p=&margins(0); inx= margins_da.cnt ) { - strncpy( newMarginName, name, sizeof newMarginName ); - p = &dummy; - } - } else { - p = &margins(inx); - } - curMargin = inx; - tBorder = p->t; - bBorder = p->b; - rBorder = p->r; - lBorder = p->l; - wFloatSetValue( optTopMargin, tBorder ); - wFloatSetValue( optBottomMargin, bBorder ); - wFloatSetValue( optRightMargin, rBorder ); - wFloatSetValue( optLeftMargin, lBorder ); -} - -static wIndex_t wPrintNewMargin( - const char * name, - const char * value ) -{ - margins_t * m; - int rc; - DYNARR_APPEND( margins_t, margins_da, 10 ); - m = &margins(margins_da.cnt-1); - - setlocale( LC_NUMERIC, "C" ); - if ((rc=sscanf( value, "%lf %lf %lf %lf", &m->t, &m->b, &m->r, &m->l ))!=4) { - margins_da.cnt--; - setlocale( LC_NUMERIC, "" ); - return FALSE; - } - setlocale( LC_NUMERIC, "" ); - - m->name = strdup( name ); - if (optMarginB) - wListAddValue( optMarginB, name, NULL, NULL ); - if ( prefMargin && strcasecmp( prefMargin, name ) == 0 ) { - curMargin = margins_da.cnt-1; - wListSetIndex( optMarginB, curMargin ); - tBorder = m->t; - bBorder = m->b; - rBorder = m->r; - lBorder = m->l; - wFloatSetValue( optTopMargin, tBorder ); - wFloatSetValue( optBottomMargin, bBorder ); - wFloatSetValue( optRightMargin, rBorder ); - wFloatSetValue( optLeftMargin, lBorder ); - } - return TRUE; -} - - -static void doChangeMargin( void ) -{ - static char marginValue[256]; - margins_t * m; - sprintf( marginValue, "%0.3f %0.3f %0.3f %0.3f", tBorder, bBorder, rBorder, lBorder ); - if ( curMargin >= margins_da.cnt ) { - DYNARR_APPEND( margins_t, margins_da, 10 ); - curMargin = margins_da.cnt-1; - margins(curMargin).name = strdup( newMarginName ); - wListAddValue( optMarginB, margins(curMargin).name, NULL, NULL ); - wListSetIndex( optMarginB, curMargin ); - } - m = &margins(curMargin); - m->t = tBorder; - m->b = bBorder; - m->r = rBorder; - m->l = lBorder; - wPrefSetString( WMARGIN, m->name, marginValue ); -} - - -static void doMarginDelete( void ) -{ - int inx; - if ( curMargin >= margins_da.cnt || margins_da.cnt <= 1 || curMargin == 0 ) - return; - wPrefSetString( WMARGIN, margins(curMargin).name, "" ); - free( (char*)margins(curMargin).name ); - for ( inx=curMargin+1; inx= margins_da.cnt ) - curMargin--; - doMarginSel( curMargin, margins(curMargin).name, 0, NULL, NULL ); -} - - -static const char * curPsFont = NULL; -static const char * curXFont = NULL; - - -static void newFontAliasSel( const char * alias, void * data ) -{ - wPrefSetString( WFONT, curXFont, alias ); - curPsFont = wPrefGetString( WFONT, curXFont ); - wWinShow( newFontAliasW, FALSE ); - wListAddValue( optXFontL, curXFont, NULL, NULL ); -} - - -static const char * findPSFont( wFont_p fp ) -{ - const char *f; - static const char * oldXFont = NULL; - - curXFont = gtkFontTranslate(fp); - if (curXFont != NULL && - oldXFont != NULL && - strcasecmp(oldXFont, curXFont) == 0 && - curPsFont != NULL ) - return curPsFont; - if (curXFont == NULL) - return "Times-Roman"; - oldXFont = curXFont; - printInit(); - f = wPrefGetString( WFONT, curXFont ); - if (f) - return curPsFont = f; - wMessageSetValue( newFontAliasXFntB, curXFont ); - wWinShow( newFontAliasW, TRUE ); - return curPsFont; -} - -/***************************************************************************** - * - * BASIC PRINTING - * - */ - -static void setLineType( - double lineWidth, - wDrawLineType_e lineType, - wDrawOpts opts ) -{ - PS_LT_E want; - - if (lineWidth < 0.0) { - lineWidth = P2I(-lineWidth)*2.0; - } - - if (lineWidth != currLineWidth) { - currLineWidth = lineWidth; - psPrintf( psFile, "%0.3f setlinewidth\n", currLineWidth / (PPI*10) ); - } - - if (lineType == wDrawLineDash) - want = PS_LT_DASH; - else - want = PS_LT_SOLID; - if (want != currentLT) { - currentLT = want; - switch (want) { - case PS_LT_DASH: - psPrintf( psFile, "[%0.3f %0.3f] 0 setdash\n", P2I(2), P2I(2) ); - break; - case PS_LT_SOLID: - psPrintf( psFile, "[] 0 setdash\n" ); - break; - } - } -} - - -void psSetColor( - wDrawColor color ) -{ - static long currColor = 0; - long newColor; - - newColor = wDrawGetRGB( color ); - if (newColor != currColor) { - psPrintf( psFile, "%0.3f %0.3f %0.3f setrgbcolor\n", - (float)((newColor>>16)&0xFF)/256.0, - (float)((newColor>>8)&0xFF)/256.0, - (float)((newColor)&0xFF)/256.0 ); - currColor = newColor; - } -} - - -void psPrintLine( - 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 ); - psPrintf(psFile, - "%0.3f %0.3f moveto %0.3f %0.3f lineto closepath stroke\n", - D2I(x0), D2I(y0), D2I(x1), D2I(y1) ); -} - -/** - * Print an arc around a specified center - * - * \param x0, y0 IN center of arc - * \param r IN radius - * \param angle0, angle1 IN start and end angle - * \param drawCenter draw marking for center - * \param width line width - * \param lineType - * \param color color - * \param 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 ) -{ - 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; - psPrintf(psFile, - "newpath %0.3f %0.3f %0.3f %0.3f %0.3f arc stroke\n", - D2I(x0), D2I(y0), D2I(r), angle1, angle0 ); - - if( drawCenter ) { - psPrintf(psFile, - "%0.3f %0.3f moveto %0.3f %0.3f lineto closepath stroke\n", - D2I(x0 - CENTERMARK_LENGTH / 2), D2I(y0), D2I(x0 + CENTERMARK_LENGTH / 2), D2I(y0) ); - psPrintf(psFile, - "%0.3f %0.3f moveto %0.3f %0.3f lineto closepath stroke\n", - D2I(x0), D2I(y0 - CENTERMARK_LENGTH / 2), D2I(x0), D2I(y0 + CENTERMARK_LENGTH / 2) ); - - } -} - - -void psPrintFillRectangle( - wPos_t x0, wPos_t y0, - wPos_t x1, wPos_t y1, - wDrawColor color, - wDrawOpts opts ) -{ - if (color == wDrawColorWhite) - return; - if (opts&wDrawOptTemp) - return; - psSetColor(color); - psPrintf(psFile, - "%0.3f %0.3f moveto %0.3f %0.3f lineto closepath fill\n", - D2I(x0), D2I(y0), D2I(x1), D2I(y1) ); -} - - -void psPrintFillPolygon( - wPos_t p[][2], - int cnt, - wDrawColor color, - wDrawOpts opts ) -{ - int inx; - if (color == wDrawColorWhite) - return; - if (opts&wDrawOptTemp) - return; - psSetColor(color); - psPrintf( psFile, "%0.3f %0.3f moveto ", D2I(p[0][0]), D2I(p[0][1]) ); - for (inx=0; inx0?totalPageCount:pageCount) ); - - if (printFormat == PRINT_LANDSCAPE) { - psPrintf(psFile, "%0.3f %0.3f translate -90 rotate\n", lBorder*PPI, (papers[curPaper].h-tBorder)*PPI); - } else { - psPrintf(psFile, "%0.3f %0.3f translate 0 rotate\n", lBorder*PPI, bBorder*PPI); - } - - psPrintf( psFile, "%0.1f %0.1f scale\n", PPI, PPI ); - - psPrintf( psFile, "/Times-Bold findfont %0.3f scalefont setfont\n", - P2I(16) ); - addFontName("Times-Bold"); - sprintf( tmp, _("Page %d"), pageCount ); - wMessageSetValue( printAbortM, tmp ); - wFlush(); - - currLineWidth = 0; - return &psPrint_d; -} - -/** - * End of page - * - * \param p IN ignored - * \return always printContinue - */ - - -wBool_t wPrintPageEnd( wDraw_p p ) -{ - psPrintf( psFile, - "grestore\n" \ - "restore\n" \ - "showpage\n"\ - "%%%%EndPage\n"); - - return printContinue; -} - -/***************************************************************************** - * - * PRINT START/END - * - */ - -/** - * Allow the user to enter a new file name and location for the file. - * Thanks to Andrew Krause's great book Foundations of GTK+ Development - * for this code snippet. - * - * \param junk IN ignored - */ - -static void printFileNameSel( void * junk ) -{ - GtkWidget *dialog; - gchar *filename; - gint result; - - dialog = gtk_file_chooser_dialog_new (_("Print to file ..."), (GtkWindow *)printSetupW->gtkwin, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - if (result == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER ( dialog )); - if( filename ) { - sPrintFileName = malloc( strlen( filename ) + 1 ); - if( sPrintFileName ) { - strcpy( sPrintFileName, filename ); - } - else { - fputs( "Insufficient memory for printing to file\n", stderr ); - abort(); - } - g_free( filename ); - } - } - - gtk_widget_destroy (dialog); -} - - -/* - * open the printer output stream. In case print to file is selected, the filename for - * the print out is fetched from the user and the file opened. - * - * \return the printer stream - */ - -wPrinterStream_p wPrinterOpen( void ) -{ - char * fn; - char sPrintCmdName[80]; - char tmp[80+8]; - FILE * f; - wIndex_t cmdOrFile; - wPrinterStream_p p; - - printInit(); - pageCount = 0; - f = NULL; - curPsFont = NULL; - if (curPrinter == 0 ) { - - printFileNameSel( NULL ); - - // did the user cancel the file dialog? If yes, cancel operation - if( !sPrintFileName ) { - return( NULL ); - } - if ( sPrintFileName[0] == '\0' ) { - wNoticeEx( NT_ERROR, _("No file name specified"), _("Ok"), NULL ); - return NULL; - } - if ( access(sPrintFileName, F_OK ) == 0 ) { - sprintf( tmp, _("%s exists"), sPrintFileName ); - if (!wNoticeEx( NT_INFORMATION, tmp, _("Overwrite"), _("Cancel") )) - return NULL; - } - f = fopen( sPrintFileName, "w" ); - if (f == NULL) { - strcat( sPrintFileName, _(": cannot open") ); - wNoticeEx( NT_ERROR, sPrintFileName, _("Ok"), NULL ); - return NULL; - } - fn = sPrintFileName; - cmdOrFile = PRINT_FILE; - } else { - sprintf( sPrintCmdName, printers(curPrinter).cmd, printers(curPrinter).name ); - f = popen( sPrintCmdName, "w" ); - fn = sPrintCmdName; - cmdOrFile = PRINT_COMMAND; - } - if (f == NULL) { - strcat( sPrintFileName, _(": cannot open") ); - wNoticeEx( NT_ERROR, sPrintFileName, _("Ok"), NULL ); - return NULL; - } - p = (wPrinterStream_p)malloc( sizeof *p ); - p->f = f; - p->cmdOrFile = cmdOrFile; - return p; -} - - -void wPrinterWrite( wPrinterStream_p p, char * buff, int siz ) -{ - fwrite( buff, 1, siz, p->f ); -} - -void wPrinterClose( wPrinterStream_p p ) -{ - if (p->cmdOrFile == PRINT_FILE) - fclose( p->f ); - else - pclose( p->f ); - - // free the filename again - if( sPrintFileName ) { - free( sPrintFileName ); - sPrintFileName = NULL; - } -} - -/** - * Start a new Postscript document - * - * Opens the output file and emits the Adobe DSC Prolog comments, - * etc. Note that the 3.0 in "PS-Adobe-3.0" refers to the - * version of the Document Structuring Conventions Specification, - * not to the Postscript language level. - * - * \param title IN title of document ( name of layout ) - * \param fTotalPageCount IN number of pages to print - * \param copiesP OUT ??? - * \return TRUE if successful - */ - -wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP ) -{ - char tmp[80]; - pageCount = 0; - totalPageCount = fTotalPageCount; - psFile = NULL; - psFileStream = wPrinterOpen(); - if (psFileStream == NULL) - return FALSE; - psFile = psFileStream->f; - - /* Initialize the list of fonts used */ - fontsUsedInit(); /* in case a document had been - produced earlier */ - - psPrintf( psFile, - "%%!PS-Adobe-3.0\n\ -%%%%DocumentFonts: (atend)\n\ -%%%%Title: %s\n\ -%%%%Creator: XTrackCAD\n\ -%%%%Pages: (atend)\n\ -%%%%BoundingBox: %ld %ld %ld %ld\n\ -%%%%EndComments\n\n\ -%%%%Prolog\n\ -/mp_stm usertime def\n\ -/mp_pgc statusdict begin pagecount end def\n\ -statusdict begin /jobname () def end\n\ -%%%%EndProlog\n", \ - title, - (long)floor(margins(curMargin).l*72), - (long)floor(margins(curMargin).b*72), - (long)floor((papers[curPaper].w-margins(curMargin).r)*72), - (long)floor((papers[curPaper].h-margins(curMargin).t)*72) ); - - printContinue = TRUE; - sprintf( tmp, ("Now printing %s"), title ); - wMessageSetValue( printAbortT, tmp ); - wMessageSetValue( printAbortM, _("Page 1") ); - pageCount = 0; - wWinShow( printAbortW, TRUE ); - if (copiesP) - *copiesP = 1; - return TRUE; -} - -/** - * Outputs the Adobe Document Structure Comments. - * These are needed at the - * end of a Postscript document destined for modern (2012) print - * spoolers. E.g. CUPS - */ - -void wPrintDocEnd( void ) -{ - struct list_node *p; - int i; - if (psFile == NULL) - return; - - psPrintf( psFile, - "%%%%Trailer\n%%%%Pages: %d\n", - pageCount ); - - /* Postscript lines are <255 chars so print fonts list 4 - per line - */ - psPrintf( psFile, "%%%%DocumentFonts: " ); - p = fontsUsed; - i = 0; - while ((p=fontsUsedPop()) != NULL) { - if ((i % 4) == 0 ) psPrintf( psFile, "\n%%%%+ "); - psPrintf( psFile, " %s", p->data); - free(p->data); - free(p); - i++; - } - psPrintf( psFile, "\n"); - - psPrintf( psFile, "%%%%EOF\n"); - /* Reset the fonts list to empty for the next document. - */ - fontsUsedInit(); - - wPrinterClose( psFileStream ); - wWinShow( printAbortW, FALSE ); -} - - -wBool_t wPrintQuit( void ) -{ - return FALSE; -} - - -static void pLine( double x0, double y0, double x1, double y1 ) -{ - psPrintf( psFile, "%0.3f %0.3f moveto %0.3f %0.3f lineto stroke\n", - x0, y0, x1, y1 ); -} - -/** - * Generate a test page that helps setting up printer margins. - */ - -static void pTestPage( void ) -{ - double w, h; - long oldPrinter; - int i, j, k, run; - double x0, x1, y0, y1; - const char * psFont, * xFont; - long curMargin0; - - oldPrinter = curPrinter; - curPrinter = newPPrinter; - curMargin0 = curMargin; - curMargin = 0; - wPrintDocStart( _("Printer Margin Test Page"), 1, NULL ); - wPrintPageStart(); - curMargin = curMargin0; - w = papers[curPaper].w; - h = papers[curPaper].h; - if ( psFile == NULL ) - return; - -#define MAXIMUM (100) - - psPrintf( psFile, "/Times-Roman findfont 0.06 scalefont setfont\n" ); - addFontName("Times-Roman"); - for ( i=5; i<=MAXIMUM; i+=5 ) { - x0 = ((double)i)/100; - pLine( 0.5, x0, w-0.5, x0 ); - pLine( 0.5, h-x0, w-0.5, h-x0 ); - pLine( x0, 0.5, x0, h-0.5 ); - pLine( w-x0, 0.5, w-x0, h-0.5 ); - - psPrintf( psFile, "%0.3f %0.3f moveto (%0.2f) show\n", - 1.625 + x0*5 - 0.05, 0.2+MAXIMUM/100.0, x0 ); - pLine( 1.625 + x0*5, (0.2+MAXIMUM/100.0), 1.625 + x0*5, x0 ); - psPrintf( psFile, "%0.3f %0.3f moveto (%0.2f) show\n", - 1.625 + x0*5 - 0.05, h-(0.2+MAXIMUM/100.0)-0.05, x0 ); - pLine( 1.625 + x0*5, h-(0.2+MAXIMUM/100.0), 1.625 + x0*5, h-x0 ); - - psPrintf( psFile, "%0.3f %0.3f moveto (%0.2f) show\n", - (0.2+MAXIMUM/100.0), 1.625 + x0*5-0.020, x0 ); - pLine( (0.2+MAXIMUM/100.0), 1.625 + x0*5, x0, 1.625 + x0*5 ); - psPrintf( psFile, "%0.3f %0.3f moveto (%0.2f) show\n", - w-(0.2+MAXIMUM/100.0)-0.10, 1.625 + x0*5-0.020, x0 ); - pLine( w-(0.2+MAXIMUM/100.0), 1.625 + x0*5, w-x0, 1.625 + x0*5 ); - } - - psPrintf( psFile, "/Times-Bold findfont 0.20 scalefont setfont\n" ); - addFontName("Times-Bold"); - psPrintf( psFile, "%0.3f %0.3f moveto (%s) show\n", 2.0, h-2.0, "Printer Margin Setup" ); - psPrintf( psFile, "/Times-Roman findfont 0.12 scalefont setfont\n" ); - addFontName("Times-Roman"); - psPrintf( psFile, "%0.3f %0.3f moveto (%s) show\n", 2.0, h-2.15, - "Enter the position of the first visible line for each margin on the Printer Setup dialog"); - if ( curMargin < margins_da.cnt ) - psPrintf( psFile, "%0.3f %0.3f moveto (" - "Current margins for the %s printer are: Top: %0.3f, Left: %0.3f, Right: %0.3f, Bottom: %0.3f" - ") show\n", 2.0, h-2.30, - margins(curMargin).name, margins(curMargin).t, margins(curMargin).l, margins(curMargin).r, margins(curMargin).b ); - - - psPrintf( psFile, "/Times-Bold findfont 0.20 scalefont setfont\n" ); - addFontName("Times-Bold"); - psPrintf( psFile, "%0.3f %0.3f moveto (%s) show\n", 2.0, h-3.0, "Font Map" ); - for (i=j=0; 0.2*j < h-5.0 && (psFont = wPrefGetSectionItem( WFONT, &i, &xFont )) != NULL; j++ ) { - if ( psFont[0] == '\0' ) continue; - psPrintf( psFile, "/Times-Roman findfont 0.12 scalefont setfont\n" ); - addFontName("Times-Roman"); - psPrintf( psFile, "%0.3f %0.3f moveto (%s -> %s) show\n", 2.0, h-3.15-0.15*j, xFont, psFont ); - psPrintf( psFile, "/%s findfont 0.12 scalefont setfont\n", psFont ); - addFontName(psFont); - psPrintf( psFile, "%0.3f %0.3f moveto (%s) show\n", 5.5, h-3.15-0.15*j, "ABCD wxyz 0123 -+$!" ); - } - x0 = 0.5; - run = TRUE; - i = 0; - while (run) { - x1 = x0 + 0.25; - if (x1 >= w-0.5) { - x1 = w-0.5; - run = FALSE; - } - for ( j = 1; j<5; j++ ) { - y0 = ((double)(i+j))/100; - for (k=0; k= 25) - i = 0; - } - - y0 = 0.5; - run = TRUE; - i = 0; - while (run) { - y1 = y0 + 0.25; - if (y1 >= h-0.5) { - y1 = h-0.5; - run = FALSE; - } - for ( j = 1; j<5; j++ ) { - x0 = ((double)(i+j))/100; - for (k=0; k= 25) - i = 0; - } - - /* psPrintf( psFile, "showpage\n"); */ - wPrintPageEnd(NULL); - wPrintDocEnd(); - curPrinter = oldPrinter; -} - - -#ifdef LATER -static void newPrinter( void * context ) -{ - wStringSetValue( addPrinterN, "" ); - wStringSetValue( addPrinterC, "" ); - addPrinterName[0] = 0; - addPrinterCommand[0] = 0; - wWinShow( addPrinterW, TRUE ); -} - - -static void addPrinterOk( const char * str, void * context ) -{ - char tmp[80]; - if (strlen(addPrinterName) == 0 || strlen(addPrinterCommand) == 0) { - wNotice( _("Enter both printer name and command"), _("Ok"), NULL ); - return; - } - if (printerDefine) - printerDefine( addPrinterName, addPrinterCommand ); - else - wNotice( _("Can not save New Printer definition"), _("Ok"), NULL ); - sprintf( tmp, "%s=%s", addPrinterName, addPrinterCommand ); - wPrintNewPrinter( tmp ); -} - - -static void newMargin( void * context ) -{ - wStringSetValue( addMarginN, "" ); - addMarginName[0] = 0; - wWinShow( addMarginW, TRUE ); - gtkSetReadonly((wControl_p)optTopMargin,FALSE); - gtkSetReadonly((wControl_p)optBottomMargin,FALSE); - gtkSetReadonly((wControl_p)optLeftMargin,FALSE); - gtkSetReadonly((wControl_p)optRightMargin,FALSE); -} - - -static void addMarginOk( const char * str, void * context ) -{ - margins_t * m; - if (strlen(addMarginName) == 0) { - wNotice( _("Enter printer name"), _("Ok"), NULL ); - return; - } - if (marginDefine) - marginDefine( addMarginName, tBorder, bBorder, rBorder, lBorder ); - else - wNotice( _("Can not save New Margin definition"), _("Ok"), NULL ); - DYNARR_APPEND( margins_t, margins_da, 10 ); - m = &margins(margins_da.cnt-1); - m->name = strdup( addMarginName ); - m->t = tBorder; - m->b = bBorder; - m->r = rBorder; - m->l = lBorder; - wListAddValue( optMarginB, addMarginName, NULL, NULL ); - gtkSetReadonly((wControl_p)optTopMargin,TRUE); - gtkSetReadonly((wControl_p)optBottomMargin,TRUE); - gtkSetReadonly((wControl_p)optLeftMargin,TRUE); - gtkSetReadonly((wControl_p)optRightMargin,TRUE); -} -#endif - - -static wLines_t lines[] = { - { 1, 25, 11, 95, 11 }, - { 1, 95, 11, 95, 111 }, - { 1, 95, 111, 25, 111 }, - { 1, 25, 111, 25, 11 }}; -#ifdef LATER - { 1, 97, 10, 125, 10 }, - { 1, 160, 10, 177, 10 }, - { 1, 97, 10, 97, 50 }, - { 1, 97, 67, 97, 110 }, - { 1, 177, 10, 177, 50 }, - { 1, 177, 67, 177, 110 }, - { 1, 97, 110, 125, 110 }, - { 1, 160, 110, 177, 110 } }; -#endif - -static const char * printFmtLabels[] = { N_("Portrait"), N_("Landscape"), NULL }; - -static struct { - const char * xfontname, * psfontname; - } fontmap[] = { - { "times-medium-r", "Times-Roman" }, - { "times-medium-i", "Times-Italic" }, - { "times-bold-r", "Times-Bold" }, - { "times-bold-i", "Times-BoldItalic" }, - { "helvetica-medium-r", "Helvetica" }, - { "helvetica-medium-o", "Helvetica-Oblique" }, - { "helvetica-bold-r", "Helvetica-Bold" }, - { "helvetica-bold-o", "Helvetica-BoldOblique" }, - { "courier-medium-r", "Courier" }, - { "courier-medium-o", "Courier-Oblique" }, - { "courier-medium-i", "Courier-Oblique" }, - { "courier-bold-r", "Courier-Bold" }, - { "courier-bold-o", "Courier-BoldOblique" }, - { "courier-bold-i", "Courier-BoldOblique" }, - { "avantgarde-book-r", "AvantGarde-Book" }, - { "avantgarde-book-o", "AvantGarde-BookOblique" }, - { "avantgarde-demi-r", "AvantGarde-Demi" }, - { "avantgarde-demi-o", "AvantGarde-DemiOblique" }, - { "palatino-medium-r", "Palatino-Roman" }, - { "palatino-medium-i", "Palatino-Italic" }, - { "palatino-bold-r", "Palatino-Bold" }, - { "palatino-bold-i", "Palatino-BoldItalic" }, - { "new century schoolbook-medium-r", "NewCenturySchlbk-Roman" }, - { "new century schoolbook-medium-i", "NewCenturySchlbk-Italic" }, - { "new century schoolbook-bold-r", "NewCenturySchlbk-Bold" }, - { "new century schoolbook-bold-i", "NewCenturySchlbk-BoldItalic" }, - { "zapfchancery-medium-i", "ZapfChancery-MediumItalic" } }; - -static struct { - const char * name, * value; - } pagemargins [] = { - { "None", "0.00 0.00 0.00 0.00" }, - { "BJC-600", "0.10 0.44 0.38 0.13" }, - { "DeskJet", "0.167 0.50 0.25 0.25" }, - { "PaintJet", "0.167 0.167 0.167 0.167" }, - { "DJ505", "0.25 0.668 0.125 0.125" }, - { "DJ560C", "0.37 0.46 0.25 0.25" }, - { "LaserJet", "0.43 0.21 0.43 0.28" } }; - - -static void doSetOptXFont( - wIndex_t inx, - const char * xFont, - wIndex_t inx2, - void * itemData, - void * listData ) -{ - const char * cp; - optXFont = xFont; - cp = wPrefGetString( WFONT, xFont ); - if ( !cp ) - cp = ""; - wStringSetValue( optPSFontS, cp ); -} - - -static void doSetOptPSFont( - const char * psFont, - void * data ) -{ - if ( optXFont && - psFont[0] ) - wPrefSetString( WFONT, optXFont, psFont ); -} - - -static void printInit( void ) -{ - wIndex_t i; - wPos_t x, y; - static wBool_t printInitted = FALSE; - const char * cp, * cq; - char num[10]; - - if (printInitted) - return; - - printInitted = TRUE; - prefName = wPrefGetString( "printer", "name" ); - prefPaper = wPrefGetString( "printer", "paper" ); - prefMargin = wPrefGetString( "printer", "margin" ); - prefFormat = wPrefGetString( "printer", "format" ); - if (prefFormat && strcasecmp(prefFormat, "landscape") == 0) - printFormat = PRINT_LANDSCAPE; - else - printFormat = PRINT_PORTRAIT; - wPrefGetFloat( WPRINTFONT, "factor", &fontSizeFactor, 1.0 ); - if ( fontSizeFactor < 0.5 || fontSizeFactor > 2.0 ) { - fontSizeFactor = 1.0; - wPrefSetFloat( WPRINTFONT, "factor", fontSizeFactor ); - } - - x = wLabelWidth( _("Paper Size") )+4; - printSetupW = wWinPopupCreate( NULL, 4, 4, "printSetupW", _("Print Setup"), "xvprintsetup", F_AUTOSIZE|F_RECALLPOS, NULL, NULL ); - optPrinterB = wDropListCreate( printSetupW, x, -4, "printSetupPrinter", _("Printer"), 0, 4, 100, &newPPrinter, NULL, NULL ); -#ifdef LATER - wButtonCreate( printSetupW, -10, 2, "printSetupPrinter", _("New"), 0, 0, newPrinter, NULL ); -#endif - optPaperSizeB = wDropListCreate( printSetupW, x, -4, "printSetupPaper", _("Paper Size"), 0, 4, 100, &newPPaper, NULL, NULL ); - y = wControlGetPosY( (wControl_p)optPaperSizeB ) + wControlGetHeight( (wControl_p)optPaperSizeB ) + 10; - for ( i=0; i \n", argv[0] ); - exit(1); - } - argv++; - printFormat = (*(*argv++)=='L')?PRINT_LANDSCAPE:PRINT_PORTRAIT; - printDraw_d.orig.x = atof(*argv++); - printDraw_d.orig.y = atof(*argv++); - printRoomSize.x = atof(*argv++); - printRoomSize.y = atof(*argv++); - fprintf( stderr, "Fmt=%c, orig=(%0.3f %0.3f) RS=(%0.3f %0.3f)\n", - (printFormat==PRINT_LANDSCAPE)?'L':'P', - printDraw_d.orig.x, printDraw_d.orig.y, - printRoomSize.x, printRoomSize.y ); - wPrintGetPageSize(PRINT_GAUDY, printFormat); - fprintf( stderr, "PageSize= (%0.3f %0.3f)\n", printDraw_d.size.x, printDraw_d.size.y ); - - wPrintDocStart( PRINT_GAUDY ); - wPrintPage( PRINT_GAUDY, 0, 0 ); - wPrintDocEnd( ); -} - -#endif diff --git a/app/wlib/gtklib/wpref.c b/app/wlib/gtklib/wpref.c index b79c8d2..4df3de9 100644 --- a/app/wlib/gtklib/wpref.c +++ b/app/wlib/gtklib/wpref.c @@ -66,8 +66,8 @@ EXPORT const char * wGetAppLibDir( void ) * The search order is: * 1. Directory specified by the XTRKCADLIB environment variable * 2. Directory specified by XTRKCAD_INSTALL_PREFIX/share/xtrkcad - * 3. /usr/lib/xtrkcad - * 4. /usr/local/lib/xtrkcad + * 3. /usr/share/xtrkcad + * 4. /usr/local/share/xtrkcad * * \return pointer to directory name */ @@ -102,13 +102,13 @@ EXPORT const char * wGetAppLibDir( void ) } #endif - strcpy( appLibDir, "/usr/lib/" ); + strcpy( appLibDir, "/usr/share/" ); strcat( appLibDir, wAppName ); if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) { return appLibDir; } - strcpy( appLibDir, "/usr/local/lib/" ); + strcpy( appLibDir, "/usr/local/share/" ); strcat( appLibDir, wAppName ); if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) { return appLibDir; @@ -118,8 +118,8 @@ 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/lib/%s or\n" - " /usr/local/lib/%s\n" + " /usr/share/%s or\n" + " /usr/local/share/%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 ); diff --git a/app/wlib/include/wlib.h b/app/wlib/include/wlib.h index 4582231..cf8f337 100644 --- a/app/wlib/include/wlib.h +++ b/app/wlib/include/wlib.h @@ -1,20 +1,21 @@ /** \file wlib.h - * Commaon definitions and declarations for the wlib library - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/include/wlib.h,v 1.18 2010-04-28 04:04:39 dspagnol Exp $ + * Common definitions and declarations for the wlib library */ #ifndef WIN_H #define WIN_H #ifdef WINDOWS #include +#define FILE_SEP_CHAR "\\" +#else +#define FILE_SEP_CHAR "/" #endif #ifdef USE_SIMPLE_GETTEXT char *bindtextdomain( char *domainname, char *dirname ); char *bind_textdomain_codeset(char *domainname, char *codeset ); char *textdomain( char *domainname ); -char *gettext( char *msgid ); +char *gettext( const char *msgid ); char *g_win32_getlocale (void); #endif @@ -331,6 +332,7 @@ void wListSetEditable( wList_p, wBool_t ); wIndex_t wListAddValue( wList_p, const char *, wIcon_p, void * ); void wListDelete( wList_p, wIndex_t ); wIndex_t wListGetValues( wList_p, char *, int, void * *, void * * ); +void wListSelectAll( wList_p bl ); wIndex_t wListGetCount( wList_p ); void * wListGetItemContext( wList_p, wIndex_t ); wBool_t wListGetItemSelected( wList_p, wIndex_t ); @@ -638,16 +640,18 @@ void wAttachAccelKey( wAccelKey_e, int, wAccelKeyCallBack_p, void * ); * File Selection */ +#define FS_MULTIPLEFILES 1 + struct wFilSel_t; typedef enum { FS_SAVE, FS_LOAD, FS_UPDATE } wFilSelMode_e; -typedef int (*wFilSelCallBack_p)( const char * pathName, const char * fileName, void * ); +typedef int (*wFilSelCallBack_p)( int files, char ** fileName, void * ); struct wFilSel_t * wFilSelCreate(wWin_p, wFilSelMode_e, int, const char *, const char *, wFilSelCallBack_p, void * ); -int wFilSelect( struct wFilSel_t *, const char * ); +int wFilSelect( struct wFilSel_t *, const char * ); /*------------------------------------------------------------------------------ diff --git a/app/wlib/mswlib/mswbutt.c b/app/wlib/mswlib/mswbutt.c index b5d7b49..24e669f 100644 --- a/app/wlib/mswlib/mswbutt.c +++ b/app/wlib/mswlib/mswbutt.c @@ -257,7 +257,7 @@ static void buttDone( free(b); } -long FAR PASCAL _export pushButt( +LRESULT CALLBACK pushButt( HWND hWnd, UINT message, UINT wParam, @@ -301,9 +301,10 @@ long FAR PASCAL _export pushButt( InvalidateRect( b->hWnd, NULL, TRUE ); return 0L; break; - case WM_ERASEBKGND: - if (kludge12) - return 1L; + case WM_LBUTTONUP: + /* don't know why but this solves a problem with color selection */ + Sleep( 0 ); + break; } return CallWindowProc( oldButtProc, hWnd, message, wParam, lParam ); } @@ -372,9 +373,8 @@ wButton_p wButtonCreate( b->action = action; mswCallBacks[B_BUTTON] = &buttonCallBacks; mswChainFocus( (wControl_p)b ); - newButtProc = MakeProcInstance( (XWNDPROC)pushButt, mswHInst ); - oldButtProc = (XWNDPROC)GetWindowLong( b->hWnd, GWL_WNDPROC ); - SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newButtProc ); + + oldButtProc = (WNDPROC) SetWindowLongPtr(b->hWnd, GWL_WNDPROC, (LONG_PTR)&pushButt); if (mswPalette) { hDc = GetDC( b->hWnd ); SelectPalette( hDc, mswPalette, 0 ); diff --git a/app/wlib/mswlib/mswlist.c b/app/wlib/mswlib/mswlist.c index 968624a..18fa92d 100644 --- a/app/wlib/mswlib/mswlist.c +++ b/app/wlib/mswlib/mswlist.c @@ -285,6 +285,39 @@ void wListDelete( } +/** + * Select all items in list. + * + * \param bl IN list handle + * \return + */ + +void wListSelectAll( wList_p bl ) +{ + wIndex_t inx; + listData *ldp; + + // mark all items selected + SendMessage( bl->hWnd, + LB_SETSEL, + (WPARAM)TRUE, + (DWORD)-1L ); + + // and synchronize the internal data structures + wListGetCount(bl); + for ( inx=0; inxcount; inx++ ) { + ldp = (listData*)SendMessage( bl->hWnd, + (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA), + inx, 0L ); + ldp->selected = TRUE; + SendMessage( bl->hWnd, + (UINT)bl->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA, + (WPARAM)inx, + (DWORD)ldp ); + } +} + + wIndex_t wListGetCount( wList_p bl ) { @@ -333,6 +366,8 @@ wIndex_t wListGetSelectedCount( } + + wIndex_t wListAddValue( wList_p b, const char * value, diff --git a/app/wlib/mswlib/mswmenu.c b/app/wlib/mswlib/mswmenu.c index 15053a2..de49742 100644 --- a/app/wlib/mswlib/mswmenu.c +++ b/app/wlib/mswlib/mswmenu.c @@ -1,3 +1,26 @@ +/** \file mswmenu.c + * Pulldown menu creation and handling + * \todo Code for accelerator keys was copied and pasted, replace with utility function + */ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) (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 OEMRESOURCE #include @@ -9,6 +32,7 @@ #include #include #include "mswint.h" +#include "i18n.h" /* ***************************************************************************** @@ -834,6 +858,11 @@ wMenuToggle_p wMenuToggleCreate( { wMenuToggle_p mt; int rc; + char label[80]; + char *cp; + char ac; + UINT vk; + long modifier; mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof *mt ); /*setAcclKey( m->parent, m->menu, mt->menu_item, acclKey );*/ @@ -842,7 +871,47 @@ wMenuToggle_p wMenuToggleCreate( mt->mparent = m; mt->enabled = TRUE; mt->parentMenu = m; - rc = AppendMenu( m->menu, MF_STRING, mt->index, labelStr ); + strcpy( label, mt->labelStr ); + modifier = 0; + + if ( acclKey != 0 ) { + DYNARR_APPEND( acclTable_t, acclTable_da, 10 ); + cp = label + strlen( label ); + *cp++ = '\t'; + if (acclKey & WCTL ) { + strcpy( cp, _("Ctrl+") ); +// cp += 5; + modifier |= WKEY_CTRL; + } + if (acclKey & WALT ) { + strcpy( cp, _("Alt+") ); +// cp += 4; + modifier |= WKEY_ALT; + } + if (acclKey & WSHIFT ) { + strcpy( cp, _("Shift+") ); +// cp += 6; + modifier |= WKEY_SHIFT; + } + cp = label + strlen( label ); + if( ((char)acclKey & 0xFF ) == ' ' ) { + strcat( label, _("Space") ); + } else { + *cp++ = toupper( (char)(acclKey & 0xFF) ); + *cp++ = '\0'; + } + ac = (char)(acclKey & 0xFF); + if (isalpha(ac)) { + ac = tolower( ac ); + } + vk = VkKeyScan( ac ); + if ( vk & 0xFF00 ) + modifier |= WKEY_SHIFT; + acclTable(acclTable_da.cnt-1).acclKey = (modifier<<8) | (vk&0x00FF); + acclTable(acclTable_da.cnt-1).mp = mt; + } + + rc = AppendMenu( m->menu, MF_STRING, mt->index, label ); wMenuToggleSet( mt, set ); return mt; } diff --git a/app/wlib/mswlib/mswmisc.c b/app/wlib/mswlib/mswmisc.c index fc1dbe6..85438e0 100644 --- a/app/wlib/mswlib/mswmisc.c +++ b/app/wlib/mswlib/mswmisc.c @@ -1,7 +1,5 @@ /** \file mswmisc.c * Basic windows functions and main entry point for application. - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswmisc.c,v 1.28 2010-04-28 04:04:38 dspagnol Exp $ */ /* XTrkCad - Model Railroad CAD @@ -2003,13 +2001,26 @@ static char selFileName[1024]; static char selFileTitle[1024]; static char sysDirName[1024]; +/** + * Run the file selector. After the selector is finished an array of filenames is + * created. Each filename will be fully qualified. The array and the number of + * filenames are passed to a callback function. This is similar to the argc argv c + * convention in C. Once the callback returns, the allocated strings are free'd. + * + * \param fs IN the file selector dialog + * \param dirName IN the initial directory presented + * \return FALSE on error, TRUE if ok + */ + int wFilSelect( struct wFilSel_t * fs, const char * dirName ) { int rc; OPENFILENAME ofn; - char * fileName; + char **fileName; + char *nextFileName; + int cntFiles; const char * ext; char defExt[4]; int i; @@ -2024,7 +2035,7 @@ int wFilSelect( ofn.hwndOwner = mswHWnd; ofn.lpstrFilter = fs->extList; ofn.nFilterIndex = 0; - selFileName[0] = '\0'; + memset( selFileName, '\0', sizeof(selFileName)); ofn.lpstrFile = selFileName; ofn.nMaxFile = sizeof selFileName; selFileTitle[0] = '\0'; @@ -2041,7 +2052,13 @@ int wFilSelect( defExt[0] = '\0'; } ofn.lpstrDefExt = defExt; - ofn.Flags |= OFN_LONGFILENAMES; + + if ( fs->option & FS_MULTIPLEFILES ) { + ofn.Flags = OFN_ALLOWMULTISELECT | OFN_LONGFILENAMES | OFN_EXPLORER; + } else { + ofn.Flags = OFN_LONGFILENAMES; + } + if (fs->mode == FS_LOAD) { ofn.Flags |= OFN_FILEMUSTEXIST; rc = GetOpenFileName( &ofn ); @@ -2054,12 +2071,37 @@ int wFilSelect( return FALSE; if (!rc) return FALSE; - fileName = strrchr( selFileName, '\\' ); - if (fileName == NULL) { - mswFail( "wFilSelect: cant extract fileName" ); - return FALSE; + + nextFileName = selFileName; + selFileName[ofn.nFileOffset - 1] = '\0'; + cntFiles = 0; + + while (*nextFileName) { + cntFiles++; + nextFileName = nextFileName + strlen( nextFileName ) + 1; + } + + // strings were counted including the path on its own so reduce the count + cntFiles--; + + // build up the array of filenames + fileName = malloc(sizeof(nextFileName) * cntFiles); + nextFileName = selFileName + ofn.nFileOffset; + for ( i=0; i < cntFiles; i++) { + fileName[ i ] = malloc(strlen(selFileName) + strlen(nextFileName) + 2 ); + strcpy(fileName[ i ], selFileName); + strcat(fileName[ i ], FILE_SEP_CHAR); + strcat(fileName[ i ], nextFileName); + nextFileName = nextFileName + strlen( nextFileName ) + 1; } - fs->action( selFileName, fileName+1, fs->data ); + + fs->action( cntFiles, fileName, fs->data ); + + for (i=0; i < cntFiles; i++) { + free( fileName[ i ] ); + } + free( fileName ); + return TRUE; } diff --git a/app/wlib/mswlib/simple-gettext.c b/app/wlib/mswlib/simple-gettext.c index 295d515..d213fc3 100644 --- a/app/wlib/mswlib/simple-gettext.c +++ b/app/wlib/mswlib/simple-gettext.c @@ -1,4 +1,5 @@ -/* simple-gettext.c - a simplified version of gettext. +/* \file simple-gettext.c + * a simplified version of gettext. * Copyright (C) 1995, 1996, 1997, 1999, * 2005 Free Software Foundation, Inc. * @@ -378,7 +379,7 @@ get_string( struct loaded_domain *domain, u32 idx ) */ char * -gettext( char *msgid ) +gettext( const char *msgid ) { struct loaded_domain *domain; size_t act = 0; @@ -446,7 +447,7 @@ gettext( char *msgid ) } not_found: - return msgid; + return (char *)msgid; } /** -- cgit v1.2.3