1 // bbmail.cpp for bbmail - an tool for display the mail in X11.
2 //
3 //  Copyright (c) 1998-2005 by John Kennis, jkennis@chello.nl
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 2 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // (See the included file COPYING / GPL-2.0)
20 //
21 
22 #include "bbmail.h"
23 #include "config.h"
24 #include <string>
25 #include <cstdio>  // for fprintf popen stderr etc
26 #include <cstring> // for strncmp
27 #include <cstdlib>
28 #include <cmath>
29 
30 extern "C" {
31 #include <utime.h>
32 #include <dirent.h>
33 #include <X11/cursorfont.h>
34 #include <sys/stat.h>
35 }
36 
37 #include "EWMH.hh"
38 
39 #define SEPERATOR "/"
40 
Checkmail(ToolWindow * toolwindow)41 Checkmail::Checkmail(ToolWindow *toolwindow):
42     m_pBbtool(toolwindow)
43 {
44     timer = new bt::Timer(m_pBbtool, this) ;
45     timer->setTimeout(m_pBbtool->getResource()->report.check_delay * 1000);
46     timer->recurring(true);
47 
48     timer->start();
49     broken = false;
50     last_totalmail = 0;
51     last_newmail = 0;
52     new_mailbox = 0;
53     newmail = 0;
54     spoolfile = new
55                 LocalSpoolfile[m_pBbtool->getResource()->report.number_of_spoolfiles];
56     number_of_checks = m_pBbtool->getResource()->report.force_check_delay;
57 }
58 
~Checkmail()59 Checkmail::~Checkmail()
60 {
61     delete [] spoolfile;
62     delete timer;
63 }
64 
reconfigure()65 void Checkmail::reconfigure()
66 {
67     delete [] spoolfile;
68     spoolfile = new LocalSpoolfile[
69             m_pBbtool->getResource()->report.number_of_spoolfiles];
70     number_of_checks = m_pBbtool->getResource()->report.force_check_delay;
71     timer->fireTimeout();
72 }
73 
CheckMaildir(int spoolno)74 bool Checkmail::CheckMaildir(int spoolno)
75 {
76     struct stat file_status, maildir_status;
77 
78     if (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty())
79     {
80         fprintf(stderr,"No qmail maildir specified\n");
81         return(false);
82     }
83 
84     if (stat(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
85              &file_status)!=0)
86     {
87         fprintf(stderr,"Could not read status spool file %s\n",
88                 m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
89         return(false);
90     }
91 
92     // check maildir new/
93 
94     if (stat(m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str(),
95               &maildir_status) != 0)
96     {
97         fprintf(stderr,"Could not read status new maildir: %s\n",
98                 m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
99         return(false);
100     }
101     if (maildir_status.st_mtime > file_status.st_mtime)
102     {
103         file_status.st_mtime = maildir_status.st_mtime;
104     }
105 
106     if (stat(m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str(),
107         &maildir_status) != 0)
108     {
109         fprintf(stderr,"Could not read status current maildir: %s\n",
110              m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str());
111         return(false);
112     }
113     if (maildir_status.st_mtime > file_status.st_mtime)
114     {
115         file_status.st_mtime = maildir_status.st_mtime;
116     }
117 
118     if  (file_status.st_mtime != spoolfile[spoolno].last_mtime)
119     {
120         spoolfile[spoolno].last_mtime = file_status.st_mtime;
121         spoolfile[spoolno].newmail=0;
122         DIR *dir;
123 
124         if ((dir = opendir(
125               m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str())
126             ) == NULL)
127         {
128             fprintf(stderr,"Could not open maildir %s\n",
129               m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
130             return false;
131         }
132 
133         while (readdir (dir))
134         {
135             spoolfile[spoolno].newmail++;
136         }
137         /* -2 for . and .. */
138         spoolfile[spoolno].newmail -= 2;
139         closedir(dir);
140 
141         if ((dir = opendir(
142             m_pBbtool->getResource()->spoolfile[spoolno].cur_maildir.c_str())
143             ) == NULL)
144         {
145             fprintf(stderr,"Could not open maildir %s\n",
146              m_pBbtool->getResource()->spoolfile[spoolno].new_maildir.c_str());
147             return false;
148         }
149 
150         spoolfile[spoolno].totalmail=spoolfile[spoolno].newmail;
151 
152         while (readdir (dir))
153         {
154             spoolfile[spoolno].totalmail++;
155         }
156         /* -2 for . and .. */
157         spoolfile[spoolno].totalmail-=2;
158         closedir(dir);
159     }
160     return(true);
161 }
162 
CheckOther(int spoolno,bool force)163 bool Checkmail::CheckOther(int spoolno,bool force)
164 {
165     struct stat file_status;
166     FILE *fp;
167     int num[2]={-1,-1};
168     int number_of_values;
169 
170 
171     if ((m_pBbtool->getResource()->spoolfile[spoolno].proc.empty())&
172             (m_pBbtool->getResource()->spoolfile[spoolno].proc.empty()))
173     {
174         fprintf(stderr,"Nothing to do, no proc defined\n");
175         return(false);
176     }
177     if (!m_pBbtool->getResource()->spoolfile[spoolno].filename.empty())
178     {
179         if (stat(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
180                  &file_status)!=0)
181         {
182             fprintf(stderr,"Could not read status spool file %s\n",
183                 m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
184             return(false);
185         }
186     }
187 
188     if  ((file_status.st_mtime != spoolfile[spoolno].last_mtime)&&
189          (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty())||
190          (force && m_pBbtool->getResource()->spoolfile[spoolno].force_check))
191     {
192 
193         if (m_pBbtool->getResource()->spoolfile[spoolno].second_ignore)
194         {
195             number_of_values = 1;
196         }
197         else
198         {
199             number_of_values = 2;
200         }
201 
202         spoolfile[spoolno].last_mtime = file_status.st_mtime;
203         int old_newmail = spoolfile[spoolno].newmail;
204         spoolfile[spoolno].newmail = 0;
205         spoolfile[spoolno].totalmail = 0;
206 
207         if (!m_pBbtool->getResource()->spoolfile[spoolno].proc.empty())
208         {
209             if ((fp = (FILE*)popen(
210                       m_pBbtool->getResource()->spoolfile[spoolno].proc.c_str(),
211                       "r")) == NULL)
212             {
213                 fprintf(stderr,"Could not run command %s\n",
214                     m_pBbtool->getResource()->spoolfile[spoolno].proc.c_str());
215                 return(false);
216             }
217             else
218             {
219                 while (!(feof(fp)))
220                 {
221                     if (ReadPipe(fp,num,number_of_values) != 0)
222                     {
223                         if (num[0] > old_newmail)
224                         {
225                             new_mailbox = spoolno;
226                         }
227 #ifdef DEBUG
228                         fprintf(stderr,"first int: %i, second int %i\n",num[0],num[1]);
229 #endif
230                         spoolfile[spoolno].newmail += num[0];
231                         spoolfile[spoolno].totalmail += num[1];
232                     }
233                     else
234                     {
235                         if ((num[0] == -1) & (num[1] == -1))
236                         {
237                             pclose(fp);
238                             return(false);
239                         }
240                     }
241                 }
242                 pclose(fp);
243             }
244         }
245         if  (!m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.empty())
246         {
247             if ((fp=(FILE*)popen(
248               m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.c_str(),
249               "r")) == NULL)
250             {
251                 fprintf(stderr,"Could not run command %s\n",
252                         m_pBbtool->getResource()->spoolfile[spoolno].reversedProc.c_str());
253                 return(false);
254             }
255             else
256             {
257                 while (!(feof(fp)))
258                 {
259                     if (ReadPipe(fp,num,number_of_values)!=0)
260                     {
261                         if (num[1]>old_newmail) new_mailbox = spoolno;
262                         spoolfile[spoolno].newmail+=num[1];
263                         spoolfile[spoolno].totalmail+=num[0];
264                     }
265                 }
266                 pclose(fp);
267             }
268         }
269         if (!m_pBbtool->getResource()->spoolfile[spoolno].first_is_new)
270             spoolfile[spoolno].newmail=spoolfile[spoolno].totalmail-
271                                        spoolfile[spoolno].newmail;
272         if (!m_pBbtool->getResource()->spoolfile[spoolno].second_is_total)
273             spoolfile[spoolno].totalmail=spoolfile[spoolno].newmail+
274                                          spoolfile[spoolno].totalmail;
275 
276     }
277 
278     return(true);
279 }
280 
forceCheck()281 void Checkmail::forceCheck()
282 {
283     timer->fireTimeout();
284 }
285 
getChar(const char * string,int * index)286 bool Checkmail::getChar(const char *string,int *index)
287 {
288     bool special = false;
289     if (string[*index] == '\\') {
290         (*index)++;
291     } else {
292         if ((string[*index] == '[')|(string[*index] == ']'))
293             special = true;
294     }
295     return(special);
296 }
297 
checkStatusFlag(char * status_flag,int spoolno)298 bool Checkmail::checkStatusFlag(char *status_flag,int spoolno)
299 {
300     int i, x, len;
301     bool passed;
302 
303     len = m_pBbtool->getResource()->spoolfile[spoolno].statusflag.length();
304     for (i = 0, x = 0; i < len; i++, x++) {
305         if (getChar(m_pBbtool->getResource()->spoolfile[spoolno].statusflag.c_str(), &i)) {
306             if ((m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]=='[')) {
307                 passed=false;
308                 while ((m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]!=']')
309                         & (i<len)) {
310                     i++;
311 
312                     if (!getChar(m_pBbtool->getResource()->spoolfile[spoolno].statusflag.c_str(),
313                                  &i))
314                         if (m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]==
315                                 status_flag[x]) {
316                             passed=true;
317                         }
318                 }
319                 if (!passed) return false;
320             } else {
321                 fprintf(stderr,"unexpected token in statusFlag\n");
322             }
323         } else
324             if (m_pBbtool->getResource()->spoolfile[spoolno].statusflag[i]!=status_flag[x])
325                 return(false);
326     }
327     return(true);
328 }
329 
CheckMbox(int spoolno)330 bool Checkmail::CheckMbox(int spoolno)
331 {
332     int readmail = 0;
333     int mailcount = 0;
334     FILE *spool_id;
335     bool read_status = true;
336     char mailbuf[128];
337     struct stat file_status;
338     struct utimbuf ut;
339 
340     if (m_pBbtool->getResource()->spoolfile[spoolno].filename.empty()) {
341         fprintf(stderr,"No mbox mailfile specified\n");
342         return(false);
343     }
344 
345     if (!(spool_id = fopen(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(),
346                            "r"))) {
347         fprintf(stderr,"Could not open mail spool file %s\n",
348                 m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str());
349         return(false);
350     }
351     fstat(fileno(spool_id), &file_status);
352     if(file_status.st_mtime != spoolfile[spoolno].last_mtime ||
353             file_status.st_size != spoolfile[spoolno].last_size) {
354         spoolfile[spoolno].last_mtime = file_status.st_mtime;
355         spoolfile[spoolno].last_size = file_status.st_size;
356         while(fgets(mailbuf, 127, spool_id)) {
357             if(!strncmp(mailbuf, "From ", 5)) {
358                 mailcount++;
359                 read_status=False;
360             } else
361                 if (checkStatusFlag(mailbuf,spoolno)) {
362                     if(!read_status) {
363                         readmail++;
364                         read_status=True;
365                     }
366                 } else if (!strncmp(mailbuf,"Subject",7)) {
367                     if (!strncmp(&mailbuf[9],
368                                  "DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA",49)!=0) {
369                         mailcount--;
370                         read_status=True;
371                     }
372                 }
373 
374         }
375         if ((mailcount - readmail) > spoolfile[spoolno].newmail)
376             new_mailbox = spoolno;
377         spoolfile[spoolno].newmail = mailcount - readmail;
378         spoolfile[spoolno].totalmail = mailcount;
379 #ifdef DEBUG
380         fprintf(stderr,"mailcount=%d, readmail=%d, spoolno=%d\n",mailcount,
381                 readmail,spoolno);
382 #endif
383     }
384     fclose(spool_id);
385     ut.actime = file_status.st_atime;
386     ut.modtime = file_status.st_mtime;
387     utime(m_pBbtool->getResource()->spoolfile[spoolno].filename.c_str(), &ut);
388     return(true);
389 }
390 
timeout(bt::Timer * timer)391 void Checkmail::timeout(bt::Timer *timer)
392 {
393     int totalmail=0;
394     bool change_raise=False;
395     bool force=False;
396     int i,old_total,old_new;
397     bool redraw=False;
398     newmail=0;
399     broken=False;
400     if (m_pBbtool->getResource()->report.force_check) {
401         if (m_pBbtool->getResource()->report.force_check_delay==number_of_checks) {
402             force=True;
403             number_of_checks=0;
404         } else {
405             number_of_checks++;
406 #ifdef DEBUG
407             fprintf(stderr,"number_of_checks %i\n",number_of_checks);
408 #endif
409         }
410     }
411     for (i = 0; i < (int)m_pBbtool->getResource()->report.number_of_spoolfiles; i++) {
412         old_new=spoolfile[i].newmail;
413         old_total=spoolfile[i].totalmail;
414 
415         if (m_pBbtool->getResource()->spoolfile[i].type==SpoolList::other) {
416             if (!(CheckOther(i,force))) {
417                 broken=True;
418             } else {
419                 newmail+=spoolfile[i].newmail;
420                 totalmail+=spoolfile[i].totalmail;
421                 if ((spoolfile[i].newmail!=old_new)|(spoolfile[i].totalmail!=old_total))
422                 {
423                     m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
424                                                   spoolfile[i].totalmail,i);
425                 }
426             }
427         } else if (m_pBbtool->getResource()->spoolfile[i].type==SpoolList::mbox) {
428             if (!(CheckMbox(i)))
429                 broken=True;
430             else {
431                 totalmail+=spoolfile[i].totalmail;
432                 newmail+=spoolfile[i].newmail;
433                 if ((spoolfile[i].newmail != old_new) | (spoolfile[i].totalmail != old_total))
434                     m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
435                                                   spoolfile[i].totalmail,i);
436             }
437         } else if (m_pBbtool->getResource()->spoolfile[i].type == SpoolList::maildir) {
438             if (!(CheckMaildir(i)))
439                 broken=True;
440             else {
441                 totalmail+=spoolfile[i].totalmail;
442                 newmail+=spoolfile[i].newmail;
443                 if ((spoolfile[i].newmail!=old_new)|(spoolfile[i].totalmail!=old_total))
444                     m_pBbtool->mbMenu()->UpdateNumbers(spoolfile[i].newmail,
445                                                   spoolfile[i].totalmail,i);
446             }
447         }
448     }
449     if (newmail>last_newmail)
450         change_raise = True;
451     else {
452         /* are there  ny not empty mailboxes left */
453         for (i = 0; i < (int)m_pBbtool->getResource()->report.number_of_spoolfiles; i++) {
454             if (spoolfile[i].newmail!=0) {
455                 new_mailbox=i;
456                 //        change_raise = True;
457             }
458         }
459     }
460     if ((newmail!=last_newmail)|(totalmail!=last_totalmail)|(broken) )
461     {
462         redraw=True;
463     }
464     last_newmail=newmail;
465     last_totalmail=totalmail;
466     if (redraw) m_pBbtool->redraw(change_raise);
467 }
468 
ReadPipe(FILE * fp,int num[2],int number_of_values)469 int Checkmail::ReadPipe(FILE *fp,int num[2],int number_of_values)
470 {
471     int i=0;
472     bool found=False;
473     bool newline=False;
474     int x=0;
475     char ch[6]={0,0,0,0,0,0};
476 
477     while (!(feof(fp))&(x!=number_of_values)&(ch[i]!='\n')&(!newline)) {
478         fread(&ch[i],1,1,fp);
479         while ((ch[i]>='0' && ch[i] <='9' && ch[1]!='\n')&(!feof(fp))) {
480             i++;
481             if (i==7) return(0);
482             fread(&ch[i],1,1,fp);
483             found=True;
484         }
485         if (ch[i]=='\n') newline=True;
486         if (found) {
487             ch[i]='\0';
488             num[x]=atoi(ch);
489             i=0;
490             x++;
491             found=False;
492         }
493     }
494     /* skip to next line */
495     while (!(feof(fp))&(ch[0]!='\n')&(!newline))
496         fread(&ch[0],1,1,fp);
497     return(x);
498 }
499 
500 
ToolWindow(Configuration cml_options)501 ToolWindow::ToolWindow(Configuration cml_options):
502     bt::Application(cml_options.appName(), cml_options.displayName().c_str(), false),
503     current_screen_info(display().screenInfo(DefaultScreen(XDisplay()))),
504     _config(cml_options)
505 {
506 
507     checkmail = NULL;
508     mbmenu = NULL;
509     current_screen = DefaultScreen(XDisplay());
510     wm_delete_window = XInternAtom (XDisplay(), "WM_DELETE_WINDOW",False);
511 
512     /* initialize xrm database */
513     XrmInitialize();
514     resource = new Resource(this, _config.rcFilename());
515     frame_window = new FrameWindow(this);
516     label_window = new LabelWindow(this);
517     envelope_window = new EnvelopeWindow(this);
518 
519     if (resource->validMailbox()) {
520         checkmail = new Checkmail(this);
521         makeWindow(false);
522         redraw(False);
523         checkmail->forceCheck();
524     } else {
525         throw -1;
526     }
527 
528 }
529 
~ToolWindow()530 ToolWindow::~ToolWindow()
531 {
532     delete envelope_window;
533     delete label_window;
534     delete mbmenu;
535     delete resource;
536     delete checkmail;
537     delete frame_window;
538 }
539 
540 
reconfigure(void)541 void ToolWindow::reconfigure(void)
542 {
543     delete resource;
544     resource = new Resource(this, _config.rcFilename());
545     mbmenu->reconfigure();
546     checkmail->reconfigure();
547 
548     makeWindow(true);
549 
550 //    if (resource->show.label) XClearWindow(XDisplay(), label_window->window());
551 //    XClearWindow(XDisplay(), envelope_window->window());
552 //    XClearWindow(XDisplay(), frame_window->window());
553     redraw(False);
554 }
555 
makeWindow(bool reconfigure)556 void ToolWindow::makeWindow(bool reconfigure)
557 {
558     frame_window->setHeight(textHeight(getCurrentScreen(), resource->frame.font) + 4 * resource->frame.bevelWidth);
559 
560     if (resource->show.envelope) {
561         envelope_window->setHeight(frame_window->height() - 2 * resource->frame.bevelWidth -
562                         2 * resource->envelope.bevelHeight);
563         envelope_window->setWidth((envelope_window->height() * 3) / 2);
564 
565         if (!(fmod((double)envelope_window->width(), 2.0) > 0.0))
566             envelope_window->setWidth(envelope_window->width() + 1);
567     } else
568         envelope_window->setWidth(0);
569 
570 
571     if (resource->show.label) {
572         label_window->calcSize();
573         label_window->setHeight(frame_window->height() - 2 * resource->frame.bevelWidth);
574     }
575 
576     frame_window->setWidth(label_window->width() + envelope_window->width()
577                  + resource->frame.bevelWidth * 3 + resource->envelope.bevelWidth * 2);
578 
579     if (resource->position.mask & XNegative)
580         resource->position.x = getCurrentScreenInfo()->width() +
581                                resource->position.x - frame_window->width();
582     if (resource->position.mask & YNegative)
583         resource->position.y = getCurrentScreenInfo()->height() +
584                                resource->position.y - frame_window->height();
585 
586     if (!config().isWithdrawn()) {
587         frame_window->setX(resource->position.x);
588         frame_window->setY(resource->position.y);
589     }
590 
591     if (!reconfigure) {
592         frame_window->createWindow();
593     } else {
594         frame_window->reconfigure();
595     }
596     if (resource->show.label) {
597         label_window->setX(2 * resource->frame.bevelWidth +
598                        envelope_window->width() + 2 * resource->envelope.bevelWidth);
599         label_window->setY(resource->frame.bevelWidth);
600        if (!reconfigure)
601             label_window->createWindow();
602         else
603             label_window->reconfigure();
604     }
605     if (resource->show.envelope) {
606         envelope_window->setX(resource->frame.bevelWidth + resource->envelope.bevelWidth);
607                 envelope_window->setY(resource->frame.bevelWidth + resource->envelope.bevelWidth);
608         if (!reconfigure)
609             envelope_window->createWindow();
610         else
611             envelope_window->reconfigure();
612     }
613 
614     if (!reconfigure) {
615         mbmenu = new MailboxMenu(this);
616         XClearWindow(XDisplay(), frame_window->window());
617         XMapSubwindows(XDisplay(), frame_window->window());
618         mapped=true;
619         if (!config().isDecorated() && !config().isWithdrawn())
620         {
621             XMoveResizeWindow(XDisplay(),frame_window->window(),frame_window->x(),
622                               frame_window->y(), frame_window->width(),
623                               frame_window->height());
624         }
625     }
626 }
627 
628 
629 
redraw(bool change_raise)630 void ToolWindow::redraw(bool change_raise)
631 {
632     if (checkmail->getNewmail()==0) {
633         if (resource->show.onlyAtNewMail&mapped) {
634             XUnmapSubwindows(XDisplay(), frame_window->window());
635             XUnmapWindow(XDisplay(), frame_window->window());
636             mapped=false;
637         }
638         else if (resource->show.envelope) {
639             envelope_window->redraw();
640         }
641     } else {
642         if ((resource->show.onlyAtNewMail) & (!(mapped))) {
643             XMapSubwindows(XDisplay(), frame_window->window());
644             XMapWindow(XDisplay(),frame_window->window());
645             mapped=true;
646         }
647         if (change_raise) {
648             if (resource->spoolfile[checkmail->getNewMailbox()].bell)
649                 XBell(XDisplay(),100);
650             if (!resource->spoolfile[checkmail->getNewMailbox()].newmailProc.empty());
651             system(resource->spoolfile[checkmail->getNewMailbox()].newmailProc.c_str());
652             if ((resource->report.auto_raise)&(!(raised))) {
653                 XRaiseWindow(XDisplay(), frame_window->window());
654                 raised = true;
655             }
656         }
657         if (resource->show.envelope) {
658             envelope_window->redraw();
659         }
660     }
661     if (resource->show.label) {
662         label_window->redraw();
663     }
664 
665 }
666 
667 
FrameWindow(ToolWindow * toolwindow)668 FrameWindow::FrameWindow(ToolWindow *toolwindow) :
669              bt::EventHandler() ,
670              m_pBbtool(toolwindow),
671              fwindow(0),
672              fx(0),
673              fy(0),
674              m_pixmap(0),
675              fposition(NULL),
676              m_screen(toolwindow->getCurrentScreen()),
677              display(toolwindow->XDisplay())
678 {
679 }
680 
~FrameWindow(void)681 FrameWindow::~FrameWindow(void)
682 {
683     if (m_pixmap) bt::PixmapCache::release(m_pixmap);
684     if (fposition) delete fposition;
685 
686     if (fwindow) XDestroyWindow(display, fwindow);
687 
688 }
689 
createWindow(void)690 void FrameWindow::createWindow(void)
691 {
692     XSetWindowAttributes attrib;
693     XWMHints wmhints;
694     unsigned long create_mask = CWBackPixmap | CWCursor | CWEventMask | CWOverrideRedirect;
695 
696     attrib.background_pixmap = ParentRelative;
697     m_pixmap = bt::PixmapCache::find(m_screen,
698          m_pBbtool->getResource()->frame.texture, fwidth, fheight);
699     if (m_pBbtool->config().isWithdrawn()) {
700         wmhints.initial_state = WithdrawnState;
701     } else {
702         wmhints.initial_state = NormalState;
703     }
704 
705     attrib.cursor =  XCreateFontCursor(display, XC_left_ptr);
706     attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
707                         FocusChangeMask | KeyPressMask | StructureNotifyMask;
708     attrib.override_redirect = False;
709 
710     bt::EWMH ewmh(m_pBbtool->display());
711     bool wm_window_type_dock = false;
712 
713     if (!m_pBbtool->config().isDecorated() && !m_pBbtool->config().isWithdrawn()) {
714         bt::EWMH::AtomList supported_atoms;
715         if (ewmh.readSupported(m_pBbtool->getCurrentScreenInfo()->rootWindow(), supported_atoms)) {
716 
717           bt::EWMH::AtomList::iterator it = supported_atoms.begin();
718             for (; it != supported_atoms.end(); ++it) {
719                 if ( (*it) ==  ewmh.wmWindowTypeDock()) {
720                     wm_window_type_dock = true;
721                 }
722             }
723         } else {
724             attrib.override_redirect = True;
725         }
726     }
727 
728     fwindow = XCreateWindow(display,
729                         m_pBbtool->getCurrentScreenInfo()->rootWindow(),
730                         fx, fy, fwidth, fheight, 0,
731                         m_pBbtool->getCurrentScreenInfo()->depth(),
732                         InputOutput, m_pBbtool->getCurrentScreenInfo()->visual(),
733                         create_mask, &attrib);
734 
735     wmhints.flags = IconWindowHint | StateHint;
736     wmhints.icon_window = fwindow;
737     XTextProperty windowname;
738     XClassHint classhints;
739 
740     char *name = (char *)PACKAGE;
741     XSizeHints sizehints;
742 
743     classhints.res_name = (char *)PACKAGE;
744     classhints.res_class = (char *)"m_pBbtools";
745 
746     sizehints.x = m_pBbtool->getResource()->position.x;
747     sizehints.y = m_pBbtool->getResource()->position.y;
748     sizehints.max_width = sizehints.min_width = fwidth;
749     sizehints.max_height = sizehints.min_height = fheight;
750     sizehints.flags = USPosition | PMinSize | PMaxSize;
751 
752     XStringListToTextProperty(&name, 1, &windowname);
753     XSetWMProperties(display, fwindow, &windowname, NULL, m_pBbtool->config().argv(), m_pBbtool->config().argc(),
754                      &sizehints, &wmhints, &classhints);
755     XFree(windowname.value);
756     Atom wmproto[2];
757     wmproto[0] = m_pBbtool->wmDeleteWindowAtom();
758     XSetWMProtocols(display, fwindow, wmproto, 1);
759     bt::EWMH::AtomList window_type_atom;
760     window_type_atom.push_back(ewmh.wmWindowTypeDock());
761     if (!m_pBbtool->config().isDecorated() && !m_pBbtool->config().isWithdrawn()) {
762         if (wm_window_type_dock) {
763                 XChangeProperty(display, fwindow, ewmh.wmWindowType(), XA_ATOM,
764                             32, PropModeReplace,
765                             reinterpret_cast<unsigned char*>(&(window_type_atom[0])), window_type_atom.size());
766         } else {
767             //attrib.override_redirect set
768             fprintf(stderr, "Cannot dock\n");
769         }
770     }
771     bt::EWMH::AtomList state_atom;
772     state_atom.push_back(ewmh.wmStateSticky());
773     state_atom.push_back(ewmh.wmStateSkipTaskbar());
774     state_atom.push_back(ewmh.wmStateSkipPager());
775     ewmh.setWMState(fwindow, state_atom);
776 
777     //XSetWindowBackgroundPixmap(display, fwindow, m_pixmap);
778     redraw();
779 
780     m_pBbtool->insertEventHandler(fwindow, this);
781 }
782 
redraw(void)783 void FrameWindow::redraw(void)
784 {
785      bt::Rect u(0, 0, fwidth, fheight);
786      bt::drawTexture(m_screen,
787                       m_pBbtool->getResource()->frame.texture,
788                       fwindow,
789                       u, u, m_pixmap);
790 }
791 
reconfigure(void)792 void FrameWindow::reconfigure(void)
793 {
794     bt::PixmapCache::release(m_pixmap);
795     m_pixmap = bt::PixmapCache::find(m_screen,
796          m_pBbtool->getResource()->frame.texture, fwidth, fheight);
797 
798      if (!m_pBbtool->config().isWithdrawn()) {
799         XMoveResizeWindow(display, fwindow, fx, fy, fwidth, fheight);
800     } else {
801         XResizeWindow(display, fwindow, fwidth, fheight);
802     }
803      redraw();
804 }
805 
clientMessageEvent(const XClientMessageEvent * xclient_event)806 void FrameWindow::clientMessageEvent(const XClientMessageEvent *xclient_event)
807 {
808     if ((unsigned)xclient_event->data.l[0] == m_pBbtool->wmDeleteWindowAtom())
809       m_pBbtool->shutdown();
810 }
811 
exposeEvent(const XExposeEvent *)812 void FrameWindow::exposeEvent(const XExposeEvent *)
813 {
814     redraw();
815 }
816 
buttonPressEvent(const XButtonEvent * xbutton_event)817 void FrameWindow::buttonPressEvent(const XButtonEvent *xbutton_event)
818 {
819     if (xbutton_event->button == LEFT_BUTTON) {
820         if (!m_pBbtool->isRaised()) {
821             XRaiseWindow(display, fwindow);
822             m_pBbtool->setRaised(true);
823         }
824     } else if (xbutton_event->button == MIDDLE_BUTTON) {
825         if (m_pBbtool->isRaised()) {
826             XLowerWindow(display, fwindow);
827             m_pBbtool->setRaised(false);
828         }
829     }
830 }
831 
LabelWindow(ToolWindow * toolwindow)832 LabelWindow::LabelWindow(ToolWindow *toolwindow) :
833              bt::EventHandler() ,
834              m_pBbtool(toolwindow),
835              m_pDisplay(toolwindow->XDisplay()),
836              m_window(0),
837              m_pixmap(0),
838              m_x(0),
839              m_y(0),
840              m_widthNewMail(0),
841              m_widthTotalMail(0),
842              m_widthSeperator(0),
843              m_screen(toolwindow->getCurrentScreen())
844 
845 {
846 }
847 
~LabelWindow(void)848 LabelWindow::~LabelWindow(void)
849 {
850     if (m_pixmap) bt::PixmapCache::release(m_pixmap);
851     if (m_window) XDestroyWindow(m_pDisplay, m_window);
852     delete m_pPen;
853 }
854 
createWindow(void)855 void LabelWindow::createWindow(void)
856 {
857     XSetWindowAttributes attrib;
858     unsigned long create_mask = CWBackPixmap | CWEventMask;
859 
860     int i;
861     m_maxValue = 1;
862     for (i = 0; i < m_pBbtool->getResource()->report.number_of_digits; i++)
863         m_maxValue *= 10;
864 
865     m_maxValue -= 1;
866 
867 
868     attrib.background_pixmap = ParentRelative;
869     attrib.cursor =  XCreateFontCursor(m_pDisplay, XC_left_ptr);
870     attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
871                         FocusChangeMask | KeyPressMask | StructureNotifyMask;
872 
873     if (!m_pBbtool->getResource()->label.transparent)
874         m_pixmap = bt::PixmapCache::find(m_screen,
875                         m_pBbtool->getResource()->label.texture, m_width, m_height);
876     m_window = XCreateWindow(m_pDisplay, m_pBbtool->frameWindow()->window(), m_x, m_y,
877                             m_width, m_height, 0,
878                             m_pBbtool->getCurrentScreenInfo()->depth(), InputOutput,
879                             m_pBbtool->getCurrentScreenInfo()->visual(),
880                             create_mask, &attrib);
881 
882     m_pPen = new bt::Pen(m_screen,
883                          m_pBbtool->getResource()->label.newmail_textColor);
884 //  lpen->setFont(m_pBbtool->getResource()->label.font);
885 
886     redraw();
887     m_pBbtool->insertEventHandler(m_window, this);
888     XClearWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
889     XMapWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
890     XMapSubwindows(m_pDisplay, m_pBbtool->frameWindow()->window());
891 
892 
893 }
894 
reconfigure(void)895 void LabelWindow::reconfigure(void)
896 {
897     if (!m_pBbtool->getResource()->label.transparent) {
898         bt::PixmapCache::release(m_pixmap);
899         m_pixmap = bt::PixmapCache::find(m_screen,
900                         m_pBbtool->getResource()->label.texture, m_width, m_height);
901     }
902     XMoveResizeWindow(m_pDisplay, m_window, m_x, m_y, m_width, m_height);
903     delete m_pPen;
904     m_pPen = new bt::Pen(m_screen,
905                          m_pBbtool->getResource()->label.newmail_textColor);
906 
907     redraw();
908 }
909 
calcSize()910 void LabelWindow::calcSize()
911 {
912     bt::ustring str;
913     char *t;
914     t = new char [m_pBbtool->getResource()->report.number_of_digits + m_pBbtool->getResource()->report.number_of_digits + 1 + 1];
915     if (m_pBbtool->getResource()->show.newmail_counter && m_pBbtool->getResource()->show.newmail_counter)
916     {
917         sprintf(t, "%0*d/%0*d", m_pBbtool->getResource()->report.number_of_digits, 0, m_pBbtool->getResource()->report.number_of_digits, 0);
918         str = bt::toUnicode(t);
919         unsigned int text_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
920         m_width = text_width + 3 * m_pBbtool->getResource()->frame.bevelWidth;
921         sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
922         str = bt::toUnicode(t);
923         m_widthNewMail = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
924         sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
925         str = bt::toUnicode(t);
926         m_widthTotalMail = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width();
927         m_widthSeperator = text_width - m_widthNewMail - m_widthTotalMail;
928     }
929     else if (m_pBbtool->getResource()->show.newmail_counter)    // split these up now, so we can use different number_of_digits later
930     {
931         sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
932         str = bt::toUnicode(t);
933         m_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width() +
934             2 * m_pBbtool->getResource()->frame.bevelWidth;
935     }
936     else if (m_pBbtool->getResource()->show.totalmail_counter)
937     {
938         sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, 0);
939         str = bt::toUnicode(t);
940         m_width = bt::textRect(m_pBbtool->getCurrentScreen(), m_pBbtool->getResource()->label.font, str).width() +
941             2 * m_pBbtool->getResource()->frame.bevelWidth;
942     }
943     delete [] t;
944 }
945 
946 
redraw(void)947 void LabelWindow::redraw(void)
948 {
949     // redraw windows
950     if (m_pixmap == ParentRelative || m_pBbtool->getResource()->label.transparent)    // we can remove the transparent option in the future
951     {
952         bt::Rect u(0, 0, width(), height());
953         bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
954         bt::drawTexture(m_screen,
955                         m_pBbtool->getResource()->frame.texture,
956                         m_window,
957                         t, u, m_pBbtool->frameWindow()->pixmap());
958     }
959     else
960     {
961         bt::Rect u(0, 0, width(), height());
962         bt::drawTexture(m_screen,
963                         m_pBbtool->getResource()->label.texture,
964                         m_window,
965                         u, u, m_pixmap);
966     }
967 
968     // redraw text
969     char t[6];
970     bt::ustring txt;
971 //    if (m_pBbtool->getResource()->show.label)
972 //        XClearWindow(m_pDisplay, m_window);
973     if (m_pBbtool->getResource()->show.newmail_counter) {
974         if (m_pBbtool->checkMail()->getNewmail() == 0)
975             XSetForeground(m_pDisplay, m_pPen->gc(),
976                            m_pBbtool->getResource()->label.newmail_boring_textColor.pixel(m_screen));
977         else
978                 XSetForeground(m_pDisplay, m_pPen->gc(),
979                                m_pBbtool->getResource()->label.newmail_textColor.pixel(m_screen));
980 
981         if (m_pBbtool->checkMail()->getNewmail() < m_maxValue) {
982             sprintf(t, "%0*d",m_pBbtool->getResource()->report.number_of_digits, m_pBbtool->checkMail()->getNewmail());
983             txt = bt::toUnicode(t);
984             bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
985             text_rect.setX(m_pBbtool->getResource()->frame.bevelWidth);
986             text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
987             text_rect.setWidth(m_widthNewMail);
988             drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window,
989                  text_rect, bt::AlignCenter, txt);
990         } else {
991             sprintf(t, ">");
992             txt = bt::toUnicode(t);
993             bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
994             text_rect.setX(m_pBbtool->getResource()->frame.bevelWidth);
995             text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
996             text_rect.setWidth(m_widthNewMail);
997             drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window,
998                  text_rect, bt::AlignCenter, txt);
999         }
1000     }
1001     if (m_pBbtool->getResource()->show.totalmail_counter) {
1002         if (m_pBbtool->getResource()->show.newmail_counter) {
1003             if ((m_pBbtool->checkMail()->getLastTotalmail() == 0) | (m_pBbtool->checkMail()->getNewmail() == 0))
1004                 XSetForeground(m_pDisplay, m_pPen->gc(),
1005                  m_pBbtool->getResource()->label.seperator_boring_textColor.pixel(m_screen));
1006             else
1007                 XSetForeground(m_pDisplay, m_pPen->gc(),
1008                            m_pBbtool->getResource()->label.seperator_textColor.pixel(m_screen));
1009             sprintf(t, SEPERATOR);
1010             txt = bt::toUnicode(t);
1011             bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
1012             text_rect.setX(m_widthNewMail + m_pBbtool->getResource()->frame.bevelWidth);
1013             text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
1014             text_rect.setWidth(m_widthSeperator);
1015             drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window,
1016                  text_rect, bt::AlignCenter, txt);
1017         }
1018         if (m_pBbtool->checkMail()->getLastTotalmail() > m_maxValue) {
1019             sprintf(t, ">");
1020             txt = bt::toUnicode(t);
1021             bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
1022             text_rect.setX(m_widthNewMail + m_widthSeperator + m_pBbtool->getResource()->frame.bevelWidth);
1023             text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
1024             text_rect.setWidth(m_widthTotalMail);
1025             drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window,
1026                  text_rect, bt::AlignCenter, txt);
1027         } else {
1028             if (m_pBbtool->checkMail()->getLastTotalmail() == 0) {
1029                 XSetForeground(m_pDisplay, m_pPen->gc(),
1030                         m_pBbtool->getResource()->label.totalmail_boring_textColor.pixel(m_screen));
1031                 } else {
1032                     XSetForeground(m_pDisplay, m_pPen->gc(),
1033                         m_pBbtool->getResource()->label.totalmail_textColor.pixel(m_screen));
1034             }
1035 
1036             sprintf(t, "%0*d", m_pBbtool->getResource()->report.number_of_digits, m_pBbtool->checkMail()->getLastTotalmail());
1037             txt = bt::toUnicode(t);
1038             bt::Rect text_rect = bt::textRect(m_screen, m_pBbtool->getResource()->label.font, txt);
1039             text_rect.setX( m_widthNewMail + m_widthSeperator + m_pBbtool->getResource()->frame.bevelWidth);
1040             text_rect.setY(text_rect.y() + m_pBbtool->getResource()->frame.bevelWidth);
1041             text_rect.setWidth(m_widthTotalMail);
1042             drawText(m_pBbtool->getResource()->label.font, *m_pPen, m_window,
1043                 text_rect, bt::AlignCenter, txt);
1044         }
1045     }
1046 }
1047 
buttonPressEvent(const XButtonEvent * xbutton_event)1048 void LabelWindow::buttonPressEvent(const XButtonEvent *xbutton_event)
1049 {
1050     if (xbutton_event->button == LEFT_BUTTON) {
1051         if (!m_pBbtool->isRaised()) {
1052             XRaiseWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
1053             m_pBbtool->setRaised(true);
1054         }
1055     } else if (xbutton_event->button == MIDDLE_BUTTON) {
1056         if (m_pBbtool->isRaised()) {
1057             XLowerWindow(m_pDisplay, m_pBbtool->frameWindow()->window());
1058             m_pBbtool->setRaised(false);
1059         }
1060     }
1061 }
1062 
exposeEvent(const XExposeEvent *)1063 void LabelWindow::exposeEvent(const XExposeEvent *)
1064 {
1065     redraw();
1066 }
1067 
EnvelopeWindow(ToolWindow * toolwindow)1068 EnvelopeWindow::EnvelopeWindow(ToolWindow *toolwindow) :
1069             bt::EventHandler() ,
1070             display(toolwindow->XDisplay()),
1071             m_pBbtool(toolwindow),
1072             m_screen(toolwindow->getCurrentScreen()),
1073             m_window(0),
1074             ex(0),
1075             ey(0),
1076             pixmap(0),
1077             pixmap_pressed(0),
1078             envelope_pushed(false)
1079 {
1080 }
1081 
~EnvelopeWindow(void)1082 EnvelopeWindow::~EnvelopeWindow(void)
1083 {
1084     if (pixmap) bt::PixmapCache::release(pixmap);
1085     if (pixmap_pressed) bt::PixmapCache::release(pixmap_pressed);
1086     int i;
1087     for (i = 0; i < num_of_pixmaps; i++) {
1088         bt::PixmapCache::release(pixmap_new[i]);
1089         bt::PixmapCache::release(pixmap_new_pressed[i]);
1090     }
1091 
1092     delete [] pixmap_new;
1093     delete [] pixmap_new_pressed;
1094     delete epen;
1095 
1096     if (m_window) XDestroyWindow(display, m_window);
1097 }
1098 
createWindow(void)1099 void EnvelopeWindow::createWindow(void)
1100 {
1101     XSetWindowAttributes attrib;
1102     unsigned long create_mask = CWBackPixmap | CWCursor | CWEventMask;
1103     attrib.background_pixmap = ParentRelative;
1104     attrib.cursor =  XCreateFontCursor(display, XC_left_ptr);
1105     attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
1106                         FocusChangeMask | KeyPressMask | StructureNotifyMask;
1107 
1108 
1109     pixmap = bt::PixmapCache::find(m_screen,
1110             m_pBbtool->getResource()->envelope.texture, ewidth, eheight);
1111 
1112     pixmap_pressed = bt::PixmapCache::find(m_screen,
1113               m_pBbtool->getResource()->envelope.texture_pressed,
1114               ewidth, eheight);
1115 
1116     num_of_pixmaps = m_pBbtool->getResource()->report.number_of_spoolfiles;
1117     pixmap_new = new Pixmap [num_of_pixmaps];
1118     pixmap_new_pressed = new Pixmap [num_of_pixmaps];
1119 
1120     int i;
1121     for (i = 0; i < num_of_pixmaps; i++) {
1122         pixmap_new[i] = bt::PixmapCache::find(m_screen,
1123                 m_pBbtool->getResource()->spoolfile[i].newmail_texture,
1124                 ewidth, eheight);
1125 
1126         pixmap_new_pressed[i] = bt::PixmapCache::find(m_screen,
1127                     m_pBbtool->getResource()->spoolfile[i].newmail_pressed_texture,
1128                     ewidth, eheight);
1129     }
1130 
1131     m_window = XCreateWindow(display, m_pBbtool->frameWindow()->window(),
1132                     ex, ey, ewidth, eheight, 0,
1133                         m_pBbtool->getCurrentScreenInfo()->depth(),
1134                         InputOutput, m_pBbtool->getCurrentScreenInfo()->visual(),
1135                         create_mask, &attrib);
1136 
1137     epen = new bt::Pen(m_screen, m_pBbtool->getResource()->envelope.textColor);
1138     //epen->setFont(m_pBbtool->getResource()->frame.font);
1139 
1140     calcPoints();
1141 
1142     m_pBbtool->insertEventHandler(m_window, this);
1143 
1144 }
1145 
reconfigure(void)1146 void EnvelopeWindow::reconfigure(void)
1147 {
1148     bt::PixmapCache::release(pixmap);
1149     bt::PixmapCache::release(pixmap_pressed);
1150 
1151     int i;
1152     for (i = 0; i < num_of_pixmaps; i++) {
1153         bt::PixmapCache::release(pixmap_new[i]);
1154         bt::PixmapCache::release(pixmap_new_pressed[i]);
1155     }
1156 
1157     delete [] pixmap_new;
1158     delete [] pixmap_new_pressed;
1159 
1160     pixmap = bt::PixmapCache::find(m_screen,
1161             m_pBbtool->getResource()->envelope.texture, ewidth, eheight);
1162 
1163     pixmap_pressed = bt::PixmapCache::find(m_screen,
1164               m_pBbtool->getResource()->envelope.texture_pressed,
1165               ewidth, eheight);
1166 
1167     num_of_pixmaps = m_pBbtool->getResource()->report.number_of_spoolfiles;
1168     pixmap_new = new Pixmap [num_of_pixmaps];
1169     pixmap_new_pressed = new Pixmap [num_of_pixmaps];
1170 
1171 
1172     for (i = 0; i < num_of_pixmaps; i++) {
1173         pixmap_new[i] = bt::PixmapCache::find(m_screen,
1174                 m_pBbtool->getResource()->spoolfile[i].newmail_texture,
1175                 ewidth, eheight);
1176 
1177         pixmap_new_pressed[i] = bt::PixmapCache::find(m_screen,
1178                     m_pBbtool->getResource()->spoolfile[i].newmail_pressed_texture,
1179                     ewidth, eheight);
1180     }
1181     delete epen;
1182     epen = new bt::Pen(m_screen, m_pBbtool->getResource()->envelope.textColor);
1183     calcPoints();
1184 
1185     XMoveResizeWindow(display, m_window, ex, ey, ewidth, eheight);
1186     redraw();
1187 }
1188 
release(void)1189 void EnvelopeWindow::release(void)
1190 {
1191     if (envelope_pushed) {
1192         envelope_pushed = false;
1193         m_pBbtool->redraw(false);
1194     }
1195 }
1196 
buttonPressEvent(const XButtonEvent * xbutton_event)1197 void EnvelopeWindow::buttonPressEvent(const XButtonEvent *xbutton_event)
1198 {
1199     if (xbutton_event->button == LEFT_BUTTON) {
1200         if (!m_pBbtool->isRaised()) {
1201             XRaiseWindow(display, m_pBbtool->frameWindow()->window());
1202             m_pBbtool->setRaised(true);
1203         }
1204         envelope_pushed = true;
1205         m_pBbtool->redraw(false);
1206     } else if (xbutton_event->button == MIDDLE_BUTTON) {
1207         if (m_pBbtool->isRaised()) {
1208             XLowerWindow(display, m_pBbtool->frameWindow()->window());
1209             m_pBbtool->setRaised(false);
1210         }
1211     } else if (xbutton_event->button == RIGHT_BUTTON) {
1212         if (!envelope_pushed) {
1213             envelope_pushed = true;
1214             m_pBbtool->redraw(false);
1215             if (!m_pBbtool->mbMenu()->isVisible()) {
1216                 m_pBbtool->mbMenu()->popup(m_pBbtool->frameWindow()->x(), m_pBbtool->frameWindow()->y(),
1217                                 m_pBbtool->config().isWithdrawn());
1218             }
1219         }
1220     }
1221 }
1222 
buttonReleaseEvent(const XButtonEvent * xbutton_event)1223 void EnvelopeWindow::buttonReleaseEvent(const XButtonEvent *xbutton_event)
1224 {
1225     if (xbutton_event->button == LEFT_BUTTON) {
1226         envelope_pushed = false;
1227         m_pBbtool->redraw(false);
1228         if (xbutton_event->x > 0 && xbutton_event->x < (int)ewidth &&
1229             xbutton_event->y > 0 && xbutton_event->y < (int)eheight ) {
1230             if (m_pBbtool->checkMail()->getNewmail() != 0) {
1231                 if (!m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].runCommand.empty()) {
1232                     system(m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].runCommand.c_str());
1233                 }
1234                 else {
1235                     if (!m_pBbtool->getResource()->report.runCommand.empty()) {
1236                         system(m_pBbtool->getResource()->report.runCommand.c_str());
1237                     }
1238                 }
1239             } else {
1240                 if (!m_pBbtool->getResource()->report.runCommand.empty()) {
1241                     system(m_pBbtool->getResource()->report.runCommand.c_str());
1242                 }
1243             }
1244         }
1245     }
1246 }
1247 
exposeEvent(const XExposeEvent *)1248 void EnvelopeWindow::exposeEvent(const XExposeEvent *)
1249 {
1250     redraw();
1251 }
1252 
calcPoints(void)1253 void EnvelopeWindow::calcPoints(void) {
1254     points[0].x =  2;
1255     points[0].y =  2;
1256     points[1].x = ewidth / 2;
1257     points[1].y = (eheight * 2) / 3;
1258     points[2].x = ewidth - 3;
1259     points[2].y = 2;
1260 
1261     points[3].x = 2;
1262     points[3].y = eheight - 3;
1263     points[4].x = ewidth / 3;
1264     points[4].y = eheight / 2 - 1;
1265 
1266     points[5].x = ewidth - 3;
1267     points[5].y = eheight - 3;
1268     points[6].x = (ewidth * 2) / 3;
1269     points[6].y = eheight / 2;
1270 
1271     points[7].x = ewidth / 3;
1272     points[7].y = 2;
1273     points[8].x = (ewidth * 2) / 3 - 1;
1274     points[8].y = eheight / 2;
1275 
1276     points[9].x = (ewidth * 2) / 3 - 1;
1277     points[9].y = 2;
1278     points[10].x = ewidth / 3;
1279     points[10].y = eheight / 2;
1280 }
1281 
redraw(void)1282 void EnvelopeWindow::redraw(void)
1283 {
1284     if (m_pBbtool->checkMail()->getNewmail() == 0)
1285     {
1286 
1287         if (envelope_pushed)
1288         {
1289 //            XSetWindowBackgroundPixmap(display, m_window, pixmap_pressed);
1290             if (pixmap_pressed == ParentRelative)
1291             {
1292                 bt::Rect u(0, 0, width(), height());
1293                 bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
1294                 bt::drawTexture(m_screen,
1295                                 m_pBbtool->getResource()->frame.texture,
1296                                 m_window,
1297                                 t, u, m_pBbtool->frameWindow()->pixmap());
1298             }
1299             else
1300             {
1301                 bt::Rect u(0, 0, width(), height());
1302                 bt::drawTexture(m_screen,
1303                                 m_pBbtool->getResource()->envelope.texture_pressed,
1304                                 m_window,
1305                                 u, u, pixmap_pressed);
1306             }
1307         }
1308         else
1309         {
1310 //            XSetWindowBackgroundPixmap(display, m_window, pixmap);
1311             if (pixmap == ParentRelative)
1312             {
1313                 bt::Rect u(0, 0, width(), height());
1314                 bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
1315                 bt::drawTexture(m_screen,
1316                                 m_pBbtool->getResource()->frame.texture,
1317                                 m_window,
1318                                 t, u, m_pBbtool->frameWindow()->pixmap());
1319             }
1320             else
1321             {
1322                 bt::Rect u(0, 0, width(), height());
1323                 bt::drawTexture(m_screen,
1324                                 m_pBbtool->getResource()->envelope.texture,
1325                                 m_window,
1326                                 u, u, pixmap);
1327             }
1328         }
1329 
1330         XSetForeground(display, epen->gc(),
1331                 m_pBbtool->getResource()->envelope.textColor.pixel(m_screen));
1332         XClearWindow(display, m_window);
1333         XDrawLines(display, m_window, epen->gc(), points, 3, CoordModeOrigin);
1334         XDrawLine(display, m_window, epen->gc(), points[3].x, points[3].y,
1335               points[4].x, points[4].y);
1336         XDrawLine(display, m_window, epen->gc(), points[5].x, points[5].y,
1337               points[6].x, points[6].y);
1338         if (m_pBbtool->checkMail()->getBroken()) {
1339             XSetForeground(display, epen->gc(),
1340                     m_pBbtool->getResource()->envelope.error_textColor.pixel(m_screen));
1341             XSetLineAttributes(display, epen->gc() , 2, LineSolid, CapButt, JoinMiter);
1342             XDrawLine(display, m_window, epen->gc(), points[7].x, points[7].y,
1343                   points[8].x, points[8].y);
1344             XDrawLine(display, m_window, epen->gc(), points[9].x, points[9].y,
1345                   points[10].x, points[10].y);
1346             XSetLineAttributes(display, epen->gc(), 0, LineSolid,CapButt,JoinMiter);
1347         }
1348     } else {
1349         if (envelope_pushed)
1350         {
1351             if (pixmap_pressed == ParentRelative)
1352             {
1353                 bt::Rect u(0, 0, width(), height());
1354                 bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
1355                 bt::drawTexture(m_screen,
1356                                 m_pBbtool->getResource()->frame.texture,
1357                                 m_window,
1358                                 t, u, m_pBbtool->frameWindow()->pixmap());
1359             }
1360             else
1361             {
1362                 bt::Rect u(0, 0, width(), height());
1363                 bt::drawTexture(m_screen,
1364                                 m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].newmail_pressed_texture,
1365                                 m_window,
1366                                 u, u, pixmap_new_pressed[m_pBbtool->checkMail()->getNewMailbox()]);
1367             }
1368 
1369 //            XSetWindowBackgroundPixmap(display, m_window,
1370 //                           pixmap_new_pressed[m_pBbtool->checkMail()->getNewMailbox()]);
1371         }
1372         else
1373         {
1374             if (pixmap_pressed == ParentRelative)
1375             {
1376                 bt::Rect u(0, 0, width(), height());
1377                 bt::Rect t(-x(), -y(), m_pBbtool->frameWindow()->width(), m_pBbtool->frameWindow()->height());
1378                 bt::drawTexture(m_screen,
1379                                 m_pBbtool->getResource()->frame.texture,
1380                                 m_window,
1381                                 t, u, m_pBbtool->frameWindow()->pixmap());
1382             }
1383             else
1384             {
1385                 bt::Rect u(0, 0, width(), height());
1386                 bt::drawTexture(m_screen,
1387                                 m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].newmail_texture,
1388                                 m_window,
1389                                 u, u, pixmap_new[m_pBbtool->checkMail()->getNewMailbox()]);
1390             }
1391 //            XSetWindowBackgroundPixmap(display, m_window,
1392 //                           pixmap_new[m_pBbtool->checkMail()->getNewMailbox()]);
1393         }
1394         XSetForeground(display, epen->gc(),
1395                    m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].
1396                    newmail_textColor.pixel(m_screen));
1397 
1398         XClearWindow(display, m_window);
1399         XDrawLines(display, m_window, epen->gc(), points, 3, CoordModeOrigin);
1400         XDrawLine(display, m_window, epen->gc(), points[3].x,
1401               points[3].y, points[4].x, points[4].y);
1402         XDrawLine(display, m_window, epen->gc(), points[5].x, points[5].y,
1403               points[6].x, points[6].y);
1404 
1405         if (m_pBbtool->checkMail()->getBroken()) {
1406             XSetForeground(display, epen->gc(),
1407                        m_pBbtool->getResource()->spoolfile[m_pBbtool->checkMail()->getNewMailbox()].
1408                        newmail_error_textColor.pixel(m_screen));
1409             XSetLineAttributes(display, epen->gc(), 2, LineSolid,CapButt,JoinMiter);
1410             XDrawLine(display, m_window, epen->gc(), points[7].x, points[7].y,
1411                   points[8].x, points[8].y);
1412             XDrawLine(display, m_window, epen->gc(), points[9].x, points[9].y,
1413                   points[10].x, points[10].y);
1414             XSetLineAttributes(display, epen->gc(), 0, LineSolid, CapButt, JoinMiter);
1415         }
1416     }
1417 }
1418 
configureNotifyEvent(const XConfigureEvent * xconfigure_event)1419 void FrameWindow::configureNotifyEvent(const XConfigureEvent *xconfigure_event)
1420 {
1421     if (xconfigure_event->send_event) {
1422         if (m_pBbtool->config().isWithdrawn()) {
1423             m_pBbtool->reconfigure();
1424         }
1425         int parent_x,parent_y;
1426         Window parent_root;
1427         unsigned int parent_width;
1428         unsigned int parent_height;
1429         unsigned int parent_border_width;
1430         unsigned int parent_depth;
1431         if (m_pBbtool->config().isWithdrawn()) {
1432             XGetGeometry(display, xconfigure_event->above, &parent_root,
1433                          &parent_x, &parent_y, &parent_width, &parent_height,
1434                          &parent_border_width, &parent_depth);
1435             fx = xconfigure_event->x + parent_x;
1436             fy = xconfigure_event->y + parent_y;
1437         } else {
1438             fx = xconfigure_event->x;
1439             fy = xconfigure_event->y;
1440             if (m_pBbtool->config().isDecorated()) {
1441                 char position[13];
1442                 sprintf(position,"+%i+%i", fx, fy);
1443                 m_pBbtool->config().setGeometry(position);
1444             }
1445         }
1446         if (m_pBbtool->mbMenu()->isVisible())
1447             m_pBbtool->mbMenu()->show();
1448     }
1449 }
1450