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

📄 dw_page.c

📁 微型浏览器
💻 C
📖 第 1 页 / 共 3 页
字号:
								return shape->link;						}					}				}			}		}	}	return -1;}/* * Standard Dw function. */static gint Dw_page_button_press(DwWidget * widget, gint32 x, gint32 y, GdkEventButton * event){	DwPage *page = DW_PAGE(widget);#ifdef VERBOSE	g_print("Dw_page_button_press: button (%d, %d) +%d\n", x, y, button->button);#endif	page->link_pressed = Dw_page_find_link(page, x, y);	if (page->link_pressed >= 0) {		gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_PRESSED], page->links[page->link_pressed].url, event);		return TRUE;	} else		return FALSE;}/* * Standard Dw function. */static gint Dw_page_button_release(DwWidget * widget, gint32 x, gint32 y, GdkEventButton * event){	DwPage *page = DW_PAGE(widget);	char full_url[1024];	gint link_pressed, link_released; 	/* gint i, j, changed; */	link_pressed = page->link_pressed;	link_released = Dw_page_find_link(page, x, y);	page->link_pressed = -1;	if (link_released >= 0) {		gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_RELEASED], page->links[link_released].url, event);		if (link_pressed == link_released) {			/*			 * todo: How do we pass these datas to the server ?			 * Url.c functions can't deal with that yet			 */			if (page->x_click > 0) {				sprintf(full_url, "%s?%d,%d", page->links[link_pressed].url, page->x_click, page->y_click);				gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_CLICKED], full_url, event);			} else				gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_CLICKED], page->links[link_released].url, event);			/*			 * This is only a workaround to visualize links opened in a			 * new window. It will definitely change.			 */#if 0			if (link_released >= 0)				for (i = 0; i < page->num_lines; i++) {					changed = FALSE;					for (j = page->lines[i].first_word; j < page->lines[i].last_word; j++)						if (page->words[j].style->link == link_released) {							DwStyle style_attr = *(page->words[j].style);							style_attr.color = a_Dw_style_color_new(page->visited_color, widget->window);							a_Dw_style_unref(page->words[j].style);							page->words[j].style = a_Dw_style_new(&style_attr, widget->window);							changed = TRUE;						}					if (changed)						Dw_widget_queue_draw_area(widget, 0, page->lines[i].y_top, widget->allocation.width, page->lines[i].y_ascent + page->lines[i].y_descent);				}#endif			/* end workaround */		}		page->x_click = -1;		return TRUE;	} else		return FALSE;}/* * Standard Dw function. */static gint Dw_page_motion_notify(DwWidget * widget, gint32 x, gint32 y, GdkEventMotion * event){	DwPage *page = DW_PAGE(widget);	gint hover_link;	char full_url[1024];	hover_link = Dw_page_find_link(page, x, y);	if (hover_link >= 0 && page->x_click >= 0) {		sprintf(full_url, "%s?%d,%d", page->links[hover_link].url, page->x_click, page->y_click);		gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_ENTERED], full_url);	}	if (page->hover_link != hover_link) {		if (hover_link >= 0) {			/* If page->x_click >= 0, the signal has already been emitted. */			if (page->x_click < 0) {				if (page->links[hover_link].alt)					gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_ENTERED], page->links[hover_link].alt);				else					gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_ENTERED], page->links[hover_link].url);			}		} else			gtk_signal_emit(GTK_OBJECT(widget), page_signals[LINK_ENTERED], NULL);		page->hover_link = hover_link;		return TRUE;	} else		return FALSE;}/* * Create a new link, return the index. */gint a_Dw_page_new_link(DwPage * page, const char *url, const char *alt){	gint nl;	nl = page->num_links;	a_List_add(page->links, nl, sizeof(*page->links), page->num_links_max);	page->links[nl].url = url ? g_strdup(url) : NULL;	page->links[nl].alt = alt ? g_strdup(alt) : NULL;	return page->num_links++;}/* * Add a word to the page structure. Stashes the argument pointer in * the page data structure so that it will be deallocated on destroy. */void a_Dw_page_add_text(DwPage * page, char *text, DwStyle * style){	DwPageWord *word;	gint x_size, y_ascent, y_descent;	/* todo: ???	   if (attr >= page->num_attrs || page->attrs[attr].font >= page->num_fonts)	   return;                   / *BUG: Should use default text! * /	 */	x_size = gdk_string_width(style->font->font, text);	y_ascent = style->font->font->ascent;	y_descent = style->font->font->descent;	/* In case of a sub or super script we increase the word's height and	 * potentially the line's height. 	 */	if (style->SubSup == TEXT_SUB)		y_descent += (y_ascent / 2);	else if (style->SubSup == TEXT_SUP)		y_ascent += (y_ascent / 3);	word = Dw_page_new_word(page, x_size, y_ascent, y_descent, style);	word->content_type = DW_PAGE_CONTENT_TEXT;	word->content.text = text;	word->style = style;	a_Dw_style_ref(style);}/* * Add a widget (word type) to the page. todo: comments. */void a_Dw_page_add_widget(DwPage * page, DwWidget * widget, gfloat rel_width, gfloat rel_height, DwStyle * style){	DwPageWord st_word, *word;	gint x_size, y_ascent, y_descent;	/* First, find the child widget's width. For now, we always	 * give the minimum requisition, but that will change with table	 * support (tables should probably get 100% of the set width - the	 * margins, or the maximum requisition, whichever is smaller). */	/* todo: a bit kludgy */	st_word.content.widget.rel_width = rel_width;	st_word.content.widget.rel_height = rel_height;	st_word.content.widget.widget = widget;	Dw_page_calc_widget_size(page, &st_word);	x_size = st_word.x_size;	y_ascent = st_word.y_ascent;	y_descent = st_word.y_descent;	word = Dw_page_new_word(page, x_size, y_ascent, y_descent, style);	word->content_type = DW_PAGE_CONTENT_WIDGET;	word->content.widget.widget = widget;	word->content.widget.rel_width = rel_width;	word->content.widget.rel_height = rel_height;	word->style = style;	a_Dw_style_ref(style);	Dw_widget_set_parent(widget, DW_WIDGET(page));	a_Dw_widget_set_style(widget, style);}/* * Add an anchor to the page. name is copied, so no strdup is neccessary for * the caller. */void a_Dw_page_add_anchor(DwPage * page, char *name, DwStyle * style){	DwPageWord *word;	word = Dw_page_new_word(page, 0, 0, 0, style);	word->content_type = DW_PAGE_CONTENT_ANCHOR;	word->content.anchor = g_strdup(name);	word->style = style;	a_Dw_style_ref(style);	Dw_widget_set_anchor(DW_WIDGET(page), word->content.anchor, page->lines[page->num_lines - 1].y_top);}/* * ? */void a_Dw_page_add_space(DwPage * page, DwStyle * style){	gint nl, nw;	gint space;	nl = page->num_lines - 1;	if (nl >= 0) {		nw = page->num_words - 1;		if (nw >= 0) {			space = style->font->space_width;			page->words[nw].x_space = space;		}	}}/* * Cause a line break */void a_Dw_page_linebreak(DwPage * page){	gint i;	i = page->num_lines;	if (i == 0)		return;	page->lines[i - 1].hard = TRUE;}/* * Cause a paragraph break */void a_Dw_page_parbreak(DwPage * page, gint space){	gint i;	i = page->num_lines;	if (i == 0)		return;	page->lines[i - 1].hard = TRUE;	if (space > page->lines[i - 1].y_space)		page->lines[i - 1].y_space = space;}/* * Call this routine before updating the state. By wrapping all state * changes between these two routines, the internal state of the widget * always matches the display, without requiring each state change * operation to calculate updates on a fine-grained basis. */void a_Dw_page_update_begin(DwPage * page){}/* * Call this routine after updating the state. */void a_Dw_page_update_end(DwPage * page){	Dw_widget_queue_resize(DW_WIDGET(page));}typedef struct {	gint LineNum;	gint Index;} LineData;typedef enum {	F_NewKey,	F_Read,	F_Seek,	F_Found,	F_End} FindState;typedef struct {	gchar *Key;	guint KeyLen;	DwPage *Page;	gint LineNum;	gint Matches;	GSList *IList;	GString *TextBuf;	gchar StopSet[3];	gint Eof;	FindState State;} FindData;/* * Read lines into local buffer */void Dw_page_read_lines(FindData * F, gint N){	gint i, j, nw;	LineData *LNode;	for (j = 0; F->LineNum < F->Page->num_lines && j < N; F->LineNum++, j++) {		LNode = g_new(LineData, 1);		LNode->LineNum = F->LineNum;		LNode->Index = F->TextBuf->len;		F->IList = g_slist_append(F->IList, LNode);		/* This can find strings that span over two or more lines */		for (nw = i = F->Page->lines[F->LineNum].first_word; i < F->Page->lines[F->LineNum].last_word; i++) {			if (F->Page->words[i].content_type != DW_PAGE_CONTENT_TEXT)				continue;			F->TextBuf = g_string_append(F->TextBuf, F->Page->words[i].content.text);			F->TextBuf = g_string_append(F->TextBuf, " ");			++nw;		}		if (nw == 0)	/* Empty line ? */			F->IList = g_slist_remove(F->IList, LNode);	}	F->Eof = (F->LineNum == F->Page->num_lines);}/* * Erase the first N characters from local buffer */void Dw_page_erase_chars(FindData * F, gint N){	gint i;	LineData *LNode, *LNext;	for (i = 0; (LNode = g_slist_nth_data(F->IList, i)); i++)		LNode->Index -= N;	while ((LNode = g_slist_nth_data(F->IList, 0)) && LNode->Index <= 0) {		LNode->Index = 0;		if ((LNext = g_slist_nth_data(F->IList, 1)) && LNext->Index <= 0)			F->IList = g_slist_remove(F->IList, LNode);		else			break;	}	F->TextBuf = g_string_erase(F->TextBuf, 0, N);}/* * Erase the local buffer */void Dw_page_erase_buf(FindData * F){	LineData *LNode;	if (F->IList)		while ((LNode = g_slist_nth_data(F->IList, 0)))			F->IList = g_slist_remove(F->IList, LNode);	if (F->TextBuf)		F->TextBuf = g_string_truncate(F->TextBuf, 0);}/* * Find the text in the page. */void a_Dw_page_find_text(DwPage * page, char *NewKey){	gint i;	gchar *Ptr = NULL;	LineData *LNode;	static FindData *F = NULL;	DwWidget *widget = DW_WIDGET(page);	g_return_if_fail(widget->viewport != NULL);	if (!F)		F = g_new0(FindData, 1);	if (!F->Key || strcmp(F->Key, NewKey) || F->Page != page)		F->State = F_NewKey;	/* Let the FSM find the search string */	while (1) {		switch (F->State) {		case F_NewKey:			if (!F->TextBuf)				F->TextBuf = g_string_sized_new(256);			if (F->Key)				g_free(F->Key);			F->Key = g_strdup(NewKey);			if (!(F->KeyLen = strlen(F->Key)))				return;			sprintf(F->StopSet, "%c%c", tolower(F->Key[0]), toupper(F->Key[0]));			Dw_page_erase_buf(F);			F->Page = page;			F->Matches = F->LineNum = F->Eof = 0;			F->State = F_Read;			break;		case F_Read:			if (F->Eof)				F->State = F_End;			else {				Dw_page_read_lines(F, 10);				F->State = F_Seek;			}			// g_print("TextBuf: %s\n", F->TextBuf->str);			break;		case F_Seek:			if (!(Ptr = strpbrk(F->TextBuf->str, F->StopSet))) {				Dw_page_erase_buf(F);				F->State = F_Read;			} else if (strlen(Ptr) < F->KeyLen) {				F->State = F_Read;			} else if (g_strncasecmp(Ptr, F->Key, F->KeyLen) == 0) {				Dw_page_erase_chars(F, Ptr - F->TextBuf->str);				F->State = F_Found;			} else				Dw_page_erase_chars(F, Ptr - F->TextBuf->str + 1);			break;		case F_Found:			F->Matches++;			LNode = g_slist_nth_data(F->IList, 0);			i = LNode->LineNum;			a_Dw_widget_scroll_to(widget, page->lines[i].y_top);			Dw_page_erase_chars(F, 1);			F->State = F_Seek;			return;		case F_End:			if (F->Matches)				F->State = F_NewKey;			else				return;		}	}}

⌨️ 快捷键说明

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