aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2000-05-26 08:44:08 +0000
committerlecoanet2000-05-26 08:44:08 +0000
commit3f0180a73676ef6365802c2f2567be96191add37 (patch)
tree89c1b66127af08bc4bed1df34c0803b9cbb07e8c /generic
parent2a2ab8eca8e3b16586d36a0589ea93931676198a (diff)
downloadtkzinc-3f0180a73676ef6365802c2f2567be96191add37.zip
tkzinc-3f0180a73676ef6365802c2f2567be96191add37.tar.gz
tkzinc-3f0180a73676ef6365802c2f2567be96191add37.tar.bz2
tkzinc-3f0180a73676ef6365802c2f2567be96191add37.tar.xz
Ajout des m�thodes permettant l'�dition de texte, focus, selection,
index. Correction des autres m�thodes et int�gration avec la structure partag�e dans WidgetInfo.
Diffstat (limited to 'generic')
-rw-r--r--generic/Text.c441
1 files changed, 393 insertions, 48 deletions
diff --git a/generic/Text.c b/generic/Text.c
index 187a228..61e5020 100644
--- a/generic/Text.c
+++ b/generic/Text.c
@@ -24,12 +24,21 @@
*
*/
+/*
+ * Some functions in this file are derived from tkCanvText.c and thus
+ * copyrighted:
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ */
#include <math.h>
#include <ctype.h>
#include <X11/Xatom.h>
#include <malloc.h>
#include <string.h>
+#include <stdlib.h>
#include "Item.h"
#include "Geo.h"
@@ -42,16 +51,11 @@ static const char rcsid[] = "$Imagine: Text.c,v 1.13 1997/05/15 11:35:46 lecoane
static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
-static Bool got_selection = True;
-
-
/*
* Bit offset of flags.
*/
#define UNDERLINED 1
#define OVERSTRIKED 2
-#define HAS_FOCUS 4 /* True if the text has the focus and should display
- * the insertion cursor */
/*
@@ -88,9 +92,8 @@ typedef struct _TextItemStruct {
/* Private data */
ZnPoint pos_dev;
+ int num_chars;
int insert_index;
- int sel_start;
- int sel_end;
ZnList text_info;
int max_width;
} TextItemStruct, *TextItem;
@@ -145,7 +148,7 @@ static ZnAttrConfig text_attrs[] = {
{ ZN_CONFIG_BOOL, "-visible", NULL,
Tk_Offset(TextItemStruct, header.flags), VISIBLE_BIT,
ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
- { ZN_CONFIG_INT, "-width", NULL,
+ { ZN_CONFIG_DIM, "-width", NULL,
Tk_Offset(TextItemStruct, width), 0,
ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
@@ -179,6 +182,7 @@ Init(Item item,
text->pos.x = text->pos.y = 0.0;
text->text = "";
+ text->num_chars = 0;
text->fill_pattern = ZnUnspecifiedPattern;
text->anchor = ZnAnchorNW;
text->connection_anchor = ZnAnchorSW;
@@ -190,11 +194,8 @@ Init(Item item,
text->spacing = 0;
text->insert_index = 0;
- text->sel_start = 0;
- text->sel_end = 0;
CLEAR(text->flags, UNDERLINED);
CLEAR(text->flags, OVERSTRIKED);
- CLEAR(text->flags, HAS_FOCUS);
return ZN_OK;
}
@@ -343,12 +344,16 @@ ComputeCoordinates(Item item,
TextItem text = (TextItem) item;
TextLineInfo infos;
Tk_FontMetrics fm;
- int i, num_lines;
+ int i, fuzz, num_lines;
int cur_dy;
int font_height, height;
ResetBBox(&item->item_bounding_box);
- if (strlen(text->text) == 0) {
+ 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;
}
@@ -469,6 +474,8 @@ ComputeCoordinates(Item item,
}
else {
ZnTransformPoint(wi->current_transfo, &text->pos, &text->pos_dev);
+ text->pos_dev.x = REAL_TO_INT(text->pos_dev.x);
+ text->pos_dev.y = REAL_TO_INT(text->pos_dev.y);
}
Anchor2Origin(&text->pos_dev, text->max_width, height, text->anchor,
@@ -480,10 +487,11 @@ ComputeCoordinates(Item item,
AddPointToBBox(&item->item_bounding_box, text->pos_dev.x, text->pos_dev.y);
AddPointToBBox(&item->item_bounding_box, text->pos_dev.x+text->max_width+1,
text->pos_dev.y+height);
- item->item_bounding_box.orig.x -= 1;
- item->item_bounding_box.orig.y -= 1;
- item->item_bounding_box.corner.x += 1;
- item->item_bounding_box.corner.y += 1;
+ 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;
/*
* Update connected items.
@@ -587,7 +595,7 @@ Draw(Item item)
* position along the X axis.
*/
line_index = lines_ptr->start - text->text;
- if (ISSET(text->flags, HAS_FOCUS) &&
+ if ((wi->text_info.focus_item == item) && wi->text_info.got_focus &&
text->insert_index >= line_index &&
text->insert_index <= line_index + lines_ptr->num_chars) {
cursor_line = i;
@@ -599,22 +607,23 @@ Draw(Item item)
* Compute the selection first and last line as well as
* the positions along the X axis.
*/
- if (text->sel_end >= line_index &&
- text->sel_start <= line_index + lines_ptr->num_chars) {
+ 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 (sel_first_line < 0) {
- char_index = text->sel_start - line_index;
+ char_index = wi->text_info.sel_first - line_index;
if (char_index <= 0) {
sel_first_line = i;
sel_start_offset = 0;
- //printf("sel_start_offset 1 : %d\n", sel_start_offset);
+ /*printf("sel_start_offset 1 : %d\n", sel_start_offset);*/
}
else if (char_index <= lines_ptr->num_chars) {
sel_first_line = i;
sel_start_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start, char_index);
- //printf("sel_start_offset 2 : %d\n", sel_start_offset);
+ /*printf("sel_start_offset 2 : %d\n", sel_start_offset);*/
}
}
- char_index = text->sel_end - line_index;
+ char_index = wi->text_info.sel_last - line_index;
sel_last_line = i;
if (char_index == lines_ptr->num_chars+1)
sel_stop_offset = lines_ptr->width;
@@ -628,10 +637,10 @@ Draw(Item item)
/*
* Setup the gc for the selection and fill the selection.
*/
- if ((sel_first_line >= 0) && got_selection) {
+ if ((wi->text_info.sel_item == item) && (sel_first_line >= 0)) {
int x, y;
- values.foreground = ZnPixel(text->fill_color);
+ values.foreground = ZnPixel(wi->text_info.sel_color);
values.fill_style = FillSolid;
XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
@@ -645,21 +654,42 @@ Draw(Item item)
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, lines[sel_first_line].width - sel_start_offset, font_height);
+ x, y,
+ text->max_width-lines[sel_first_line].text_origin.x-sel_start_offset,
+ font_height);
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 + lines_ptr->text_origin.x);
- y = (int)(text->pos_dev.y + lines_ptr->text_origin.y - fm.ascent);
+ 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, lines_ptr->width, font_height);
+ x, y, text->max_width, font_height);
}
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, sel_stop_offset, font_height);
+ x, y, lines[sel_last_line].text_origin.x+sel_stop_offset,
+ font_height);
}
}
+ //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->text_info.focus_item == item) && wi->text_info.cursor_on) {
+ int xs, ys;
+
+ values.fill_style = FillSolid;
+ values.line_width = wi->text_info.insert_width;
+ values.foreground = ZnPixel(wi->text_info.insert_color);
+ 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 + font_height - 1);
+ }
+
/*
* Setup the gc to render the text and draw it.
*/
@@ -709,22 +739,6 @@ Draw(Item item)
tmp_x, y_over, tmp_x+lines_ptr->width, y_over);
}
}
-
- //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) && ISSET(text->flags, HAS_FOCUS)) {
- int xs, ys;
-
- values.fill_style = FillSolid;
- values.line_width = 2;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCLineWidth, &values);
-
- xs = (int)(text->pos_dev.x + lines[cursor_line].text_origin.x + cursor_offset + 1);
- 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 + font_height - 1);
- }
}
@@ -823,7 +837,7 @@ GetAnchor(Item item,
{
TextItem text = (TextItem) item;
- if (strlen(text->text) != 0) {
+ if (text->num_chars != 0) {
Origin2Anchor(&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,
@@ -904,6 +918,332 @@ Coords(Item item,
/*
**********************************************************************************
*
+ * Index --
+ * Parse a text index and return its value and aa
+ * error status (standard Tcl result).
+ *
+ **********************************************************************************
+ */
+static int
+PointToChar(Item item,
+ int x,
+ int y)
+{
+ TextItem text = (TextItem) item;
+ int i, n, num_lines, dummy;
+ TextLineInfo lines, p;
+ Tk_FontMetrics fm;
+
+ x -= text->pos_dev.x;
+ y -= text->pos_dev.y;
+
+ /*
+ * Point above text, returns index 0.
+ */
+ if (y < 0) {
+ return 0;
+ }
+
+ /*
+ * Find the text line under point.
+ */
+ num_lines = ZnListSize(text->text_info);
+ lines = p = (TextLineInfo) 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) {
+ /*
+ * Point to the left of the current line, returns
+ * index of first char.
+ */
+ return p->start - text->text;
+ }
+ if (x >= (p->text_origin.x + p->width)) {
+ /*
+ * Point to the right of the current line, returns
+ * index past the last char.
+ */
+ return p->start + p->num_chars - text->text;
+ }
+ n = Tk_MeasureChars(text->font, p->start, p->num_chars,
+ x + 2 - p->text_origin.x, TK_PARTIAL_OK, &dummy);
+ return (p->start + n - 1) - text->text;
+ }
+ }
+ /*
+ * Point below all lines, return the index after
+ * the last char in text.
+ */
+ p--;
+ return p->start + p->num_chars - text->text;
+}
+
+static int
+Index(Item item,
+ char *index_str,
+ int *index)
+{
+ TextItem text = (TextItem) item;
+ WidgetInfo *wi = item->wi;
+ int c, length;
+ int x, y;
+ double tmp;
+ char *end, *p;
+
+ c = index_str[0];
+ length = strlen(index_str);
+
+ if ((c == 'e') && (strncmp(index_str, "end", length) == 0)) {
+ *index = text->num_chars;
+ }
+ else if ((c == 'i') && (strncmp(index_str, "insert", length) == 0)) {
+ *index = text->insert_index;
+ }
+ else if ((c == 's') && (strncmp(index_str, "sel.first", length) == 0) &&
+ (length >= 5)) {
+ if (wi->text_info.sel_item != item) {
+ Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
+ return TCL_ERROR;
+ }
+ *index = wi->text_info.sel_first;
+ }
+ else if ((c == 's') && (strncmp(index_str, "sel.last", length) == 0) &&
+ (length >= 5)) {
+ if (wi->text_info.sel_item != item) {
+ Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
+ return TCL_ERROR;
+ }
+ *index = wi->text_info.sel_last;
+ }
+ else if (c == '@') {
+ p = index_str+1;
+ tmp = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ /*x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
+ x = tmp;
+ p = end+1;
+ tmp = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ /*y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
+ y = tmp;
+
+ *index = PointToChar(item, x-wi->inset, y-wi->inset);
+ }
+ else if (Tcl_GetInt(wi->interp, index_str, index) == TCL_OK) {
+ if (*index < 0){
+ *index = 0;
+ }
+ else if (*index > text->num_chars) {
+ *index = text->num_chars;
+ }
+ }
+ else {
+ badIndex:
+ Tcl_AppendResult(wi->interp, "bad index \"", index_str, "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * InsertChars --
+ *
+ **********************************************************************************
+ */
+static void
+InsertChars(Item item,
+ int index,
+ char *chars)
+{
+ TextItem text = (TextItem) item;
+ WidgetInfo *wi = item->wi;
+ int length = strlen(chars);
+ char *new;
+
+ if (length == 0) {
+ return;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ if (index > text->num_chars) {
+ index = text->num_chars;
+ }
+
+ new = ZnMalloc((unsigned) (text->num_chars + length + 1));
+ strncpy(new, text->text, (size_t) index);
+ strcpy(new+index, chars);
+ strcpy(new+index+length, text->text+index);
+ ZnFree(text->text);
+ text->text = new;
+ text->num_chars += length;
+
+ /*
+ * Inserting characters invalidates indices such as those for the
+ * selection and cursor. Update the indices appropriately.
+ */
+ if (wi->text_info.sel_item == item) {
+ if (wi->text_info.sel_first >= index) {
+ wi->text_info.sel_first += length;
+ }
+ if (wi->text_info.sel_last >= index) {
+ wi->text_info.sel_last += length;
+ }
+ if ((wi->text_info.anchor_item == item)
+ && (wi->text_info.sel_anchor >= index)) {
+ wi->text_info.sel_anchor += length;
+ }
+ }
+ if (text->insert_index >= index) {
+ text->insert_index += length;
+ }
+
+ ITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * DeleteChars --
+ *
+ **********************************************************************************
+ */
+static void
+DeleteChars(Item item,
+ int first,
+ int last)
+{
+ TextItem text = (TextItem) item;
+ WidgetInfo *wi = item->wi;
+ int count;
+ char *new;
+
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= text->num_chars) {
+ last = text->num_chars-1;
+ }
+ if (first > last) {
+ return;
+ }
+ count = last + 1 - first;
+
+ new = (char *) ZnMalloc((unsigned) (text->num_chars + 1 - count));
+ strncpy(new, text->text, (size_t) first);
+ strcpy(new+first, text->text+last+1);
+ ZnFree(text->text);
+ text->text = new;
+ text->num_chars -= count;
+
+ /*
+ * Update indexes for the selection and cursor to reflect the
+ * renumbering of the remaining characters.
+ */
+ if (wi->text_info.sel_item == item) {
+ if (wi->text_info.sel_first > first) {
+ wi->text_info.sel_first -= count;
+ if (wi->text_info.sel_first < first) {
+ wi->text_info.sel_first = first;
+ }
+ }
+ if (wi->text_info.sel_last >= first) {
+ wi->text_info.sel_last -= count;
+ if (wi->text_info.sel_last < (first-1)) {
+ wi->text_info.sel_last = (first-1);
+ }
+ }
+ if (wi->text_info.sel_first > wi->text_info.sel_last) {
+ wi->text_info.sel_item = ZN_NO_ITEM;
+ }
+ if ((wi->text_info.anchor_item == item)
+ && (wi->text_info.sel_anchor > first)) {
+ wi->text_info.sel_anchor -= count;
+ if (wi->text_info.sel_anchor < first) {
+ wi->text_info.sel_anchor = first;
+ }
+ }
+ }
+ if (text->insert_index > first) {
+ text->insert_index -= count;
+ if (text->insert_index < first) {
+ text->insert_index = first;
+ }
+ }
+
+ ITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Cursor --
+ *
+ **********************************************************************************
+ */
+static void
+TextCursor(Item item,
+ int index)
+{
+ TextItem text = (TextItem) item;
+
+ if (index < 0) {
+ text->insert_index = 0;
+ }
+ else if (index > text->num_chars) {
+ text->insert_index = text->num_chars;
+ }
+ else {
+ text->insert_index = index;
+ }
+}
+
+
+/*
+ **********************************************************************************
+ *
+ * Selection --
+ *
+ **********************************************************************************
+ */
+static int
+Selection(Item item,
+ int offset,
+ char *chars,
+ int max_chars)
+{
+ TextItem text = (TextItem) item;
+ WidgetInfo *wi = item->wi;
+ int count;
+
+ count = wi->text_info.sel_last - wi->text_info.sel_first - offset;
+ if (count > max_chars) {
+ count = max_chars;
+ }
+ if (count <= 0) {
+ return 0;
+ }
+ strncpy(chars, text->text + wi->text_info.sel_first + offset, (size_t) count);
+ chars[count] = '\0';
+
+ return count;
+}
+
+
+/*
+ **********************************************************************************
+ *
* Exported functions struct
*
**********************************************************************************
@@ -924,6 +1264,11 @@ static ItemClassStruct TEXT_ITEM_CLASS = {
GetAnchor,
GetClipVertices,
Coords,
+ InsertChars,
+ DeleteChars,
+ TextCursor,
+ Index,
+ Selection,
NULL, /* Contour */
ComputeCoordinates,
ToArea,