~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to WINGs/wbrowser.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
 
 
3
 
 
4
 
 
5
#include "WINGsP.h"
 
6
#include <math.h> /* for : double rint (double) */
 
7
 
 
8
 
 
9
 
 
10
typedef struct W_Browser {
 
11
    W_Class widgetClass;
 
12
    W_View *view;
 
13
 
 
14
    char **titles;
 
15
    WMList **columns;
 
16
 
 
17
    short columnCount;
 
18
    short usedColumnCount;             /* columns actually being used */
 
19
    short minColumnWidth;
 
20
 
 
21
    short maxVisibleColumns;
 
22
    short firstVisibleColumn;
 
23
 
 
24
    short titleHeight;
 
25
 
 
26
    short selectedColumn;
 
27
 
 
28
    WMSize columnSize;
 
29
 
 
30
 
 
31
    void *clientData;
 
32
    WMAction *action;
 
33
    void *doubleClientData;
 
34
    WMAction *doubleAction;
 
35
 
 
36
    WMBrowserDelegate *delegate;
 
37
 
 
38
    WMScroller *scroller;
 
39
 
 
40
    char *pathSeparator;
 
41
 
 
42
    struct {
 
43
        unsigned int isTitled:1;
 
44
        unsigned int allowMultipleSelection:1;
 
45
        unsigned int allowEmptySelection:1;
 
46
        unsigned int hasScroller:1;
 
47
 
 
48
        /* */
 
49
        unsigned int loaded:1;
 
50
        unsigned int loadingColumn:1;
 
51
    } flags;
 
52
} Browser;
 
53
 
 
54
 
 
55
#define COLUMN_SPACING  4
 
56
#define TITLE_SPACING 2
 
57
 
 
58
#define DEFAULT_WIDTH                 305
 
59
#define DEFAULT_HEIGHT                200
 
60
#define DEFAULT_HAS_SCROLLER          True
 
61
#define DEFAULT_TITLE_HEIGHT          20
 
62
#define DEFAULT_IS_TITLED             True
 
63
#define DEFAULT_MAX_VISIBLE_COLUMNS   2
 
64
#define DEFAULT_SEPARATOR             "/"
 
65
 
 
66
#define MIN_VISIBLE_COLUMNS           1
 
67
#define MAX_VISIBLE_COLUMNS           32
 
68
 
 
69
 
 
70
#define COLUMN_IS_VISIBLE(b, c) ((c) >= (b)->firstVisibleColumn \
 
71
    && (c) < (b)->firstVisibleColumn + (b)->maxVisibleColumns)
 
72
 
 
73
 
 
74
static void handleEvents(XEvent *event, void *data);
 
75
static void destroyBrowser(WMBrowser *bPtr);
 
76
 
 
77
static void setupScroller(WMBrowser *bPtr);
 
78
 
 
79
static void scrollToColumn(WMBrowser *bPtr, int column, Bool updateScroller);
 
80
 
 
81
static void paintItem(WMList *lPtr, int index, Drawable d, char *text,
 
82
                      int state, WMRect *rect);
 
83
 
 
84
static void loadColumn(WMBrowser *bPtr, int column);
 
85
 
 
86
static void removeColumn(WMBrowser *bPtr, int column);
 
87
 
 
88
static char* createTruncatedString(WMFont *font, char *text, int *textLen,
 
89
                                   int width);
 
90
 
 
91
static void willResizeBrowser(W_ViewDelegate*, WMView*,
 
92
                              unsigned int*, unsigned int*);
 
93
 
 
94
W_ViewDelegate _BrowserViewDelegate = {
 
95
    NULL,
 
96
    NULL,
 
97
    NULL,
 
98
    NULL,
 
99
    willResizeBrowser
 
100
};
 
101
 
 
102
 
 
103
 
 
104
WMBrowser*
 
105
WMCreateBrowser(WMWidget *parent)
 
106
{
 
107
    WMBrowser *bPtr;
 
108
    int i;
 
109
 
 
110
    wassertrv(parent, NULL);
 
111
 
 
112
    bPtr = wmalloc(sizeof(WMBrowser));
 
113
    memset(bPtr, 0, sizeof(WMBrowser));
 
114
 
 
115
    bPtr->widgetClass = WC_Browser;
 
116
 
 
117
    bPtr->view = W_CreateView(W_VIEW(parent));
 
118
    if (!bPtr->view) {
 
119
        wfree(bPtr);
 
120
        return NULL;
 
121
    }
 
122
    bPtr->view->self = bPtr;
 
123
 
 
124
    bPtr->view->delegate = &_BrowserViewDelegate;
 
125
 
 
126
    WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
 
127
                         |ClientMessageMask, handleEvents, bPtr);
 
128
 
 
129
    /* default configuration */
 
130
    bPtr->flags.hasScroller = DEFAULT_HAS_SCROLLER;
 
131
 
 
132
    bPtr->titleHeight = DEFAULT_TITLE_HEIGHT;
 
133
    bPtr->flags.isTitled = DEFAULT_IS_TITLED;
 
134
    bPtr->maxVisibleColumns = DEFAULT_MAX_VISIBLE_COLUMNS;
 
135
 
 
136
    WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
 
137
 
 
138
    bPtr->pathSeparator = wstrdup(DEFAULT_SEPARATOR);
 
139
 
 
140
    if (bPtr->flags.hasScroller)
 
141
        setupScroller(bPtr);
 
142
 
 
143
    for (i=0; i<bPtr->maxVisibleColumns; i++) {
 
144
        WMAddBrowserColumn(bPtr);
 
145
    }
 
146
    bPtr->usedColumnCount = 0;
 
147
 
 
148
    bPtr->selectedColumn = -1;
 
149
 
 
150
    return bPtr;
 
151
}
 
152
 
 
153
 
 
154
void
 
155
WMSetBrowserAllowMultipleSelection(WMBrowser *bPtr, Bool flag)
 
156
{
 
157
    int i;
 
158
 
 
159
    bPtr->flags.allowMultipleSelection = ((flag==0) ? 0 : 1);
 
160
    for (i=0; i<bPtr->columnCount; i++) {
 
161
        WMSetListAllowMultipleSelection(bPtr->columns[i], flag);
 
162
    }
 
163
}
 
164
 
 
165
 
 
166
void
 
167
WMSetBrowserAllowEmptySelection(WMBrowser *bPtr, Bool flag)
 
