/** \file * \brief Text Control * * See Copyright Notice in "iup.h" */ #include #include #include #include #include #include #include "iup.h" #include "iupcbs.h" #include "iup_object.h" #include "iup_layout.h" #include "iup_attrib.h" #include "iup_str.h" #include "iup_image.h" #include "iup_mask.h" #include "iup_drv.h" #include "iup_drvfont.h" #include "iup_image.h" #include "iup_key.h" #include "iup_array.h" #include "iup_text.h" #include "iupgtk_drv.h" #ifndef PANGO_WEIGHT_SEMIBOLD #define PANGO_WEIGHT_SEMIBOLD 600 #endif void iupdrvTextAddSpin(int *w, int h) { int spin_size = 16; *w += spin_size; (void)h; } void iupdrvTextAddBorders(int *x, int *y) { int border_size = 2*5; (*x) += border_size; (*y) += border_size; } static void gtkTextParseParagraphFormat(Ihandle* formattag, GtkTextTag* tag) { int val; char* format; format = iupAttribGet(formattag, "INDENT"); if (format && iupStrToInt(format, &val)) g_object_set(G_OBJECT(tag), "indent", val, NULL); format = iupAttribGet(formattag, "ALIGNMENT"); if (format) { if (iupStrEqualNoCase(format, "JUSTIFY")) val = GTK_JUSTIFY_FILL; else if (iupStrEqualNoCase(format, "RIGHT")) val = GTK_JUSTIFY_RIGHT; else if (iupStrEqualNoCase(format, "CENTER")) val = GTK_JUSTIFY_CENTER; else /* "LEFT" */ val = GTK_JUSTIFY_LEFT; g_object_set(G_OBJECT(tag), "justification", val, NULL); } format = iupAttribGet(formattag, "TABSARRAY"); { PangoTabArray *tabs; int pos, i = 0; PangoTabAlign align; char* str; tabs = pango_tab_array_new(32, FALSE); while (format) { str = iupStrCopyUntil((char**)&format, ' '); if (!str) break; pos = atoi(str); free(str); str = iupStrCopyUntil((char**)&format, ' '); if (!str) break; /* if (iupStrEqualNoCase(str, "DECIMAL")) unsupported for now align = PANGO_TAB_NUMERIC; else if (iupStrEqualNoCase(str, "RIGHT")) align = PANGO_TAB_RIGHT; else if (iupStrEqualNoCase(str, "CENTER")) align = PANGO_TAB_CENTER; else */ /* "LEFT" */ align = PANGO_TAB_LEFT; free(str); pango_tab_array_set_tab(tabs, i, align, iupGTK_PIXELS2PANGOUNITS(pos)); i++; if (i == 32) break; } g_object_set(G_OBJECT(tag), "tabs", tabs, NULL); pango_tab_array_free(tabs); } format = iupAttribGet(formattag, "SPACEBEFORE"); if (format && iupStrToInt(format, &val)) g_object_set(G_OBJECT(tag), "pixels-above-lines", val, NULL); format = iupAttribGet(formattag, "SPACEAFTER"); if (format && iupStrToInt(format, &val)) g_object_set(G_OBJECT(tag), "pixels-below-lines", val, NULL); format = iupAttribGet(formattag, "LINESPACING"); if (format && iupStrToInt(format, &val)) g_object_set(G_OBJECT(tag), "pixels-inside-wrap", val, NULL); } static void gtkTextParseCharacterFormat(Ihandle* formattag, GtkTextTag* tag) { int val; char* format; format = iupAttribGet(formattag, "LANGUAGE"); if (format) g_object_set(G_OBJECT(tag), "language", format, NULL); format = iupAttribGet(formattag, "STRETCH"); if (format) { if (iupStrEqualNoCase(format, "EXTRA_CONDENSED")) val = PANGO_STRETCH_EXTRA_CONDENSED; else if (iupStrEqualNoCase(format, "CONDENSED")) val = PANGO_STRETCH_CONDENSED; else if (iupStrEqualNoCase(format, "SEMI_CONDENSED")) val = PANGO_STRETCH_SEMI_CONDENSED; else if (iupStrEqualNoCase(format, "SEMI_EXPANDED")) val = PANGO_STRETCH_SEMI_EXPANDED; else if (iupStrEqualNoCase(format, "EXPANDED")) val = PANGO_STRETCH_EXPANDED; else if (iupStrEqualNoCase(format, "EXTRA_EXPANDED")) val = PANGO_STRETCH_EXTRA_EXPANDED; else /* "NORMAL" */ val = PANGO_STRETCH_NORMAL; g_object_set(G_OBJECT(tag), "stretch", val, NULL); } format = iupAttribGet(formattag, "RISE"); if (format) { val = 0; if (iupStrEqualNoCase(format, "SUPERSCRIPT")) { g_object_set(G_OBJECT(tag), "scale", PANGO_SCALE_X_SMALL, NULL); val = 10; /* 10 pixels up */ } else if (iupStrEqualNoCase(format, "SUBSCRIPT")) { g_object_set(G_OBJECT(tag), "scale", PANGO_SCALE_X_SMALL, NULL); val = -10; /* 10 pixels down */ } else iupStrToInt(format, &val); val = iupGTK_PIXELS2PANGOUNITS(val); g_object_set(G_OBJECT(tag), "rise", val, NULL); } format = iupAttribGet(formattag, "SMALLCAPS"); if (format) { if (iupStrBoolean(format)) val = PANGO_VARIANT_SMALL_CAPS; else val = PANGO_VARIANT_NORMAL; g_object_set(G_OBJECT(tag), "variant", val, NULL); } format = iupAttribGet(formattag, "ITALIC"); if (format) { if (iupStrBoolean(format)) val = PANGO_STYLE_ITALIC; else val = PANGO_STYLE_NORMAL; g_object_set(G_OBJECT(tag), "style", val, NULL); } format = iupAttribGet(formattag, "STRIKEOUT"); if (format) { val = iupStrBoolean(format); g_object_set(G_OBJECT(tag), "strikethrough", val, NULL); } format = iupAttribGet(formattag, "PROTECTED"); if (format) { val = iupStrBoolean(format); g_object_set(G_OBJECT(tag), "editable", val, NULL); } format = iupAttribGet(formattag, "FONTSIZE"); if (format && iupStrToInt(format, &val)) { if (val < 0) /* in pixels */ { val = iupGTK_PIXELS2PANGOUNITS(-val); g_object_set(G_OBJECT(tag), "size", val, NULL); } else /* in points */ g_object_set(G_OBJECT(tag), "size-points", (double)val, NULL); } format = iupAttribGet(formattag, "FONTSCALE"); if (format) { float fval = 0; if (iupStrEqualNoCase(format, "XX-SMALL")) fval = (float)PANGO_SCALE_XX_SMALL; else if (iupStrEqualNoCase(format, "X-SMALL")) fval = (float)PANGO_SCALE_X_SMALL; else if (iupStrEqualNoCase(format, "SMALL")) fval = (float)PANGO_SCALE_SMALL; else if (iupStrEqualNoCase(format, "MEDIUM")) fval = (float)PANGO_SCALE_MEDIUM; else if (iupStrEqualNoCase(format, "LARGE")) fval = (float)PANGO_SCALE_LARGE; else if (iupStrEqualNoCase(format, "X-LARGE")) fval = (float)PANGO_SCALE_X_LARGE; else if (iupStrEqualNoCase(format, "XX-LARGE")) fval = (float)PANGO_SCALE_XX_LARGE; else iupStrToFloat(format, &fval); if (fval > 0) g_object_set(G_OBJECT(tag), "scale", (double)fval, NULL); } format = iupAttribGet(formattag, "FONTFACE"); if (format) g_object_set(G_OBJECT(tag), "family", format, NULL); format = iupAttribGet(formattag, "FGCOLOR"); if (format) { unsigned char r, g, b; if (iupStrToRGB(format, &r, &g, &b)) { GdkColor color; iupgdkColorSet(&color, r, g, b); g_object_set(G_OBJECT(tag), "foreground-gdk", &color, NULL); } } format = iupAttribGet(formattag, "BGCOLOR"); if (format) { unsigned char r, g, b; if (iupStrToRGB(format, &r, &g, &b)) { GdkColor color; iupgdkColorSet(&color, r, g, b); g_object_set(G_OBJECT(tag), "background-gdk", &color, NULL); } } format = iupAttribGet(formattag, "UNDERLINE"); if (format) { if (iupStrEqualNoCase(format, "SINGLE")) val = PANGO_UNDERLINE_SINGLE; else if (iupStrEqualNoCase(format, "DOUBLE")) val = PANGO_UNDERLINE_DOUBLE; else /* "NONE" */ val = PANGO_UNDERLINE_NONE; g_object_set(G_OBJECT(tag), "underline", val, NULL); } format = iupAttribGet(formattag, "WEIGHT"); if (format) { if (iupStrEqualNoCase(format, "EXTRALIGHT")) val = PANGO_WEIGHT_ULTRALIGHT; else if (iupStrEqualNoCase(format, "LIGHT")) val = PANGO_WEIGHT_LIGHT; else if (iupStrEqualNoCase(format, "SEMIBOLD")) val = PANGO_WEIGHT_SEMIBOLD; else if (iupStrEqualNoCase(format, "BOLD")) val = PANGO_WEIGHT_BOLD; else if (iupStrEqualNoCase(format, "EXTRABOLD")) val = PANGO_WEIGHT_ULTRABOLD; else if (iupStrEqualNoCase(format, "HEAVY")) val = PANGO_WEIGHT_HEAVY; else /* "NORMAL" */ val = PANGO_WEIGHT_NORMAL; g_object_set(G_OBJECT(tag), "weight", val, NULL); } } static void gtkTextMoveIterToLinCol(GtkTextBuffer *buffer, GtkTextIter *iter, int lin, int col) { int line_count, line_length; lin--; /* IUP starts at 1 */ col--; line_count = gtk_text_buffer_get_line_count(buffer); if (lin < 0) lin = 0; if (lin >= line_count) lin = line_count-1; gtk_text_buffer_get_iter_at_line(buffer, iter, lin); line_length = gtk_text_iter_get_chars_in_line(iter); if (col < 0) col = 0; if (col > line_length) col = line_length; /* after the last character */ gtk_text_iter_set_line_offset(iter, col); } static void gtkTextGetLinColFromPosition(const GtkTextIter *iter, int *lin, int *col) { *lin = gtk_text_iter_get_line(iter); *col = gtk_text_iter_get_line_offset(iter); (*lin)++; /* IUP starts at 1 */ (*col)++; } static int gtkTextGetCharSize(Ihandle* ih) { int charwidth; PangoFontMetrics* metrics; PangoContext* context; PangoFontDescription* fontdesc = (PangoFontDescription*)iupgtkGetPangoFontDescAttrib(ih); if (!fontdesc) return 0; context = gdk_pango_context_get(); metrics = pango_context_get_metrics(context, fontdesc, pango_context_get_language(context)); charwidth = pango_font_metrics_get_approximate_char_width(metrics); pango_font_metrics_unref(metrics); return charwidth; } void iupdrvTextConvertLinColToPos(Ihandle* ih, int lin, int col, int *pos) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtkTextMoveIterToLinCol(buffer, &iter, lin, col); *pos = gtk_text_iter_get_offset(&iter); } void iupdrvTextConvertPosToLinCol(Ihandle* ih, int pos, int *lin, int *col) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_offset(buffer, &iter, pos); gtkTextGetLinColFromPosition(&iter, lin, col); } static int gtkTextConvertXYToPos(Ihandle* ih, int x, int y) { if (ih->data->is_multiline) { GtkTextIter iter; gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(ih->handle), GTK_TEXT_WINDOW_WIDGET, x, y, &x, &y); gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(ih->handle), &iter, x, y); return gtk_text_iter_get_offset(&iter); } else { int trailing, off_x, off_y, pos; /* transform to Layout coordinates */ gtk_entry_get_layout_offsets(GTK_ENTRY(ih->handle), &off_x, &off_y); x = iupGTK_PIXELS2PANGOUNITS(x - off_x); y = iupGTK_PIXELS2PANGOUNITS(y - off_y); pango_layout_xy_to_index(gtk_entry_get_layout(GTK_ENTRY(ih->handle)), x, y, &pos, &trailing); return pos; } } static void gtkTextScrollToVisible(Ihandle* ih) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); GtkTextMark* mark = gtk_text_buffer_get_insert(buffer); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(ih->handle), mark); } /*******************************************************************************************/ static int gtkTextSelectionAttribToIter(Ihandle* ih, const char* value, GtkTextIter* start_iter, GtkTextIter* end_iter) { int lin_start=1, col_start=1, lin_end=1, col_end=1; GtkTextBuffer *buffer; if (!value || !ih->data->is_multiline) return 0; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (!value || iupStrEqualNoCase(value, "NONE")) { gtk_text_buffer_get_start_iter(buffer, start_iter); gtk_text_buffer_get_start_iter(buffer, end_iter); return 1; } if (iupStrEqualNoCase(value, "ALL")) { gtk_text_buffer_get_start_iter(buffer, start_iter); gtk_text_buffer_get_end_iter(buffer, end_iter); return 1; } if (sscanf(value, "%d,%d:%d,%d", &lin_start, &col_start, &lin_end, &col_end)!=4) return 0; if (lin_start<1 || col_start<1 || lin_end<1 || col_end<1) return 0; gtkTextMoveIterToLinCol(buffer, start_iter, lin_start, col_start); gtkTextMoveIterToLinCol(buffer, end_iter, lin_end, col_end); return 1; } static int gtkTextSetSelectionAttrib(Ihandle* ih, const char* value) { int start=1, end=1; if (!value) return 0; if (ih->data->is_multiline) { GtkTextIter start_iter, end_iter; if (gtkTextSelectionAttribToIter(ih, value, &start_iter, &end_iter)) gtk_text_buffer_select_range(buffer, &start_iter, &start_iter); return 0; } if (iupStrEqualNoCase(value, "NONE")) { gtk_editable_select_region(GTK_EDITABLE(ih->handle), 0, 0); return 0; } if (iupStrEqualNoCase(value, "ALL")) { gtk_editable_select_region(GTK_EDITABLE(ih->handle), 0, -1); return 0; } if (iupStrToIntInt(value, &start, &end, ':')!=2) return 0; if(start<1 || end<1) return 0; start--; /* IUP starts at 1 */ end--; gtk_editable_select_region(GTK_EDITABLE(ih->handle), start, end); return 0; } static char* gtkTextGetSelectionAttrib(Ihandle* ih) { char *str; if (ih->data->is_multiline) { int start_col, start_lin, end_col, end_lin; GtkTextIter start_iter, end_iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter)) { gtkTextGetLinColFromPosition(&start_iter, &start_lin, &start_col); gtkTextGetLinColFromPosition(&end_iter, &end_lin, &end_col); str = iupStrGetMemory(100); sprintf(str,"%d,%d:%d,%d", start_lin, start_col, end_lin, end_col); return str; } } else { int start, end; if (gtk_editable_get_selection_bounds(GTK_EDITABLE(ih->handle), &start, &end)) { start++; /* IUP starts at 1 */ end++; str = iupStrGetMemory(100); sprintf(str, "%d:%d", (int)start, (int)end); return str; } } return NULL; } static int gtkTextSelectionPosAttribToIter(Ihandle* ih, const char* value, GtkTextIter* start_iter, GtkTextIter* end_iter) { int start=0, end=0; GtkTextBuffer *buffer; if (!value || !ih->data->is_multiline) return 0; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (!value || iupStrEqualNoCase(value, "NONE")) { gtk_text_buffer_get_start_iter(buffer, start_iter); gtk_text_buffer_get_start_iter(buffer, end_iter); return 1; } if (iupStrEqualNoCase(value, "ALL")) { gtk_text_buffer_get_start_iter(buffer, start_iter); gtk_text_buffer_get_end_iter(buffer, end_iter); return 1; } if (iupStrToIntInt(value, &start, &end, ':')!=2) return 0; if(start<0 || end<0) return 0; gtk_text_buffer_get_iter_at_offset(buffer, start_iter, start); gtk_text_buffer_get_iter_at_offset(buffer, end_iter, end); return 1; } static int gtkTextSetSelectionPosAttrib(Ihandle* ih, const char* value) { int start=0, end=0; if (!value) return 0; if (ih->data->is_multiline) { GtkTextIter start_iter, end_iter; if (gtkTextSelectionPosAttribToIter(ih, value, &start_iter, &end_iter)) gtk_text_buffer_select_range(buffer, &start_iter, &start_iter); return 0; } if (iupStrEqualNoCase(value, "NONE")) { gtk_editable_select_region(GTK_EDITABLE(ih->handle), 0, 0); return 0; } if (iupStrEqualNoCase(value, "ALL")) { gtk_editable_select_region(GTK_EDITABLE(ih->handle), 0, -1); return 0; } if (iupStrToIntInt(value, &start, &end, ':')!=2) return 0; if(start<0 || end<0) return 0; gtk_editable_select_region(GTK_EDITABLE(ih->handle), start, end); return 0; } static char* gtkTextGetSelectionPosAttrib(Ihandle* ih) { int start, end; char *str; if (ih->data->is_multiline) { GtkTextIter start_iter, end_iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter)) { start = gtk_text_iter_get_offset(&start_iter); end = gtk_text_iter_get_offset(&end_iter); str = iupStrGetMemory(100); sprintf(str, "%d:%d", (int)start, (int)end); return str; } } else { if (gtk_editable_get_selection_bounds(GTK_EDITABLE(ih->handle), &start, &end)) { str = iupStrGetMemory(100); sprintf(str, "%d:%d", (int)start, (int)end); return str; } } return NULL; } static int gtkTextSetSelectedTextAttrib(Ihandle* ih, const char* value) { if (!value) return 0; if (ih->data->is_multiline) { GtkTextIter start_iter, end_iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter)) { /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); gtk_text_buffer_delete(buffer, &start_iter, &end_iter); gtk_text_buffer_insert(buffer, &start_iter, iupgtkStrConvertToUTF8(value), -1); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); } } else { int start, end; if (gtk_editable_get_selection_bounds(GTK_EDITABLE(ih->handle), &start, &end)) { /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); gtk_editable_delete_selection(GTK_EDITABLE(ih->handle)); gtk_editable_insert_text(GTK_EDITABLE(ih->handle), iupgtkStrConvertToUTF8(value), -1, &start); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); } } return 0; } static char* gtkTextGetSelectedTextAttrib(Ihandle* ih) { if (ih->data->is_multiline) { GtkTextIter start_iter, end_iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter)) return iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, TRUE))); } else { int start, end; if (gtk_editable_get_selection_bounds(GTK_EDITABLE(ih->handle), &start, &end)) { char* selectedtext = gtk_editable_get_chars(GTK_EDITABLE(ih->handle), start, end); char* str = iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(selectedtext)); g_free(selectedtext); return str; } } return NULL; } static int gtkTextSetCaretAttrib(Ihandle* ih, const char* value) { int pos = 1; if (!value) return 0; if (ih->data->is_multiline) { int lin = 1, col = 1; GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); iupStrToIntInt(value, &lin, &col, ','); gtkTextMoveIterToLinCol(buffer, &iter, lin, col); gtk_text_buffer_place_cursor(buffer, &iter); gtkTextScrollToVisible(ih); } else { sscanf(value,"%i",&pos); pos--; /* IUP starts at 1 */ if (pos < 0) pos = 0; gtk_editable_set_position(GTK_EDITABLE(ih->handle), pos); } return 0; } static char* gtkTextGetCaretAttrib(Ihandle* ih) { char* str = iupStrGetMemory(50); if (ih->data->is_multiline) { int col, lin; GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer)); gtkTextGetLinColFromPosition(&iter, &lin, &col); sprintf(str, "%d,%d", lin, col); } else { int pos = gtk_editable_get_position(GTK_EDITABLE(ih->handle)); pos++; /* IUP starts at 1 */ sprintf(str, "%d", (int)pos); } return str; } static int gtkTextSetCaretPosAttrib(Ihandle* ih, const char* value) { int pos = 0; if (!value) return 0; sscanf(value,"%i",&pos); if (pos < 0) pos = 0; if (ih->data->is_multiline) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_offset(buffer, &iter, pos); gtk_text_buffer_place_cursor(buffer, &iter); gtkTextScrollToVisible(ih); } else gtk_editable_set_position(GTK_EDITABLE(ih->handle), pos); return 0; } static char* gtkTextGetCaretPosAttrib(Ihandle* ih) { int pos; char* str = iupStrGetMemory(50); if (ih->data->is_multiline) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer)); pos = gtk_text_iter_get_offset(&iter); } else pos = gtk_editable_get_position(GTK_EDITABLE(ih->handle)); sprintf(str, "%d", (int)pos); return str; } static int gtkTextSetScrollToAttrib(Ihandle* ih, const char* value) { if (!value) return 0; if (ih->data->is_multiline) { int lin = 1, col = 1; GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); iupStrToIntInt(value, &lin, &col, ','); if (lin < 1) lin = 1; if (col < 1) col = 1; gtkTextMoveIterToLinCol(buffer, &iter, lin, col); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ih->handle), &iter, 0, FALSE, 0, 0); } else { int pos = 1; sscanf(value,"%i",&pos); if (pos < 1) pos = 1; pos--; /* return to GTK referece */ gtk_editable_set_position(GTK_EDITABLE(ih->handle), pos); } return 0; } static int gtkTextSetScrollToPosAttrib(Ihandle* ih, const char* value) { int pos = 0; if (!value) return 0; sscanf(value,"%i",&pos); if (pos < 0) pos = 0; if (ih->data->is_multiline) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_offset(buffer, &iter, pos); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ih->handle), &iter, 0, FALSE, 0, 0); } else gtk_editable_set_position(GTK_EDITABLE(ih->handle), pos); return 0; } static int gtkTextSetValueAttrib(Ihandle* ih, const char* value) { if (!value) value = ""; /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_set_text(buffer, iupgtkStrConvertToUTF8(value), -1); } else gtk_entry_set_text(GTK_ENTRY(ih->handle), iupgtkStrConvertToUTF8(value)); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); return 0; } static char* gtkTextGetValueAttrib(Ihandle* ih) { char* value; if (ih->data->is_multiline) { GtkTextIter start_iter; GtkTextIter end_iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_start_iter(buffer, &start_iter); gtk_text_buffer_get_end_iter(buffer, &end_iter); value = iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, TRUE))); } else value = iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(gtk_entry_get_text(GTK_ENTRY(ih->handle)))); if (!value) value = ""; return value; } static int gtkTextSetInsertAttrib(Ihandle* ih, const char* value) { if (!ih->handle) /* do not do the action before map */ return 0; if (!value) return 0; /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_insert_at_cursor(buffer, iupgtkStrConvertToUTF8(value), -1); } else { gint pos = gtk_editable_get_position(GTK_EDITABLE(ih->handle)); gtk_editable_insert_text(GTK_EDITABLE(ih->handle), iupgtkStrConvertToUTF8(value), -1, &pos); } iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); return 0; } static int gtkTextSetAppendAttrib(Ihandle* ih, const char* value) { gint pos; if (!ih->handle) /* do not do the action before map */ return 0; /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); if (ih->data->is_multiline) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_end_iter(buffer, &iter); pos = gtk_text_buffer_get_char_count(buffer); if (ih->data->append_newline && pos!=0) gtk_text_buffer_insert(buffer, &iter, "\n", 1); gtk_text_buffer_insert(buffer, &iter, iupgtkStrConvertToUTF8(value), -1); } else { #if GTK_CHECK_VERSION(2, 14, 0) pos = gtk_entry_get_text_length(GTK_ENTRY(ih->handle))+1; #else pos = strlen(gtk_entry_get_text(GTK_ENTRY(ih->handle)))+1; #endif gtk_editable_insert_text(GTK_EDITABLE(ih->handle), iupgtkStrConvertToUTF8(value), -1, &pos); } iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); return 0; } static int gtkTextSetAlignmentAttrib(Ihandle* ih, const char* value) { float xalign; GtkJustification justification; if (iupStrEqualNoCase(value, "ARIGHT")) { xalign = 1.0f; justification = GTK_JUSTIFY_RIGHT; } else if (iupStrEqualNoCase(value, "ACENTER")) { xalign = 0.5f; justification = GTK_JUSTIFY_CENTER; } else /* "ALEFT" */ { xalign = 0; justification = GTK_JUSTIFY_LEFT; } if (ih->data->is_multiline) gtk_text_view_set_justification(GTK_TEXT_VIEW(ih->handle), justification); else gtk_entry_set_alignment(GTK_ENTRY(ih->handle), xalign); return 1; } static int gtkTextSetPaddingAttrib(Ihandle* ih, const char* value) { iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x'); if (ih->handle) { if (ih->data->is_multiline) { gtk_text_view_set_left_margin(GTK_TEXT_VIEW(ih->handle), ih->data->horiz_padding); gtk_text_view_set_right_margin(GTK_TEXT_VIEW(ih->handle), ih->data->horiz_padding); ih->data->vert_padding = 0; } else { #if GTK_CHECK_VERSION(2, 10, 0) GtkBorder border; border.bottom = border.top = ih->data->vert_padding; border.left = border.right = ih->data->horiz_padding; gtk_entry_set_inner_border(GTK_ENTRY(ih->handle), &border); #endif } return 0; } else return 1; /* store until not mapped, when mapped will be set again */ } static int gtkTextSetNCAttrib(Ihandle* ih, const char* value) { if (!iupStrToInt(value, &ih->data->nc)) ih->data->nc = INT_MAX; if (ih->handle) { if (!ih->data->is_multiline) gtk_entry_set_max_length(GTK_ENTRY(ih->handle), ih->data->nc); return 0; } else return 1; /* store until not mapped, when mapped will be set again */ } static int gtkTextSetClipboardAttrib(Ihandle *ih, const char *value) { /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); if (iupStrEqualNoCase(value, "COPY")) { if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); GtkClipboard *clipboard = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)); gtk_text_buffer_copy_clipboard(buffer, clipboard); } else gtk_editable_copy_clipboard(GTK_EDITABLE(ih->handle)); } else if (iupStrEqualNoCase(value, "CUT")) { if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); GtkClipboard *clipboard = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)); gtk_text_buffer_cut_clipboard(buffer, clipboard, TRUE); } else gtk_editable_cut_clipboard(GTK_EDITABLE(ih->handle)); } else if (iupStrEqualNoCase(value, "PASTE")) { if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); GtkClipboard *clipboard = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)); gtk_text_buffer_paste_clipboard(buffer, clipboard, NULL, TRUE); } else gtk_editable_paste_clipboard(GTK_EDITABLE(ih->handle)); } else if (iupStrEqualNoCase(value, "CLEAR")) { if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_delete_selection(buffer, FALSE, TRUE); } else gtk_editable_delete_selection(GTK_EDITABLE(ih->handle)); } iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); return 0; } static int gtkTextSetReadOnlyAttrib(Ihandle* ih, const char* value) { if (ih->data->is_multiline) gtk_text_view_set_editable(GTK_TEXT_VIEW(ih->handle), !iupStrBoolean(value)); else gtk_editable_set_editable(GTK_EDITABLE(ih->handle), !iupStrBoolean(value)); return 0; } static char* gtkTextGetReadOnlyAttrib(Ihandle* ih) { int editable; if (ih->data->is_multiline) editable = gtk_text_view_get_editable(GTK_TEXT_VIEW(ih->handle)); else editable = gtk_editable_get_editable(GTK_EDITABLE(ih->handle)); if (!editable) return "YES"; else return "NO"; } static char* gtkTextGetPangoLayoutAttrib(Ihandle* ih) { if (ih->data->is_multiline) return NULL; else return (char*)gtk_entry_get_layout(GTK_ENTRY(ih->handle)); } static int gtkTextSetBgColorAttrib(Ihandle* ih, const char* value) { if (ih->data->is_multiline) { GtkScrolledWindow* scrolled_window = (GtkScrolledWindow*)iupAttribGet(ih, "_IUP_EXTRAPARENT"); unsigned char r, g, b; /* ignore given value, must use only from parent for the scrollbars */ char* parent_value = iupBaseNativeParentGetBgColor(ih); if (iupStrToRGB(parent_value, &r, &g, &b)) { GtkWidget* sb; iupgtkBaseSetBgColor((GtkWidget*)scrolled_window, r, g, b); #if GTK_CHECK_VERSION(2, 8, 0) sb = gtk_scrolled_window_get_hscrollbar(scrolled_window); if (sb) iupgtkBaseSetBgColor(sb, r, g, b); sb = gtk_scrolled_window_get_vscrollbar(scrolled_window); if (sb) iupgtkBaseSetBgColor(sb, r, g, b); #endif } } return iupdrvBaseSetBgColorAttrib(ih, value); } static int gtkTextSetTabSizeAttrib(Ihandle* ih, const char* value) { PangoTabArray *tabs; int tabsize, charwidth; if (!ih->data->is_multiline) return 0; iupStrToInt(value, &tabsize); charwidth = gtkTextGetCharSize(ih); tabsize *= charwidth; tabs = pango_tab_array_new_with_positions(1, FALSE, PANGO_TAB_LEFT, tabsize); gtk_text_view_set_tabs(GTK_TEXT_VIEW(ih->handle), tabs); pango_tab_array_free(tabs); return 1; } static int gtkTextSetOverwriteAttrib(Ihandle* ih, const char* value) { if (!ih->data->is_multiline) return 0; gtk_text_view_set_overwrite(GTK_TEXT_VIEW(ih->handle), iupStrBoolean(value)); return 0; } static char* gtkTextGetOverwriteAttrib(Ihandle* ih) { if (!ih->data->is_multiline) return "NO"; if (gtk_text_view_get_overwrite(GTK_TEXT_VIEW(ih->handle))) return "YES"; else return "NO"; } void iupdrvTextAddFormatTag(Ihandle* ih, Ihandle* formattag) { GtkTextBuffer *buffer; GtkTextIter start_iter, end_iter; GtkTextTag* tag; char *selection; if (!ih->data->is_multiline) return; selection = iupAttribGet(formattag, "SELECTION"); if (selection) { if (!gtkTextSelectionAttribToIter(ih, selection, &start_iter, &end_iter)) return; } else { char* selectionpos = iupAttribGet(formattag, "SELECTIONPOS"); if (selectionpos) { if (!gtkTextSelectionPosAttribToIter(ih, selectionposstart_iter, &end_iter)) return; } else { GtkTextMark* mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, mark); gtk_text_buffer_get_iter_at_mark(buffer, &end_iter, mark); } } buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); tag = gtk_text_buffer_create_tag(buffer, NULL, NULL); gtkTextParseParagraphFormat(formattag, tag); gtkTextParseCharacterFormat(formattag, tag); gtk_text_buffer_apply_tag(buffer, tag, &start_iter, &end_iter); } static int gtkTextSetRemoveFormattingAttrib(Ihandle* ih, const char* value) { GtkTextBuffer *buffer; GtkTextIter start_iter, end_iter; if (!ih->data->is_multiline) return 0; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); if (gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter)) gtk_text_buffer_remove_all_tags(buffer, &start_iter, &end_iter); (void)value; return 0; } /************************************************************************************************/ static gboolean gtkTextSpinOutput(GtkSpinButton *spin, Ihandle* ih) { if (iupAttribGet(ih, "_IUPGTK_SPIN_NOAUTO")) { iupAttribSetInt(ih, "_IUPGTK_SPIN_VALUE", (int)spin->adjustment->value); return TRUE; /* disable output update */ } else { iupAttribSetStr(ih, "_IUPGTK_SPIN_OLDVALUE", gtk_entry_get_text(GTK_ENTRY(ih->handle))); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); return FALSE; } } static gint gtkTextSpinInput(GtkSpinButton *spin, gdouble *val, Ihandle* ih) { (void)spin; *val = (double)iupAttribGetInt(ih, "_IUPGTK_SPIN_VALUE"); /* called only when SPINAUTO=NO */ return TRUE; /* disable input update */ } static void gtkTextSpinValueChanged(GtkSpinButton* spin, Ihandle* ih) { IFni cb; iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); cb = (IFni)IupGetCallback(ih, "SPIN_CB"); if (cb) { int pos, ret; if (iupAttribGet(ih, "_IUPGTK_SPIN_NOAUTO")) pos = iupAttribGetInt(ih, "_IUPGTK_SPIN_VALUE"); else pos = gtk_spin_button_get_value_as_int((GtkSpinButton*)ih->handle); ret = cb(ih, pos); if (ret == IUP_IGNORE) { /* this is not working: g_signal_stop_emission_by_name(spin, "value_changed"); */ } } (void)spin; } static int gtkTextSetSpinMinAttrib(Ihandle* ih, const char* value) { if (GTK_IS_SPIN_BUTTON(ih->handle)) { int min; if (iupStrToInt(value, &min)) { int max = iupAttribGetInt(ih, "SPINMAX"); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); gtk_spin_button_set_range((GtkSpinButton*)ih->handle, (double)min, (double)max); g_signal_handlers_unblock_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); } } return 1; } static int gtkTextSetSpinMaxAttrib(Ihandle* ih, const char* value) { if (GTK_IS_SPIN_BUTTON(ih->handle)) { int max; if (iupStrToInt(value, &max)) { int min = iupAttribGetInt(ih, "SPINMIN"); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); gtk_spin_button_set_range((GtkSpinButton*)ih->handle, (double)min, (double)max); g_signal_handlers_unblock_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); } } return 1; } static int gtkTextSetSpinIncAttrib(Ihandle* ih, const char* value) { if (GTK_IS_SPIN_BUTTON(ih->handle)) { int inc; if (iupStrToInt(value, &inc)) gtk_spin_button_set_increments((GtkSpinButton*)ih->handle, (double)inc, (double)(inc*10)); } return 1; } static int gtkTextSetSpinValueAttrib(Ihandle* ih, const char* value) { if (GTK_IS_SPIN_BUTTON(ih->handle)) { int pos; if (iupStrToInt(value, &pos)) { iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); gtk_spin_button_set_value((GtkSpinButton*)ih->handle, (double)pos); g_signal_handlers_unblock_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkTextSpinValueChanged), ih); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); if (iupAttribGet(ih, "_IUPGTK_SPIN_NOAUTO")) iupAttribSetInt(ih, "_IUPGTK_SPIN_VALUE", pos); } } return 1; } static char* gtkTextGetSpinValueAttrib(Ihandle* ih) { if (GTK_IS_SPIN_BUTTON(ih->handle)) { int pos; char *str = iupStrGetMemory(50); if (iupAttribGet(ih, "_IUPGTK_SPIN_NOAUTO")) pos = iupAttribGetInt(ih, "_IUPGTK_SPIN_VALUE"); else pos = gtk_spin_button_get_value_as_int((GtkSpinButton*)ih->handle); sprintf(str, "%d", pos); return str; } return NULL; } /**********************************************************************************************************/ static void gtkTextMoveCursor(GtkWidget *w, GtkMovementStep step, gint count, gboolean extend_selection, Ihandle* ih) { int col, lin, pos; IFniii cb = (IFniii)IupGetCallback(ih, "CARET_CB"); if (!cb) return; if (ih->data->is_multiline) { GtkTextIter iter; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer)); gtkTextGetLinColFromPosition(&iter, &lin, &col); pos = gtk_text_iter_get_offset(&iter); } else { pos = gtk_editable_get_position(GTK_EDITABLE(ih->handle)); col = pos; col++; /* IUP starts at 1 */ lin = 1; } if (pos != ih->data->last_caret_pos) { ih->data->last_caret_pos = pos; cb(ih, lin, col, pos); } (void)w; (void)step; (void)count; (void)extend_selection; } static gboolean gtkTextKeyReleaseEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih) { gtkTextMoveCursor(NULL, 0, 0, 0, ih); (void)widget; (void)evt; return FALSE; } static gboolean gtkTextButtonEvent(GtkWidget *widget, GdkEventButton *evt, Ihandle *ih) { gtkTextMoveCursor(NULL, 0, 0, 0, ih); return iupgtkButtonEvent(widget, evt, ih); } static int gtkTextCallActionCb(Ihandle* ih, const char* insert_value, int len, int start, int end) { char *new_value, *value; int ret = -1, key = 0; IFnis cb = (IFnis)IupGetCallback(ih, "ACTION"); if (!cb && !ih->data->mask) return -1; /* continue */ value = gtkTextGetValueAttrib(ih); /* new_value is the internal buffer */ if (!insert_value) { new_value = iupStrDup(value); if (end<0) end = strlen(value)+1; iupStrRemove(new_value, start, end, 1); } else { if (value[0]==0) new_value = iupStrDup(insert_value); else { if (len < end-start) { new_value = iupStrDup(value); new_value = iupStrInsert(new_value, insert_value, start, end); } else new_value = iupStrInsert(value, insert_value, start, end); } } if (insert_value && insert_value[0]!=0 && insert_value[1]==0) key = insert_value[0]; if (!new_value) return -1; /* continue */ if (ih->data->nc && (int)strlen(new_value) > ih->data->nc) { if (new_value != value) free(new_value); return 0; /* abort */ } if (ih->data->mask && iupMaskCheck(ih->data->mask, new_value)==0) { if (new_value != value) free(new_value); return 0; /* abort */ } if (cb) { int cb_ret = cb(ih, key, (char*)new_value); if (cb_ret==IUP_IGNORE) ret = 0; /* abort */ else if (cb_ret==IUP_CLOSE) { IupExitLoop(); ret = 0; /* abort */ } else if (cb_ret!=0 && key!=0 && cb_ret != IUP_DEFAULT && cb_ret != IUP_CONTINUE) ret = cb_ret; /* abort and replace */ } if (new_value != value) free(new_value); return ret; /* continue */ } static void gtkTextEntryDeleteText(GtkEditable *editable, int start, int end, Ihandle* ih) { if (iupAttribGet(ih, "_IUPGTK_DISABLE_TEXT_CB")) return; if (gtkTextCallActionCb(ih, NULL, 0, start, end)==0) g_signal_stop_emission_by_name (editable, "delete_text"); } static void gtkTextEntryInsertText(GtkEditable *editable, char *insert_value, int len, int *pos, Ihandle* ih) { int ret; if (iupAttribGet(ih, "_IUPGTK_DISABLE_TEXT_CB")) return; ret = gtkTextCallActionCb(ih, iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(insert_value)), len, *pos, *pos); if (ret == 0) g_signal_stop_emission_by_name(editable, "insert_text"); else if (ret != -1) { insert_value[0] = (char)ret; /* replace key */ /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); gtk_editable_insert_text(editable, insert_value, 1, pos); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); g_signal_stop_emission_by_name(editable, "insert_text"); } } static void gtkTextBufferDeleteRange(GtkTextBuffer *textbuffer, GtkTextIter *start_iter, GtkTextIter *end_iter, Ihandle* ih) { int start, end; if (iupAttribGet(ih, "_IUPGTK_DISABLE_TEXT_CB")) return; start = gtk_text_iter_get_offset(start_iter); end = gtk_text_iter_get_offset(end_iter); if (gtkTextCallActionCb(ih, NULL, 0, start, end)==0) g_signal_stop_emission_by_name (textbuffer, "delete_range"); } static void gtkTextBufferInsertText(GtkTextBuffer *textbuffer, GtkTextIter *pos_iter, gchar *insert_value, gint len, Ihandle* ih) { int ret, pos; if (iupAttribGet(ih, "_IUPGTK_DISABLE_TEXT_CB")) return; pos = gtk_text_iter_get_offset(pos_iter); ret = gtkTextCallActionCb(ih, iupStrGetMemoryCopy(iupgtkStrConvertFromUTF8(insert_value)), len, pos, pos); if (ret == 0) g_signal_stop_emission_by_name(textbuffer, "insert_text"); else if (ret != -1) { insert_value[0] = (char)ret; /* replace key */ /* disable callbacks */ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1"); gtk_text_buffer_insert(textbuffer, pos_iter, insert_value, 1); iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL); g_signal_stop_emission_by_name(textbuffer, "insert_text"); } } static void gtkTextChanged(void* dummy, Ihandle* ih) { if (iupAttribGet(ih, "_IUPGTK_DISABLE_TEXT_CB")) return; iupBaseCallValueChangedCb(ih); (void)dummy; } /**********************************************************************************************************/ static int gtkTextMapMethod(Ihandle* ih) { GtkScrolledWindow* scrolled_window = NULL; if (ih->data->is_multiline) { GtkPolicyType hscrollbar_policy, vscrollbar_policy; int wordwrap = 0; ih->handle = gtk_text_view_new(); if (!ih->handle) return IUP_ERROR; scrolled_window = (GtkScrolledWindow*)gtk_scrolled_window_new(NULL, NULL); if (!scrolled_window) return IUP_ERROR; gtk_container_add((GtkContainer*)scrolled_window, ih->handle); gtk_widget_show((GtkWidget*)scrolled_window); iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)scrolled_window); /* formatting is always supported when MULTILINE=YES */ ih->data->has_formatting = 1; if (iupAttribGetBoolean(ih, "WORDWRAP")) { wordwrap = 1; ih->data->sb &= ~IUP_SB_HORIZ; /* must remove the horizontal scroolbar */ } if (iupAttribGetBoolean(ih, "BORDER")) gtk_scrolled_window_set_shadow_type(scrolled_window, GTK_SHADOW_IN); else gtk_scrolled_window_set_shadow_type(scrolled_window, GTK_SHADOW_NONE); if (ih->data->sb & IUP_SB_HORIZ) { if (iupAttribGetBoolean(ih, "AUTOHIDE")) hscrollbar_policy = GTK_POLICY_AUTOMATIC; else hscrollbar_policy = GTK_POLICY_ALWAYS; } else hscrollbar_policy = GTK_POLICY_NEVER; if (ih->data->sb & IUP_SB_VERT) { if (iupAttribGetBoolean(ih, "AUTOHIDE")) vscrollbar_policy = GTK_POLICY_AUTOMATIC; else vscrollbar_policy = GTK_POLICY_ALWAYS; } else vscrollbar_policy = GTK_POLICY_NEVER; gtk_scrolled_window_set_policy(scrolled_window, hscrollbar_policy, vscrollbar_policy); if (wordwrap) gtk_text_view_set_wrap_mode((GtkTextView*)ih->handle, GTK_WRAP_WORD); gtk_widget_add_events(ih->handle, GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK); } else { if (iupAttribGetBoolean(ih, "SPIN")) ih->handle = gtk_spin_button_new_with_range(0, 100, 1); else ih->handle = gtk_entry_new(); if (!ih->handle) return IUP_ERROR; /* formatting is never supported when MULTILINE=NO */ ih->data->has_formatting = 0; gtk_entry_set_has_frame((GtkEntry*)ih->handle, IupGetInt(ih, "BORDER")); if (iupAttribGetBoolean(ih, "PASSWORD")) gtk_entry_set_visibility((GtkEntry*)ih->handle, FALSE); if (GTK_IS_SPIN_BUTTON(ih->handle)) { gtk_spin_button_set_numeric((GtkSpinButton*)ih->handle, FALSE); gtk_spin_button_set_digits((GtkSpinButton*)ih->handle, 0); gtk_spin_button_set_wrap((GtkSpinButton*)ih->handle, iupAttribGetBoolean(ih, "SPINWRAP")); g_signal_connect(G_OBJECT(ih->handle), "value-changed", G_CALLBACK(gtkTextSpinValueChanged), ih); g_signal_connect(G_OBJECT(ih->handle), "output", G_CALLBACK(gtkTextSpinOutput), ih); if (!iupAttribGetBoolean(ih, "SPINAUTO")) { g_signal_connect(G_OBJECT(ih->handle), "input", G_CALLBACK(gtkTextSpinInput), ih); iupAttribSetStr(ih, "_IUPGTK_SPIN_NOAUTO", "1"); } } } /* add to the parent, all GTK controls must call this. */ iupgtkBaseAddToParent(ih); if (!iupAttribGetBoolean(ih, "CANFOCUS")) GTK_WIDGET_FLAGS(ih->handle) &= ~GTK_CAN_FOCUS; g_signal_connect(G_OBJECT(ih->handle), "enter-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "leave-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "focus-in-event", G_CALLBACK(iupgtkFocusInOutEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "focus-out-event", G_CALLBACK(iupgtkFocusInOutEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "key-press-event", G_CALLBACK(iupgtkKeyPressEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "show-help", G_CALLBACK(iupgtkShowHelp), ih); g_signal_connect_after(G_OBJECT(ih->handle), "move-cursor", G_CALLBACK(gtkTextMoveCursor), ih); /* only report some caret movements */ g_signal_connect_after(G_OBJECT(ih->handle), "key-release-event", G_CALLBACK(gtkTextKeyReleaseEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "button-press-event", G_CALLBACK(gtkTextButtonEvent), ih); /* if connected "after" then it is ignored */ g_signal_connect(G_OBJECT(ih->handle), "button-release-event",G_CALLBACK(gtkTextButtonEvent), ih); g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih); if (ih->data->is_multiline) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle)); g_signal_connect(G_OBJECT(buffer), "delete-range", G_CALLBACK(gtkTextBufferDeleteRange), ih); g_signal_connect(G_OBJECT(buffer), "insert-text", G_CALLBACK(gtkTextBufferInsertText), ih); g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(gtkTextChanged), ih); } else { g_signal_connect(G_OBJECT(ih->handle), "delete-text", G_CALLBACK(gtkTextEntryDeleteText), ih); g_signal_connect(G_OBJECT(ih->handle), "insert-text", G_CALLBACK(gtkTextEntryInsertText), ih); g_signal_connect(G_OBJECT(ih->handle), "changed", G_CALLBACK(gtkTextChanged), ih); } if (scrolled_window) gtk_widget_realize((GtkWidget*)scrolled_window); gtk_widget_realize(ih->handle); /* configure for DRAG&DROP */ if (IupGetCallback(ih, "DROPFILES_CB")) iupAttribSetStr(ih, "DRAGDROP", "YES"); /* update a mnemonic in a label if necessary */ iupgtkUpdateMnemonic(ih); if (ih->data->formattags) iupTextUpdateFormatTags(ih); IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)gtkTextConvertXYToPos); return IUP_NOERROR; } void iupdrvTextInitClass(Iclass* ic) { /* Driver Dependent Class functions */ ic->Map = gtkTextMapMethod; /* Driver Dependent Attribute functions */ /* Common GTK only (when text is in a secondary element) */ iupClassRegisterAttribute(ic, "PANGOLAYOUT", gtkTextGetPangoLayoutAttrib, NULL, NULL, NULL, IUPAF_NO_INHERIT); /* Visual */ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, gtkTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT); /* Special */ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT); /* IupText only */ iupClassRegisterAttribute(ic, "PADDING", iupTextGetPaddingAttrib, gtkTextSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED); iupClassRegisterAttribute(ic, "VALUE", gtkTextGetValueAttrib, gtkTextSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SELECTEDTEXT", gtkTextGetSelectedTextAttrib, gtkTextSetSelectedTextAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SELECTION", gtkTextGetSelectionAttrib, gtkTextSetSelectionAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SELECTIONPOS", gtkTextGetSelectionPosAttrib, gtkTextSetSelectionPosAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CARET", gtkTextGetCaretAttrib, gtkTextSetCaretAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "CARETPOS", gtkTextGetCaretPosAttrib, gtkTextSetCaretPosAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "INSERT", NULL, gtkTextSetInsertAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "APPEND", NULL, gtkTextSetAppendAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "READONLY", gtkTextGetReadOnlyAttrib, gtkTextSetReadOnlyAttrib, NULL, NULL, IUPAF_DEFAULT); iupClassRegisterAttribute(ic, "NC", iupTextGetNCAttrib, gtkTextSetNCAttrib, NULL, NULL, IUPAF_NOT_MAPPED); iupClassRegisterAttribute(ic, "CLIPBOARD", NULL, gtkTextSetClipboardAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SCROLLTO", NULL, gtkTextSetScrollToAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SCROLLTOPOS", NULL, gtkTextSetScrollToPosAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SPINMIN", NULL, gtkTextSetSpinMinAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SPINMAX", NULL, gtkTextSetSpinMaxAttrib, IUPAF_SAMEASSYSTEM, "100", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SPININC", NULL, gtkTextSetSpinIncAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SPINVALUE", gtkTextGetSpinValueAttrib, gtkTextSetSpinValueAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT); /* IupText Windows and GTK only */ iupClassRegisterAttribute(ic, "ADDFORMATTAG", NULL, iupTextSetAddFormatTagAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "ADDFORMATTAG_HANDLE", NULL, iupTextSetAddFormatTagHandleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, gtkTextSetAlignmentAttrib, IUPAF_SAMEASSYSTEM, "ALEFT", IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupgtkSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "FORMATTING", iupTextGetFormattingAttrib, iupTextSetFormattingAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "OVERWRITE", gtkTextGetOverwriteAttrib, gtkTextSetOverwriteAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "REMOVEFORMATTING", NULL, gtkTextSetRemoveFormattingAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "TABSIZE", NULL, gtkTextSetTabSizeAttrib, "8", NULL, IUPAF_DEFAULT); /* force new default value */ iupClassRegisterAttribute(ic, "PASSWORD", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT); }