OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [libgui/] [src/] [tkTableCell.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkTableCell.c --
3
 *
4
 *      This module implements cell oriented functions for table
5
 *      widgets.
6
 *
7
 * Copyright (c) 1998 Jeffrey Hobbs
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 */
13
 
14
#include "tkTable.h"
15
 
16
static int      TableSortCompareProc _ANSI_ARGS_((CONST VOID *first,
17
                                                  CONST VOID *second));
18
 
19
/*
20
 *----------------------------------------------------------------------
21
 *
22
 * TableCellCoords --
23
 *      Takes a row,col pair in real coords and finds it position
24
 *      on the virtual screen.
25
 *
26
 * Results:
27
 *      The virtual x, y, width, and height of the cell
28
 *      are placed in the pointers.
29
 *
30
 * Side effects:
31
 *      None.
32
 *
33
 *----------------------------------------------------------------------
34
 */
35
void
36
TableCellCoords(Table *tablePtr, int row, int col,
37
                int *x, int *y, int *width, int *height)
38
{
39
  if (tablePtr->rows <= 0 || tablePtr->cols <= 0) {
40
    *width = *height = *x = *y = 0;
41
    return;
42
  }
43
  /* real coords required, always should be passed acceptable values,
44
   * but this is a possible seg fault otherwise */
45
  row = MIN(tablePtr->rows-1, MAX(0, row));
46
  col = MIN(tablePtr->cols-1, MAX(0, col));
47
  *width = tablePtr->colPixels[col];
48
  *height = tablePtr->rowPixels[row];
49
  *x = tablePtr->highlightWidth + tablePtr->colStarts[col] -
50
    ((col < tablePtr->titleCols) ? 0 : tablePtr->colStarts[tablePtr->leftCol]
51
     - tablePtr->colStarts[tablePtr->titleCols]);
52
  *y = tablePtr->highlightWidth + tablePtr->rowStarts[row] -
53
    ((row < tablePtr->titleRows) ? 0 : tablePtr->rowStarts[tablePtr->topRow]
54
     - tablePtr->rowStarts[tablePtr->titleRows]);
55
}
56
 
57
/*
58
 *----------------------------------------------------------------------
59
 *
60
 * TableCellVCoords --
61
 *      Takes a row,col pair in real coords and finds it position
62
 *      on the actual screen.  The full arg specifies whether
63
 *      only 100% visible cells should be considered visible.
64
 *
65
 * Results:
66
 *      The x, y, width, and height of the cell are placed in the pointers,
67
 *      depending upon visibility of the cell.
68
 *      Returns 0 for hidden and 1 for visible cells.
69
 *
70
 * Side effects:
71
 *      None.
72
 *
73
 *----------------------------------------------------------------------
74
 */
75
int
76
TableCellVCoords(Table *tablePtr, int row, int col,
77
                 int *rx, int *ry, int *rw, int *rh, int full)
78
{
79
  if (tablePtr->tkwin == NULL) return 0;
80
 
81
  if ((row < tablePtr->topRow && row >= tablePtr->titleRows) ||
82
      (col < tablePtr->leftCol && col >= tablePtr->titleCols)) {
83
    /* hiding in "dead" space between title areas and visible cells */
84
    *rx = 0; *ry = 0; *rw = 0; *rh = 0;
85
    return 0;
86
  } else {
87
    int x, y, w, h, w0, h0, hl = tablePtr->highlightWidth;
88
    /* Necessary to use separate vars in case dummies are passed in */
89
    TableCellCoords(tablePtr, row, col, &x, &y, &w, &h);
90
    *rx = x; *ry = y;
91
    if (full) {
92
      w0 = w; h0 = h;
93
    } else {
94
      /* if we don't care about seeing the whole thing, then
95
       * make sure we at least see a pixel worth */
96
      w0 = h0 = 1;
97
    }
98
    /* Is the cell visible? */
99
    if (x<hl || y<hl || (x+w0)>(Tk_Width(tablePtr->tkwin)-hl)
100
        || (y+h0)>(Tk_Height(tablePtr->tkwin)-hl)) {
101
      /* definitely off the screen */
102
      *rw = *rh = 0;
103
      return 0;
104
    } else {
105
      if (full) {
106
        *rw = w; *rh = h;
107
      } else {
108
        *rw = MIN(w, Tk_Width(tablePtr->tkwin)-hl-x);
109
        *rh = MIN(h, Tk_Height(tablePtr->tkwin)-hl-y);
110
      }
111
      return 1;
112
    }
113
  }
114
}
115
 
116
/*
117
 *----------------------------------------------------------------------
118
 *
119
 * TableWhatCell --
120
 *      Takes a x,y screen coordinate and determines what cell contains.
121
 *      that point.  This will return cells that are beyond the right/bottom
122
 *      edge of the viewable screen.
123
 *
124
 * Results:
125
 *      The row,col of the cell are placed in the pointers.
126
 *
127
 * Side effects:
128
 *      None.
129
 *
130
 *----------------------------------------------------------------------
131
 */
132
void
133
TableWhatCell(register Table *tablePtr, int x, int y, int *row, int *col)
134
{
135
  int i;
136
  x = MAX(0, x); y = MAX(0, y);
137
  /* Adjust for table's global highlightthickness border */
138
  x -= tablePtr->highlightWidth;
139
  y -= tablePtr->highlightWidth;
140
  /* Adjust the x coord if not in the column titles to change display coords
141
   * into internal coords */
142
  x += (x < tablePtr->colStarts[tablePtr->titleCols]) ? 0 :
143
    tablePtr->colStarts[tablePtr->leftCol] -
144
    tablePtr->colStarts[tablePtr->titleCols];
145
  y += (y < tablePtr->rowStarts[tablePtr->titleRows]) ? 0 :
146
    tablePtr->rowStarts[tablePtr->topRow] -
147
    tablePtr->rowStarts[tablePtr->titleRows];
148
  x = MIN(x, tablePtr->maxWidth-1);
149
  y = MIN(y, tablePtr->maxHeight-1);
150
  for (i = 1; x >= tablePtr->colStarts[i]; i++);
151
  *col = i - 1;
152
  for (i = 1; y >= tablePtr->rowStarts[i]; i++);
153
  *row = i - 1;
154
}
155
 
156
/*
157
 *----------------------------------------------------------------------
158
 *
159
 * TableAtBorder --
160
 *      Takes a x,y screen coordinate and determines if that point is
161
 *      over a border.
162
 *
163
 * Results:
164
 *      The left/top row,col corresponding to that point are placed in
165
 *      the pointers.  The number of borders (+1 for row, +1 for col)
166
 *      hit is returned.
167
 *
168
 * Side effects:
169
 *      None.
170
 *
171
 *----------------------------------------------------------------------
172
 */
173
int
174
TableAtBorder(Table * tablePtr, int x, int y, int *row, int *col)
175
{
176
  int i, borders = 2, bd = tablePtr->borderWidth;
177
  int dbd = 2*bd;
178
  x = MAX(0, x); y = MAX(0, y);
179
  x -= tablePtr->highlightWidth; y -= tablePtr->highlightWidth;
180
  /* Adjust the x coord if not in the column titles to change display coords
181
   * into internal coords */
182
  x += (x < tablePtr->colStarts[tablePtr->titleCols]) ? 0 :
183
    tablePtr->colStarts[tablePtr->leftCol] -
184
    tablePtr->colStarts[tablePtr->titleCols];
185
  y += (y < tablePtr->rowStarts[tablePtr->titleRows]) ? 0 :
186
    tablePtr->rowStarts[tablePtr->topRow] -
187
    tablePtr->rowStarts[tablePtr->titleRows];
188
  x = MIN(x, tablePtr->maxWidth - 1);
189
  y = MIN(y, tablePtr->maxHeight - 1);
190
  for (i = 1; i <= tablePtr->cols && x+dbd >= tablePtr->colStarts[i]; i++);
191
  if (x > tablePtr->colStarts[--i]+bd) {
192
    borders--;
193
    *col = -1;
194
  } else {
195
    *col = (--i < tablePtr->leftCol && i >= tablePtr->titleCols) ?
196
      tablePtr->titleCols-1 : i;
197
  }
198
  for (i = 1; i <= tablePtr->rows && y+dbd >= tablePtr->rowStarts[i]; i++);
199
  if (y > tablePtr->rowStarts[--i]+bd) {
200
    borders--;
201
    *row = -1;
202
  } else {
203
    *row = (--i < tablePtr->topRow && i >= tablePtr->titleRows) ?
204
      tablePtr->titleRows-1 : i;
205
  }
206
  return borders;
207
}
208
 
209
/*
210
 *----------------------------------------------------------------------
211
 *
212
 * TableGetCellValue --
213
 *      Takes a row,col pair in user coords and returns the value for
214
 *      that cell.  This varies depending on what data source the
215
 *      user has selected.
216
 *
217
 * Results:
218
 *      The value of the cell is returned.  The return value is VOLATILE
219
 *      (do not free).
220
 *
221
 * Side effects:
222
 *      The value will be cached if caching is turned on.
223
 *
224
 *----------------------------------------------------------------------
225
 */
226
char *
227
TableGetCellValue(Table *tablePtr, int r, int c)
228
{
229
  register Tcl_Interp *interp = tablePtr->interp;
230
  char *result = NULL;
231
  char buf[INDEX_BUFSIZE];
232
  Tcl_HashEntry *entryPtr = NULL;
233
  int new = 1;
234
 
235
  TableMakeArrayIndex(r, c, buf);
236
 
237
  if (tablePtr->caching) {
238
    /* if we are caching, let's see if we have the value cached */
239
    entryPtr = Tcl_CreateHashEntry(tablePtr->cache, buf, &new);
240
    if (!new) {
241
      result = (char *) Tcl_GetHashValue(entryPtr);
242
      return result?result:"";
243
    }
244
  }
245
  if (tablePtr->command && tablePtr->useCmd) {
246
    Tcl_DString script;
247
    Tcl_DStringInit(&script);
248
    ExpandPercents(tablePtr, tablePtr->command, r, c, "", (char *)NULL,
249
                   0, &script, 0);
250
    if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) == TCL_ERROR) {
251
      tablePtr->useCmd = 0;
252
      tablePtr->dataSource &= ~DATA_COMMAND;
253
      if (tablePtr->arrayVar)
254
        tablePtr->dataSource |= DATA_ARRAY;
255
      Tcl_AddErrorInfo(interp, "\n\t(in command executed by table)");
256
      Tcl_AddErrorInfo(interp, Tcl_DStringValue(&script));
257
      Tk_BackgroundError(interp);
258
      TableInvalidateAll(tablePtr, 0);
259
    } else {
260
      result = Tcl_GetStringResult(interp);
261
    }
262
    Tcl_FreeResult(interp);
263
    Tcl_DStringFree(&script);
264
  } else if (tablePtr->arrayVar) {
265
    result = Tcl_GetVar2(interp, tablePtr->arrayVar, buf, TCL_GLOBAL_ONLY);
266
  }
