⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gnttextview.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	parent_class->draw = gnt_text_view_draw;	parent_class->map = gnt_text_view_map;	parent_class->size_request = gnt_text_view_size_request;	parent_class->key_pressed = gnt_text_view_key_pressed;	parent_class->clicked = gnt_text_view_clicked;	parent_class->size_changed = gnt_text_view_size_changed;	GNTDEBUG;}static voidgnt_text_view_init(GTypeInstance *instance, gpointer class){	GntWidget *widget = GNT_WIDGET(instance);		GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), GNT_WIDGET_GROW_Y | GNT_WIDGET_GROW_X);	widget->priv.minw = 5;	widget->priv.minh = 2;	GNTDEBUG;}/****************************************************************************** * GntTextView API *****************************************************************************/GTypegnt_text_view_get_gtype(void){	static GType type = 0;	if(type == 0)	{		static const GTypeInfo info = {			sizeof(GntTextViewClass),			NULL,					/* base_init		*/			NULL,					/* base_finalize	*/			(GClassInitFunc)gnt_text_view_class_init,			NULL,					/* class_finalize	*/			NULL,					/* class_data		*/			sizeof(GntTextView),			0,						/* n_preallocs		*/			gnt_text_view_init,			/* instance_init	*/			NULL					/* value_table		*/		};		type = g_type_register_static(GNT_TYPE_WIDGET,									  "GntTextView",									  &info, 0);	}	return type;}GntWidget *gnt_text_view_new(){	GntWidget *widget = g_object_new(GNT_TYPE_TEXT_VIEW, NULL);	GntTextView *view = GNT_TEXT_VIEW(widget);	GntTextLine *line = g_new0(GntTextLine, 1);	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);	view->string = g_string_new(NULL);	view->list = g_list_append(view->list, line);	return widget;}void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags){	gnt_text_view_append_text_with_tag(view, text, flags, NULL);}void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text,			GntTextFormatFlags flags, const char *tagname){	GntWidget *widget = GNT_WIDGET(view);	int fl = 0;	const char *start, *end;	GList *list = view->list;	GntTextLine *line;	int len;	if (text == NULL || *text == '\0')		return;	fl = gnt_text_format_flag_to_chtype(flags);	len = view->string->len;	view->string = g_string_append(view->string, text);	if (tagname) {		GntTextTag *tag = g_new0(GntTextTag, 1);		tag->name = g_strdup(tagname);		tag->start = len;		tag->end = view->string->len;		view->tags = g_list_append(view->tags, tag);	}	view->list = g_list_first(view->list);	start = end = view->string->str + len;	while (*start) {		GntTextLine *oldl;		GntTextSegment *seg = NULL;		if (*end == '\n' || *end == '\r') {			if (!strncmp(end, "\r\n", 2))				end++;			end++;			start = end;			gnt_text_view_next_line(view);			view->list = g_list_first(view->list);			continue;		}		line = view->list->data;		if (line->length == widget->priv.width - 1) {			/* The last added line was exactly the same width as the widget */			line = g_new0(GntTextLine, 1);			line->soft = TRUE;			view->list = g_list_prepend(view->list, line);		}		if ((end = strchr(start, '\r')) != NULL ||			(end = strchr(start, '\n')) != NULL) {			len = gnt_util_onscreen_width(start, end - 1);			if (len >= widget->priv.width - line->length - 1) {				end = NULL;			}		}		if (end == NULL)			end = gnt_util_onscreen_width_to_pointer(start,					widget->priv.width - line->length - 1, &len);		/* Try to append to the previous segment if possible */		if (line->segments) {			seg = g_list_last(line->segments)->data;			if (seg->flags != fl)				seg = NULL;		}		if (seg == NULL) {			seg = g_new0(GntTextSegment, 1);			seg->start = start - view->string->str;			seg->tvflag = flags;			seg->flags = fl;			line->segments = g_list_append(line->segments, seg);		}		oldl = line;		if (*end && *end != '\n' && *end != '\r') {			const char *tmp = end;			while (end && *end != '\n' && *end != '\r' && !g_ascii_isspace(*end)) {				end = g_utf8_find_prev_char(seg->start + view->string->str, end);			}			if (!end || !g_ascii_isspace(*end))				end = tmp;			else				end++; /* Remove the space */			line = g_new0(GntTextLine, 1);			line->soft = TRUE;			view->list = g_list_prepend(view->list, line);		}		seg->end = end - view->string->str;		oldl->length += len;		start = end;	}	view->list = list;	gnt_widget_draw(widget);}void gnt_text_view_scroll(GntTextView *view, int scroll){	if (scroll == 0)	{		view->list = g_list_first(view->list);	}	else if (scroll > 0)	{		GList *list = g_list_nth_prev(view->list, scroll);		if (list == NULL)			list = g_list_first(view->list);		view->list = list;	}	else if (scroll < 0)	{		GList *list = g_list_nth(view->list, -scroll);		if (list == NULL)			list = g_list_last(view->list);		view->list = list;	}			gnt_widget_draw(GNT_WIDGET(view));}void gnt_text_view_next_line(GntTextView *view){	GntTextLine *line = g_new0(GntTextLine, 1);	GList *list = view->list;		view->list = g_list_prepend(g_list_first(view->list), line);	view->list = list;	gnt_widget_draw(GNT_WIDGET(view));}chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags){	chtype fl = 0;	if (flags & GNT_TEXT_FLAG_BOLD)		fl |= A_BOLD;	if (flags & GNT_TEXT_FLAG_UNDERLINE)		fl |= A_UNDERLINE;	if (flags & GNT_TEXT_FLAG_BLINK)		fl |= A_BLINK;	if (flags & GNT_TEXT_FLAG_DIM)		fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED));	else if (flags & GNT_TEXT_FLAG_HIGHLIGHT)		fl |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));	else		fl |= COLOR_PAIR(GNT_COLOR_NORMAL);	return fl;}void gnt_text_view_clear(GntTextView *view){	GntTextLine *line;	g_list_foreach(view->list, free_text_line, NULL);	g_list_free(view->list);	view->list = NULL;	line = g_new0(GntTextLine, 1);	view->list = g_list_append(view->list, line);	if (view->string)		g_string_free(view->string, TRUE);	view->string = g_string_new(NULL);	if (GNT_WIDGET(view)->window)		gnt_widget_draw(GNT_WIDGET(view));}int gnt_text_view_get_lines_below(GntTextView *view){	int below = 0;	GList *list = view->list;	while ((list = list->prev))		++below;	return below;}int gnt_text_view_get_lines_above(GntTextView *view){	int above = 0;	GList *list = view->list;	list = g_list_nth(view->list, GNT_WIDGET(view)->priv.height);	if (!list)		return 0;	while ((list = list->next))		++above;	return above;}/** * XXX: There are quite possibly more than a few bugs here. */int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all){	GList *alllines = g_list_first(view->list);	GList *list, *next, *iter, *inext;	const int text_length = text ? strlen(text) : 0;	int count = 0;	for (list = view->tags; list; list = next) {		GntTextTag *tag = list->data;		next = list->next;		if (strcmp(tag->name, name) == 0) {			int change;			char *before, *after;			count++;			before = g_strndup(view->string->str, tag->start);			after = g_strdup(view->string->str + tag->end);			change = (tag->end - tag->start) - text_length;			g_string_printf(view->string, "%s%s%s", before, text ? text : "", after);			g_free(before);			g_free(after);			/* Update the offsets of the next tags */			for (iter = next; iter; iter = iter->next) {				GntTextTag *t = iter->data;				t->start -= change;				t->end -= change;			}			/* Update the offsets of the segments */			for (iter = alllines; iter; iter = inext) {				GList *segs, *snext;				GntTextLine *line = iter->data;				inext = iter->next;				for (segs = line->segments; segs; segs = snext) {					GntTextSegment *seg = segs->data;					snext = segs->next;					if (seg->start >= tag->end) {						/* The segment is somewhere after the tag */						seg->start -= change;						seg->end -= change;					} else if (seg->end <= tag->start) {						/* This segment is somewhere in front of the tag */					} else if (seg->start >= tag->start) {						/* This segment starts in the middle of the tag */						if (text == NULL) {							free_text_segment(seg, NULL);							line->segments = g_list_delete_link(line->segments, segs);							if (line->segments == NULL) {								free_text_line(line, NULL);								if (view->list == iter) {									if (inext)										view->list = inext;									else										view->list = iter->prev;								}								alllines = g_list_delete_link(alllines, iter);							}						} else {							/* XXX: (null) */							seg->start = tag->start;							seg->end = tag->end - change;						}						line->length -= change;						/* XXX: Make things work if the tagged text spans over several lines. */					} else {						/* XXX: handle the rest of the conditions */						g_printerr("WTF! This needs to be handled properly!!\n");					}				}			}			if (text == NULL) {				/* Remove the tag */				view->tags = g_list_delete_link(view->tags, list);				free_tag(tag, NULL);			} else {				tag->end -= change;			}			if (!all)				break;		}	}	return count;}static gbooleanscroll_tv(GntWidget *wid, const char *key, GntTextView *tv){	if (strcmp(key, GNT_KEY_PGUP) == 0) {		gnt_text_view_scroll(tv, -(GNT_WIDGET(tv)->priv.height - 2));	} else if (strcmp(key, GNT_KEY_PGDOWN) == 0) {		gnt_text_view_scroll(tv, GNT_WIDGET(tv)->priv.height - 2);	} else if (strcmp(key, GNT_KEY_DOWN) == 0) {		gnt_text_view_scroll(tv, 1);	} else if (strcmp(key, GNT_KEY_UP) == 0) {		gnt_text_view_scroll(tv, -1);	} else {		return FALSE;	}	return TRUE;}void gnt_text_view_attach_scroll_widget(GntTextView *view, GntWidget *widget){	g_signal_connect(G_OBJECT(widget), "key_pressed", G_CALLBACK(scroll_tv), view);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -