Code update for Window Maker version 0.50.0
[wmaker-crm.git] / WINGs / wbrowser.c
blob0f923140605c2733e6fa65a12f0e5d7e06011715
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, int index, Drawable d, char *text,
76 int state, 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-WMFontHeight(scr->boldFont))/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 #if 1
252 int limit;
254 if(bPtr->usedColumnCount < bPtr->maxVisibleColumns)
255 limit = bPtr->usedColumnCount;
256 else
257 limit = bPtr->maxVisibleColumns;
259 for (i=column; i < limit; i++) {
260 if (bPtr->titles[i])
261 free(bPtr->titles[i]);
262 bPtr->titles[i] = NULL;
264 WMClearList(bPtr->columns[i]);
265 bPtr->usedColumnCount--;
267 #else
268 for (i=column; i < bPtr->maxVisibleColumns; i++) {
269 if (bPtr->titles[i])
270 free(bPtr->titles[i]);
271 bPtr->titles[i] = NULL;
273 WMClearList(bPtr->columns[i]);
274 bPtr->usedColumnCount--;
276 tmp = bPtr->columnCount;
277 for (i=bPtr->maxVisibleColumns; i < tmp; i++) {
278 if (bPtr->titles[i])
279 free(bPtr->titles[i]);
280 bPtr->titles[i] = NULL;
282 WMDestroyWidget(bPtr->columns[i]);
283 bPtr->columns[i] = NULL;
284 bPtr->columnCount--;
285 bPtr->usedColumnCount--;
287 #endif
288 } else {
289 int tmp = bPtr->columnCount;
290 for (i=column; i < tmp; i++) {
291 if (bPtr->titles[i])
292 free(bPtr->titles[i]);
293 bPtr->titles[i] = NULL;
295 WMDestroyWidget(bPtr->columns[i]);
296 bPtr->columns[i] = NULL;
297 bPtr->columnCount--;
298 bPtr->usedColumnCount--;
301 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
302 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
303 memcpy(clist, bPtr->columns, sizeof(WMList*)*bPtr->columnCount);
304 memcpy(tlist, bPtr->titles, sizeof(char*)*bPtr->columnCount);
305 free(bPtr->titles);
306 free(bPtr->columns);
307 bPtr->titles = tlist;
308 bPtr->columns = clist;
313 WMListItem*
314 WMGetBrowserSelectedItemInColumn(WMBrowser *bPtr, int column)
316 if ((column < 0) || (column > bPtr->columnCount))
317 return NULL;
319 return WMGetListSelectedItem(bPtr->columns[column]);
325 WMGetBrowserSelectedColumn(WMBrowser *bPtr)
327 return bPtr->selectedColumn;
332 WMGetBrowserSelectedRowInColumn(WMBrowser *bPtr, int column)
334 if (column >= 0 && column < bPtr->columnCount) {
335 return WMGetListSelectedItemRow(bPtr->columns[column]);
336 } else {
337 return -1;
342 void
343 WMSetBrowserTitled(WMBrowser *bPtr, Bool flag)
345 int i;
346 int columnX, columnY;
348 if (bPtr->flags.isTitled == flag)
349 return;
351 columnX = 0;
353 if (!bPtr->flags.isTitled) {
354 columnY = TITLE_SPACING + bPtr->titleHeight;
356 bPtr->columnSize.height -= columnY;
358 for (i=0; i<bPtr->columnCount; i++) {
359 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
360 bPtr->columnSize.height);
362 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
364 WMMoveWidget(bPtr->columns[i], columnX, columnY);
366 } else {
367 bPtr->columnSize.height += TITLE_SPACING + bPtr->titleHeight;
369 for (i=0; i<bPtr->columnCount; i++) {
370 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
371 bPtr->columnSize.height);
373 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
375 WMMoveWidget(bPtr->columns[i], columnX, 0);
379 bPtr->flags.isTitled = flag;
383 WMListItem*
384 WMAddSortedBrowserItem(WMBrowser *bPtr, int column, char *text, Bool isBranch)
386 WMListItem *item;
388 if (column < 0 || column >= bPtr->columnCount)
389 return NULL;
391 item = WMAddSortedListItem(bPtr->columns[column], text);
392 item->isBranch = isBranch;
394 return item;
399 WMListItem*
400 WMInsertBrowserItem(WMBrowser *bPtr, int column, int row, char *text,
401 Bool isBranch)
403 WMListItem *item;
405 if (column < 0 || column >= bPtr->columnCount)
406 return NULL;
408 item = WMInsertListItem(bPtr->columns[column], row, text);
409 item->isBranch = isBranch;
411 return item;
417 static void
418 resizeBrowser(WMWidget *w, unsigned int width, unsigned int height)
420 WMBrowser *bPtr = (WMBrowser*)w;
421 int cols = bPtr->maxVisibleColumns;
422 int colX, colY;
423 int i;
425 assert(width > 0);
426 assert(height > 0);
428 bPtr->columnSize.width = (width-(cols-1)*COLUMN_SPACING) / cols;
429 bPtr->columnSize.height = height;
431 if (bPtr->flags.isTitled) {
432 bPtr->columnSize.height -= TITLE_SPACING + bPtr->titleHeight;
433 colY = TITLE_SPACING + bPtr->titleHeight;
434 } else {
435 colY = 0;
438 if (bPtr->flags.hasScroller) {
439 bPtr->columnSize.height -= SCROLLER_WIDTH + 4;
441 if (bPtr->scroller) {
442 WMResizeWidget(bPtr->scroller, width-2, 1);
443 WMMoveWidget(bPtr->scroller, 1, height-SCROLLER_WIDTH-1);
447 colX = 0;
448 for (i = 0; i < bPtr->columnCount; i++) {
449 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
450 bPtr->columnSize.height);
452 WMMoveWidget(bPtr->columns[i], colX, colY);
454 if (COLUMN_IS_VISIBLE(bPtr, i)) {
455 colX += bPtr->columnSize.width+COLUMN_SPACING;
459 W_ResizeView(bPtr->view, width, height);
463 static void
464 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
465 WMRect *rect)
467 WMView *view = W_VIEW(lPtr);
468 W_Screen *scr = view->screen;
469 int width, height, x, y;
471 width = rect->size.width;
472 height = rect->size.height;
473 x = rect->pos.x;
474 y = rect->pos.y;
476 if (state & WLDSSelected)
477 XFillRectangle(scr->display, d, W_GC(scr->white), x, y,
478 width, height);
479 else
480 XClearArea(scr->display, d, x, y, width, height, False);
482 if (text) {
483 W_PaintText(view, d, scr->normalFont, x+4, y, width,
484 WALeft, W_GC(scr->black), False, text, strlen(text));
487 if (state & WLDSIsBranch) {
488 XDrawLine(scr->display, d, W_GC(scr->darkGray), x+width-11, y+3,
489 x+width-6, y+height/2);
490 if (state & WLDSSelected)
491 XDrawLine(scr->display, d,W_GC(scr->gray), x+width-11, y+height-5,
492 x+width-6, y+height/2);
493 else
494 XDrawLine(scr->display, d,W_GC(scr->white), x+width-11, y+height-5,
495 x+width-6, y+height/2);
496 XDrawLine(scr->display, d, W_GC(scr->black), x+width-12, y+3,
497 x+width-12, y+height-5);
502 static void
503 scrollCallback(WMWidget *scroller, void *self)
505 WMBrowser *bPtr = (WMBrowser*)self;
506 WMScroller *sPtr = (WMScroller*)scroller;
507 int newFirst;
508 #define LAST_VISIBLE_COLUMN bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
510 switch (WMGetScrollerHitPart(sPtr)) {
511 case WSDecrementLine:
512 if (bPtr->firstVisibleColumn > 0) {
513 scrollToColumn(bPtr, bPtr->firstVisibleColumn-1);
515 break;
517 case WSDecrementPage:
518 if (bPtr->firstVisibleColumn > 0) {
519 newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
521 scrollToColumn(bPtr, newFirst);
523 break;
526 case WSIncrementLine:
527 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
528 scrollToColumn(bPtr, bPtr->firstVisibleColumn+1);
530 break;
532 case WSIncrementPage:
533 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
534 newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
536 if (newFirst+bPtr->maxVisibleColumns >= bPtr->columnCount)
537 newFirst = bPtr->columnCount - bPtr->maxVisibleColumns;
539 scrollToColumn(bPtr, newFirst);
541 break;
543 case WSKnob:
545 float floatValue;
546 float value = bPtr->columnCount - bPtr->maxVisibleColumns;
548 floatValue = WMGetScrollerValue(bPtr->scroller);
550 floatValue = (floatValue*value)/value;
552 newFirst = floatValue*(float)(bPtr->columnCount - bPtr->maxVisibleColumns);
554 if (bPtr->firstVisibleColumn != newFirst)
555 scrollToColumn(bPtr, newFirst);
556 else
557 WMSetScrollerParameters(bPtr->scroller, floatValue,
558 bPtr->maxVisibleColumns/(float)bPtr->columnCount);
561 break;
563 case WSKnobSlot:
564 case WSNoPart:
565 /* do nothing */
566 break;
568 #undef LAST_VISIBLE_COLUMN
572 static void
573 setupScroller(WMBrowser *bPtr)
575 WMScroller *sPtr;
576 int y;
578 y = bPtr->view->size.height - SCROLLER_WIDTH - 1;
580 sPtr = WMCreateScroller(bPtr);
581 WMSetScrollerAction(sPtr, scrollCallback, bPtr);
582 WMMoveWidget(sPtr, 1, y);
583 WMResizeWidget(sPtr, bPtr->view->size.width-2, SCROLLER_WIDTH);
585 bPtr->scroller = sPtr;
587 WMMapWidget(sPtr);
591 void
592 WMSetBrowserAction(WMBrowser *bPtr, WMAction *action, void *clientData)
594 bPtr->action = action;
595 bPtr->clientData = clientData;
599 void
600 WMSetBrowserHasScroller(WMBrowser *bPtr, int hasScroller)
602 bPtr->flags.hasScroller = hasScroller;
607 Bool
608 WMSetBrowserPath(WMBrowser *bPtr, char *path)
610 int i;
611 char *str = wstrdup(path);
612 char *tmp;
613 int item;
614 Bool ok = True;
615 WMListItem *listItem;
617 removeColumn(bPtr, 1);
619 i = 0;
620 tmp = strtok(str, bPtr->pathSeparator);
621 while (tmp) {
622 /* select it in the column */
623 item = WMFindRowOfListItemWithTitle(bPtr->columns[i], tmp);
624 if (item<0) {
625 ok = False;
626 break;
628 WMSelectListItem(bPtr->columns[i], item);
629 WMSetListPosition(bPtr->columns[i], item);
631 listItem = WMGetListItem(bPtr->columns[i], item);
632 if (!listItem || !listItem->isBranch) {
633 break;
636 /* load next column */
637 WMAddBrowserColumn(bPtr);
639 loadColumn(bPtr, i+1);
641 tmp = strtok(NULL, bPtr->pathSeparator);
643 i++;
645 free(str);
647 bPtr->selectedColumn = bPtr->usedColumnCount - 1;
649 scrollToColumn(bPtr, bPtr->columnCount-bPtr->maxVisibleColumns);
651 return ok;
655 char*
656 WMGetBrowserPath(WMBrowser *bPtr)
658 return WMGetBrowserPathToColumn(bPtr, bPtr->columnCount);
662 char*
663 WMGetBrowserPathToColumn(WMBrowser *bPtr, int column)
665 int i, size;
666 char *path;
667 WMListItem *item;
669 if (column >= bPtr->usedColumnCount)
670 column = bPtr->usedColumnCount-1;
672 /* calculate size of buffer */
673 size = 0;
674 for (i = 0; i <= column; i++) {
675 item = WMGetListSelectedItem(bPtr->columns[i]);
676 if (!item)
677 break;
678 size += strlen(item->text);
681 /* get the path */
682 path = wmalloc(size+(column+1)*strlen(bPtr->pathSeparator)+1);
683 /* ignore first / */
684 *path = 0;
685 for (i = 0; i <= column; i++) {
686 strcat(path, bPtr->pathSeparator);
687 item = WMGetListSelectedItem(bPtr->columns[i]);
688 if (!item)
689 break;
690 strcat(path, item->text);
693 return path;
697 static void
698 loadColumn(WMBrowser *bPtr, int column)
700 assert(bPtr->fillColumn);
702 bPtr->flags.loadingColumn = 1;
703 (*bPtr->fillColumn)(bPtr, column);
704 bPtr->flags.loadingColumn = 0;
708 static void
709 paintBrowser(WMBrowser *bPtr)
711 int i;
713 if (!bPtr->view->flags.mapped)
714 return;
716 W_DrawRelief(bPtr->view->screen, bPtr->view->window, 0,
717 bPtr->view->size.height-SCROLLER_WIDTH-2,
718 bPtr->view->size.width, 22, WRSunken);
720 if (bPtr->flags.isTitled) {
721 for (i=0; i<bPtr->maxVisibleColumns; i++) {
722 drawTitleOfColumn(bPtr, i+bPtr->firstVisibleColumn);
728 static void
729 handleEvents(XEvent *event, void *data)
731 WMBrowser *bPtr = (WMBrowser*)data;
733 CHECK_CLASS(data, WC_Browser);
736 switch (event->type) {
737 case Expose:
738 paintBrowser(bPtr);
739 break;
741 case DestroyNotify:
742 destroyBrowser(bPtr);
743 break;
750 static void
751 scrollToColumn(WMBrowser *bPtr, int column)
753 int i;
754 int x;
755 int notify = 0;
758 if (column != bPtr->firstVisibleColumn)
759 notify = 1;
761 if (column < 0)
762 column = 0;
764 x = 0;
765 bPtr->firstVisibleColumn = column;
766 for (i = 0; i < bPtr->usedColumnCount; i++) {
767 if (COLUMN_IS_VISIBLE(bPtr, i)) {
768 WMMoveWidget(bPtr->columns[i], x,
769 WMWidgetView(bPtr->columns[i])->pos.y);
770 if (!WMWidgetView(bPtr->columns[i])->flags.realized)
771 WMRealizeWidget(bPtr->columns[i]);
772 WMMapWidget(bPtr->columns[i]);
773 x += bPtr->columnSize.width+COLUMN_SPACING;
774 } else {
775 WMUnmapWidget(bPtr->columns[i]);
779 /* update the scroller */
780 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
781 float value, proportion;
783 value = bPtr->firstVisibleColumn
784 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
785 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
786 WMSetScrollerParameters(bPtr->scroller, value, proportion);
787 } else {
788 WMSetScrollerParameters(bPtr->scroller, 0, 1);
791 if (bPtr->view->flags.mapped)
792 paintBrowser(bPtr);
794 if (notify)
795 WMPostNotificationName(WMBrowserDidScrollNotification, bPtr, NULL);
799 static void
800 listCallback(void *self, void *clientData)
802 WMBrowser *bPtr = (WMBrowser*)clientData;
803 WMList *lPtr = (WMList*)self;
804 WMListItem *item;
805 int i;
807 item = WMGetListSelectedItem(lPtr);
808 if (!item)
809 return;
811 for (i=0; i<bPtr->columnCount; i++) {
812 if (lPtr == bPtr->columns[i])
813 break;
815 assert(i<bPtr->columnCount);
817 bPtr->selectedColumn = i;
819 /* columns at right must be cleared */
820 removeColumn(bPtr, i+1);
821 /* open directory */
822 if (item->isBranch) {
823 WMAddBrowserColumn(bPtr);
824 loadColumn(bPtr, bPtr->usedColumnCount-1);
826 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
827 i = 0;
828 else
829 i = bPtr->usedColumnCount-bPtr->maxVisibleColumns;
830 scrollToColumn(bPtr, i);
832 /* call callback for click */
833 if (bPtr->action)
834 (*bPtr->action)(bPtr, bPtr->clientData);
838 void
839 WMLoadBrowserColumnZero(WMBrowser *bPtr)
841 if (!bPtr->flags.loaded) {
842 /* create column 0 */
843 WMAddBrowserColumn(bPtr);
845 loadColumn(bPtr, 0);
847 /* make column 0 visible */
848 scrollToColumn(bPtr, 0);
850 bPtr->flags.loaded = 1;
855 void
856 WMRemoveBrowserItem(WMBrowser *bPtr, int column, int row)
858 WMList *list;
860 if (column < 0 || column >= bPtr->usedColumnCount)
861 return;
863 list = WMGetBrowserListInColumn(bPtr, column);
865 if (row < 0 || row >= WMGetListNumberOfRows(list))
866 return;
868 removeColumn(bPtr, column+1);
869 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
870 scrollToColumn(bPtr, 0);
871 else
872 scrollToColumn(bPtr, bPtr->usedColumnCount-bPtr->maxVisibleColumns);
874 WMRemoveListItem(list, row);
879 WMAddBrowserColumn(WMBrowser *bPtr)
881 WMList *list;
882 WMList **clist;
883 char **tlist;
884 int colY;
885 int index;
888 if (bPtr->usedColumnCount < bPtr->columnCount) {
889 return bPtr->usedColumnCount++;
892 bPtr->usedColumnCount++;
894 if (bPtr->flags.isTitled) {
895 colY = TITLE_SPACING + bPtr->titleHeight;
896 } else {
897 colY = 0;
900 index = bPtr->columnCount;
901 bPtr->columnCount++;
902 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
903 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
904 memcpy(clist, bPtr->columns, sizeof(WMList*)*(bPtr->columnCount-1));
905 memcpy(tlist, bPtr->titles, sizeof(char*)*(bPtr->columnCount-1));
906 if (bPtr->columns)
907 free(bPtr->columns);
908 if (bPtr->titles)
909 free(bPtr->titles);
910 bPtr->columns = clist;
911 bPtr->titles = tlist;
913 bPtr->titles[index] = NULL;
915 list = WMCreateList(bPtr);
916 WMSetListAction(list, listCallback, bPtr);
917 WMSetListUserDrawProc(list, paintItem);
918 bPtr->columns[index] = list;
920 WMResizeWidget(list, bPtr->columnSize.width, bPtr->columnSize.height);
921 WMMoveWidget(list, (bPtr->columnSize.width+COLUMN_SPACING)*index, colY);
922 if (COLUMN_IS_VISIBLE(bPtr, index))
923 WMMapWidget(list);
925 /* update the scroller */
926 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
927 float value, proportion;
929 value = bPtr->firstVisibleColumn
930 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
931 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
932 WMSetScrollerParameters(bPtr->scroller, value, proportion);
935 return index;
940 static void
941 destroyBrowser(WMBrowser *bPtr)
943 int i;
945 for (i=0; i<bPtr->columnCount; i++) {
946 if (bPtr->titles[i])
947 free(bPtr->titles[i]);
949 free(bPtr->titles);
951 free(bPtr->pathSeparator);
953 free(bPtr);