267
  if (result == NULL)
268
    result = "";
269
  if (tablePtr->caching && entryPtr != NULL) {
270
    /* if we are caching, make sure we cache the returned value */
271
    /* entryPtr will have been set from above, but check to make sure
272
     * someone didn't change caching during -command evaluation */
273
    char *val;
274
    val = (char *)ckalloc(strlen(result)+1);
275
    strcpy(val, result);
276
    Tcl_SetHashValue(entryPtr, val);
277
  }
278
  return result;
279
}
280
 
281
/*
282
 *----------------------------------------------------------------------
283
 *
284
 * TableSetCellValue --
285
 *      Takes a row,col pair in user coords and saves the given value for
286
 *      that cell.  This varies depending on what data source the
287
 *      user has selected.
288
 *
289
 * Results:
290
 *      Returns TCL_ERROR or TCL_OK, depending on whether an error
291
 *      occured during set (ie: during evaluation of -command).
292
 *
293
 * Side effects:
294
 *      If the value is NULL (empty string), it will be unset from
295
 *      an array rather than set to the empty string.
296
 *
297
 *----------------------------------------------------------------------
298
 */
299
int
300
TableSetCellValue(Table *tablePtr, int r, int c, char *value)
301
{
302
  register Tcl_Interp *interp = tablePtr->interp;
303
  char buf[INDEX_BUFSIZE];
304
  int code = TCL_OK;
305
 
306
  TableMakeArrayIndex(r, c, buf);
307
 
308
  if (tablePtr->state == STATE_DISABLED)
309
    return code;
310
  if (tablePtr->command && tablePtr->useCmd) {
311
    Tcl_DString script;
312
 
313
    Tcl_DStringInit(&script);
314
    ExpandPercents(tablePtr, tablePtr->command, r, c, value, (char *)NULL,
315
                   1, &script, 0);
316
    if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) == TCL_ERROR) {
317
      /* An error resulted.  Prevent further triggering of the command
318
       * and set up the error message. */
319
      tablePtr->useCmd = 0;
320
      tablePtr->dataSource &= ~DATA_COMMAND;
321
      if (tablePtr->arrayVar)
322
        tablePtr->dataSource |= DATA_ARRAY;
323
      Tcl_AddErrorInfo(interp, "\n\t(in command executed by table)");
324
      Tk_BackgroundError(interp);
325
      code = TCL_ERROR;
326
    }
327
    Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
328
    Tcl_DStringFree(&script);
329
  } else if (tablePtr->arrayVar) {
330
    if (value == NULL || *value == '\0') {
331
      Tcl_UnsetVar2(interp, tablePtr->arrayVar, buf, TCL_GLOBAL_ONLY);
332
    } else if (Tcl_SetVar2(interp, tablePtr->arrayVar, buf, value,
333
                           TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
334
      code = TCL_ERROR;
335
    }
336
  }
337
  if (tablePtr->caching && code == TCL_OK) {
338
    Tcl_HashEntry *entryPtr;
339
    int new;
340
    char *val;
341
 
342
    val = (char *)ckalloc(strlen(value)+1);
343
    strcpy(val, value);
344
    entryPtr = Tcl_CreateHashEntry(tablePtr->cache, buf, &new);
345
    Tcl_SetHashValue(entryPtr, val);
346
  }
347
  return code;
348
}
349
 
350
/*
351
 *----------------------------------------------------------------------
352
 *
353
 * TableSortCompareProc --
354
 *      This procedure is invoked by qsort to determine the proper
355
 *      ordering between two elements.
356
 *
357
 * Results:
358
 *      < 0 means first is "smaller" than "second", > 0 means "first"
359
 *      is larger than "second", and 0 means they should be treated
360
 *      as equal.
361
 *
362
 * Side effects:
363
 *      None, unless a user-defined comparison command does something
364
 *      weird.
365
 *
366
 *----------------------------------------------------------------------
367
 */
