aboutsummaryrefslogtreecommitdiff
path: root/generic/Text.c
diff options
context:
space:
mode:
authorlecoanet2002-04-11 09:23:07 +0000
committerlecoanet2002-04-11 09:23:07 +0000
commit29d5058bf5ffa32c28134c7950e359208d6e9541 (patch)
tree9cb0a125a7a3ee5efc29ecac522d55375fe46058 /generic/Text.c
parent819bf7115667448382e6680c705db84239794ab5 (diff)
downloadtkzinc-29d5058bf5ffa32c28134c7950e359208d6e9541.zip
tkzinc-29d5058bf5ffa32c28134c7950e359208d6e9541.tar.gz
tkzinc-29d5058bf5ffa32c28134c7950e359208d6e9541.tar.bz2
tkzinc-29d5058bf5ffa32c28134c7950e359208d6e9541.tar.xz
Correction d'un core dans DeleteChars suite � un pointeur
non d�r�f�renc�. Int�gration des nouveaux indices: bol, eol, bow, eow, up, down. Mise � jour des indices de s�lection et d'insertion lors d'une reconfiguration du texte (bug). L'indice sel.end retourne en fait l'index du caract�re de fin de s�lection plut�t que le point insertion entre celui-ci et le suivant.
Diffstat (limited to 'generic/Text.c')
-rw-r--r--generic/Text.c198
1 files changed, 162 insertions, 36 deletions
diff --git a/generic/Text.c b/generic/Text.c
index 302f5c4..64e0c21 100644
--- a/generic/Text.c
+++ b/generic/Text.c
@@ -285,6 +285,7 @@ Configure(Item item,
{
TextItem text = (TextItem) item;
Item old_connected = item->connected_item;
+ int num_chars;
#ifdef GLX
ZnFont old_font = text->font;
#endif
@@ -299,6 +300,31 @@ Configure(Item item,
text->txf = NULL;
}
#endif
+ num_chars = strlen(text->text);
+ if (text->num_chars != num_chars) {
+ TextInfo *ti = &item->wi->text_info;
+ /*
+ * The text has changed, update the selection and
+ * insertion pos to keep them valid.
+ */
+ if (item == ti->sel_item) {
+ if (ti->sel_last > num_chars) {
+ ti->sel_last = num_chars;
+ }
+ if (ti->sel_first >= ti->sel_last) {
+ ti->sel_item = ZN_NO_ITEM;
+ ti->sel_field = ZN_NO_PART;
+ }
+ if ((ti->anchor_item == item) && (ti->sel_anchor > num_chars)) {
+ ti->sel_anchor = num_chars;
+ }
+ }
+ if (text->insert_index > text->num_chars) {
+ text->insert_index = text->num_chars;
+ }
+ text->num_chars = num_chars;
+ }
+
if (ISSET(*flags, ZN_ITEM_FLAG)) {
/*
* If the new connected item is not appropriate back up
@@ -358,10 +384,7 @@ ComputeCoordinates(Item item,
int font_height, height;
ResetBBox(&item->item_bounding_box);
- text->num_chars = strlen(text->text);
- if (text->insert_index > text->num_chars) {
- text->insert_index = text->num_chars;
- }
+
if (text->num_chars == 0) {
return;
}
@@ -588,6 +611,7 @@ ComputeCursorAndSel(Item item,
{
TextItem text = (TextItem) item;
WidgetInfo *wi = item->wi;
+ TextInfo *ti = &wi->text_info;
TextLineInfo lines_ptr;
int i, line_index, char_index;
@@ -597,7 +621,7 @@ ComputeCursorAndSel(Item item,
* position along the X axis.
*/
line_index = lines_ptr->start - text->text;
- if ((wi->focus_item == item) && wi->got_focus && wi->text_info.cursor_on &&
+ if ((wi->focus_item == item) && wi->got_focus && ti->cursor_on &&
text->insert_index >= line_index &&
text->insert_index <= line_index + lines_ptr->num_chars) {
*cursor_line = i;
@@ -609,11 +633,10 @@ ComputeCursorAndSel(Item item,
* Compute the selection first and last line as well as
* the positions along the X axis.
*/
- if ((wi->text_info.sel_item == item) &&
- (wi->text_info.sel_last >= line_index) &&
- (wi->text_info.sel_first <= (line_index + lines_ptr->num_chars))) {
+ if ((ti->sel_item == item) && (ti->sel_last >= line_index) &&
+ (ti->sel_first <= (line_index + lines_ptr->num_chars))) {
if (*sel_first_line < 0) {
- char_index = wi->text_info.sel_first - line_index;
+ char_index = ti->sel_first - line_index;
if (char_index <= 0) {
*sel_first_line = i;
*sel_start_offset = 0;
@@ -626,7 +649,7 @@ ComputeCursorAndSel(Item item,
/*printf("sel_start_offset 2 : %d\n", *sel_start_offset);*/
}
}
- char_index = wi->text_info.sel_last - line_index;
+ char_index = ti->sel_last - line_index;
*sel_last_line = i;
if (char_index == lines_ptr->num_chars+1)
*sel_stop_offset = lines_ptr->width;
@@ -655,6 +678,7 @@ Draw(Item item)
int font_height;
int num_lines, i;
TextLineInfo lines, lines_ptr;
+ TextInfo *ti = &wi->text_info;
int underline_thickness, underline_pos=0, overstrike_pos=0;
int sel_first_line=-1, sel_last_line=-1, cursor_line=-1;
int sel_start_offset=0, sel_stop_offset=0, cursor_offset=0;
@@ -680,10 +704,10 @@ Draw(Item item)
/*
* Setup the gc for the selection and fill the selection.
*/
- if ((wi->text_info.sel_item == item) && (sel_first_line >= 0)) {
+ if ((ti->sel_item == item) && (sel_first_line >= 0)) {
int x, y;
- values.foreground = ZnPixel(ZnGetGradientColor(wi->text_info.sel_color, 0, NULL));
+ values.foreground = ZnPixel(ZnGetGradientColor(ti->sel_color, 0, NULL));
values.fill_style = FillSolid;
XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
@@ -723,8 +747,8 @@ Draw(Item item)
int xs, ys;
values.fill_style = FillSolid;
- values.line_width = wi->text_info.insert_width;
- values.foreground = ZnPixel(ZnGetGradientColor(wi->text_info.insert_color, 0, NULL));
+ values.line_width = ti->insert_width;
+ values.foreground = ZnPixel(ZnGetGradientColor(ti->insert_color, 0, NULL));
XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCLineWidth, &values);
xs = (int)(text->pos_dev.x + lines[cursor_line].text_origin.x + cursor_offset);
@@ -798,6 +822,7 @@ Render(Item item)
WidgetInfo *wi = item->wi;
TextItem text = (TextItem) item;
TextLineInfo lines, lines_ptr;
+ TextInfo *ti = &wi->text_info;
int i, num_lines;
XColor *color;
int alpha;
@@ -844,10 +869,10 @@ Render(Item item)
/*
* Render the selection.
*/
- color = ZnGetGradientColor(wi->text_info.sel_color, 0, &alpha);
+ color = ZnGetGradientColor(ti->sel_color, 0, &alpha);
alpha = ZnComposeAlpha(alpha, wi->alpha);
glColor4us(color->red, color->green, color->blue, alpha);
- if ((wi->text_info.sel_item == item) && (sel_first_line >= 0)) {
+ if ((ti->sel_item == item) && (sel_first_line >= 0)) {
ZnReal xo, yo, xc, yc;
glBegin(GL_QUADS);
@@ -896,14 +921,14 @@ Render(Item item)
/*
* Render the cursor.
*/
- color = ZnGetGradientColor(wi->text_info.insert_color, 0, &alpha);
+ color = ZnGetGradientColor(ti->insert_color, 0, &alpha);
alpha = ZnComposeAlpha(alpha, wi->alpha);
glColor4us(color->red, color->green, color->blue, alpha);
if ((cursor_line >= 0) &&
- (wi->focus_item == item) && wi->text_info.cursor_on) {
+ (wi->focus_item == item) && ti->cursor_on) {
int xs, ys;
- glLineWidth(wi->text_info.insert_width);
+ glLineWidth(ti->insert_width);
xs = text->pos_dev.x + lines[cursor_line].text_origin.x + cursor_offset;
ys = text->pos_dev.y + lines[cursor_line].text_origin.y - fm.ascent + 1;
glBegin(GL_LINES);
@@ -1144,11 +1169,10 @@ Coords(Item item,
**********************************************************************************
*/
static int
-PointToChar(Item item,
+PointToChar(TextItem text,
int x,
int y)
{
- TextItem text = (TextItem) item;
int i, n, num_lines, dummy;
TextLineInfo lines, p;
Tk_FontMetrics fm;
@@ -1171,7 +1195,7 @@ PointToChar(Item item,
* Find the text line under point.
*/
num_lines = ZnListSize(text->text_info);
- lines = p = (TextLineInfo) ZnListArray(text->text_info);
+ lines = p = 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) {
@@ -1202,6 +1226,87 @@ PointToChar(Item item,
return p->start + p->num_chars - text->text;
}
+/*
+ * Return a new index from a current index and a
+ * move command.
+ *
+ * 0 end of index line
+ * 1 beginning of index line
+ * 2 next word or end of word from index
+ * 3 previous word or beginning of word from index
+ * 4 previous line from index line
+ * 5 next line from index line
+ *
+ */
+static int
+MoveFromIndex(TextItem text,
+ int index,
+ int move)
+{
+ int num_lines, num_chars;
+ int line_index, line_start;
+ TextLineInfo lines, p;
+ char *strp;
+
+ num_lines = ZnListSize(text->text_info);
+ lines = p = ZnListArray(text->text_info);
+ for (line_index = 0; line_index < num_lines; line_index++, p++) {
+ line_start = p->start - text->text;
+ num_chars = p->num_chars;
+ if (line_start + num_chars >= index) {
+ break;
+ }
+ }
+ if (line_index == num_lines) {
+ line_index--;
+ p--;
+ }
+
+ switch (move) {
+ case 0:
+ return line_start + num_chars;
+ case 1:
+ return line_start;
+ case 2:
+ strp = &text->text[index];
+ while ((strp[1] == ' ') || (strp[1] == '\n')) {
+ strp++;
+ }
+ while ((strp[1] != ' ') && (strp[1] != '\n') && strp[1]) {
+ strp++;
+ }
+ return strp + 1 - text->text;
+ case 3:
+ strp = &text->text[index];
+ while (((strp[-1] == ' ') || (strp[-1] == '\n')) && (strp != text->text)) {
+ strp--;
+ }
+ while ((strp[-1] != ' ') && (strp[-1] != '\n') && (strp != text->text)) {
+ strp--;
+ }
+ return strp - text->text;
+ case 4:
+ if (line_index > 0) {
+ index -= line_start;
+ p = &lines[line_index-1];
+ index = MIN(index, p->num_chars);
+ line_start = p->start - text->text;
+ index += line_start;
+ }
+ return index;
+ case 5:
+ if (line_index < num_lines-1) {
+ index -= line_start;
+ p = &lines[line_index+1];
+ index = MIN(index, p->num_chars);
+ line_start = p->start - text->text;
+ index += line_start;
+ }
+ default:
+ return index;
+ }
+}
+
static int
Index(Item item,
int field,
@@ -1210,6 +1315,7 @@ Index(Item item,
{
TextItem text = (TextItem) item;
WidgetInfo *wi = item->wi;
+ TextInfo *ti = &wi->text_info;
int c, length;
int x, y;
double tmp;
@@ -1219,27 +1325,50 @@ Index(Item item,
c = p[0];
length = strlen(p);
- if ((c == 'e') && (strncmp(p, "end", length) == 0)) {
+ if ((c == 'e') && (length > 1) && (strncmp(p, "end", length) == 0)) {
*index = text->num_chars;
}
+ else if ((c == 'e') && (length > 1) && (strncmp(p, "eol", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 0);
+ }
+ else if ((c == 'b') && (length > 1) && (strncmp(p, "bol", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 1);
+ }
+ else if ((c == 'e') && (length > 1) && (strncmp(p, "eow", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 2);
+ }
+ else if ((c == 'b') && (length > 1) && (strncmp(p, "bow", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 3);
+ }
+ else if ((c == 'u') && (strncmp(p, "up", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 4);
+ }
+ else if ((c == 'd') && (strncmp(p, "down", length) == 0)) {
+ *index = MoveFromIndex(text, text->insert_index, 5);
+ }
else if ((c == 'i') && (strncmp(p, "insert", length) == 0)) {
*index = text->insert_index;
}
else if ((c == 's') && (strncmp(p, "sel.first", length) == 0) &&
(length >= 5)) {
- if (wi->text_info.sel_item != item) {
+ if (ti->sel_item != item) {
Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
return TCL_ERROR;
}
- *index = wi->text_info.sel_first;
+ *index = ti->sel_first;
}
else if ((c == 's') && (strncmp(p, "sel.last", length) == 0) &&
(length >= 5)) {
- if (wi->text_info.sel_item != item) {
+ if (ti->sel_item != item) {
Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
return TCL_ERROR;
}
- *index = wi->text_info.sel_last;
+ /*
+ * We return a modified selection end so that it reflect
+ * the text index of the last character _not_ the insertion
+ * point between the last and the next.
+ */
+ *index = ti->sel_last-1;
}
else if (c == '@') {
p++;
@@ -1257,7 +1386,7 @@ Index(Item item,
/*y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
y = tmp;
- *index = PointToChar(item, x, y);
+ *index = PointToChar(text, x, y);
}
else if (Tcl_GetIntFromObj(wi->interp, index_spec, index) == TCL_OK) {
if (*index < 0){
@@ -1272,7 +1401,7 @@ Index(Item item,
Tcl_AppendResult(wi->interp, "bad index \"", p, "\"", (char *) NULL);
return TCL_ERROR;
}
-
+
return TCL_OK;
}
@@ -1337,10 +1466,6 @@ DeleteChars(Item item,
int count;
char *new;
- if (!text->text_info) {
- return;
- }
-
if (*first < 0) {
*first = 0;
}
@@ -1353,7 +1478,7 @@ DeleteChars(Item item,
count = *last + 1 - *first;
new = (char *) ZnMalloc((unsigned) (text->num_chars + 1 - count));
- strncpy(new, text->text, (size_t) first);
+ strncpy(new, text->text, (size_t) *first);
strcpy(new + *first, text->text + *last + 1);
ZnFree(text->text);
text->text = new;
@@ -1412,9 +1537,10 @@ Selection(Item item,
{
TextItem text = (TextItem) item;
WidgetInfo *wi = item->wi;
+ TextInfo *ti = &wi->text_info;
int count;
- count = wi->text_info.sel_last - wi->text_info.sel_first - offset;
+ count = ti->sel_last - ti->sel_first - offset;
if (count > max_chars) {
count = max_chars;
}
@@ -1424,7 +1550,7 @@ Selection(Item item,
if (count <= 0) {
return 0;
}
- strncpy(chars, text->text + wi->text_info.sel_first + offset, (size_t) count);
+ strncpy(chars, text->text + ti->sel_first + offset, (size_t) count);
chars[count] = 0;
return count;