📄 dw_page.c
字号:
gint32 y, GdkEventButton *event){ DwPage *page = DW_PAGE (widget); gint link_pressed, link_released;#ifdef VERBOSE g_print("Dw_page_button_release: button (%d, %d) +%d\n", x, y, event->button);#endif 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], link_released, -1, -1, event); if (link_pressed == link_released) { gtk_signal_emit (GTK_OBJECT (widget), page_signals[LINK_CLICKED], link_released, -1, -1, event); } 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 link, link_old; link_old = page->hover_link; link = Dw_page_find_link(page, x, y); page->hover_link = link; if (link != link_old) { gtk_signal_emit (GTK_OBJECT (widget), page_signals[LINK_ENTERED], link, -1, -1); return TRUE; } else return (link != -1);}/* * Standard Dw function. */static gint Dw_page_leave_notify (DwWidget *widget, DwWidget *next5_widget, GdkEventMotion *event){ DwPage *page = DW_PAGE (widget); if (page->hover_link != -1) { page->hover_link = -1; gtk_signal_emit (GTK_OBJECT (widget), page_signals[LINK_ENTERED], -1, -1, -1); } return FALSE;}/* * Add a new word (text, widget etc.) to a page. */static DwPageWord *Dw_page_add_word(DwPage *page, gint width, gint ascent, gint descent, DwStyle *style){ DwPageWord *word; page->num_words++; a_List_add(page->words, page->num_words, page->num_words_max); word = &page->words[page->num_words - 1]; word->size.width = width; word->orig_space = 0; word->eff_space = 0; word->size.ascent = ascent; word->size.descent = descent; word->style = style; word->space_style = style; a_Dw_style_ref (style); a_Dw_style_ref (style); return word;}/* * 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 width, ascent, descent; width = gdk_string_width(style->font->font, text); ascent = style->font->font->ascent; 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) descent += (ascent / 2); else if (style->SubSup == TEXT_SUP) ascent += (ascent / 3); word = Dw_page_add_word(page, width, ascent, descent, style); word->content_type = DW_PAGE_CONTENT_TEXT; word->content.text = text; Dw_page_word_wrap (page, page->num_words - 1);}/* * Add a widget (word type) to the page. */void a_Dw_page_add_widget (DwPage *page, DwWidget *widget, DwStyle *style){ DwPageWord *word; DwRequisition size; p_Dw_widget_set_parent (widget, DW_WIDGET (page)); a_Dw_widget_set_style (widget, style); Dw_page_calc_widget_size (page, widget, &size); word = Dw_page_add_word(page, size.width, size.ascent, size.descent, style); word->content_type = DW_PAGE_CONTENT_WIDGET; word->content.widget = widget; Dw_page_word_wrap (page, page->num_words - 1); word->content.widget->parent_ref = page->num_lines - 1;}/* * 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, const char *name, DwStyle *style){ DwPageWord *word; word = Dw_page_add_word(page, 0, 0, 0, style); word->content_type = DW_PAGE_CONTENT_ANCHOR; word->content.anchor = g_strdup(name); Dw_page_word_wrap (page, page->num_words - 1); p_Dw_widget_set_anchor(DW_WIDGET(page), word->content.anchor, page->lines[page->num_lines - 1].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].orig_space = space; page->words[nw].eff_space = space; a_Dw_style_unref (page->words[nw].space_style); page->words[nw].space_style = style; a_Dw_style_ref (style); } }}/* * Cause a paragraph break */void a_Dw_page_add_parbreak(DwPage *page, gint space, DwStyle *style){ DwPageWord *word, *word2; DwWidget *widget; DwPage *page2; gboolean isfirst; gint lineno; /* A break may not be the first word of a page, or directly after the bullet/number (which is the first word) in a list item. (See also comment in Dw_page_size_request.) */ if (page->num_words == 0 || (page->list_item && page->num_words == 1)) { /* This is a bit hackish: If a break is added as the first/second word of a page, and the parent widget is also a DwPage, and there is a break before -- this is the case when a widget is used as a text box (lists, blockquotes, list items etc) -- then we simply adjust the break before, in a way that the space is in any case visible. */ /* Find the widget where to adjust the break_space. */ for (widget = DW_WIDGET(page); widget->parent && DW_IS_PAGE (widget->parent); widget = widget->parent) { page2 = DW_PAGE(widget->parent); if (page2->list_item) isfirst = (page2->words[1].content_type == DW_PAGE_CONTENT_WIDGET && page2->words[1].content.widget == widget); else isfirst = (page2->words[0].content_type == DW_PAGE_CONTENT_WIDGET && page2->words[0].content.widget == widget); if (!isfirst) { /* The page we searched for has been found. */ lineno = widget->parent_ref; if (lineno > 0 && (word2 = &page2->words[page2->lines[lineno - 1].first_word]) && word2->content_type == DW_PAGE_CONTENT_BREAK) { if(word2->content.break_space < space) { word2->content.break_space = space; p_Dw_widget_queue_resize (DW_WIDGET(page2), lineno, FALSE); page2->must_queue_resize = FALSE; } } return; } /* Otherwise continue to examine parents. */ } /* Return in any case. */ return; } /* Another break before? */ if ((word = &page->words[page->num_words - 1]) && word->content_type == DW_PAGE_CONTENT_BREAK) { word->content.break_space = MAX (word->content.break_space, space); return; } word = Dw_page_add_word(page, 0, 0, 0, style); word->content_type = DW_PAGE_CONTENT_BREAK; word->content.break_space = space; Dw_page_word_wrap (page, page->num_words - 1);}/* * Cause a line break. */void a_Dw_page_add_linebreak (DwPage *page, DwStyle *style){ DwPageWord *word; word = Dw_page_add_word(page, 0, style->font->font->ascent, style->font->font->descent, style); word->content_type = DW_PAGE_CONTENT_BREAK; word->content.break_space = 0; word->style = style; //a_Dw_style_ref (style); Dw_page_word_wrap (page, page->num_words - 1);}/* * This function "hands" the last break of a page "over" to a parent * page. This is used for "collapsing spaces". */void a_Dw_page_hand_over_break (DwPage *page, DwStyle *style){ DwPageLine *last_line; DwWidget *parent; if (page->num_lines == 0) return; last_line = &page->lines[page->num_lines - 1]; if (last_line->break_space != 0 && (parent = DW_WIDGET(page)->parent) && DW_IS_PAGE (parent)) a_Dw_page_add_parbreak (DW_PAGE (parent), last_line->break_space, style);}/* * todo: comment */void a_Dw_page_flush (DwPage *page){ if (page->must_queue_resize) { p_Dw_widget_queue_resize (DW_WIDGET(page), -1, TRUE); page->must_queue_resize = FALSE; }}/* * Find the text in the page. * (Standar DwContainer function) -- todo: move near forall */static gint Dw_page_findtext(DwContainer *container, gpointer FP, gpointer KP, gchar *NewKey){ gint i; DwPageWord *word; FindData *F, *Fi, *Fj; DwPage *page = DW_PAGE(container); g_return_val_if_fail ((DW_WIDGET(page))->viewport != NULL, 0); if (!NewKey || !*NewKey) return 0; if ( !(F = *(FindData**)FP) ) *(FindData **)FP = F = g_new0(FindData, 1); if ( !F->Key || strcmp(F->Key->KeyStr, NewKey) || F->widget != DW_WIDGET (page) ) F->State = F_NewKey; /* Let the FSM find the search string */ while ( 1 ) { switch (F->State) { case F_NewKey: /* free FindData stack */ for (Fi = F->next; Fi; Fi = Fj){ Fj = Fi ? Fi->next : NULL; g_free(Fi); } /* initialize F */ if (!KP && F->Key) a_Findtext_key_free(F->Key); F->Key = (KP) ? KP : a_Findtext_key_new(NewKey); F->widget = DW_WIDGET (page); F->WordNum = 0; F->next = NULL; F->State = F_Seek; break; case F_Seek: for ( ; F->WordNum < page->num_words; F->WordNum++) { word = &page->words[F->WordNum]; if (word->content_type == DW_PAGE_CONTENT_TEXT && a_Findtext_compare(word->content.text, F->Key)) { F->State = F_GetPos; break; } else if (word->content_type == DW_PAGE_CONTENT_WIDGET && DW_IS_CONTAINER (word->content.widget)) { if ( a_Dw_container_findtext( DW_CONTAINER(word->content.widget), (gpointer)&F->next, (gpointer)F->Key, NewKey) ) { F->State = F_Seek; return 1; } } } if (F->WordNum == page->num_words) F->State = F_End; break; case F_GetPos: if (F->Key->y_pos < 0) { for (i = 0; page->lines[i].last_word <= F->WordNum; ++i); F->Key->y_pos = page->lines[i].top; } F->WordNum++; F->State = (g_slist_length(F->Key->WordList) == F->Key->Matches) ? F_Found : F_Seek; break; case F_Found: a_Dw_widget_scroll_to(DW_WIDGET (page), F->Key->y_pos); //g_print(">>>[Wn %d]\n", F->WordNum); F->State = F_Seek; return 1; case F_End: /* free memory */ if (!KP && F->Key) a_Findtext_key_free(F->Key); g_free(F); *(FindData **)FP = NULL; return 0; } } /* compiler happiness */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -