📄 dw_page.c
字号:
if (word->style->text_decoration & DW_STYLE_TEXT_DECORATION_LINE_THROUGH) gdk_draw_line (window, hl_gc, start_hl, y_viewport_base - word->size.ascent / 2 + diff, start_hl + width_hl - 1, y_viewport_base - word->size.ascent / 2 + diff); } } } break; case DW_CONTENT_WIDGET: child = word->content.data.widget; if (p_Dw_widget_intersect (child, area, &child_area)) a_Dw_widget_draw (child, &child_area, event); break; case DW_CONTENT_ANCHOR: case DW_CONTENT_BREAK: /* nothing - an anchor/break isn't seen */ /* * Historical note: * > BUG: sometimes anchors have x_space; * > we subtract that just in case --EG * This is inconsistent with other parts of the code, so it should * be tried to prevent this earlier.--SG */ /* * x_viewport -= word->size.width + word->eff_space; * x_widget -= word->size.width + word->eff_space; */#if 0 /* Useful for testing: draw breaks. */ if (word->content.type == DW_CONTENT_BREAK) gdk_draw_rectangle (window, gc, TRUE, p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x + Dw_page_line_total_x_offset(page, line)), y_viewport_base + line->descent, DW_WIDGET_CONTENT_WIDTH(widget), word->content.data.break_space);#endif break; default: g_warning ("BUG!!! at (%d, %d).", x_viewport, y_viewport_base + diff); break; } x_viewport += word->size.width + word->eff_space; x_widget += 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 && Dw_page_line_total_y_offset_i (page, index) < y) low = index; step = (step + 1) >> 1; } if (low < max_index && Dw_page_line_total_y_offset_i (page, low + 1) < 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 * That function has now been inlined into Dw_page_motion_notify() --JV */ return low;}/* * Find the line of word <word_index>. */static gint Dw_page_find_line_of_word (DwPage *page, gint word_index){ gint high = page->num_lines - 1, index, low = 0; g_return_val_if_fail (word_index >= 0, -1); g_return_val_if_fail (word_index < page->num_words, -1); while (TRUE) { index = (low + high) / 2; if (word_index >= page->lines[index].first_word) { if (word_index < page->lines[index].last_word) return index; else low = index + 1; } else high = index - 1; }}/* * 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, FALSE); 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 (Dw_page_line_total_y_offset(page, line) >= area->y + area->height) break; Dw_page_draw_line (page, line, area, event); }}/* * Find the index of the word, or -1. */static gint Dw_page_find_word (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 (Dw_page_line_total_y_offset(page, line) + 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_index; } return -1;}/* * Construct an iterator for a word. */static DwIterator *Dw_page_construct_iterator (DwPage *page, gint word_index){ DwIterator *it; it = Dw_page_iterator (DW_WIDGET (page), DW_CONTENT_ALL, FALSE); //DW_CONTENT_TEXT | DW_CONTENT_WIDGET, FALSE); ((DwIteratorInt*)it)->pos = word_index; it->content = page->words[word_index].content; return it;}/* * Send event to selection. */static gboolean Dw_page_send_selection_event (DwPage *page, gint (*fn) (Selection*, DwIterator *, gint, gint, GdkEventButton*, gboolean within_content), gint32 x, gint32 y, GdkEventButton *event){ DwIterator *it; DwPageLine *line, *last_line; gint32 next_word_start_x, word_start_x, word_x, next_word_x, yfirst, ylast; gint char_pos = 0, word_index, line_index, link; DwPageWord *word; gboolean found; gboolean within_content; DEBUG_MSG (DEBUG_EVENT_LEVEL, "Dw_page_send_selection_event: x = %d, y = %d\n", x, y); if (page->num_words == 0) { DEBUG_MSG (DEBUG_EVENT_LEVEL, " no words\n"); return FALSE; } /* In most cases true, so set here: */ link = -1; within_content = TRUE; last_line = &page->lines[page->num_lines - 1]; yfirst = Dw_page_line_total_y_offset_i (page, 0); ylast = Dw_page_line_total_y_offset (page, last_line) + last_line->ascent + last_line->descent; if (y < yfirst) { /* Above the first line: take the first word. */ DEBUG_MSG (DEBUG_EVENT_LEVEL, " above first line (at %d)\n", yfirst); within_content = FALSE; word_index = 0; char_pos = 0; } else if (y >= ylast) { /* Below the last line: take the last word. */ DEBUG_MSG (DEBUG_EVENT_LEVEL, " below last line (at %d)\n", ylast); within_content = FALSE; word_index = page->num_words - 1; word = &page->words[word_index]; char_pos = word->content.type == DW_CONTENT_TEXT ? strlen (word->content.data.text) : 0; } else { line_index = Dw_page_find_line_index (page, y); line = &page->lines[line_index]; DEBUG_MSG (DEBUG_EVENT_LEVEL, " in line %d\n", line_index); /* Pointer within the break space? */ if (y > (Dw_page_line_total_y_offset(page, line) + line->ascent + line->descent)) { /* Choose this break. */ DEBUG_MSG (DEBUG_EVENT_LEVEL, " break\n"); within_content = FALSE; word_index = line->last_word - 1; char_pos = 0; } else if (x < Dw_page_line_total_x_offset (page, line)) { /* Left of the first word in the line. */ DEBUG_MSG (DEBUG_EVENT_LEVEL, " left of this line\n"); word_index = line->first_word; within_content = FALSE; char_pos = 0; } else { next_word_start_x = Dw_page_line_total_x_offset (page, line); found = FALSE; for (word_index = line->first_word; !found && word_index < line->last_word; word_index++) { word = &page->words[word_index]; word_start_x = next_word_start_x; next_word_start_x += word->size.width + word->eff_space; DEBUG_MSG (DEBUG_EVENT_LEVEL, " word %d (%s) from %d to %d, delta = %d + %d\n", word_index, a_Dw_content_text (&word->content), word_start_x, next_word_start_x, word->size.width, word->eff_space); if (x >= word_start_x && x < next_word_start_x) { DEBUG_MSG (DEBUG_EVENT_LEVEL, " found word %d (%s)\n", word_index, a_Dw_content_text (&word->content)); /* We have found the word. */ if (word->content.type == DW_CONTENT_TEXT) { /* Search the character the mouse pointer is in. * next_word_x is the right side of this character. */ char_pos = 0; while ((next_word_x = word_start_x + gdk_text_width(word->style->font->font, word->content.data.text, char_pos)) <= x) char_pos++; /* The left side of this character. */ word_x = word_start_x + gdk_text_width (word->style->font->font, word->content.data.text, char_pos - 1); /* If the mouse pointer is left from the middle, use the left * position, otherwise, use the right one. */ if (x <= (word_x + next_word_x) / 2) char_pos--; } else { /* Depends on whether the pointer is within the left or * right half of the (non-text) word. */ if (x >= (word_start_x + next_word_start_x) / 2) char_pos = SELECTION_EOW; else char_pos = 0; } found = TRUE; link = word->style ? word->style->x_link : -1; break; } } if (!found) { /* No word found in this line (i.e. we are on the right side), * take the last of this line. */ DEBUG_MSG (DEBUG_EVENT_LEVEL, " not found\n"); within_content = FALSE; word_index = line->last_word - 1; if (word_index >= page->num_words) word_index--; word = &page->words[word_index]; char_pos = word->content.type == DW_CONTENT_TEXT ? strlen (word->content.data.text) : SELECTION_EOW; } } } word = &page->words[word_index]; it = Dw_page_construct_iterator (page, word_index); DEBUG_MSG (DEBUG_EVENT_LEVEL, "-> word %d (of %d), char %d, link %d: %s\n", word_index, page->num_words, char_pos, link, a_Dw_iterator_text (it)); return fn (GTK_DW_VIEWPORT(DW_WIDGET(page)->viewport)->selection, it, char_pos, link, event, within_content);}/* * Standard Dw function. */static gboolean Dw_page_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event){ return Dw_page_send_selection_event (DW_PAGE (widget), a_Selection_button_press, x, y, event);}/* * Standard Dw function. */static gboolean Dw_page_button_release (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event){ return Dw_page_send_selection_event (DW_PAGE (widget), a_Selection_button_release, x, y, event);}/* * Standard Dw function. */static gbool
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -