1
/* This file is part of Malaga, a system for Natural Language Analysis.
2
* Copyright (C) 1995-1999 Bjoern Beutel
5
* Universitaet Erlangen-Nuernberg
6
* Abteilung fuer Computerlinguistik
9
* e-mail: malaga@linguistik.uni-erlangen.de
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
25
/* description ==============================================================*/
27
/* This is a TCL/TK package that implements feature/value matrixes for
30
/* includes =================================================================*/
50
/* constants ================================================================*/
52
#define VALUE_ERROR_STRING_LENGTH 256
54
#define RECORD_TOP_BORDER 3
55
#define RECORD_BOTTOM_BORDER 3
56
#define RECORD_LEFT_BORDER 6
57
#define RECORD_RIGHT_BORDER 6
58
#define LIST_TOP_BORDER 3
59
#define LIST_BOTTOM_BORDER 3
60
#define ANGLE_BRACKET_RATIO 6 /* height:width ratio of angle brackets */
61
#define POINT_SIZE_LEN 20
65
#define HANGUL_FONT "-*-mincho-medium-r-normal--*-*-*-*-c-*-ksc5601.1987-0"
66
#define BUFFER_SIZE 500
69
/* types ====================================================================*/
71
typedef enum /* type of a node in "matrix_value_t" */
78
typedef struct MATRIX_VALUE_T /* a Malaga value in TK */
80
value_type_t value_type; /* type of this node */
81
struct MATRIX_VALUE_T *first; /* first element if record or list */
82
struct MATRIX_VALUE_T *next; /* next element for record and list elements */
83
string_t attribute; /* attribute name (if record element) */
84
string_t string; /* string (for STRING_TYPE) */
85
int_t attribute_width; /* width of attribute */
86
int_t width; /* width of value box */
87
int_t height; /* height of value box */
90
typedef struct MATRIX_ITEM /* The structure defines a canvas item. */
92
Tk_Item header; /* generic stuff - MUST BE FIRST IN STRUCTURE! */
93
double x, y; /* positioning point for matrix: upper left */
94
GC gc; /* graphics context for lines and text */
95
short line_width; /* width of a brace line */
96
XColor *color; /* color for line and text */
97
string_t char_set; /* latin1 and hangul (KSC5601) are supported. */
98
#if TK_MAJOR_VERSION > 4
99
Tk_Font font; /* font for drawing text */
101
XFontStruct *font; /* font for drawing text */
103
short ascent; /* ascent of <font> */
104
short line_height; /* height of a line in <font> */
105
short space_width; /* with of a space in <font> */
106
short comma_width; /* with of a comma in <font> */
107
matrix_value_t *root_value; /* value tree for matrix object */
109
XFontStruct *hangul_font; /* font for drawing hangul characters */
113
/* variables ================================================================*/
115
LOCAL char value_error_string[VALUE_ERROR_STRING_LENGTH];
116
/* buffer for parse errors */
118
LOCAL bool_t parse_value_error;
119
LOCAL jmp_buf *parse_value_error_jump_point;
120
/* the current point of return in case of an error */
122
LOCAL Tk_CustomOption tagsOption =
123
{Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, (ClientData) NULL};
125
LOCAL Tk_ConfigSpec config_specs[] =
126
/* Information used for parsing configuration specs. If you change any
127
* of the default strings, be sure to change the corresponding default
128
* values in CreateMatrix. */
130
{TK_CONFIG_COLOR, "-fill", NULL, NULL,
131
"black", Tk_Offset (matrix_t, color), TK_CONFIG_NULL_OK},
132
{TK_CONFIG_PIXELS, "-line_width", NULL, NULL,
133
"1", Tk_Offset (matrix_t, line_width), TK_CONFIG_DONT_SET_DEFAULT},
134
{TK_CONFIG_STRING, "-char_set", NULL, NULL,
135
"latin1", Tk_Offset (matrix_t, char_set), 0},
136
{TK_CONFIG_FONT, "-font", NULL, NULL,
137
"-*-helvetica-medium-r-normal--14-*-75-75-p-*-iso8859-1",
138
Tk_Offset (matrix_t, font), 0},
139
{TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
140
NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
141
{TK_CONFIG_END, NULL, NULL, NULL,
146
LOCAL XChar2b string16[BUFFER_SIZE]; /* buffer for converted KSC string */
147
LOCAL XFontStruct *hangul_font;
148
LOCAL int_t hangul_font_refs; /* number of references to <hangul_font> */
151
/* forward declarations =====================================================*/
153
FORWARD matrix_value_t *local_parse_value (void);
155
/* functions ================================================================*/
157
LOCAL void error_handler (string_t format, ...) NO_RETURN;
158
LOCAL void error_handler (string_t format, ...)
159
/* Manage syntax errors during parsing of Malaga value structures. */
163
va_start (arg, format);
165
if (parse_value_error_jump_point != NULL)
167
vsprintf (value_error_string, format, arg);
170
parse_value_error = 1;
171
longjmp (*parse_value_error_jump_point, 1);
176
fprintf (stderr, "error: ");
178
vfprintf (stderr, format, arg);
179
fputc ('\n', stderr);
186
/* parsing Malaga values ====================================================*/
188
LOCAL void free_value (matrix_value_t **value_ptr)
189
/* Free memory used by the tree. */
191
matrix_value_t *value, *next_value;
193
for (value = *value_ptr; value != NULL; value = next_value)
195
next_value = value->next;
196
free_value (&value->first);
197
free_mem (&value->attribute);
198
free_mem (&value->string);
204
/*---------------------------------------------------------------------------*/
206
LOCAL string_t parse_symbol (void)
207
/* Parse a symbol and return it. */
211
test_token (TOK_IDENT);
212
symbol = new_string (token_name, NULL);
217
/*---------------------------------------------------------------------------*/
219
LOCAL matrix_value_t *parse_attribute_value_pair (void)
220
/* Parse an attribute-value pair and return a pointer to it. */
223
matrix_value_t *new_value;
225
if (next_token == '(') /* Read a hidden attribute. */
228
attribute = parse_symbol ();
230
new_value = new_mem (sizeof (matrix_value_t));
231
new_value->value_type = STRING_TYPE;
232
new_value->attribute = concat_strings (attribute, ":", NULL);
233
new_value->string = new_string ("...", NULL);
234
free_mem (&attribute);
238
attribute = parse_symbol ();
240
new_value = local_parse_value ();
241
new_value->attribute = concat_strings (attribute, ":", NULL);
242
free_mem (&attribute);
247
/*---------------------------------------------------------------------------*/
249
LOCAL matrix_value_t *local_parse_value (void)
250
/* Parse a value and return it as a "matrix_value". */
252
matrix_value_t *new_value_ptr;
254
/* pointer to last list or record element */
255
matrix_value_t *element_ptr;
257
new_value_ptr = new_mem (sizeof (matrix_value_t));
262
new_value_ptr->value_type = LIST_TYPE;
264
if (next_token != '>') /* Insert "new_value" as first list element. */
266
new_value_ptr->first = local_parse_value ();
267
element_ptr = new_value_ptr->first;
269
while (next_token == ',')
273
/* Insert "new_value" as successor element. */
274
element_ptr->next = local_parse_value ();
275
element_ptr = element_ptr->next;
282
new_value_ptr->value_type = RECORD_TYPE;
284
if (next_token != ']')
286
new_value_ptr->first = parse_attribute_value_pair ();
287
element_ptr = new_value_ptr->first;
288
while (next_token == ',')
291
element_ptr->next = parse_attribute_value_pair ();
292
element_ptr = element_ptr->next;
299
new_value_ptr->value_type = STRING_TYPE;
300
new_value_ptr->string = parse_symbol ();
304
new_value_ptr->value_type = STRING_TYPE;
305
new_value_ptr->string = concat_strings ("\"", token_string, "\"", NULL);
310
new_value_ptr->value_type = STRING_TYPE;
311
new_value_ptr->string = double_to_string (token_number);
316
error ("value expected, not `%s'", token_as_text (next_token));
318
return new_value_ptr;
321
/*---------------------------------------------------------------------------*/
323
LOCAL matrix_value_t *build_value_tree (string_t string_value)
324
/* Parse Malaga value "*string_value" and return it as a "matrix_value". */
326
/* where to jump after an error */
327
static jmp_buf local_parse_error_jump_point;
328
matrix_value_t *first_value;
331
setjmp (local_parse_error_jump_point);
332
parse_value_error_jump_point = &local_parse_error_jump_point;
334
if (parse_value_error)
336
free_value (&first_value);
337
parse_value_error_jump_point = NULL;
338
parse_value_error = FALSE;
342
set_scanner_input ((string_t) string_value);
343
if (next_token == '!') /* Enter a string without quotes. */
346
test_token (TOK_STRING);
347
first_value = new_mem (sizeof (matrix_value_t));
348
first_value->value_type = STRING_TYPE;
349
first_value->string = new_string (token_string, NULL);
353
first_value = local_parse_value ();
355
/* Allow an additional ';'. */
356
if (next_token == ';')
360
parse_value_error_jump_point = NULL;
365
/* displaying Malaga values =================================================*/
368
LOCAL int_t string_to_string16 (string_t string)
369
/* Convert <string> to <string16> and return its length. */
373
for (n = 0; n < BUFFER_SIZE; n++)
375
if (ORD (string[0]) < 0xa0 || ORD (string[1]) < 0xa0)
378
/* Convert KSC5601 character. */
379
string16[n].byte1 = ORD (string[0]) & 0x7f;
380
string16[n].byte2 = ORD (string[1]) & 0x7f;
387
/*---------------------------------------------------------------------------*/
389
LOCAL int_t string_width (matrix_t *matrix, string_t string)
390
/* Return width of <string> in pixels when displayed as part of <matrix>. */
394
if (matrix->hangul_font != NULL)
399
while (*string != EOS)
400
{ /* Add width of a Hangul segment. */
402
n = string_to_string16 (string);
405
width += XTextWidth16 (matrix->hangul_font, string16, n);
407
/* Add width of an ASCII segment. */
409
while (*string != EOS
410
&& (ORD (string[0]) < 0xa0 || ORD (string[1]) < 0xa0))
417
#if TK_MAJOR_VERSION > 4
418
width += Tk_TextWidth (matrix->font, string - n, n);
420
width += XTextWidth (matrix->font, string - n, n);
428
#if TK_MAJOR_VERSION > 4
429
return Tk_TextWidth (matrix->font, string, strlen (string));
431
return XTextWidth (matrix->font, string, strlen (string));
435
/*---------------------------------------------------------------------------*/
437
LOCAL void draw_string (Display *display,
443
/* Draw a string as part of a value matrix. */
445
origin_y += matrix->ascent;
448
if (matrix->hangul_font != NULL)
449
/* Hangul KSC5601 section - show hangul characters in Hangul font.
450
* All other characters are shown in normal font. */
454
while (*string != '\0')
456
/* Display a Hangul segment. */
457
n = string_to_string16 (string);
461
XSetFont (display, matrix->gc, matrix->hangul_font->fid);
462
XDrawString16 (display, drawable, matrix->gc,
463
origin_x, origin_y, string16, n);
464
origin_x += XTextWidth16 (matrix->hangul_font, string16, n);
467
/* Print an ASCII segment. */
469
while (*string != EOS
470
&& (ORD (string[0]) < 0xa0 || ORD (string[1]) < 0xa0))
477
#if TK_MAJOR_VERSION > 4
478
XSetFont (display, matrix->gc, Tk_FontId (matrix->font));
479
Tk_DrawChars (display, drawable, matrix->gc, matrix->font,
480
string - n, n, origin_x, origin_y);
481
origin_x += Tk_TextWidth (matrix->font, string - n, n);
483
XSetFont (display, matrix->gc, matrix->font->fid);
484
XDrawString (display, drawable, matrix->gc, origin_x, origin_y,
486
origin_x += XTextWidth (matrix->font, string - n, n);
494
/* Display Latin1 string. */
495
#if TK_MAJOR_VERSION > 4
496
Tk_DrawChars (display, drawable, matrix->gc, matrix->font,
497
string, strlen (string), origin_x, origin_y);
499
XDrawString (display, drawable, matrix->gc, origin_x, origin_y,
500
string, strlen (string));
504
/*---------------------------------------------------------------------------*/
506
LOCAL int_t max_attribute_width (matrix_value_t *value)
507
/* Compute maximum attribute width of a record. */
509
matrix_value_t *element;
510
int_t max_length = 0;
512
for (element = value->first; element != NULL; element = element->next)
513
max_length = MAX (max_length, element->attribute_width);
517
/*---------------------------------------------------------------------------*/
519
LOCAL void compute_value_bounding_box (matrix_t *matrix,
520
matrix_value_t *value)
521
/* Compute the coordinates of matrix value <value> in <matrix> */
523
matrix_value_t *element;
525
if (value->attribute != NULL)
526
value->attribute_width = string_width (matrix, value->attribute);
528
switch (value->value_type)
532
int_t max_attrib_width, max_element_width;
535
max_attrib_width = 0;
536
max_element_width = 0;
537
for (element = value->first; element != NULL; element = element->next)
539
compute_value_bounding_box (matrix, element);
540
max_attrib_width = MAX (max_attrib_width, element->attribute_width);
541
max_element_width = MAX (max_element_width, element->width);
542
value->height += element->height;
545
value->height = (RECORD_TOP_BORDER
546
+ MAX (value->height, matrix->line_height)
547
+ RECORD_BOTTOM_BORDER);
548
value->width = (RECORD_LEFT_BORDER + max_attrib_width
549
+ matrix->space_width + max_element_width
550
+ RECORD_RIGHT_BORDER);
556
int_t max_element_height;
559
max_element_height = matrix->line_height;
560
for (element = value->first; element != NULL; element = element->next)
562
compute_value_bounding_box (matrix, element);
564
max_element_height = MAX (max_element_height, element->height);
565
value->width += element->width;
566
if (element->next != NULL)
567
value->width += (matrix->comma_width + matrix->space_width);
571
value->height = (LIST_TOP_BORDER + max_element_height
572
+ LIST_BOTTOM_BORDER);
573
value->width += 2 * (value->height / ANGLE_BRACKET_RATIO);
578
value->width = string_width (matrix, value->string);
579
value->height = matrix->line_height;
583
error ("unexpected node type");
587
/*---------------------------------------------------------------------------*/
589
LOCAL void compute_matrix_bounding_box (matrix_t *matrix)
590
/* Compute the bounding box of all the pixels that may be
591
* drawn as part of matrix <matrix>. */
593
compute_value_bounding_box (matrix, matrix->root_value);
594
matrix->header.x1 = (int) matrix->x ;
595
matrix->header.y1 = (int) matrix->y;
596
matrix->header.x2 = (int) (matrix->x + matrix->root_value->width);
597
matrix->header.y2 = (int) (matrix->y + matrix->root_value->height);
600
/*---------------------------------------------------------------------------*/
602
LOCAL int configure_matrix (Tcl_Interp *interp,
608
/* Configure various aspects of matrix <item>. */
610
matrix_t *matrix = (matrix_t *) item;
614
Tk_Window tk_window = Tk_CanvasTkwin (canvas);
616
if (Tk_ConfigureWidget (interp, tk_window, config_specs,
617
argc, argv, (char *) matrix, flags) != TCL_OK)
621
if ((strcmp (matrix->char_set, "latin1") != 0) &&
622
(strcmp (matrix->char_set, "hangul") != 0))
624
Tcl_AppendResult (interp, "for matrix widget, option \"-char_set\" "
625
"should be \"latin1\" or \"hangul\"", NULL);
629
if (strcmp (matrix->char_set, "hangul") == 0 && matrix->hangul_font == NULL)
631
if (hangul_font == NULL)
632
hangul_font = XLoadQueryFont (Tk_Display (tk_window), HANGUL_FONT);
633
if (hangul_font == NULL)
635
Tcl_AppendResult (interp, "can't load hangul font for matrix widget");
639
matrix->hangul_font = hangul_font;
642
else if (strcmp (matrix->char_set, "hangul") != 0
643
&& matrix->hangul_font != NULL)
645
matrix->hangul_font = NULL;
651
if (matrix->color != NULL && matrix->font != NULL)
653
gc_values.foreground = matrix->color->pixel;
654
#if TK_MAJOR_VERSION > 4
655
gc_values.font = Tk_FontId (matrix->font);
657
gc_values.font = matrix->font->fid;
659
mask = GCForeground|GCFont;
660
new_gc = Tk_GetGC (tk_window, mask, &gc_values);
662
#if TK_MAJOR_VERSION > 4
664
Tk_FontMetrics font_metrics;
666
Tk_GetFontMetrics (matrix->font, &font_metrics);
667
matrix->ascent = font_metrics.ascent;
668
matrix->line_height = (font_metrics.ascent + font_metrics.descent);
669
matrix->space_width = Tk_TextWidth (matrix->font, " ", 1);
670
matrix->comma_width = Tk_TextWidth (matrix->font, ",", 1);
673
matrix->ascent = matrix->font->ascent;
674
matrix->line_height = (matrix->font->ascent + matrix->font->descent);
675
matrix->space_width = XTextWidth (matrix->font, " ", 1);
676
matrix->comma_width = XTextWidth (matrix->font, ",", 1);
680
if (matrix->gc != None)
681
Tk_FreeGC (Tk_Display (tk_window), matrix->gc);
685
compute_matrix_bounding_box (matrix);
690
/*---------------------------------------------------------------------------*/
692
LOCAL void delete_matrix (Tk_Canvas canvas, Tk_Item *item, Display *display)
693
/* Delete Matrix <item>. */
695
matrix_t *matrix = (matrix_t *) item;
697
if (matrix->root_value != NULL)
698
free_value (&matrix->root_value);
700
if (matrix->color != NULL)
701
Tk_FreeColor (matrix->color);
703
if (matrix->gc != None)
704
Tk_FreeGC (display, matrix->gc);
706
if (matrix->font != NULL)
707
#if TK_MAJOR_VERSION > 4
708
Tk_FreeFont (matrix->font);
710
Tk_FreeFontStruct (matrix->font);
714
if (matrix->hangul_font != NULL)
716
matrix->hangul_font = NULL;
720
if (hangul_font != NULL && hangul_font_refs == 0)
722
XFreeFont (display, hangul_font);
728
/*---------------------------------------------------------------------------*/
730
LOCAL int create_matrix (Tcl_Interp *interp,
735
/* Create a new matrix item in a canvas. */
737
matrix_t *matrix = (matrix_t *) item;
741
Tcl_AppendResult (interp, "wrong # args: should be \"",
742
Tk_PathName (Tk_CanvasTkwin (canvas)), "\" create ",
743
item->typePtr->name, " x1 y1 value ?options?",
748
/* Carry out initialisation that is needed to set defaults and to
749
* allow proper cleanup after errors during the the remainder of
752
/* Process the arguments to fill in the item record. */
753
if (Tk_CanvasGetCoord (interp, canvas, argv[0], &matrix->x) != TCL_OK
754
|| Tk_CanvasGetCoord (interp, canvas, argv[1], &matrix->y) != TCL_OK)
758
matrix->color = None;
759
matrix->line_width = 1;
761
matrix->char_set = NULL;
762
matrix->line_height = 0;
763
matrix->space_width = 0;
764
matrix->comma_width = 0;
765
matrix->root_value = NULL;
766
parse_value_error_jump_point = NULL;
767
parse_value_error = 0;
769
matrix->hangul_font = NULL;
772
matrix->root_value = build_value_tree (argv[2]);
773
if (matrix->root_value == NULL)
775
Tcl_AppendResult (interp, value_error_string, (char *) NULL);
781
if (configure_matrix (interp, canvas, item, argc-3, argv+3, 0) != TCL_OK)
783
/*delete_matrix (canvas, item, Tk_Display (Tk_CanvasTkwin (canvas))); */
791
/*---------------------------------------------------------------------------*/
793
LOCAL int matrix_coords (Tcl_Interp *interp,
798
/* Implement "coords" widget command on matrices. */
800
matrix_t *matrix = (matrix_t *) item;
801
char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
805
Tcl_PrintDouble (interp, matrix->x, x);
806
Tcl_PrintDouble (interp, matrix->y, y);
807
Tcl_AppendResult (interp, x, " ", y, (char *) NULL);
811
if (Tk_CanvasGetCoord (interp, canvas, argv[0], &matrix->x) != TCL_OK
812
|| Tk_CanvasGetCoord (interp, canvas, argv[1], &matrix->y) != TCL_OK)
815
compute_matrix_bounding_box (matrix);
819
sprintf (interp->result,
820
"wrong # coordinates: expected 0 or 2, got %d", argc);
826
/*---------------------------------------------------------------------------*/
828
LOCAL void display_value (Display *display,
831
matrix_value_t *value,
838
/* Draw a matrix value in a given drawable. */
840
matrix_value_t *element;
841
XPoint points[MAX_POINTS];
842
int_t element_origin_x, element_origin_y, element_bottom;
844
/* If (sub)value is out of bounds, no need to draw it. */
845
if (origin_x >= x + width || origin_y >= y + height
846
|| origin_x + value->width <= x || origin_y + value->height <= y)
849
switch (value->value_type)
852
points[0].x = origin_x + RECORD_LEFT_BORDER - 1;
853
points[0].y = origin_y + 1;
855
points[1].x = origin_x + 1;
856
points[1].y = origin_y + 1;
858
points[2].x = origin_x + 1;
859
points[2].y = origin_y + value->height - 2;
861
points[3].x = origin_x + RECORD_LEFT_BORDER - 1;
862
points[3].y = origin_y + value->height - 2;
864
XDrawLines (display, drawable, matrix->gc, points, 4, CoordModeOrigin);
866
points[0].x = origin_x + value->width - RECORD_RIGHT_BORDER;
867
points[0].y = origin_y + 1;
869
points[1].x = origin_x + value->width - 2;
870
points[1].y = origin_y + 1;
872
points[2].x = origin_x + value->width - 2;
873
points[2].y = origin_y + value->height - 2;
875
points[3].x = origin_x + value->width - RECORD_RIGHT_BORDER;
876
points[3].y = origin_y + value->height - 2;
878
XDrawLines (display, drawable, matrix->gc, points, 4, CoordModeOrigin);
880
element_origin_x = (origin_x + RECORD_LEFT_BORDER +
881
max_attribute_width (value) + matrix->space_width);
882
element_origin_y = origin_y + RECORD_TOP_BORDER;
884
for (element = value->first; element != NULL; element = element->next)
886
draw_string (display, drawable, matrix,
887
origin_x + RECORD_LEFT_BORDER,
889
+ (element->height - matrix->line_height) / 2,
892
display_value (display, matrix, drawable, element,
893
element_origin_x, element_origin_y, x, y, width, height);
894
element_origin_y += element->height;
900
int_t angle_bracket_width = value->height / ANGLE_BRACKET_RATIO;
902
points[0].x = origin_x + angle_bracket_width;
903
points[0].y = origin_y + 1;
905
points[1].x = origin_x + 1;
906
points[1].y = origin_y + value->height / 2;
908
points[2].x = origin_x + angle_bracket_width;
909
points[2].y = origin_y + value->height - 2;
911
XDrawLines (display, drawable, matrix->gc, points, 3, CoordModeOrigin);
913
points[0].x = origin_x + value->width - angle_bracket_width - 1;
914
points[0].y = origin_y + 1;
916
points[1].x = origin_x + value->width - 2;
917
points[1].y = origin_y + value->height / 2;
919
points[2].x = origin_x + value->width - angle_bracket_width - 1;
920
points[2].y = origin_y + value->height - 2;
922
XDrawLines (display, drawable, matrix->gc, points, 3, CoordModeOrigin);
924
element_origin_x = origin_x + angle_bracket_width + 2;
925
element_bottom = origin_y + value->height - LIST_BOTTOM_BORDER;
927
for (element = value->first; element != NULL; element = element->next)
929
display_value (display, matrix, drawable, element,
930
element_origin_x, element_bottom - element->height,
931
x, y, width, height);
932
element_origin_x += element->width;
934
if (element->next != NULL)
936
draw_string (display, drawable, matrix, element_origin_x,
937
element_bottom - matrix->line_height, ",");
938
element_origin_x += (matrix->comma_width + matrix->space_width);
945
draw_string (display, drawable, matrix, origin_x, origin_y, value->string);
949
error ("unexpected node type");
953
/*---------------------------------------------------------------------------*/
955
LOCAL void display_matrix (Tk_Canvas canvas,
963
/* Draw a matrix in a given drawable. */
965
matrix_t *matrix = (matrix_t *) item;
966
short origin_x, origin_y;
968
Tk_CanvasDrawableCoords (canvas, matrix->x, matrix->y,
969
&origin_x, &origin_y);
970
display_value (display, matrix, drawable, matrix->root_value,
972
x + origin_x - matrix->x, y + origin_y - matrix->y,
976
/*---------------------------------------------------------------------------*/
978
LOCAL double matrix_to_point (Tk_Canvas canvas, Tk_Item *item, double point[])
979
/* Return the distance between the point (<point>[0], <point>[1])
980
* and the matrix <item>. If the point is inside, return 0. */
982
matrix_t *matrix = (matrix_t *) item;
983
double diff_x, diff_y;
985
if (point[0] < matrix->header.x1)
986
diff_x = matrix->header.x1 - point[0];
987
else if (point[0] > matrix->header.x2)
988
diff_x = point[0] - matrix->header.x1;
992
if (point[1] < matrix->header.y1)
993
diff_y = matrix->header.y1 - point[1];
994
else if (point[1] > matrix->header.y2)
995
diff_y = point[1] - matrix->header.y1;
1000
return sqrt (diff_x * diff_x + diff_y * diff_y);
1003
/*---------------------------------------------------------------------------*/
1005
LOCAL int matrix_to_area (Tk_Canvas canvas, Tk_Item *item, double rect[])
1006
/* Return -1 if <item> lies entirely outside <rect>,
1007
* 0 if it overlaps, and 1 if it is entirely inside. */
1009
matrix_t *matrix = (matrix_t *) item;
1011
if (matrix->header.x2 < rect[0] ||
1012
matrix->header.x1 > rect[2] ||
1013
matrix->header.y2 < rect[1] ||
1014
matrix->header.y1 > rect[3])
1017
if (matrix->header.x1 >= rect[0] &&
1018
matrix->header.x2 <= rect[2] &&
1019
matrix->header.y1 >= rect[1] &&
1020
matrix->header.y2 <= rect[3])
1026
/*---------------------------------------------------------------------------*/
1028
LOCAL void scale_matrix (Tk_Canvas canvas,
1034
/* Rescale a matrix item. */
1036
/* matrices can't be scaled */
1039
/*---------------------------------------------------------------------------*/
1041
LOCAL void translate_matrix (Tk_Canvas canvas,
1045
/* Move matrix <item> by <delta_x> and <delta_y>. */
1047
matrix_t *matrix = (matrix_t *) item;
1049
matrix->x += delta_x;
1050
matrix->y += delta_y;
1052
matrix->header.x1 = (int) matrix->x;
1053
matrix->header.y1 = (int) matrix->y;
1054
matrix->header.x2 = (int) (matrix->x + matrix->root_value->width);
1055
matrix->header.y2 = (int) (matrix->y + matrix->root_value->height);
1058
/*---------------------------------------------------------------------------*/
1060
LOCAL void line_to_ps (Tcl_Interp *interp,
1064
int_t num_of_points)
1065
/* Print line in postscript format. */
1069
Tk_CanvasPsPath (interp, canvas, points, num_of_points);
1070
sprintf (buffer, "%d setlinewidth\n", matrix->line_width);
1071
Tcl_AppendResult (interp, buffer, NULL);
1072
Tcl_AppendResult (interp, "stroke\n", NULL);
1075
/*---------------------------------------------------------------------------*/
1077
LOCAL void string_to_ps (Tcl_Interp *interp,
1083
/* Print <string> in postscript format at <origin_x>/<origin_y>. */
1088
sprintf (buffer, "%.15g %.15g moveto ",
1090
Tk_CanvasPsY (canvas, (double) origin_y + matrix->ascent));
1091
Tcl_AppendResult (interp, buffer, NULL);
1093
sprintf (buffer, "(");
1094
for (s = string; *s != EOS; s++)
1096
if (*s == '(' || *s == ')' || *s == '\\')
1097
sprintf (buffer, "\\%c", *s);
1099
sprintf (buffer, "%c", *s);
1102
sprintf (buffer, "(%s) show\n", string);
1103
Tcl_AppendResult (interp, buffer, NULL);
1106
/*---------------------------------------------------------------------------*/
1108
LOCAL void value_to_postscript (Tcl_Interp *interp,
1111
matrix_value_t *value,
1114
/* Generate Postscript code for a value. */
1116
matrix_value_t *element;
1117
double points[2 * MAX_POINTS];
1118
int_t element_origin_x, element_origin_y, element_bottom;
1120
switch (value->value_type)
1123
points[0] = origin_x + RECORD_LEFT_BORDER - 1;
1124
points[1] = origin_y + 1;
1126
points[2] = origin_x + 1;
1127
points[3] = origin_y + 1;
1129
points[4] = origin_x + 1;
1130
points[5] = origin_y + value->height - 2;
1132
points[6] = origin_x + RECORD_LEFT_BORDER - 1;
1133
points[7] = origin_y + value->height - 2;
1135
line_to_ps (interp, canvas, matrix, points, 4);
1137
points[0] = origin_x + value->width - RECORD_RIGHT_BORDER;
1138
points[1] = origin_y + 1;
1140
points[2] = origin_x + value->width - 2;
1141
points[3] = origin_y + 1;
1143
points[4] = origin_x + value->width - 2;
1144
points[5] = origin_y + value->height - 2;
1146
points[6] = origin_x + value->width - RECORD_RIGHT_BORDER;
1147
points[7] = origin_y + value->height - 2;
1149
line_to_ps (interp, canvas, matrix, points, 4);
1151
element_origin_x = (origin_x + RECORD_LEFT_BORDER
1152
+ max_attribute_width (value) + matrix->space_width);
1153
element_origin_y = origin_y + RECORD_TOP_BORDER;
1155
for (element = value->first; element != NULL; element = element->next)
1157
string_to_ps (interp, canvas, matrix,
1159
origin_x + RECORD_LEFT_BORDER,
1161
+ (element->height - matrix->line_height)/2);
1163
value_to_postscript (interp, canvas, matrix, element,
1164
element_origin_x, element_origin_y);
1166
element_origin_y += element->height;
1172
int_t angle_bracket_width = value->height / ANGLE_BRACKET_RATIO;
1174
points[0] = origin_x + angle_bracket_width;
1175
points[1] = origin_y + 1;
1177
points[2] = origin_x + 1;
1178
points[3] = origin_y + value->height / 2;
1180
points[4] = origin_x + angle_bracket_width;
1181
points[5] = origin_y + value->height - 2;
1183
line_to_ps (interp, canvas, matrix, points, 3);
1185
points[0] = origin_x + value->width - angle_bracket_width-1;
1186
points[1] = origin_y + 1;
1188
points[2] = origin_x + value->width - 2;
1189
points[3] = origin_y + value->height / 2;
1191
points[4] = origin_x + value->width - angle_bracket_width-1;
1192
points[5] = origin_y + value->height - 2;
1194
line_to_ps (interp, canvas, matrix, points, 3);
1196
element_origin_x = origin_x + angle_bracket_width + 2;
1197
element_bottom = origin_y + value->height - LIST_BOTTOM_BORDER;
1199
for (element = value->first; element != NULL; element = element->next)
1201
value_to_postscript (interp, canvas, matrix, element,
1202
element_origin_x, element_bottom - element->height);
1204
element_origin_x += element->width;
1206
if (element->next != NULL)
1208
string_to_ps (interp, canvas, matrix, ",",
1209
element_origin_x, element_bottom - matrix->line_height);
1210
element_origin_x += (matrix->comma_width + matrix->space_width);
1217
string_to_ps (interp, canvas, matrix, value->string, origin_x, origin_y);
1221
error ("unexpected node type");
1225
/*---------------------------------------------------------------------------*/
1227
LOCAL int matrix_to_postscript (Tcl_Interp *interp,
1231
/* Generate Postscript code for a matrix. */
1233
matrix_t *matrix = (matrix_t *) item;
1238
if (matrix->color == NULL)
1241
if (Tk_CanvasPsFont (interp, canvas, matrix->font) != TCL_OK)
1244
if (Tk_CanvasPsColor (interp, canvas, matrix->color) != TCL_OK)
1247
value_to_postscript (interp, canvas, matrix, matrix->root_value,
1248
matrix->header.x1, matrix->header.y1);
1253
/*---------------------------------------------------------------------------*/
1255
/* procedures of matrix item type that can be invoked by generic item code */
1256
Tk_ItemType matrix_type =
1258
"matrix", /* name */
1259
sizeof (matrix_t), /* itemSize */
1260
create_matrix, /* createProc */
1261
config_specs, /* configSpecs */
1262
configure_matrix, /* configureProc */
1263
matrix_coords, /* coordProc */
1264
delete_matrix, /* deleteProc */
1265
display_matrix, /* displayProc */
1266
0, /* alwaysRedraw */
1267
matrix_to_point, /* pointProc */
1268
matrix_to_area, /* areaProc */
1269
matrix_to_postscript, /* postscriptProc */
1270
scale_matrix, /* scaleProc */
1271
translate_matrix, /* translateProc */
1272
(Tk_ItemIndexProc *) NULL, /* indexProc */
1273
(Tk_ItemCursorProc *) NULL, /* icursorProc */
1274
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
1275
(Tk_ItemInsertProc *) NULL, /* insertProc */
1276
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
1277
(Tk_ItemType *) NULL /* nextPtr */
1280
/*---------------------------------------------------------------------------*/
1282
int Matrix_Init (Tcl_Interp *interp)
1283
/* Initialise the package. */
1285
/* Install error handler. */
1286
error = error_handler;
1288
/* Insert <matrix_type> into the type list. */
1289
Tk_CreateItemType (&matrix_type);
1294
/* end of file ==============================================================*/