Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wtabview.c
dissimilarity index 96%
index 00e2727..3ae4728 100644 (file)
-
-#include "WINGsP.h"
-
-
-typedef struct W_TabView {
-    W_Class widgetClass;
-    W_View *view;
-
-    struct W_TabViewItem **items;
-    int itemCount;
-    int maxItems;             /* size of items array, can be increased */
-
-    int selectedItem;
-    int firstVisible;
-
-    int visibleTabs;
-
-    WMFont *font;
-
-    WMColor *lightGray;
-    WMColor *tabColor;
-
-    WMTabViewDelegate *delegate;
-
-    short tabHeight;
-
-    struct {
-        WMReliefType relief:4;
-        WMTitlePosition titlePosition:4;
-        WMTabViewType type:2;
-
-        unsigned enabled:1;
-        unsigned tabbed:1;
-        unsigned dontFitAll:1;
-        unsigned bordered:1;
-        unsigned uniformTabs:1;
-    } flags;
-} TabView;
-
-
-typedef struct W_TabViewItem {
-    WMTabView *tabView;
-
-    W_View *view;
-
-    char *label;
-
-    short tabWidth;
-    int identifier;
-
-    struct {
-        unsigned visible:1;
-        unsigned enabled:1;
-    } flags;
-} W_TabViewItem;
-
-
-
-
-
-
-#define DEFAULT_WIDTH  40
-#define DEFAULT_HEIGHT 40
-
-#define NORMAL_SIDE_OFFSET 8
-#define BUTTONED_SIDE_OFFSET 15
-
-
-static void destroyTabView(TabView *tPtr);
-static void paintTabView(TabView *tPtr);
-
-
-static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
-
-static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect,
-                        Bool enabled);
-
-static void W_UnmapTabViewItem(WMTabViewItem *item);
-
-static void W_MapTabViewItem(WMTabViewItem *item);
-
-static WMView *W_TabViewItemView(WMTabViewItem *item);
-
-static int W_TabViewItemTabWidth(WMTabViewItem *item);
-
-static void W_SetTabViewItemTabWidth(WMTabViewItem *item, int width);
-
-
-static void recalcTabWidth(TabView *tPtr);
-static void rearrange(TabView *tPtr);
-
-static void didResize(struct W_ViewDelegate*, WMView*);
-
-static W_ViewDelegate delegate = {
-    NULL,
-    NULL,
-    didResize,
-    NULL,
-    NULL
-};
-
-
-static int
-positionOfTab(WMTabView *tabView, int tab)
-{
-    int i;
-    int offs;
-
-    if (tab < tabView->firstVisible)
-        return -1;
-
-    if (tab > tabView->firstVisible + tabView->visibleTabs)
-        return -1;
-
-    if (tabView->flags.dontFitAll)
-        offs = BUTTONED_SIDE_OFFSET;
-    else
-        offs = NORMAL_SIDE_OFFSET;
-
-    for (i = tabView->firstVisible; i < tab; i++)
-        offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
-
-    return offs;
-}
-
-
-static int
-countVisibleTabs(TabView *tPtr, int first)
-{
-    int i;
-    int width;
-
-    if (first < 0) {
-        width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
-        first = 0;
-    } else {
-        width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
-    }
-
-    for (i = first; i < tPtr->itemCount; i++) {
-        width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
-        if (width <= 0) {
-            return i - first;
-        }
-    }
-    return i - first;
-}
-
-
-
-static void
-handleEvents(XEvent *event, void *data)
-{
-    TabView *tPtr = (TabView*)data;
-
-    CHECK_CLASS(data, WC_TabView);
-
-    switch (event->type) {
-    case Expose:
-        if (event->xexpose.count!=0)
-            break;
-        paintTabView(tPtr);
-        break;
-
-    case ButtonPress:
-        if (tPtr->flags.enabled) {
-            WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
-                                                       event->xbutton.x,
-                                                       event->xbutton.y);
-            /*if (item && !item->flags.enabled)
-             break;*/
-
-            if (item && item->flags.enabled) {
-                WMSelectTabViewItem(tPtr, item);
-            } else if (tPtr->flags.dontFitAll) {
-                int redraw = 0;
-                int lastVisible = tPtr->firstVisible+tPtr->visibleTabs-1;
-
-                if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
-                    if (tPtr->firstVisible > 0) {
-                        redraw = 1;
-                        tPtr->firstVisible--;
-                    }
-                } else if (event->xbutton.x > positionOfTab(tPtr,lastVisible)){
-
-                    if (lastVisible < tPtr->itemCount-1) {
-                        redraw = 1;
-                        tPtr->firstVisible++;
-                    }
-                }
-                tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
-                if (redraw) {
-                    paintTabView(tPtr);
-                }
-            }
-        }
-        break;
-
-    case DestroyNotify:
-        destroyTabView(tPtr);
-        break;
-    }
-}
-
-
-
-WMTabView*
-WMCreateTabView(WMWidget *parent)
-{
-    TabView *tPtr;
-    WMScreen *scr = WMWidgetScreen(parent);
-
-    tPtr = wmalloc(sizeof(TabView));
-    memset(tPtr, 0, sizeof(TabView));
-
-    tPtr->widgetClass = WC_TabView;
-
-    tPtr->view = W_CreateView(W_VIEW(parent));
-    if (!tPtr->view) {
-        wfree(tPtr);
-        return NULL;
-    }
-    tPtr->view->self = tPtr;
-    tPtr->view->delegate = &delegate;
-
-    tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
-    tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
-
-    tPtr->font = WMRetainFont(scr->normalFont);
-
-    tPtr->flags.type = WTTopTabsBevelBorder;
-    tPtr->flags.bordered = 1;
-    tPtr->flags.uniformTabs = 0;
-    tPtr->flags.enabled = 1;
-
-    WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
-                         |ButtonPressMask, handleEvents, tPtr);
-
-    WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
-
-    tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
-
-    return tPtr;
-}
-
-
-void
-WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
-{
-    tPtr->delegate = delegate;
-}
-
-
-WMTabViewItem*
-WMAddTabViewItemWithView(WMTabView *tPtr, WMView *view, int identifier,
-                         char *label)
-{
-    WMTabViewItem *item;
-
-    item = WMCreateTabViewItemWithIdentifier(identifier);
-    WMSetTabViewItemView(item, view);
-    WMAddItemInTabView(tPtr, item);
-    WMSetTabViewItemLabel(item, label);
-
-    return item;
-}
-
-
-void
-WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
-{
-    WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
-}
-
-
-void
-WMSetTabViewEnabled(WMTabView *tPtr, Bool flag)
-{
-    tPtr->flags.enabled = ((flag==0) ? 0 : 1);
-    if (W_VIEW_REALIZED(tPtr->view))
-        paintTabView(tPtr);
-}
-
-
-void
-WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
-{
-    wassertr(W_TabViewItemView(item) != NULL);
-
-    if (tPtr->maxItems == tPtr->itemCount) {
-        WMTabViewItem **items;
-
-        items = wrealloc(tPtr->items,
-                         sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
-        memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
-        tPtr->items = items;
-        tPtr->maxItems += 10;
-    }
-
-    if (index > tPtr->itemCount)
-        index = tPtr->itemCount;
-
-    if (index == 0 && tPtr->items[0]) {
-        W_UnmapTabViewItem(tPtr->items[0]);
-    }
-
-    if (index < tPtr->itemCount) {
-        memmove(tPtr->items + index + 1, tPtr->items + index,
-                (tPtr->itemCount - index) * sizeof(WMTabViewItem*));
-    }
-
-    tPtr->items[index] = item;
-
-    tPtr->itemCount++;
-
-    recalcTabWidth(tPtr);
-
-    W_SetTabViewItemParent(item, tPtr);
-
-    W_UnmapTabViewItem(item);
-
-    if (tPtr->flags.bordered) {
-        W_ReparentView(W_TabViewItemView(item), tPtr->view, 1,
-                       tPtr->tabHeight + 1);
-
-        W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
-                     tPtr->view->size.height - tPtr->tabHeight - 3);
-    } else {
-        W_ReparentView(W_TabViewItemView(item), tPtr->view, 0,
-                       tPtr->tabHeight);
-
-        W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
-                     tPtr->view->size.height - tPtr->tabHeight);
-    }
-
-    if (index == 0) {
-        W_MapTabViewItem(item);
-    }
-    if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
-        (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
-
-    if (W_VIEW_REALIZED(tPtr->view))
-        paintTabView(tPtr);
-}
-
-
-void
-WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
-{
-    int i;
-
-    for (i = 0; i < tPtr->itemCount; i++) {
-        if (tPtr->items[i] == item) {
-            if (i < tPtr->itemCount - 1)
-                memmove(&tPtr->items[i], &tPtr->items[i + 1],
-                        tPtr->itemCount - i - 1);
-            else
-                tPtr->items[i] = NULL;
-
-            W_SetTabViewItemParent(item, NULL);
-
-            tPtr->itemCount--;
-            break;
-        }
-    }
-    if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
-        (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
-}
-
-
-
-static Bool
-isInside(int x, int y, int width, int height, int px, int py)
-{
-    if (py >= y + height - 3 && py <= y + height
-        && px >= x + py - (y + height - 3)
-        && px <= x + width - (py - (y + height - 3))) {
-
-        return True;
-    }
-    if (py >= y + 3 && py < y + height - 3
-        && px >= x + 3 + ((y + 3) - py)*3/7
-        && px <= x + width - 3 - ((y + 3) - py)*3/7) {
-
-        return True;
-    }
-    if (py >= y && py < y + 3
-        && px >= x + 7 + py - y
-        && px <= x + width - 7 - (py - y)) {
-
-        return True;
-    }
-    return False;
-}
-
-
-WMTabViewItem*
-WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
-{
-    int i;
-    int count = tPtr->visibleTabs;
-    int first = tPtr->firstVisible;
-
-    if (tPtr->flags.dontFitAll) {
-        i = tPtr->selectedItem - tPtr->firstVisible;
-        if (i >= 0 && i < tPtr->visibleTabs
-            && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
-                        W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]),
-                        tPtr->tabHeight, x, y)) {
-            return tPtr->items[tPtr->selectedItem];
-        }
-    } else {
-        i = tPtr->selectedItem;
-        if (isInside(positionOfTab(tPtr, i), 0,
-                     W_TabViewItemTabWidth(tPtr->items[i]),
-                     tPtr->tabHeight, x, y)) {
-            return tPtr->items[i];
-        }
-    }
-
-    for (i = first; i < first + count; i++) {
-        int pos;
-
-        pos = positionOfTab(tPtr, i);
-        if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]),
-                     tPtr->tabHeight, x, y)) {
-            return tPtr->items[i];
-        }
-    }
-    return NULL;
-}
-
-
-void
-WMSetTabViewType(WMTabView *tPtr, WMTabViewType type)
-{
-    tPtr->flags.type = type;
-
-    if (type != WTTopTabsBevelBorder)
-        tPtr->tabHeight = 0;
-    else
-        tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
-
-    if (type == WTNoTabsNoBorder)
-        tPtr->flags.bordered = 0;
-    else
-        tPtr->flags.bordered = 1;
-
-    rearrange(tPtr);
-}
-
-void
-WMSelectFirstTabViewItem(WMTabView *tPtr)
-{
-    WMSelectTabViewItemAtIndex(tPtr, 0);
-}
-
-
-void
-WMSelectLastTabViewItem(WMTabView *tPtr)
-{
-    WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
-}
-
-
-void
-WMSelectNextTabViewItem(WMTabView *tPtr)
-{
-    WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
-}
-
-
-void
-WMSelectPreviousTabViewItem(WMTabView *tPtr)
-{
-    WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
-}
-
-
-WMTabViewItem*
-WMGetSelectedTabViewItem(WMTabView *tPtr)
-{
-    return tPtr->items[tPtr->selectedItem];
-}
-
-
-void
-WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
-{
-    int i;
-
-    for (i = 0; i < tPtr->itemCount; i++) {
-        if (tPtr->items[i] == item) {
-            WMSelectTabViewItemAtIndex(tPtr, i);
-            break;
-        }
-    }
-}
-
-
-void
-WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
-{
-    WMTabViewItem *item;
-
-    if (index == tPtr->selectedItem) {
-        return;
-    }
-
-    if (index < 0)
-        index = 0;
-    else if (index >= tPtr->itemCount)
-        index = tPtr->itemCount - 1;
-
-    item = tPtr->items[tPtr->selectedItem];
-
-    if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
-        if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
-                                                 tPtr->items[index]))
-            return;
-
-    if (tPtr->delegate && tPtr->delegate->willSelectItem)
-        (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
-                                          tPtr->items[index]);
-
-    W_UnmapTabViewItem(item);
-
-
-    item = tPtr->items[index];
-
-    W_MapTabViewItem(item);
-
-    tPtr->selectedItem = index;
-
-    if (tPtr->delegate && tPtr->delegate->didSelectItem)
-        (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
-                                         tPtr->items[index]);
-
-    paintTabView(tPtr);
-}
-
-
-
-static void
-recalcTabWidth(TabView *tPtr)
-{
-    int i;
-    /*int twidth = W_VIEW(tPtr)->size.width;*/
-    int width;
-
-    if (tPtr->flags.uniformTabs) {
-        int tabWidth;
-
-        tabWidth = 0;
-
-        for (i = 0; i < tPtr->itemCount; i++) {
-            char *str = WMGetTabViewItemLabel(tPtr->items[i]);
-
-            if (str) {
-                width = WMWidthOfString(tPtr->font, str, strlen(str));
-                if (width > tabWidth)
-                    tabWidth = width;
-            }
-        }
-
-        tabWidth = tabWidth + 30;
-
-        for (i = 0; i < tPtr->itemCount; i++)
-            W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
-
-        tPtr->firstVisible = 0;
-        tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
-        if (tPtr->visibleTabs < tPtr->itemCount)
-            tPtr->flags.dontFitAll = 1;
-        else
-            tPtr->flags.dontFitAll = 0;
-    } else {
-        for (i = 0; i < tPtr->itemCount; i++) {
-            char *str = WMGetTabViewItemLabel(tPtr->items[i]);
-            if (!str)
-                continue;
-
-            width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
-
-            W_SetTabViewItemTabWidth(tPtr->items[i], width);
-        }
-
-        if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
-            tPtr->flags.dontFitAll = 1;
-            tPtr->firstVisible = 0;
-            tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
-        } else {
-            tPtr->flags.dontFitAll = 0;
-            tPtr->firstVisible = 0;
-            tPtr->visibleTabs = tPtr->itemCount;
-        }
-    }
-}
-
-
-static void
-drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
-           unsigned int height)
-{
-    Display *dpy = scr->display;
-    GC bgc = WMColorGC(scr->black);
-    GC wgc = WMColorGC(scr->white);
-    GC dgc = WMColorGC(scr->darkGray);
-
-    XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
-
-    XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
-    XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
-
-    XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
-    XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
-}
-
-
-static void
-drawTab(TabView *tPtr, Drawable d, int x, int y,
-        unsigned width, unsigned height, Bool selected)
-{
-    WMScreen *scr = W_VIEW(tPtr)->screen;
-    Display *dpy = scr->display;
-    GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
-    GC black = WMColorGC(scr->black);
-    GC dark = WMColorGC(scr->darkGray);
-    GC light = WMColorGC(scr->gray);
-    XPoint trap[8];
-
-    trap[0].x = x + (selected ? 0 : 1);
-    trap[0].y = y + height - (selected ? 0 : 1);
-
-    trap[1].x = x + 3;
-    trap[1].y = y + height - 3;
-
-    trap[2].x = x + 10 - 3;
-    trap[2].y = y + 3;
-
-    trap[3].x = x + 10;
-    trap[3].y = y;
-
-    trap[4].x = x + width - 10;
-    trap[4].y = y;
-
-    trap[5].x = x + width - 10 + 3;
-    trap[5].y = y + 3;
-
-    trap[6].x = x + width - 3;
-    trap[6].y = y + height - 3;
-
-    trap[7].x = x + width - (selected ? 0 : 1);
-    trap[7].y = y + height - (selected ? 0 : 1);
-
-    XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
-                 Convex, CoordModeOrigin);
-
-    XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
-    XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
-    XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
-    XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
-    XDrawLine(dpy, d, dark,  trap[4].x, trap[4].y, trap[5].x, trap[5].y);
-    XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
-    XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
-
-    XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
-              trap[0].x, trap[0].y, trap[7].x, trap[7].y);
-}
-
-
-static void
-paintDot(TabView *tPtr, Drawable d, int x, int y)
-{
-    WMScreen *scr = W_VIEW(tPtr)->screen;
-    Display *dpy = scr->display;
-    GC white = WMColorGC(scr->white);
-    GC black = WMColorGC(scr->black);
-
-    XFillRectangle(dpy, d, black, x, y, 2, 2);
-    XDrawPoint(dpy, d, white, x, y);
-}
-
-
-
-static void
-paintTabView(TabView *tPtr)
-{
-    Pixmap buffer;
-    WMScreen *scr = W_VIEW(tPtr)->screen;
-    Display *dpy = scr->display;
-    GC white = WMColorGC(scr->white);
-    int i;
-
-    if (tPtr->flags.type == WTTopTabsBevelBorder) {
-        int count = tPtr->visibleTabs;
-        int first = tPtr->firstVisible;
-        int moreAtLeft;
-        int moreAtRight;
-        int selectedIsVisible;
-        int ty;
-        int twidth, theight;
-
-        ty = 2;
-        theight = tPtr->tabHeight;
-
-        buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
-                               W_VIEW(tPtr)->size.width, theight,
-                               W_VIEW(tPtr)->screen->depth);
-
-        XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
-                       0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
-
-        if (tPtr->flags.dontFitAll) {
-            moreAtLeft = first > 0;
-            moreAtRight = (first + count) < tPtr->itemCount;
-            if (tPtr->selectedItem >= first
-                && tPtr->selectedItem < first + count)
-                selectedIsVisible = 1;
-            else
-                selectedIsVisible = 0;
-        } else {
-            moreAtLeft = 0;
-            moreAtRight = 0;
-            selectedIsVisible = 1;
-        }
-
-        if (moreAtRight) {
-            drawTab(tPtr, buffer, positionOfTab(tPtr, first+count), 0,
-                    W_VIEW_WIDTH(tPtr->view), theight, False);
-        }
-        for (i = first + count-1; i >= first; i--) {
-            if (!selectedIsVisible || i != tPtr->selectedItem) {
-                twidth = W_TabViewItemTabWidth(tPtr->items[i]);
-
-                drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0,
-                        twidth, theight, False);
-            }
-        }
-        if (moreAtLeft) {
-            drawTab(tPtr, buffer, positionOfTab(tPtr, 0)-2*BUTTONED_SIDE_OFFSET,
-                    0, BUTTONED_SIDE_OFFSET*4, theight, False);
-        }
-
-        if (selectedIsVisible) {
-            int idx = tPtr->selectedItem;
-
-            drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
-                    0, W_TabViewItemTabWidth(tPtr->items[idx]),
-                    theight, True);
-
-            XDrawLine(dpy, buffer, white, 0, theight - 1,
-                      positionOfTab(tPtr, idx), theight - 1);
-
-            XDrawLine(dpy, buffer, white,
-                      positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
-                      tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1,
-                      tPtr->tabHeight - 1);
-        } else {
-            XDrawLine(dpy, buffer, white, 0, theight - 1,
-                      W_VIEW_WIDTH(tPtr->view), theight - 1);
-        }
-
-        for (i = 0; i < count; i++) {
-            WMRect rect;
-
-            rect.pos.x = 15 + positionOfTab(tPtr, first+i);
-            rect.pos.y = ty;
-            rect.size.width = W_TabViewItemTabWidth(tPtr->items[first+i]);
-            rect.size.height = theight;
-            W_DrawLabel(tPtr->items[first+i], buffer, rect,
-                        tPtr->flags.enabled &&
-                        tPtr->items[first+i]->flags.enabled);
-        }
-
-        if (moreAtLeft) {
-            paintDot(tPtr, buffer, 4, 10);
-            paintDot(tPtr, buffer, 7, 10);
-            paintDot(tPtr, buffer, 10, 10);
-        }
-        if (moreAtRight) {
-            int x;
-
-            x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
-
-            x = x + (W_VIEW_WIDTH(tPtr->view) - x)/2;
-            paintDot(tPtr, buffer, x + 5, 10);
-            paintDot(tPtr, buffer, x + 8, 10);
-            paintDot(tPtr, buffer, x + 11, 10);
-        }
-
-        XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
-                  W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
-
-        XFreePixmap(dpy, buffer);
-    }
-    switch (tPtr->flags.type) {
-    case WTTopTabsBevelBorder:
-        drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
-                   W_VIEW(tPtr)->size.width,
-                   W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
-        break;
-
-    case WTNoTabsBevelBorder:
-        W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
-                     W_VIEW(tPtr)->size.height, WRRaised);
-        break;
-
-    case WTNoTabsLineBorder:
-        W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
-                     W_VIEW(tPtr)->size.height, WRSimple);
-        break;
-
-    case WTNoTabsNoBorder:
-        break;
-    }
-}
-
-
-static void
-rearrange(TabView *tPtr)
-{
-    int i;
-    int width, height;
-    int bordered = tPtr->flags.bordered;
-
-    recalcTabWidth(tPtr);
-
-    width = tPtr->view->size.width - (bordered ? 3 : 0);
-    height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
-
-    for (i = 0; i < tPtr->itemCount; i++) {
-        W_MoveView(W_TabViewItemView(tPtr->items[i]),
-                   1*bordered, tPtr->tabHeight + 1*bordered);
-        W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
-    }
-    if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
-        paintTabView(tPtr);
-}
-
-
-static void
-didResize(struct W_ViewDelegate *deleg, WMView *view)
-{
-    rearrange(view->self);
-}
-
-
-static void
-destroyTabView(TabView *tPtr)
-{
-    int i;
-
-    for (i = 0; i < tPtr->itemCount; i++) {
-        WMSetTabViewItemView(tPtr->items[i], NULL);
-        WMDestroyTabViewItem(tPtr->items[i]);
-    }
-    wfree(tPtr->items);
-
-    WMReleaseColor(tPtr->lightGray);
-    WMReleaseColor(tPtr->tabColor);
-    WMReleaseFont(tPtr->font);
-
-    wfree(tPtr);
-}
-
-/******************************************************************/
-
-
-static void
-W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
-{
-    item->tabView = parent;
-}
-
-
-static void
-W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect, Bool enabled)
-{
-    WMScreen *scr = W_VIEW(item->tabView)->screen;
-
-    if (!item->label)
-        return;
-
-    WMDrawString(scr, d, enabled ? scr->black : scr->darkGray,
-                 item->tabView->font, rect.pos.x, rect.pos.y,
-                 item->label, strlen(item->label));
-}
-
-
-static void
-W_UnmapTabViewItem(WMTabViewItem *item)
-{
-    wassertr(item->view);
-
-    W_UnmapView(item->view);
-
-    item->flags.visible = 0;
-}
-
-
-static void
-W_MapTabViewItem(WMTabViewItem *item)
-{
-    wassertr(item->view);
-
-    W_MapView(item->view);
-    W_RaiseView(item->view);
-
-    item->flags.visible = 1;
-}
-
-
-static WMView*
-W_TabViewItemView(WMTabViewItem *item)
-{
-    return item->view;
-}
-
-
-static int
-W_TabViewItemTabWidth(WMTabViewItem *item)
-{
-    return item->tabWidth;
-}
-
-
-static void
-W_SetTabViewItemTabWidth(WMTabViewItem *item, int width)
-{
-    item->tabWidth = width;
-}
-
-
-WMTabViewItem*
-WMCreateTabViewItemWithIdentifier(int identifier)
-{
-    WMTabViewItem *item;
-
-    item = wmalloc(sizeof(WMTabViewItem));
-    memset(item, 0, sizeof(WMTabViewItem));
-
-    item->identifier = identifier;
-
-    item->flags.enabled = 1;
-
-    return item;
-}
-
-
-WMTabViewItem*
-WMCreateTabViewItem(int identifier, char *label)
-{
-    WMTabViewItem *item;
-
-    item = wmalloc(sizeof(WMTabViewItem));
-    memset(item, 0, sizeof(WMTabViewItem));
-
-    item->identifier = identifier;
-
-    item->flags.enabled = 1;
-
-    WMSetTabViewItemLabel(item, label);
-
-    return item;
-}
-
-
-void
-WMSetTabViewItemEnabled(WMTabViewItem *tPtr, Bool flag)
-{
-    tPtr->flags.enabled = ((flag==0) ? 0 : 1);
-    if (tPtr->tabView && W_VIEW_REALIZED(tPtr->tabView->view))
-        paintTabView(tPtr->tabView);
-}
-
-
-int
-WMGetTabViewItemIdentifier(WMTabViewItem *item)
-{
-    return item->identifier;
-}
-
-
-void
-WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
-{
-    if (tPtr->font)
-        WMReleaseFont(tPtr->font);
-
-    tPtr->font = WMRetainFont(font);
-    tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
-    recalcTabWidth(tPtr);
-}
-
-
-void
-WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
-{
-    if (item->label)
-        wfree(item->label);
-
-    if (label)
-        item->label = wstrdup(label);
-    else
-        item->label = NULL;
-
-    if (item->tabView)
-        recalcTabWidth(item->tabView);
-}
-
-
-char*
-WMGetTabViewItemLabel(WMTabViewItem *item)
-{
-    return item->label;
-}
-
-
-void
-WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
-{
-    item->view = view;
-}
-
-
-WMView*
-WMGetTabViewItemView(WMTabViewItem *item)
-{
-    return item->view;
-}
-
-
-void
-WMDestroyTabViewItem(WMTabViewItem *item)
-{
-    if (item->label)
-        wfree(item->label);
-
-    if (item->view)
-        W_DestroyView(item->view);
-
-    wfree(item);
-}
-
+
+#include "WINGsP.h"
+
+typedef struct W_TabView {
+       W_Class widgetClass;
+       W_View *view;
+
+       struct W_TabViewItem **items;
+       int itemCount;
+       int maxItems;           /* size of items array, can be increased */
+
+       int selectedItem;
+       int firstVisible;
+
+       int visibleTabs;
+
+       WMFont *font;
+
+       WMColor *lightGray;
+       WMColor *tabColor;
+
+       WMTabViewDelegate *delegate;
+
+       short tabHeight;
+
+       struct {
+               WMReliefType relief:4;
+               WMTitlePosition titlePosition:4;
+               WMTabViewType type:2;
+
+               unsigned enabled:1;
+               unsigned tabbed:1;
+               unsigned dontFitAll:1;
+               unsigned bordered:1;
+               unsigned uniformTabs:1;
+       } flags;
+} TabView;
+
+typedef struct W_TabViewItem {
+       WMTabView *tabView;
+
+       W_View *view;
+
+       char *label;
+
+       short tabWidth;
+       int identifier;
+
+       struct {
+               unsigned visible:1;
+               unsigned enabled:1;
+       } flags;
+} W_TabViewItem;
+
+#define DEFAULT_WIDTH  40
+#define DEFAULT_HEIGHT 40
+
+#define NORMAL_SIDE_OFFSET 8
+#define BUTTONED_SIDE_OFFSET 15
+
+static void destroyTabView(TabView * tPtr);
+static void paintTabView(TabView * tPtr);
+
+static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent);
+
+static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled);
+
+static void W_UnmapTabViewItem(WMTabViewItem * item);
+
+static void W_MapTabViewItem(WMTabViewItem * item);
+
+static WMView *W_TabViewItemView(WMTabViewItem * item);
+
+static int W_TabViewItemTabWidth(WMTabViewItem * item);
+
+static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width);
+
+static void recalcTabWidth(TabView * tPtr);
+static void rearrange(TabView * tPtr);
+
+static void didResize(struct W_ViewDelegate *, WMView *);
+
+static W_ViewDelegate delegate = {
+       NULL,
+       NULL,
+       didResize,
+       NULL,
+       NULL
+};
+
+static int positionOfTab(WMTabView * tabView, int tab)
+{
+       int i;
+       int offs;
+
+       if (tab < tabView->firstVisible)
+               return -1;
+
+       if (tab > tabView->firstVisible + tabView->visibleTabs)
+               return -1;
+
+       if (tabView->flags.dontFitAll)
+               offs = BUTTONED_SIDE_OFFSET;
+       else
+               offs = NORMAL_SIDE_OFFSET;
+
+       for (i = tabView->firstVisible; i < tab; i++)
+               offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
+
+       return offs;
+}
+
+static int countVisibleTabs(TabView * tPtr, int first)
+{
+       int i;
+       int width;
+
+       if (first < 0) {
+               width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
+               first = 0;
+       } else {
+               width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
+       }
+
+       for (i = first; i < tPtr->itemCount; i++) {
+               width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
+               if (width <= 0) {
+                       return i - first;
+               }
+       }
+       return i - first;
+}
+
+static void handleEvents(XEvent * event, void *data)
+{
+       TabView *tPtr = (TabView *) data;
+
+       CHECK_CLASS(data, WC_TabView);
+
+       switch (event->type) {
+       case Expose:
+               if (event->xexpose.count != 0)
+                       break;
+               paintTabView(tPtr);
+               break;
+
+       case ButtonPress:
+               if (tPtr->flags.enabled) {
+                       WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
+                                                                  event->xbutton.x,
+                                                                  event->xbutton.y);
+                       /*if (item && !item->flags.enabled)
+                          break; */
+
+                       if (item && item->flags.enabled) {
+                               WMSelectTabViewItem(tPtr, item);
+                       } else if (tPtr->flags.dontFitAll) {
+                               int redraw = 0;
+                               int lastVisible = tPtr->firstVisible + tPtr->visibleTabs - 1;
+
+                               if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
+                                       if (tPtr->firstVisible > 0) {
+                                               redraw = 1;
+                                               tPtr->firstVisible--;
+                                       }
+                               } else if (event->xbutton.x > positionOfTab(tPtr, lastVisible)) {
+
+                                       if (lastVisible < tPtr->itemCount - 1) {
+                                               redraw = 1;
+                                               tPtr->firstVisible++;
+                                       }
+                               }
+                               tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
+                               if (redraw) {
+                                       paintTabView(tPtr);
+                               }
+                       }
+               }
+               break;
+
+       case DestroyNotify:
+               destroyTabView(tPtr);
+               break;
+       }
+}
+
+WMTabView *WMCreateTabView(WMWidget * parent)
+{
+       TabView *tPtr;
+       WMScreen *scr = WMWidgetScreen(parent);
+
+       tPtr = wmalloc(sizeof(TabView));
+       memset(tPtr, 0, sizeof(TabView));
+
+       tPtr->widgetClass = WC_TabView;
+
+       tPtr->view = W_CreateView(W_VIEW(parent));
+       if (!tPtr->view) {
+               wfree(tPtr);
+               return NULL;
+       }
+       tPtr->view->self = tPtr;
+       tPtr->view->delegate = &delegate;
+
+       tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
+       tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
+
+       tPtr->font = WMRetainFont(scr->normalFont);
+
+       tPtr->flags.type = WTTopTabsBevelBorder;
+       tPtr->flags.bordered = 1;
+       tPtr->flags.uniformTabs = 0;
+       tPtr->flags.enabled = 1;
+
+       WMCreateEventHandler(tPtr->view, ExposureMask | StructureNotifyMask | ButtonPressMask, handleEvents, tPtr);
+
+       WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+
+       tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
+
+       return tPtr;
+}
+
+void WMSetTabViewDelegate(WMTabView * tPtr, WMTabViewDelegate * delegate)
+{
+       tPtr->delegate = delegate;
+}
+
+WMTabViewItem *WMAddTabViewItemWithView(WMTabView * tPtr, WMView * view, int identifier, char *label)
+{
+       WMTabViewItem *item;
+
+       item = WMCreateTabViewItemWithIdentifier(identifier);
+       WMSetTabViewItemView(item, view);
+       WMAddItemInTabView(tPtr, item);
+       WMSetTabViewItemLabel(item, label);
+
+       return item;
+}
+
+void WMAddItemInTabView(WMTabView * tPtr, WMTabViewItem * item)
+{
+       WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
+}
+
+void WMSetTabViewEnabled(WMTabView * tPtr, Bool flag)
+{
+       tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
+       if (W_VIEW_REALIZED(tPtr->view))
+               paintTabView(tPtr);
+}
+
+void WMInsertItemInTabView(WMTabView * tPtr, int index, WMTabViewItem * item)
+{
+       wassertr(W_TabViewItemView(item) != NULL);
+
+       if (tPtr->maxItems == tPtr->itemCount) {
+               WMTabViewItem **items;
+
+               items = wrealloc(tPtr->items, sizeof(WMTabViewItem *) * (tPtr->maxItems + 10));
+               memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem *) * 10);
+               tPtr->items = items;
+               tPtr->maxItems += 10;
+       }
+
+       if (index > tPtr->itemCount)
+               index = tPtr->itemCount;
+
+       if (index == 0 && tPtr->items[0]) {
+               W_UnmapTabViewItem(tPtr->items[0]);
+       }
+
+       if (index < tPtr->itemCount) {
+               memmove(tPtr->items + index + 1, tPtr->items + index,
+                       (tPtr->itemCount - index) * sizeof(WMTabViewItem *));
+       }
+
+       tPtr->items[index] = item;
+
+       tPtr->itemCount++;
+
+       recalcTabWidth(tPtr);
+
+       W_SetTabViewItemParent(item, tPtr);
+
+       W_UnmapTabViewItem(item);
+
+       if (tPtr->flags.bordered) {
+               W_ReparentView(W_TabViewItemView(item), tPtr->view, 1, tPtr->tabHeight + 1);
+
+               W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
+                            tPtr->view->size.height - tPtr->tabHeight - 3);
+       } else {
+               W_ReparentView(W_TabViewItemView(item), tPtr->view, 0, tPtr->tabHeight);
+
+               W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
+                            tPtr->view->size.height - tPtr->tabHeight);
+       }
+
+       if (index == 0) {
+               W_MapTabViewItem(item);
+       }
+       if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
+               (*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
+
+       if (W_VIEW_REALIZED(tPtr->view))
+               paintTabView(tPtr);
+}
+
+void WMRemoveTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
+{
+       int i;
+
+       for (i = 0; i < tPtr->itemCount; i++) {
+               if (tPtr->items[i] == item) {
+                       if (i < tPtr->itemCount - 1)
+                               memmove(&tPtr->items[i], &tPtr->items[i + 1], tPtr->itemCount - i - 1);
+                       else
+                               tPtr->items[i] = NULL;
+
+                       W_SetTabViewItemParent(item, NULL);
+
+                       tPtr->itemCount--;
+                       break;
+               }
+       }
+       if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
+               (*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
+}
+
+static Bool isInside(int x, int y, int width, int height, int px, int py)
+{
+       if (py >= y + height - 3 && py <= y + height && px >= x + py - (y + height - 3)
+           && px <= x + width - (py - (y + height - 3))) {
+
+               return True;
+       }
+       if (py >= y + 3 && py < y + height - 3
+           && px >= x + 3 + ((y + 3) - py) * 3 / 7 && px <= x + width - 3 - ((y + 3) - py) * 3 / 7) {
+
+               return True;
+       }
+       if (py >= y && py < y + 3 && px >= x + 7 + py - y && px <= x + width - 7 - (py - y)) {
+
+               return True;
+       }
+       return False;
+}
+
+WMTabViewItem *WMTabViewItemAtPoint(WMTabView * tPtr, int x, int y)
+{
+       int i;
+       int count = tPtr->visibleTabs;
+       int first = tPtr->firstVisible;
+
+       if (tPtr->flags.dontFitAll) {
+               i = tPtr->selectedItem - tPtr->firstVisible;
+               if (i >= 0 && i < tPtr->visibleTabs
+                   && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
+                               W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]), tPtr->tabHeight, x, y)) {
+                       return tPtr->items[tPtr->selectedItem];
+               }
+       } else {
+               i = tPtr->selectedItem;
+               if (isInside(positionOfTab(tPtr, i), 0,
+                            W_TabViewItemTabWidth(tPtr->items[i]), tPtr->tabHeight, x, y)) {
+                       return tPtr->items[i];
+               }
+       }
+
+       for (i = first; i < first + count; i++) {
+               int pos;
+
+               pos = positionOfTab(tPtr, i);
+               if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]), tPtr->tabHeight, x, y)) {
+                       return tPtr->items[i];
+               }
+       }
+       return NULL;
+}
+
+void WMSetTabViewType(WMTabView * tPtr, WMTabViewType type)
+{
+       tPtr->flags.type = type;
+
+       if (type != WTTopTabsBevelBorder)
+               tPtr->tabHeight = 0;
+       else
+               tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
+
+       if (type == WTNoTabsNoBorder)
+               tPtr->flags.bordered = 0;
+       else
+               tPtr->flags.bordered = 1;
+
+       rearrange(tPtr);
+}
+
+void WMSelectFirstTabViewItem(WMTabView * tPtr)
+{
+       WMSelectTabViewItemAtIndex(tPtr, 0);
+}
+
+void WMSelectLastTabViewItem(WMTabView * tPtr)
+{
+       WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
+}
+
+void WMSelectNextTabViewItem(WMTabView * tPtr)
+{
+       WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
+}
+
+void WMSelectPreviousTabViewItem(WMTabView * tPtr)
+{
+       WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
+}
+
+WMTabViewItem *WMGetSelectedTabViewItem(WMTabView * tPtr)
+{
+       return tPtr->items[tPtr->selectedItem];
+}
+
+void WMSelectTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
+{
+       int i;
+
+       for (i = 0; i < tPtr->itemCount; i++) {
+               if (tPtr->items[i] == item) {
+                       WMSelectTabViewItemAtIndex(tPtr, i);
+                       break;
+               }
+       }
+}
+
+void WMSelectTabViewItemAtIndex(WMTabView * tPtr, int index)
+{
+       WMTabViewItem *item;
+
+       if (index == tPtr->selectedItem) {
+               return;
+       }
+
+       if (index < 0)
+               index = 0;
+       else if (index >= tPtr->itemCount)
+               index = tPtr->itemCount - 1;
+
+       item = tPtr->items[tPtr->selectedItem];
+
+       if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
+               if (!(*tPtr->delegate->shouldSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]))
+                       return;
+
+       if (tPtr->delegate && tPtr->delegate->willSelectItem)
+               (*tPtr->delegate->willSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
+
+       W_UnmapTabViewItem(item);
+
+       item = tPtr->items[index];
+
+       W_MapTabViewItem(item);
+
+       tPtr->selectedItem = index;
+
+       if (tPtr->delegate && tPtr->delegate->didSelectItem)
+               (*tPtr->delegate->didSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
+
+       paintTabView(tPtr);
+}
+
+static void recalcTabWidth(TabView * tPtr)
+{
+       int i;
+       /*int twidth = W_VIEW(tPtr)->size.width; */
+       int width;
+
+       if (tPtr->flags.uniformTabs) {
+               int tabWidth;
+
+               tabWidth = 0;
+
+               for (i = 0; i < tPtr->itemCount; i++) {
+                       char *str = WMGetTabViewItemLabel(tPtr->items[i]);
+
+                       if (str) {
+                               width = WMWidthOfString(tPtr->font, str, strlen(str));
+                               if (width > tabWidth)
+                                       tabWidth = width;
+                       }
+               }
+
+               tabWidth = tabWidth + 30;
+
+               for (i = 0; i < tPtr->itemCount; i++)
+                       W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
+
+               tPtr->firstVisible = 0;
+               tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
+               if (tPtr->visibleTabs < tPtr->itemCount)
+                       tPtr->flags.dontFitAll = 1;
+               else
+                       tPtr->flags.dontFitAll = 0;
+       } else {
+               for (i = 0; i < tPtr->itemCount; i++) {
+                       char *str = WMGetTabViewItemLabel(tPtr->items[i]);
+                       if (!str)
+                               continue;
+
+                       width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
+
+                       W_SetTabViewItemTabWidth(tPtr->items[i], width);
+               }
+
+               if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
+                       tPtr->flags.dontFitAll = 1;
+                       tPtr->firstVisible = 0;
+                       tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
+               } else {
+                       tPtr->flags.dontFitAll = 0;
+                       tPtr->firstVisible = 0;
+                       tPtr->visibleTabs = tPtr->itemCount;
+               }
+       }
+}
+
+static void drawRelief(W_Screen * scr, Drawable d, int x, int y, unsigned int width, unsigned int height)
+{
+       Display *dpy = scr->display;
+       GC bgc = WMColorGC(scr->black);
+       GC wgc = WMColorGC(scr->white);
+       GC dgc = WMColorGC(scr->darkGray);
+
+       XDrawLine(dpy, d, wgc, x, y, x, y + height - 1);
+
+       XDrawLine(dpy, d, bgc, x, y + height - 1, x + width - 1, y + height - 1);
+       XDrawLine(dpy, d, dgc, x + 1, y + height - 2, x + width - 2, y + height - 2);
+
+       XDrawLine(dpy, d, bgc, x + width - 1, y, x + width - 1, y + height - 1);
+       XDrawLine(dpy, d, dgc, x + width - 2, y + 1, x + width - 2, y + height - 2);
+}
+
+static void drawTab(TabView * tPtr, Drawable d, int x, int y, unsigned width, unsigned height, Bool selected)
+{
+       WMScreen *scr = W_VIEW(tPtr)->screen;
+       Display *dpy = scr->display;
+       GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
+       GC black = WMColorGC(scr->black);
+       GC dark = WMColorGC(scr->darkGray);
+       GC light = WMColorGC(scr->gray);
+       XPoint trap[8];
+
+       trap[0].x = x + (selected ? 0 : 1);
+       trap[0].y = y + height - (selected ? 0 : 1);
+
+       trap[1].x = x + 3;
+       trap[1].y = y + height - 3;
+
+       trap[2].x = x + 10 - 3;
+       trap[2].y = y + 3;
+
+       trap[3].x = x + 10;
+       trap[3].y = y;
+
+       trap[4].x = x + width - 10;
+       trap[4].y = y;
+
+       trap[5].x = x + width - 10 + 3;
+       trap[5].y = y + 3;
+
+       trap[6].x = x + width - 3;
+       trap[6].y = y + height - 3;
+
+       trap[7].x = x + width - (selected ? 0 : 1);
+       trap[7].y = y + height - (selected ? 0 : 1);
+
+       XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8, Convex, CoordModeOrigin);
+
+       XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
+       XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
+       XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
+       XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
+       XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
+       XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
+       XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
+
+       XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white), trap[0].x, trap[0].y, trap[7].x, trap[7].y);
+}
+
+static void paintDot(TabView * tPtr, Drawable d, int x, int y)
+{
+       WMScreen *scr = W_VIEW(tPtr)->screen;
+       Display *dpy = scr->display;
+       GC white = WMColorGC(scr->white);
+       GC black = WMColorGC(scr->black);
+
+       XFillRectangle(dpy, d, black, x, y, 2, 2);
+       XDrawPoint(dpy, d, white, x, y);
+}
+
+static void paintTabView(TabView * tPtr)
+{
+       Pixmap buffer;
+       WMScreen *scr = W_VIEW(tPtr)->screen;
+       Display *dpy = scr->display;
+       GC white = WMColorGC(scr->white);
+       int i;
+
+       if (tPtr->flags.type == WTTopTabsBevelBorder) {
+               int count = tPtr->visibleTabs;
+               int first = tPtr->firstVisible;
+               int moreAtLeft;
+               int moreAtRight;
+               int selectedIsVisible;
+               int ty;
+               int twidth, theight;
+
+               ty = 2;
+               theight = tPtr->tabHeight;
+
+               buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
+                                      W_VIEW(tPtr)->size.width, theight, W_VIEW(tPtr)->screen->depth);
+
+               XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
+                              0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
+
+               if (tPtr->flags.dontFitAll) {
+                       moreAtLeft = first > 0;
+                       moreAtRight = (first + count) < tPtr->itemCount;
+                       if (tPtr->selectedItem >= first && tPtr->selectedItem < first + count)
+                               selectedIsVisible = 1;
+                       else
+                               selectedIsVisible = 0;
+               } else {
+                       moreAtLeft = 0;
+                       moreAtRight = 0;
+                       selectedIsVisible = 1;
+               }
+
+               if (moreAtRight) {
+                       drawTab(tPtr, buffer, positionOfTab(tPtr, first + count), 0,
+                               W_VIEW_WIDTH(tPtr->view), theight, False);
+               }
+               for (i = first + count - 1; i >= first; i--) {
+                       if (!selectedIsVisible || i != tPtr->selectedItem) {
+                               twidth = W_TabViewItemTabWidth(tPtr->items[i]);
+
+                               drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0, twidth, theight, False);
+                       }
+               }
+               if (moreAtLeft) {
+                       drawTab(tPtr, buffer, positionOfTab(tPtr, 0) - 2 * BUTTONED_SIDE_OFFSET,
+                               0, BUTTONED_SIDE_OFFSET * 4, theight, False);
+               }
+
+               if (selectedIsVisible) {
+                       int idx = tPtr->selectedItem;
+
+                       drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
+                               0, W_TabViewItemTabWidth(tPtr->items[idx]), theight, True);
+
+                       XDrawLine(dpy, buffer, white, 0, theight - 1, positionOfTab(tPtr, idx), theight - 1);
+
+                       XDrawLine(dpy, buffer, white,
+                                 positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
+                                 tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1, tPtr->tabHeight - 1);
+               } else {
+                       XDrawLine(dpy, buffer, white, 0, theight - 1, W_VIEW_WIDTH(tPtr->view), theight - 1);
+               }
+
+               for (i = 0; i < count; i++) {
+                       WMRect rect;
+
+                       rect.pos.x = 15 + positionOfTab(tPtr, first + i);
+                       rect.pos.y = ty;
+                       rect.size.width = W_TabViewItemTabWidth(tPtr->items[first + i]);
+                       rect.size.height = theight;
+                       W_DrawLabel(tPtr->items[first + i], buffer, rect,
+                                   tPtr->flags.enabled && tPtr->items[first + i]->flags.enabled);
+               }
+
+               if (moreAtLeft) {
+                       paintDot(tPtr, buffer, 4, 10);
+                       paintDot(tPtr, buffer, 7, 10);
+                       paintDot(tPtr, buffer, 10, 10);
+               }
+               if (moreAtRight) {
+                       int x;
+
+                       x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
+
+                       x = x + (W_VIEW_WIDTH(tPtr->view) - x) / 2;
+                       paintDot(tPtr, buffer, x + 5, 10);
+                       paintDot(tPtr, buffer, x + 8, 10);
+                       paintDot(tPtr, buffer, x + 11, 10);
+               }
+
+               XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
+                         W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
+
+               XFreePixmap(dpy, buffer);
+       }
+       switch (tPtr->flags.type) {
+       case WTTopTabsBevelBorder:
+               drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
+                          W_VIEW(tPtr)->size.width, W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
+               break;
+
+       case WTNoTabsBevelBorder:
+               W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
+                            W_VIEW(tPtr)->size.height, WRRaised);
+               break;
+
+       case WTNoTabsLineBorder:
+               W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
+                            W_VIEW(tPtr)->size.height, WRSimple);
+               break;
+
+       case WTNoTabsNoBorder:
+               break;
+       }
+}
+
+static void rearrange(TabView * tPtr)
+{
+       int i;
+       int width, height;
+       int bordered = tPtr->flags.bordered;
+
+       recalcTabWidth(tPtr);
+
+       width = tPtr->view->size.width - (bordered ? 3 : 0);
+       height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
+
+       for (i = 0; i < tPtr->itemCount; i++) {
+               W_MoveView(W_TabViewItemView(tPtr->items[i]), 1 * bordered, tPtr->tabHeight + 1 * bordered);
+               W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
+       }
+       if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
+               paintTabView(tPtr);
+}
+
+static void didResize(struct W_ViewDelegate *deleg, WMView * view)
+{
+       rearrange(view->self);
+}
+
+static void destroyTabView(TabView * tPtr)
+{
+       int i;
+
+       for (i = 0; i < tPtr->itemCount; i++) {
+               WMSetTabViewItemView(tPtr->items[i], NULL);
+               WMDestroyTabViewItem(tPtr->items[i]);
+       }
+       wfree(tPtr->items);
+
+       WMReleaseColor(tPtr->lightGray);
+       WMReleaseColor(tPtr->tabColor);
+       WMReleaseFont(tPtr->font);
+
+       wfree(tPtr);
+}
+
+/******************************************************************/
+
+static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent)
+{
+       item->tabView = parent;
+}
+
+static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled)
+{
+       WMScreen *scr = W_VIEW(item->tabView)->screen;
+
+       if (!item->label)
+               return;
+
+       WMDrawString(scr, d, enabled ? scr->black : scr->darkGray,
+                    item->tabView->font, rect.pos.x, rect.pos.y, item->label, strlen(item->label));
+}
+
+static void W_UnmapTabViewItem(WMTabViewItem * item)
+{
+       wassertr(item->view);
+
+       W_UnmapView(item->view);
+
+       item->flags.visible = 0;
+}
+
+static void W_MapTabViewItem(WMTabViewItem * item)
+{
+       wassertr(item->view);
+
+       W_MapView(item->view);
+       W_RaiseView(item->view);
+
+       item->flags.visible = 1;
+}
+
+static WMView *W_TabViewItemView(WMTabViewItem * item)
+{
+       return item->view;
+}
+
+static int W_TabViewItemTabWidth(WMTabViewItem * item)
+{
+       return item->tabWidth;
+}
+
+static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width)
+{
+       item->tabWidth = width;
+}
+
+WMTabViewItem *WMCreateTabViewItemWithIdentifier(int identifier)
+{
+       WMTabViewItem *item;
+
+       item = wmalloc(sizeof(WMTabViewItem));
+       memset(item, 0, sizeof(WMTabViewItem));
+
+       item->identifier = identifier;
+
+       item->flags.enabled = 1;
+
+       return item;
+}
+
+WMTabViewItem *WMCreateTabViewItem(int identifier, char *label)
+{
+       WMTabViewItem *item;
+
+       item = wmalloc(sizeof(WMTabViewItem));
+       memset(item, 0, sizeof(WMTabViewItem));
+
+       item->identifier = identifier;
+
+       item->flags.enabled = 1;
+
+       WMSetTabViewItemLabel(item, label);
+
+       return item;
+}
+
+void WMSetTabViewItemEnabled(WMTabViewItem * tPtr, Bool flag)
+{
+       tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
+       if (tPtr->tabView && W_VIEW_REALIZED(tPtr->tabView->view))
+               paintTabView(tPtr->tabView);
+}
+
+int WMGetTabViewItemIdentifier(WMTabViewItem * item)
+{
+       return item->identifier;
+}
+
+void WMSetTabViewFont(WMTabView * tPtr, WMFont * font)
+{
+       if (tPtr->font)
+               WMReleaseFont(tPtr->font);
+
+       tPtr->font = WMRetainFont(font);
+       tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
+       recalcTabWidth(tPtr);
+}
+
+void WMSetTabViewItemLabel(WMTabViewItem * item, char *label)
+{
+       if (item->label)
+               wfree(item->label);
+
+       if (label)
+               item->label = wstrdup(label);
+       else
+               item->label = NULL;
+
+       if (item->tabView)
+               recalcTabWidth(item->tabView);
+}
+
+char *WMGetTabViewItemLabel(WMTabViewItem * item)
+{
+       return item->label;
+}
+
+void WMSetTabViewItemView(WMTabViewItem * item, WMView * view)
+{
+       item->view = view;
+}
+
+WMView *WMGetTabViewItemView(WMTabViewItem * item)
+{
+       return item->view;
+}
+
+void WMDestroyTabViewItem(WMTabViewItem * item)
+{
+       if (item->label)
+               wfree(item->label);
+
+       if (item->view)
+               W_DestroyView(item->view);
+
+       wfree(item);
+}