// bbmail.cpp for bbmail - an tool for display the mail in X11.
//
//  Copyright (c) 1998-2005 by John Kennis, jkennis@chello.nl
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// (See the included file COPYING / GPL-2.0)
//

#include "bbmail.h"
#include "config.h"
#include <string>

extern "C" {
#include <utime.h>
#include <dirent.h>
#include <X11/cursorfont.h>
#include <sys/stat.h>
#include <math.h>
}

#include "EWMH.hh"

#define SEPERATOR "/"

Checkmail::Checkmail(ToolWindow *toolwindow):
    m_pBbtool(toolwindow)
{
    timer = new bt::Timer(m_pBbtool, this) ;
    timer->setTimeout(m_pBbtool->getResource()->report.check_delay * 1000);
    timer->recurring(true);

    timer->start();
    broken = false;
    last_totalmail = 0;
    last_newmail = 0;
    new_mailbox = 0;
    newmail = 0;
    spoolfile = new
                LocalSpoolfile[m_pBbtool->getResource()->report.number_of_spoolfiles];
    number_of_checks = m_pBbtool->getResource()->report.force_check_delay;
}

Checkmail::~Checkmail()
{
    delete [] spoolfile;
    delete timer;
}

void Checkmail::reconfigure()
{
    delete [] spoolfile;
    spoolfile = new LocalSpoolfile[
            m_pBbtool->getResource()->report.number_of_spoolfiles];
    number_of_checks = m_pBbtool->getResource()->report.force_check_delay;
    timer->fireTimeout();
}

bool Checkmail::CheckMaildir(int spoolno)
{
    struct stat file_status, maildir_status;

    if (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty()) 
    {
        fprintf(stderr,"No qmail maildir specified\n");
        return(false);
    }

    if (stat(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
             &file_status)!=0) 
    {
        fprintf(stderr,"Could not read status spool file %s\n",
                m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
        return(false);
    }

    // check maildir new/

    if (stat(m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str(), 
              &maildir_status) != 0) 
    {
        fprintf(stderr,"Could not read status new maildir: %s\n",
                m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
        return(false);
    }
    if (maildir_status.st_mtime > file_status.st_mtime) 
    {
        file_status.st_mtime = maildir_status.st_mtime;
    }

    if (stat(m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str(), 
        &maildir_status) != 0)
    {
        fprintf(stderr,"Could not read status current maildir: %s\n",
             m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str());
        return(false);
    }
    if (maildir_status.st_mtime > file_status.st_mtime) 
    {
        file_status.st_mtime = maildir_status.st_mtime;
    }

    if  (file_status.st_mtime != spoolfile[spoolno].last_mtime) 
    {
        spoolfile[spoolno].last_mtime = file_status.st_mtime;
        spoolfile[spoolno].newmail=0;
        DIR *dir;

        if ((dir = opendir(
              m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str())
            ) == NULL) 
        {
            fprintf(stderr,"Could not open maildir %s\n",
              m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
            return false;
        }

        while (readdir (dir))
        {
            spoolfile[spoolno].newmail++;
        }
        /* -2 for . and .. */
        spoolfile[spoolno].newmail -= 2;
        closedir(dir);

        if ((dir = opendir(
            m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str())
            ) == NULL) 
        {
            fprintf(stderr,"Could not open maildir %s\n",
             m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
            return false;
        }

        spoolfile[spoolno].totalmail=spoolfile[spoolno].newmail;

        while (readdir (dir))
        {
            spoolfile[spoolno].totalmail++;
        }
        /* -2 for . and .. */
        spoolfile[spoolno].totalmail-=2;
        closedir(dir);
    }
    return(true);
}

bool Checkmail::CheckOther(int spoolno,bool force)
{
    struct stat file_status;
    FILE *fp;
    int num[2]={-1,-1};
    int number_of_values;


    if ((m_pBbtool->getResource()->spoolfile[spoolno].proc.empty())&
            (m_pBbtool->getResource()->spoolfile[spoolno].proc.empty())) 
    {
        fprintf(stderr,"Nothing to do, no proc defined\n");
        return(false);
    }
    if (!m_pBbtool->getResource()->spoolfile[spoolno].filename.empty()) 
    {
        if (stat(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
                 &file_status)!=0) 
        {
            fprintf(stderr,"Could not read status spool file %s\n",
                m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
            return(false);
        }
    }

    if  ((file_status.st_mtime != spoolfile[spoolno].last_mtime)&&
         (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty())||
         (force && m_pBbtool->getResource()->spoolfile[spoolno].force_check)) 
    {

        if (m_pBbtool->getResource()->spoolfile[spoolno].second_ignore)
        {
            number_of_values = 1;
        }
        else
        {
            number_of_values = 2;
        }

        spoolfile[spoolno].last_mtime = file_status.st_mtime;
        int old_newmail = spoolfile[spoolno].newmail;
        spoolfile[spoolno].newmail = 0;
        spoolfile[spoolno].totalmail = 0;

        if (!m_pBbtool->getResource()->spoolfile[spoolno].proc.empty()) 
        {
            if ((fp = (FILE*)popen(
                      m_pBbtool->getResource()->spoolfile[spoolno].proc.c_str(),
                      "r")) == NULL) 
            {
                fprintf(stderr,"Could not run command %s\n",
                    m_pBbtool->getResource()->spoolfile[spoolno].proc.c_str());
                return(false);
            } 
            else 
            {
                while (!(feof(fp))) 
                {
                    if (ReadPipe(fp,num,number_of_values) != 0) 
                    {
                        if (num[0] > old_newmail)
                        {
                            new_mailbox = spoolno;
                        }
#ifdef DEBUG
                        fprintf(stderr,"first int: %i, second int %i\n",num[0],num[1]);
#endif
                        spoolfile[spoolno].newmail += num[0];
                        spoolfile[spoolno].totalmail += num[1];
                    } 
                    else 
                    {
                        if ((num[0] == -1) & (num[1] == -1)) 
                        {
                            pclose(fp);
                            return(false);
                        }
                    }
                }
                pclose(fp);
            }
        }
        if  (!m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.empty())
        {
            if ((fp=(FILE*)popen(
              m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.c_str(),
              "r")) == NULL) 
            {
                fprintf(stderr,"Could not run command %s\n",
                        m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.c_str());
                return(false);
            } 
            else 
            {
                while (!(feof(fp))) 
                {
                    if (ReadPipe(fp,num,number_of_values)!=0) 
                    {
                        if (num[1]>old_newmail) new_mailbox = spoolno;
                        spoolfile[spoolno].newmail+=num[1];
                        spoolfile[spoolno].totalmail+=num[0];
                    }
                }
                pclose(fp);
            }
        }
        if (!m_pBbtool->getResource()->spoolfile[spoolno].first_is_new)
            spoolfile[spoolno].newmail=spoolfile[spoolno].totalmail-
                                       spoolfile[spoolno].newmail;
        if (!m_pBbtool->getResource()->spoolfile[spoolno].second_is_total)
            spoolfile[spoolno].totalmail=spoolfile[spoolno].newmail+
                                         spoolfile[spoolno].totalmail;

    }

    return(true);
}

void Checkmail::forceCheck()
{
    timer->fireTimeout();
}

bool Checkmail::getChar(const char *string,int *index)
{
    bool special = false;
    if (string[*index] == '\\') {
        (*index)++;
    } else {
        if ((string[*index] == '[')|(string[*index] == ']'))
            special = true;
    }
    return(special);
}

bool Checkmail::checkStatusFlag(char *status_flag,int spoolno)
{
    int i, x, len;
    bool passed;

    len = m_pBbtool->getResource()->spoolfile[spoolno].statusflag.length();
    for (i = 0, x = 0; i < len; i++, x++) {
        if (getChar(m_pBbtool->getResource()->spoolfile[spoolno].statusflag.c_str(), &i)) {
            if ((m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]=='[')) {
                passed=false;
                while ((m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]!=']')
                        & (i<len)) {
                    i++;

                    if (!getChar(m_pBbtool->getResource()->spoolfile[spoolno].statusflag.c_str(),
                                 &i))
                        if (m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]==
                                status_flag[x]) {
                            passed=true;
                        }
                }
                if (!passed) return false;
            } else {
                fprintf(stderr,"unexpected token in statusFlag\n");
            }
        } else
            if (m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]!=status_flag[x])
                return(false);
    }
    return(true);
}

bool Checkmail::CheckMbox(int spoolno)
{
    int readmail = 0;
    int mailcount = 0;
    FILE *spool_id;
    bool read_status = true;
    char mailbuf[128];
    struct stat file_status;
    struct utimbuf ut;

    if (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty()) {
        fprintf(stderr,"No mbox mailfile specified\n");
        return(false);
    }

    if (!(spool_id = fopen(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
                           "r"))) {
        fprintf(stderr,"Could not open mail spool file %s\n",
                m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
        return(false);
    }
    fstat(fileno(spool_id), &file_status);
    if(file_status.st_mtime != spoolfile[spoolno].last_mtime ||
            file_status.st_size != spoolfile[spoolno].last_size) {
        spoolfile[spoolno].last_mtime = file_status.st_mtime;
        spoolfile[spoolno].last_size = file_status.st_size;
        while(fgets(mailbuf, 127, spool_id)) {
            if(!strncmp(mailbuf, "From ", 5)) {
                mailcount++;
                read_status=False;
            } else
                if (checkStatusFlag(mailbuf,spoolno)) {
                    if(!read_status) {
                        readmail++;
                        read_status=True;
                    }
                } else if (!strncmp(mailbuf,"Subject",7)) {
                    if (!strncmp(&mailbuf[9],
                                 "DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA",49)!=0) {
                        mailcount--;
                        read_status=True;
                    }
                }

        }
        if ((mailcount - readmail) > spoolfile[spoolno].newmail)
            new_mailbox = spoolno;
        spoolfile[spoolno].newmail = mailcount - readmail;
        spoolfile[spoolno].totalmail = mailcount;
#ifdef DEBUG
        fprintf(stderr,"mailcount=%d, readmail=%d, spoolno=%d\n",mailcount,
                readmail,spoolno);
#endif
    }
    fclose(spool_id);
    ut.actime = file_status.st_atime;
    ut.modtime = file_status.st_mtime;
    utime(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(), &ut);
    return(true);
}

void Checkmail::timeout(bt::Timer *timer)
{
    int totalmail=0;
    bool change_raise=False;
    bool force=False;
    int i,old_total,old_new;
    bool redraw=False;
    newmail=0;
    broken=False;
    if (m_pBbtool->getResource()->report.force_check) {
        if (m_pBbtool->getResource()->report.force_check_delay==number_of_checks) {
            force=True;
            number_of_checks=0;
        } else {
            number_of_checks++;
#ifdef DEBUG
            fprintf(stderr,"number_of_checks %i\n",number_of_checks);
#endif
        }
    }
    for (i = 0; i < (int)m_pBbtool->getResource()->report.number_of_spoolfiles; i++) {
        old_new=spoolfile[i].newmail;
        old_total=spoolfile[i].totalmail;

        if (m_pBbtool->getResource()->spoolfile[i].type==SpoolList::other) {
            if (!(CheckOther(i,force))) {
                broken=True;
            } else {
                newmail+=spoolfile[i].newmail;
                totalmail+=spoolfile[i].totalmail;
                if ((spoolfile[i].newmail!=old_new)|(spoolfile[i].totalmail!=old_total))
                {
                    m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
                                                  spoolfile[i].totalmail,i);
                }
            }
        } else if (m_pBbtool->getResource()->spoolfile[i].type==SpoolList::mbox) {
            if (!(CheckMbox(i)))
                broken=True;
            else {
                totalmail+=spoolfile[i].totalmail;
                newmail+=spoolfile[i].newmail;
                if ((spoolfile[i].newmail != old_new) | (spoolfile[i].totalmail != old_total))
                    m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
                                                  spoolfile[i].totalmail,i);
            }
        } else if (m_pBbtool->getResource()->spoolfile[i].type == SpoolList::maildir) {
            if (!(CheckMaildir(i)))
                broken=True;
            else {
                totalmail+=spoolfile[i].totalmail;
                newmail+=spoolfile[i].newmail;
                if ((spoolfile[i].newmail!=old_new)|(spoolfile[i].totalmail!=old_total))
                    m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
                                                  spoolfile[i].totalmail,i);
            }
        }
    }
    if (newmail>last_newmail)
        change_raise = True;
    else {
        /* are there  ny not empty mailboxes left */
        for (i = 0; i < (int)m_pBbtool->getResource()->report.number_of_spoolfiles; i++) {
            if (spoolfile[i].newmail!=0) {
                new_mailbox=i;
                //        change_raise = True;
            }
        }
    }
    if ((newmail!=last_newmail)|(totalmail!=last_totalmail)|(broken) )
    {
        redraw=True;
    }
    last_newmail=newmail;
    last_totalmail=totalmail;
    if (redraw) m_pBbtool->redraw(change_raise);
}

int Checkmail::ReadPipe(FILE *fp,int num[2],int number_of_values)
{
    int i=0;
    bool found=False;
    bool newline=False;
    int x=0;
    char ch[6]={0,0,0,0,0,0};

    while (!(feof(fp))&(x!=number_of_values)&(ch[i]!='\n')&(!newline)) {
        fread(&ch[i],1,1,fp);
        while ((ch[i]>='0' && ch[i] <='9' && ch[1]!='\n')&(!feof(fp))) {
            i++;
            if (i==7) return(0);
            fread(&ch[i],1,1,fp);
            found=True;
        }
        if (ch[i]=='\n') newline=True;
        if (found) {
            ch[i]='\0';
            num[x]=atoi(ch);
            i=0;
            x++;
            found=False;
        }
    }
    /* skip to next line */
    while (!(feof(fp))&(ch[0]!='\n')&(!newline))
        fread(&ch[0],1,1,fp);
    return(x);
}


ToolWindow::ToolWindow(Configuration cml_options):
    bt::Application(cml_options.appName(), cml_options.displayName().c_str(), false),
    current_screen_info(display().screenInfo(DefaultScreen(XDisplay()))),
    _config(cml_options)
{
    
    checkmail = NULL;
    mbmenu = NULL;
    current_screen = DefaultScreen(XDisplay());
    wm_delete_window = XInternAtom (XDisplay(), "WM_DELETE_WINDOW",False);

    /* initialize xrm database */
    XrmInitialize();
    resource = new Resource(this, _config.rcFilename());
    frame_window = new FrameWindow(this);
    label_window = new LabelWindow(this);
    envelope_window = new EnvelopeWindow(this);

    if (resource->validMailbox()) {
        checkmail = new Checkmail(this);
        makeWindow(false);
        redraw(False);
        checkmail->forceCheck();
    } else {
        throw -1;
    }
    
}

ToolWindow::~ToolWindow()
{
    delete envelope_window;
    delete label_window;
    delete mbmenu;
    delete resource;
    delete checkmail;
    delete frame_window;
}


void ToolWindow::reconfigure(void)
{
    delete resource;
    resource = new Resource(this, _config.rcFilename());
    mbmenu->reconfigure();
    checkmail->reconfigure();

    makeWindow(true);

//    if (resource->show.label) XClearWindow(XDisplay(), label_window->window());
//    XClearWindow(XDisplay(), envelope_window->window());
//    XClearWindow(XDisplay(), frame_window->window());
    redraw(False);
}

void ToolWindow::makeWindow(bool reconfigure)
{
    frame_window->setHeight(textHeight(getCurrentScreen(), resource->frame.font) + 4 * resource->frame.bevelWidth);
    
    if (resource->show.envelope) {
        envelope_window->setHeight(frame_window->height() - 2 * resource->frame.bevelWidth -
                        2 * resource->envelope.bevelHeight);
        envelope_window->setWidth((envelope_window->height() * 3) / 2);

        if (!(fmod((double)envelope_window->width(), 2.0) > 0.0)) 
            envelope_window->setWidth(envelope_window->width() + 1);
    } else 
        envelope_window->setWidth(0);


    if (resource->show.label) {
        label_window->calcSize();
        label_window->setHeight(frame_window->height() - 2 * resource->frame.bevelWidth);
    }
        
    frame_window->setWidth(label_window->width() + envelope_window->width()
                 + resource->frame.bevelWidth * 3 + resource->envelope.bevelWidth * 2);

    if (resource->position.mask & XNegative)
        resource->position.x = getCurrentScreenInfo()->width() +
                               resource->position.x - frame_window->width();
    if (resource->position.mask & YNegative)
        resource->position.y = getCurrentScreenInfo()->height() +
                               resource->position.y - frame_window->height();

    if (!config().isWithdrawn()) {
        frame_window->setX(resource->position.x);
        frame_window->setY(resource->position.y);
    }

    if (!reconfigure) {
        frame_window->createWindow();
    } else {
        frame_window->reconfigure();
    }
    if (resource->show.label) {
        label_window->setX(2 * resource->frame.bevelWidth +
                       envelope_window->width() + 2 * resource->envelope.bevelWidth);
        label_window->setY(resource->frame.bevelWidth);
       if (!reconfigure)
            label_window->createWindow();
        else
            label_window->reconfigure();
    }
    if (resource->show.envelope) {
        envelope_window->setX(resource->frame.bevelWidth + resource->envelope.bevelWidth);
                envelope_window->setY(resource->frame.bevelWidth + resource->envelope.bevelWidth);
        if (!reconfigure)
            envelope_window->createWindow();
        else
            envelope_window->reconfigure();
    }

    if (!reconfigure) {
        mbmenu = new MailboxMenu(this);
        XClearWindow(XDisplay(), frame_window->window());
        XMapSubwindows(XDisplay(), frame_window->window());
        mapped=true;
        if (!config().isDecorated() && !config().isWithdrawn())
        {
            XMoveResizeWindow(XDisplay(),frame_window->window(),frame_window->x(),
                              frame_window->y(), frame_window->width(),
                              frame_window->height());
        }
    }
}



void ToolWindow::redraw(bool change_raise)
{
    if (checkmail->getNewmail()==0) {
        if (resource->show.onlyAtNewMail&mapped) {
            XUnmapSubwindows(XDisplay(), frame_window->window());
            XUnmapWindow(XDisplay(), frame_window->window());
            mapped=false;
        }
        else if (resource->show.envelope) {
            envelope_window->redraw();
        }
    } else {
        if ((resource->show.onlyAtNewMail) & (!(mapped))) {
            XMapSubwindows(XDisplay(), frame_window->window());
            XMapWindow(XDisplay(),frame_window->window());
            mapped=true;
        }
        if (change_raise) {
            if (resource->spoolfile[checkmail->getNewMailbox()].bell)
                XBell(XDisplay(),100);
            if (!resource->spoolfile[checkmail->getNewMailbox()].newmailProc.empty());
            system(resource->spoolfile[checkmail->getNewMailbox()].newmailProc.c_str());
            if ((resource->report.auto_raise)&(!(raised))) {
                XRaiseWindow(XDisplay(), frame_window->window());
                raised = true;
            }
        }
        if (resource->show.envelope) {
            envelope_window->redraw();
        }
    }
    if (resource->show.label) {
        label_window->redraw();
    }

}


FrameWindow::FrameWindow(ToolWindow *toolwindow) :
             bt::EventHandler() ,
             m_pBbtool(toolwindow),
             fwindow(0),
             fx(0),
             fy(0),
             m_pixmap(0),
             fposition(NULL),
             m_screen(toolwindow->getCurrentScreen()),
             display(toolwindow->XDisplay())
{
}

FrameWindow::~FrameWindow(void)
{
    if (m_pixmap) bt::PixmapCache::release(m_pixmap);
    if (fposition) delete fposition;

    if (fwindow) XDestroyWindow(display, fwindow);

}

void FrameWindow::createWindow(void)
{
    XSetWindowAttributes attrib;
    XWMHints wmhints;
    unsigned long create_mask = CWBackPixmap | CWCursor | CWEventMask | CWOverrideRedirect;

    attrib.background_pixmap = ParentRelative;
    m_pixmap = bt::PixmapCache::find(m_screen, 
         m_pBbtool->getResource()->frame.texture, fwidth, fheight);
    if (m_pBbtool->config().isWithdrawn()) {
        wmhints.initial_state = WithdrawnState;
    } else {
        wmhints.initial_state = NormalState;
    }

    attrib.cursor =  XCreateFontCursor(display, XC_left_ptr);
    attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
                        FocusChangeMask | KeyPressMask | StructureNotifyMask;
    attrib.override_redirect = False;

    bt::EWMH ewmh(m_pBbtool->display());
    bool wm_window_type_dock = false;

    if (!m_pBbtool->config().isDecorated() && !m_pBbtool->config().isWithdrawn()) { 
        bt::EWMH::AtomList supported_atoms;
        if (ewmh.readSupported(m_pBbtool->getCurrentScreenInfo()->rootWindow(), supported_atoms)) {

          bt::EWMH::AtomList::iterator it = supported_atoms.begin();
            for (; it != supported_atoms.end(); ++it) {
                if ( (*it) ==  ewmh.wmWindowTypeDock()) {
                    wm_window_type_dock = true;
                }
            }
        } else {
            attrib.override_redirect = True;
        }
    }

    fwindow = XCreateWindow(display,
                        m_pBbtool->getCurrentScreenInfo()->rootWindow(), 
                        fx, fy, fwidth, fheight, 0, 
                        m_pBbtool->getCurrentScreenInfo()->depth(),
                        InputOutput, m_pBbtool->getCurrentScreenInfo()->visual(),
                        create_mask, &attrib);

    wmhints.flags = IconWindowHint | StateHint;
    wmhints.icon_window = fwindow;
    XTextProperty windowname;
    XClassHint classhints;

    char *name = PACKAGE;
    XSizeHints sizehints;

    classhints.res_name = PACKAGE;
    classhints.res_class = "m_pBbtools";

    sizehints.x = m_pBbtool->getResource()->position.x;
    sizehints.y = m_pBbtool->getResource()->position.y;
    sizehints.max_width = sizehints.min_width = fwidth;
    sizehints.max_height = sizehints.min_height = fheight;
    sizehints.flags = USPosition | PMinSize | PMaxSize;

    XStringListToTextProperty(&name, 1, &windowname);
    XSetWMProperties(display, fwindow, &windowname, NULL, m_pBbtool->config().argv(), m_pBbtool->config().argc(),
                     &sizehints, &wmhints, &classhints);
    XFree(windowname.value);
    Atom wmproto[2];
    wmproto[0] = m_pBbtool->wmDeleteWindowAtom();
    XSetWMProtocols(display, fwindow, wmproto, 1);
    bt::EWMH::AtomList window_type_atom;
    window_type_atom.push_back(ewmh.wmWindowTypeDock());
    if (!m_pBbtool->config().isDecorated() && !m_pBbtool->config().isWithdrawn()) {
        if (wm_window_type_dock) {
                XChangeProperty(display, fwindow, ewmh.wmWindowType(), XA_ATOM,
                            32, PropModeReplace,
                            reinterpret_cast<unsigned char*>(&(window_type_atom[0])), window_type_atom.size());
        } else {
            //attrib.override_redirect set
            fprintf(stderr, "Cannot dock\n");
        }
    } 
    bt::EWMH::AtomList state_atom;
    state_atom.push_back(ewmh.wmStateSticky());
    state_atom.push_back(ewmh.wmStateSkipTaskbar());
    state_atom.push_back(ewmh.wmStateSkipPager());
    ewmh.setWMState(fwindow, state_atom);

    //XSetWindowBackgroundPixmap(display, fwindow, m_pixmap);
    redraw();

    m_pBbtool->insertEventHandler(fwindow, this);
}

void FrameWindow::redraw(void)
{
     bt::Rect u(0, 0, fwidth, fheight);
     bt::drawTexture(m_screen,
                      m_pBbtool->getResource()->frame.texture,
                      fwindow, 
                      u, u, m_pixmap);
}

void FrameWindow::reconfigure(void)
{
    bt::PixmapCache::release(m_pixmap);
    m_pixmap = bt::PixmapCache::find(m_screen, 
         m_pBbtool->getResource()->frame.texture, fwidth, fheight);

     if (!m_pBbtool->config().isWithdrawn()) {
        XMoveResizeWindow(display, fwindow, fx, fy, fwidth, fheight);
    } else {
        XResizeWindow(display, fwindow, fwidth, fheight);
    }
     redraw();
}

void FrameWindow::clientMessageEvent(const XClientMessageEvent *xclient_event) 
{
    if ((unsigned)xclient_event->data.l[0] == m_pBbtool->wmDeleteWindowAtom()) 
      m_pBbtool->shutdown();
}

void FrameWindow::exposeEvent(const XExposeEvent *) 
{
    redraw();
}

void FrameWindow::buttonPressEvent(const XButtonEvent *xbutton_event) 
{
    if (xbutton_event->button == LEFT_BUTTON) {
        if (!m_pBbtool->isRaised()) {
            XRaiseWindow(display, fwindow);
            m_pBbtool->setRaised(true);
        }
    } else if (xbutton_event->button == MIDDLE_BUTTON) {
        if (m_pBbtool->isRaised()) {
            XLowerWindow(display, fwindow);
            m_pBbtool->setRaised(false);
        }
    }
}

LabelWindow::LabelWindow(ToolWindow *toolwindow) :  
             bt::EventHandler() ,
             m_pBbtool(toolwindow),
             m_pDisplay(toolwindow->XDisplay()),
             m_window(0),
             m_pixmap(0),
             m_x(0),
             m_y(0),
             m_widthNewMail(0),
             m_widthTotalMail(0),
             m_widthSeperator(0),
             m_screen(toolwindow->getCurrentScreen())

{
}

LabelWindow::~LabelWindow(void)
{
    if (m_pixmap) bt::PixmapCache::release(m_pixmap);
    if (m_window) XDestroyWindow(m_pDisplay, m_window);
    delete m_pPen;
}

void LabelWindow::createWindow(void)
{
    XSetWindowAttributes attrib;
    unsigned long create_mask = CWBackPixmap | CWEventMask;

    int i;
    m_maxValue = 1;
    for (i = 0; i < m_pBbtool->getResource()->report.number_of_digits; i++)
        m_maxValue *= 10;

    m_maxValue -= 1;

    
    attrib.background_pixmap = ParentRelative;
    attrib.cursor =  XCreateFontCursor(m_pDisplay, XC_left_ptr);
    attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
                        FocusChangeMask | KeyPressMask | StructureNotifyMask;

    if (!m_pBbtool->getResource()->label.transparent)
        m_pixmap = bt::PixmapCache::find(m_screen, 
                        m_pBbtool->getResource()->label.texture, m_width, m_height);
    m_window = XCreateWindow(m_pDisplay, m_pBbtool->frameWindow()->window(), m_x, m_y,
                            m_width, m_height, 0,
                            m_pBbtool->getCurrentScreenInfo()->depth(), InputOutput,
                            m_pBbtool->getCurrentScreenInfo()->visual(),
                            create_mask, &attrib);
  
    m_pPen = new bt::Pen(m_screen, 
                         m_pBbtool->getResource()->label.newmail_textColor);
//  lpen->setFont(m_pBbtool->getResource()->label.font);

    redraw();
    m_pBbtool->insertEventHandler(m_window, this);
    XClearWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
    XMapWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
    XMapSubwindows(m_pDisplay, m_pBbtool->frameWindow()->window());
 
    
}

void LabelWindow::reconfigure(void)
{
    if (!m_pBbtool->getResource()->label.transparent) {
        bt::PixmapCache::release(m_pixmap);
        m_pixmap = bt::PixmapCache::find(m_screen, 
                        m_pBbtool->getResource()->label.texture, m_width, m_height);
    }
    XMoveResizeWindow(m_pDisplay, m_window, m_x, m_y, m_width, m_height);
    delete m_pPen;
    m_pPen = new bt::Pen(m_screen, 
                         m_pBbtool->getResource()->label.newmail_textColor);

    redraw();
}

void LabelWindow::calcSize()
{
    bt::ustring str;
    char *t;
    t = new char [m_pBbtool->getResource()->report.number_of_digits + m_pBbtool->getResource()->report.number_of_digits + 1 + 1];
    if (m_pBbtool->getResource()->show.newmail_counter && m_pBbtool->getResource()->show.newmail_counter) 
    {
        sprintf(t, "%0*d/%0*d", m_pBbtool->getResource()->report.number_of_digits, 0, m_pBbtool->getResource()->report.number_of_digits, 0);
        str = bt::toUnicode(t);
        unsigned int text_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
        m_width = text_width + 3 * m_pBbtool->getResource()->frame.bevelWidth;
        sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
        str = bt::toUnicode(t);
        m_widthNewMail = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
        sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
        str = bt::toUnicode(t);
        m_widthTotalMail = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
        m_widthSeperator = text_width - m_widthNewMail - m_widthTotalMail;
    }
    else if (m_pBbtool->getResource()->show.newmail_counter)    // split these up now, so we can use different number_of_digits later
    {
        sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
        str = bt::toUnicode(t);
        m_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width() +
            2 * m_pBbtool->getResource()->frame.bevelWidth;
    }
    else if (m_pBbtool->getResource()->show.totalmail_counter)
    {
        sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
        str = bt::toUnicode(t);
        m_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width() +
            2 * m_pBbtool->getResource()->frame.bevelWidth;
    }
    delete [] t;
}


