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 + -
显示快捷键?