~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qmon/Xbae/Draw.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
 
3
 * Copyright(c) 1995-99 Andrew Lister
 
4
 *                        All rights reserved
 
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
 
11
 * Bellcore.
 
12
 *
 
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.
 
22
 *
 
23
 * $Id$
 
24
 */
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#include <config.h>
 
28
#endif
 
29
 
 
30
#include <Xm/Xm.h>
 
31
#include <Xm/XmP.h>
 
32
#if XmVersion > 1001
 
33
#include <Xm/DrawP.h>
 
34
#endif
 
35
#include "MatrixP.h"
 
36
#include "Utils.h"
 
37
#include "Shadow.h"
 
38
#include "Draw.h"
 
39
#include <stdlib.h>
 
40
 
 
41
static void xbaeDrawCellString P((XbaeMatrixWidget, int, int, int, int,
 
42
                                  String, Pixel, Pixel));
 
43
#if CELL_WIDGETS
 
44
static void xbaeDrawCellWidget P((XbaeMatrixWidget, int, int, int, int,
 
45
                                  Widget, Pixel, Pixel));
 
46
#endif
 
47
static void xbaeDrawCellPixmap P((XbaeMatrixWidget, int, int, int, int,
 
48
                                  Pixmap, Pixmap, int, int, Pixel,
 
49
                                  Pixel, int));
 
50
 
 
51
/*
 
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.
 
54
 */
 
55
static void
 
56
xbaeDrawCellPixmap(mw, row, column, x, y, pixmap, mask, width, height, bg,
 
57
                   fg, depth)
 
58
XbaeMatrixWidget mw;
 
59
int row;
 
60
int column;
 
61
int x;
 
62
int y;
 
63
Pixmap pixmap;
 
64
Pixmap mask;
 
65
int width;
 
66
int height;
 
67
Pixel bg;
 
68
Pixel fg;
 
69
int depth;
 
70
{
 
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);
 
75
    Widget w;
 
76
    unsigned char alignment = mw->matrix.column_alignments ?
 
77
        mw->matrix.column_alignments[column] : XmALIGNMENT_BEGINNING;
 
78
    Display *display = XtDisplay(mw);
 
79
    GC gc;
 
80
    Window win = xbaeGetCellWindow(mw, &w, row, column);
 
81
 
 
82
    if (!win)
 
83
        return;
 
84
 
 
85
    /*
 
86
     * Convert the row/column to the coordinates relative to the correct
 
87
     * window
 
88
     */
 
89
    dest_x = x + TEXT_WIDTH_OFFSET(mw);
 
90
 
 
91
    gc = mw->matrix.pixmap_gc;
 
92
 
 
93
    XSetForeground(display, gc, bg);
 
94
 
 
95
#if XmVersion >= 1002
 
96
    /*
 
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
 
99
     */
 
100
    if (mw->matrix.highlighted_cells &&
 
101
        mw->matrix.highlight_location != HighlightNone)
 
102
    {
 
103
        xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, cell_width,
 
104
                              cell_height, mw->matrix.highlight_location);
 
105
        return;
 
106
    }
 
107
#endif
 
108
 
 
109
    XFillRectangle(display, win, gc, x, y,
 
110
                   COLUMN_WIDTH(mw, column), ROW_HEIGHT(mw));
 
111
 
 
112
    XSetForeground(display, gc, fg);
 
113
    XSetBackground(display, gc, bg);
 
114
 
 
115
    /*
 
116
     * Adjust the x and y drawing destinations as appropriate.  First the
 
117
     * y value....
 
118
     */
 
119
    dest_y = y;
 
120
    if (height > cell_height)
 
121
    {
 
122
        /* Adjust the starting location in the src image */
 
123
        src_y = (height - cell_height) / 2;
 
124
        copy_height = cell_height;
 
125
    }
 
126
    else
 
127
    {
 
128
        /* Adjust the destination point */
 
129
        src_y = 0;
 
130
        dest_y += ((cell_height - height) / 2);
 
131
        copy_height = height;
 
132
    }
 
133
 
 
134
    /*
 
135
     * Adjust the x value, paying attention to the columnAlignment
 
136
     */
 
137
    if (width > cell_width)
 
138
        copy_width = cell_width;
 
139
    else
 
140
        copy_width = width;
 
141
    
 
142
    switch (alignment)
 
143
    {
 
144
    case XmALIGNMENT_BEGINNING:
 
145
        src_x = 0;
 
146
        break;
 
147
    case XmALIGNMENT_CENTER:
 
148
        if (width > cell_width)
 
149
            src_x = (width - cell_width) / 2;
 
150
        else
 
151
        {
 
152
            src_x = 0;
 
153
            dest_x += ((cell_width - width) / 2);
 
154
        }
 
155
        break;
 
156
    case XmALIGNMENT_END:        
 
157
        if (width > cell_width)
 
158
            src_x = width - cell_width;
 
159
        else
 
160
        {
 
161
            src_x = 0;
 
162
            dest_x = x + COLUMN_WIDTH(mw, column) - TEXT_WIDTH_OFFSET(mw) -
 
163
                width;
 
164
        }
 
165
        break;
 
166
    }
 
