Update to Window Maker 0.50.2
[wmaker-crm.git] / WINGs / wbrowser.c
blob3054cf50ddc807d7f921d132b4da5af8fb98943e
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 0
252 /* this code causes bugs */
253 int limit;
255 if(bPtr->usedColumnCount < bPtr->maxVisibleColumns)
256 limit = bPtr->usedColumnCount;
257 else
258 limit = bPtr->maxVisibleColumns;
260 for (i=column; i < limit; i++) {
261 if (bPtr->titles[i])
262 free(bPtr->titles[i]);
263 bPtr->titles[i] = NULL;
265 WMClearList(bPtr->columns[i]);
266 bPtr->usedColumnCount--;
268 #else
269 for (i=column; i < bPtr->maxVisibleColumns; i++) {
270 if (bPtr->titles[i])
271 free(bPtr->titles[i]);
272 bPtr->titles[i] = NULL;
274 WMClearList(bPtr->columns[i]);
275 bPtr->usedColumnCount--;
277 tmp = bPtr->columnCount;
278 for (i=bPtr->maxVisibleColumns; i < tmp; i++) {
279 if (bPtr->titles[i])
280 free(bPtr->titles[i]);
281 bPtr->titles[i] = NULL;
283 WMDestroyWidget(bPtr->columns[i]);
284 bPtr->columns[i] = NULL;
285 bPtr->columnCount--;
286 bPtr->usedColumnCount--;
288 #endif
289 } else {
290 int tmp = bPtr->columnCount;
291 for (i=column; i < tmp; i++) {
292 if (bPtr->titles[i])
293 free(bPtr->titles[i]);
294 bPtr->titles[i] = NULL;
296 WMDestroyWidget(bPtr->columns[i]);
297 bPtr->columns[i] = NULL;
298 bPtr->columnCount--;
299 bPtr->usedColumnCount--;
302 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
303 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
304 memcpy(clist, bPtr->columns, sizeof(WMList*)*bPtr->columnCount);
305 memcpy(tlist, bPtr->titles, sizeof(char*)*bPtr->columnCount);
306 free(bPtr->titles);
307 free(bPtr->columns);
308 bPtr->titles = tlist;
309 bPtr->columns = clist;
314 WMListItem*
315 WMGetBrowserSelectedItemInColumn(WMBrowser *bPtr, int column)
317 if ((column < 0) || (column > bPtr->columnCount))
318 return NULL;
320 return WMGetListSelectedItem(bPtr->columns[column]);
326 WMGetBrowserSelectedColumn(WMBrowser *bPtr)
328 return bPtr->selectedColumn;
333 WMGetBrowserSelectedRowInColumn(WMBrowser *bPtr, int column)
335 if (column >= 0 && column < bPtr->columnCount) {
336 return WMGetListSelectedItemRow(bPtr->columns[column]);
337 } else {
338 return -1;
343 void
344 WMSetBrowserTitled(WMBrowser *bPtr, Bool flag)
346 int i;
347 int columnX, columnY;
349 if (bPtr->flags.isTitled == flag)
350 return;
352 columnX = 0;
354 if (!bPtr->flags.isTitled) {
355 columnY = TITLE_SPACING + bPtr->titleHeight;
357 bPtr->columnSize.height -= columnY;
359 for (i=0; i<bPtr->columnCount; i++) {
360 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
361 bPtr->columnSize.height);
363 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
365 WMMoveWidget(bPtr->columns[i], columnX, columnY);
367 } else {
368 bPtr->columnSize.height += TITLE_SPACING + bPtr->titleHeight;
370 for (i=0; i<bPtr->columnCount; i++) {
371 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
372 bPtr->columnSize.height);
374 columnX = WMWidgetView(bPtr->columns[i])->pos.x;
376 WMMoveWidget(bPtr->columns[i], columnX, 0);
380 bPtr->flags.isTitled = flag;
384 WMListItem*
385 WMAddSortedBrowserItem(WMBrowser *bPtr, int column, char *text, Bool isBranch)
387 WMListItem *item;
389 if (column < 0 || column >= bPtr->columnCount)
390 return NULL;
392 item = WMAddSortedListItem(bPtr->columns[column], text);
393 item->isBranch = isBranch;
395 return item;
400 WMListItem*
401 WMInsertBrowserItem(WMBrowser *bPtr, int column, int row, char *text,
402 Bool isBranch)
404 WMListItem *item;
406 if (column < 0 || column >= bPtr->columnCount)
407 return NULL;
409 item = WMInsertListItem(bPtr->columns[column], row, text);
410 item->isBranch = isBranch;
412 return item;
418 static void
419 resizeBrowser(WMWidget *w, unsigned int width, unsigned int height)
421 WMBrowser *bPtr = (WMBrowser*)w;
422 int cols = bPtr->maxVisibleColumns;
423 int colX, colY;
424 int i;
426 assert(width > 0);
427 assert(height > 0);
429 bPtr->columnSize.width = (width-(cols-1)*COLUMN_SPACING) / cols;
430 bPtr->columnSize.height = height;
432 if (bPtr->flags.isTitled) {
433 bPtr->columnSize.height -= TITLE_SPACING + bPtr->titleHeight;
434 colY = TITLE_SPACING + bPtr->titleHeight;
435 } else {
436 colY = 0;
439 if (bPtr->flags.hasScroller) {
440 bPtr->columnSize.height -= SCROLLER_WIDTH + 4;
442 if (bPtr->scroller) {
443 WMResizeWidget(bPtr->scroller, width-2, 1);
444 WMMoveWidget(bPtr->scroller, 1, height-SCROLLER_WIDTH-1);
448 colX = 0;
449 for (i = 0; i < bPtr->columnCount; i++) {
450 WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
451 bPtr->columnSize.height);
453 WMMoveWidget(bPtr->columns[i], colX, colY);
455 if (COLUMN_IS_VISIBLE(bPtr, i)) {
456 colX += bPtr->columnSize.width+COLUMN_SPACING;
460 W_ResizeView(bPtr->view, width, height);
464 static void
465 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
466 WMRect *rect)
468 WMView *view = W_VIEW(lPtr);
469 W_Screen *scr = view->screen;
470 int width, height, x, y;
472 width = rect->size.width;
473 height = rect->size.height;
474 x = rect->pos.x;
475 y = rect->pos.y;
477 if (state & WLDSSelected)
478 XFillRectangle(scr->display, d, W_GC(scr->white), x, y,
479 width, height);
480 else
481 XClearArea(scr->display, d, x, y, width, height, False);
483 if (text) {
484 W_PaintText(view, d, scr->normalFont, x+4, y, width,
485 WALeft, W_GC(scr->black), False, text, strlen(text));
488 if (state & WLDSIsBranch) {
489 XDrawLine(scr->display, d, W_GC(scr->darkGray), x+width-11, y+3,
490 x+width-6, y+height/2);
491 if (state & WLDSSelected)
492 XDrawLine(scr->display, d,W_GC(scr->gray), x+width-11, y+height-5,
493 x+width-6, y+height/2);
494 else
495 XDrawLine(scr->display, d,W_GC(scr->white), x+width-11, y+height-5,
496 x+width-6, y+height/2);
497 XDrawLine(scr->display, d, W_GC(scr->black), x+width-12, y+3,
498 x+width-12, y+height-5);
503 static void
504 scrollCallback(WMWidget *scroller, void *self)
506 WMBrowser *bPtr = (WMBrowser*)self;
507 WMScroller *sPtr = (WMScroller*)scroller;
508 int newFirst;
509 #define LAST_VISIBLE_COLUMN bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
511 switch (WMGetScrollerHitPart(sPtr)) {
512 case WSDecrementLine:
513 if (bPtr->firstVisibleColumn > 0) {
514 scrollToColumn(bPtr, bPtr->firstVisibleColumn-1);
516 break;
518 case WSDecrementPage:
519 if (bPtr->firstVisibleColumn > 0) {
520 newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
522 scrollToColumn(bPtr, newFirst);
524 break;
527 case WSIncrementLine:
528 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
529 scrollToColumn(bPtr, bPtr->firstVisibleColumn+1);
531 break;
533 case WSIncrementPage:
534 if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
535 newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
537 if (newFirst+bPtr->maxVisibleColumns >= bPtr->columnCount)
538 newFirst = bPtr->columnCount - bPtr->maxVisibleColumns;
540 scrollToColumn(bPtr, newFirst);
542 break;
544 case WSKnob:
546 float floatValue;
547 float value = bPtr->columnCount - bPtr->maxVisibleColumns;
549 floatValue = WMGetScrollerValue(bPtr->scroller);
551 floatValue = (floatValue*value)/value;
553 newFirst = floatValue*(float)(bPtr->columnCount - bPtr->maxVisibleColumns);
555 if (bPtr->firstVisibleColumn != newFirst)
556 scrollToColumn(bPtr, newFirst);
557 else
558 WMSetScrollerParameters(bPtr->scroller, floatValue,
559 bPtr->maxVisibleColumns/(float)bPtr->columnCount);
562 break;
564 case WSKnobSlot:
565 case WSNoPart:
566 /* do nothing */
567 break;
569 #undef LAST_VISIBLE_COLUMN
573 static void
574 setupScroller(WMBrowser *bPtr)
576 WMScroller *sPtr;
577 int y;
579 y = bPtr->view->size.height - SCROLLER_WIDTH - 1;
581 sPtr = WMCreateScroller(bPtr);
582 WMSetScrollerAction(sPtr, scrollCallback, bPtr);
583 WMMoveWidget(sPtr, 1, y);
584 WMResizeWidget(sPtr, bPtr->view->size.width-2, SCROLLER_WIDTH);
586 bPtr->scroller = sPtr;
588 WMMapWidget(sPtr);
592 void
593 WMSetBrowserAction(WMBrowser *bPtr, WMAction *action, void *clientData)
595 bPtr->action = action;
596 bPtr->clientData = clientData;
600 void
601 WMSetBrowserHasScroller(WMBrowser *bPtr, int hasScroller)
603 bPtr->flags.hasScroller = hasScroller;
608 Bool
609 WMSetBrowserPath(WMBrowser *bPtr, char *path)
611 int i;
612 char *str = wstrdup(path);
613 char *tmp;
614 int item;
615 Bool ok = True;
616 WMListItem *listItem;
618 removeColumn(bPtr, 1);
620 i = 0;
621 tmp = strtok(str, bPtr->pathSeparator);
622 while (tmp) {
623 /* select it in the column */
624 item = WMFindRowOfListItemWithTitle(bPtr->columns[i], tmp);
625 if (item<0) {
626 ok = False;
627 break;
629 WMSelectListItem(bPtr->columns[i], item);
630 WMSetListPosition(bPtr->columns[i], item);
632 listItem = WMGetListItem(bPtr->columns[i], item);
633 if (!listItem || !listItem->isBranch) {
634 break;
637 /* load next column */
638 WMAddBrowserColumn(bPtr);
640 loadColumn(bPtr, i+1);
642 tmp = strtok(NULL, bPtr->pathSeparator);
644 i++;
646 free(str);
648 bPtr->selectedColumn = bPtr->usedColumnCount - 1;
650 scrollToColumn(bPtr, bPtr->columnCount-bPtr->maxVisibleColumns);
652 return ok;
656 char*
657 WMGetBrowserPath(WMBrowser *bPtr)
659 return WMGetBrowserPathToColumn(bPtr, bPtr->columnCount);
663 char*
664 WMGetBrowserPathToColumn(WMBrowser *bPtr, int column)
666 int i, size;
667 char *path;
668 WMListItem *item;
670 if (column >= bPtr->usedColumnCount)
671 column = bPtr->usedColumnCount-1;
673 /* calculate size of buffer */
674 size = 0;
675 for (i = 0; i <= column; i++) {
676 item = WMGetListSelectedItem(bPtr->columns[i]);
677 if (!item)
678 break;
679 size += strlen(item->text);
682 /* get the path */
683 path = wmalloc(size+(column+1)*strlen(bPtr->pathSeparator)+1);
684 /* ignore first / */
685 *path = 0;
686 for (i = 0; i <= column; i++) {
687 strcat(path, bPtr->pathSeparator);
688 item = WMGetListSelectedItem(bPtr->columns[i]);
689 if (!item)
690 break;
691 strcat(path, item->text);
694 return path;
698 static void
699 loadColumn(WMBrowser *bPtr, int column)
701 assert(bPtr->fillColumn);
703 bPtr->flags.loadingColumn = 1;
704 (*bPtr->fillColumn)(bPtr, column);
705 bPtr->flags.loadingColumn = 0;
709 static void
710 paintBrowser(WMBrowser *bPtr)
712 int i;
714 if (!bPtr->view->flags.mapped)
715 return;
717 W_DrawRelief(bPtr->view->screen, bPtr->view->window, 0,
718 bPtr->view->size.height-SCROLLER_WIDTH-2,
719 bPtr->view->size.width, 22, WRSunken);
721 if (bPtr->flags.isTitled) {
722 for (i=0; i<bPtr->maxVisibleColumns; i++) {
723 drawTitleOfColumn(bPtr, i+bPtr->firstVisibleColumn);
729 static void
730 handleEvents(XEvent *event, void *data)
732 WMBrowser *bPtr = (WMBrowser*)data;
734 CHECK_CLASS(data, WC_Browser);
737 switch (event->type) {
738 case Expose:
739 paintBrowser(bPtr);
740 break;
742 case DestroyNotify:
743 destroyBrowser(bPtr);
744 break;
751 static void
752 scrollToColumn(WMBrowser *bPtr, int column)
754 int i;
755 int x;
756 int notify = 0;
759 if (column != bPtr->firstVisibleColumn)
760 notify = 1;
762 if (column < 0)
763 column = 0;
765 x = 0;
766 bPtr->firstVisibleColumn = column;
767 for (i = 0; i < bPtr->usedColumnCount; i++) {
768 if (COLUMN_IS_VISIBLE(bPtr, i)) {
769 WMMoveWidget(bPtr->columns[i], x,
770 WMWidgetView(bPtr->columns[i])->pos.y);
771 if (!WMWidgetView(bPtr->columns[i])->flags.realized)
772 WMRealizeWidget(bPtr->columns[i]);
773 WMMapWidget(bPtr->columns[i]);
774 x += bPtr->columnSize.width+COLUMN_SPACING;
775 } else {
776 WMUnmapWidget(bPtr->columns[i]);
780 /* update the scroller */
781 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
782 float value, proportion;
784 value = bPtr->firstVisibleColumn
785 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
786 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
787 WMSetScrollerParameters(bPtr->scroller, value, proportion);
788 } else {
789 WMSetScrollerParameters(bPtr->scroller, 0, 1);
792 if (bPtr->view->flags.mapped)
793 paintBrowser(bPtr);
795 if (notify)
796 WMPostNotificationName(WMBrowserDidScrollNotification, bPtr, NULL);
800 static void
801 listCallback(void *self, void *clientData)
803 WMBrowser *bPtr = (WMBrowser*)clientData;
804 WMList *lPtr = (WMList*)self;
805 WMListItem *item;
806 int i;
808 item = WMGetListSelectedItem(lPtr);
809 if (!item)
810 return;
812 for (i=0; i<bPtr->columnCount; i++) {
813 if (lPtr == bPtr->columns[i])
814 break;
816 assert(i<bPtr->columnCount);
818 bPtr->selectedColumn = i;
820 /* columns at right must be cleared */
821 removeColumn(bPtr, i+1);
822 /* open directory */
823 if (item->isBranch) {
824 WMAddBrowserColumn(bPtr);
825 loadColumn(bPtr, bPtr->usedColumnCount-1);
827 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
828 i = 0;
829 else
830 i = bPtr->usedColumnCount-bPtr->maxVisibleColumns;
831 scrollToColumn(bPtr, i);
833 /* call callback for click */
834 if (bPtr->action)
835 (*bPtr->action)(bPtr, bPtr->clientData);
839 void
840 WMLoadBrowserColumnZero(WMBrowser *bPtr)
842 if (!bPtr->flags.loaded) {
843 /* create column 0 */
844 WMAddBrowserColumn(bPtr);
846 loadColumn(bPtr, 0);
848 /* make column 0 visible */
849 scrollToColumn(bPtr, 0);
851 bPtr->flags.loaded = 1;
856 void
857 WMRemoveBrowserItem(WMBrowser *bPtr, int column, int row)
859 WMList *list;
861 if (column < 0 || column >= bPtr->usedColumnCount)
862 return;
864 list = WMGetBrowserListInColumn(bPtr, column);
866 if (row < 0 || row >= WMGetListNumberOfRows(list))
867 return;
869 removeColumn(bPtr, column+1);
870 if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
871 scrollToColumn(bPtr, 0);
872 else
873 scrollToColumn(bPtr, bPtr->usedColumnCount-bPtr->maxVisibleColumns);
875 WMRemoveListItem(list, row);
880 WMAddBrowserColumn(WMBrowser *bPtr)
882 WMList *list;
883 WMList **clist;
884 char **tlist;
885 int colY;
886 int index;
889 if (bPtr->usedColumnCount < bPtr->columnCount) {
890 return bPtr->usedColumnCount++;
893 bPtr->usedColumnCount++;
895 if (bPtr->flags.isTitled) {
896 colY = TITLE_SPACING + bPtr->titleHeight;
897 } else {
898 colY = 0;
901 index = bPtr->columnCount;
902 bPtr->columnCount++;
903 clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
904 tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
905 memcpy(clist, bPtr->columns, sizeof(WMList*)*(bPtr->columnCount-1));
906 memcpy(tlist, bPtr->titles, sizeof(char*)*(bPtr->columnCount-1));
907 if (bPtr->columns)
908 free(bPtr->columns);
909 if (bPtr->titles)
910 free(bPtr->titles);
911 bPtr->columns = clist;
912 bPtr->titles = tlist;
914 bPtr->titles[index] = NULL;
916 list = WMCreateList(bPtr);
917 WMSetListAction(list, listCallback, bPtr);
918 WMSetListUserDrawProc(list, paintItem);
919 bPtr->columns[index] = list;
921 WMResizeWidget(list, bPtr->columnSize.width, bPtr->columnSize.height);
922 WMMoveWidget(list, (bPtr->columnSize.width+COLUMN_SPACING)*index, colY);
923 if (COLUMN_IS_VISIBLE(bPtr, index))
924 WMMapWidget(list);
926 /* update the scroller */
927 if (bPtr->columnCount > bPtr->maxVisibleColumns) {
928 float value, proportion;
930 value = bPtr->firstVisibleColumn
931 /(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
932 proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
933 WMSetScrollerParameters(bPtr->scroller, value, proportion);
936 return index;
941 static void
942 destroyBrowser(WMBrowser *bPtr)
944 int i;
946 for (i=0; i<bPtr->columnCount; i++) {
947 if (bPtr->titles[i])
948 free(bPtr->titles[i]);
950 free(bPtr->titles);
952 free(bPtr->pathSeparator);
954 free(bPtr);