168
{
 
169
    int i;
 
170
 
 
171
    bPtr->flags.allowEmptySelection = ((flag==0) ? 0 : 1);
 
172
    for (i=0; i<bPtr->columnCount; i++) {
 
173
        WMSetListAllowEmptySelection(bPtr->columns[i], flag);
 
174
    }
 
175
}
 
176
 
 
177
 
 
178
int
 
179
WMGetBrowserMaxVisibleColumns(WMBrowser *bPtr)
 
180
{
 
181
    return bPtr->maxVisibleColumns;
 
182
}
 
183
 
 
184
 
 
185
void
 
186
WMSetBrowserMaxVisibleColumns(WMBrowser *bPtr, int columns)
 
187
{
 
188
    int curMaxVisibleColumns;
 
189
    int newFirstVisibleColumn = 0;
 
190
 
 
191
    assert ((int) bPtr);
 
192
 
 
193
    columns = (columns < MIN_VISIBLE_COLUMNS) ? MIN_VISIBLE_COLUMNS : columns;
 
194
    columns = (columns > MAX_VISIBLE_COLUMNS) ? MAX_VISIBLE_COLUMNS : columns;
 
195
    if (columns == bPtr->maxVisibleColumns) {
 
196
        return;
 
197
    }
 
198
    curMaxVisibleColumns = bPtr->maxVisibleColumns;
 
199
    bPtr->maxVisibleColumns = columns;
 
200
    /* browser not loaded */
 
201
    if (!bPtr->flags.loaded) {
 
202
        if ((columns > curMaxVisibleColumns) && (columns > bPtr->columnCount)) {
 
203
            int i = columns - bPtr->columnCount;
 
204
            bPtr->usedColumnCount = bPtr->columnCount;
 
205
            while (i--) {
 
206
                WMAddBrowserColumn(bPtr);
 
207
            }
 
208
            bPtr->usedColumnCount = 0;
 
209
        }
 
210
        /* browser loaded and columns > curMaxVisibleColumns */
 
211
    } else if (columns > curMaxVisibleColumns) {
 
212
        if (bPtr->usedColumnCount > columns) {
 
213
            newFirstVisibleColumn = bPtr->usedColumnCount - columns;
 
214
        }
 
215
        if (newFirstVisibleColumn > bPtr->firstVisibleColumn) {
 
216
            newFirstVisibleColumn = bPtr->firstVisibleColumn;
 
217
        }
 
218
        if (columns > bPtr->columnCount) {
 
219
            int i = columns - bPtr->columnCount;
 
220
            int curUsedColumnCount = bPtr->usedColumnCount;
 
221
            bPtr->usedColumnCount = bPtr->columnCount;
 
222
            while (i--) {
 
223
                WMAddBrowserColumn(bPtr);
 
224
            }
 
225
            bPtr->usedColumnCount = curUsedColumnCount;
 
226
        }
 
227
        /* browser loaded and columns < curMaxVisibleColumns */
 
228
    } else {
 
229
        newFirstVisibleColumn = bPtr->firstVisibleColumn;
 
230
        if (newFirstVisibleColumn + columns >= bPtr->usedColumnCount) {
 
231
            removeColumn(bPtr, newFirstVisibleColumn + columns);
 
232
        }
 
233
    }
 
234
    WMResizeWidget(bPtr, bPtr->view->size.width, bPtr->view->size.height);
 
235
    if (bPtr->flags.loaded) {
 
236
        XClearArea(bPtr->view->screen->display, bPtr->view->window, 0, 0,
 
237
                   bPtr->view->size.width, bPtr->titleHeight, False);
 
238
        scrollToColumn (bPtr, newFirstVisibleColumn, True);
 
239
    }
 
240
}
 
241
 
 
242
 
 
243
int
 
244
WMGetBrowserNumberOfColumns(WMBrowser *bPtr)
 
245
{
 
246
    return bPtr->usedColumnCount;
 
247
}
 
248
 
 
249
void
 
250
WMSetBrowserPathSeparator(WMBrowser *bPtr, char *separator)
 
251
{
 
252
    if (bPtr->pathSeparator)
 
253
        wfree(bPtr->pathSeparator);
 
254
    bPtr->pathSeparator = wstrdup(separator);
 
255
}
 
256
 
 
257
 
 
258
 
 
259
static void
 
260
drawTitleOfColumn(WMBrowser *bPtr, int column)
 
261
{
 
262
    WMScreen *scr = bPtr->view->screen;
 
263
    int x;
 
264
 
 
265
    x=(column-bPtr->firstVisibleColumn)*(bPtr->columnSize.width+COLUMN_SPACING);
 
266
 
 
267
    XFillRectangle(scr->display, bPtr->view->window, WMColorGC(scr->darkGray), x, 0,
 
268
                   bPtr->columnSize.width, bPtr->titleHeight);
 
269
    W_DrawRelief(scr, bPtr->view->window, x, 0,
 
270
                 bPtr->columnSize.width, bPtr->titleHeight, WRSunken);
 
271
 
 
272
    if (column < bPtr->usedColumnCount && bPtr->titles[column]) {
 
273
        int titleLen = strlen(bPtr->titles[column]);
 
274
        int widthC = bPtr->columnSize.width-8;
 
275
 
 
276
        if (WMWidthOfString(scr->boldFont, bPtr->titles[column], titleLen)
 
277
            > widthC) {
 
278
            char *titleBuf = createTruncatedString(scr->boldFont,
 
279
                                                   bPtr->titles[column],
 
280
                                                   &titleLen, widthC);
 
281
            W_PaintText(bPtr->view, bPtr->view->window, scr->boldFont, x,
 
282
                        (bPtr->titleHeight-WMFontHeight(scr->boldFont))/2,
 
283
                        bPtr->columnSize.width, WACenter, scr->white,
 
284
                        False, titleBuf, titleLen);
 
285
            wfree (titleBuf);
 
286
        } else {
 
287
            W_PaintText(bPtr->view, bPtr->view->window, scr->boldFont, x,
 
288
                        (bPtr->titleHeight-WMFontHeight(scr->boldFont))/2,
 
289
                        bPtr->columnSize.width, WACenter, scr->white,
 
290
                        False, bPtr->titles[column], titleLen);
 
291
        }
 
292
    }
 
293
}
 
294
 
 
295
 
 
296
WMList*
 
297
WMGetBrowserListInColumn(WMBrowser *bPtr, int column)
 
298
{
 
299
    if (column < 0 || column >= bPtr->usedColumnCount)
 
300
        return NULL;
 
301
 
 
302
    return bPtr->columns[column];
 
303
}
 
304
 
 
305
 
 
306
void
 
307
WMSetBrowserDelegate(WMBrowser *bPtr, WMBrowserDelegate *delegate)
 
308
{
 
309
    bPtr->delegate = delegate;
 
310
}
 
311
 
 
312
 
 
313
int
 
314
WMGetBrowserFirstVisibleColumn(WMBrowser *bPtr)
 
315
{
 
316
    return bPtr->firstVisibleColumn;
 
317
}
 
318
 
 
319
 
 
320
static void
 
321
removeColumn(WMBrowser *bPtr, int column)
 
322
{
 
323
    int i, clearEnd, destroyEnd;
 
324
    WMList **clist;
 
325
    char **tlist;
 
326
 
 
327
    assert ((int) bPtr);
 
328
 
 
329
    column = (column < 0) ? 0 : column;
 
330
    if (column >= bPtr->columnCount) {
 
331
        return;
 
332
    }
 
333
    if (column < bPtr->maxVisibleColumns) {
 
334
        clearEnd = bPtr->maxVisibleColumns;
 
335
        destroyEnd = bPtr->columnCount;
 
336
        bPtr->columnCount = bPtr->maxVisibleColumns;
 
337
    } else {
 
338
        clearEnd = column;
 
339
        destroyEnd = bPtr->columnCount;
 
340
        bPtr->columnCount = column;
 
341
    }
 
342
    if (column < bPtr->usedColumnCount) {
 
343
        bPtr->usedColumnCount = column;
 
344
    }
 
345
    for (i=column; i < clearEnd; i++) {
 
346
        if (bPtr->titles[i]) {
 
347
            wfree(bPtr->titles[i]);
 
348
            bPtr->titles[i] = NULL;
 
349
        }
 
350
        WMClearList(bPtr->columns[i]);
 
351
    }
 
352
    for (;i < destroyEnd; i++) {
 
353
        if (bPtr->titles[i]) {
 
354
            wfree(bPtr->titles[i]);
 
355
            bPtr->titles[i] = NULL;
 
356
        }
 
357
        WMRemoveNotificationObserverWithName(bPtr,
 
358
                                             WMListSelectionDidChangeNotification,
 
359
                                             bPtr->columns[i]);
 
360
        WMDestroyWidget(bPtr->columns[i]);
 
361
        bPtr->columns[i] = NULL;
 
362
    }
 
363
    clist = wmalloc(sizeof(WMList*) * (bPtr->columnCount));
 
364
    tlist = wmalloc(sizeof(char*) * (bPtr->columnCount));
 
365
    memcpy(clist, bPtr->columns, sizeof(WMList*) * (bPtr->columnCount));
 
366
    memcpy(tlist, bPtr->titles, sizeof(char*) * (bPtr->columnCount));
 
367
    wfree(bPtr->titles);
 
368
    wfree(bPtr->columns);
 
369
    bPtr->titles = tlist;
 
370
    bPtr->columns = clist;
 
371
}
 
372
 
 
373
 
 
374
WMListItem*
 
375
WMGetBrowserSelectedItemInColumn(WMBrowser *bPtr, int column)
 
376
{
 
377
    if ((column < 0) || (column >= bPtr->usedColumnCount))
 
378
        return NULL;
 
379
 
 
380
    return WMGetListSelectedItem(bPtr->columns[column]);
 
381
}
 
382
 
 
383
 
 
384
 
 
385
int
 
386
WMGetBrowserSelectedColumn(WMBrowser *bPtr)
 
387
{
 
388
    return bPtr->selectedColumn;
 
389
}
 
390
 
 
391
 
 
392
int
 
393
WMGetBrowserSelectedRowInColumn(WMBrowser *bPtr, int column)
 
394
{
 
395
    if (column >= 0 && column < bPtr->columnCount) {
 
396
        return WMGetListSelectedItemRow(bPtr->columns[column]);
 
397
    } else {
 
398
        return -1;
 
399
    }
 
400
}
 
401
 
 
402
 
 
403
void
 
404
WMSetBrowserColumnTitle(WMBrowser *bPtr, int column, char *title)
 
405
{
 
406
    assert(column >= 0);
 
407
    assert(column < bPtr->usedColumnCount);
 
408
 
 
409
    if (bPtr->titles[column])
 
410
        wfree(bPtr->titles[column]);
 
411
 
 
412
    bPtr->titles[column] = wstrdup(title);
 
413
 
 
414
    if (COLUMN_IS_VISIBLE(bPtr, column) && bPtr->flags.isTitled) {
 
415
        drawTitleOfColumn(bPtr, column);
 
416
    }
 
417
}
 
418
 
 
419
 
 
420
void
 
421
WMSetBrowserTitled(WMBrowser *bPtr, Bool flag)
 
422
{
 
423
    int i;
 
424
    int columnX, columnY;
 
425
 
 
426
    flag = ((flag==0) ? 0 : 1);
 
427
 
 
428
    if (bPtr->flags.isTitled == flag)
 
429
        return;
 
430
 
 
431
    columnX = 0;
 
432
 
 
433
    if (!bPtr->flags.isTitled) {
 
434
        columnY = TITLE_SPACING + bPtr->titleHeight;
 
435
 
 
436
        bPtr->columnSize.height -= columnY;
 
437
 
 
438
        for (i=0; i<bPtr->columnCount; i++) {
 
439
            WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
 
440
                           bPtr->columnSize.height);
 
441
 
 
442
            columnX = WMWidgetView(bPtr->columns[i])->pos.x;
 
443
 
 
444
            WMMoveWidget(bPtr->columns[i], columnX, columnY);
 
445
        }
 
446
    } else {
 
447
        bPtr->columnSize.height += TITLE_SPACING + bPtr->titleHeight;
 
448
 
 
449
        for (i=0; i<bPtr->columnCount; i++) {
 
450
            WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
 
451
                           bPtr->columnSize.height);
 
452
 
 
453
            columnX = WMWidgetView(bPtr->columns[i])->pos.x;
 
454
 
 
455
            WMMoveWidget(bPtr->columns[i], columnX, 0);
 
456
        }
 
457
    }
 
458
 
 
459
    bPtr->flags.isTitled = flag;
 
460
}
 
461
 
 
462
 
 
463
void
 
464
WMSortBrowserColumn(WMBrowser *bPtr, int column)
 