167
 
 
168
    /*
 
169
     * Draw the pixmap.  Clip it, if necessary
 
170
     */
 
171
    if (pixmap)
 
172
    {
 
173
        if (depth > 1)                /* A pixmap using xpm */
 
174
        {
 
175
            if (mask)
 
176
            {
 
177
                XSetClipMask(display, gc, mask);
 
178
 
 
179
                XSetClipOrigin(display, gc, dest_x - src_x, dest_y - src_y);
 
180
            }
 
181
            XCopyArea(display, pixmap, win, gc, src_x, src_y, copy_width,
 
182
                      copy_height, dest_x, dest_y);
 
183
            if (mask)
 
184
                XSetClipMask(display, gc, None);
 
185
        }
 
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);
 
189
    }
 
190
    
 
191
    /*
 
192
     * If we need to fill the rest of the space, do so
 
193
     */
 
194
    if (IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw) &&
 
195
        (row == (mw->matrix.rows - 1)))
 
196
    {
 
197
        int ax, ay;
 
198
        int fill_width, fill_height;
 
199
        /*
 
200
         * Need to check the actual window we are drawing on to ensure
 
201
         * the correct visual
 
202
         */
 
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);
 
207
    }
 
208
    else if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw) &&
 
209
            (column == (mw->matrix.columns - 1)))
 
210
    {
 
211
        int ax, ay;
 
212
        int fill_width, fill_height;
 
213
 
 
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);
 
218
    }
 
219
 
 
220
#if XmVersion >= 1002
 
221
    if (mw->matrix.highlighted_cells &&
 
222
        mw->matrix.highlighted_cells[row][column])
 
223
    {
 
224
        xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, cell_width,
 
225
                              cell_height, HIGHLIGHTING_SOMETHING);
 
226
    }
 
227
#endif
 
228
    xbaeDrawCellShadow(mw, win, row, column, x, y, cell_width,
 
229
                       cell_height, False, False, False);
 
230
}
 
231
 
 
232
/*
 
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.
 
235
 */
 
236
static void
 
237
xbaeDrawCellString(XbaeMatrixWidget mw, int row, int column, int x, int y, String string, Pixel bg, Pixel fg)
 
238
{
 
239
    GC gc;
 
240
    Widget w;
 
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;
 
248
    String str = string;
 
249
    
 
250
    if (!win)
 
251
        return;
 
252
 
 
253
#if 0
 
254
    /*
 
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
 
257
     *
 
258
     * Make sure y coordinate is valid 
 
259
     */
 
260
    if ((win == XtWindow(mw)) &&
 
261
        ((y > (CLIP_VERT_VISIBLE_SPACE(mw) + ROW_LABEL_OFFSET(mw) - 1)) ||
 
262
         (y < ROW_LABEL_OFFSET(mw))))
 
263
        return;
 
264
#endif
 
265
    gc = mw->matrix.draw_gc;
 
266
    XSetForeground(XtDisplay(mw), gc, bg);
 
267
 
 
268
    /*
 
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
 
271
     */
 
272
    if (mw->matrix.highlighted_cells &&
 
273
        mw->matrix.highlight_location != HighlightNone)
 
274
    {
 
275
        xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, width, height,
 
276
                              mw->matrix.highlight_location);
 
277
        return;
 
278
    }
 
279
 
 
280
    /*
 
281
     * Fill the cell's background if it can be done
 
282
     * without duplicating work below
 
283
     */
 
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);
 
291
 
 
292
    /*
 
293
     * If we need to fill the rest of the space, do so
 
294
     */
 
295
    if (IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw) &&
 
296
        ((mw->matrix.rows - 1) == row))
 
297
    {
 
298
        int ax, ay;
 
299
        int fill_width, fill_height;
 
300
        /*
 
301
         * Need to check the actual window we are drawing on to ensure
 
302
         * the correct visual
 
303
         */
 
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);
 
308
    }
 
309
    else if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw) &&
 
310
             (column == (mw->matrix.columns - 1)))
 
311
    {
 
312
        int ax, ay;
 
313
        int fill_width, fill_height;
 
314
 
 
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);
 
319
    }
 
320
 
 
321
    /*
 
322
     * Draw the string in the cell.
 
323
     */
 
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);
 
331
 
 
332
#if XmVersion >= 1002
 
333
    if (mw->matrix.highlighted_cells &&
 
334
        mw->matrix.highlighted_cells[row][column])
 
335
    {
 
336
        xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, width, height,
 
337
                              HIGHLIGHTING_SOMETHING);
 
338
    }
 
339
#endif
 
340
 
 
341
    xbaeDrawCellShadow(mw, win, row, column, x, y, COLUMN_WIDTH(mw, column),
 
342
                       ROW_HEIGHT(mw), False, False, False);
 
343
}
 
344
#if CELL_WIDGETS
 
345
/*
 
346
 * Draw a user defined widget in the cell
 
347
 */
 
348
static void
 
349
xbaeDrawCellWidget(mw, row, column, x, y, widget, bg, fg)
 
350
XbaeMatrixWidget mw;
 
351
int row, column;
 
352
int x, y;
 
353
Widget widget;
 
354
Pixel bg, fg;
 
355
{
 
356
    GC gc;
 
357
    Widget w;
 
358
    Window win = xbaeGetCellWindow(mw, &w, row, column);
 
359
 
 
360
    if (!win)
 
361
        return;
 
362
 
 
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));
 
367
 
 
368
    /*
 
369
     * Draw the widget in the cell.
 
370
     */
 
371
    XtMoveWidget(widget,
 
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);
 
376
 
 
377
    xbaeDrawCellShadow(mw, win, row, column, x, y, COLUMN_WIDTH(mw, column),
 
378
                       ROW_HEIGHT(mw), False, clipped, False);
 
379
}
 
380
#endif
 
381
 
 
382
/*
 
383
 * Width in pixels of a character in a given font
 
384
 */
 
385
#define charWidth(fs,c) ((fs)->per_char ? \
 
386
                         (fs)->per_char[((c) < (fs)->min_char_or_byte2 ? \
 
387
                                         (fs)->default_char : \
 
388
                                         (c) - \
 
389
                                         (fs)->min_char_or_byte2)].width : \
 
390
                         (fs)->min_bounds.width)
 
391
 
 
392
 
 
393
/*
 
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.
 
396
 */
 
397
void
 
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)
 
403
#else
 
404
xbaeDrawString(mw, win, gc, string, length, x, y, maxlen, alignment,
 
405
               highlight, bold, rowLabel, colLabel, color)
 
406
XbaeMatrixWidget mw;
 
407
Window win;
 
408
GC gc;
 
409
String string;
 
410
int length;
 
411
int x;
 
412
int y;
 
413
int maxlen;
 
414
unsigned char alignment;
 
415
Boolean highlight;
 
416
Boolean bold;
 
417
Boolean rowLabel;
 
418
Boolean colLabel;
 
419
Pixel color;
 
420
#endif
 
421
{
 
422
    int start, width, maxwidth;
 
423
    XFontStruct        *font_struct;
 
424
    XFontSet        font_set;
 
425
    Boolean choppedStart = False;
 
426
    Boolean choppedEnd = False;
 
427
    XRectangle *ink_array = NULL;
 
428
    XRectangle *logical_array = NULL;
 
429
    int num_chars;
 
430
    XRectangle overall_logical;
 
431
 
 
432
    if (rowLabel || colLabel)
 
433
    {
 
434
        font_struct = mw->matrix.label_font_struct;
 
435
        font_set = mw->matrix.label_font_set;
 
436
    }
 
437
    else
 
438
    {
 
439
        font_struct = mw->matrix.font_struct;
 
440
        font_set = mw->matrix.font_set;
 
441
    }
 
442
    /*
 
443
     * Initialize starting character in string
 
444
     */
 
445
    start = 0;
 
446
 
 
447
    if (!rowLabel)
 
448
        maxwidth = maxlen * FONT_WIDTH(mw);
 
449
    else 
 
450
        maxwidth = maxlen * LABEL_WIDTH(mw);
 
451
 
 
452
    if (font_set)
 
453
    {
 
454
        ink_array = (XRectangle*)XtMalloc(length * sizeof(XRectangle));
 
455
        logical_array = (XRectangle*)XtMalloc(length * sizeof(XRectangle));
 
456
 
 
457
        XmbTextPerCharExtents(font_set, string, length,
 
458
            ink_array, logical_array, length, &num_chars,
 
459
            NULL, &overall_logical);
 
460
 
 
461
        /*
 
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
 
465
         * width.
 
466
         */
 
467
        if (overall_logical.width > maxwidth)
 
468
        {
 
469
            switch (alignment)
 
470
            {
 
471
 
 
472
            case XmALIGNMENT_CENTER:
 
473
            {
 
474
                int startx;
 
475
                int endx;
 
476
                int i;
 
477
                int end;
 
478
 
 
479
                /*
 
480
                 * If we are going to draw arrows at both ends, allow for them.
 
481
                 */
 
482
                if (mw->matrix.show_arrows)
 
483
                {
 
484
                    maxwidth -= 2 * mw->matrix.font_width;
 
485
                    choppedStart = True;
 
486
                    choppedEnd = True;
 
487
                }
 
488
 
 
489
                /*
 
490
                 * Find limits of cell relative to the origin of the string.
 
491
                 */
 
492
                startx = overall_logical.x + overall_logical.width / 2 -
 
493
                    maxwidth / 2;
 
494
                endx = startx + maxwidth - 1;
 
495
 
 
496
                /*
 
497
                 * Find the first character which fits into the cell.
 
498
                 */
 
499
                for (i = 0; i < num_chars && logical_array[i].x < startx; ++i)
 
500
                {
 
501
                    int cl = mblen(string + start, length);
 
502
                    start += cl;
 
503
                    length -= cl;
 
504
                }
 
505
 
 
506
                /*
 
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.
 
511
                 */
 
512
                for (end = start; i < num_chars && (logical_array[i].x +
 
513
                                                    logical_array[i].width) <
 
514
                         endx; ++i)
 
515
                {
 
516
                    int cl = mblen(string + end, length);
 
517
                    end += cl;
 
518
                    length -= cl;
 
519
                }
 
520
 
 
521
                /*
 
522
                 * Now reset length so that it represents the number of bytes
 
523
                 * in the string.
 
524
                 */
 
525
                length = end - start;
 
526
 
 
527
                break;
 
528
            }
 
529
 
 
530
            case XmALIGNMENT_END:
 
531
            {
 
532
                int startx;
 
533
                int i;
 
534
 
 
535
                /*
 
536
                 * We are going to an draw arrow at the end, allow for it.
 
537
                 */
 
538
                if (mw->matrix.show_arrows)
 
539
                {
 
540
                    maxwidth -= mw->matrix.font_width;
 
541
                    choppedEnd = True;
 
542
                }
 
543
 
 
544
                /*
 
545
                 * Find limits of cell relative to the origin of the string.
 
546
                 */
 
547
                startx = overall_logical.x + overall_logical.width - maxwidth;
 
548
 
 
549
                /*
 
550
                 * Find the first character which fits into the cell.
 
551
                 */
 
552
                for (i = 0; i < num_chars && logical_array[i].x < startx; ++i)
 
553
                {
 
554
                    int cl = mblen(string + start, length);
 
555
                    start += cl;
 
556
                    length -= cl;
 
557
                }
 
558
 
 
559
                break;
 
560
            }
 
561
 
 
562
            case XmALIGNMENT_BEGINNING:
 
563
            default:
 
564
            {
 
565
                int endx;
 
566
                int i;
 
567
                int end;
 
568
 
 
569
                /*
 
570
                 * We are going to an draw arrow at the start, allow for it.
 
571
                 */
 
572
                if (mw->matrix.show_arrows)
 
573
                {
 
574
                    maxwidth -= mw->matrix.font_width;
 
575
                    choppedStart = True;
 
576
                }
 
577
 
 
578
                /*
 
579
                 * Find limits of cell relative to the origin of the string.
 
580
                 */
 
581
                endx = overall_logical.x + maxwidth - 1;
 
582
 
 
583
                /*
 
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
 
587
                 * string.
 
588
                 */
 
589
                for (i = 0, end = start;
 
590
                     i < num_chars && (logical_array[i].x +
 
591
                                       logical_array[i].width) < endx; ++i)
 
592
                {
 
593
                    int cl = mblen(string + end, length);
 
594
                    end += cl;
 
595
                    length -= cl;
 
596
                    choppedEnd = True;
 
597
                }
 
598
 
 
599
                /*
 
600
                 * Now reset length so that it represents the number of bytes
 
601
                 * in the string.
 
602
                 */
 
603
                length = end - start;
 
604
 
 
605
                break;
 
606
            }
 
607
            }
 
608
 
 
609
            /*
 
610
             * Having truncated string recalculate extents to find origin
 
611
             */
 
612
            XmbTextPerCharExtents(font_set, string, length,
 
613
                ink_array, logical_array, length, &num_chars,
 
614
                NULL, &overall_logical);
 
615
        }
 
616
        /*
 
617
         * We fit inside our cell, so just compute the x of the start of
 
618
         * our string
 
619
         */
 
620
        else
 
621
        {
 
622
            switch (alignment)
 
623
            {
 
624
 
 
625
            case XmALIGNMENT_CENTER:
 
626
                x += maxwidth / 2 - overall_logical.width / 2;
 
627
                break;
 
628
 
 
629
            case XmALIGNMENT_END:
 
630
                x += maxwidth - overall_logical.width;
 
631
                break;
 
632
 
 
633
            case XmALIGNMENT_BEGINNING:
 
634
            default:
 
635
                /*
 
636
                 * Leave x alone
 
637
                 */
 
638
                break;
 
639
            }
 
640
        }
 
641
 
 
642
        /*
 
643
         * Don't worry, XSetForeground is smart about avoiding unnecessary
 
644
         * protocol requests.
 
645
         */
 
646
        XSetForeground(XtDisplay(mw), gc, color);
 
647
 
 
648
        if (mw->matrix.show_arrows && choppedStart)
 
649
        {
 
650
            XPoint points[ 3 ];
 
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;
 
654
            points[ 2 ].x = x;
 
655
            points[ 2 ].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
 
656
 
 
657
            XFillPolygon(XtDisplay(mw), win, gc, points, 3,
 
658
                         Convex, CoordModeOrigin);
 
659
 
 
660
            /* Offset the start point so as to not draw on the triangle */
 
661
            x += FONT_WIDTH(mw);
 
662
        }
 
663
 
 
664
        if (mw->matrix.show_arrows && choppedEnd)
 
665
        {
 
666
            XPoint points[ 3 ];
 
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;
 
672
 
 
673
            XFillPolygon(XtDisplay(mw), win, gc, points, 3,
 
674
                         Convex, CoordModeOrigin);
 
675
        }
 
676
 
 
677
        /*
 
678
         * Adjust x for origin of string.
 
679
         */
 
680
        x -= overall_logical.x;
 
681
 
 
682
        /*
 
683
         * Now draw the string at x starting at char 'start' and of
 
684
         * length 'length'
 
685
         */
 
686
        XmbDrawString(XtDisplay(mw), win, font_set, gc, x, y, &string[start],
 
687
                      length);
 
688
 
 
689
        /*
 
690
         * If bold is on, draw the string again offset by 1 pixel (overstrike)
 
691
         */
 
692
        if (bold)
 
693
            XmbDrawString(XtDisplay(mw), win, font_set, gc, x - 1, y,
 
694
                          &string[start], length);
 
695
        if (ink_array)
 
696
            XtFree((char*)ink_array);
 
697
        if (logical_array)
 
698
            XtFree((char*)logical_array);
 
699
    }
 
700
    else
 
701
    {
 
702
        width = XTextWidth(font_struct, string, length);
 
703
 
 
704
        /*
 
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
 
708
         * width.
 
709
         */
 
710
        if (width > maxwidth)
 
711
        {
 
712
            switch (alignment)
 
713
            {
 
714
 
 
715
            case XmALIGNMENT_CENTER:
 
716
            {
 
717
                int startx = x;
 
718
                int endx = x + maxwidth - 1;
 
719
                int newendx;
 
720
 
 
721
                /*
 
722
                 * Figure out our x for the centered string.  Then loop
 
723
                 * and chop characters off the front until we are within
 
724
                 * the cell.
 
725
                 *
 
726
                 * Adjust x, the starting character and the length of the
 
727
                 * string for each char.
 
728
                 */
 
729
                x += maxwidth / 2 - width / 2;
 
730
                while (x < startx)
 
731
                {
 
732
                    int cw = charWidth(font_struct,
 
733
                                       (unsigned char)string[start]);
 
734
 
 
735
                    x += cw;
 
736
                    width -= cw;
 
737
                    length--;
 
738
                    start++;
 
739
                    choppedStart = True;
 
740
                }
 
741
 
 
742
                /*
 
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.
 
745
                 */
 
746
                newendx = x + width - 1;
 
747
                while (newendx > endx && *(string + start))
 
748
                {
 
749
                    int cw = charWidth(font_struct,
 
750
                                       (unsigned char)string[start]);
 
751
 
 
752
                    newendx -= cw;
 
753
                    width -= cw;
 
754
                    length--;
 
755
                    choppedEnd = True;
 
756
                }
 
757
 
 
758
                break;
 
759
            }
 
760
 
 
761
            case XmALIGNMENT_END:
 
762
            {
 
763
 
 
764
                /*
 
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.
 
769
                 */
 
770
                x += maxwidth - width;
 
771
                while (width > maxwidth)
 
772
                {
 
773
                    int cw = charWidth(font_struct,
 
774
                                       (unsigned char)string[start]);
 
775
 
 
776
                    width -= cw;
 
777
                    x += cw;
 
778
                    length--;
 
779
                    start++;
 
780
                    choppedStart = True;
 
781
                }
 
782
                break;
 
783
            }
 
784
 
 
785
            case XmALIGNMENT_BEGINNING:
 
786
            default:
 
787
                /*
 
788
                 * Leave x alone, but chop characters off the end until we fit
 
789
                 */
 
790
                while (width > maxwidth)
 
791
                {
 
792
                    width -= charWidth(font_struct,
 
793
                                       (unsigned char)string[length - 1]);
 
794
                    length--;
 
795
                    choppedEnd = True;
 
796
                }
 
797
                break;
 
798
            }
 
799
        }
 
800
 
 
801
        /*
 
802
         * We fit inside our cell, so just compute the x of the start of
 
803
         * our string
 
804
         */
 
805
        else
 
806
        {
 
807
            switch (alignment)
 
808
            {
 
809
 
 
810
            case XmALIGNMENT_CENTER:
 
811
                x += maxwidth / 2 - width / 2;
 
812
                break;
 
813
 
 
814
            case XmALIGNMENT_END:
 
815
                x += maxwidth - width;
 
816
                break;
 
817
 
 
818
            case XmALIGNMENT_BEGINNING:
 
819
            default:
 
820
                /*
 
821
                 * Leave x alone
 
822
                 */
 
823
                break;
 
824
            }
 
825
        }
 
826
        
 
827
        /*
 
828
         * Don't worry, XSetForeground is smart about avoiding unnecessary
 
829
         * protocol requests.
 
830
         */
 
831
        XSetForeground(XtDisplay(mw), gc, color);
 
832
 
 
833
        if (mw->matrix.show_arrows && choppedEnd)
 
834
        {
 
835
            XPoint points[3];
 
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;
 
841
 
 
842
            XFillPolygon(XtDisplay(mw), win, gc, points, 3,
 
843
                         Convex, CoordModeOrigin);
 
844
 
 
845
            /* Reduce the length to allow for our foreign character */
 
846
            length--;
 
847
        }
 
848
        if (mw->matrix.show_arrows && choppedStart)
 
849
        {
 
850
            XPoint points[3];
 
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;
 
854
            points[2].x = x;
 
855
            points[2].y = y + mw->matrix.font_y + mw->matrix.font_height / 2;
 
856
 
 
857
            XFillPolygon(XtDisplay(mw), win, gc, points, 3,
 
858
                         Convex, CoordModeOrigin);
 
859
 
 
860
            /* Offset the start point so as to not draw on the triangle */
 
861
            x += mw->matrix.font_width;
 
862
            start++;
 
863
            length--;
 
864
        }
 
865
 
 
866
        /*
 
867
         * Now draw the string at x starting at char 'start' and of length
 
868
         * 'length'
 
869
         */
 
870
#ifdef NEED_WCHAR
 
871
        if (TWO_BYTE_FONT(mw))
 
872
            XDrawString16(XtDisplay(mw), win, gc, x, y, &string[start],
 
873
                          length);
 
874
        else
 
875
#endif
 
876
            XDrawString(XtDisplay(mw), win, gc, x, y, &string[start], length);
 
877
 
 
878
        /*
 
879
         * If bold is on, draw the string again offset by 1 pixel (overstrike)
 
880
         */
 
881
        if (bold)
 
882
#ifdef NEED_WCHAR
 
883
            if (TWO_BYTE_FONT(mw))
 
884
                XDrawString16(XtDisplay(mw), win, gc, x - 1, y,
 
885
                              &string[start], length);
 
886
            else
 
887
#endif
 
888
                XDrawString(XtDisplay(mw), win, gc, x - 1, y,
 
889
                            &string[start], length);
 
890
    }
 
891
}
 
892
 
 
893
void
 
894
xbaeComputeCellColors(mw, row, column, fg, bg)
 
895
XbaeMatrixWidget mw;
 
896
int row, column;
 
897
Pixel *fg, *bg;
 
898
{
 
899
    Boolean alt = mw->matrix.alt_row_count ?
 
900
        (row / mw->matrix.alt_row_count) % 2 : False;
 
901
 
 
902
    /*
 
903
     * Compute the background and foreground colours of the cell
 
904
     */
 
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];
 
909
            else 
 
910
                *bg = mw->manager.foreground;
 
911
        } 
 
912
        else 
 
913
            *bg = mw->matrix.selected_background;
 
914
    }
 
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];
 
919
    }    
 
920
    else {
 
921
        if (alt)
 
922
            *bg = mw->matrix.odd_row_background;
 
923
        else
 
924
            *bg = mw->matrix.even_row_background;
 
925
    }
 
926
 
 
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];
 
931
            else
 
932
                *fg = mw->core.background_pixel;
 
933
        }
 
934
        else
 
935
            *fg = mw->matrix.selected_foreground;
 
936
    }
 
937
    else if (mw->matrix.colors)
 
938
        *fg = mw->matrix.colors[row][column];
 
939
    else
 
940
        *fg = mw->manager.foreground;    
 
941
}
 
942
 
 
943
void
 
944
xbaeDrawCell(mw, row, column)
 
945
XbaeMatrixWidget mw;
 
946
int row, column;
 
947
{
 
948
    Pixel bg, fg;
 
949
    String string;
 
950
    int x, y;
 
951
    
 
952
    if (mw->matrix.disable_redisplay || mw->matrix.rows == 0 ||
 
953
        mw->matrix.columns == 0)
 
954
        return;
 
955
 
 
956
    /*
 
957
     * Convert the row/column to the coordinates relative to the correct
 
958
     * window
 
959
     */
 
960
    xbaeRowColToXY(mw, row, column, &x, &y);
 
961
 
 
962
    xbaeComputeCellColors(mw, row, column, &fg, &bg);
 
963
 
 
964
#if CELL_WIDGETS
 
965
    if (mw->matrix.cell_widgets[row][column])
 
966
        xbaeDrawCellWidget(mw, row, column, x, y,
 
967
                           mw->matrix.cell_widgets[row][column], bg, fg);
 
968
    else
 
969
#endif
 
970
 
 
971
        if (!mw->matrix.draw_cell_callback)
 
972
        {
 
973
            if (row < mw->matrix.rows && column < mw->matrix.columns)
 
974
            {
 
975
                if (mw->matrix.cells && mw->matrix.cells[row])
 
976
                    string = mw->matrix.cells[row][column];
 
977
                else
 
978
                    string = "";
 
979
 
 
980
                xbaeDrawCellString(mw, row, column, x, y, string, bg, fg);
 
981
            }
 
982
        }
 
983
        else
 
984
        {
 
985
            Pixmap pixmap;
 
986
            Pixmap mask;
 
987
            XbaeCellType type;
 
988
            int width, height;
 
989
            int depth;
 
990
        
 
991
            if (row < mw->matrix.rows && column < mw->matrix.columns)
 
992
            {
 
993
                type = xbaeGetDrawCellValue(mw, row, column, &string, &pixmap,
 
994
                                            &mask, &width, &height, &bg, &fg,
 
995
                                            &depth);
 
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);
 
1001
            }
 
1002
        }
 
