/** \file gtktext.c * Multi line text entry */ /* XTrkCad - Model Railroad CAD * Copyright (C) 2005 Dave Bullis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define GTK_ENABLE_BROKEN #include #include #include #include "gtkint.h" /* * Disable USE_TEXTVIEW to use the deprecated gtk_text */ #define USE_TEXTVIEW /* ***************************************************************************** * * Multi-line Text Boxes * ***************************************************************************** */ struct wText_t { WOBJ_COMMON wPos_t width, height; int changed; GtkWidget * text; GtkWidget * vscroll; }; EXPORT void wTextClear( wText_p bt ) { #ifdef USE_TEXTVIEW GtkTextBuffer * tb; #endif if (bt->text == 0) abort(); #ifdef USE_TEXTVIEW tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); gtk_text_buffer_set_text( tb, "", -1 ); if (bt->option & BO_READONLY) gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); #else gtk_text_set_point( GTK_TEXT(bt->text), 0 ); gtk_text_forward_delete( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) ) ); if (bt->option & BO_READONLY) gtk_text_set_editable( GTK_TEXT(bt->text), FALSE ); #endif bt->changed = FALSE; } /** * 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 ) { #ifdef USE_TEXTVIEW GtkTextBuffer * tb; GtkTextIter ti1, ti2; // PangoFontDescription *pfd; #else static GdkFont * fixedRegularFont = NULL; static GdkFont * fixedBoldFont = NULL; static GdkFont * variableRegularFont = NULL; static GdkFont * variableBoldFont = NULL; GdkFont * regularFont = NULL; GdkFont * boldFont = NULL; #endif wBool_t doBold; char * cp; int len; if (bt->text == 0) abort(); #ifdef USE_TEXTVIEW tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); //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) fixedRegularFont = gdk_font_load( "-*-courier-medium-r-*-*-12-*-*-*-*-*-iso8859-*" ); if (fixedBoldFont==NULL) fixedBoldFont = gdk_font_load( "-*-courier-bold-r-*-*-12-*-*-*-*-*-iso8859-*" ); regularFont = fixedRegularFont; boldFont = fixedBoldFont; } else { if (variableRegularFont==NULL) variableRegularFont = gdk_font_load( "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-*" ); if (variableBoldFont==NULL) variableBoldFont = gdk_font_load( "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-*" ); regularFont = variableRegularFont; boldFont = variableBoldFont; } #endif /*gtk_text_freeze( GTK_TEXT (bt->text) );*/ doBold = FALSE; text = gtkConvertInput( text ); while ( text && *text ) { if ( (bt->option & BT_DOBOLD) != 0 && ( cp = strchr( text, doBold?'>':'<' ) ) != NULL ) { len = cp-text; cp++; } else { len = -1; cp = NULL; } if ( len != 0 ) { #ifdef USE_TEXTVIEW gtk_text_buffer_get_bounds( tb, &ti1, &ti2 ); if ( !doBold ) gtk_text_buffer_insert( tb, &ti2, text, len ); else gtk_text_buffer_insert_with_tags_by_name( tb, &ti2, text, len, "bold", NULL ); #else gtk_text_insert( GTK_TEXT(bt->text), doBold?boldFont:regularFont, &bt->text->style->black, NULL, text, len ); #endif } text = cp; doBold = !doBold; } /*gtk_text_set_point( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) )-1 );*/ /*gtk_text_thaw( GTK_TEXT (bt->text) );*/ bt->changed = FALSE; } EXPORT void gtkTextFreeze( wText_p bt ) { #ifdef USE_TEXTVIEW gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); #else gtk_text_freeze( GTK_TEXT (bt->text) ); #endif } EXPORT void gtkTextThaw( wText_p bt ) { #ifdef USE_TEXTVIEW gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), TRUE ); #else gtk_text_thaw( GTK_TEXT (bt->text) ); #endif } EXPORT void wTextReadFile( wText_p bt, const char * fileName ) { FILE * f; char buff[BUFSIZ+1]; if (fileName) { f = fopen( fileName, "r" ); if (f == NULL) { perror( fileName ); return; } while (fgets( buff, sizeof buff, f ) != NULL ) { wTextAppend( bt, buff ); } } } #ifdef USE_TEXTVIEW static char * gtkGetText( wText_p bt ) { GtkTextBuffer * tb; GtkTextIter ti1, ti2; char * cp; if (bt->text == 0) abort(); tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); gtk_text_buffer_get_bounds( tb, &ti1, &ti2 ); cp = gtk_text_buffer_get_text( tb, &ti1, &ti2, FALSE ); cp = gtkConvertOutput( cp ); return cp; } #endif EXPORT wBool_t wTextSave( wText_p bt, const char * fileName ) { #ifndef USE_TEXTVIEW int siz, pos, cnt; #endif FILE * f; char * cp; f = fopen( fileName, "w" ); if (f==NULL) { wNoticeEx( NT_ERROR, fileName, "Ok", NULL ); return FALSE; } #ifdef USE_TEXTVIEW cp = gtkGetText( bt ); fwrite( cp, 1, strlen(cp), f ); free(cp); #else siz = gtk_text_get_length( GTK_TEXT(bt->text) ); pos = 0; cnt = BUFSIZ; while (possiz) cnt = siz-pos; cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), pos, pos+cnt ); if (cp == NULL) break; fwrite( cp, 1, cnt, f ); free(cp); pos += cnt; } #endif fclose(f); return TRUE; } 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; } #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; } #endif wPrinterClose(f); return TRUE; } EXPORT int wTextGetSize( wText_p bt ) { #ifdef USE_TEXTVIEW char * cp = gtkGetText( bt ); int len = strlen( cp ); free( cp ); return len; #else return (int)gtk_text_get_length( GTK_TEXT(bt->text) ); #endif } EXPORT void wTextGetText( wText_p bt, char * text, int len ) { char * cp; #ifdef USE_TEXTVIEW cp = gtkGetText(bt); strncpy( text, cp, len ); free( cp ); #else cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), 0, len ); strncpy( text, cp, len ); #endif } EXPORT void wTextSetReadonly ( wText_p bt, wBool_t ro ) { #ifdef USE_TEXTVIEW gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), !ro ); #else gtk_text_set_editable( GTK_TEXT(bt->text), !ro ); #endif if (ro) { bt->option |= BO_READONLY; } else { bt->option &= ~BO_READONLY; } } EXPORT wBool_t wTextGetModified( wText_p bt ) { return bt->changed; } EXPORT void wTextSetSize( wText_p bt, wPos_t w, wPos_t h ) { #ifdef USE_TEXTVIEW gtk_widget_set_size_request( bt->widget, w, h ); // gtk_widget_set_size_request( bt->text, w-15, h ); // gtk_widget_set_size_request( bt->vscroll, 15, h ); #else gtk_widget_set_usize( bt->widget, w, h ); gtk_widget_set_usize( bt->text, w-15, h ); gtk_widget_set_usize( bt->vscroll, 15, h ); gtk_widget_queue_resize( GTK_WIDGET(bt->widget) ); gtk_widget_queue_resize( GTK_WIDGET(bt->text) ); gtk_widget_queue_resize( GTK_WIDGET(bt->vscroll) ); #endif bt->w = w; bt->h = h; } EXPORT void wTextComputeSize( wText_p bt, int rows, int cols, wPos_t *width, wPos_t *height ) { *width = rows * 7; *height = cols * 14; } EXPORT void wTextSetPosition( wText_p bt, int pos ) { #ifdef USE_TEXTVIEW /* TODO */ #else GTK_TEXT(bt->text)->first_line_start_index = pos; gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE ); gtk_text_set_point( GTK_TEXT(bt->text), pos ); #endif } static void textChanged( GtkWidget * widget, wText_p bt ) { if (bt == 0) return; bt->changed = TRUE; } /** * 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, wPos_t y, const char * helpStr, const char * labelStr, long option, wPos_t width, wPos_t height ) { wText_p bt; #ifdef USE_TEXTVIEW GtkTextBuffer * tb; PangoFontDescription *pfd; #else GtkRequisition requisition; #endif bt = gtkAlloc( parent, B_MULTITEXT, x, y, labelStr, sizeof *bt, NULL ); gtkComputePos( (wControl_p)bt ); bt->width = width; bt->height = height; bt->option = option; gtkComputePos( (wControl_p)bt ); #ifdef USE_TEXTVIEW bt->widget = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bt->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); bt->text = gtk_text_view_new(); if (bt->text == 0) abort(); gtk_container_add (GTK_CONTAINER (bt->widget), bt->text); tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) ); gtk_text_buffer_create_tag( tb, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); /* gtk_text_buffer_create_tag( tb, "italic", "style", PANGO_STYLE_ITALIC, NULL); */ /* gtk_text_buffer_create_tag( tb, "bolditalic", "weight", PANGO_WEIGHT_BOLD, "style", PANGO_STYLE_ITALIC, NULL); */ 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 bt->widget = gtk_hbox_new( FALSE, 0 ); bt->text = gtk_text_new( NULL, NULL ); if (bt->text == 0) abort(); gtk_box_pack_start( GTK_BOX(bt->widget), bt->text, FALSE, FALSE, 0 ); bt->vscroll = gtk_vscrollbar_new( GTK_TEXT(bt->text)->vadj ); if (bt->vscroll == 0) abort(); gtk_box_pack_start( GTK_BOX(bt->widget), bt->vscroll, FALSE, FALSE, 0 ); #endif if (option&BT_CHARUNITS) { width *= 7; height *= 14; } gtk_widget_show( bt->text ); gtk_widget_show( bt->vscroll ); gtk_widget_show( bt->widget ); #ifdef USE_TEXTVIEW // gtk_widget_set_size_request( GTK_WIDGET(bt->text), width, height ); // gtk_widget_set_size_request( GTK_WIDGET(bt->vscroll), -1, height ); gtk_widget_set_size_request( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height ); #else gtk_widget_set_usize( GTK_WIDGET(bt->text), width, height ); gtk_widget_set_usize( GTK_WIDGET(bt->vscroll), -1, height ); gtk_widget_size_request( GTK_WIDGET(bt->vscroll), &requisition ); gtk_widget_set_usize( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height ); #endif if (bt->option&BO_READONLY) { #ifdef USE_TEXTVIEW gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE ); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(bt->text), FALSE); #else gtk_text_set_editable( GTK_TEXT(bt->text), FALSE ); #endif } #ifdef USE_TEXTVIEW gtk_fixed_put( GTK_FIXED(parent->widget), bt->widget, bt->realX, bt->realY ); #else gtk_container_add( GTK_CONTAINER(parent->widget), bt->widget ); gtk_widget_set_uposition( bt->widget, bt->realX, bt->realY ); #endif gtkControlGetSize( (wControl_p)bt ); if (labelStr) bt->labelW = gtkAddLabel( (wControl_p)bt, labelStr ); #ifdef USE_TEXTVIEW gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(bt->text), GTK_WRAP_WORD ); #else gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE ); #endif gtk_widget_realize( bt->text ); gtkAddButton( (wControl_p)bt ); gtkAddHelpString( bt->widget, helpStr ); #ifdef USE_TEXTVIEW g_signal_connect( G_OBJECT(tb), "changed", GTK_SIGNAL_FUNC(textChanged), bt ); #else gtk_signal_connect( GTK_OBJECT(bt->text), "changed", GTK_SIGNAL_FUNC(textChanged), bt ); #endif return bt; }