2
* Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
3
* Copyright(c) 1995-99 Andrew Lister
5
* Permission to use, copy, modify and distribute this material for
6
* any purpose and without fee is hereby granted, provided that the
7
* above copyright notice and this permission notice appear in all
8
* copies, and that the name of Bellcore not be used in advertising
9
* or publicity pertaining to this material without the specific,
10
* prior written permission of an authorized representative of
13
* BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
14
* PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
15
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
* FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
17
* FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE
18
* SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
19
* ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
20
* LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
21
* ING TO THE SOFTWARE.
41
static void xbaeDrawCellString P((XbaeMatrixWidget, int, int, int, int,
42
String, Pixel, Pixel));
44
static void xbaeDrawCellWidget P((XbaeMatrixWidget, int, int, int, int,
45
Widget, Pixel, Pixel));
47
static void xbaeDrawCellPixmap P((XbaeMatrixWidget, int, int, int, int,
48
Pixmap, Pixmap, int, int, Pixel,
52
* Draw a fixed or non-fixed cell. The coordinates are calculated relative
53
* to the correct window and pixmap is copied to that window.
56
xbaeDrawCellPixmap(mw, row, column, x, y, pixmap, mask, width, height, bg,
71
int src_x = 0, src_y, dest_x, dest_y;
72
int copy_width, copy_height;
73
int cell_height = ROW_HEIGHT(mw);
74
int cell_width = COLUMN_WIDTH(mw, column);
76
unsigned char alignment = mw->matrix.column_alignments ?
77
mw->matrix.column_alignments[column] : XmALIGNMENT_BEGINNING;
78
Display *display = XtDisplay(mw);
80
Window win = xbaeGetCellWindow(mw, &w, row, column);
86
* Convert the row/column to the coordinates relative to the correct
89
dest_x = x + TEXT_WIDTH_OFFSET(mw);
91
gc = mw->matrix.pixmap_gc;
93
XSetForeground(display, gc, bg);
97
* If we are only changing the highlighting of a cell, we don't need
98
* to do anything other than draw (or undraw) the highlight
100
if (mw->matrix.highlighted_cells &&
101
mw->matrix.highlight_location != HighlightNone)
103
xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, cell_width,
104
cell_height, mw->matrix.highlight_location);
109
XFillRectangle(display, win, gc, x, y,
110
COLUMN_WIDTH(mw, column), ROW_HEIGHT(mw));
112
XSetForeground(display, gc, fg);
113
XSetBackground(display, gc, bg);
116
* Adjust the x and y drawing destinations as appropriate. First the
120
if (height > cell_height)
122
/* Adjust the starting location in the src image */
123
src_y = (height - cell_height) / 2;
124
copy_height = cell_height;
128
/* Adjust the destination point */
130
dest_y += ((cell_height - height) / 2);
131
copy_height = height;
135
* Adjust the x value, paying attention to the columnAlignment
137
if (width > cell_width)
138
copy_width = cell_width;
144
case XmALIGNMENT_BEGINNING:
147
case XmALIGNMENT_CENTER:
148
if (width > cell_width)
149
src_x = (width - cell_width) / 2;
153
dest_x += ((cell_width - width) / 2);
156
case XmALIGNMENT_END:
157
if (width > cell_width)
158
src_x = width - cell_width;
162
dest_x = x + COLUMN_WIDTH(mw, column) - TEXT_WIDTH_OFFSET(mw) -
169
* Draw the pixmap. Clip it, if necessary
173
if (depth > 1) /* A pixmap using xpm */
177
XSetClipMask(display, gc, mask);
179
XSetClipOrigin(display, gc, dest_x - src_x, dest_y - src_y);
181
XCopyArea(display, pixmap, win, gc, src_x, src_y, copy_width,
182
copy_height, dest_x, dest_y);
184
XSetClipMask(display, gc, None);
186
else /* A plain old bitmap */
187
XCopyPlane(display, pixmap, win, gc, src_x, src_y, copy_width,
188
copy_height, dest_x, dest_y, 1L);
192
* If we need to fill the rest of the space, do so
194
if (IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw) &&
195
(row == (mw->matrix.rows - 1)))
198
int fill_width, fill_height;
200
* Need to check the actual window we are drawing on to ensure
203
xbaeCalcVertFill(mw, win, x, y, row, column, &ax, &ay,
204
&fill_width, &fill_height);
205
XFillRectangle(XtDisplay(mw), XtWindow(mw), gc,
206
ax, ay, fill_width, fill_height);
208
else if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw) &&
209
(column == (mw->matrix.columns - 1)))
212
int fill_width, fill_height;
214
xbaeCalcHorizFill(mw, win, x, y, row, column, &ax, &ay,
215
&fill_width, &fill_height);
216
XFillRectangle(XtDisplay(mw), XtWindow(mw), gc,
217
ax, ay, fill_width, fill_height);
220
#if XmVersion >= 1002
221
if (mw->matrix.highlighted_cells &&
222
mw->matrix.highlighted_cells[row][column])
224
xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, cell_width,
225
cell_height, HIGHLIGHTING_SOMETHING);
228
xbaeDrawCellShadow(mw, win, row, column, x, y, cell_width,
229
cell_height, False, False, False);
233
* Draw a fixed or non-fixed cell. The coordinates are calculated relative
234
* to the correct window and the cell is drawn in that window.
237
xbaeDrawCellString(XbaeMatrixWidget mw, int row, int column, int x, int y, String string, Pixel bg, Pixel fg)
241
Window win = xbaeGetCellWindow(mw, &w, row, column);
242
Dimension column_width = COLUMN_WIDTH(mw, column);
243
Dimension row_height = ROW_HEIGHT(mw);
244
Dimension width = column_width;
245
Dimension height = row_height;
246
Boolean selected = mw->matrix.selected_cells ?
247
mw->matrix.selected_cells[row][column] : False;
255
* Probably not needed - time will tell! If anybody gets a segv on
256
* ignoring this code, be sure to let me know - AL 11/96
258
* Make sure y coordinate is valid
260
if ((win == XtWindow(mw)) &&
261
((y > (CLIP_VERT_VISIBLE_SPACE(mw) + ROW_LABEL_OFFSET(mw) - 1)) ||
262
(y < ROW_LABEL_OFFSET(mw))))
265
gc = mw->matrix.draw_gc;
266
XSetForeground(XtDisplay(mw), gc, bg);
269
* If we are only changing the highlighting of a cell, we don't need
270
* to do anything other than draw (or undraw) the highlight
272
if (mw->matrix.highlighted_cells &&
273
mw->matrix.highlight_location != HighlightNone)
275
xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, width, height,
276
mw->matrix.highlight_location);
281
* Fill the cell's background if it can be done
282
* without duplicating work below
284
if ((XtWindow(mw) != win) ||
285
(!(IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw) &&
286
((mw->matrix.rows - 1) == row)) &&
287
!(IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw) &&
288
((mw->matrix.columns - 1) == column))))
289
XFillRectangle(XtDisplay(mw), win, gc, x, y,
290
column_width, row_height);
293
* If we need to fill the rest of the space, do so
295
if (IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw) &&
296
((mw->matrix.rows - 1) == row))
299
int fill_width, fill_height;
301
* Need to check the actual window we are drawing on to ensure
304
xbaeCalcVertFill(mw, win, x, y, row, column, &ax, &ay,
305
&fill_width, &fill_height);
306
XFillRectangle(XtDisplay(mw), XtWindow(mw), gc,
307
ax, ay, fill_width, fill_height);
309
else if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw) &&
310
(column == (mw->matrix.columns - 1)))
313
int fill_width, fill_height;
315
xbaeCalcHorizFill(mw, win, x, y, row, column, &ax, &ay,
316
&fill_width, &fill_height);
317
XFillRectangle(XtDisplay(mw), XtWindow(mw), gc,
318
ax, ay, fill_width, fill_height);
322
* Draw the string in the cell.
324
xbaeDrawString(mw, win, gc, str, strlen(str),
325
x + TEXT_X_OFFSET(mw), y + TEXT_Y_OFFSET(mw),
326
mw->matrix.column_widths[column],
327
mw->matrix.column_alignments ?
328
mw->matrix.column_alignments[column] :
329
XmALIGNMENT_BEGINNING, selected,
330
False, False, False, fg);
332
#if XmVersion >= 1002
333
if (mw->matrix.highlighted_cells &&
334
mw->matrix.highlighted_cells[row][column])
336
xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, width, height,
337
HIGHLIGHTING_SOMETHING);
341
xbaeDrawCellShadow(mw, win, row, column, x, y, COLUMN_WIDTH(mw, column),
342
ROW_HEIGHT(mw), False, False, False);
346
* Draw a user defined widget in the cell
349
xbaeDrawCellWidget(mw, row, column, x, y, widget, bg, fg)
358
Window win = xbaeGetCellWindow(mw, &w, row, column);
363
gc = mw->matrix.draw_gc;
364
XSetForeground(XtDisplay(mw), gc, bg);
365
XFillRectangle(XtDisplay(mw), win, gc, x, y,
366
COLUMN_WIDTH(mw, column), ROW_HEIGHT(mw));
369
* Draw the widget in the cell.
372
x + mw->matrix.cell_shadow_thickness +
373
mw->matrix.cell_highlight_thickness,
374
y + mw->matrix.cell_shadow_thickness +
375
mw->matrix.cell_highlight_thickness);
377
xbaeDrawCellShadow(mw, win, row, column, x, y, COLUMN_WIDTH(mw, column),
378
ROW_HEIGHT(mw), False, clipped, False);
383
* Width in pixels of a character in a given font
385
#define charWidth(fs,c) ((fs)->per_char ? \
386
(fs)->per_char[((c) < (fs)->min_char_or_byte2 ? \
387
(fs)->default_char : \
389
(fs)->min_char_or_byte2)].width : \
390
(fs)->min_bounds.width)
394
* Draw a string with specified attributes. We want to avoid having to
395
* use a GC clip_mask, so we clip by characters. This complicates the code.
398
#if NeedFunctionPrototypes
399
xbaeDrawString(XbaeMatrixWidget mw, Window win, GC gc, String string,
400
int length, int x, int y, int maxlen, unsigned char alignment,
401
Boolean highlight, Boolean bold, Boolean rowLabel,
402
Boolean colLabel, Pixel color)
404
xbaeDrawString(mw, win, gc, string, length, x, y, maxlen, alignment,
405
highlight, bold, rowLabel, colLabel, color)
414
unsigned char alignment;
422
int start, width, maxwidth;
423
XFontStruct *font_struct;
425
Boolean choppedStart = False;
426
Boolean choppedEnd = False;
427
XRectangle *ink_array = NULL;
428
XRectangle *logical_array = NULL;
430
XRectangle overall_logical;
432
if (rowLabel || colLabel)
434
font_struct = mw->matrix.label_font_struct;
435
font_set = mw->matrix.label_font_set;
439
font_struct = mw->matrix.font_struct;
440
font_set = mw->matrix.font_set;
443
* Initialize starting character in string
448
maxwidth = maxlen * FONT_WIDTH(mw);
450
maxwidth = maxlen * LABEL_WIDTH(mw);
454
ink_array = (XRectangle*)XtMalloc(length * sizeof(XRectangle));
455
logical_array = (XRectangle*)XtMalloc(length * sizeof(XRectangle));
457
XmbTextPerCharExtents(font_set, string, length,
458
ink_array, logical_array, length, &num_chars,
459
NULL, &overall_logical);
462
* If the width of the string is greater than the width of this cell,
463
* we need to clip. We don't want to use the server to clip because
464
* it is slow, so we truncate characters if we exceed a cells pixel
467
if (overall_logical.width > maxwidth)
472
case XmALIGNMENT_CENTER:
480
* If we are going to draw arrows at both ends, allow for them.
482
if (mw->matrix.show_arrows)
484
maxwidth -= 2 * mw->matrix.font_width;
490
* Find limits of cell relative to the origin of the string.
492
startx = overall_logical.x + overall_logical.width / 2 -
494
endx = startx + maxwidth - 1;
497
* Find the first character which fits into the cell.
499
for (i = 0; i < num_chars && logical_array[i].x < startx; ++i)
501
int cl = mblen(string + start, length);
507
* Find the last character which fits into the cell.
508
* At this point length represents the number of bytes
509
* between the end of the cell and the end of the full
510
* string. Note that the scan continues from above.
512
for (end = start; i < num_chars && (logical_array[i].x +
513
logical_array[i].width) <
516
int cl = mblen(string + end, length);
522
* Now reset length so that it represents the number of bytes
525
length = end - start;
530
case XmALIGNMENT_END:
536
* We are going to an draw arrow at the end, allow for it.
538
if (mw->matrix.show_arrows)
540
maxwidth -= mw->matrix.font_width;
545
* Find limits of cell relative to the origin of the string.
547
startx = overall_logical.x + overall_logical.width - maxwidth;
550
* Find the first character which fits into the cell.
552
for (i = 0; i < num_chars && logical_array[i].x < startx; ++i)
554
int cl = mblen(string + start, length);
562
case XmALIGNMENT_BEGINNING:
570
* We are going to an draw arrow at the start, allow for it.
572
if (mw->matrix.show_arrows)
574
maxwidth -= mw->matrix.font_width;
579
* Find limits of cell relative to the origin of the string.
581
endx = overall_logical.x + maxwidth - 1;
584
* Find the last character which fits into the cell.
585
* At this point length represents the number of bytes
586
* between the end of the cell and the end of the full
589
for (i = 0, end = start;
590
i < num_chars && (logical_array[i].x +
591
logical_array[i].width) < endx; ++i)
593
int cl = mblen(string + end, length);
600
* Now reset length so that it represents the number of bytes
603
length = end - start;
610
* Having truncated string recalculate extents to find origin
612
XmbTextPerCharExtents(font_set, string, length,
613
ink_array, logical_array, length, &num_chars,
614
NULL, &overall_logical);
617
* We fit inside our cell, so just compute the x of the start of
625
case XmALIGNMENT_CENTER:
626
x += maxwidth / 2 - overall_logical.width / 2;
629
case XmALIGNMENT_END:
630
x += maxwidth - overall_logical.width;
633
case XmALIGNMENT_BEGINNING:
643
* Don't worry, XSetForeground is smart about avoiding unnecessary
646
XSetForeground(XtDisplay(mw), gc, color);
648
if (mw->matrix.show_arrows && choppedStart)
651
points[ 0 ].x = points[ 1 ].x = x + mw->matrix.font_width;
652
points[ 0 ].y = y + mw->matrix.font_y;
653
points[ 1 ].y = y + mw->matrix.font_y + mw->matrix.font_height;
655
points[ 2 ].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
657
XFillPolygon(XtDisplay(mw), win, gc, points, 3,
658
Convex, CoordModeOrigin);
660
/* Offset the start point so as to not draw on the triangle */
664
if (mw->matrix.show_arrows && choppedEnd)
667
points[ 0 ].x = points[ 1 ].x = x + overall_logical.width;
668
points[ 0 ].y = y + mw->matrix.font_y;
669
points[ 1 ].y = y + mw->matrix.font_y + mw->matrix.font_height;
670
points[ 2 ].x = x + overall_logical.width + mw->matrix.font_width;
671
points[ 2 ].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
673
XFillPolygon(XtDisplay(mw), win, gc, points, 3,
674
Convex, CoordModeOrigin);
678
* Adjust x for origin of string.
680
x -= overall_logical.x;
683
* Now draw the string at x starting at char 'start' and of
686
XmbDrawString(XtDisplay(mw), win, font_set, gc, x, y, &string[start],
690
* If bold is on, draw the string again offset by 1 pixel (overstrike)
693
XmbDrawString(XtDisplay(mw), win, font_set, gc, x - 1, y,
694
&string[start], length);
696
XtFree((char*)ink_array);
698
XtFree((char*)logical_array);
702
width = XTextWidth(font_struct, string, length);
705
* If the width of the string is greater than the width of this cell,
706
* we need to clip. We don't want to use the server to clip because
707
* it is slow, so we truncate characters if we exceed a cells pixel
710
if (width > maxwidth)
715
case XmALIGNMENT_CENTER:
718
int endx = x + maxwidth - 1;
722
* Figure out our x for the centered string. Then loop
723
* and chop characters off the front until we are within
726
* Adjust x, the starting character and the length of the
727
* string for each char.
729
x += maxwidth / 2 - width / 2;
732
int cw = charWidth(font_struct,
733
(unsigned char)string[start]);
743
* Now figure out the end x of the string. Then loop and chop
744
* characters off the end until we are within the cell.
746
newendx = x + width - 1;
747
while (newendx > endx && *(string + start))
749
int cw = charWidth(font_struct,
750
(unsigned char)string[start]);
761
case XmALIGNMENT_END:
765
* Figure out our x for the right justified string.
766
* Then loop and chop characters off the front until we fit.
767
* Adjust x for each char lopped off. Also adjust the starting
768
* character and length of the string for each char.
770
x += maxwidth - width;
771
while (width > maxwidth)
773
int cw = charWidth(font_struct,
774
(unsigned char)string[start]);
785
case XmALIGNMENT_BEGINNING:
788
* Leave x alone, but chop characters off the end until we fit
790
while (width > maxwidth)
792
width -= charWidth(font_struct,
793
(unsigned char)string[length - 1]);
802
* We fit inside our cell, so just compute the x of the start of
810
case XmALIGNMENT_CENTER:
811
x += maxwidth / 2 - width / 2;
814
case XmALIGNMENT_END:
815
x += maxwidth - width;
818
case XmALIGNMENT_BEGINNING:
828
* Don't worry, XSetForeground is smart about avoiding unnecessary
831
XSetForeground(XtDisplay(mw), gc, color);
833
if (mw->matrix.show_arrows && choppedEnd)
836
points[0].x = points[1].x = x + width - mw->matrix.font_width;
837
points[0].y = y + mw->matrix.font_y;
838
points[1].y = y + mw->matrix.font_y + mw->matrix.font_height;
839
points[2].x = x + width;
840
points[2].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
842
XFillPolygon(XtDisplay(mw), win, gc, points, 3,
843
Convex, CoordModeOrigin);
845
/* Reduce the length to allow for our foreign character */
848
if (mw->matrix.show_arrows && choppedStart)
851
points[0].x = points[1].x = x + mw->matrix.font_width;
852
points[0].y = y + mw->matrix.font_y;
853
points[1].y = y + mw->matrix.font_y + mw->matrix.font_height;
855
points[2].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
857
XFillPolygon(XtDisplay(mw), win, gc, points, 3,
858
Convex, CoordModeOrigin);
860
/* Offset the start point so as to not draw on the triangle */
861
x += mw->matrix.font_width;
867
* Now draw the string at x starting at char 'start' and of length
871
if (TWO_BYTE_FONT(mw))
872
XDrawString16(XtDisplay(mw), win, gc, x, y, &string[start],
876
XDrawString(XtDisplay(mw), win, gc, x, y, &string[start], length);
879
* If bold is on, draw the string again offset by 1 pixel (overstrike)
883
if (TWO_BYTE_FONT(mw))
884
XDrawString16(XtDisplay(mw), win, gc, x - 1, y,
885
&string[start], length);
888
XDrawString(XtDisplay(mw), win, gc, x - 1, y,
889
&string[start], length);
894
xbaeComputeCellColors(mw, row, column, fg, bg)
899
Boolean alt = mw->matrix.alt_row_count ?
900
(row / mw->matrix.alt_row_count) % 2 : False;
903
* Compute the background and foreground colours of the cell
905
if (mw->matrix.selected_cells && mw->matrix.selected_cells[row][column]) {
906
if (mw->matrix.reverse_select) {
907
if (mw->matrix.colors)
908
*bg = mw->matrix.colors[row][column];
910
*bg = mw->manager.foreground;
913
*bg = mw->matrix.selected_background;
915
else if (mw->matrix.cell_background &&
916
mw->matrix.cell_background[row][column] !=
917
mw->core.background_pixel) {
918
*bg = mw->matrix.cell_background[row][column];
922
*bg = mw->matrix.odd_row_background;
924
*bg = mw->matrix.even_row_background;
927
if (mw->matrix.selected_cells && mw->matrix.selected_cells[row][column]) {
928
if (mw->matrix.reverse_select) {
929
if (mw->matrix.cell_background)
930
*fg = mw->matrix.cell_background[row][column];
932
*fg = mw->core.background_pixel;
935
*fg = mw->matrix.selected_foreground;
937
else if (mw->matrix.colors)
938
*fg = mw->matrix.colors[row][column];
940
*fg = mw->manager.foreground;
944
xbaeDrawCell(mw, row, column)
952
if (mw->matrix.disable_redisplay || mw->matrix.rows == 0 ||
953
mw->matrix.columns == 0)
957
* Convert the row/column to the coordinates relative to the correct
960
xbaeRowColToXY(mw, row, column, &x, &y);
962
xbaeComputeCellColors(mw, row, column, &fg, &bg);
965
if (mw->matrix.cell_widgets[row][column])
966
xbaeDrawCellWidget(mw, row, column, x, y,
967
mw->matrix.cell_widgets[row][column], bg, fg);
971
if (!mw->matrix.draw_cell_callback)
973
if (row < mw->matrix.rows && column < mw->matrix.columns)
975
if (mw->matrix.cells && mw->matrix.cells[row])
976
string = mw->matrix.cells[row][column];
980
xbaeDrawCellString(mw, row, column, x, y, string, bg, fg);
991
if (row < mw->matrix.rows && column < mw->matrix.columns)
993
type = xbaeGetDrawCellValue(mw, row, column, &string, &pixmap,
994
&mask, &width, &height, &bg, &fg,
996
if (type == XbaeString)
997
xbaeDrawCellString(mw, row, column, x, y, string, bg, fg);
998
else if (type == XbaePixmap)
999
xbaeDrawCellPixmap(mw, row, column, x, y, pixmap, mask,
1000
width, height, bg, fg, depth);
1006
xbaeGetDrawCellValue(mw, row, column, string, pixmap, mask, width,
1007
height, bg, fg, depth)
1008
XbaeMatrixWidget mw;
1014
int *width, *height;
1018
XbaeMatrixDrawCellCallbackStruct call_data;
1020
call_data.reason = XbaeDrawCellReason;
1021
call_data.event = (XEvent *)NULL;
1022
call_data.row = row;
1023
call_data.column = column;
1024
call_data.width = COLUMN_WIDTH(mw, column) - TEXT_WIDTH_OFFSET(mw) * 2;
1025
call_data.height = ROW_HEIGHT(mw) - TEXT_HEIGHT_OFFSET(mw) * 2;
1026
call_data.type = XbaeString;
1027
call_data.string = "";
1028
call_data.pixmap = (Pixmap)NULL;
1029
call_data.mask = (Pixmap)NULL;
1030
call_data.foreground = *fg;
1031
call_data.background = *bg;
1032
call_data.depth = 0;
1034
XtCallCallbackList((Widget)mw, mw->matrix.draw_cell_callback,
1035
(XtPointer) &call_data);
1037
*pixmap = call_data.pixmap;
1038
*mask = call_data.mask;
1039
*string = call_data.string ? call_data.string : ""; /* Handle NULLs */
1041
if (mw->matrix.reverse_select && mw->matrix.selected_cells &&
1042
mw->matrix.selected_cells[row][column])
1045
* if colours were set by the draw cell callback, handle reverse
1048
if (*bg != call_data.background)
1050
if (*fg != call_data.foreground)
1051
*bg = call_data.foreground;
1052
*fg = call_data.background;
1054
else if (*fg != call_data.foreground)
1055
*bg = call_data.foreground;
1059
*fg = call_data.foreground;
1060
*bg = call_data.background;
1062
*width = call_data.width;
1063
*height = call_data.height;
1064
*depth = call_data.depth;
1066
if (call_data.type == XbaePixmap)
1068
if (*mask == XmUNSPECIFIED_PIXMAP || *mask == BadPixmap)
1071
if (*pixmap == XmUNSPECIFIED_PIXMAP || *pixmap == BadPixmap)
1074
XtWidgetToApplicationContext((Widget)mw),
1075
"drawCellCallback", "Pixmap", "XbaeMatrix",
1076
"XbaeMatrix: Bad pixmap passed from drawCellCallback",
1078
call_data.type = XbaeString;
1084
* If we know the depth, width and height don't do a round
1089
int x_return, y_return;
1090
unsigned int width_return, height_return;
1091
unsigned int border_width_return;
1092
unsigned int depth_return;
1094
if (XGetGeometry(XtDisplay(mw), *pixmap, &root_return,
1095
&x_return, &y_return, &width_return,
1096
&height_return, &border_width_return,
1099
*width = width_return;
1100
*height = height_return;
1101
*depth = depth_return;
1105
return (call_data.type);
1109
* Draw the column label for the specified column. Handles labels in
1110
* fixed and non-fixed columns.
1113
#if NeedFunctionPrototypes
1114
xbaeDrawColumnLabel(XbaeMatrixWidget mw, int column, Boolean pressed)
1116
xbaeDrawColumnLabel(mw, column, pressed)
1117
XbaeMatrixWidget mw;
1127
Window win = XtWindow(mw);
1128
Boolean clipped = (column >= (int)mw->matrix.fixed_columns &&
1129
column < TRAILING_HORIZ_ORIGIN(mw));
1131
Boolean button = mw->matrix.button_labels ||
1132
(mw->matrix.column_button_labels &&
1133
mw->matrix.column_button_labels[column]);
1135
if (mw->matrix.column_labels[column][0] == '\0' && !button)
1139
* If the column label is in a fixed column, we don't need to account
1140
* for the horiz_origin
1142
if (column < (int)mw->matrix.fixed_columns)
1144
labelX = COLUMN_LABEL_OFFSET(mw) + COLUMN_POSITION(mw, column) +
1146
buttonX = COLUMN_LABEL_OFFSET(mw) + COLUMN_POSITION(mw, column);
1148
else if (column >= TRAILING_HORIZ_ORIGIN(mw))
1150
labelX = TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw) +
1151
COLUMN_POSITION(mw, column) -
1152
COLUMN_POSITION(mw, TRAILING_HORIZ_ORIGIN(mw)) +
1154
buttonX = TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw) +
1155
COLUMN_POSITION(mw, column) -
1156
COLUMN_POSITION(mw, TRAILING_HORIZ_ORIGIN(mw));
1160
labelX = COLUMN_LABEL_OFFSET(mw) +
1161
(COLUMN_POSITION(mw, column) - HORIZ_ORIGIN(mw)) +
1163
buttonX = COLUMN_LABEL_OFFSET(mw) + (COLUMN_POSITION(mw, column) -
1168
* Set our y to the baseline of the first line in this column
1170
labelY = -mw->matrix.label_font_y +
1171
mw->matrix.cell_shadow_thickness +
1172
mw->matrix.cell_highlight_thickness +
1173
mw->matrix.cell_margin_height +
1174
mw->matrix.text_shadow_thickness +
1175
(mw->matrix.column_label_maxlines -
1176
mw->matrix.column_label_lines[column].lines) * LABEL_HEIGHT(mw) +
1177
HORIZ_SB_OFFSET(mw);
1180
gc = mw->matrix.label_clip_gc;
1182
gc = mw->matrix.label_gc;
1186
XSetForeground(XtDisplay(mw), gc, mw->matrix.button_label_background);
1187
XFillRectangle(XtDisplay(mw), win, gc, buttonX, HORIZ_SB_OFFSET(mw),
1188
COLUMN_WIDTH(mw, column), COLUMN_LABEL_HEIGHT(mw));
1191
XSetForeground(XtDisplay(mw), gc, mw->matrix.column_label_color);
1192
XSetBackground(XtDisplay(mw), gc, mw->matrix.button_label_background);
1194
label = mw->matrix.column_labels[column];
1196
if (label[0] != '\0')
1197
for (i = 0; i < mw->matrix.column_label_lines[column].lines; i++)
1199
xbaeDrawString(mw, XtWindow(mw), gc, label,
1200
mw->matrix.column_label_lines[column].lengths[i],
1201
labelX, labelY, mw->matrix.column_widths[column],
1202
mw->matrix.column_label_alignments ?
1203
mw->matrix.column_label_alignments[column] :
1204
XmALIGNMENT_BEGINNING, False,
1205
mw->matrix.bold_labels, False, True,
1206
mw->matrix.column_label_color);
1208
labelY += LABEL_HEIGHT(mw);
1209
label += mw->matrix.column_label_lines[column].lengths[i] + 1;
1212
xbaeDrawCellShadow(mw, XtWindow(mw), -1, column,
1213
buttonX, HORIZ_SB_OFFSET(mw),
1214
COLUMN_WIDTH(mw, column),
1215
COLUMN_LABEL_HEIGHT(mw), True, clipped, pressed);
1219
* Draw the row label for the specified row. Handles labels in fixed and
1223
#if NeedFunctionPrototypes
1224
xbaeDrawRowLabel(XbaeMatrixWidget mw, int row, Boolean pressed)
1226
xbaeDrawRowLabel(mw, row, pressed)
1227
XbaeMatrixWidget mw;
1234
Window win = XtWindow(mw);
1235
Boolean clipped = (row >= (int)mw->matrix.fixed_rows &&
1236
row < TRAILING_VERT_ORIGIN(mw));
1238
Boolean button = mw->matrix.button_labels ||
1239
(mw->matrix.row_button_labels && mw->matrix.row_button_labels[row]);
1241
if (mw->matrix.row_labels[row][0] == '\0' && !button)
1245
* If the row label is in a fixed row we don't need to account
1246
* for the vert_origin
1248
if (row < (int)mw->matrix.fixed_rows)
1249
y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * row + TEXT_Y_OFFSET(mw);
1250
else if (row >= TRAILING_VERT_ORIGIN(mw))
1251
y = TRAILING_FIXED_ROW_LABEL_OFFSET(mw) +
1252
ROW_HEIGHT(mw) * (row - TRAILING_VERT_ORIGIN(mw)) +
1255
y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * (row - VERT_ORIGIN(mw)) +
1256
LABEL_Y_OFFSET(mw) - mw->matrix.first_row_offset;
1259
gc = mw->matrix.label_clip_gc;
1261
gc = mw->matrix.label_gc;
1265
XSetForeground(XtDisplay(mw), gc, mw->matrix.button_label_background);
1266
XFillRectangle(XtDisplay(mw), win, gc, VERT_SB_OFFSET(mw),
1267
y - TEXT_Y_OFFSET(mw), ROW_LABEL_WIDTH(mw),
1271
XSetForeground(XtDisplay(mw), gc, mw->matrix.row_label_color);
1272
XSetBackground(XtDisplay(mw), gc, mw->matrix.button_label_background);
1274
if (mw->matrix.row_labels[row][0] != '\0')
1275
xbaeDrawString(mw, win, gc,
1276
mw->matrix.row_labels[row],
1277
strlen(mw->matrix.row_labels[row]),
1278
TEXT_X_OFFSET(mw) + VERT_SB_OFFSET(mw), y,
1279
mw->matrix.row_label_width,
1280
mw->matrix.row_label_alignment, False,
1281
mw->matrix.bold_labels, True, False,
1282
mw->matrix.row_label_color);
1285
xbaeDrawCellShadow(mw, win, row, -1, VERT_SB_OFFSET(mw),
1286
y - TEXT_Y_OFFSET(mw), ROW_LABEL_WIDTH(mw),
1287
ROW_HEIGHT(mw), True, clipped, pressed);