#include "WINGsP.h"

#include <wraster.h>
#include <ctype.h>


void
W_DrawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
             unsigned int height, WMReliefType relief)
{
    W_DrawReliefWithGC(scr, d, x, y, width, height, relief,
                       WMColorGC(scr->black), WMColorGC(scr->darkGray),
                       WMColorGC(scr->gray), WMColorGC(scr->white));
}


void
W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
                   unsigned int height, WMReliefType relief,
                   GC black, GC dark, GC light, GC white)
{
    Display *dpy = scr->display;
    GC bgc;
    GC wgc;
    GC lgc;
    GC dgc;

    switch (relief) {
    case WRSimple:
        XDrawRectangle(dpy, d, black, x, y, width-1, height-1);
        return;

    case WRRaised:
        bgc = black;
        dgc = dark;
        wgc = white;
        lgc = light;
        break;

    case WRSunken:
        wgc = dark;
        lgc = black;
        bgc = white;
        dgc = light;
        break;

    case WRPushed:
        lgc = wgc = black;
        dgc = bgc = white;
        break;

    case WRRidge:
        lgc = bgc = dark;
        dgc = wgc = white;
        break;

    case WRGroove:
        wgc = dgc = dark;
        lgc = bgc = white;
        break;

    default:
        return;
    }
    /* top left */
    XDrawLine(dpy, d, wgc, x, y, x+width-1, y);
    if (width > 2 && relief != WRRaised && relief!=WRPushed) {
        XDrawLine(dpy, d, lgc, x+1, y+1, x+width-3, y+1);
    }

    XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
    if (height > 2 && relief != WRRaised && relief!=WRPushed) {
        XDrawLine(dpy, d, lgc, x+1, y+1, x+1, y+height-3);
    }

    /* bottom right */
    XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
    if (width > 2 && relief!=WRPushed) {
        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);
    if (height > 2 && relief!=WRPushed) {
        XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
    }
}


static int
findNextWord(char *text, int limit)
{
    int pos, len;

    len = strcspn(text, " \t\n\r");
    pos = len + strspn(text+len, " \t\n\r");
    if (pos > limit)
        pos = limit;

    return pos;
}


static int
fitText(char *text, WMFont *font, int width, int wrap)
{
    int i, w, beforecrlf, word1, word2;

    /* text length before first cr/lf */
    beforecrlf = strcspn(text, "\n");

    if (!wrap || beforecrlf==0)
        return beforecrlf;

    w = WMWidthOfString(font, text, beforecrlf);
    if (w <= width) {
        /* text up to first crlf fits */
        return beforecrlf;
    }

    word1 = 0;
    while (1) {
        word2 = word1 + findNextWord(text+word1, beforecrlf-word1);
        if (word2 >= beforecrlf)
            break;
        w = WMWidthOfString(font, text, word2);
        if (w > width)
            break;
        word1 = word2;
    }

    for (i=word1; i<word2; i++) {
        w = WMWidthOfString(font, text, i);
        if (w > width) {
            break;
        }
    }

    /* keep words complete if possible */
    if (!isspace(text[i]) && word1>0) {
        i = word1;
    } else if (isspace(text[i]) && i<beforecrlf) {
        /* keep space on current row, so new row has next word in column 1 */
        i++;
    }

    return i;
}


#ifdef OLD_CODE
static int
fitText(char *text, WMFont *font, int width, int wrap)
{
    int i, j;
    int w;

    if (text[0]==0)
        return 0;

    i = 0;
    if (wrap) {
        if (text[0]=='\n')
            return 0;

        do {
            i++;
            w = WMWidthOfString(font, text, i);
        } while (w < width && text[i]!='\n' && text[i]!=0);

        if (text[i]=='\n')
            return i;

        /* keep words complete */
        if (!isspace(text[i])) {
            j = i;
            while (j>1 && !isspace(text[j]) && text[j]!=0)
                j--;
            if (j>1)
                i = j;
        }
    } else {
        i = strcspn(text, "\n");
    }
    return i;
}
#endif


int
W_GetTextHeight(WMFont *font, char *text, int width, int wrap)
{
    char *ptr = text;
    int count;
    int length = strlen(text);
    int h;
    int fheight = WMFontHeight(font);

    h = 0;
    while (length > 0) {
        count = fitText(ptr, font, width, wrap);

        h += fheight;

        if (isspace(ptr[count]))
            count++;

        ptr += count;
        length -= count;
    }
    return h;
}


void
W_PaintText(W_View *view, Drawable d, WMFont *font,  int x, int y,
            int width, WMAlignment alignment, WMColor *color,
            int wrap, char *text, int length)
{
    char *ptr = text;
    int line_width;
    int line_x;
    int count;
    int fheight = WMFontHeight(font);

    while (length > 0) {
        count = fitText(ptr, font, width, wrap);

        line_width = WMWidthOfString(font, ptr, count);
        if (alignment==WALeft)
            line_x = x;
        else if (alignment==WARight)
            line_x = x + width - line_width;
        else
            line_x = x + (width - line_width) / 2;

        WMDrawString(view->screen, d, color, font, line_x, y, ptr, count);

        if (wrap && ptr[count]!='\n')
            y += fheight;

        while (ptr[count] && ptr[count]=='\n') {
            y += fheight;
            count++;
        }

        ptr += count;
        length -= count;
    }
}


void
W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font,
                    WMReliefType relief, char *text,
                    WMAlignment alignment,  W_Pixmap *image,
                    WMImagePosition position, WMColor *backColor, int ofs)
{
    W_Screen *screen = view->screen;
    int ix, iy;
    int x, y, w, h;
    Drawable d = view->window;


#ifdef DOUBLE_BUFFER
    d = XCreatePixmap(screen->display, view->window,
                      view->size.width, view->size.height, screen->depth);
#endif

    /* background */
    if (backColor) {
        XFillRectangle(screen->display, d, WMColorGC(backColor),
                       0, 0, view->size.width, view->size.height);
    } else {
#ifndef DOUBLE_BUFFER
        XClearWindow(screen->display, d);
#else
        XSetForeground(screen->display, screen->copyGC,
                       view->attribs.background_pixel);
        XFillRectangle(screen->display, d, screen->copyGC, 0, 0,
                       view->size.width, view->size.height);
#endif
    }


    if (relief == WRFlat) {
        x = 0;
        y = 0;
        w = view->size.width;
        h = view->size.height;
    } else {
        x = 1;
        y = 1;
        w = view->size.width - 3;
        h = view->size.height - 3;
    }

    /* calc. image alignment */
    if (position!=WIPNoImage && image!=NULL) {
        switch (position) {
        case WIPOverlaps:
        case WIPImageOnly:
            ix = (view->size.width - image->width) / 2;
            iy = (view->size.height - image->height) / 2;
            /*
             x = 2;
             y = 0;
             */
            break;

        case WIPLeft:
            ix = x;
            iy = y + (h - image->height) / 2;
            x = x + image->width + 5;
            y = 0;
            w -= image->width + 5;
            break;

        case WIPRight:
            ix = view->size.width - image->width - x;
            iy = y + (h - image->height) / 2;
            w -= image->width + 5;
            break;

        case WIPBelow:
            ix = (view->size.width - image->width) / 2;
            iy = h - image->height;
            y = 0;
            h -= image->height;
            break;

        default:
        case WIPAbove:
            ix = (view->size.width - image->width) / 2;
            iy = y;
            y = image->height;
            h -= image->height;
            break;
        }

        ix += ofs;
        iy += ofs;

        XSetClipOrigin(screen->display, screen->clipGC, ix, iy);
        XSetClipMask(screen->display, screen->clipGC, image->mask);

        if (image->depth==1)
            XCopyPlane(screen->display, image->pixmap, d, screen->clipGC,
                       0, 0, image->width, image->height, ix, iy, 1);
        else
            XCopyArea(screen->display, image->pixmap, d, screen->clipGC,
                      0, 0, image->width, image->height, ix, iy);
    }

    /* draw text */
    if (position != WIPImageOnly && text!=NULL) {
        int textHeight;

        textHeight = W_GetTextHeight(font, text, w-8, wrap);
        W_PaintText(view, d, font, x+ofs+4, y+ofs + (h-textHeight)/2, w-8,
                    alignment, textColor, wrap, text, strlen(text));
    }


    /* draw relief */
    W_DrawRelief(screen, d, 0, 0, view->size.width, view->size.height, relief);

#ifdef DOUBLE_BUFFER
    XCopyArea(screen->display, d, view->window, screen->copyGC, 0, 0,
              view->size.width, view->size.height, 0, 0);
    XFreePixmap(screen->display, d);
#endif
}



WMPoint
wmkpoint(int x, int y)
{
    WMPoint point;

    point.x = x;
    point.y = y;

    return point;
}


WMSize
wmksize(unsigned int width, unsigned int height)
{
    WMSize size;

    size.width = width;
    size.height = height;

    return size;
}


WMRect
wmkrect(int x, int y, unsigned int width, unsigned int height)
{
    WMRect rect;

    rect.pos.x = x;
    rect.pos.y = y;
    rect.size.width = width;
    rect.size.height = height;

    return rect;
}





syntax highlighted by Code2HTML, v. 0.9.1