465
{
 
466
    WMSortListItems(bPtr->columns[column]);
 
467
}
 
468
 
 
469
 
 
470
void
 
471
WMSortBrowserColumnWithComparer(WMBrowser *bPtr, int column,
 
472
                                WMCompareDataProc *func)
 
473
{
 
474
    WMSortListItemsWithComparer(bPtr->columns[column], func);
 
475
}
 
476
 
 
477
 
 
478
 
 
479
WMListItem*
 
480
WMInsertBrowserItem(WMBrowser *bPtr, int column, int row, char *text,
 
481
                    Bool isBranch)
 
482
{
 
483
    WMListItem *item;
 
484
 
 
485
    if (column < 0 || column >= bPtr->columnCount)
 
486
        return NULL;
 
487
 
 
488
    item = WMInsertListItem(bPtr->columns[column], row, text);
 
489
    item->isBranch = isBranch;
 
490
 
 
491
    return item;
 
492
}
 
493
 
 
494
 
 
495
 
 
496
 
 
497
static void
 
498
willResizeBrowser(W_ViewDelegate *self, WMView *view,
 
499
                  unsigned int *width, unsigned int *height)
 
500
{
 
501
    WMBrowser *bPtr = (WMBrowser*)view->self;
 
502
    int cols = bPtr->maxVisibleColumns;
 
503
    int colX, colY;
 
504
    int i;
 
505
 
 
506
    assert(*width > 0);
 
507
    assert(*height > 0);
 
508
 
 
509
    bPtr->columnSize.width = (*width-(cols-1)*COLUMN_SPACING) / cols;
 
510
    bPtr->columnSize.height = *height;
 
511
 
 
512
    if (bPtr->flags.isTitled) {
 
513
        colY = TITLE_SPACING + bPtr->titleHeight;
 
514
        bPtr->columnSize.height -= colY;
 
515
    } else {
 
516
        colY = 0;
 
517
    }
 
518
 
 
519
    if (bPtr->flags.hasScroller) {
 
520
        bPtr->columnSize.height -= SCROLLER_WIDTH + 4;
 
521
 
 
522
        if (bPtr->scroller) {
 
523
            WMResizeWidget(bPtr->scroller, *width-2, 1);
 
524
            WMMoveWidget(bPtr->scroller, 1, *height-SCROLLER_WIDTH-1);
 
525
        }
 
526
    }
 
527
 
 
528
    colX = 0;
 
529
    for (i = 0; i < bPtr->columnCount; i++) {
 
530
        WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
 
531
                       bPtr->columnSize.height);
 
532
 
 
533
        WMMoveWidget(bPtr->columns[i], colX, colY);
 
534
 
 
535
        if (COLUMN_IS_VISIBLE(bPtr, i)) {
 
536
            colX += bPtr->columnSize.width+COLUMN_SPACING;
 
537
        }
 
538
    }
 
539
}
 
540
 
 
541
 
 
542
static void
 
543
paintItem(WMList *lPtr, int index, Drawable d, char *text, int state, WMRect *rect)
 
544
{
 
545
    WMView *view = W_VIEW(lPtr);
 
546
    W_Screen *scr = view->screen;
 
547
    Display *display = scr->display;
 
548
    WMFont *font = ((state & WLDSIsBranch) ? scr->boldFont : scr->normalFont);
 
549
    WMColor *backColor = ((state & WLDSSelected) ? scr->white : view->backColor);
 
550
    int width, height, x, y, textLen;
 
551
 
 
552
    width = rect->size.width;
 
553
    height = rect->size.height;
 
554
    x = rect->pos.x;
 
555
    y = rect->pos.y;
 
556
    textLen = strlen(text);
 
557
 
 
558
    XFillRectangle(display, d, WMColorGC(backColor), x, y, width, height);
 
559
 
 
560
    if (text) {
 
561
        /* Avoid overlaping... */
 
562
        int widthC = (state & WLDSIsBranch) ? width-20 : width-8;
 
563
        if (WMWidthOfString(font, text, textLen) > widthC) {
 
564
            char *textBuf = createTruncatedString(font, text, &textLen, widthC);
 
565
            W_PaintText(view, d, font,  x+4, y, widthC,
 
566
                        WALeft, scr->black, False, textBuf, textLen);
 
567
            wfree(textBuf);
 
568
        } else {
 
569
            W_PaintText(view, d, font,  x+4, y, widthC,
 
570
                        WALeft, scr->black, False, text, textLen);
 
571
        }
 
572
    }
 
573
 
 
574
    if (state & WLDSIsBranch) {
 
575
        WMColor *lineColor = ((state & WLDSSelected) ? scr->gray : scr->white);
 
576
 
 
577
        XDrawLine(display, d, WMColorGC(scr->darkGray), x+width-11, y+3,
 
578
                  x+width-6, y+height/2);
 
579
        XDrawLine(display, d, WMColorGC(lineColor), x+width-11, y+height-5,
 
580
                  x+width-6, y+height/2);
 
581
        XDrawLine(display, d, WMColorGC(scr->black), x+width-12, y+3,
 
582
                  x+width-12, y+height-5);
 
583
    }
 
584
}
 
585
 
 
586
 
 
587
static void
 
588
scrollCallback(WMWidget *scroller, void *self)
 
589
{
 
590
    WMBrowser *bPtr = (WMBrowser*)self;
 
591
    WMScroller *sPtr = (WMScroller*)scroller;
 
592
    int newFirst;
 
593
#define LAST_VISIBLE_COLUMN  bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
 
594
 
 
595
    switch (WMGetScrollerHitPart(sPtr)) {
 
596
    case WSDecrementLine:
 
597
        if (bPtr->firstVisibleColumn > 0) {
 
598
            scrollToColumn(bPtr, bPtr->firstVisibleColumn-1, True);
 
599
        }
 
600
        break;
 
601
 
 
602
    case WSDecrementPage:
 
603
    case WSDecrementWheel:
 
604
        if (bPtr->firstVisibleColumn > 0) {
 
605
            newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
 
606
 
 
607
            scrollToColumn(bPtr, newFirst, True);
 
608
        }
 
609
        break;
 
610
 
 
611
 
 
612
    case WSIncrementLine:
 
613
        if (LAST_VISIBLE_COLUMN < bPtr->usedColumnCount) {
 
614
            scrollToColumn(bPtr, bPtr->firstVisibleColumn+1, True);
 
615
        }
 
616
        break;
 
617
 
 
618
    case WSIncrementPage:
 
619
    case WSIncrementWheel:
 
620
        if (LAST_VISIBLE_COLUMN < bPtr->usedColumnCount) {
 
621
            newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
 
622
 
 
623
            if (newFirst+bPtr->maxVisibleColumns >= bPtr->columnCount)
 
624
                newFirst = bPtr->columnCount - bPtr->maxVisibleColumns;
 
625
 
 
626
            scrollToColumn(bPtr, newFirst, True);
 
627
        }
 
628
        break;
 
629
 
 
630
    case WSKnob:
 
631
        {
 
632
            double floatValue;
 
633
            double value = bPtr->columnCount - bPtr->maxVisibleColumns;
 
634
 
 
635
            floatValue = WMGetScrollerValue(bPtr->scroller);
 
636
 
 
637
            floatValue = (floatValue*value)/value;
 
638
 
 
639
            newFirst = rint(floatValue*(float)(bPtr->columnCount - bPtr->maxVisibleColumns));
 
640
 
 
641
            if (bPtr->firstVisibleColumn != newFirst)
 
642
                scrollToColumn(bPtr, newFirst, False);
 
643
            /*else
 
644
             WMSetScrollerParameters(bPtr->scroller, floatValue,
 
645
             bPtr->maxVisibleColumns/(float)bPtr->columnCount);
 
646
             */
 
647
 
 
648
        }
 
649
        break;
 
650
 
 
651
    case WSKnobSlot:
 
652
    case WSNoPart:
 
653
        /* do nothing */
 
654
        break;
 
655
    }
 
656
#undef LAST_VISIBLE_COLUMN
 
657
}
 
658
 
 
659
 
 
660
static void
 
661
setupScroller(WMBrowser *bPtr)
 
662
{
 
663
    WMScroller *sPtr;
 
664
    int y;
 
665
 
 
666
    y = bPtr->view->size.height - SCROLLER_WIDTH - 1;
 
667
 
 
668
    sPtr = WMCreateScroller(bPtr);
 
669
    WMSetScrollerAction(sPtr, scrollCallback, bPtr);
 
670
    WMMoveWidget(sPtr, 1, y);
 
671
    WMResizeWidget(sPtr, bPtr->view->size.width-2, SCROLLER_WIDTH);
 
672
 
 
673
    bPtr->scroller = sPtr;
 
674
 
 
675
    WMMapWidget(sPtr);
 
676
}
 
677
 
 
678
 
 
679
void
 
680
WMSetBrowserAction(WMBrowser *bPtr, WMAction *action, void *clientData)
 
681
{
 
682
    bPtr->action = action;
 
683
    bPtr->clientData = clientData;
 
684
}
 
685
 
 
686
 
 
687
void
 
688
WMSetBrowserDoubleAction(WMBrowser *bPtr, WMAction *action, void *clientData)
 
689
{
 
690
    bPtr->doubleAction = action;
 
691
    bPtr->doubleClientData = clientData;
 
692
}
 
693
 
 
694
 
 
695
void
 
696
WMSetBrowserHasScroller(WMBrowser *bPtr, int hasScroller)
 
697
{
 
698
    bPtr->flags.hasScroller = hasScroller;
 
699
}
 
700
 
 
701
 
 
702
char*
 
703
WMSetBrowserPath(WMBrowser *bPtr, char *path)
 
704
{
 
705
    int i;
 
706
    char *str;
 
707
    char *tmp, *retPtr = NULL;
 
708
    int item;
 
709
    WMListItem *listItem;
 
710
 
 
711
    /* WMLoadBrowserColumnZero must be call first */
 
712
    if (!bPtr->flags.loaded) {
 
713
        return False;
 
714
    }
 
715
 
 
716
    removeColumn(bPtr, 1);
 
717
 
 
718
    WMSelectListItem(bPtr->columns[0], -1);
 
719
    WMSetListPosition(bPtr->columns[0], 0);
 
720
 
 
721
    i = 0;
 
722
    str = wstrdup(path);
 
723
    tmp = strtok(str, bPtr->pathSeparator);
 
724
    while (tmp) {
 
725
        /* select it in the column */
 
726
        item = WMFindRowOfListItemWithTitle(bPtr->columns[i], tmp);
 
727
        if (item<0) {
 
728
            retPtr = &path[(int)(tmp - str)];
 
729
            break;
 
730
        }
 
731
        WMSelectListItem(bPtr->columns[i], item);
 
732
        WMSetListPosition(bPtr->columns[i], item);
 
733
 
 
734
        listItem = WMGetListItem(bPtr->columns[i], item);
 
735
        if (!listItem || !listItem->isBranch) {
 
736
            break;
 
737
        }
 
738
 
 
739
        /* load next column */
 
740
        WMAddBrowserColumn(bPtr);
 
741
 
 
742
        loadColumn(bPtr, i+1);
 
743
 
 
744
        tmp = strtok(NULL, bPtr->pathSeparator);
 
745
 
 
746
        i++;
 
747
    }
 
748
 
 
749
    wfree(str);
 
750
 
 
751
    for (i = bPtr->usedColumnCount - 1;
 
752
         (i > -1) && !WMGetListSelectedItem(bPtr->columns[i]);
 
753
         i--);
 
754
 
 
755
    bPtr->selectedColumn = i;
 
756
 
 
757
    if (bPtr->columnCount < bPtr->maxVisibleColumns) {
 
758
        int i = bPtr->maxVisibleColumns - bPtr->columnCount;
 
759
        int curUsedColumnCount = bPtr->usedColumnCount;
 
760
        bPtr->usedColumnCount = bPtr->columnCount;
 
761
        while (i--) {
 
762
            WMAddBrowserColumn(bPtr);
 
763
        }
 
764
        bPtr->usedColumnCount = curUsedColumnCount;
 
765
    }
 
766
 
 
767
    scrollToColumn(bPtr, bPtr->columnCount - bPtr->maxVisibleColumns, True);
 
768
 
 
769
    return retPtr;
 
770
}
 
771
 
 
772
 
 
773
char*
 
774
WMGetBrowserPath(WMBrowser *bPtr)
 
775
{
 
776
    return WMGetBrowserPathToColumn(bPtr, bPtr->columnCount);
 
777
}
 
778
 
 
779
 
 
780
char*
 
781
WMGetBrowserPathToColumn(WMBrowser *bPtr, int column)
 
782
{
 
783
    int i, size;
 
784
    char *path;
 
785
    WMListItem *item;
 
786
 
 
787
    if (column >= bPtr->usedColumnCount)
 
788
        column = bPtr->usedColumnCount-1;
 
789
 
 
790
    if (column < 0) {
 
791
        return wstrdup(bPtr->pathSeparator);
 
792
    }
 
793
 
 
794
    /* calculate size of buffer */
 
795
    size = 0;
 
796
    for (i = 0; i <= column; i++) {
 
797
        item = WMGetListSelectedItem(bPtr->columns[i]);
 
798
        if (!item)
 
799
            break;
 
800
        size += strlen(item->text);
 
801
    }
 
802
 
 
803
    /* get the path */
 
804
    path = wmalloc(size+(column+1)*strlen(bPtr->pathSeparator)+1);
 
805
    /* ignore first / */
 
806
    *path = 0;
 
807
    for (i = 0; i <= column; i++) {
 
808
        strcat(path, bPtr->pathSeparator);
 
809
        item = WMGetListSelectedItem(bPtr->columns[i]);
 
810
        if (!item)
 
811
            break;
 
812
        strcat(path, item->text);
 
813
    }
 
814
 
 
815
    return path;
 
816
}
 
817
 
 
818
 
 
819
WMArray*
 
820
WMGetBrowserPaths(WMBrowser *bPtr)
 
821
{
 
822
    int column, i, k, size, selNo;
 
823
    char *path;
 
824
    WMListItem *item, *lastItem;
 
825
    WMArray *paths, *items;
 
826
 
 
827
    column = bPtr->usedColumnCount-1;
 
828
 
 
829
    if (column < 0) {
 
830
        paths = WMCreateArrayWithDestructor(1, wfree);
 
831
        WMAddToArray(paths, wstrdup(bPtr->pathSeparator));
 
832
        return paths;
 
833
    }
 
834
 
 
835
    items = WMGetListSelectedItems(bPtr->columns[column]);
 
836
    selNo = WMGetArrayItemCount(items);
 
837
    paths = WMCreateArrayWithDestructor(selNo, wfree);
 
838
 
 
839
    if (selNo <= 1) {
 
840
        WMAddToArray(paths, WMGetBrowserPath(bPtr));
 
841
        return paths;
 
842
    }
 
843
 
 
844
    /* calculate size of buffer */
 
845
    size = 0;
 
846
    for (i=0; i<column; i++) {
 
847
        item = WMGetListSelectedItem(bPtr->columns[i]);
 
848
        if (!item)
 
849
            break;
 
850
        size += strlen(item->text);
 
851
    }
 
852
 
 
853
    size += (column+1)*strlen(bPtr->pathSeparator)+1;
 
854
 
 
855
    for (k=0; k<selNo; k++) {
 
856
        /* get the path */
 
857
        lastItem = WMGetFromArray(items, k);
 
858
        path = wmalloc(size + (lastItem!=NULL ?  strlen(lastItem->text) : 0));
 
859
        /* ignore first / */
 
860
        *path = 0;
 
861
        for (i=0; i<=column; i++) {
 
862
            strcat(path, bPtr->pathSeparator);
 
863
            if (i == column) {
 
864
                item = lastItem;
 
865
            } else {
 
866
                item = WMGetListSelectedItem(bPtr->columns[i]);
 
867
            }
 
868
            if (!item)
 
869
                break;
 
870
            strcat(path, item->text);
 
871
        }
 
872
        WMAddToArray(paths, path);
 
873
    }
 
874
 
 
875
    return paths;
 
876
}
 
877
 
 
878
 
 
879
Bool
 
880
WMBrowserAllowsMultipleSelection(WMBrowser *bPtr)
 
881
{
 
882
    return bPtr->flags.allowMultipleSelection;
 
883
}
 
884
 
 
885
 
 
886
Bool
 
887
WMBrowserAllowsEmptySelection(WMBrowser *bPtr)
 
888
{
 
889
    return bPtr->flags.allowEmptySelection;
 
890
}
 
891
 
 
892
 
 
893
static void
 
894
loadColumn(WMBrowser *bPtr, int column)
 
895
{
 
896
    assert(bPtr->delegate);
 
897
    assert(bPtr->delegate->createRowsForColumn);
 
898
 
 
899
    bPtr->flags.loadingColumn = 1;
 
900
    (*bPtr->delegate->createRowsForColumn)(bPtr->delegate, bPtr, column,
 
901
                                           bPtr->columns[column]);
 
902
    bPtr->flags.loadingColumn = 0;
 
903
 
 
904
    if (bPtr->delegate->titleOfColumn) {
 
905
        char *title;
 
906
 
 
907
        title = (*bPtr->delegate->titleOfColumn)(bPtr->delegate, bPtr, column);
 
908
 
 
909
        if (bPtr->titles[column])
 
910
            wfree(bPtr->titles[column]);
 
911
 
 
912
        bPtr->titles[column] = wstrdup(title);
 
913
 
 
914
        if (COLUMN_IS_VISIBLE(bPtr, column) && bPtr->flags.isTitled) {
 
915
            drawTitleOfColumn(bPtr, column);
 
916
        }
 
917
    }
 
918
}
 
919
 
 
920
 
 
921
static void
 
922
paintBrowser(WMBrowser *bPtr)
 
923
{
 
924
    int i;
 
925
 
 
926
    if (!bPtr->view->flags.mapped)
 
927
        return;
 
928
 
 
929
    W_DrawRelief(bPtr->view->screen, bPtr->view->window, 0,
 
930
                 bPtr->view->size.height-SCROLLER_WIDTH-2,
 
931
                 bPtr->view->size.width, 22, WRSunken);
 
932
 
 
933
    if (bPtr->flags.isTitled) {
 
934
        for (i=0; i<bPtr->maxVisibleColumns; i++) {
 
935
            drawTitleOfColumn(bPtr, i+bPtr->firstVisibleColumn);
 
936
        }
 
937
    }
 
938
}
 
939
 
 
940
 
 
941
static void
 
942
handleEvents(XEvent *event, void *data)
 
943
{
 
944
    WMBrowser *bPtr = (WMBrowser*)data;
 
945
 
 
946
    CHECK_CLASS(data, WC_Browser);
 
947
 
 
948
 
 
949
    switch (event->type) {
 
950
    case Expose:
 
951
        paintBrowser(bPtr);
 
952
        break;
 
953
 
 
954
    case DestroyNotify:
 
955
        destroyBrowser(bPtr);
 
956
        break;
 
957
 
 
958
    }
 
959
}
 
960
 
 
961
 
 
962
 
 
963
static void
 
964
scrollToColumn(WMBrowser *bPtr, int column, Bool updateScroller)
 
965
{
 
966
    int i;
 
967
    int x;
 
968
    int notify = 0;
 
969
 
 
970
 
 
971
    if (column != bPtr->firstVisibleColumn) {
 
972
        notify = 1;
 
973
    }
 
974
 
 
975
    if (column < 0)
 
976
        column = 0;
 
977
 
 
978
    if (notify && bPtr->delegate && bPtr->delegate->willScroll) {
 
979
        (*bPtr->delegate->willScroll)(bPtr->delegate, bPtr);
 
980
    }
 
981
 
 
982
    x = 0;
 
983
    bPtr->firstVisibleColumn = column;
 
984
    for (i = 0; i < bPtr->columnCount; i++) {
 
985
        if (COLUMN_IS_VISIBLE(bPtr, i)) {
 
986
            WMMoveWidget(bPtr->columns[i], x,
 
987
                         WMWidgetView(bPtr->columns[i])->pos.y);
 
988
            if (!WMWidgetView(bPtr->columns[i])->flags.realized)
 
989
                WMRealizeWidget(bPtr->columns[i]);
 
990
            WMMapWidget(bPtr->columns[i]);
 
991
            x += bPtr->columnSize.width + COLUMN_SPACING;
 
992
        } else {
 
993
            WMUnmapWidget(bPtr->columns[i]);
 
994
        }
 
995
    }
 
996
 
 
997
    /* update the scroller */
 
998
    if (updateScroller) {
 
999
        if (bPtr->columnCount > bPtr->maxVisibleColumns) {
 
1000
            float value, proportion;
 
1001
 
 
1002
            value = bPtr->firstVisibleColumn
 
1003
                /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
 
1004
            proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
 
1005
            WMSetScrollerParameters(bPtr->scroller, value, proportion);
 
1006
        } else {
 
1007
            WMSetScrollerParameters(bPtr->scroller, 0, 1);
 
1008
        }
 
1009
    }
 
1010
 
 
1011
    if (bPtr->view->flags.mapped)
 
1012
        paintBrowser(bPtr);
 
1013
 
 
1014
    if (notify && bPtr->delegate && bPtr->delegate->didScroll) {
 
1015
        (*bPtr->delegate->didScroll)(bPtr->delegate, bPtr);
 
1016
    }
 
1017
}
 
1018
 
 
1019
 
 
1020
static void
 
1021
listCallback(void *self, void *clientData)
 
1022
{
 
1023
    WMBrowser *bPtr = (WMBrowser*)clientData;
 
1024
    WMList *lPtr = (WMList*)self;
 
1025
    WMListItem *item;
 
1026
    int i, selNo;
 
1027
    static WMListItem *oldItem = NULL;
 
1028
    static int oldSelNo = 0;
 
1029
 
 
1030
    item = WMGetListSelectedItem(lPtr);
 
1031
    selNo = WMGetArrayItemCount(WMGetListSelectedItems(lPtr));
 
1032
 
 
1033
    if (oldItem==NULL || oldItem!=item || oldSelNo!=selNo) {
 
1034
        for (i=0; i<bPtr->columnCount; i++) {
 
1035
            if (lPtr == bPtr->columns[i])
 
1036
                break;
 
1037
        }
 
1038
        assert(i<bPtr->columnCount);
 
1039
 
 
1040
        bPtr->selectedColumn = i;
 
1041
 
 
1042
        /* columns at right must be cleared */
 
1043
        removeColumn(bPtr, i+1);
 
1044
        /* open directory */
 
1045
        if (item && item->isBranch && selNo==1) {
 
1046
            WMAddBrowserColumn(bPtr);
 
1047
        }
 
1048
        if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
 
1049
            i = 0;
 
1050
        else
 
1051
            i = bPtr->usedColumnCount-bPtr->maxVisibleColumns;
 
1052
        scrollToColumn(bPtr, i, True);
 
1053
        if (item && item->isBranch && selNo==1) {
 
1054
            loadColumn(bPtr, bPtr->usedColumnCount-1);
 
1055
        }
 
1056
    }
 
1057
 
 
1058
    /* call callback for click */
 
1059
    if (bPtr->action)
 
1060
        (*bPtr->action)(bPtr, bPtr->clientData);
 
1061
 
 
1062
    oldItem = item;
 
1063
    oldSelNo = selNo;
 
1064
}
 
1065
 
 
1066
 
 
1067
static void
 
1068
listDoubleCallback(void *self, void *clientData)
 
1069
{
 
1070
    WMBrowser *bPtr = (WMBrowser*)clientData;
 
1071
    WMList *lPtr = (WMList*)self;
 
1072
    WMListItem *item;
 
1073
 
 
1074
    item = WMGetListSelectedItem(lPtr);
 
1075
    if (!item)
 
1076
        return;
 
1077
 
 
1078
    /* call callback for double click */
 
1079
    if (bPtr->doubleAction)
 
1080
        (*bPtr->doubleAction)(bPtr, bPtr->doubleClientData);
 
1081
}
 
1082
 
 
1083
 
 
1084
void
 
1085
WMLoadBrowserColumnZero(WMBrowser *bPtr)
 
1086
{
 
1087
    if (!bPtr->flags.loaded) {
 
1088
        /* create column 0 */
 
1089
        WMAddBrowserColumn(bPtr);
 
1090
 
 
1091
        loadColumn(bPtr, 0);
 
1092
 
 
1093
        /* make column 0 visible */
 
1094
        scrollToColumn(bPtr, 0, True);
 
1095
 
 
1096
        bPtr->flags.loaded = 1;
 
1097
    }
 
1098
}
 
1099
 
 
1100
 
 
1101
void
 
1102
WMRemoveBrowserItem(WMBrowser *bPtr, int column, int row)
 
1103
{
 
1104
    WMList *list;
 
1105
 
 
1106
    if (column < 0 || column >= bPtr->usedColumnCount)
 
1107
        return;
 
1108
 
 
1109
    list = WMGetBrowserListInColumn(bPtr, column);
 
1110
 
 
1111
    if (row < 0 || row >= WMGetListNumberOfRows(list))
 
1112
        return;
 
1113
 
 
1114
    removeColumn(bPtr, column+1);
 
1115
    if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
 
1116
        scrollToColumn(bPtr, 0, True);
 
1117
    else
 
1118
        scrollToColumn(bPtr, bPtr->usedColumnCount-bPtr->maxVisibleColumns,
 
1119
                       True);
 
1120
 
 
1121
    WMRemoveListItem(list, row);
 
1122
}
 
1123
 
 
1124
 
 
1125
static void
 
1126
listSelectionObserver(void *observerData, WMNotification *notification)
 
1127
{
 
1128
    WMBrowser *bPtr = (WMBrowser*)observerData;
 
1129
    int column;
 
1130
    WMList *lPtr = (WMList*)WMGetNotificationObject(notification);
 
1131
 
 
1132
    for (column = 0; column < bPtr->usedColumnCount; column++)
 
1133
        if (bPtr->columns[column] == lPtr)
 
1134
            break;
 
1135
 
 
1136
    /* this can happen when a list is being cleared with WMClearList
 
1137
     * after the column was removed */
 
1138
    if (column >= bPtr->usedColumnCount) {
 
1139
        return;
 
1140
    }
 
1141
 
 
1142
    if (WMGetArrayItemCount(WMGetListSelectedItems(lPtr)) == 0)
 
1143
        column--;
 
1144
 
 
1145
    bPtr->selectedColumn = column;
 
1146
}
 
1147
 
 
1148
 
 
1149
int
 
1150
WMAddBrowserColumn(WMBrowser *bPtr)
 
1151
{
 
1152
    WMList *list;
 
1153
    WMList **clist;
 
1154
    char **tlist;
 
1155
    int colY;
 
1156
    int index;
 
1157
 
 
1158
 
 
1159
    if (bPtr->usedColumnCount < bPtr->columnCount) {
 
1160
        return bPtr->usedColumnCount++;
 
1161
    }
 
1162
 
 
1163
    bPtr->usedColumnCount++;
 
1164
 
 
1165
    if (bPtr->flags.isTitled) {
 
1166
        colY = TITLE_SPACING + bPtr->titleHeight;
 
1167
    } else {
 
1168
        colY = 0;
 
1169
    }
 
1170
 
 
1171
    index = bPtr->columnCount;
 
1172
    bPtr->columnCount++;
 
1173
    clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
 
1174
    tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
 
1175
    memcpy(clist, bPtr->columns, sizeof(WMList*)*(bPtr->columnCount-1));
 
1176
    memcpy(tlist, bPtr->titles, sizeof(char*)*(bPtr->columnCount-1));
 
1177
    if (bPtr->columns)
 
1178
        wfree(bPtr->columns);
 
1179
    if (bPtr->titles)
 
1180
        wfree(bPtr->titles);
 
1181
    bPtr->columns = clist;
 
1182
    bPtr->titles = tlist;
 
1183
 
 
1184
    bPtr->titles[index] = NULL;
 
1185
 
 
1186
    list = WMCreateList(bPtr);
 
1187
    WMSetListAllowMultipleSelection(list, bPtr->flags.allowMultipleSelection);
 
1188
    WMSetListAllowEmptySelection(list, bPtr->flags.allowEmptySelection);
 
1189
    WMSetListAction(list, listCallback, bPtr);
 
1190
    WMSetListDoubleAction(list, listDoubleCallback, bPtr);
 
1191
    WMSetListUserDrawProc(list, paintItem);
 
1192
    WMAddNotificationObserver(listSelectionObserver, bPtr,
 
1193
                              WMListSelectionDidChangeNotification, list);
 
1194
 
 
1195
    bPtr->columns[index] = list;
 
1196
 
 
1197
    WMResizeWidget(list, bPtr->columnSize.width, bPtr->columnSize.height);
 
1198
    WMMoveWidget(list, (bPtr->columnSize.width+COLUMN_SPACING)*index, colY);
 
1199
    if (COLUMN_IS_VISIBLE(bPtr, index))
 
1200
        WMMapWidget(list);
 
1201
 
 
1202
    /* update the scroller */
 
1203
    if (bPtr->columnCount > bPtr->maxVisibleColumns) {
 
1204
        float value, proportion;
 
1205
 
 
1206
        value = bPtr->firstVisibleColumn
 
1207
            /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
 
1208
        proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
 
1209
        WMSetScrollerParameters(bPtr->scroller, value, proportion);
 
1210
    }
 
1211
 
 
1212
    return index;
 
1213
}
 
1214
 
 
1215
 
 
1216
 
 
1217
static void
 
1218
destroyBrowser(WMBrowser *bPtr)
 
1219
{
 
1220
    int i;
 
1221
 
 
1222
    for (i = 0; i < bPtr->columnCount; i++) {
 
1223
        if (bPtr->titles[i])
 
1224
            wfree(bPtr->titles[i]);
 
1225
    }
 
1226
    wfree(bPtr->titles);
 
1227
 
 
1228
    wfree(bPtr->pathSeparator);
 
1229
 
 
1230
    WMRemoveNotificationObserver(bPtr);
 
1231
 
 
1232
    wfree(bPtr);
 
1233
}
 
1234
 
 
1235
 
 
1236
static char*
 
1237
createTruncatedString(WMFont *font, char *text, int *textLen, int width)
 
1238
{
 
1239
    int dLen = WMWidthOfString(font, ".", 1);
 
1240
    char *textBuf = (char*)wmalloc((*textLen)+4);
 
1241
 
 
1242
    if (width >= 3*dLen) {
 
1243
        int dddLen = 3*dLen;
 
1244
        int tmpTextLen = *textLen;
 
1245
 
 
1246
        strcpy(textBuf, text);
 
1247
        while (tmpTextLen
 
1248
               && (WMWidthOfString(font, textBuf, tmpTextLen)+dddLen > width))
 
1249
            tmpTextLen--;
 
1250
        strcpy(textBuf+tmpTextLen, "...");
 
1251
        *textLen = tmpTextLen+3;
 
1252
    } else if (width >= 2*dLen) {
 
1253
        strcpy(textBuf, "..");
 
1254
        *textLen = 2;
 
1255
    } else if (width >= dLen) {
 
1256
        strcpy(textBuf, ".");
 
1257
        *textLen = 1;
 
1258
    } else {
 
1259
        *textBuf = '\0';
 
1260
        *textLen = 0;
 
1261
    }
 
1262
    return textBuf;
 
1263
}
 
1264