void LabelWindow::redraw(void)
{
    // redraw windows
    if (m_pixmap == ParentRelative || m_pBbtool->getResource()->label.transparent)    // we can remove the transparent option in the future
    {
        bt::Rect u(0, 0, width(), height());
        bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
        bt::drawTexture(m_screen,
                        m_pBbtool->getResource()->frame.texture,
                        m_window, 
                        t, u, m_pBbtool->frameWindow()->pixmap());
    }
    else
    {
        bt::Rect u(0, 0, width(), height());
        bt::drawTexture(m_screen,
                        m_pBbtool->getResource()->label.texture,
                        m_window, 
                        u, u, m_pixmap);
    }

    // redraw text
    char t[6];
    bt::ustring txt;
//    if (m_pBbtool->getResource()->show.label) 
//        XClearWindow(m_pDisplay, m_window);
    if (m_pBbtool->getResource()->show.newmail_counter) {
        if (m_pBbtool->checkMail()->getNewmail() == 0)
            XSetForeground(m_pDisplay, m_pPen->gc(),
                           m_pBbtool->getResource()->label.newmail_boring_textColor.pixel(m_screen));
        else
                XSetForeground(m_pDisplay, m_pPen->gc(),
                               m_pBbtool->getResource()->label.newmail_textColor.pixel(m_screen));

        if (m_pBbtool->checkMail()->getNewmail() < m_maxValue) {
            sprintf(t, "%0*d",m_pBbtool->getResource()->report.number_of_digits, m_pBbtool->checkMail()->getNewmail());
            txt = bt::toUnicode(t);
            bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
            text_rect.setX(m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setWidth(m_widthNewMail);
            drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window, 
                 text_rect, bt::AlignCenter, txt);
        } else {
            sprintf(t, ">");
            txt = bt::toUnicode(t);
            bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
            text_rect.setX(m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setWidth(m_widthNewMail);
            drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window, 
                 text_rect, bt::AlignCenter, txt);
        }
    }
    if (m_pBbtool->getResource()->show.totalmail_counter) {
        if (m_pBbtool->getResource()->show.newmail_counter) {
            if ((m_pBbtool->checkMail()->getLastTotalmail() == 0) | (m_pBbtool->checkMail()->getNewmail() == 0))
                XSetForeground(m_pDisplay, m_pPen->gc(),
                 m_pBbtool->getResource()->label.seperator_boring_textColor.pixel(m_screen));
            else
                XSetForeground(m_pDisplay, m_pPen->gc(),
                           m_pBbtool->getResource()->label.seperator_textColor.pixel(m_screen));
            sprintf(t, SEPERATOR);
            txt = bt::toUnicode(t);
            bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
            text_rect.setX(m_widthNewMail + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setWidth(m_widthSeperator);
            drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window, 
                 text_rect, bt::AlignCenter, txt);
        }
        if (m_pBbtool->checkMail()->getLastTotalmail() > m_maxValue) {
            sprintf(t, ">");
            txt = bt::toUnicode(t);
            bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
            text_rect.setX(m_widthNewMail + m_widthSeperator + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setWidth(m_widthTotalMail);
            drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window, 
                 text_rect, bt::AlignCenter, txt);
        } else {
            if (m_pBbtool->checkMail()->getLastTotalmail() == 0) {
                XSetForeground(m_pDisplay, m_pPen->gc(),
                        m_pBbtool->getResource()->label.totalmail_boring_textColor.pixel(m_screen));
                } else {
                    XSetForeground(m_pDisplay, m_pPen->gc(),
                        m_pBbtool->getResource()->label.totalmail_textColor.pixel(m_screen));
            }
            
            sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, m_pBbtool->checkMail()->getLastTotalmail());
            txt = bt::toUnicode(t);
            bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
            text_rect.setX( m_widthNewMail + m_widthSeperator + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
            text_rect.setWidth(m_widthTotalMail);
            drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window, 
                text_rect, bt::AlignCenter, txt);
        }
    }
}

void LabelWindow::buttonPressEvent(const XButtonEvent *xbutton_event)
{
    if (xbutton_event->button == LEFT_BUTTON) {
        if (!m_pBbtool->isRaised()) {
            XRaiseWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
            m_pBbtool->setRaised(true);
        }
    } else if (xbutton_event->button == MIDDLE_BUTTON) {
        if (m_pBbtool->isRaised()) {
            XLowerWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
            m_pBbtool->setRaised(false);
        }
    }
}

void LabelWindow::exposeEvent(const XExposeEvent *)
{
    redraw();
}

EnvelopeWindow::EnvelopeWindow(ToolWindow *toolwindow) :  
            bt::EventHandler() ,
            display(toolwindow->XDisplay()),
            m_pBbtool(toolwindow),
            m_screen(toolwindow->getCurrentScreen()),
            m_window(0),
            ex(0),
            ey(0),
            pixmap(0),
            pixmap_pressed(0),
            envelope_pushed(false)
{
}

EnvelopeWindow::~EnvelopeWindow(void)
{
    if (pixmap) bt::PixmapCache::release(pixmap);
    if (pixmap_pressed) bt::PixmapCache::release(pixmap_pressed);
    int i;
    for (i = 0; i < num_of_pixmaps; i++) {
        bt::PixmapCache::release(pixmap_new[i]);
        bt::PixmapCache::release(pixmap_new_pressed[i]);
    }

    delete [] pixmap_new;
    delete [] pixmap_new_pressed;
    delete epen;
    
    if (m_window) XDestroyWindow(display, m_window);
}