368
static int
369
TableSortCompareProc(first, second)
370
    CONST VOID *first, *second;         /* Elements to be compared. */
371
{
372
    int r1, c1, r2, c2;
373
    char *firstString = *((char **) first);
374
    char *secondString = *((char **) second);
375
 
376
    /* This doesn't account for badly formed indices */
377
    sscanf(firstString, "%d,%d", &r1, &c1);
378
    sscanf(secondString, "%d,%d", &r2, &c2);
379
    if (r1 > r2)
380
      return 1;
381
    else if (r1 < r2)
382
      return -1;
383
    else if (c1 > c2)
384
      return 1;
385
    else if (c1 < c2)
386
      return -1;
387
    return 0;
388
}
389
 
390
/*
391
 *----------------------------------------------------------------------
392
 *
393
 * TableCellSort --
394
 *      Sort a list of table cell elements (of form row,col)
395
 *
396
 * Results:
397
 *      Returns the sorted list of elements.  Because Tcl_Merge allocs
398
 *      the space for result, it must later be ckfree'd by caller.
399
 *
400
 * Side effects:
401
 *      Behaviour undefined for ill-formed input list of elements.
402
 *
403
 *----------------------------------------------------------------------
404
 */
405
char *
406
TableCellSort(Table *tablePtr, char *str)
407
{
408
  int listArgc;
409
  char **listArgv;
410
  char *result;
411
 
412
  if (Tcl_SplitList(tablePtr->interp, str, &listArgc, &listArgv) != TCL_OK)
413
    return str;
414
  qsort((VOID *) listArgv, (size_t) listArgc, sizeof (char *),
415
        TableSortCompareProc);
416
  result = Tcl_Merge(listArgc, listArgv);
417
  ckfree((char *) listArgv);
418
  return result;
419
}
420
 
421
/*
422
 *----------------------------------------------------------------------
423
 *
424
 * TableGetIcursor --
425
 *      Parses the argument as an index into the active cell string.
426
 *      Recognises 'end', 'insert' or an integer.  Constrains it to the
427
 *      size of the buffer.  This acts like a "SetIcursor" when *posn is NULL.
428
 *
429
 * Results:
430
 *      If (posn != NULL), then it gets the cursor position.
431
 *
432
 * Side effects:
433
 *      Can move cursor position.
434
 *
435
 *----------------------------------------------------------------------
436
 */
437
int
438
TableGetIcursor(Table *tablePtr, char *arg, int *posn)
439
{
440
  int tmp, len;
441
#if (TK_MINOR_VERSION > 0)
442
  len = Tcl_NumUtfChars(tablePtr->activeBuf, strlen(tablePtr->activeBuf));
443
#else
444
  len = strlen(tablePtr->activeBuf);
445
#endif
446
  /* ensure icursor didn't get out of sync */
447
  if (tablePtr->icursor > len) tablePtr->icursor = len;
448
  /* is this end */
449
  if (strcmp(arg, "end") == 0) {
450
    tmp = len;
451
  } else if (strcmp(arg, "insert") == 0) {
452
    tmp = tablePtr->icursor;
453
  } else {
454
    if (Tcl_GetInt(tablePtr->interp, arg, &tmp) != TCL_OK) {
455
      return TCL_ERROR;
456
    }
457
    tmp = MIN(MAX(0, tmp), len);
458
  }
459
  if (posn)
460
    *posn = tmp;
461
  else
462
    tablePtr->icursor = tmp;
463
  return TCL_OK;
464
}
465
 
466
/*
467
 *--------------------------------------------------------------
468
 *
469
 * TableGetIndex --
470
 *      Parse an index into a table and return either its value
471
 *      or an error.
472
 *
473
 * Results:
474
 *      A standard Tcl result.  If all went well, then *row,*col is
475
 *      filled in with the index corresponding to string.  If an
476
 *      error occurs then an error message is left in interp result.
477
 *      The index returned is in user coords.
478
 *
479
 * Side effects:
480
 *      Sets row,col index to an appropriately constrained user index.
481
 *
482
 *--------------------------------------------------------------
483
 */
484
int
485
TableGetIndex(tablePtr, str, row_p, col_p)
486
     register Table *tablePtr;  /* Table for which the index is being
487
                                 * specified. */
488
     char *str;                 /* Symbolic specification of cell in table. */
489
     int *row_p;                /* Where to store converted row. */
490
     int *col_p;                /* Where to store converted col. */
491
{
492
  int r, c, len = strlen(str);
493
 
494
  /*
495
   * Note that all of these values will be adjusted by row/ColOffset
496
   */
497
  if (str[0] == '@') {                           /* @x,y coordinate */
498
    int x, y;
499
    char *p, *end;
500
 
501
    p = str+1;
502
    x = strtol(p, &end, 0);
503
    if ((end == p) || (*end != ','))
504
      goto IndexError;
505
    p = end+1;
506
    y = strtol(p, &end, 0);
507
    if ((end == p) || (*end != '\0'))
508
      goto IndexError;
509
    TableWhatCell(tablePtr, x, y, &r, &c);
510
    r += tablePtr->rowOffset;
511
    c += tablePtr->colOffset;
512
  } else if (sscanf(str, "%d,%d", &r,&c) == 2) {
513
    char buf[INDEX_BUFSIZE];
514
    TableMakeArrayIndex(r, c, buf);
515
    /* Make sure it won't work for "2,3extrastuff" */
516
    if (strcmp(buf, str))
517
      goto IndexError;
518
    /* ensure appropriate user index */
519
    r = MIN(MAX(tablePtr->rowOffset,r),tablePtr->rows-1+tablePtr->rowOffset);
520
    c = MIN(MAX(tablePtr->colOffset,c),tablePtr->cols-1+tablePtr->colOffset);
521
  } else if (len > 1 && strncmp(str, "active", len) == 0 ) {     /* active */
522
    if (tablePtr->flags & HAS_ACTIVE) {
523
      r = tablePtr->activeRow+tablePtr->rowOffset;
524
      c = tablePtr->activeCol+tablePtr->colOffset;
525
    } else {
526
      Tcl_AppendResult(tablePtr->interp, "no \"active\" cell in table", NULL);
527
      return TCL_ERROR;
528
    }
529
  } else if (len > 1 && strncmp(str, "anchor", len) == 0) {      /* anchor */
530
    if (tablePtr->flags & HAS_ANCHOR) {
531
      r = tablePtr->anchorRow+tablePtr->rowOffset;
532
      c = tablePtr->anchorCol+tablePtr->colOffset;
533
    } else {
534
      Tcl_AppendResult(tablePtr->interp, "no \"anchor\" cell in table", NULL);
535
      return TCL_ERROR;
536
    }
537
  } else if (strncmp(str, "end", len) == 0) {            /* end */
538
    r = tablePtr->rows-1+tablePtr->rowOffset;
539
    c = tablePtr->cols-1+tablePtr->colOffset;
540
  } else if (strncmp(str, "origin", len) == 0) { /* origin */
541
    r = tablePtr->titleRows+tablePtr->rowOffset;
542
    c = tablePtr->titleCols+tablePtr->colOffset;
543
  } else if (strncmp(str, "topleft", len) == 0) {        /* topleft */
544
    r = tablePtr->topRow+tablePtr->rowOffset;
545
    c = tablePtr->leftCol+tablePtr->colOffset;
546
  } else if (strncmp(str, "bottomright", len) == 0) {    /* bottomright */
547
    TableGetLastCell(tablePtr, &r, &c);
548
    r += tablePtr->rowOffset;
549
    c += tablePtr->colOffset;
550
  } else {
551
  IndexError:
552
    Tcl_AppendResult(tablePtr->interp, "bad table index \"",
553
                     str, "\"", (char *)NULL);
554
    return TCL_ERROR;
555
  }
556
 
557
  /* Note: values are expected to be properly constrained
558
   * as a user index by this point */
559
  if (row_p) *row_p = r;
560
  if (col_p) *col_p = c;
561
  return TCL_OK;
562
}
563
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.