📄 dw_page.c
字号:
Dw_page_get_word_extremes (word, &word_extremes); last_space = (word_ind > 0) ? page->words[word_ind - 1].orig_space : 0; if (word->content_type == DW_PAGE_CONTENT_BREAK) last_line->break_space = MAX (word->content.break_space, last_line->break_space); page->last_line_width += word->size.width; if (!new_line) page->last_line_width += last_space; last_line->par_max += word_extremes.max_width; if (!new_par) last_line->par_max += last_space; if (word->style->nowrap) last_line->par_min += word_extremes.min_width; else last_line->max_word_min = MAX (last_line->max_word_min, word_extremes.min_width); /* Finally, justify the line. Breaks are ignored, since the HTML * parser sometimes assignes the wrong style to them. (todo: ) */ if (word->content_type != DW_PAGE_CONTENT_BREAK) { switch (word->style->text_align) { case DW_STYLE_TEXT_ALIGN_LEFT: 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; } else last_line->left_offset = left_offset; } page->must_queue_resize = TRUE;}/* * 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; avail_width = page->avail_width - p_Dw_style_box_diff_width(DW_WIDGET(page)->style); 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); } else { if (widget->style->width == DW_STYLE_UNDEF_LENGTH || widget->style->height == DW_STYLE_UNDEF_LENGTH) a_Dw_widget_size_request (widget, &requisition); if (widget->style->width == DW_STYLE_UNDEF_LENGTH) size->width = requisition.width; else if (DW_STYLE_IS_LENGTH (widget->style->width)) size->width = DW_STYLE_GET_LENGTH (widget->style->width, widget->style->font) + p_Dw_style_box_diff_width (widget->style); else size->width = DW_STYLE_GET_PERCENTAGE (widget->style->width) * avail_width; if (widget->style->height == DW_STYLE_UNDEF_LENGTH) { size->ascent = requisition.ascent; size->descent = requisition.descent; } else if (DW_STYLE_IS_LENGTH (widget->style->width)) { size->ascent = DW_STYLE_GET_LENGTH (widget->style->height, widget->style->font) + p_Dw_style_box_diff_height (widget->style); size->descent = 0; } else { size->ascent = DW_STYLE_GET_PERCENTAGE (widget->style->height) * avail_ascent; size->descent = DW_STYLE_GET_PERCENTAGE (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 word_index; DwPageWord *word; if (page->wrap_ref == -1) return; widget = DW_WIDGET (page); page->num_lines = page->wrap_ref; page->last_line_width = 0; if (page->num_lines > 0) word_index = page->lines[page->num_lines - 1].first_word; else word_index = 0; for (; word_index < page->num_words; word_index++) { word = &page->words[word_index]; if (word->content_type == DW_PAGE_CONTENT_WIDGET) Dw_page_calc_widget_size (page, word->content.widget, &word->size); Dw_page_word_wrap(page, word_index); if (word->content_type == DW_PAGE_CONTENT_WIDGET) word->content.widget->parent_ref = page->num_lines - 1; if ( word->content_type == DW_PAGE_CONTENT_ANCHOR ) { p_Dw_widget_set_anchor(widget, word->content.anchor, page->lines[page->num_lines - 1].top); } }}/* * 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; gint x_cursor, y_cursor; gint diff; DwWidget *child; DwRectangle child_area; GdkWindow *window; /* 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); x_cursor = p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x + Dw_page_line_total_x_offset(page,line)); y_cursor = p_Dw_widget_y_world_to_viewport (widget, widget->allocation.y + line->top + line->ascent); for (word_index = line->first_word; word_index < line->last_word; word_index++) { word = &page->words[word_index]; diff = 0; switch (word->content_type) { case DW_PAGE_CONTENT_TEXT: /* Adjust the text baseline if the word is <SUP>-ed or <SUB>-ed */ if (word->style->SubSup == TEXT_SUB) diff = word->size.ascent / 2; else if (word->style->SubSup == TEXT_SUP) diff -= word->size.ascent / 3; gdk_draw_string(window, word->style->font->font, word->style->color->gc, x_cursor, y_cursor + diff, word->content.text); /* underline */ if (word->style->uline) gdk_draw_line(window, word->style->color->gc, x_cursor, y_cursor + 1 + diff, x_cursor + word->size.width - 1, y_cursor + 1 + diff); if (word_index + 1 < line->last_word && word->space_style->uline) gdk_draw_line(window, word->style->color->gc, x_cursor + word->size.width, y_cursor + 1 + diff, x_cursor + word->size.width + word->eff_space - 1, y_cursor + 1 + diff); /* strike-through */ if (word->style->strike) gdk_draw_line(window, word->style->color->gc, x_cursor, y_cursor - word->size.ascent / 2 + diff, x_cursor + word->size.width - 1, y_cursor - word->size.ascent / 2 + diff); if (word_index + 1 < line->last_word && word->space_style->strike) gdk_draw_line(window, word->style->color->gc, x_cursor + word->size.width, y_cursor - word->size.ascent / 2 + diff, x_cursor + word->size.width + word->eff_space - 1, y_cursor - word->size.ascent / 2 + diff); break; case DW_PAGE_CONTENT_WIDGET: child = word->content.widget; if (p_Dw_widget_intersect (child, area, &child_area)) a_Dw_widget_draw (child, &child_area, event); break; case DW_PAGE_CONTENT_ANCHOR: case DW_PAGE_CONTENT_BREAK: /* nothing - an anchor/break isn't seen */ /* BUG: sometimes anchors have x_space; * we subtract that just in case --EG */ x_cursor -= word->size.width + word->eff_space;#if 0 /* Useful for testing: draw breaks. */ if (word->content_type == DW_PAGE_CONTENT_BREAK) gdk_draw_rectangle (window, word->style->color->gc, TRUE, Dw_widget_x_world_to_viewport(widget, widget->allocation.x + Dw_page_line_total_x_offset(page, line)), y_cursor + line->descent, widget->allocation.width - Dw_style_box_diff_width(widget->style), word->content.break_space);#endif break; default: g_warning ("BUG!!! at (%d, %d).", x_cursor, y_cursor + diff); break; } x_cursor += word->size.width + word->eff_space; }}/* * Find the first line index that includes y, relative to top of widget. */static gint Dw_page_find_line_index(DwPage *page, gint y){ gint max_index = page->num_lines - 1; gint step, index, low = 0; step = (page->num_lines+1) >> 1; while ( step > 1 ) { index = low + step; if (index <= max_index && page->lines[index].top < y) low = index; step = (step + 1) >> 1; } if (low < max_index && page->lines[low+1].top < y) low++; /* * This new routine returns the line number between (top) and * (top + size.ascent + size.descent + break_space): the space * _below_ the line is considered part of the line. Old routine * returned line number between (top - previous_line->break_space) * and (top + size.ascent + size.descent): the space _above_ the * line was considered part of the line. This is important for * Dw_page_find_link() --EG */ return low;}/* * Draw the actual lines, starting at (x, y) in toplevel Dw coords. * (former Dw_page_expose_lines) */static void Dw_page_draw (DwWidget *widget, DwRectangle *area, GdkEventExpose *event){ DwPage *page; gint line_index; DwPageLine *line; p_Dw_widget_draw_widget_box (widget, area); page = DW_PAGE (widget); line_index = Dw_page_find_line_index(page, area->y); for (; line_index < page->num_lines; line_index++) { line = &(page->lines[line_index]); if (line->top >= area->y + area->height) break; Dw_page_draw_line (page, line, area, event); }}/* * Find a link given a coordinate location relative to the window */static gint Dw_page_find_link(DwPage *page, gint x, gint y){ gint line_index, word_index; gint x_cursor, last_x_cursor; DwPageLine *line; DwPageWord *word; if ( (line_index = Dw_page_find_line_index(page, y)) >= page->num_lines ) return -1; line = &page->lines[line_index]; if (line->top + line->ascent + line->descent <= y) return -1; x_cursor = Dw_page_line_total_x_offset(page, line); for (word_index = line->first_word; word_index < line->last_word; word_index++) { word = &page->words[word_index]; last_x_cursor = x_cursor; x_cursor += word->size.width + word->eff_space; if (last_x_cursor <= x && x_cursor > x) return word->style->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->link_pressed, -1, -1, event); return TRUE; } else return FALSE;}/* * Standard Dw function. */static gint Dw_page_button_release(DwWidget *widget, gint32 x,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -