Window Maker 0.20.3
[wmaker-crm.git] / WINGs / wbrowser.c
blob3db14b09d9f1bab41857accf4404d4f5bd48e85a
5 #include "WINGsP.h"
8 char *WMBrowserDidScrollNotification = "WMBrowserDidScrollNotification";
11 typedef struct W_Browser {
12 W_Class widgetClass;
13 W_View *view;
15 char **titles;
16 WMList **columns;
18 short columnCount;
19 short usedColumnCount; /* columns actually being used */
20 short minColumnWidth;
22 short maxVisibleColumns;
23 short firstVisibleColumn;
25 short titleHeight;
27 short selectedColumn;
29 WMSize columnSize;
32 void *clientData;
33 WMAction *action;
34 void *doubleClientData;
35 WMAction *doubleAction;
37 WMBrowserFillColumnProc *fillColumn;
39 WMScroller *scroller;
41 char *pathSeparator;
43 struct {
44 unsigned int isTitled:1;
45 unsigned int allowMultipleSelection:1;
46 unsigned int hasScroller:1;
48 /* */
49 unsigned int loaded:1;
50 unsigned int loadingColumn:1;
51 } flags;
52 } Browser;
55 #define COLUMN_SPACING 4
56 #define TITLE_SPACING 2
58 #define DEFAULT_WIDTH 305
59 #define DEFAULT_HEIGHT 200
60 #define DEFAULT_HAS_SCROLLER True
62 #define DEFAULT_SEPARATOR "/"
64 #define COLUMN_IS_VISIBLE(b, c) ((c) >= (b)->firstVisibleColumn \
65 && (c) < (b)->firstVisibleColumn + (b)->maxVisibleColumns)
68 static void handleEvents(XEvent *event, void *data);
69 static void destroyBrowser(WMBrowser *bPtr);
71 static void setupScroller(WMBrowser *bPtr);
73 static void scrollToColumn(WMBrowser *bPtr, int column);
75 static void paintItem(WMList *lPtr, Drawable d, char *text, int state,
76 WMRect *rect);
78 static void loadColumn(WMBrowser *bPtr, int column);
81 static void resizeBrowser(WMWidget*, unsigned int, unsigned int);
83 W_ViewProcedureTable _BrowserViewProcedures = {
84 NULL,
85 resizeBrowser,
86 NULL
91 WMBrowser*
92 WMCreateBrowser(WMWidget *parent)
94 WMBrowser *bPtr;
95 int i;
97 bPtr = wmalloc(sizeof(WMBrowser));
98 memset(bPtr, 0, sizeof(WMBrowser));
100 bPtr->widgetClass = WC_Browser;
102 bPtr->view = W_CreateView(W_VIEW(parent));
103 if (!bPtr->view) {
104 free(bPtr);
105 return NULL;
107 bPtr->view->self = bPtr;
109 WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
110 |ClientMessageMask, handleEvents, bPtr);
112 /* default configuration */
113 bPtr->flags.hasScroller = DEFAULT_HAS_SCROLLER;
115 bPtr->titleHeight = 20;
116 bPtr->flags.isTitled = 1;
117 bPtr->maxVisibleColumns = 2;
119 resizeBrowser(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
121 bPtr->pathSeparator = wstrdup(DEFAULT_SEPARATOR);
123 if (bPtr->flags.hasScroller)
124 setupScroller(bPtr);
126 for (i=0; i<bPtr->maxVisibleColumns; i++) {
127 WMAddBrowserColumn(bPtr);
129 bPtr->usedColumnCount = 0;
131 bPtr->selectedColumn = -1;
133 return bPtr;
137 void
138 WMSetBrowserMaxVisibleColumns(WMBrowser *bPtr, int columns)
140 if (columns > bPtr->maxVisibleColumns) {
142 if (columns > bPtr->columnCount) {
143 int i = columns - bPtr->columnCount;
145 while (i--) {
146 WMAddBrowserColumn(bPtr);
150 resizeBrowser(bPtr, bPtr->view->size.width, bPtr->view->size.height);
152 } else if (columns < bPtr->maxVisibleColumns) {
154 resizeBrowser(bPtr, bPtr->view->size.width, bPtr->view->size.height);
157 bPtr->maxVisibleColumns = columns;
161 int
162 WMGetBrowserNumberOfColumns(WMBrowser *bPtr)
164 return bPtr->usedColumnCount;
167 void
168 WMSetBrowserPathSeparator(WMBrowser *bPtr, char *separator)
170 if (bPtr->pathSeparator)
171 free(bPtr->pathSeparator);
172 bPtr->pathSeparator = wstrdup(separator);
177 static void
178 drawTitleOfColumn(WMBrowser *bPtr, int column)
180 WMScreen *scr = bPtr->view->screen;
181 int x;
183 x=(column-bPtr->firstVisibleColumn)*(bPtr->columnSize.width+COLUMN_SPACING);
185 XFillRectangle(scr->display, bPtr->view->window, W_GC(scr->darkGray), x, 0,
186 bPtr->columnSize.width, bPtr->titleHeight);
187 W_DrawRelief(scr, bPtr->view->window, x, 0,
188 bPtr->columnSize.width, bPtr->titleHeight, WRSunken);
190 if (column < bPtr->usedColumnCount && bPtr->titles[column])
191 W_PaintText(bPtr->view, bPtr->view->window, scr->boldFont, x,
192 (bPtr->titleHeight-scr->boldFont->height)/2,
193 bPtr->columnSize.width, WACenter, W_GC(scr->white),
194 False, bPtr->titles[column], strlen(bPtr->titles[column]));
198 void
199 WMSetBrowserColumnTitle(WMBrowser *bPtr, int column, char *title)
201 assert(column >= 0);
202 assert(column < bPtr->usedColumnCount);
204 if (bPtr->titles[column])
205 free(bPtr->titles[column]);
207 bPtr->titles[column] = wstrdup(title);
209 if (COLUMN_IS_VISIBLE(bPtr, column) && bPtr->flags.isTitled) {
210 drawTitleOfColumn(bPtr, column);
215 WMList*
216 WMGetBrowserListInColumn(WMBrowser *bPtr, int column)
218 if (column < 0 || column >= bPtr->usedColumnCount)
219 return NULL;
221 return bPtr->columns[column];
225 void
226 WMSetBrowserFillColumnProc(WMBrowser *bPtr, WMBrowserFillColumnProc *proc)
228 bPtr->fillColumn = proc;
232 int
233 WMGetBrowserFirstVisibleColumn(WMBrowser *bPtr)
235 return bPtr->firstVisibleColumn;
239 static void
240 removeColumn(WMBrowser *bPtr, int column)
242 int i;
243 WMList **clist;
244 char **tlist;
246 if (column >= bPtr->usedColumnCount)
247 return;
249 if (column < bPtr->maxVisibleColumns) {
250 int tmp;
251 for (i=column; i < bPtr->maxVisibleColumns; i++) {
252 if (bPtr->titles[i])
253 free(bPtr->titles[i]);
254 bPtr->titles[i] = NULL;
256 WMClearList(bPtr->columns[i]);
257 bPtr->usedColumnCount--;
259 tmp = bPtr->columnCount;
260 for (i=bPtr->maxVisibleColumns; i < tmp; i++) {
261 if (bPtr->titles[i])
262 free(bPtr->titles[i]);
263 bPtr->titles[i] = NULL;
265 WMDestroyWidget(bPtr->columns[i]);
266 bPtr->columns[i] = NULL;
267 bPtr->columnCount--;
268 bPtr->usedColumnCount--;
270 } else {
271 int tmp = bPtr->columnCount;
272 for (i=column; i < tmp; i++) {
273 if (bPtr->titles[i])
274 free(bPtr->titles[i]);
275 bPtr->titles[i] = NULL;
277 WMDestroyWidget(bPtr->columns[i]);
278 bPtr->columns[i] = NULL;
279 bPtr->columnCount--;
280 bPtr->usedColumnCount--;
283 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
284 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
285 memcpy(clist, bPtr->columns, sizeof(WMList*)*bPtr->columnCount);
286 memcpy(tlist, bPtr->titles, sizeof(char*)*bPtr->columnCount);
287 free(bPtr->titles);
288 free(bPtr->columns);
289 bPtr->titles = tlist;
290 bPtr->columns = clist;
295 WMListItem*
296 WMGetBrowserSelectedItemInColumn(WMBrowser *bPtr, int column)
298 if ((column < 0) || (column > bPtr->columnCount))
299 return NULL;
301 return WMGetListSelectedItem(bPtr->columns[column]);
307 WMGetBrowserSelectedColumn(WMBrowser *bPtr)
309 return bPtr->selectedColumn;
314 WMGetBrowserSelectedRowInColumn(WMBrowser *bPtr, int column)
316 if (column >= 0 && column < bPtr->columnCount) {
317 return WMGetListSelectedItemRow(bPtr->columns[column]);
318 } else {
319 return -1;
324 void
325 WMSetBrowserTitled(WMBrowser *bPtr, Bool flag)
327 int i;
328 int columnX, columnY;
330 if (bPtr->flags.isTitled == flag)
331 return;
333 columnX = 0;
335 if (!bPtr->flags.isTitled) {
336 columnY = TITLE_SPACING + bPtr->titleHeight;
338 bPtr->columnSize.height -= columnY;
340 for (i=0; i<bPtr->columnCount; i++) {
341 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
342 bPtr->columnSize.height);
344 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
346 WMMoveWidget(bPtr->columns[i], columnX, columnY);
348 } else {
349 bPtr->columnSize.height += TITLE_SPACING + bPtr->titleHeight;
351 for (i=0; i<bPtr->columnCount; i++) {
352 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
353 bPtr->columnSize.height);
355 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
357 WMMoveWidget(bPtr->columns[i], columnX, 0);
361 bPtr->flags.isTitled = flag;
365 WMListItem*
366 WMAddSortedBrowserItem(WMBrowser *bPtr, int column, char *text, Bool isBranch)
368 WMListItem *item;
370 if (column < 0 || column >= bPtr->columnCount)
371 return NULL;
373 item = WMAddSortedListItem(bPtr->columns[column], text);
374 item->isBranch = isBranch;
376 return item;
381 WMListItem*
382 WMInsertBrowserItem(WMBrowser *bPtr, int column, int row, char *text,
383 Bool isBranch)
385 WMListItem *item;
387 if (column < 0 || column >= bPtr->columnCount)
388 return NULL;
390 item = WMInsertListItem(bPtr->columns[column], row, text);
391 item->isBranch = isBranch;
393 return item;
399 static void
400 resizeBrowser(WMWidget *w, unsigned int width, unsigned int height)
402 WMBrowser *bPtr = (WMBrowser*)w;
403 int cols = bPtr->maxVisibleColumns;
404 int colX, colY;
405 int i;
407 assert(width > 0);
408 assert(height > 0);
410 bPtr->columnSize.width = (width-(cols-1)*COLUMN_SPACING) / cols;
411 bPtr->columnSize.height = height;
413 if (bPtr->flags.isTitled) {
414 bPtr->columnSize.height -= TITLE_SPACING + bPtr->titleHeight;
415 colY = TITLE_SPACING + bPtr->titleHeight;
416 } else {
417 colY = 0;
420 if (bPtr->flags.hasScroller) {
421 bPtr->columnSize.height -= SCROLLER_WIDTH + 4;
423 if (bPtr->scroller) {
424 WMResizeWidget(bPtr->scroller, width-2, 1);
425 WMMoveWidget(bPtr->scroller, 1, height-SCROLLER_WIDTH-1);
429 colX = 0;
430 for (i = 0; i < bPtr->columnCount; i++) {
431 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
432 bPtr->columnSize.height);
434 WMMoveWidget(bPtr->columns[i], colX, colY);
436 if (COLUMN_IS_VISIBLE(bPtr, i)) {
437 colX += bPtr->columnSize.width+COLUMN_SPACING;
441 W_ResizeView(bPtr->view, width, height);
445 static void
446 paintItem(WMList *lPtr, Drawable d, char *text, int state, WMRect *rect)
448 WMView *view = W_VIEW(lPtr);
449 W_Screen *scr = view->screen;
450 int width, height, x, y;
452 width = rect->size.width;
453 height = rect->size.height;
454 x = rect->pos.x;
455 y = rect->pos.y;
457 if (state & WLDSSelected)
458 XFillRectangle(scr->display, d, W_GC(scr->white), x, y,
459 width, height);
460 else
461 XClearArea(scr->display, d, x, y, width, height, False);
463 if (text) {
464 W_PaintText(view, d, scr->normalFont, x+4, y, width,
465 WALeft, W_GC(scr->black), False, text, strlen(text));
468 if (state & WLDSIsBranch) {
469 XDrawLine(scr->display, d, W_GC(scr->darkGray), x+width-11, y+3,
470 x+width-6, y+height/2);
471 if (state & WLDSSelected)
472 XDrawLine(scr->display, d,W_GC(scr->gray), x+width-11, y+height-5,
473 x+width-6, y+height/2);
474 else
475 XDrawLine(scr->display, d,W_GC(scr->white), x+width-11, y+height-5,
476 x+width-6, y+height/2);
477 XDrawLine(scr->display, d, W_GC(scr->black), x+width-12, y+3,
478 x+width-12, y+height-5);
483 static void
484 scrollCallback(WMWidget *scroller, void *self)
486 WMBrowser *bPtr = (WMBrowser*)self;
487 WMScroller *sPtr = (WMScroller*)scroller;
488 int newFirst;
489 #define LAST_VISIBLE_COLUMN bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
491 switch (WMGetScrollerHitPart(sPtr)) {
492 case WSDecrementLine:
493 if (bPtr->firstVisibleColumn > 0) {
494 scrollToColumn(bPtr, bPtr->firstVisibleColumn-1);
496 break;
498 case WSDecrementPage:
499 if (bPtr->firstVisibleColumn > 0) {
500 newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
502 scrollToColumn(bPtr, newFirst);
504 break;
507 case WSIncrementLine:
508 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
509 scrollToColumn(bPtr, bPtr->firstVisibleColumn+1);
511 break;
513 case WSIncrementPage:
514 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
515 newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
517 if (newFirst+bPtr->maxVisibleColumns >= bPtr->columnCount)
518 newFirst = bPtr->columnCount - bPtr->maxVisibleColumns;
520 scrollToColumn(bPtr, newFirst);
522 break;
524 case WSKnob:
526 float floatValue;
527 float value = bPtr->columnCount - bPtr->maxVisibleColumns;
529 floatValue = WMGetScrollerValue(bPtr->scroller);
531 floatValue = (floatValue*value)/value;
533 newFirst = floatValue*(float)(bPtr->columnCount - bPtr->maxVisibleColumns);
535 if (bPtr->firstVisibleColumn != newFirst)
536 scrollToColumn(bPtr, newFirst);
537 else
538 WMSetScrollerParameters(bPtr->scroller, floatValue,
539 bPtr->maxVisibleColumns/(float)bPtr->columnCount);
542 break;
544 case WSKnobSlot:
545 case WSNoPart:
546 /* do nothing */
547 break;
549 #undef LAST_VISIBLE_COLUMN
553 static void
554 setupScroller(WMBrowser *bPtr)
556 WMScroller *sPtr;
557 int y;
559 y = bPtr->view->size.height - SCROLLER_WIDTH - 1;
561 sPtr = WMCreateScroller(bPtr);
562 WMSetScrollerAction(sPtr, scrollCallback, bPtr);
563 WMMoveWidget(sPtr, 1, y);
564 WMResizeWidget(sPtr, bPtr->view->size.width-2, SCROLLER_WIDTH);
566 bPtr->scroller = sPtr;
568 WMMapWidget(sPtr);
572 void
573 WMSetBrowserAction(WMBrowser *bPtr, WMAction *action, void *clientData)
575 bPtr->action = action;
576 bPtr->clientData = clientData;
580 void
581 WMSetBrowserHasScroller(WMBrowser *bPtr, int hasScroller)
583 bPtr->flags.hasScroller = hasScroller;
588 Bool
589 WMSetBrowserPath(WMBrowser *bPtr, char *path)
591 int i;
592 char *str = wstrdup(path);
593 char *tmp;
594 int item;
595 Bool ok = True;
596 WMListItem *listItem;
598 removeColumn(bPtr, 1);
600 i = 0;
601 tmp = strtok(str, bPtr->pathSeparator);
602 while (tmp) {
603 /* select it in the column */
604 item = WMFindRowOfListItemWithTitle(bPtr->columns[i], tmp);
605 if (item<0) {
606 ok = False;
607 break;
609 WMSelectListItem(bPtr->columns[i], item);
610 WMSetListPosition(bPtr->columns[i], item);
612 listItem = WMGetListItem(bPtr->columns[i], item);
613 if (!listItem || !listItem->isBranch) {
614 break;
617 /* load next column */
618 WMAddBrowserColumn(bPtr);
620 loadColumn(bPtr, i+1);
622 tmp = strtok(NULL, bPtr->pathSeparator);
624 i++;
626 free(str);
628 bPtr->selectedColumn = bPtr->usedColumnCount - 1;
630 scrollToColumn(bPtr, bPtr->columnCount-bPtr->maxVisibleColumns);
632 return ok;
636 char*
637 WMGetBrowserPath(WMBrowser *bPtr)
639 return WMGetBrowserPathToColumn(bPtr, bPtr->columnCount);
643 char*
644 WMGetBrowserPathToColumn(WMBrowser *bPtr, int column)
646 int i, size;
647 char *path;
648 WMListItem *item;
650 if (column >= bPtr->usedColumnCount)
651 column = bPtr->usedColumnCount-1;
653 /* calculate size of buffer */
654 size = 0;
655 for (i = 0; i <= column; i++) {
656 item = WMGetListSelectedItem(bPtr->columns[i]);
657 if (!item)
658 break;
659 size += strlen(item->text);
662 /* get the path */
663 path = wmalloc(size+(column+1)*strlen(bPtr->pathSeparator)+1);
664 /* ignore first / */
665 *path = 0;
666 for (i = 0; i <= column; i++) {
667 strcat(path, bPtr->pathSeparator);
668 item = WMGetListSelectedItem(bPtr->columns[i]);
669 if (!item)
670 break;
671 strcat(path, item->text);
674 return path;
678 static void
679 loadColumn(WMBrowser *bPtr, int column)
681 assert(bPtr->fillColumn);
683 bPtr->flags.loadingColumn = 1;
684 (*bPtr->fillColumn)(bPtr, column);
685 bPtr->flags.loadingColumn = 0;
689 static void
690 paintBrowser(WMBrowser *bPtr)
692 int i;
694 if (!bPtr->view->flags.mapped)
695 return;
697 W_DrawRelief(bPtr->view->screen, bPtr->view->window, 0,
698 bPtr->view->size.height-SCROLLER_WIDTH-2,
699 bPtr->view->size.width, 22, WRSunken);
701 if (bPtr->flags.isTitled) {
702 for (i=0; i<bPtr->maxVisibleColumns; i++) {
703 drawTitleOfColumn(bPtr, i+bPtr->firstVisibleColumn);
709 static void
710 handleEvents(XEvent *event, void *data)
712 WMBrowser *bPtr = (WMBrowser*)data;
714 CHECK_CLASS(data, WC_Browser);
717 switch (event->type) {
718 case Expose:
719 paintBrowser(bPtr);
720 break;
722 case DestroyNotify:
723 destroyBrowser(bPtr);
724 break;
731 static void
732 scrollToColumn(WMBrowser *bPtr, int column)
734 int i;
735 int x;
736 int notify = 0;
739 if (column != bPtr->firstVisibleColumn)
740 notify = 1;
742 if (column < 0)
743 column = 0;
745 x = 0;
746 bPtr->firstVisibleColumn = column;
747 for (i = 0; i < bPtr->usedColumnCount; i++) {
748 if (COLUMN_IS_VISIBLE(bPtr, i)) {
749 WMMoveWidget(bPtr->columns[i], x,
750 WMWidgetView(bPtr->columns[i])->pos.y);
751 if (!WMWidgetView(bPtr->columns[i])->flags.realized)
752 WMRealizeWidget(bPtr->columns[i]);
753 WMMapWidget(bPtr->columns[i]);
754 x += bPtr->columnSize.width+COLUMN_SPACING;
755 } else {
756 WMUnmapWidget(bPtr->columns[i]);
760 /* update the scroller */
761 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
762 float value, proportion;
764 value = bPtr->firstVisibleColumn
765 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
766 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
767 WMSetScrollerParameters(bPtr->scroller, value, proportion);
768 } else {
769 WMSetScrollerParameters(bPtr->scroller, 0, 1);
772 if (bPtr->view->flags.mapped)
773 paintBrowser(bPtr);
775 if (notify)
776 WMPostNotificationName(WMBrowserDidScrollNotification, bPtr, NULL);
780 static void
781 listCallback(void *self, void *clientData)
783 WMBrowser *bPtr = (WMBrowser*)clientData;
784 WMList *lPtr = (WMList*)self;
785 WMListItem *item;
786 int i;
788 item = WMGetListSelectedItem(lPtr);
789 if (!item)
790 return;
792 for (i=0; i<bPtr->columnCount; i++) {
793 if (lPtr == bPtr->columns[i])
794 break;
796 assert(i<bPtr->columnCount);
798 bPtr->selectedColumn = i;
800 /* columns at right must be cleared */
801 removeColumn(bPtr, i+1);
802 /* open directory */
803 if (item->isBranch) {
804 WMAddBrowserColumn(bPtr);
805 loadColumn(bPtr, bPtr->usedColumnCount-1);
807 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
808 i = 0;
809 else
810 i = bPtr->usedColumnCount-bPtr->maxVisibleColumns;
811 scrollToColumn(bPtr, i);
813 /* call callback for click */
814 if (bPtr->action)
815 (*bPtr->action)(bPtr, bPtr->clientData);
819 void
820 WMLoadBrowserColumnZero(WMBrowser *bPtr)
822 if (!bPtr->flags.loaded) {
823 /* create column 0 */
824 WMAddBrowserColumn(bPtr);
826 loadColumn(bPtr, 0);
828 /* make column 0 visible */
829 scrollToColumn(bPtr, 0);
831 bPtr->flags.loaded = 1;
836 void
837 WMRemoveBrowserItem(WMBrowser *bPtr, int column, int row)
839 WMList *list;
841 if (column < 0 || column >= bPtr->usedColumnCount)
842 return;
844 list = WMGetBrowserListInColumn(bPtr, column);
846 if (row < 0 || row >= WMGetListNumberOfRows(list))
847 return;
849 removeColumn(bPtr, column+1);
850 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
851 scrollToColumn(bPtr, 0);
852 else
853 scrollToColumn(bPtr, bPtr->usedColumnCount-bPtr->maxVisibleColumns);
855 WMRemoveListItem(list, row);
860 WMAddBrowserColumn(WMBrowser *bPtr)
862 WMList *list;
863 WMList **clist;
864 char **tlist;
865 int colY;
866 int index;
869 if (bPtr->usedColumnCount < bPtr->columnCount) {
870 return bPtr->usedColumnCount++;
873 bPtr->usedColumnCount++;
875 if (bPtr->flags.isTitled) {
876 colY = TITLE_SPACING + bPtr->titleHeight;
877 } else {
878 colY = 0;
881 index = bPtr->columnCount;
882 bPtr->columnCount++;
883 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
884 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
885 memcpy(clist, bPtr->columns, sizeof(WMList*)*(bPtr->columnCount-1));
886 memcpy(tlist, bPtr->titles, sizeof(char*)*(bPtr->columnCount-1));
887 if (bPtr->columns)
888 free(bPtr->columns);
889 if (bPtr->titles)
890 free(bPtr->titles);
891 bPtr->columns = clist;
892 bPtr->titles = tlist;
894 bPtr->titles[index] = NULL;
896 list = WMCreateList(bPtr);
897 WMSetListAction(list, listCallback, bPtr);
898 WMSetListUserDrawProc(list, paintItem);
899 bPtr->columns[index] = list;
901 WMResizeWidget(list, bPtr->columnSize.width, bPtr->columnSize.height);
902 WMMoveWidget(list, (bPtr->columnSize.width+COLUMN_SPACING)*index, colY);
903 if (COLUMN_IS_VISIBLE(bPtr, index))
904 WMMapWidget(list);
906 /* update the scroller */
907 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
908 float value, proportion;
910 value = bPtr->firstVisibleColumn
911 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
912 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
913 WMSetScrollerParameters(bPtr->scroller, value, proportion);
916 return index;
921 static void
922 destroyBrowser(WMBrowser *bPtr)
924 int i;
926 for (i=0; i<bPtr->columnCount; i++) {
927 if (bPtr->titles[i])
928 free(bPtr->titles[i]);
930 free(bPtr->titles);
932 free(bPtr->pathSeparator);
934 free(bPtr);