aboutsummaryrefslogtreecommitdiff
path: root/generic/Text.c
diff options
context:
space:
mode:
authorlecoanet2004-01-26 13:53:26 +0000
committerlecoanet2004-01-26 13:53:26 +0000
commit5375008cdfdc15fef8dd0a5080de782c7ece7204 (patch)
treefac7d85217ff3c7eb155ae6e888968d54fda6c8a /generic/Text.c
parent83c3407cb1001c5ccb43012606fca5f32373f3f8 (diff)
downloadtkzinc-5375008cdfdc15fef8dd0a5080de782c7ece7204.zip
tkzinc-5375008cdfdc15fef8dd0a5080de782c7ece7204.tar.gz
tkzinc-5375008cdfdc15fef8dd0a5080de782c7ece7204.tar.bz2
tkzinc-5375008cdfdc15fef8dd0a5080de782c7ece7204.tar.xz
* Added the scaling/rotation capabilities both in X and GL.
* (ComputeCursorAndSel): Corrected an incorrect selection extent offset. The last character of the selection was never displayed as part of the selection. * The insertion cursor wasn't displayed on an the last line when empty.
Diffstat (limited to 'generic/Text.c')
-rw-r--r--generic/Text.c882
1 files changed, 570 insertions, 312 deletions
diff --git a/generic/Text.c b/generic/Text.c
index edae1c3..7a2b1f8 100644
--- a/generic/Text.c
+++ b/generic/Text.c
@@ -69,33 +69,35 @@ static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__
typedef struct _TextLineInfo
{
char *start; /* Index of first char in line */
- unsigned int num_bytes; /* Number of displayed bytes in line (NOT chars)*/
- ZnPoint text_origin; /* X pos for drawing the line */
- unsigned int width; /* Line width in pixels */
+ unsigned short num_bytes; /* Number of displayed bytes in line (NOT chars)*/
+ unsigned short width; /* Line width in pixels */
+ unsigned short origin_x; /* X pos for drawing the line */
+ unsigned short origin_y;
} TextLineInfoStruct, *TextLineInfo;
typedef struct _TextItemStruct {
ZnItemStruct header;
/* Public data */
- ZnPoint pos;
- Tk_Anchor anchor;
- Tk_Anchor connection_anchor;
+ ZnPoint pos; /* Position at anchor */
ZnGradient *color;
char *text;
ZnImage fill_pattern;
Tk_Font font;
- Tk_Justify alignment;
- unsigned int width;
- unsigned int spacing;
+ unsigned short width;
+ short spacing;
unsigned short flags;
+ Tk_Anchor anchor;
+ Tk_Anchor connection_anchor;
+ Tk_Justify alignment;
/* Private data */
- ZnPoint pos_dev;
- unsigned int num_chars;
- unsigned int insert_index;
+ unsigned short num_chars;
+ unsigned short insert_index;
ZnList text_info;
- unsigned int max_width;
+ unsigned short max_width;
+ unsigned short height;
+ ZnPoint poly[4];
#ifdef GL
ZnTexFontInfo *tfi;
#endif
@@ -139,7 +141,7 @@ static ZnAttrConfig text_attrs[] = {
{ ZN_CONFIG_BOOL, "-sensitive", NULL,
Tk_Offset(TextItemStruct, header.flags), ZN_SENSITIVE_BIT,
ZN_REPICK_FLAG, False },
- { ZN_CONFIG_INT, "-spacing", NULL,
+ { ZN_CONFIG_SHORT, "-spacing", NULL,
Tk_Offset(TextItemStruct, spacing), 0,
ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
{ ZN_CONFIG_TAG_LIST, "-tags", NULL,
@@ -152,7 +154,7 @@ static ZnAttrConfig text_attrs[] = {
{ ZN_CONFIG_BOOL, "-visible", NULL,
Tk_Offset(TextItemStruct, header.flags), ZN_VISIBLE_BIT,
ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
- { ZN_CONFIG_INT, "-width", NULL,
+ { ZN_CONFIG_USHORT, "-width", NULL,
Tk_Offset(TextItemStruct, width), 0,
ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
@@ -175,14 +177,17 @@ Init(ZnItem item,
ZnWInfo *wi = item->wi;
TextItem text = (TextItem) item;
+ /*printf("size of a text(header) = %d(%d) %d\n",
+ sizeof(TextItemStruct), sizeof(ZnItemStruct), sizeof(TextLineInfoStruct));*/
+
text->text_info = NULL;
/* Init attributes */
SET(item->flags, ZN_VISIBLE_BIT);
SET(item->flags, ZN_SENSITIVE_BIT);
SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
- SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
- SET(item->flags, ZN_COMPOSE_SCALE_BIT);
+ CLEAR(item->flags, ZN_COMPOSE_ROTATION_BIT);
+ CLEAR(item->flags, ZN_COMPOSE_SCALE_BIT);
item->priority = 1;
text->pos.x = text->pos.y = 0.0;
@@ -380,6 +385,150 @@ Query(ZnItem item,
/*
+ * Compute the transformation to be used and the origin
+ * of the text (upper left point in item coordinates).
+ */
+static ZnTransfo *
+ComputeTransfoAndOrigin(ZnItem item,
+ ZnPoint *origin)
+{
+ TextItem text = (TextItem) item;
+
+ /*
+ * The connected item support anchors, this is checked by configure.
+ */
+ if (item->connected_item != ZN_NO_ITEM) {
+ ZnTransfo inv;
+
+ item->connected_item->class->GetAnchor(item->connected_item,
+ text->connection_anchor,
+ origin);
+
+ /* GetAnchor return a position in device coordinates not in
+ * the item coordinate space. To compute the text origin
+ * (upper left corner), we must apply the inverse transform
+ * to the ref point before calling anchor2origin.
+ */
+ ZnTransfoInvert(item->transfo, &inv);
+ ZnTransformPoint(&inv, origin, origin);
+ ZnAnchor2Origin(origin, (ZnReal) text->max_width,
+ (ZnReal) text->height, text->anchor, origin);
+
+ /*
+ * The relevant transform in case of an attachment is the item
+ * transform alone. This is case of local coordinate space where
+ * only the translation is a function of the whole transform
+ * stack, scale and rotation are reset.
+ */
+ return item->transfo;
+ }
+ else {
+ ZnAnchor2Origin(&text->pos, (ZnReal) text->max_width,
+ (ZnReal) text->height, text->anchor, origin);
+ return item->wi->current_transfo;
+ }
+}
+
+
+/*
+ * Compute the selection and the cursor geometry.
+ */
+void
+ComputeCursor(ZnItem item,
+ int *cursor_line,
+ unsigned int *cursor_offset)
+{
+ TextItem text = (TextItem) item;
+ ZnWInfo *wi = item->wi;
+ ZnTextInfo *ti = &wi->text_info;
+ TextLineInfo lines, lines_ptr;
+ unsigned int i, line_index, insert_index, num_lines;
+
+ num_lines = ZnListSize(text->text_info);
+ if (num_lines == 0) {
+ *cursor_line = 0;
+ }
+
+ lines = ZnListArray(text->text_info);
+ if ((wi->focus_item == item) && ISSET(wi->flags, ZN_GOT_FOCUS) && ti->cursor_on) {
+ insert_index = Tcl_UtfAtIndex(text->text, (int) text->insert_index)-text->text;
+ for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
+ /*
+ * Mark the line with the cursor and compute its
+ * position along the X axis.
+ */
+ line_index = lines_ptr->start - text->text;
+ if ((insert_index >= line_index) &&
+ (insert_index <= line_index + lines_ptr->num_bytes)) {
+ *cursor_line = i;
+ *cursor_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
+ insert_index - line_index);
+ }
+ }
+ }
+
+}
+
+static void
+ComputeSelection(ZnItem item,
+ int *sel_first_line,
+ int *sel_last_line,
+ unsigned int *sel_start_offset,
+ unsigned int *sel_stop_offset)
+{
+ TextItem text = (TextItem) item;
+ ZnWInfo *wi = item->wi;
+ ZnTextInfo *ti = &wi->text_info;
+ TextLineInfo lines_ptr, lines;
+ int i, num_lines, byte_index;
+ unsigned int line_index;
+ unsigned int sel_first, sel_last;
+
+ num_lines = ZnListSize(text->text_info);
+
+ if ((ti->sel_item != item) || !num_lines) {
+ return;
+ }
+
+ lines = ZnListArray(text->text_info);
+
+ sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first)-text->text;
+ sel_last = Tcl_UtfAtIndex(text->text, ti->sel_last+1)-text->text;
+ for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
+ /*
+ * Compute the selection first and last line as well as
+ * the positions along the X axis.
+ */
+ line_index = lines_ptr->start - text->text;
+ if ((sel_last >= line_index) &&
+ (sel_first <= (line_index + lines_ptr->num_bytes))) {
+ if (*sel_first_line < 0) {
+ byte_index = sel_first - line_index;
+ if (byte_index <= 0) {
+ *sel_first_line = i;
+ *sel_start_offset = 0;
+ /*printf("sel_start_offset 1 : %d\n", *sel_start_offset);*/
+ }
+ else if (byte_index <= lines_ptr->num_bytes) {
+ *sel_first_line = i;
+ *sel_start_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
+ byte_index);
+ /*printf("sel_start_offset 2 : %d\n", *sel_start_offset);*/
+ }
+ }
+ byte_index = ti->sel_last+1 - line_index;
+ *sel_last_line = i;
+ if (byte_index == lines_ptr->num_bytes+1)
+ *sel_stop_offset = lines_ptr->width;
+ else if (byte_index <= lines_ptr->num_bytes)
+ *sel_stop_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
+ byte_index);
+ }
+ }
+}
+
+
+/*
**********************************************************************************
*
* ComputeCoordinates --
@@ -394,9 +543,8 @@ ComputeCoordinates(ZnItem item,
TextItem text = (TextItem) item;
TextLineInfo infos;
Tk_FontMetrics fm;
- int i, fuzz, num_lines;
- int cur_dy;
- int font_height, height;
+ ZnTransfo *transfo;
+ int i, num_lines, cur_dy, font_height;
ZnResetBBox(&item->item_bounding_box);
@@ -429,35 +577,28 @@ ComputeCoordinates(ZnItem item,
}
if ((scan = text->text) != NULL) {
+ TextLineInfoStruct info;
+
while (*scan) {
- TextLineInfoStruct info;
- char *special;
- int num;
+ char *special;
+ int num, w;
/*
* Limit the excursion of Tk_MeasureChars to the end
* of the line. Do not include \n in the measure done.
*/
- num = strcspn(scan, "\r\n\t");
+ num = strcspn(scan, "\r\n");
special = scan + num;
info.num_bytes = Tk_MeasureChars(text->font, scan, num, wrap,
- TK_WHOLE_WORDS|TK_AT_LEAST_ONE,
- &info.width);
+ TK_WHOLE_WORDS|TK_AT_LEAST_ONE, &w);
+ info.width = w;
info.start = scan;
text->max_width = MAX(info.width, text->max_width);
scan += info.num_bytes;
/*
- * Add a text info describing the tab span (to be completed).
- * The entries in the text_info list should be interpreted
- * as text chunk not lines before going further..
- */
- while (*scan == '\t') {
- scan++;
- }
- /*
* Skip the newline line character.
*/
if ((*scan == '\r') || (*scan == '\n')) {
@@ -468,19 +609,25 @@ ComputeCoordinates(ZnItem item,
* Skip white spaces occuring after an
* automatic line break.
*/
- while ((*scan == ' ') || (*scan == '\t')) {
+ while (*scan == ' ') {
scan++;
}
}
+ ZnListAdd(text->text_info, &info, ZnListTail);
+ /*printf("adding a text info : %s, num_bytes : %d, width : %d\n",
+ info.start, info.num_bytes, info.width);*/
+ }
+ if (*text->text && ((scan[-1] == '\r') || (scan[-1] == '\n'))) {
/* Build a text info even for an empty line
* at the end of text or for an empty text.
* It is needed to enable selection and cursor
* insertion to behave correctly.
*/
+ info.num_bytes = 0;
+ info.width = 0;
+ info.start = scan;
ZnListAdd(text->text_info, &info, ZnListTail);
- /*printf("adding a text info : %s, num_bytes : %d, width : %d\n",
- info.start, info.num_bytes, info.width);*/
}
}
@@ -495,60 +642,72 @@ ComputeCoordinates(ZnItem item,
for (i = 0; i < num_lines; i++) {
switch (text->alignment) {
case TK_JUSTIFY_LEFT:
- infos[i].text_origin.x = 0;
+ infos[i].origin_x = 0;
break;
case TK_JUSTIFY_CENTER:
- infos[i].text_origin.x = (text->max_width + 1 - infos[i].width)/2;
+ infos[i].origin_x = (text->max_width + 1 - infos[i].width)/2;
break;
case TK_JUSTIFY_RIGHT:
- infos[i].text_origin.x = text->max_width + 1 - infos[i].width;
+ infos[i].origin_x = text->max_width + 1 - infos[i].width;
break;
}
- infos[i].text_origin.y = cur_dy;
+ infos[i].origin_y = cur_dy;
cur_dy += font_height + text->spacing;
- /*printf("fixing line %d x : %f, y : %f\n", i, infos[i].text_origin.x,
- infos[i].text_origin.y);*/
+ /*printf("fixing line %d x : %d, y : %d\n", i, infos[i].origin_x,
+ infos[i].origin_y);*/
}
} /* ISSET(item->inv_flags, INV_TEXT_LAYOUT) */
- height = font_height;
+ text->height = font_height;
if (text->text_info) {
- int h;
+ unsigned int h, cursor_offset;
+ int cursor_line;
+ ZnPoint origin, box[4];
+
num_lines = ZnListSize(text->text_info);
+ infos = ZnListArray(text->text_info);
h = num_lines * font_height + (num_lines-1) * text->spacing;
- height = MAX(height, h);
- }
+ text->height = MAX(text->height, h);
- /*
- * The connected item support anchors, this is checked by
- * configure.
- */
- if (item->connected_item != ZN_NO_ITEM) {
- item->connected_item->class->GetAnchor(item->connected_item,
- text->connection_anchor,
- &text->pos_dev);
- }
- else {
- ZnTransformPoint(wi->current_transfo, &text->pos, &text->pos_dev);
- text->pos_dev.x = ZnNearestInt(text->pos_dev.x);
- text->pos_dev.y = ZnNearestInt(text->pos_dev.y);
+ transfo = ComputeTransfoAndOrigin(item, &origin);
+
+ text->poly[0].x = origin.x;
+ text->poly[0].y = origin.y;
+ text->poly[3].x = text->poly[0].x + text->max_width;
+ text->poly[3].y = text->poly[0].y + text->height;
+ text->poly[1].x = text->poly[0].x;
+ text->poly[1].y = text->poly[3].y;
+ text->poly[2].x = text->poly[3].x;
+ text->poly[2].y = text->poly[0].y;
+ ZnTransformPoints(transfo, text->poly, text->poly, 4);
+ /*
+ * Add to the bounding box.
+ */
+ ZnAddPointsToBBox(&item->item_bounding_box, text->poly, 4);
+
+ /*
+ * Add the cursor shape to the bbox.
+ */
+ cursor_line = -1;
+ ComputeCursor(item, &cursor_line, &cursor_offset);
+ if (cursor_line >= 0) {
+ box[0].x = origin.x + infos[cursor_line].origin_x + cursor_offset -
+ wi->text_info.insert_width/2;
+ box[0].y = origin.y + infos[cursor_line].origin_y - fm.ascent + 1;
+ box[2].x = box[0].x + wi->text_info.insert_width;
+ box[2].y = box[0].y + font_height - 1;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ ZnAddPointsToBBox(&item->item_bounding_box, box, 4);
+ }
}
-
- ZnAnchor2Origin(&text->pos_dev, (ZnReal) text->max_width, (ZnReal) height, text->anchor,
- &text->pos_dev);
-
- /*
- * Compute the bounding box.
- */
- ZnAddPointToBBox(&item->item_bounding_box, text->pos_dev.x, text->pos_dev.y);
- ZnAddPointToBBox(&item->item_bounding_box, text->pos_dev.x+text->max_width+1,
- text->pos_dev.y+height);
- fuzz = 1+(wi->text_info.insert_width/2);
- item->item_bounding_box.orig.x -= fuzz;
- item->item_bounding_box.orig.y -= fuzz;
- item->item_bounding_box.corner.x += fuzz;
- item->item_bounding_box.corner.y += fuzz;
+ /*printf("bbox origin: %g %g corner %g %g\n",
+ item->item_bounding_box.orig.x, item->item_bounding_box.orig.y,
+ item->item_bounding_box.corner.x, item->item_bounding_box.corner.y);*/
/*
* Update connected items.
*/
@@ -577,12 +736,23 @@ ToArea(ZnItem item,
Tk_FontMetrics fm;
int font_height;
ZnBBox line_bbox, *area = ta->area;
- ZnPoint o;
+ ZnPoint box[4], p, origin;
+ ZnTransfo inv, *transfo;
if (!text->text_info || !text->text) {
return -1;
}
+ transfo = ComputeTransfoAndOrigin(item, &origin);
+ box[0] = area->orig;
+ box[2] = area->corner;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransfoInvert(transfo, &inv);
+ ZnTransformPoints(&inv, box, box, 4);
+
lines = (TextLineInfo) ZnListArray(text->text_info);
num_lines = ZnListSize(text->text_info);
Tk_GetFontMetrics(text->font, &fm);
@@ -594,19 +764,19 @@ ToArea(ZnItem item,
/*printf("text %d, num lines=%d\n", item->id, num_lines);*/
for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
ZnResetBBox(&line_bbox);
- o.x = text->pos_dev.x + lines_ptr->text_origin.x;
- o.y = text->pos_dev.y + lines_ptr->text_origin.y - fm.ascent;
- ZnAddPointToBBox(&line_bbox, o.x, o.y);
- ZnAddPointToBBox(&line_bbox, o.x + lines_ptr->width, o.y + font_height);
+ p.x = origin.x + lines_ptr->origin_x;
+ p.y = origin.y + lines_ptr->origin_y - fm.ascent;
+ ZnAddPointToBBox(&line_bbox, p.x, p.y);
+ ZnAddPointToBBox(&line_bbox, p.x + lines_ptr->width, p.y + font_height);
if (!first_done) {
first_done = True;
- inside = ZnBBoxInBBox(&line_bbox, area);
+ inside = ZnPolygonInBBox(box, 4, &line_bbox, NULL);
if (inside == 0) {
return 0;
}
}
else {
- if (ZnBBoxInBBox(&line_bbox, area) == 0) {
+ if (ZnPolygonInBBox(box, 4, &line_bbox, NULL) == 0) {
return 0;
}
}
@@ -615,83 +785,6 @@ ToArea(ZnItem item,
return inside;
}
-/*
- * Compute the selection and the cursor geometry.
- */
-static void
-ComputeCursorAndSel(ZnItem item,
- TextLineInfo lines,
- unsigned int num_lines,
- int *sel_first_line,
- int *sel_last_line,
- int *cursor_line,
- unsigned int *sel_start_offset,
- unsigned int *sel_stop_offset,
- unsigned int *cursor_offset)
-{
- TextItem text = (TextItem) item;
- ZnWInfo *wi = item->wi;
- ZnTextInfo *ti = &wi->text_info;
- TextLineInfo lines_ptr;
- unsigned int i, line_index, byte_index;
- unsigned int insert_index, sel_first, sel_last;
-
- if (num_lines == 0) {
- *cursor_line = 0;
- }
- if ((wi->focus_item == item) && ISSET(wi->flags, ZN_GOT_FOCUS) && ti->cursor_on) {
- insert_index = Tcl_UtfAtIndex(text->text, (int) text->insert_index)-text->text;
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- /*
- * Mark the line with the cursor and compute its
- * position along the X axis.
- */
- line_index = lines_ptr->start - text->text;
- if ((insert_index >= line_index) &&
- (insert_index <= line_index + lines_ptr->num_bytes)) {
- *cursor_line = i;
- *cursor_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- insert_index - line_index);
- }
- }
- }
-
- if (ti->sel_item == item) {
- sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first)-text->text;
- sel_last = Tcl_UtfAtIndex(text->text, ti->sel_last)-text->text;
- for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- /*
- * Compute the selection first and last line as well as
- * the positions along the X axis.
- */
- line_index = lines_ptr->start - text->text;
- if ((sel_last >= line_index) &&
- (sel_first <= (line_index + lines_ptr->num_bytes))) {
- if (*sel_first_line < 0) {
- byte_index = sel_first - line_index;
- if (byte_index <= 0) {
- *sel_first_line = i;
- *sel_start_offset = 0;
- /*printf("sel_start_offset 1 : %d\n", *sel_start_offset);*/
- }
- else if (byte_index <= lines_ptr->num_bytes) {
- *sel_first_line = i;
- *sel_start_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- byte_index);
- /*printf("sel_start_offset 2 : %d\n", *sel_start_offset);*/
- }
- }
- byte_index = ti->sel_last - line_index;
- *sel_last_line = i;
- if (byte_index == lines_ptr->num_bytes+1)
- *sel_stop_offset = lines_ptr->width;
- else if (byte_index <= lines_ptr->num_bytes)
- *sel_stop_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
- byte_index);
- }
- }
- }
-}
/*
**********************************************************************************
@@ -706,6 +799,12 @@ Draw(ZnItem item)
ZnWInfo *wi = item->wi;
TextItem text = (TextItem) item;
XGCValues values;
+ ZnPoint pos, box[4], origin;
+ ZnTransfo *transfo;
+ Drawable drw;
+ GC gc;
+ XImage *src_im, *dest_im=NULL;
+ unsigned int dest_im_width=0, dest_im_height=0;
unsigned int gc_mask = 0;
Tk_FontMetrics fm;
unsigned int font_height;
@@ -724,14 +823,18 @@ Draw(ZnItem item)
num_lines = ZnListSize(text->text_info);
Tk_GetFontMetrics(text->font, &fm);
font_height = fm.ascent+fm.descent;
-
+
+ transfo = ComputeTransfoAndOrigin(item, &origin);
+
/*
* Compute the selection and the cursor geometry.
*/
- ComputeCursorAndSel(item, lines, num_lines,
- &sel_first_line, &sel_last_line,
- &cursor_line, &sel_start_offset,
- &sel_stop_offset, &cursor_offset);
+ ComputeCursor(item, &cursor_line, &cursor_offset);
+ ComputeSelection(item, &sel_first_line, &sel_last_line,
+ &sel_start_offset, &sel_stop_offset);
+
+
+ ZnTransformPoint(transfo, &origin, &pos);
/*printf("sel 1st : %d offset : %d, sel last : %d offset : %d\n",
sel_first_line, sel_start_offset, sel_last_line, sel_stop_offset);*/
@@ -739,63 +842,147 @@ Draw(ZnItem item)
* Setup the gc for the selection and fill the selection.
*/
if ((ti->sel_item == item) && (sel_first_line >= 0)) {
- int x, y;
-
+ XPoint xp[4];
+
values.foreground = ZnGetGradientPixel(ti->sel_color, 0.0);
values.fill_style = FillSolid;
XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
if (sel_first_line == sel_last_line) {
- x = (int)(text->pos_dev.x + lines[sel_first_line].text_origin.x + sel_start_offset);
- y = (int)(text->pos_dev.y + lines[sel_first_line].text_origin.y - fm.ascent);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y,
- sel_stop_offset - sel_start_offset, font_height);
+ box[0].x = origin.x +
+ lines[sel_first_line].origin_x + sel_start_offset;
+ box[0].y = origin.y +
+ lines[sel_first_line].origin_y - fm.ascent;
+ box[2].x = box[0].x + sel_stop_offset - sel_start_offset;
+ box[2].y = box[0].y + font_height;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ for (i = 0; i < 4; i++) {
+ xp[i].x = box[i].x;
+ xp[i].y = box[i].y;
+ }
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
}
else {
- x = (int)(text->pos_dev.x + lines[sel_first_line].text_origin.x + sel_start_offset);
- y = (int)(text->pos_dev.y + lines[sel_first_line].text_origin.y - fm.ascent);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- x, y,
- text->max_width-(int)lines[sel_first_line].text_origin.x-sel_start_offset,
- font_height);
+ box[0].x = origin.x +
+ lines[sel_first_line].origin_x + sel_start_offset;
+ box[0].y = origin.y +
+ lines[sel_first_line].origin_y - fm.ascent;
+ box[2].x = box[0].x +
+ text->max_width-lines[sel_first_line].origin_x-sel_start_offset;
+ box[2].y = box[0].y + font_height;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ for (i = 0; i < 4; i++) {
+ xp[i].x = box[i].x;
+ xp[i].y = box[i].y;
+ }
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
i < sel_last_line; i++, lines_ptr++) {
- x = (int) text->pos_dev.x;
- y = (int) (text->pos_dev.y + lines_ptr->text_origin.y - fm.ascent);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, text->max_width, font_height);
+ box[0].x = origin.x;
+ box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
+ box[2].x = box[0].x + text->max_width;
+ box[2].y = box[0].y + font_height;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ for (i = 0; i < 4; i++) {
+ xp[i].x = box[i].x;
+ xp[i].y = box[i].y;
+ }
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
+ }
+ box[0].x = origin.x;
+ box[0].y = origin.y + lines[sel_last_line].origin_y - fm.ascent;
+ box[2].x = box[0].x + lines[sel_last_line].origin_x + sel_stop_offset;
+ box[2].y = box[0].y + font_height;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ for (i = 0; i < 4; i++) {
+ xp[i].x = box[i].x;
+ xp[i].y = box[i].y;
}
- x = (int)text->pos_dev.x;
- y = (int)(text->pos_dev.y + lines[sel_last_line].text_origin.y - fm.ascent);
- XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
- x, y, (int)lines[sel_last_line].text_origin.x+sel_stop_offset,
- font_height);
+ XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
}
}
- //printf("cursor line : %d, cursor offset : %d\n", cursor_line, cursor_offset);
+ /*printf("cursor line : %d, cursor offset : %d\n", cursor_line, cursor_offset);*/
/*
* Setup the gc for the cursor and draw it.
*/
if (cursor_line >= 0 &&
(wi->focus_item == item) && ti->cursor_on) {
- int xs, ys;
-
values.fill_style = FillSolid;
values.line_width = ti->insert_width;
values.foreground = ZnGetGradientPixel(ti->insert_color, 0.0);
XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCLineWidth, &values);
- xs = (int)(text->pos_dev.x + lines[cursor_line].text_origin.x + cursor_offset);
- ys = (int)(text->pos_dev.y + lines[cursor_line].text_origin.y - fm.ascent + 1);
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, xs, ys, xs, ys + (int) font_height - 1);
+ box[0].x = origin.x + lines[cursor_line].origin_x + cursor_offset;
+ box[0].y = origin.y + lines[cursor_line].origin_y - fm.ascent + 1;
+ box[1].x = box[0].x;
+ box[1].y = box[0].y + font_height - 1;
+ ZnTransformPoints(transfo, box, box, 2);
+ XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
+ box[0].x, box[0].y, box[1].x, box[1].y);
+ }
+
+
+ /*
+ * If the current transform is a pure translation, it is
+ * possible to optimize by directly drawing to the X back
+ * buffer. Else, we draw in a temporary buffer, get
+ * its content as an image, transform the image into another
+ * one and use this last image as a mask to draw in the X
+ * back buffer.
+ */
+ if (ZnTransfoIsTranslation(transfo)) {
+ drw = wi->draw_buffer;
+
+ gc = wi->gc;
+ values.foreground = ZnGetGradientPixel(text->color, 0.0);
+ }
+ else {
+ dest_im_width = (item->item_bounding_box.corner.x -
+ item->item_bounding_box.orig.x);
+ dest_im_height = (item->item_bounding_box.corner.y -
+ item->item_bounding_box.orig.y);
+
+ drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer,
+ MAX(dest_im_width, text->max_width),
+ MAX(dest_im_height, text->height), 1);
+ gc = XCreateGC(wi->dpy, drw, 0, NULL);
+ XSetForeground(wi->dpy, gc, 0);
+ XFillRectangle(wi->dpy, drw, gc, 0, 0,
+ MAX(dest_im_width, text->max_width),
+ MAX(dest_im_height, text->height));
+ dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
+ XYPixmap, 0, NULL, dest_im_width, dest_im_height,
+ 8, 0);
+ dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
+ memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);
+
+ values.foreground = 1;
+
+ pos.x = 0;
+ pos.y = 0;
}
/*
* Setup the gc to render the text and draw it.
*/
values.font = Tk_FontId(text->font);
- values.foreground = ZnGetGradientPixel(text->color, 0.0);
gc_mask = GCFont | GCForeground;
if (text->fill_pattern != ZnUnspecifiedImage) {
values.fill_style = FillStippled;
@@ -819,28 +1006,72 @@ Draw(ZnItem item)
values.line_width = underline_thickness;
gc_mask |= GCLineStyle | GCLineWidth;
}
- XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
+ XChangeGC(wi->dpy, gc, gc_mask, &values);
for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
int tmp_x, tmp_y;
- tmp_x = (int)(text->pos_dev.x + lines_ptr->text_origin.x);
- tmp_y = (int)(text->pos_dev.y + lines_ptr->text_origin.y);
- Tk_DrawChars(wi->dpy, wi->draw_buffer, wi->gc,
+ tmp_x = (int)(pos.x + lines_ptr->origin_x);
+ tmp_y = (int)(pos.y + lines_ptr->origin_y);
+ Tk_DrawChars(wi->dpy, drw, gc,
text->font, (char *) lines_ptr->start,
(int) lines_ptr->num_bytes, tmp_x, tmp_y);
if (ISSET(text->flags, UNDERLINED)) {
int y_under = tmp_y + underline_pos;
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
+ XDrawLine(wi->dpy, drw, gc,
tmp_x, y_under, tmp_x + (int) lines_ptr->width, y_under);
}
if (ISSET(text->flags, OVERSTRIKED)) {
int y_over = tmp_y-overstrike_pos;
- XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
+ XDrawLine(wi->dpy, drw, gc,
tmp_x, y_over, tmp_x + (int) lines_ptr->width, y_over);
}
}
+
+ if (dest_im != NULL) {
+ src_im = XGetImage(wi->dpy, drw, 0, 0, text->max_width, text->height,
+ 1, XYPixmap);
+
+ box[0].x = origin.x;
+ box[0].y = origin.y;
+ box[3].x = box[0].x + text->max_width;
+ box[3].y = box[0].y + text->height;
+ box[1].x = box[0].x;
+ box[1].y = box[3].y;
+ box[2].x = box[3].x;
+ box[2].y = box[0].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ for (i = 0; i < 4; i++) {
+ box[i].x -= item->item_bounding_box.orig.x;
+ box[i].y -= item->item_bounding_box.orig.y;
+ box[i].x = ZnNearestInt(box[i].x);
+ box[i].y = ZnNearestInt(box[i].y);
+ }
+
+ ZnMapImage(src_im, dest_im, box);
+
+ XPutImage(wi->dpy, drw, gc, dest_im,
+ 0, 0, 0, 0, dest_im_width, dest_im_height);
+
+ values.foreground = ZnGetGradientPixel(text->color, 0.0);
+ values.stipple = drw;
+ values.ts_x_origin = item->item_bounding_box.orig.x;
+ values.ts_y_origin = item->item_bounding_box.orig.y;
+ values.fill_style = FillStippled;
+ XChangeGC(wi->dpy, wi->gc,
+ GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
+ &values);
+ XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
+ item->item_bounding_box.orig.x,
+ item->item_bounding_box.orig.y,
+ dest_im_width, dest_im_height);
+
+ XFreeGC(wi->dpy, gc);
+ Tk_FreePixmap(wi->dpy, drw);
+ XDestroyImage(src_im);
+ XDestroyImage(dest_im);
+ }
}
@@ -859,6 +1090,9 @@ Render(ZnItem item)
TextItem text = (TextItem) item;
TextLineInfo lines, lines_ptr;
ZnTextInfo *ti = &wi->text_info;
+ ZnPoint o, c, origin;
+ ZnTransfo *transfo;
+ GLdouble m[16];
int i, num_lines;
XColor *color;
unsigned short alpha;
@@ -897,64 +1131,73 @@ Render(ZnItem item)
underline_pos = fm.descent/2;
overstrike_pos = fm.ascent*3/10;
+ transfo = ComputeTransfoAndOrigin(item, &origin);
+
/*
* Compute the selection and the cursor geometry.
*/
- ComputeCursorAndSel(item, lines, num_lines,
- &sel_first_line, &sel_last_line,
- &cursor_line, &sel_start_offset,
- &sel_stop_offset, &cursor_offset);
-
+ ComputeCursor(item, &cursor_line, &cursor_offset);
+ ComputeSelection(item, &sel_first_line, &sel_last_line,
+ &sel_start_offset, &sel_stop_offset);
+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
+ glPushMatrix();
+ memset(m, 0, sizeof(m));
+ m[0] = m[5] = m[15] = 1.0;
+ if (transfo) {
+ m[0] = transfo->_[0][0]; m[1] = transfo->_[0][1];
+ m[4] = transfo->_[1][0]; m[5] = transfo->_[1][1];
+ m[12] = transfo->_[2][0]; m[13] = transfo->_[2][1];
+ }
+ glLoadMatrixd(m);
+ glTranslated(origin.x, origin.y, 0.0);
+ glPushMatrix();
+
/*
* Render the selection.
*/
if ((ti->sel_item == item) && (sel_first_line >= 0)) {
- ZnReal xo, yo, xc, yc;
-
color = ZnGetGradientColor(ti->sel_color, 0.0, &alpha);
alpha = ZnComposeAlpha(alpha, wi->alpha);
glColor4us(color->red, color->green, color->blue, alpha);
+ o.x = lines[sel_first_line].origin_x + sel_start_offset;
+ o.y = lines[sel_first_line].origin_y - fm.ascent;
glBegin(GL_QUADS);
if (sel_first_line == sel_last_line) {
- xo = text->pos_dev.x + lines[sel_first_line].text_origin.x + sel_start_offset;
- yo = text->pos_dev.y + lines[sel_first_line].text_origin.y - fm.ascent;
- xc = xo + sel_stop_offset - sel_start_offset;
- yc = yo + font_height;
- glVertex2d(xo, yo);
- glVertex2d(xc, yo);
- glVertex2d(xc, yc);
- glVertex2d(xo, yc);
+ c.x = o.x + sel_stop_offset - sel_start_offset;
+ c.y = o.y + font_height;
+ glVertex2d(o.x, o.y);
+ glVertex2d(o.x, c.y);
+ glVertex2d(c.x, c.y);
+ glVertex2d(c.x, o.y);
}
else {
- xo = text->pos_dev.x + lines[sel_first_line].text_origin.x + sel_start_offset;
- yo = text->pos_dev.y + lines[sel_first_line].text_origin.y - fm.ascent;
- xc = xo + text->max_width-lines[sel_first_line].text_origin.x-sel_start_offset;
- yc = yo + font_height;
- glVertex2d(xo, yo);
- glVertex2d(xc, yo);
- glVertex2d(xc, yc);
- glVertex2d(xo, yc);
+ c.x = o.x + (text->max_width -
+ lines[sel_first_line].origin_x - sel_start_offset);
+ c.y = o.y + font_height;
+ glVertex2d(o.x, o.y);
+ glVertex2d(o.x, c.y);
+ glVertex2d(c.x, c.y);
+ glVertex2d(c.x, o.y);
for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
i < sel_last_line; i++, lines_ptr++) {
- xo = text->pos_dev.x;
- yo = text->pos_dev.y + lines_ptr->text_origin.y - fm.ascent;
- xc = xo + text->max_width;
- yc = yo + font_height;
- glVertex2d(xo, yo);
- glVertex2d(xc, yo);
- glVertex2d(xc, yc);
- glVertex2d(xo, yc);
+ o.x = 0;
+ o.y = lines_ptr->origin_y - fm.ascent;
+ c.x = o.x + text->max_width;
+ c.y = o.y + font_height;
+ glVertex2d(o.x, o.y);
+ glVertex2d(o.x, c.y);
+ glVertex2d(c.x, c.y);
+ glVertex2d(c.x, o.y);
}
- xo = text->pos_dev.x;
- yo = text->pos_dev.y + lines[sel_last_line].text_origin.y - fm.ascent;
- xc = xo + lines[sel_last_line].text_origin.x+sel_stop_offset;
- yc = yo + font_height;
- glVertex2d(xo, yo);
- glVertex2d(xc, yo);
- glVertex2d(xc, yc);
- glVertex2d(xo, yc);
+ o.x = 0;
+ o.y = lines[sel_last_line].origin_y - fm.ascent;
+ c.x = o.x + lines[sel_last_line].origin_x + sel_stop_offset;
+ c.y = o.y + font_height;
+ glVertex2d(o.x, o.y);
+ glVertex2d(o.x, c.y);
+ glVertex2d(c.x, c.y);
+ glVertex2d(c.x, o.y);
}
glEnd();
}
@@ -964,20 +1207,22 @@ Render(ZnItem item)
*/
if ((cursor_line >= 0) &&
(wi->focus_item == item) && ti->cursor_on) {
- int xs, ys;
-
color = ZnGetGradientColor(ti->insert_color, 0.0, &alpha);
alpha = ZnComposeAlpha(alpha, wi->alpha);
glColor4us(color->red, color->green, color->blue, alpha);
glLineWidth((GLfloat) ti->insert_width);
- xs = (int) (text->pos_dev.x + lines[cursor_line].text_origin.x) + cursor_offset;
- ys = (int) (text->pos_dev.y + lines[cursor_line].text_origin.y) - fm.ascent + 1;
+
+ o.x = lines[cursor_line].origin_x + cursor_offset;
+ o.y = lines[cursor_line].origin_y - fm.ascent + 1;
+ c.x = o.x;
+ c.y = o.y + font_height - 1;
+
glBegin(GL_LINES);
- glVertex2i(xs, ys);
- glVertex2i(xs, ys + font_height - 1);
+ glVertex2d(o.x, o.y);
+ glVertex2d(c.x, c.y);
glEnd();
}
-
+
/*
* Render the text.
*/
@@ -989,13 +1234,26 @@ Render(ZnItem item)
glColor4us(color->red, color->green, color->blue, alpha);
for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- ZnReal xs, ys;
-
- xs = text->pos_dev.x + lines_ptr->text_origin.x;
- ys = text->pos_dev.y + lines_ptr->text_origin.y;
-
- glPushMatrix();
- glTranslated(xs, ys, 0.0);
+ glTranslated(lines_ptr->origin_x, lines_ptr->origin_y, 0.0);
+
+ if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
+ glLineWidth((GLfloat) underline_thickness);
+ glDisable(GL_TEXTURE_2D);
+ if (ISSET(text->flags, UNDERLINED)) {
+ glBegin(GL_LINES);
+ glVertex2d(0, underline_pos);
+ glVertex2d(lines_ptr->width, underline_pos);
+ glEnd();
+ }
+ if (ISSET(text->flags, OVERSTRIKED)) {
+ glBegin(GL_LINES);
+ glVertex2d(0, -overstrike_pos);
+ glVertex2d(lines_ptr->width, -overstrike_pos);
+ glEnd();
+ }
+ glEnable(GL_TEXTURE_2D);
+ }
+
#ifndef PTK
/*
* Temporary ack to fix utf8 display.
@@ -1021,25 +1279,12 @@ Render(ZnItem item)
ZnRenderString(text->tfi, lines_ptr->start, lines_ptr->num_bytes);
#endif
glPopMatrix();
-
- if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
- glLineWidth((GLfloat) underline_thickness);
- glDisable(GL_TEXTURE_2D);
- if (ISSET(text->flags, UNDERLINED)) {
- glBegin(GL_LINES);
- glVertex2d(xs, ys+underline_pos);
- glVertex2d(xs+lines_ptr->width, ys+underline_pos);
- glEnd();
- }
- if (ISSET(text->flags, OVERSTRIKED)) {
- glBegin(GL_LINES);
- glVertex2d(xs, ys-overstrike_pos);
- glVertex2d(xs+lines_ptr->width, ys-overstrike_pos);
- glEnd();
- }
- glEnable(GL_TEXTURE_2D);
- }
+ glPushMatrix();
}
+
+ glPopMatrix();
+ glPopMatrix();
+
glDisable(GL_TEXTURE_2D);
#ifdef GL_LIST
glEndList();
@@ -1089,28 +1334,34 @@ Pick(ZnItem item,
TextLineInfo lines, lines_ptr;
Tk_FontMetrics fm;
int font_height;
- ZnBBox line_bbox;
- ZnPoint o, *p = ps->point;
-
+ ZnPoint box[4], origin, *p = ps->point;
+ ZnTransfo *transfo;
+
if (!text->text_info || !text->text) {
return dist;
}
- lines = (TextLineInfo) ZnListArray(text->text_info);
+ transfo = ComputeTransfoAndOrigin(item, &origin);
+
+ lines = ZnListArray(text->text_info);
num_lines = ZnListSize(text->text_info);
Tk_GetFontMetrics(text->font, &fm);
font_height = fm.descent + fm.ascent;
if (text->spacing > 0) {
font_height += text->spacing;
}
-
+
for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
- ZnResetBBox(&line_bbox);
- o.x = text->pos_dev.x + lines_ptr->text_origin.x;
- o.y = text->pos_dev.y + lines_ptr->text_origin.y - fm.ascent;
- ZnAddPointToBBox(&line_bbox, o.x, o.y);
- ZnAddPointToBBox(&line_bbox, o.x + lines_ptr->width, o.y + font_height);
- new_dist = ZnRectangleToPointDist(&line_bbox, p);
+ box[0].x = origin.x + lines_ptr->origin_x;
+ box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
+ box[2].x = box[0].x + lines_ptr->width;
+ box[2].y = box[0].y + font_height;
+ box[1].x = box[2].x;
+ box[1].y = box[0].y;
+ box[3].x = box[0].x;
+ box[3].y = box[2].y;
+ ZnTransformPoints(transfo, box, box, 4);
+ new_dist = ZnPolygonToPointDist(box, 4, p);
dist = MIN(dist, new_dist);
if (dist <= 0.0) {
dist = 0.0;
@@ -1149,15 +1400,12 @@ GetAnchor(ZnItem item,
ZnPoint *p)
{
TextItem text = (TextItem) item;
-
+
if (text->num_chars != 0) {
- ZnOrigin2Anchor(&text->pos_dev,
- item->item_bounding_box.corner.x-item->item_bounding_box.orig.x,
- item->item_bounding_box.corner.y-item->item_bounding_box.orig.y,
- anchor, p);
+ ZnRectOrigin2Anchor(text->poly, anchor, p);
}
else {
- p->x = p->y = 0.0;
+ *p = *text->poly;
}
}
@@ -1175,15 +1423,11 @@ static ZnBool
GetClipVertices(ZnItem item,
ZnTriStrip *tristrip)
{
- ZnPoint *points;
-
- ZnListAssertSize(item->wi->work_pts, 2);
- points = (ZnPoint *) ZnListArray(item->wi->work_pts);
- ZnTriStrip1(tristrip, points, 2, False);
- points[0] = item->item_bounding_box.orig;
- points[1] = item->item_bounding_box.corner;
+ TextItem text = (TextItem) item;
+
+ ZnTriStrip1(tristrip, text->poly, 4, False);
- return True;
+ return False;
}
@@ -1245,21 +1489,31 @@ PointToChar(TextItem text,
int y)
{
int i, n, num_lines, dummy, byte_index;
- TextLineInfo lines, p;
+ ZnPoint p;
+ TextLineInfo ti;
Tk_FontMetrics fm;
+ ZnReal a, b;
byte_index = 0;
if (!text->text_info) {
return 0;
}
- x -= (int) text->pos_dev.x;
- y -= (int) text->pos_dev.y;
-
+ p.x = x;
+ p.y = y;
+ a = ZnLineToPointDist(&text->poly[0], &text->poly[2], &p, NULL);
+ b = ZnLineToPointDist(&text->poly[0], &text->poly[1], &p, NULL);
+ p.x = (text->max_width * b /
+ hypot(text->poly[2].x - text->poly[0].x, text->poly[2].y - text->poly[0].y));
+ p.y = (text->height * a /
+ hypot(text->poly[1].x - text->poly[0].x, text->poly[1].y - text->poly[0].y));
+ p.x = ZnNearestInt(p.x);
+ p.y = ZnNearestInt(p.y);
+
/*
* Point above text, returns index 0.
*/
- if (y < 0) {
+ if (p.y < 0) {
return 0;
}
@@ -1267,29 +1521,30 @@ PointToChar(TextItem text,
* Find the text line under point.
*/
num_lines = ZnListSize(text->text_info);
- lines = p = ZnListArray(text->text_info);
+ ti = ZnListArray(text->text_info);
Tk_GetFontMetrics(text->font, &fm);
- for (i = 0; i < num_lines; i++, p++) {
- if (y < p->text_origin.y + fm.descent) {
- if (x < p->text_origin.x) {
+ for (i = 0; i < num_lines; i++, ti++) {
+ if (p.y < ti->origin_y + fm.descent) {
+ if (p.x < ti->origin_x) {
/*
* Point to the left of the current line, returns
* index of first char.
*/
- byte_index = p->start - text->text;
+ byte_index = ti->start - text->text;
break;
}
- if (x >= (p->text_origin.x + p->width)) {
+ if (p.x >= (ti->origin_x + ti->width)) {
/*
* Point to the right of the current line, returns
* index past the last char.
*/
- byte_index = p->start + p->num_bytes - text->text;
+ byte_index = ti->start + ti->num_bytes - text->text;
break;
}
- n = Tk_MeasureChars(text->font, p->start, (int) p->num_bytes,
- x + 2 - (int) p->text_origin.x, TK_PARTIAL_OK, &dummy);
- byte_index = (p->start + n - 1) - text->text;
+ n = Tk_MeasureChars(text->font, ti->start, (int) ti->num_bytes,
+ p.x + 2 - (int) ti->origin_x, TK_PARTIAL_OK,
+ &dummy);
+ byte_index = (ti->start + n - 1) - text->text;
break;
}
}
@@ -1298,8 +1553,8 @@ PointToChar(TextItem text,
* Point below all lines, return the index after
* the last char in text.
*/
- p--;
- byte_index = p->start + p->num_bytes - text->text;
+ ti--;
+ byte_index = ti->start + ti->num_bytes - text->text;
}
return Tcl_NumUtfChars(text->text, byte_index);
@@ -1615,6 +1870,9 @@ DeleteChars(ZnItem item,
if (text->insert_index < (unsigned int) *first) {
text->insert_index = *first;
}
+ else if (*first == 0) {
+ text->insert_index = 0;
+ }
}
if (ti->sel_item == item) {
if (ti->sel_first > *first) {