diff options
Diffstat (limited to 'app/wlib/gtklib/gtkmisc.c')
-rw-r--r-- | app/wlib/gtklib/gtkmisc.c | 1210 |
1 files changed, 1210 insertions, 0 deletions
diff --git a/app/wlib/gtklib/gtkmisc.c b/app/wlib/gtklib/gtkmisc.c new file mode 100644 index 0000000..acc123a --- /dev/null +++ b/app/wlib/gtklib/gtkmisc.c @@ -0,0 +1,1210 @@ +/* + * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkmisc.c,v 1.15 2009-10-03 04:49:01 dspagnol Exp $ + */ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2005 Dave Bullis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <dirent.h> +#include <sys/time.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <locale.h> + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> + +#include "gtkint.h" +#include "i18n.h" + +wWin_p gtkMainW; + +long debugWindow = 0; + +char wAppName[256]; +char wConfigName[ 256 ]; + +#define FOUR (4) +#ifndef GTK1 +#define MENUH (24) +#else +#define MENUH (24) +#endif +#define LABEL_OFFSET (3) + +const char * wNames[] = { + "MAIN", + "POPUP", + "BUTT", + "CANCEL", + "POPUP", + "TEXT", + "INTEGER", + "FLOAT", + "LIST", + "DROPLIST", + "COMBOLIST", + "RADIO", + "TOGGLE", + "DRAW", + "MENU" + "MULTITEXT", + "MESSAGE", + "LINES", + "MENUITEM", + "BOX" + }; + +static struct timeval startTime; + +static wBool_t reverseIcon = +#if defined(linux) + FALSE; +#else + TRUE; +#endif + +char gtkAccelChar; + + +/* + ***************************************************************************** + * + * Internal Utility functions + * + ***************************************************************************** + */ + +unsigned char gtkBitrotate( + char v ) +{ + unsigned char r = 0; + int i; + static unsigned char bits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + for (i=0;i<8;i++) + if (v & bits[i]) + r |= bits[7-i]; + return r; +} + +GdkPixmap* gtkMakeIcon( + GtkWidget * widget, + wIcon_p ip, + GdkBitmap ** mask ) +{ + GdkPixmap * pixmap; + char ** pixmapData; + char * oldline1; + static char newline1[] = " \tc None s None"; + char line0[40]; + char line2[40]; + int row,col,wb; + long rgb; + const char * bits; + GdkColor *transparent; + + transparent = >k_widget_get_style( gtkMainW->gtkwin )->bg[GTK_WIDGET_STATE( gtkMainW->gtkwin )]; + + if ( ip->gtkIconType == gtkIcon_pixmap ) { + pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, (char**)ip->bits ); + } + else { + wb = (ip->w+7)/8; + pixmapData = (char**)malloc( (3+ip->h) * sizeof *pixmapData ); + pixmapData[0] = line0; + rgb = wDrawGetRGB(ip->color); + sprintf( line0, " %d %d 2 1", ip->w, ip->h ); + sprintf( line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF ); + pixmapData[1] = ". c None s None"; + pixmapData[2] = line2; + bits = ip->bits; + for (row = 0; row<ip->h; row++ ) { + pixmapData[row+3] = (char*)malloc( (ip->w+1) * sizeof **pixmapData ); + for (col = 0; col<ip->w; col++ ) { + if ( bits[ row*wb+(col>>3) ] & (1<<(col&07)) ) { + pixmapData[row+3][col] = '#'; + } else { + pixmapData[row+3][col] = '.'; + } + } + pixmapData[row+3][ip->w] = 0; + } + pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, pixmapData ); + for (row = 0; row<ip->h; row++ ) { + free( pixmapData[row+3] ); + } + } + return pixmap; +} + + +int gtkAddLabel( wControl_p b, const char * labelStr ) +{ + GtkRequisition requisition; + if (labelStr == NULL) + return 0; + b->label = gtk_label_new(gtkConvertInput(labelStr)); + gtk_widget_size_request( b->label, &requisition ); + gtk_container_add( GTK_CONTAINER(b->parent->widget), b->label ); +#ifndef GTK1 + gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET ); +#else + gtk_widget_set_uposition( b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET ); +#endif + gtk_widget_show( b->label ); + return requisition.width+8; +} + + +void * gtkAlloc( + wWin_p parent, + wType_e type, + wPos_t origX, + wPos_t origY, + const char * labelStr, + int size, + void * data ) +{ + wControl_p w = (wControl_p)malloc( size ); + char * cp; + memset( w, 0, size ); + if (w == NULL) + abort(); + w->type = type; + w->parent = parent; + w->origX = origX; + w->origY = origY; + gtkAccelChar = 0; + if (labelStr) { + cp = (char*)malloc(strlen(labelStr)+1); + w->labelStr = cp; + for ( ; *labelStr; labelStr++ ) + if ( *labelStr != '&' ) + *cp++ = *labelStr; + else { +/* *cp++ = '_'; + gtkAccelChar = labelStr[1]; */ + } + *cp = 0; + } + w->doneProc = NULL; + w->data = data; + return w; +} + + +void gtkComputePos( + wControl_p b ) +{ + wWin_p w = b->parent; + + if (b->origX >= 0) + b->realX = b->origX; + else + b->realX = w->lastX + (-b->origX) - 1; + if (b->origY >= 0) + b->realY = b->origY + FOUR + ((w->option&F_MENUBAR)?MENUH:0); + else + b->realY = w->lastY + (-b->origY) - 1; +} + + +void gtkControlGetSize( + wControl_p b ) +{ + GtkRequisition requisition; + gtk_widget_size_request( b->widget, &requisition ); + b->w = requisition.width; + b->h = requisition.height; +} + + +void gtkAddButton( + wControl_p b ) +{ + wWin_p win = b->parent; + wBool_t resize = FALSE; + if (win->first == NULL) { + win->first = b; + } else { + win->last->next = b; + } + win->last = b; + b->next = NULL; + b->parent = win; + win->lastX = b->realX + b->w; + win->lastY = b->realY + b->h; + if (win->option&F_AUTOSIZE) { + if (win->lastX > win->realX) { + win->realX = win->lastX; + if (win->w != (win->realX + win->origX)) { + resize = TRUE; + win->w = (win->realX + win->origX); + } + } + if (win->lastY > win->realY) { + win->realY = win->lastY; + if (win->h != (win->realY + win->origY)) { + resize = TRUE; + win->h = (win->realY + win->origY); + } + } + if (win->shown) { + if ( resize ) { +#ifndef GTK1 + gtk_widget_set_size_request( win->gtkwin, win->w, win->h ); + gtk_widget_set_size_request( win->widget, win->w, win->h ); +#else + gtk_widget_set_usize( win->gtkwin, win->w, win->h ); + gtk_widget_set_usize( win->widget, win->w, win->h ); +#endif + } + } + } +} + + +void gtkSetReadonly( wControl_p b, wBool_t ro ) +{ + if (ro) + b->option |= BO_READONLY; + else + b->option &= ~BO_READONLY; +} + + +wControl_p gtkGetControlFromPos( + wWin_p win, + wPos_t x, + wPos_t y ) +{ + wControl_p b; + wPos_t xx, yy; + for (b=win->first; b != NULL; b = b->next) { + if ( b->widget && GTK_WIDGET_VISIBLE(b->widget) ) { + xx = b->realX; + yy = b->realY; + if ( xx <= x && x < xx+b->w && + yy <= y && y < yy+b->h ) { + return b; + } + } + } + return NULL; +} + +/* \brief Convert label string from Windows mnemonic to GTK + * + * The first occurence of '&' in the passed string is changed to '_' + * + * \param label the string to convert + * \return pointer to modified string, has to be free'd after usage + * + */ +static +char * gtkChgMnemonic( char *label ) +{ + char *ptr; + char *cp; + + cp = strdup( label ); + + ptr = strchr( cp, '&' ); + if( ptr ) + *ptr = '_'; + + return( cp ); +} + + +/* + ***************************************************************************** + * + * Exported Utility Functions + * + ***************************************************************************** + */ + +EXPORT void wBeep( + void ) +/* +Beep! +*/ +{ + gdk_display_beep(gdk_display_get_default()); +} + +typedef struct { + GtkWidget * win; + GtkWidget * label; + GtkWidget * butt[3]; + } notice_win; +static notice_win noticeW; +static long noticeValue; + +static void doNotice( + GtkWidget * widget, + long value ) +{ + noticeValue = value; + gtk_widget_destroy( noticeW.win ); + gtkDoModal( NULL, FALSE ); +} + +/** + * Show a notification window with a yes/no reply and an icon. + * + * \param type IN type of message: Information, Warning, Error + * \param msg IN message to display + * \param yes IN text for accept button + * \param no IN text for cancel button + * \return True when accept was selected, false otherwise + */ + +int wNoticeEx( int type, + const char * msg, + const char * yes, + const char * no ) +{ + + int res; + unsigned flag; + char *headline; + GtkWidget *dialog; + GtkWindow *parent = GTK_WINDOW_TOPLEVEL; + + switch( type ) { + case NT_INFORMATION: + flag = GTK_MESSAGE_INFO; + headline = _("Information"); + break; + case NT_WARNING: + flag = GTK_MESSAGE_WARNING; + headline = _("Warning"); + break; + case NT_ERROR: + flag = GTK_MESSAGE_ERROR; + headline = _("Error"); + break; + } + + if( gtkMainW ) + parent = GTK_WINDOW( gtkMainW->gtkwin); + + dialog = gtk_message_dialog_new( parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + flag, + ((no==NULL)?GTK_BUTTONS_OK:GTK_BUTTONS_YES_NO), + "%s", msg ); + gtk_window_set_title( GTK_WINDOW(dialog), headline ); + + res = gtk_dialog_run( GTK_DIALOG(dialog)); + gtk_widget_destroy( dialog ); + + return res == GTK_RESPONSE_OK || res == GTK_RESPONSE_YES; +} + + +EXPORT int wNotice( + const char * msg, /* Message */ + const char * yes, /* First button label */ + const char * no ) /* Second label (or 'NULL') */ +/* +Popup up a notice box with one or two buttons. +When this notice box is displayed the application is paused and +will not response to other actions. + +Pushing the first button returns 'TRUE'. +Pushing the second button (if present) returns 'FALSE'. +*/ +{ + return wNotice3( msg, yes, no, NULL ); +} + +/** \brief Popup a notice box with three buttons. + * + * Popup up a notice box with three buttons. + * When this notice box is displayed the application is paused and + * will not response to other actions. + * + * Pushing the first button returns 1 + * Pushing the second button returns 0 + * Pushing the third button returns -1 + * + * \param msg Text to display in message box + * \param yes First button label + * \param no Second label (or 'NULL') + * \param cancel Third button label (or 'NULL') + * + * \returns 1, 0 or -1 + */ + +EXPORT int wNotice3( + const char * msg, /* Message */ + const char * affirmative, /* First button label */ + const char * cancel, /* Second label (or 'NULL') */ + const char * alternate ) +{ + notice_win *nw; + GtkWidget * vbox; + GtkWidget * hbox; + GtkWidget * hbox1; + GtkWidget * image; + nw = ¬iceW; + + char *aff = NULL; + char *can = NULL; + char *alt = NULL; + +#ifndef GTK1 + nw->win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + /*gtk_window_set_decorated( GTK_WINDOW(nw->win), FALSE );*/ +#else + nw->win = gtk_window_new( GTK_WINDOW_DIALOG ); +#endif + gtk_window_position( GTK_WINDOW(nw->win), GTK_WIN_POS_CENTER ); + gtk_container_set_border_width (GTK_CONTAINER (nw->win), 0); + gtk_window_set_resizable (GTK_WINDOW (nw->win), FALSE); + gtk_window_set_modal (GTK_WINDOW (nw->win), TRUE); + gtk_window_set_type_hint (GTK_WINDOW (nw->win), GDK_WINDOW_TYPE_HINT_DIALOG); + + vbox = gtk_vbox_new( FALSE, 12 ); + gtk_widget_show( vbox ); + gtk_container_add( GTK_CONTAINER(nw->win), vbox ); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + + hbox = gtk_hbox_new( FALSE, 12 ); + gtk_box_pack_start( GTK_BOX(vbox), hbox, TRUE, TRUE, 0 ); + gtk_widget_show(hbox); + + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); + gtk_misc_set_alignment (GTK_MISC (image), 0, 0); + + /* create the text label, allow GTK to wrap and allow for markup (for future enhancements) */ + nw->label = gtk_label_new(msg); + gtk_widget_show( nw->label ); + gtk_box_pack_end (GTK_BOX (hbox), nw->label, TRUE, TRUE, 0); + gtk_label_set_use_markup (GTK_LABEL (nw->label), FALSE); + gtk_label_set_line_wrap (GTK_LABEL (nw->label), TRUE); + gtk_misc_set_alignment (GTK_MISC (nw->label), 0, 0); + + /* this hbox will include the button bar */ + hbox1 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox), hbox1, FALSE, TRUE, 0); + + /* add the respective buttons */ + aff = gtkChgMnemonic( (char *) affirmative); + nw->butt[ 0 ] = gtk_button_new_with_mnemonic (aff); + gtk_widget_show (nw->butt[ 0 ]); + gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 0 ], TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 0 ]), 3); + gtk_signal_connect( GTK_OBJECT(nw->butt[0]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)1 ); + GTK_WIDGET_SET_FLAGS (nw->butt[ 0 ], GTK_CAN_DEFAULT); + + if( cancel ) { + can = gtkChgMnemonic( (char *) cancel); + nw->butt[ 1 ] = gtk_button_new_with_mnemonic (can); + gtk_widget_show (nw->butt[ 1 ]); + gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 1 ], TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 1 ]), 3); + gtk_signal_connect( GTK_OBJECT(nw->butt[1]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)0 ); + GTK_WIDGET_SET_FLAGS (nw->butt[ 1 ], GTK_CAN_DEFAULT); + + if( alternate ) { + alt = gtkChgMnemonic( (char *) alternate); + nw->butt[ 2 ] = gtk_button_new_with_mnemonic (alt); + gtk_widget_show (nw->butt[ 2 ]); + gtk_box_pack_start (GTK_BOX (hbox1), nw->butt[ 2 ], TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 2 ]), 3); + gtk_signal_connect( GTK_OBJECT(nw->butt[2]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)-1 ); + GTK_WIDGET_SET_FLAGS (nw->butt[ 2 ], GTK_CAN_DEFAULT); + } + } + + gtk_widget_grab_default (nw->butt[ 0 ]); + gtk_widget_grab_focus (nw->butt[ 0 ]); + + gtk_widget_show( nw->win ); + + if ( gtkMainW ) { + gtk_window_set_transient_for( GTK_WINDOW(nw->win), GTK_WINDOW( gtkMainW->gtkwin) ); +/* gdk_window_set_group( nw->win->window, gtkMainW->gtkwin->window ); */ + } + gtkDoModal( NULL, TRUE ); + + if( aff ) + free( aff ); + + if( can ) + free( can ); + + if( alt ) + free( alt ); + + return noticeValue; +} + + +EXPORT void wFlush( + void ) +/* +Flushs all commands to the Window. +*/ +{ + while ( gtk_events_pending() ) + gtk_main_iteration(); + + gdk_display_sync(gdk_display_get_default()); +} + + +void wWinTop( wWin_p win ) +{ +} + + +void wSetCursor( wCursor_t cursor ) +{ +} + + +const char * wMemStats( void ) +{ +#ifdef LATER + static char msg[80]; + struct mstats stats; + stats = mstats(); + sprintf( msg, "Total %d, used %d(%d), free %d(%d)", + stats.bytes_total, + stats.bytes_used, stats.chunks_used, + stats.bytes_free, stats.chunks_free ); + return msg; +#else + return "No stats available"; +#endif +} + + +wBool_t wCheckExecutable( void ) +{ + return TRUE; +} + + +void wGetDisplaySize( wPos_t * w, wPos_t * h ) +{ + + *w = gdk_screen_width(); + *h = gdk_screen_height(); +} + + +wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color ) +{ + wIcon_p ip; + ip = (wIcon_p)malloc( sizeof *ip ); + ip->gtkIconType = gtkIcon_bitmap; + ip->w = w; + ip->h = h; + ip->color = color; + ip->bits = bits; + return ip; +} + +wIcon_p wIconCreatePixMap( char *pm[] ) +{ + wIcon_p ip; + ip = (wIcon_p)malloc( sizeof *ip ); + ip->gtkIconType = gtkIcon_pixmap; + ip->w = 0; + ip->h = 0; + ip->color = 0; + ip->bits = pm; + return ip; +} + + +void wIconSetColor( wIcon_p ip, wDrawColor color ) +{ + ip->color = color; +} + +void wConvertToCharSet( char * buffPtr, int buffMax ) +{ +} + + +void wConvertFromCharSet( char * buffPtr, int buffMax ) +{ +} + +static dynArr_t conversionBuffer_da; +#define convesionBuffer(N) DYNARR_N( char, conversionBuffer_da, N ) + +char * gtkConvertInput( const char * inString ) +{ +#ifndef GTK1 + const char * cp; + char * cq; + int extCharCnt, inCharCnt; + + /* Already UTF-8 encoded? */ + if (g_utf8_validate(inString, -1, NULL)) + /* Yes, do not double-convert */ + return (char*)inString; +#ifdef VERBOSE + fprintf(stderr, "gtkConvertInput(%s): Invalid UTF-8, converting...\n", inString); +#endif + + for ( cp=inString, extCharCnt=0; *cp; cp++ ) { + if ( ((*cp)&0x80) != 0 ) + extCharCnt++; + } + inCharCnt = cp-inString; + if ( extCharCnt == 0 ) + return (char*)inString; + DYNARR_SET( char, conversionBuffer_da, inCharCnt+extCharCnt+1 ); + for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) { + if ( ((*cp)&0x80) != 0 ) { + *cq++ = 0xC0+(((*cp)&0xC0)>>6); + *cq++ = 0x80+((*cp)&0x3F); + } else { + *cq++ = *cp; + } + } + *cq = 0; + return (char*)conversionBuffer_da.ptr; +#else + return (char*)inString; +#endif +} + + +char * gtkConvertOutput( const char * inString ) +{ +#ifndef GTK1 + const char * cp; + char * cq; + int extCharCnt, inCharCnt; + for ( cp=inString, extCharCnt=0; *cp; cp++ ) { + if ( ((*cp)&0xC0) == 0x80 ) + extCharCnt++; + } + inCharCnt = cp-inString; + if ( extCharCnt == 0 ) + return (char*)inString; + DYNARR_SET( char, conversionBuffer_da, inCharCnt+1 ); + for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) { + if ( ((*cp)&0x80) != 0 ) { + *cq++ = 0xC0+(((*cp)&0xC0)>>6); + *cq++ = 0x80+((*cp)&0x3F); + } else { + *cq++ = *cp; + } + } + *cq = 0; + return (char*)conversionBuffer_da.ptr; +#else + return (char*)inString; +#endif +} + +/*-----------------------------------------------------------------*/ + +typedef struct accelData_t { + wAccelKey_e key; + int modifier; + wAccelKeyCallBack_p action; + void * data; + } accelData_t; +static dynArr_t accelData_da; +#define accelData(N) DYNARR_N( accelData_t, accelData_da, N ) + + +static guint accelKeyMap[] = { + 0, /* wAccelKey_None, */ + GDK_Delete, /* wAccelKey_Del, */ + GDK_Insert, /* wAccelKey_Ins, */ + GDK_Home, /* wAccelKey_Home, */ + GDK_End, /* wAccelKey_End, */ + GDK_Page_Up, /* wAccelKey_Pgup, */ + GDK_Page_Down, /* wAccelKey_Pgdn, */ + GDK_Up, /* wAccelKey_Up, */ + GDK_Down, /* wAccelKey_Down, */ + GDK_Right, /* wAccelKey_Right, */ + GDK_Left, /* wAccelKey_Left, */ + GDK_BackSpace, /* wAccelKey_Back, */ + GDK_F1, /* wAccelKey_F1, */ + GDK_F2, /* wAccelKey_F2, */ + GDK_F3, /* wAccelKey_F3, */ + GDK_F4, /* wAccelKey_F4, */ + GDK_F5, /* wAccelKey_F5, */ + GDK_F6, /* wAccelKey_F6, */ + GDK_F7, /* wAccelKey_F7, */ + GDK_F8, /* wAccelKey_F8, */ + GDK_F9, /* wAccelKey_F9, */ + GDK_F10, /* wAccelKey_F10, */ + GDK_F11, /* wAccelKey_F11, */ + GDK_F12 /* wAccelKey_F12, */ + }; + + +EXPORT void wAttachAccelKey( + wAccelKey_e key, + int modifier, + wAccelKeyCallBack_p action, + void * data ) +{ + accelData_t * ad; + if ( key < 1 || key > wAccelKey_F12 ) { + fprintf( stderr, "wAttachAccelKey(%d) out of range\n", (int)key ); + return; + } + DYNARR_APPEND( accelData_t, accelData_da, 10 ); + ad = &accelData(accelData_da.cnt-1); + ad->key = key; + ad->modifier = modifier; + ad->action = action; + ad->data = data; +} + + +EXPORT struct accelData_t * gtkFindAccelKey( + GdkEventKey * event ) +{ + accelData_t * ad; + int modifier = 0; + if ( ( event->state & GDK_SHIFT_MASK ) ) + modifier |= WKEY_SHIFT; + if ( ( event->state & GDK_CONTROL_MASK ) ) + modifier |= WKEY_CTRL; + if ( ( event->state & GDK_MOD1_MASK ) ) + modifier |= WKEY_ALT; + for ( ad=&accelData(0); ad<&accelData(accelData_da.cnt); ad++ ) + if ( event->keyval == accelKeyMap[ad->key] && + modifier == ad->modifier ) + return ad; + return NULL; +} + + +EXPORT wBool_t gtkHandleAccelKey( + GdkEventKey *event ) +{ + accelData_t * ad = gtkFindAccelKey( event ); + if ( ad ) { + ad->action( ad->key, ad->data ); + return TRUE; + } + return FALSE; +} + +/* + ***************************************************************************** + * + * Timer Functions + * + ***************************************************************************** + */ + +static wBool_t gtkPaused = FALSE; +static int alarmTimer = 0; + +static gint doAlarm( + gpointer data ) +{ + wAlarmCallBack_p func = (wAlarmCallBack_p)data; + if (alarmTimer) + gtk_timeout_remove( alarmTimer ); + func(); + alarmTimer = 0; + return 0; +} + + +EXPORT void wAlarm( + long count, + wAlarmCallBack_p func ) /* milliseconds */ +/* +Alarm for <count> milliseconds. +*/ +{ + gtkPaused = TRUE; + if (alarmTimer) + gtk_timeout_remove( alarmTimer ); + alarmTimer = gtk_timeout_add( count, doAlarm, (void *) (GtkFunction)func ); +} + + +static wControl_p triggerControl = NULL; +static setTriggerCallback_p triggerFunc = NULL; + +static void doTrigger( void ) +{ + if (triggerControl && triggerFunc) { + triggerFunc( triggerControl ); + triggerFunc = NULL; + triggerControl = NULL; + } +} + +void gtkSetTrigger( + wControl_p b, + setTriggerCallback_p trigger ) +{ + triggerControl = b; + triggerFunc = trigger; + wAlarm( 500, doTrigger ); +} + + +EXPORT void wPause( + long count ) /* milliseconds */ +/* +Pause for <count> milliseconds. +*/ +{ + struct timeval timeout; + sigset_t signal_mask; + sigset_t oldsignal_mask; + + gdk_display_sync(gdk_display_get_default()); + + timeout.tv_sec = count/1000; + timeout.tv_usec = (count%1000)*1000; + + sigemptyset( &signal_mask ); + sigaddset( &signal_mask, SIGIO ); + sigaddset( &signal_mask, SIGALRM ); + sigprocmask( SIG_BLOCK, &signal_mask, &oldsignal_mask ); + + if (select( 0, NULL, NULL, NULL, &timeout ) == -1) { + perror("wPause:select"); + } + sigprocmask( SIG_BLOCK, &oldsignal_mask, NULL ); +} + + +unsigned long wGetTimer( void ) +{ + struct timeval tv; + struct timezone tz; + int rc; + rc = gettimeofday( &tv, &tz ); + return (tv.tv_sec-startTime.tv_sec+1) * 1000 + tv.tv_usec /1000; +} + + + +/** + * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by + * calling wControlLinkedActive for one member of the list + * + * \param b1 IN first control + * \param b2 IN second control + * \return none + */ + +EXPORT void wControlLinkedSet( wControl_p b1, wControl_p b2 ) +{ + + b2->synonym = b1->synonym; + if( b2->synonym == NULL ) + b2->synonym = b1; + + b1->synonym = b2; +} + +/** + * Activate/deactivate a group of synonymous controls. + * + * \param b IN control + * \param active IN state + * \return none + */ + + +EXPORT void wControlLinkedActive( wControl_p b, int active ) +{ + wControl_p savePtr = b; + + if( savePtr->type == B_MENUITEM ) + wMenuPushEnable( (wMenuPush_p)savePtr, active ); + else + wControlActive( savePtr, active ); + + savePtr = savePtr->synonym; + + while( savePtr && savePtr != b ) { + + if( savePtr->type == B_MENUITEM ) + wMenuPushEnable( (wMenuPush_p)savePtr, active ); + else + wControlActive( savePtr, active ); + + savePtr = savePtr->synonym; + } +} + +/* + ***************************************************************************** + * + * Control Utilities + * + ***************************************************************************** + */ + +EXPORT void wControlShow( + wControl_p b, /* Control */ + wBool_t show ) /* Command */ +/* +Cause the control <b> to be displayed or hidden. +Used to hide control (such as a list) while it is being updated. +*/ +{ + if ( b->type == B_LINES ) { + gtkLineShow( (wLine_p)b, show ); + return; + } + if (b->widget == 0) abort(); + if (show) { + gtk_widget_show( b->widget ); + if (b->label) + gtk_widget_show( b->label ); + } else { + gtk_widget_hide( b->widget ); + if (b->label) + gtk_widget_hide( b->label ); + } +} + +EXPORT void wControlActive( + wControl_p b, /* Control */ + int active ) /* Command */ +/* +Cause the control <b> to be marked active or inactive. +Inactive controls donot respond to actions. +*/ +{ + if (b->widget == 0) abort(); + gtk_widget_set_sensitive( GTK_WIDGET(b->widget), active ); +} + + +EXPORT wPos_t wLabelWidth( + const char * label ) /* Label */ +/* +Returns the width of <label>. +This is used for computing window layout. +Typically the width to the longest label is computed and used as +the X-position for <controls>. +*/ +{ + GtkWidget * widget; + GtkRequisition requisition; + widget = gtk_label_new( gtkConvertInput(label) ); + gtk_widget_size_request( widget, &requisition ); + gtk_widget_destroy( widget ); + return requisition.width+8; +} + + +EXPORT wPos_t wControlGetWidth( + wControl_p b) /* Control */ +{ + return b->w; +} + + +EXPORT wPos_t wControlGetHeight( + wControl_p b) /* Control */ +{ + return b->h; +} + + +EXPORT wPos_t wControlGetPosX( + wControl_p b) /* Control */ +{ + return b->realX; +} + + +EXPORT wPos_t wControlGetPosY( + wControl_p b) /* Control */ +{ + return b->realY - FOUR - ((b->parent->option&F_MENUBAR)?MENUH:0); +} + + +EXPORT void wControlSetPos( + wControl_p b, /* Control */ + wPos_t x, /* X-position */ + wPos_t y ) /* Y-position */ +{ + b->realX = x; + b->realY = y + FOUR + ((b->parent->option&F_MENUBAR)?MENUH:0); +#ifndef GTK1 + if (b->widget) + gtk_fixed_move( GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY ); + if (b->label) + gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); +#else + if (b->widget) + gtk_widget_set_uposition( b->widget, b->realX, b->realY ); + if (b->label) + gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); +#endif +} + + +EXPORT void wControlSetLabel( + wControl_p b, + const char * labelStr ) +{ + GtkRequisition requisition; + if (b->label) { + gtk_label_set( GTK_LABEL(b->label), gtkConvertInput(labelStr) ); + gtk_widget_size_request( b->label, &requisition ); + b->labelW = requisition.width+8; +#ifndef GTK1 + gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); +#else + gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET ); +#endif + } else { + b->labelW = gtkAddLabel( b, labelStr ); + } +} + +EXPORT void wControlSetContext( + wControl_p b, + void * context ) +{ + b->data = context; +} + + +EXPORT void wControlSetFocus( + wControl_p b ) +{ +} + + +static int gtkControlHiliteWidth = 3; +EXPORT void wControlHilite( + wControl_p b, + wBool_t hilite ) +{ + int off = gtkControlHiliteWidth/2+1; + if ( b->parent->gc == NULL ) { + b->parent->gc = gdk_gc_new( b->parent->gtkwin->window ); + gdk_gc_copy( b->parent->gc, b->parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] ); + b->parent->gc_linewidth = 0; + gdk_gc_set_line_attributes( b->parent->gc, b->parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); + } + if ( b->widget == NULL ) + return; + if ( ! GTK_WIDGET_VISIBLE( b->widget ) ) + return; + if ( ! GTK_WIDGET_VISIBLE( b->parent->widget ) ) + return; + gdk_gc_set_foreground( b->parent->gc, gtkGetColor( wDrawColorBlack, FALSE ) ); + gdk_gc_set_function( b->parent->gc, GDK_XOR ); + gdk_gc_set_line_attributes( b->parent->gc, gtkControlHiliteWidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER ); + gdk_draw_line( b->parent->widget->window, b->parent->gc, + b->realX - gtkControlHiliteWidth, + b->realY - off, + b->realX + b->w + gtkControlHiliteWidth, + b->realY - off ); + gdk_draw_line( b->parent->widget->window, b->parent->gc, + b->realX - gtkControlHiliteWidth, + b->realY + b->h + off - 1, + b->realX + b->w + gtkControlHiliteWidth, + b->realY + b->h + off - 1 ); + gdk_draw_line( b->parent->widget->window, b->parent->gc, + b->realX - off, + b->realY, + b->realX - off, + b->realY + b->h ); + gdk_draw_line( b->parent->widget->window, b->parent->gc, + b->realX + b->w + off - 1, + b->realY, + b->realX + b->w + off - 1, + b->realY + b->h ); +} + +/* + ******************************************************************************* + * + * Main + * + ******************************************************************************* + */ + +#ifdef GTK +static wBool_t wAbortOnErrors = FALSE; +#endif + +int do_rgb_init = 1; + +int main( int argc, char *argv[] ) +{ + wWin_p win; + wControl_p b; + const char *ld, *hp; + static char buff[BUFSIZ]; + + if ( getenv( "GTKLIB_NOLOCALE" ) == 0 ) + setlocale( LC_ALL, "en_US" ); + gtk_init( &argc, &argv ); + gettimeofday( &startTime, NULL ); + + if ( getenv( "XVLIB_REVERSEICON" ) != 0 ) + reverseIcon = !reverseIcon; + + if ( do_rgb_init ) + gdk_rgb_init(); /* before we try to draw */ + + if ((win=wMain( argc, argv )) == (wWin_p)0) + exit(1); + + ld = wGetAppLibDir(); + if (ld != NULL) { + sprintf( buff, "HELPPATH=/usr/lib/help:%s:", ld ); + if ( (hp = getenv("HELPPATH")) != NULL ) + strcat( buff, hp ); + putenv( buff ); + } + + if (!win->shown) + wWinShow( win, TRUE ); + for (b=win->first; b != NULL; b = b->next) { + if (b->repaintProc) + b->repaintProc( b ); + } + gtk_main(); + exit(0); +} |