📄 gtkentry.c
字号:
{ gtk_paint_flat_box (widget->style, drawable, selected_state, GTK_SHADOW_NONE, NULL, widget, "text", INNER_BORDER + selection_start_xoffset, INNER_BORDER, selection_end_xoffset - selection_start_xoffset, height - 2*INNER_BORDER); gdk_draw_text_wc (drawable, widget->style->font, widget->style->fg_gc[selected_state], INNER_BORDER + selection_start_xoffset, y, toprint + selection_start_pos - start_pos, selection_end_pos - selection_start_pos); } if (selection_end_pos < end_pos) gdk_draw_text_wc (drawable, widget->style->font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], INNER_BORDER + selection_end_xoffset, y, toprint + selection_end_pos - start_pos, end_pos - selection_end_pos); /* free the space allocated for the stars if it's neccessary. */ if (!editable->visible) g_free (toprint); if (editable->editable) gtk_entry_draw_cursor_on_drawable (entry, drawable); if (use_backing_pixmap) gdk_draw_pixmap(entry->text_area, widget->style->fg_gc[GTK_STATE_NORMAL], entry->backing_pixmap, 0, 0, 0, 0, width, height); }}static voidgtk_entry_draw_cursor (GtkEntry *entry){ g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); gtk_entry_draw_cursor_on_drawable (entry, entry->text_area);}static voidgtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable){ GtkWidget *widget; GtkEditable *editable; gint xoffset; gint text_area_height; g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); if (GTK_WIDGET_DRAWABLE (entry)) { widget = GTK_WIDGET (entry); editable = GTK_EDITABLE (entry); xoffset = INNER_BORDER + entry->char_offset[editable->current_pos]; xoffset -= entry->scroll_offset; gdk_window_get_size (entry->text_area, NULL, &text_area_height); if (GTK_WIDGET_HAS_FOCUS (widget) && (editable->selection_start_pos == editable->selection_end_pos)) { gdk_draw_line (drawable, widget->style->fg_gc[GTK_STATE_NORMAL], xoffset, INNER_BORDER, xoffset, text_area_height - INNER_BORDER); } else { gint yoffset = (text_area_height - (widget->style->font->ascent + widget->style->font->descent)) / 2 + widget->style->font->ascent; gtk_paint_flat_box (widget->style, drawable, GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, NULL, widget, "entry_bg", xoffset, INNER_BORDER, 1, text_area_height - INNER_BORDER); /* Draw the character under the cursor again */ if ((editable->current_pos < entry->text_length) && (editable->selection_start_pos == editable->selection_end_pos)) { GdkWChar c = editable->visible ? *(entry->text + editable->current_pos) : '*'; gdk_draw_text_wc (drawable, widget->style->font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], xoffset, yoffset, &c, 1); } }#ifdef USE_XIM if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { editable->ic_attr->spot_location.x = xoffset; editable->ic_attr->spot_location.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2; gdk_ic_set_attr (editable->ic, editable->ic_attr, GDK_IC_SPOT_LOCATION); }#endif }}static voidgtk_entry_queue_draw (GtkEntry *entry){ g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); if (!entry->timer) entry->timer = gtk_timeout_add (DRAW_TIMEOUT, gtk_entry_timer, entry);}static gintgtk_entry_timer (gpointer data){ GtkEntry *entry; GDK_THREADS_ENTER (); entry = GTK_ENTRY (data); entry->timer = 0; gtk_entry_draw_text (entry); GDK_THREADS_LEAVE (); return FALSE;}static gintgtk_entry_find_position (GtkEntry *entry, gint x){ gint start = 0; gint end = entry->text_length; gint half; if (x <= 0) return 0; if (x >= entry->char_offset[end]) return end; /* invariant - char_offset[start] <= x < char_offset[end] */ while (start != end) { half = (start+end)/2; if (half == start) return half; else if (entry->char_offset[half] <= x) start = half; else end = half; } return start;}static gintgtk_entry_position (GtkEntry *entry, gint x){ return gtk_entry_find_position(entry, x);}static voidentry_adjust_scroll (GtkEntry *entry){ gint xoffset, max_offset; gint text_area_width; g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); if (!entry->text_area) return; gdk_window_get_size (entry->text_area, &text_area_width, NULL); /* Display as much text as we can */ max_offset = MAX(0, entry->char_offset[entry->text_length] - text_area_width); if (entry->scroll_offset > max_offset) entry->scroll_offset = max_offset; /* And make sure cursor is on screen */ xoffset = entry->char_offset[GTK_EDITABLE(entry)->current_pos]; xoffset -= entry->scroll_offset; if (xoffset < 0) entry->scroll_offset += xoffset; else if (xoffset > text_area_width) entry->scroll_offset += xoffset - text_area_width + 1; gtk_widget_queue_draw (GTK_WIDGET (entry));}static voidgtk_entry_grow_text (GtkEntry *entry){ gint previous_size; gint i; g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); previous_size = entry->text_size; if (!entry->text_size) entry->text_size = 128; else entry->text_size *= 2; entry->text = g_realloc (entry->text, entry->text_size * sizeof(GdkWChar)); entry->char_offset = g_realloc (entry->char_offset, entry->text_size * sizeof(guint)); if (entry->text_length == 0) /* initial allocation */ { entry->char_offset[0] = 0; } for (i = previous_size; i < entry->text_size; i++) entry->text[i] = '\0';}static voidgtk_entry_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position){ GdkWChar *text; gint start_pos; gint end_pos; gint last_pos; gint max_length; gint i; guchar *new_text_nt; gint insertion_length; GdkWChar *insertion_text; GtkEntry *entry; GtkWidget *widget; g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_ENTRY (editable)); entry = GTK_ENTRY (editable); widget = GTK_WIDGET (editable); if ((entry->text_length == 0) && (entry->use_wchar == FALSE)) { if (!GTK_WIDGET_REALIZED (widget)) gtk_widget_ensure_style (widget); if ((widget->style) && (widget->style->font->type == GDK_FONT_FONTSET)) entry->use_wchar = TRUE; } if (new_text_length < 0) { new_text_nt = (gchar *)new_text; new_text_length = strlen (new_text); if (new_text_length <= 0) return; } else if (new_text_length == 0) { return; } else { /* make a null-terminated copy of new_text */ new_text_nt = g_new (gchar, new_text_length + 1); memcpy (new_text_nt, new_text, new_text_length); new_text_nt[new_text_length] = 0; } /* The algorithms here will work as long as, the text size (a * multiple of 2), fits into a guint16 but we specify a shorter * maximum length so that if the user pastes a very long text, there * is not a long hang from the slow X_LOCALE functions. */ if (entry->text_max_length == 0) max_length = 2047; else max_length = MIN (2047, entry->text_max_length); /* Convert to wide characters */ insertion_text = g_new (GdkWChar, new_text_length); if (entry->use_wchar) insertion_length = gdk_mbstowcs (insertion_text, new_text_nt, new_text_length); else for (insertion_length=0; new_text_nt[insertion_length]; insertion_length++) insertion_text[insertion_length] = new_text_nt[insertion_length]; if (new_text_nt != (guchar *)new_text) g_free (new_text_nt); /* Make sure we do not exceed the maximum size of the entry. */ if (insertion_length + entry->text_length > max_length) insertion_length = max_length - entry->text_length; /* Don't insert anything, if there was nothing to insert. */ if (insertion_length <= 0) { g_free(insertion_text); return; } /* Make sure we are inserting at integral character position */ start_pos = *position; if (start_pos < 0) start_pos = 0; else if (start_pos > entry->text_length) start_pos = entry->text_length; end_pos = start_pos + insertion_length; last_pos = insertion_length + entry->text_length; if (editable->selection_start_pos >= *position) editable->selection_start_pos += insertion_length; if (editable->selection_end_pos >= *position) editable->selection_end_pos += insertion_length; while (last_pos >= entry->text_size) gtk_entry_grow_text (entry); text = entry->text; for (i = last_pos - 1; i >= end_pos; i--) text[i] = text[i- (end_pos - start_pos)]; for (i = start_pos; i < end_pos; i++) text[i] = insertion_text[i - start_pos]; g_free (insertion_text); /* Fix up the the character offsets */ if (GTK_WIDGET_REALIZED (entry)) { gint offset = 0; for (i = last_pos; i >= end_pos; i--) entry->char_offset[i] = entry->char_offset[i - insertion_length]; for (i=start_pos; i<end_pos; i++) { entry->char_offset[i] = entry->char_offset[start_pos] + offset; if (editable->visible) { offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, entry->text[i]); } else { offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } for (i = end_pos; i <= last_pos; i++) entry->char_offset[i] += offset; } entry->text_length += insertion_length; *position = end_pos; entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry);}/* Recompute the x offsets of all characters in the buffer */static voidgtk_entry_recompute_offsets (GtkEntry *entry){ gint i; gint offset = 0; for (i=0; i<entry->text_length; i++) { entry->char_offset[i] = offset; if (GTK_EDITABLE (entry)->visible) { offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, entry->text[i]); } else { offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } entry->char_offset[i] = offset;}static voidgtk_entry_delete_text (GtkEditable *editable, gint start_pos, gint end_pos){ GdkWChar *text; gint deletion_length; gint i; GtkEntry *entry; g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_ENTRY (editable)); entry = GTK_ENTRY (editable); if (end_pos < 0) end_pos = entry->text_length; if (editable->selection_start_pos > start_pos) editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos; if (editable->selection_end_pos > start_pos) editable->selection_end_pos -= MIN(end_pos, editable->selection_end_pos) - start_pos; if ((start_pos < end_pos) && (start_pos >= 0) && (end_pos <= entry->text_length)) { text = entry->text; deletion_length = end_pos - start_pos; /* Fix up the character offsets */ if (GTK_WIDGET_REALIZED (entry)) { gint deletion_width = entry->char_offset[end_pos] - entry->char_offset[start_pos]; for (i = 0 ; i <= entry->text_length - end_pos; i++) entry->char_offset[start_pos+i] = entry->char_offset[end_pos+i] - deletion_width; } for (i = end_pos; i < entry->text_length; i++) text[i - deletion_length] = text[i]; for (i = entry->text_length - deletion_length; i < entry->text_length; i++) text[i] = '\0'; entry->text_length -= deletion_length; editable->current_pos = start_pos; } entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry);}static voidgtk_entry_update_text (GtkEditable *editable,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -