📄 dw_page.c
字号:
case DW_STYLE_TEXT_ALIGN_JUSTIFY: /* see some lines above */ case DW_STYLE_TEXT_ALIGN_STRING: /* handled elsewhere (in future) */ left_offset = 0; break; case DW_STYLE_TEXT_ALIGN_RIGHT: left_offset = avail_width - page->last_line_width; break; case DW_STYLE_TEXT_ALIGN_CENTER: left_offset = (avail_width - page->last_line_width) / 2; break; default: /* compiler happiness */ left_offset = 0; } /* For large lines (images etc), which do not fit into the viewport: */ if (left_offset < 0) left_offset = 0; if (page->list_item && last_line == page->lines) { /* List item markers are always on the left. */ last_line->left_offset = 0; page->words[0].eff_space = page->words[0].orig_space + left_offset; DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", 0, page->words[0].eff_space); } else last_line->left_offset = left_offset; } page->must_queue_resize = TRUE; DBG_MSG_END (page);}/* * Calculate the size of a widget within the page. * (Subject of change in the near future!) */static void Dw_page_calc_widget_size (DwPage *page, DwWidget *widget, DwRequisition *size){ DwRequisition requisition; gint32 avail_width, avail_ascent, avail_descent; /* We ignore line1_offset[_eff]. */ avail_width = page->avail_width - p_Dw_style_box_diff_width (DW_WIDGET(page)->style) - page->inner_padding; avail_ascent = page->avail_ascent - p_Dw_style_box_diff_height (DW_WIDGET(page)->style); avail_descent = page->avail_descent; if (DW_WIDGET_USES_HINTS (widget)) { a_Dw_widget_set_width (widget, avail_width); a_Dw_widget_set_ascent (widget, avail_ascent); a_Dw_widget_set_descent (widget, avail_descent); a_Dw_widget_size_request (widget, size); size->ascent -= widget->style->margin.top; size->descent -= widget->style->margin.bottom; } else { /* TODO: Use margin.{top|bottom} here, like above. * (No harm for the next future.) */ if (widget->style->width == DW_STYLE_LENGTH_AUTO || widget->style->height == DW_STYLE_LENGTH_AUTO) a_Dw_widget_size_request (widget, &requisition); if (widget->style->width == DW_STYLE_LENGTH_AUTO) size->width = requisition.width; else if (DW_STYLE_IS_ABS_LENGTH (widget->style->width)) /* Fixed lengths are only applied to the content, so we have to * add padding, border and margin. */ size->width = DW_STYLE_ABS_LENGTH_VAL (widget->style->width) + p_Dw_style_box_diff_width (widget->style); else size->width = DW_STYLE_PER_LENGTH_VAL (widget->style->width) * avail_width; if (widget->style->height == DW_STYLE_LENGTH_AUTO) { size->ascent = requisition.ascent; size->descent = requisition.descent; } else if (DW_STYLE_IS_ABS_LENGTH (widget->style->height)) { /* Fixed lengths are only applied to the content, so we have to * add padding, border and margin. */ size->ascent = DW_STYLE_ABS_LENGTH_VAL (widget->style->height) + p_Dw_style_box_diff_height (widget->style); size->descent = 0; } else { size->ascent = DW_STYLE_PER_LENGTH_VAL (widget->style->height) * avail_ascent; size->descent = DW_STYLE_PER_LENGTH_VAL (widget->style->height) * avail_descent; } }}/* * Rewrap the page from the line from which this is necessary. * There are basically two times we'll want to do this: * either when the viewport is resized, or when the size changes on one * of the child widgets. */static void Dw_page_rewrap (DwPage *page){ DwWidget *widget; gint i, word_index; DwPageWord *word; DwPageLine *last_line; if (page->wrap_ref == -1) /* page does not have to be rewrapped */ return; widget = DW_WIDGET (page); DBG_MSGF (page, "wrap", 0, "Dw_page_rewrap: page->wrap_ref = %d, in page with %d word(s)", page->wrap_ref, page->num_words); DBG_MSG_START (page); /* All lines up from page->wrap_ref will be rebuild from the word list, * the line list up from this position is rebuild. */ page->num_lines = page->wrap_ref; page->last_line_width = 0; DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines); DBG_OBJ_SET_NUM(page, "last_line_width", page->last_line_width); /* In the word list, we start at the last word, plus one (see definition * of last_word), in the line before. */ if (page->wrap_ref > 0) { /* Note: In this case, Dw_page_real_word_wrap will immediately find * the need to rewrap the line, since we start with the last one (plus * one). This is also the reason, why page->last_line_width is set * to the length of the line. */ last_line = &page->lines[page->num_lines - 1]; page->last_line_par_min = last_line->par_min; page->last_line_par_max = last_line->par_max; word_index = last_line->last_word; for (i = last_line->first_word; i < last_line->last_word - 1; i++) page->last_line_width += (page->words[i].size.width + page->words[i].orig_space); page->last_line_width += page->words[last_line->last_word - 1].size.width; } else { page->last_line_par_min = 0; page->last_line_par_max = 0; word_index = 0; } for (; word_index < page->num_words; word_index++) { word = &page->words[word_index]; if (word->content.type == DW_CONTENT_WIDGET) Dw_page_calc_widget_size (page, word->content.data.widget, &word->size); Dw_page_word_wrap (page, word_index); if (word->content.type == DW_CONTENT_WIDGET) { word->content.data.widget->parent_ref = page->num_lines - 1; DBG_OBJ_SET_NUM (word->content.data.widget, "parent_ref", word->content.data.widget->parent_ref); } DEBUG_MSG(DEBUG_REWRAP_LEVEL, "Assigning parent_ref = %d to rewrapped word %d, " "in page with %d word(s)\n", page->num_lines - 1, word_index, page->num_words); if ( word->content.type == DW_CONTENT_ANCHOR ) p_Dw_gtk_viewport_put_anchor (widget, word->content.data.anchor, Dw_page_line_total_y_offset (page, &page->lines[page->num_lines - 1])); } /* Next time, the page will not have to be rewrapped. */ page->wrap_ref = -1; DBG_MSG_END (page);}/* * Paint a line * - x and y are toplevel dw coordinates (Question: what Dw? Changed. Test!) * - area is used always (ev. set it to event->area) * - event is only used when is_expose */static void Dw_page_draw_line (DwPage *page, DwPageLine *line, DwRectangle *area, GdkEventExpose *event){ DwWidget *widget; DwPageWord *word; gint word_index; gint32 x_widget, y_widget, x_viewport, y_viewport, y_viewport_base; gint32 start_hl, width_hl; gint32 diff, word_len, eff_hl_end, layer; DwWidget *child; DwRectangle child_area; GdkWindow *window; GdkGC *gc, *hl_gc; DwStyleColor *page_bg_color, *word_bg_color; /* Here's an idea on how to optimize this routine to minimize the number * of calls to gdk_draw_string: * * Copy the text from the words into a buffer, adding a new word * only if: the attributes match, and the spacing is either zero or * equal to the width of ' '. In the latter case, copy a " " into * the buffer. Then draw the buffer. */ widget = DW_WIDGET (page); window = DW_WIDGET_WINDOW (widget); page_bg_color = p_Dw_widget_get_bg_color (widget); x_widget = Dw_page_line_total_x_offset(page,line); x_viewport = p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x + x_widget); y_widget = Dw_page_line_total_y_offset(page,line); y_viewport = p_Dw_widget_y_world_to_viewport (widget, widget->allocation.y + y_widget); y_viewport_base = y_viewport + line->ascent; for (word_index = line->first_word; word_index < line->last_word; word_index++) { word = &page->words[word_index]; diff = 0; gc = word->style->color->gc; DBG_OBJ_ARRSET_NUM (page, "words.%d.<i>drawn at</i>.x", word_index, x_widget); DBG_OBJ_ARRSET_NUM (page, "words.%d.<i>drawn at</i>.y", word_index, y_widget); switch (word->content.type) { case DW_CONTENT_TEXT: if (word->style->background_color) word_bg_color = word->style->background_color; else word_bg_color = page_bg_color; /* Adjust the text baseline if the word is <SUP>-ed or <SUB>-ed. */ if (word->style->valign == DW_STYLE_VALIGN_SUB) diff = word->size.ascent / 2; else if (word->style->valign == DW_STYLE_VALIGN_SUPER) diff -= word->size.ascent / 3; /* Draw background (color, image), when given. */ /* todo: Test (word->style->background_color) is incomplete, and * should in future include background images. */ if (word->style->background_color && word->size.width > 0) p_Dw_widget_draw_box (widget, word->style, area, x_widget, y_widget + line->ascent - word->size.ascent, word->size.width, word->size.ascent + word->size.descent, FALSE); /* Draw space background (color, image), when given. */ /* todo: Test (word->space_style->background_color) is incomplete, and * should in future include background images. */ if (word->space_style->background_color && word->eff_space > 0) p_Dw_widget_draw_box (widget, word->space_style, area, x_widget + word->size.width, y_widget + line->ascent - word->size.ascent, word->eff_space, word->size.ascent + word->size.descent, FALSE); gdk_draw_string (window, word->style->font->font, gc, x_viewport, y_viewport_base + diff, word->content.data.text); /* underline */ if (word->style->text_decoration & DW_STYLE_TEXT_DECORATION_UNDERLINE) gdk_draw_line (window, gc, x_viewport, y_viewport_base + 1 + diff, x_viewport + word->size.width - 1, y_viewport_base + 1 + diff); if (word_index + 1 < line->last_word && (word->space_style->text_decoration & DW_STYLE_TEXT_DECORATION_UNDERLINE)) gdk_draw_line (window, gc, x_viewport + word->size.width, y_viewport_base + 1 + diff, x_viewport + word->size.width + word->eff_space - 1, y_viewport_base + 1 + diff); /* strike-through */ if (word->style->text_decoration & DW_STYLE_TEXT_DECORATION_LINE_THROUGH) gdk_draw_line (window, gc, x_viewport, y_viewport_base - word->size.ascent / 2 + diff, x_viewport + word->size.width - 1, y_viewport_base - word->size.ascent / 2 + diff); if (word_index + 1 < line->last_word && (word->space_style->text_decoration & DW_STYLE_TEXT_DECORATION_LINE_THROUGH)) gdk_draw_line (window, gc, x_viewport + word->size.width, y_viewport_base - word->size.ascent / 2 + diff, x_viewport + word->size.width + word->eff_space - 1, y_viewport_base - word->size.ascent / 2 + diff); for (layer = 0; layer < DW_HIGHLIGHT_NUM_LAYERS; layer++) { if (word->hl_start[layer] != -1) { word_len = strlen (word->content.data.text); eff_hl_end = MIN (word_len, word->hl_end[layer]); start_hl = x_viewport + gdk_text_width (word->style->font->font, word->content.data.text, word->hl_start[layer]); width_hl = gdk_text_width (word->style->font->font, word->content.data.text + word->hl_start[layer], eff_hl_end - word->hl_start[layer]); /* If the space after this word highlighted, and this word * is not the last one in this line, highlight also the * space. */ /* todo: This should also be done with spaces after non-text * words, but this is not yet defined very well. */ if (word->hl_end[layer] > eff_hl_end && word_index < page->num_words && word_index != line->last_word - 1) width_hl += word->eff_space; if (width_hl != 0) { /* Draw background for highlighted text. */ gdk_draw_rectangle (window, word_bg_color->inverse_gc, TRUE, start_hl, y_viewport_base - word->size.ascent, width_hl, word->size.ascent + word->size.descent); /* Highlight the text. */ hl_gc = word->style->color->inverse_gc; gdk_draw_text (window, word->style->font->font, hl_gc, start_hl, y_viewport_base + diff, word->content.data.text + word->hl_start[layer], eff_hl_end - word->hl_start[layer]); /* underline and strike-through */ if (word->style->text_decoration & DW_STYLE_TEXT_DECORATION_UNDERLINE) gdk_draw_line (window, hl_gc, start_hl, y_viewport_base + 1 + diff, start_hl + width_hl - 1, y_viewport_base + 1 + diff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -