gntentry.c
来自「Linux下的多协议即时通讯程序源代码」· C语言 代码 · 共 946 行 · 第 1/2 页
C
946 行
if (iter < entry->start) return TRUE; iter = (char*)begin_word(iter, entry->start); count = entry->cursor - iter; memmove(iter, entry->cursor, entry->end - entry->cursor); entry->end -= count; entry->cursor = iter; if (entry->cursor <= entry->scroll) { entry->scroll = entry->cursor - widget->priv.width + 2; if (entry->scroll < entry->start) entry->scroll = entry->start; } memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); entry_redraw(widget); entry_text_changed(entry); return TRUE;}static gbooleanmove_forward_word(GntBindable *bind, GList *list){ GntEntry *entry = GNT_ENTRY(bind); GntWidget *widget = GNT_WIDGET(bind); entry->cursor = (char *)next_begin_word(entry->cursor, entry->end); while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) { entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); } entry_redraw(widget); return TRUE;}static gbooleandelete_forward_word(GntBindable *bind, GList *list){ GntEntry *entry = GNT_ENTRY(bind); GntWidget *widget = GNT_WIDGET(bind); char *iter = (char *)next_begin_word(entry->cursor, entry->end); int len = entry->end - iter + 1; if (len <= 0) return TRUE; memmove(entry->cursor, iter, len); len = iter - entry->cursor; entry->end -= len; memset(entry->end, '\0', len); entry_redraw(widget); entry_text_changed(entry); return TRUE;}static gbooleangnt_entry_key_pressed(GntWidget *widget, const char *text){ GntEntry *entry = GNT_ENTRY(widget); if (text[0] == 27) { if (text[1] == 0) { destroy_suggest(entry); return TRUE; } return FALSE; } else { if ((text[0] == '\r' || text[0] == ' ') && entry->ddown) { char *text = g_strdup(gnt_tree_get_selection_data(GNT_TREE(entry->ddown))); destroy_suggest(entry); complete_suggest(entry, text); g_free(text); entry_text_changed(entry); return TRUE; } if (!iscntrl(text[0])) { const char *str, *next; for (str = text; *str; str = next) { int len; next = g_utf8_find_next_char(str, NULL); len = next - str; /* Valid input? */ /* XXX: Is it necessary to use _unichar_ variants here? */ if (ispunct(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_PUNCT)) continue; if (isspace(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_SPACE)) continue; if (isalpha(*str) && !(entry->flag & GNT_ENTRY_FLAG_ALPHA)) continue; if (isdigit(*str) && !(entry->flag & GNT_ENTRY_FLAG_INT)) continue; /* Reached the max? */ if (entry->max && g_utf8_pointer_to_offset(entry->start, entry->end) >= entry->max) continue; if (entry->end + len - entry->start >= entry->buffer) { /* This will cause the buffer to grow */ char *tmp = g_strdup(entry->start); gnt_entry_set_text_internal(entry, tmp); g_free(tmp); } memmove(entry->cursor + len, entry->cursor, entry->end - entry->cursor + 1); entry->end += len; while (str < next) { if (*str == '\r' || *str == '\n') *entry->cursor = ' '; else *entry->cursor = *str; entry->cursor++; str++; } while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); if (entry->ddown) show_suggest_dropdown(entry); } entry_redraw(widget); entry_text_changed(entry); return TRUE; } } return FALSE;}static voidgnt_entry_destroy(GntWidget *widget){ GntEntry *entry = GNT_ENTRY(widget); g_free(entry->start); if (entry->history) { entry->history = g_list_first(entry->history); g_list_foreach(entry->history, (GFunc)g_free, NULL); g_list_free(entry->history); } if (entry->suggests) { g_list_foreach(entry->suggests, (GFunc)g_free, NULL); g_list_free(entry->suggests); } if (entry->ddown) { gnt_widget_destroy(entry->ddown->parent); }}static voidgnt_entry_lost_focus(GntWidget *widget){ GntEntry *entry = GNT_ENTRY(widget); destroy_suggest(entry); entry_redraw(widget);}static voidgnt_entry_class_init(GntEntryClass *klass){ GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); char s[2] = {erasechar(), 0}; parent_class = GNT_WIDGET_CLASS(klass); parent_class->destroy = gnt_entry_destroy; parent_class->draw = gnt_entry_draw; parent_class->map = gnt_entry_map; parent_class->size_request = gnt_entry_size_request; parent_class->key_pressed = gnt_entry_key_pressed; parent_class->lost_focus = gnt_entry_lost_focus; signals[SIG_TEXT_CHANGED] = g_signal_new("text_changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntEntryClass, text_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gnt_bindable_class_register_action(bindable, "cursor-home", move_start, GNT_KEY_CTRL_A, NULL); gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL); gnt_bindable_class_register_action(bindable, "cursor-end", move_end, GNT_KEY_CTRL_E, NULL); gnt_bindable_register_binding(bindable, "cursor-end", GNT_KEY_END, NULL); gnt_bindable_class_register_action(bindable, "delete-prev", backspace, GNT_KEY_BACKSPACE, NULL); gnt_bindable_register_binding(bindable, "delete-prev", s, NULL); gnt_bindable_register_binding(bindable, "delete-prev", GNT_KEY_CTRL_H, NULL); gnt_bindable_class_register_action(bindable, "delete-next", delkey, GNT_KEY_DEL, NULL); gnt_bindable_register_binding(bindable, "delete-next", GNT_KEY_CTRL_D, NULL); gnt_bindable_class_register_action(bindable, "delete-start", del_to_home, GNT_KEY_CTRL_U, NULL); gnt_bindable_class_register_action(bindable, "delete-end", del_to_end, GNT_KEY_CTRL_K, NULL); gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word, GNT_KEY_CTRL_W, NULL); gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word, "\033" "b", NULL); gnt_bindable_class_register_action(bindable, "cursor-prev", move_back, GNT_KEY_LEFT, NULL); gnt_bindable_register_binding(bindable, "cursor-prev", GNT_KEY_CTRL_B, NULL); gnt_bindable_class_register_action(bindable, "cursor-next", move_forward, GNT_KEY_RIGHT, NULL); gnt_bindable_register_binding(bindable, "cursor-next", GNT_KEY_CTRL_F, NULL); gnt_bindable_class_register_action(bindable, "cursor-next-word", move_forward_word, "\033" "f", NULL); gnt_bindable_class_register_action(bindable, "delete-next-word", delete_forward_word, "\033" "d", NULL); gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show, "\t", NULL); gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next, GNT_KEY_DOWN, NULL); gnt_bindable_class_register_action(bindable, "suggest-prev", suggest_prev, GNT_KEY_UP, NULL); gnt_bindable_class_register_action(bindable, "history-prev", history_prev, GNT_KEY_CTRL_DOWN, NULL); gnt_bindable_class_register_action(bindable, "history-next", history_next, GNT_KEY_CTRL_UP, NULL); gnt_bindable_class_register_action(bindable, "clipboard-paste", clipboard_paste, GNT_KEY_CTRL_V, NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); GNTDEBUG;}static voidgnt_entry_init(GTypeInstance *instance, gpointer class){ GntWidget *widget = GNT_WIDGET(instance); GntEntry *entry = GNT_ENTRY(instance); entry->flag = GNT_ENTRY_FLAG_ALL; entry->max = 0; entry->histlength = 0; entry->history = NULL; entry->word = TRUE; entry->always = FALSE; entry->suggests = NULL; GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS); GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_GROW_X); widget->priv.minw = 3; widget->priv.minh = 1; GNTDEBUG;}/****************************************************************************** * GntEntry API *****************************************************************************/GTypegnt_entry_get_gtype(void){ static GType type = 0; if(type == 0) { static const GTypeInfo info = { sizeof(GntEntryClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)gnt_entry_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(GntEntry), 0, /* n_preallocs */ gnt_entry_init, /* instance_init */ NULL /* value_table */ }; type = g_type_register_static(GNT_TYPE_WIDGET, "GntEntry", &info, 0); } return type;}GntWidget *gnt_entry_new(const char *text){ GntWidget *widget = g_object_new(GNT_TYPE_ENTRY, NULL); GntEntry *entry = GNT_ENTRY(widget); gnt_entry_set_text_internal(entry, text); return widget;}static voidgnt_entry_set_text_internal(GntEntry *entry, const char *text){ int len; int scroll, cursor; g_free(entry->start); if (text && text[0]) { len = strlen(text); } else { len = 0; } entry->buffer = len + 128; scroll = entry->scroll - entry->start; cursor = entry->end - entry->cursor; entry->start = g_new0(char, entry->buffer); if (text) snprintf(entry->start, len + 1, "%s", text); entry->end = entry->start + len; entry->scroll = entry->start + scroll; entry->cursor = entry->end - cursor; if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED)) entry_redraw(GNT_WIDGET(entry));}void gnt_entry_set_text(GntEntry *entry, const char *text){ gboolean changed = TRUE; if (text == NULL && entry->start == NULL) changed = FALSE; if (text && entry->start && g_utf8_collate(text, entry->start) == 0) changed = FALSE; gnt_entry_set_text_internal(entry, text); if (changed) entry_text_changed(entry);}void gnt_entry_set_max(GntEntry *entry, int max){ entry->max = max;}void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag){ entry->flag = flag; /* XXX: Check the existing string to make sure the flags are respected? */}const char *gnt_entry_get_text(GntEntry *entry){ return entry->start;}void gnt_entry_clear(GntEntry *entry){ gnt_entry_set_text_internal(entry, NULL); entry->scroll = entry->cursor = entry->end = entry->start; entry_redraw(GNT_WIDGET(entry)); destroy_suggest(entry); entry_text_changed(entry);}void gnt_entry_set_masked(GntEntry *entry, gboolean set){ entry->masked = set;}void gnt_entry_add_to_history(GntEntry *entry, const char *text){ g_return_if_fail(entry->history != NULL); /* Need to set_history_length first */ if (g_list_length(entry->history) >= entry->histlength) return; entry->history = g_list_first(entry->history); g_free(entry->history->data); entry->history->data = g_strdup(text); entry->history = g_list_prepend(entry->history, NULL);}void gnt_entry_set_history_length(GntEntry *entry, int num){ if (num == 0) { entry->histlength = num; if (entry->history) { entry->history = g_list_first(entry->history); g_list_foreach(entry->history, (GFunc)g_free, NULL); g_list_free(entry->history); entry->history = NULL; } return; } if (entry->histlength == 0) { entry->histlength = num; entry->history = g_list_append(NULL, NULL); return; } if (num > 0 && num < entry->histlength) { GList *first, *iter; int index = 0; for (first = entry->history, index = 0; first->prev; first = first->prev, index++); while ((iter = g_list_nth(first, num)) != NULL) { g_free(iter->data); first = g_list_delete_link(first, iter); } entry->histlength = num; if (index >= num) entry->history = g_list_last(first); return; } entry->histlength = num;}void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word){ entry->word = word;}void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always){ entry->always = always;}void gnt_entry_add_suggest(GntEntry *entry, const char *text){ GList *find; if (!text || !*text) return; find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate); if (find) return; entry->suggests = g_list_append(entry->suggests, g_strdup(text));}void gnt_entry_remove_suggest(GntEntry *entry, const char *text){ GList *find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate); if (find) { g_free(find->data); entry->suggests = g_list_delete_link(entry->suggests, find); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?