void EnvelopeWindow::createWindow(void)
{
    XSetWindowAttributes attrib;
    unsigned long create_mask = CWBackPixmap | CWCursor | CWEventMask;
    attrib.background_pixmap = ParentRelative;
    attrib.cursor =  XCreateFontCursor(display, XC_left_ptr);
    attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
                        FocusChangeMask | KeyPressMask | StructureNotifyMask;

  
    pixmap = bt::PixmapCache::find(m_screen, 
            m_pBbtool->getResource()->envelope.texture, ewidth, eheight);

    pixmap_pressed = bt::PixmapCache::find(m_screen, 
              m_pBbtool->getResource()->envelope.texture_pressed, 
              ewidth, eheight);

    num_of_pixmaps = m_pBbtool->getResource()->report.number_of_spoolfiles;
    pixmap_new = new Pixmap [num_of_pixmaps];
    pixmap_new_pressed = new Pixmap [num_of_pixmaps];

    int i;
    for (i = 0; i < num_of_pixmaps; i++) {
        pixmap_new[i] = bt::PixmapCache::find(m_screen, 
                m_pBbtool->getResource()->spoolfile[i].newmail_texture, 
                ewidth, eheight);

        pixmap_new_pressed[i] = bt::PixmapCache::find(m_screen, 
                    m_pBbtool->getResource()->spoolfile[i].newmail_pressed_texture,
                    ewidth, eheight);
    }

    m_window = XCreateWindow(display, m_pBbtool->frameWindow()->window(),
                    ex, ey, ewidth, eheight, 0,
                        m_pBbtool->getCurrentScreenInfo()->depth(),
                        InputOutput, m_pBbtool->getCurrentScreenInfo()->visual(),
                        create_mask, &attrib);

    epen = new bt::Pen(m_screen, m_pBbtool->getResource()->envelope.textColor);
    //epen->setFont(m_pBbtool->getResource()->frame.font);
    
    calcPoints();

    m_pBbtool->insertEventHandler(m_window, this);

}

void EnvelopeWindow::reconfigure(void)
{
    bt::PixmapCache::release(pixmap);
    bt::PixmapCache::release(pixmap_pressed);

    int i;
    for (i = 0; i < num_of_pixmaps; i++) {
        bt::PixmapCache::release(pixmap_new[i]);
        bt::PixmapCache::release(pixmap_new_pressed[i]);
    }

    delete [] pixmap_new;
    delete [] pixmap_new_pressed;

    pixmap = bt::PixmapCache::find(m_screen, 
            m_pBbtool->getResource()->envelope.texture, ewidth, eheight);

    pixmap_pressed = bt::PixmapCache::find(m_screen, 
              m_pBbtool->getResource()->envelope.texture_pressed, 
              ewidth, eheight);

    num_of_pixmaps = m_pBbtool->getResource()->report.number_of_spoolfiles;
    pixmap_new = new Pixmap [num_of_pixmaps];
    pixmap_new_pressed = new Pixmap [num_of_pixmaps];


    for (i = 0; i < num_of_pixmaps; i++) {
        pixmap_new[i] = bt::PixmapCache::find(m_screen, 
                m_pBbtool->getResource()->spoolfile[i].newmail_texture, 
                ewidth, eheight);

        pixmap_new_pressed[i] = bt::PixmapCache::find(m_screen, 
                    m_pBbtool->getResource()->spoolfile[i].newmail_pressed_texture,
                    ewidth, eheight);
    }
    delete epen;
    epen = new bt::Pen(m_screen, m_pBbtool->getResource()->envelope.textColor);
    calcPoints();

    XMoveResizeWindow(display, m_window, ex, ey, ewidth, eheight);
    redraw();
}

void EnvelopeWindow::release(void)
{
    if (envelope_pushed) {
        envelope_pushed = false;
        m_pBbtool->redraw(false);
    }
}

void EnvelopeWindow::buttonPressEvent(const XButtonEvent *xbutton_event)
{
    if (xbutton_event->button == LEFT_BUTTON) {
        if (!m_pBbtool->isRaised()) {
            XRaiseWindow(display, m_pBbtool->frameWindow()->window());
            m_pBbtool->setRaised(true);
        }
        envelope_pushed = true;
        m_pBbtool->redraw(false);
    } else if (xbutton_event->button == MIDDLE_BUTTON) {
        if (m_pBbtool->isRaised()) {
            XLowerWindow(display, m_pBbtool->frameWindow()->window());
            m_pBbtool->setRaised(false);
        }
    } else if (xbutton_event->button == RIGHT_BUTTON) {
        if (!envelope_pushed) {
            envelope_pushed = true;
            m_pBbtool->redraw(false);
            if (!m_pBbtool->mbMenu()->isVisible()) {
                m_pBbtool->mbMenu()->popup(m_pBbtool->frameWindow()->x(), m_pBbtool->frameWindow()->y(),
                                m_pBbtool->config().isWithdrawn());
            }
        }
    }
}

void EnvelopeWindow::buttonReleaseEvent(const XButtonEvent *xbutton_event)
{
    if (xbutton_event->button == LEFT_BUTTON) {
        envelope_pushed = false;
        m_pBbtool->redraw(false);
        if (xbutton_event->x > 0 && xbutton_event->x < (int)ewidth &&
            xbutton_event->y > 0 && xbutton_event->y < (int)eheight ) {
            if (m_pBbtool->checkMail()->getNewmail() != 0) {
                if (!m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].runCommand.empty()) {
                    system(m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].runCommand.c_str());
                }
                else {
                    if (!m_pBbtool->getResource()->report.runCommand.empty()) {
                        system(m_pBbtool->getResource()->report.runCommand.c_str());
                    }
                }
            } else {
                if (!m_pBbtool->getResource()->report.runCommand.empty()) {
                    system(m_pBbtool->getResource()->report.runCommand.c_str());
                }
            }
        }
    }
}

void EnvelopeWindow::exposeEvent(const XExposeEvent *)
{
    redraw();
}

void EnvelopeWindow::calcPoints(void) {
    points[0].x =  2;
    points[0].y =  2;
    points[1].x = ewidth / 2;
    points[1].y = (eheight * 2) / 3;
    points[2].x = ewidth - 3;
    points[2].y = 2;

    points[3].x = 2;
    points[3].y = eheight - 3;
    points[4].x = ewidth / 3;
    points[4].y = eheight / 2 - 1;

    points[5].x = ewidth - 3;
    points[5].y = eheight - 3;
    points[6].x = (ewidth * 2) / 3;
    points[6].y = eheight / 2;

    points[7].x = ewidth / 3;
    points[7].y = 2;
    points[8].x = (ewidth * 2) / 3 - 1;
    points[8].y = eheight / 2;

    points[9].x = (ewidth * 2) / 3 - 1;
    points[9].y = 2;
    points[10].x = ewidth / 3;
    points[10].y = eheight / 2;
}