1003
}
 
1004
 
 
1005
XbaeCellType
 
1006
xbaeGetDrawCellValue(mw, row, column, string, pixmap, mask, width,
 
1007
                     height, bg, fg, depth)
 
1008
XbaeMatrixWidget mw;
 
1009
int row;
 
1010
int column;
 
1011
String *string;
 
1012
Pixmap *pixmap;
 
1013
Pixmap *mask;
 
1014
int *width, *height;
 
1015
Pixel *bg, *fg;
 
1016
int *depth;
 
1017
{
 
1018
    XbaeMatrixDrawCellCallbackStruct call_data;
 
1019
 
 
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;
 
1033
 
 
1034
    XtCallCallbackList((Widget)mw, mw->matrix.draw_cell_callback,
 
1035
                       (XtPointer) &call_data);
 
1036
 
 
1037
    *pixmap = call_data.pixmap;
 
1038
    *mask = call_data.mask;
 
1039
    *string = call_data.string ? call_data.string : ""; /* Handle NULLs */
 
1040
 
 
1041
    if (mw->matrix.reverse_select && mw->matrix.selected_cells &&
 
1042
        mw->matrix.selected_cells[row][column])
 
1043
    {
 
1044
        /*
 
1045
         * if colours were set by the draw cell callback, handle reverse
 
1046
         * selection
 
1047
         */
 
1048
        if (*bg != call_data.background)
 
1049
        {
 
1050
            if (*fg != call_data.foreground)
 
1051
                *bg = call_data.foreground;
 
1052
            *fg = call_data.background;
 
1053
        }
 
1054
        else if (*fg != call_data.foreground)
 
1055
            *bg = call_data.foreground;
 
1056
    }
 
1057
    else
 
1058
    {
 
1059
        *fg = call_data.foreground;
 
1060
        *bg = call_data.background;
 
1061
    }
 
1062
    *width = call_data.width;
 
1063
    *height = call_data.height;
 
1064
    *depth = call_data.depth;
 
1065
    
 
1066
    if (call_data.type == XbaePixmap)
 
1067
    {
 
1068
        if (*mask == XmUNSPECIFIED_PIXMAP || *mask == BadPixmap)
 
1069
            call_data.mask = 0;
 
1070
 
 
1071
        if (*pixmap == XmUNSPECIFIED_PIXMAP || *pixmap == BadPixmap)
 
1072
        {
 
1073
            XtAppWarningMsg(
 
1074
                XtWidgetToApplicationContext((Widget)mw),
 
1075
                "drawCellCallback", "Pixmap", "XbaeMatrix",
 
1076
                "XbaeMatrix: Bad pixmap passed from drawCellCallback",
 
1077
                NULL, 0);
 
1078
            call_data.type = XbaeString;
 
1079
            *string = "";
 
1080
        }
 
1081
        else if (!*depth)
 
1082
        {
 
1083
             /*
 
1084
              * If we know the depth, width and height don't do a round
 
1085
              * trip to find the
 
1086
              * geometry
 
1087
              */
 
1088
            Window root_return;
 
1089
            int x_return, y_return;
 
1090
            unsigned int width_return, height_return;
 
1091
            unsigned int border_width_return;
 
1092
            unsigned int depth_return;
 
1093
 
 
1094
            if (XGetGeometry(XtDisplay(mw), *pixmap, &root_return,
 
1095
                             &x_return, &y_return, &width_return,
 
1096
                             &height_return, &border_width_return,
 
1097
                             &depth_return))
 
1098
            {
 
1099
                *width = width_return;
 
1100
                *height = height_return;
 
1101
                *depth = depth_return;
 
1102
            }
 
1103
        }
 
1104
    }
 
1105
    return (call_data.type);
 
1106
}
 
1107
 
 
1108
/*
 
1109
 * Draw the column label for the specified column.  Handles labels in
 
1110
 * fixed and non-fixed columns.
 
1111
 */
 
1112
void
 
1113
#if NeedFunctionPrototypes
 
1114
xbaeDrawColumnLabel(XbaeMatrixWidget mw, int column, Boolean pressed)
 
1115
#else
 
1116
xbaeDrawColumnLabel(mw, column, pressed)
 
1117
XbaeMatrixWidget mw;
 
1118
int column;
 
1119
Boolean pressed;
 
1120
#endif
 