void EnvelopeWindow::redraw(void)
{
    if (m_pBbtool->checkMail()->getNewmail() == 0) 
    {

        if (envelope_pushed)
        {
//            XSetWindowBackgroundPixmap(display, m_window, pixmap_pressed);
            if (pixmap_pressed == ParentRelative) 
            {
                bt::Rect u(0, 0, width(), height());
                bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->frame.texture,
                                m_window, 
                                t, u, m_pBbtool->frameWindow()->pixmap());
            }
            else
            {
                bt::Rect u(0, 0, width(), height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->envelope.texture_pressed,
                                m_window, 
                                u, u, pixmap_pressed);
            }
        }
        else
        {
//            XSetWindowBackgroundPixmap(display, m_window, pixmap);
            if (pixmap == ParentRelative) 
            {
                bt::Rect u(0, 0, width(), height());
                bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->frame.texture,
                                m_window, 
                                t, u, m_pBbtool->frameWindow()->pixmap());
            }
            else
            {
                bt::Rect u(0, 0, width(), height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->envelope.texture,
                                m_window, 
                                u, u, pixmap);
            }
        }

        XSetForeground(display, epen->gc(), 
                m_pBbtool->getResource()->envelope.textColor.pixel(m_screen));
        XClearWindow(display, m_window);
        XDrawLines(display, m_window, epen->gc(), points, 3, CoordModeOrigin);
        XDrawLine(display, m_window, epen->gc(), points[3].x, points[3].y,
              points[4].x, points[4].y);
        XDrawLine(display, m_window, epen->gc(), points[5].x, points[5].y,
              points[6].x, points[6].y);
        if (m_pBbtool->checkMail()->getBroken()) {
            XSetForeground(display, epen->gc(),
                    m_pBbtool->getResource()->envelope.error_textColor.pixel(m_screen));
            XSetLineAttributes(display, epen->gc() , 2, LineSolid, CapButt, JoinMiter);
            XDrawLine(display, m_window, epen->gc(), points[7].x, points[7].y,
                  points[8].x, points[8].y);
            XDrawLine(display, m_window, epen->gc(), points[9].x, points[9].y,
                  points[10].x, points[10].y);
            XSetLineAttributes(display, epen->gc(), 0, LineSolid,CapButt,JoinMiter);
        }
    } else {
        if (envelope_pushed)
        {
            if (pixmap_pressed == ParentRelative) 
            {
                bt::Rect u(0, 0, width(), height());
                bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->frame.texture,
                                m_window, 
                                t, u, m_pBbtool->frameWindow()->pixmap());
            }
            else
            {
                bt::Rect u(0, 0, width(), height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].newmail_pressed_texture,
                                m_window, 
                                u, u, pixmap_new_pressed[m_pBbtool->checkMail()->getNewMailbox()]);
            }

//            XSetWindowBackgroundPixmap(display, m_window,
//                           pixmap_new_pressed[m_pBbtool->checkMail()->getNewMailbox()]);
        }
        else
        {
            if (pixmap_pressed == ParentRelative) 
            {
                bt::Rect u(0, 0, width(), height());
                bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->frame.texture,
                                m_window, 
                                t, u, m_pBbtool->frameWindow()->pixmap());
            }
            else
            {
                bt::Rect u(0, 0, width(), height());
                bt::drawTexture(m_screen,
                                m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].newmail_texture,
                                m_window, 
                                u, u, pixmap_new[m_pBbtool->checkMail()->getNewMailbox()]);
            }
//            XSetWindowBackgroundPixmap(display, m_window,
//                           pixmap_new[m_pBbtool->checkMail()->getNewMailbox()]);
        }
        XSetForeground(display, epen->gc(),
                   m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].
                   newmail_textColor.pixel(m_screen));

        XClearWindow(display, m_window);
        XDrawLines(display, m_window, epen->gc(), points, 3, CoordModeOrigin);
        XDrawLine(display, m_window, epen->gc(), points[3].x,
              points[3].y, points[4].x, points[4].y);
        XDrawLine(display, m_window, epen->gc(), points[5].x, points[5].y,
              points[6].x, points[6].y);

        if (m_pBbtool->checkMail()->getBroken()) {
            XSetForeground(display, epen->gc(),
                       m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].
                       newmail_error_textColor.pixel(m_screen));
            XSetLineAttributes(display, epen->gc(), 2, LineSolid,CapButt,JoinMiter);
            XDrawLine(display, m_window, epen->gc(), points[7].x, points[7].y,
                  points[8].x, points[8].y);
            XDrawLine(display, m_window, epen->gc(), points[9].x, points[9].y,
                  points[10].x, points[10].y);
            XSetLineAttributes(display, epen->gc(), 0, LineSolid, CapButt, JoinMiter);
        }
    }
}

void FrameWindow::configureNotifyEvent(const XConfigureEvent *xconfigure_event)
{
    if (xconfigure_event->send_event) {
        if (m_pBbtool->config().isWithdrawn()) {
            m_pBbtool->reconfigure();
        }
        int parent_x,parent_y;
        Window parent_root;
        unsigned int parent_width;
        unsigned int parent_height;
        unsigned int parent_border_width;
        unsigned int parent_depth;
        if (m_pBbtool->config().isWithdrawn()) {
            XGetGeometry(display, xconfigure_event->above, &parent_root,
                         &parent_x, &parent_y, &parent_width, &parent_height,
                         &parent_border_width, &parent_depth);
            fx = xconfigure_event->x + parent_x;
            fy = xconfigure_event->y + parent_y;
        } else {
            fx = xconfigure_event->x;
            fy = xconfigure_event->y;
            if (m_pBbtool->config().isDecorated()) {
                char position[13];
                sprintf(position,"+%i+%i", fx, fy);
                m_pBbtool->config().setGeometry(position);
            }
        }
        if (m_pBbtool->mbMenu()->isVisible())
            m_pBbtool->mbMenu()->show();
    }
}


syntax highlighted by Code2HTML, v. 0.9.1