1121
{
 
1122
    String label;
 
1123
    int labelX, labelY;
 
1124
    int buttonX;
 
1125
    int i;
 
1126
    GC gc;
 
1127
    Window win = XtWindow(mw);
 
1128
    Boolean clipped = (column >= (int)mw->matrix.fixed_columns &&
 
1129
                       column < TRAILING_HORIZ_ORIGIN(mw));
 
1130
 
 
1131
    Boolean button = mw->matrix.button_labels ||
 
1132
        (mw->matrix.column_button_labels &&
 
1133
         mw->matrix.column_button_labels[column]);
 
1134
 
 
1135
    if (mw->matrix.column_labels[column][0] == '\0' && !button)
 
1136
        return;
 
1137
 
 
1138
    /*
 
1139
     * If the column label is in a fixed column, we don't need to account
 
1140
     * for the horiz_origin
 
1141
     */
 
1142
    if (column < (int)mw->matrix.fixed_columns)
 
1143
    {
 
1144
        labelX = COLUMN_LABEL_OFFSET(mw) + COLUMN_POSITION(mw, column) +
 
1145
            TEXT_X_OFFSET(mw);
 
1146
        buttonX = COLUMN_LABEL_OFFSET(mw) + COLUMN_POSITION(mw, column);
 
1147
    }
 
1148
    else if (column >= TRAILING_HORIZ_ORIGIN(mw))
 
1149
    {
 
1150
        labelX = TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw) +
 
1151
            COLUMN_POSITION(mw, column) -
 
1152
            COLUMN_POSITION(mw, TRAILING_HORIZ_ORIGIN(mw)) +
 
1153
            TEXT_X_OFFSET(mw);
 
1154
        buttonX = TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw) +
 
1155
            COLUMN_POSITION(mw, column) -
 
1156
            COLUMN_POSITION(mw, TRAILING_HORIZ_ORIGIN(mw));
 
1157
    }
 
1158
    else
 
1159
    {
 
1160
        labelX = COLUMN_LABEL_OFFSET(mw) +
 
1161
            (COLUMN_POSITION(mw, column) - HORIZ_ORIGIN(mw)) +
 
1162
            TEXT_X_OFFSET(mw);
 
1163
        buttonX = COLUMN_LABEL_OFFSET(mw) + (COLUMN_POSITION(mw, column) -
 
1164
                                             HORIZ_ORIGIN(mw));
 
1165
    }        
 
1166
 
 
1167
    /*
 
1168
     * Set our y to the baseline of the first line in this column
 
1169
     */
 
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);
 
1178
 
 
1179
    if (clipped)
 
1180
        gc = mw->matrix.label_clip_gc;
 
1181
    else
 
1182
        gc = mw->matrix.label_gc;
 
1183
    
 
1184
    if (button)
 
1185
    {
 
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));
 
1189
    }
 
1190
 
 
1191
    XSetForeground(XtDisplay(mw), gc, mw->matrix.column_label_color);
 
1192
    XSetBackground(XtDisplay(mw), gc, mw->matrix.button_label_background);
 
1193
 
 
1194
    label = mw->matrix.column_labels[column];
 
1195
 
 
1196
    if (label[0] != '\0')
 
1197
        for (i = 0; i < mw->matrix.column_label_lines[column].lines; i++)
 
1198
        {
 
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);
 
1207
        
 
1208
            labelY += LABEL_HEIGHT(mw);
 
1209
            label += mw->matrix.column_label_lines[column].lengths[i] + 1;
 
1210
        }
 
1211
    if (button)
 
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);
 
1216
}
 
1217
 
 
1218
/*
 
1219
 * Draw the row label for the specified row. Handles labels in fixed and
 
1220
 * non-fixed rows.
 
1221
 */
 
1222
void
 
1223
#if NeedFunctionPrototypes
 
1224
xbaeDrawRowLabel(XbaeMatrixWidget mw, int row, Boolean pressed)
 
1225
#else
 
1226
xbaeDrawRowLabel(mw, row, pressed)
 
1227
XbaeMatrixWidget mw;
 
1228
int row;
 
1229
Boolean pressed;
 
1230
#endif
 
1231
{
 
1232
    int y;
 
1233
    GC gc;
 
1234
    Window win = XtWindow(mw);
 
1235
    Boolean clipped = (row >= (int)mw->matrix.fixed_rows &&
 
1236
                       row < TRAILING_VERT_ORIGIN(mw));
 
1237
    
 
1238
    Boolean button = mw->matrix.button_labels ||
 
1239
        (mw->matrix.row_button_labels && mw->matrix.row_button_labels[row]);
 
1240
 
 
1241
    if (mw->matrix.row_labels[row][0] == '\0' && !button)
 
1242
        return;
 
1243
 
 
1244
    /*
 
1245
     * If the row label is in a fixed row we don't need to account
 
1246
     * for the vert_origin
 
1247
     */
 
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)) +
 
1253
            TEXT_Y_OFFSET(mw);
 
1254
    else
 
1255
        y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * (row - VERT_ORIGIN(mw)) +
 
1256
            LABEL_Y_OFFSET(mw) - mw->matrix.first_row_offset;
 
1257
 
 
1258
    if (clipped)
 
1259
        gc = mw->matrix.label_clip_gc;
 
1260
    else
 
1261
        gc = mw->matrix.label_gc;
 
1262
    
 
1263
    if (button)
 
1264
    {
 
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),
 
1268
                       ROW_HEIGHT(mw));
 
1269
    }
 
1270
 
 
1271
    XSetForeground(XtDisplay(mw), gc, mw->matrix.row_label_color);
 
1272
    XSetBackground(XtDisplay(mw), gc, mw->matrix.button_label_background);
 
1273
 
 
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);
 
1283
    
 
1284
    if (button)
 
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);
 
1288
}