3 * multi pop3 mail checker.
4 * written by Louis-Benoit JOURDAIN (lb@jourdain.org)
5 * based on the original work by Scott Holden (scotth@thezone.net)
18 #include <sys/socket.h>
20 #include <sys/param.h>
21 #include <sys/types.h>
23 #include <sys/ioctl.h>
27 #include <X11/extensions/shape.h>
31 #include "../wmgeneral/misc.h"
32 #include "../wmgeneral/wmgeneral.h"
33 #include "Pop3Client.h"
37 char wminet_mask_bits
[64*64];
38 int wminet_mask_width
= 64;
39 int wminet_mask_height
= 64;
43 char mailclient
[32] = "pine";
48 int mailCheckDelay
= 10; /* default */
49 int autoChecking
= YES
; /* default */
50 int newMessagesOnly
= YES
; /* default */
53 char config_file
[256] = "not-defined";
54 int scrollspeed
= 100;
57 int nb_conf
; /* number of configured pop servers */
58 int summess
; /* total number of messages */
65 t_scrollbar scrollbar
;
68 void printversion(void);
69 void wmCheckMail_routine(int, char **);
70 int readConfigFile( char *filename
);
72 void BlitString(char *name
, int x
, int y
, int fragment
);
73 void BlitNum(int num
, int x
, int y
, int todelete
);
75 int pop3DeleteMail(int num
, Pop3 pc
);
76 int pop3VerifStats(Pop3 pc
);
78 /********************************
80 ********************************/
81 void deleteoldtmpfiles()
88 if ((dir
= opendir(tempdir
))) {
90 while((dp
= readdir(dir
))) {
91 if (!strncmp(dp
->d_name
, TMPPREFIX
, TMPPREFIXLEN
)) {
92 sprintf(buf
, "%s/%s", tempdir
, dp
->d_name
);
94 printf(" delete old tmp file: %s\n", buf
);
104 int main(int argc
, char *argv
[]) {
109 if (strlen(ProgName
) >= 5)
110 ProgName
+= (strlen(ProgName
) - 5);
112 for (i
=1; i
<argc
; i
++) {
118 if (strcmp(arg
+1, "display")) {
124 if (strcmp(arg
+1, "geometry")) {
136 strcpy(config_file
, argv
[i
+1]);
147 wmCheckMail_routine(argc
, argv
);
152 void build_line(char *buf
, int num
, int index
, Pop3 pc
)
158 /* display spaces in case alias is less than 3 char long */
159 memset(tmp
, ' ', sizeof(char) * 3);
160 memset(tmp
+ 3, 0, sizeof(char) * (256 - 3));
161 memcpy(tmp
, pc
->alias
, strlen(pc
->alias
));
164 for (len
= 0; len
< MAIL_BUFLEN
&& pc
->mails
[num
].from
[len
]; len
++);
165 memcpy(tmp
+ pos
, pc
->mails
[num
].from
, len
);
166 tmp
[pos
+ len
] = '/';
168 for (len
= 0; len
< MAIL_BUFLEN
&& pc
->mails
[num
].subject
[len
]; len
++);
169 memcpy(tmp
+ pos
, pc
->mails
[num
].subject
, len
);
176 if (len
- pos
< (NB_DISP
+ EXTRA
)) { /* We are at the end of the string */
177 memcpy(buf
, tmp
+ pos
, len
- pos
);
178 memcpy(buf
+ len
- pos
, tmp
, (NB_DISP
+ EXTRA
) - len
+ pos
);
181 memcpy(buf
, tmp
+ pos
, NB_DISP
+ EXTRA
);
185 void display_index(int mail_index
, int line
, Pop3 pc
)
189 printf(" mail_index: %d, line: %d, todelete: %d\n",
190 mail_index
, line
, pc
->mails
[mail_index
].todelete
);
193 if (pc
->mails
[mail_index
].todelete
) {
194 copyXPMArea(67, 12, 2, 5, 7, (line
* 6) + TOP_MARGIN
);
197 copyXPMArea(69, 11, 2, 6, 7, (line
* 6) + TOP_MARGIN
- 1);
201 void ClearDisplay() {
204 copyXPMArea(72, 4, 3, 42, LEFT_MARGIN
, 4);
205 copyXPMArea(72, 4, 50, 42, 9, 4 );
206 for (i
= 0; i
< NB_LINE
; i
++) {
207 copyXPMArea(69, 11, 2, 6, 7, (i
* 6) + TOP_MARGIN
- 1);
211 /* return < 0 if error
213 else nb of mails which couldn't be deleted */
214 int DeleteMail(Pop3 pc
)
217 int old_sizeOfAllMessages
;
220 old_sizeOfAllMessages
= pc
->sizeOfAllMessages
;
221 BlitString(pc
->alias
, 10, TOP_MARGIN
, 0);
222 BlitString("connect", 10, 6*2 + TOP_MARGIN
, 0);
224 etat
= pop3MakeConnection(pc
, pc
->popserver
, pc
->serverport
);
226 BlitString("login", 10, (6*3) + TOP_MARGIN
, 0);
228 etat
= pop3Login(pc
, pc
->username
, pc
->password
);
231 BlitString("chk cont", 10, (6*4) + TOP_MARGIN
, 0);
233 etat
= pop3VerifStats(pc
);
236 if (etat
!= old_sizeOfAllMessages
) {
237 BlitString("mailbox", 10, TOP_MARGIN
, 0);
238 BlitString("content", 10, 6 + TOP_MARGIN
, 0);
239 BlitString("changed", 10, 6*2 + TOP_MARGIN
, 0);
240 BlitString("between", 10, 6*3 + TOP_MARGIN
, 0);
241 BlitString("updates", 10, 6*4 + TOP_MARGIN
, 0);
242 BlitString("del can.", 10, 6*6 + TOP_MARGIN
, 0);
245 for (i
= 0, etat
= 0; i
< pc
->numOfMessages
; i
++) {
246 etat
+= pc
->mails
[i
].todelete
;
251 for (i
= 0; i
< pc
->numOfMessages
; i
++) {
252 if (pc
->mails
[i
].todelete
) {
253 etat
+= pop3DeleteMail(i
+ 1, pc
);
263 void launch_mail_client(int iS)
271 if ((args = conf[iS]->mailclient)) {
272 BlitString("starting", 10, TOP_MARGIN, 0);
273 for (i = 0; i < 5 && args[i]; i++) {
274 for (j = 0; j < 8 && args[i][j]; j++);
275 memcpy(str, args[i], j);
277 BlitString(str, 10, (i + 2)*6 + TOP_MARGIN, 0);
280 if (execvp(args[0], args)) {
282 copyXPMArea(72, 4, 3, 42, LEFT_MARGIN, 4);
283 copyXPMArea(72, 4, 50, 6, 9, 4 );
284 copyXPMArea(69, 11, 2, 6, 7, TOP_MARGIN - 1);
285 BlitString("Error", 10, TOP_MARGIN, 0);
289 conf[iS]->nextCheckTime = time(0) + 30;
293 BlitString(" mail", 10, TOP_MARGIN, 0);
294 BlitString(" client", 10, 6 + TOP_MARGIN, 0);
295 BlitString("not set", 10, 6*2 + TOP_MARGIN, 0);
296 BlitString(" check", 15, 6*5 + TOP_MARGIN, 0);
297 BlitString("wmpop3rc", 10, 6*6 + TOP_MARGIN, 0);
304 void display_scrollbar(int index
, int totalmessages
,
305 int maxlines
, int scrollmode
)
311 if (totalmessages
<= maxlines
) {
314 printf(" full scrollbar\n");
316 copyXPMArea((scrollmode
) ? 68 : 65, 18, SCROLL_W
,
317 SCROLL_H
+ (2 * SCROLL_EXT
), SCROLL_LX
, SCROLL_TY
);
318 scrollbar
.top
= SCROLL_TY
;
319 scrollbar
.bottom
= SCROLL_TY
+ SCROLL_H
;
320 scrollbar
.allowedspace
= SCROLL_H
;
323 delta
= totalmessages
- maxlines
;
324 /* determine the size of the scrollbar */
325 if (0 >= (scrollen
= SCROLL_H
- ((SCROLL_H
/ maxlines
) * delta
)))
327 /* determine the position */
328 scrollbar
.allowedspace
= SCROLL_H
- scrollen
;
329 vertpos
= scrollbar
.allowedspace
* index
/ delta
;
330 copyXPMArea((scrollmode
) ? 68 : 65, 18, SCROLL_W
, SCROLL_EXT
,
331 SCROLL_LX
, vertpos
+ SCROLL_TY
);
332 copyXPMArea((scrollmode
) ? 68 : 65, 18 + SCROLL_EXT
, SCROLL_W
, scrollen
,
333 SCROLL_LX
, vertpos
+ SCROLL_TY
+ SCROLL_EXT
);
334 copyXPMArea((scrollmode
) ? 68 : 65, 18 + SCROLL_EXT
+ SCROLL_H
,
335 SCROLL_W
, SCROLL_EXT
,
336 SCROLL_LX
, vertpos
+ SCROLL_TY
+ SCROLL_EXT
+ scrollen
);
337 scrollbar
.top
= vertpos
+ SCROLL_TY
;
338 scrollbar
.bottom
= vertpos
+ SCROLL_TY
+ (SCROLL_EXT
* 2) + scrollen
;
342 printf(" index: %d, totalmess:%d, mxli: %d, delta: %d, vertpos: %d, allowedspace: %d, sl:%d\n",
343 index
, totalmessages
, maxlines
, delta
, vertpos
,
344 scrollbar
.allowedspace
, scrollen
);
348 /* RedrawWindow(); */
351 int is_for_each_mail(char **command
)
356 for (i
= 0; command
[i
]; i
++) {
357 if ('%' == command
[i
][0]) {
358 if (('f' == command
[i
][1]) ||
359 ('s' == command
[i
][1]) ||
360 ('m' == command
[i
][1]) ||
361 ('n' == command
[i
][1]))
369 char *quotify(char *str
)
375 if (NULL
!= (retour
= (char *) malloc(sizeof(char) * len
+ 3))) {
377 memcpy(retour
+ 1, str
, len
);
378 retour
[len
+ 1] = '\'';
379 retour
[len
+ 2] = '\0';
384 /* nb: number of the mail on the server - 1 (if -1: for all mails)
385 path: allocated buffer to store path of tmp file
386 newonly: only for new messages
387 onlyselected: only for selected messages
389 on success return 0 */
390 int writemailstofile(int nb
, char *path
, int newonly
,
391 int onlyselected
, Pop3 pc
)
397 int goforwritemail
= 0;
398 int mustdisconnect
= 0;
400 len
= strlen(tempdir
);
403 strcat(path
, tempdir
);
404 if ('/' != tempdir
[len
- 1])
406 strcat(path
, TMPPREFIX
);
407 strcat(path
, "XXXXXX");
409 printf(" creating temporary file [%s]\n", path
);
410 printf(" nb=%d, newonly=%d, onlyselected=%d\n",
411 nb
, newonly
, onlyselected
);
413 if (-1 == (fd
= mkstemp(path
))) {
414 fprintf(stderr
, "Error: writing mail to file\n");
419 /* to prevent connecting many times, do it now. */
420 if (NOT_CONNECTED
== pc
->connected
) {
422 printf(" writemailstofile not connected, connecting\n");
424 if (pop3MakeConnection(pc
,pc
->popserver
,pc
->serverport
) == -1){
427 if (pop3Login(pc
, pc
->username
, pc
->password
) == -1) {
434 /* concatenate all the mails into 1 file */
435 for (i
= 0; i
< pc
->numOfMessages
; i
++) {
438 printf(" mail %d:", i
);
440 if (!newonly
&& !onlyselected
) {
442 printf(" !newonly && !onlyselected\n");
447 if (pc
->mails
[i
].new &&
448 (!onlyselected
|| (onlyselected
&& pc
->mails
[i
].todelete
))) {
450 printf(" newonly\n");
455 else if (onlyselected
&& pc
->mails
[i
].todelete
) {
457 printf(" onlyselected\n");
461 if (goforwritemail
) {
462 /* put the mail separator */
463 if (strlen(pc
->mailseparator
)) {
465 printf(" pc->mailseparator: [%s]\n", pc
->mailseparator
);
467 write(fd
, pc
->mailseparator
, strlen(pc
->mailseparator
));
471 printf(" TXT_SEPARATOR: [%s]\n", TXT_SEPARATOR
);
473 write(fd
, TXT_SEPARATOR
, strlen(TXT_SEPARATOR
));
475 if (pop3WriteOneMail(i
+ 1, fd
, pc
)) {
483 if (pop3WriteOneMail(nb
+ 1, fd
, pc
))
487 /* close the connection if we've opened it */
488 if (mustdisconnect
) {
490 printf(" writemailstofile disconnecting\n");
497 fprintf(stderr
, "no tempdir configured, can't create file\n");
504 * do_command_completion
505 * returned array should be freed by calling function
506 * if nbnewmail == 0, for %c option concatenate _all_ the messages
508 char **do_command_completion(int num
, char **command
,
509 int nbnewmail
, Pop3 pc
)
516 for (i
= 0; command
[i
]; i
++);
518 printf(" %d args to the command, mail num %d\n", i
, num
);
520 if (NULL
== (retour
= (char **) malloc (sizeof(char *) * i
+ 1))) {
523 memset(retour
, 0, sizeof(char *) * i
+ 1);
524 for (i
= 0; command
[i
]; i
++) {
526 printf(" arg %d: [%s]\n", i
, command
[i
]);
528 if ('%' == command
[i
][0]) {
529 switch (command
[i
][1]) {
530 case 'T': /* total nb of mails */
531 if (NULL
!= (retour
[i
] = (char *) malloc(sizeof(char) * 8)))
532 sprintf(retour
[i
], "%d", pc
->numOfMessages
);
536 case 't': /* total nb of new mails */
537 if (NULL
!= (retour
[i
] = (char *) malloc(sizeof(char) * 8)))
538 sprintf(retour
[i
], "%d", (nbnewmail
< 0) ? 0 : 1);
542 case 'C': /* concatenate all the selected mails in 1 file */
543 if (writemailstofile(-1, path
, 0, SELECTONLY
, pc
))
546 if (NULL
== (retour
[i
] = strdup(path
))) {
550 case 'c': /* concatenate all the mails in 1 file */
551 if (writemailstofile(-1, path
, (nbnewmail
> 0), NOSELECTONLY
, pc
))
554 if (NULL
== (retour
[i
] = strdup(path
))) {
558 case 'f': /* from field */
560 printf(" from field: [%s]\n", pc
->mails
[num
].from
);
562 if (NULL
== (retour
[i
] = quotify(pc
->mails
[num
].from
)))
565 case 's': /* subject of the mail */
567 printf(" subject field: [%s]\n", pc
->mails
[num
].subject
);
569 if (NULL
== (retour
[i
] = quotify(pc
->mails
[num
].subject
)))
572 case 'm': /* copy the mail to tmp file */
574 if (writemailstofile(num
, path
, (nbnewmail
> 0), NOSELECTONLY
, pc
))
577 if (NULL
== (retour
[i
] = strdup(path
))) {
582 case 'n': /* number of the message on the mail server */
583 if (NULL
!= (retour
[i
] = (char *) malloc(sizeof(char) * 8)))
584 sprintf(retour
[i
], "%d", num
+ 1);
588 case 'S': /* server name */
589 if (NULL
== (retour
[i
] = strdup(pc
->popserver
)))
592 case 'a': /* server alias */
593 if (NULL
== (retour
[i
] = strdup(pc
->alias
)))
596 case 'u': /* user name */
597 if (NULL
== (retour
[i
] = strdup(pc
->username
)))
600 case 'w': /* user password */
601 if (NULL
== (retour
[i
] = strdup(pc
->password
)))
604 case 'P': /* server port */
605 if (NULL
!= (retour
[i
] = (char *) malloc(sizeof(char) * 8)))
606 sprintf(retour
[i
], "%d", pc
->serverport
);
610 case '%': /* % character, leave in place */
611 if (NULL
== (retour
[i
] = strdup(command
[i
])))
620 printf(" just copying arg [%s]\n", command
[i
]);
622 if (NULL
== (retour
[i
] = strdup(command
[i
])))
628 printf(" retour: %ld\n", (long) retour
);
636 /* num is the index of the mail in the mail array
637 if num == -1, means that the command isn't for each mail */
640 void spawn_command(int num
, char **command
, int nbnewmail
,
641 char *display
, Pop3 pc
)
650 BlitString(display
, 10, 6 + TOP_MARGIN
, 0);
651 BlitString("not set", 10, 6*2 + TOP_MARGIN
, 0);
652 BlitString(" check", 15, 6*5 + TOP_MARGIN
, 0);
653 BlitString("wmpop3rc", 10, 6*6 + TOP_MARGIN
, 0);
656 BlitString("starting", 10, TOP_MARGIN
, 0);
657 for (i
= 0; i
< 5 && command
[i
]; i
++) {
658 for (j
= 0; j
< 8 && command
[i
][j
]; j
++);
659 memcpy(str
, command
[i
], j
);
661 BlitString(str
, 10, (i
+ 2)*6 + TOP_MARGIN
, 0);
667 /* check for any '%' sign in the command and complete it */
668 tmpcommand
= do_command_completion(num
, command
, nbnewmail
, pc
);
670 /* launch the command in a new process */
673 printf(" spawning command: [");
674 for (i
= 0; tmpcommand
[i
]; i
++) {
675 printf(" %s ", tmpcommand
[i
]);
679 if (execvp(tmpcommand
[0], tmpcommand
)) {
685 /* set the check delay to 30 seconds */
686 pc
->nextCheckTime
= time(0) + 30;
688 /* free the memory (in the parent process...) */
689 for (i
= 0; tmpcommand
[i
]; i
++) {
690 free (tmpcommand
[i
]);
698 BlitString(" Error", 15, TOP_MARGIN
, 0);
699 BlitString(" While", 15, 6*2 + TOP_MARGIN
, 0);
700 BlitString("parsing", 15, 6*3 + TOP_MARGIN
, 0);
701 BlitString("command", 15, 6*4 +TOP_MARGIN
, 0);
702 BlitString(display
, 10, 6*6 + TOP_MARGIN
, 0);
703 fprintf(stderr
, "Error while parsing %s\n", display
);
706 fprintf(stderr
, "Error while parsing command\n");
716 * wmCheckMail_routine : This function is used to set up the X display
717 * for wmpop3 and check for mail every n number of minutes.
720 void wmCheckMail_routine(int argc
, char **argv
){
722 int buttonStatus
= -1;
743 if( !strcmp( config_file
, "not-defined") )
744 sprintf(config_file
, "%s/.wmpop3rc", getenv("HOME"));
746 if( readConfigFile(config_file
) == -1){
749 /* Set up timer for checking mail */
750 createXBMfromXPM(wminet_mask_bits
, wmpop3_xpm
751 , wminet_mask_width
, wminet_mask_height
);
753 openXwindow(argc
, argv
, wmpop3_xpm
, wminet_mask_bits
754 , wminet_mask_width
, wminet_mask_height
);
756 AddMouseRegion(0, 19, 49, 30, 58); /* check button */
757 AddMouseRegion(1, 46, 49, 50, 58 ); /* autocheck button */
758 AddMouseRegion(2, 53, 49, 57, 58 ); /* switch display button */
759 AddMouseRegion(3, 5, 49, 16, 58 ); /* delete button */
760 AddMouseRegion(4, 33, 49, 44, 53); /* top arrow */
761 AddMouseRegion(5, 33, 54, 44, 58); /* botton arrow */
762 /* add the mouse regions for each line */
763 for (i
= 0; i
< NB_LINE
; i
++) {
764 AddMouseRegion(6 + i
, 9, (i
*6) + TOP_MARGIN
,
765 58, (i
*6) + TOP_MARGIN
+ CHAR_HEIGHT
);
769 /* Check if Autochecking is on or off */
770 if(autoChecking
== NO
){
771 copyXPMArea(142, 38, 7, 11, 45, 48);
774 copyXPMArea(142, 49, 7, 11, 45, 48);
783 sleeplenght
= (long) 20000L + (20000L - (20000L * scrollspeed
/ 100));
786 for (iS
= 0; iS
< nb_conf
; iS
++) {
788 if( (((time(0) > pc
->nextCheckTime
) ||
789 (pc
->nextCheckTime
== 0)) && ( autoChecking
== YES
))
790 || (pc
->forcedCheck
== YES
)){
793 BlitString(pc
->alias
, 10, TOP_MARGIN
, 0);
794 BlitString("connect", 10, (6*2) + TOP_MARGIN
, 0);
797 if(pop3MakeConnection(pc
,pc
->popserver
,pc
->serverport
) == -1){
801 BlitString("login", 10, (6*3) + TOP_MARGIN
, 0);
803 if (pop3Login(pc
, pc
->username
, pc
->password
) == -1 )
807 BlitString("get mail", 10, (6*4) + TOP_MARGIN
, 0);
809 if (pop3CheckMail(pc
) == -1)
812 pc
->nextCheckTime
= time(0) + (pc
->mailCheckDelay
* SEC_IN_MIN
);
814 pc
->forcedCheck
= NO
;
815 /* check if new mail has arrived */
816 for (i
= 0, nbnewmail
= 0; i
< pc
->numOfMessages
; i
++)
817 if (pc
->mails
[i
].new)
819 /* launch the new mail command */
820 if (pc
->newmailcommand
&& (-1 != pc
->sizechanged
)) {
823 printf(" %d New mail(s) ha(s)(ve) arrived!\n", nbnewmail
);
825 if (is_for_each_mail(pc
->newmailcommand
)) {
826 for (i
= 0; i
< pc
->numOfMessages
; i
++)
827 if (pc
->mails
[i
].new)
828 spawn_command(i
, pc
->newmailcommand
, nbnewmail
, NULL
, pc
);
831 spawn_command(-1, pc
->newmailcommand
, nbnewmail
, NULL
, pc
);
835 /* close the connection */
840 waitpid(0, NULL
, WNOHANG
);
841 /* reset the number of messages */
843 for (summess
= 0, iS
= 0; iS
< nb_conf
; iS
++) {
847 summess
+= pc
->numOfMessages
;
850 /* set the offset from the beginning of the list */
851 if (summess
!= oldnbmess
) {
853 if (summess
< NB_LINE
)
856 index_vert
= summess
- NB_LINE
;
860 /* clear the display */
863 for (iS
= 0; iS
< nb_conf
; iS
++) {
865 for (i
= 0; i
< summess
&& i
< pc
->numOfMessages
; i
++) {
868 printf(" %s, mails[%d], todelete=%d\n",
869 pc
->alias
, i
, pc
->mails
[i
].todelete
);
872 nbsel
+= pc
->mails
[i
].todelete
;
876 /* make sure we display the correct buttons */
878 if ((NO
== newMessagesOnly
) && nbsel
)
879 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
881 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
883 if (newMessagesOnly
== YES
){
884 /* Show messages waiting */
886 for (color
= 0, iS
= 0; iS
< nb_conf
; iS
++) {
888 if (pc
->countunreadonly
)
894 sprintf(str
, "%-3s%cC*ER", pc
->alias
, separ
);
897 sprintf(str
, "%-3s%cL*ER", pc
->alias
, separ
);
900 sprintf(str
, "%-3s%cM*ER", pc
->alias
, separ
);
903 sprintf(str
, "%-3s%c %3d", pc
->alias
, separ
,
904 (pc
->countunreadonly
) ? pc
->numOfUnreadMessages
:
908 BlitString(str
, 10, (int) (6*iS
) + TOP_MARGIN
, 0);
912 sprintf(str
, "sel.: %2d", nbsel
);
913 BlitString(str
, 10, (int) (6*6) + TOP_MARGIN
, 0);
919 BlitString(" error", 10, TOP_MARGIN
, 0);
922 BlitString("No Mesg", 10, TOP_MARGIN
, 0);
924 if (autoChecking
== YES
) {
925 BlitString(" next", 10, 6*2 + TOP_MARGIN
, 0);
926 BlitString(" update", 10, 6*3 + TOP_MARGIN
, 0);
927 j
= SEC_IN_MIN
* 1000;
929 for (i
= 0, k
= 0; i
< nb_conf
; i
++) {
930 if ((conf
[i
]->nextCheckTime
- thistime
) < j
) {
931 j
= conf
[i
]->nextCheckTime
- thistime
;
935 sprintf(str
, " is:%s", conf
[k
]->alias
);
936 BlitString(str
, 10, 6*4 + TOP_MARGIN
, 0);
937 BlitString(" in", 10, 6*5 + TOP_MARGIN
, 0);
938 sprintf(str
, "%-5d s.", j
);
939 BlitString(str
, 10, 6*6 + TOP_MARGIN
, 0);
944 /* iS = index in the conf struct
945 i = index of the mail
946 j = line nb on display */
947 memset(linestodel
, 0, sizeof(char *));
948 for (iS
= 0, j
= 0; iS
< nb_conf
&& j
< NB_LINE
+ index_vert
; iS
++) {
950 for (i
= 0; (j
< NB_LINE
+ index_vert
) && i
< pc
->numOfMessages
;
952 if (j
>= index_vert
) {
953 build_line(str
, i
, index
, pc
);
954 BlitString(str
, 10, ((j
- index_vert
) * 6) + TOP_MARGIN
,
956 display_index(i
, (j
- index_vert
), pc
);
957 /* store the address of the delete flag, so that it will */
958 /* be easier to modify it afterwards */
959 linestodel
[j
- index_vert
] = &(pc
->mails
[i
].todelete
);
964 display_scrollbar(index_vert
, summess
, NB_LINE
, scrollmode
);
967 if (0 == (fragment
% (CHAR_WIDTH
+ 1))) {
970 /* printf("index=%d, fragment=%d\n", index, fragment); */
981 while (XPending(display
)){
982 XNextEvent(display
, &Event
);
983 switch (Event
.type
) {
988 XCloseDisplay(display
);
994 printf(" ca bouge... index_vert before = %d, %d x %d, allowedspace: %d, summess: %d\n",
996 Event
.xbutton
.x
, Event
.xbutton
.y
,
997 scrollbar
.allowedspace
,
1001 if (summess
> NB_LINE
) {
1002 index_vert
= scrollbar
.orig_index_vert
+
1003 ((Event
.xbutton
.y
- scrollbar
.orig_y
) * (summess
- NB_LINE
) /
1004 scrollbar
.allowedspace
);
1007 if (index_vert
+ NB_LINE
> summess
)
1008 index_vert
= summess
- NB_LINE
;
1011 printf(" deplacement de %d pixels --> index_vert = %d\n",
1012 Event
.xbutton
.y
- scrollbar
.orig_y
, index_vert
);
1017 buttonStatus
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
1018 if (buttonStatus
>= 0){
1019 switch (buttonStatus
){
1020 case 0 : /* check / open button pressed */
1021 if ((NO
== newMessagesOnly
) && nbsel
)
1022 copyXPMArea(128, 60 ,14 ,11 ,18 ,48 );
1024 copyXPMArea(128,38 ,14 ,11 ,18 ,48 );
1026 case 1 : /* autocheck button pressed */
1028 case 2: /* switch display button pressed */
1030 case 3: /* delete button pressed */
1031 copyXPMArea(127, 15, 14, 11, 4, 48);
1033 case 4: /* top arrow button pressed */
1035 case 5: /* bottom arrow button pressed */
1042 else if (SCROLL_LX
<= Event
.xbutton
.x
&& SCROLL_RX
>= Event
.xbutton
.x
1043 && scrollbar
.top
<= Event
.xbutton
.y
&&
1044 scrollbar
.bottom
>= Event
.xbutton
.y
) {
1045 scrollbar
.orig_y
= Event
.xbutton
.y
;
1046 scrollbar
.orig_index_vert
= index_vert
;
1051 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
1053 if (buttonStatus
== i
&& buttonStatus
>= 0){
1054 switch (buttonStatus
){
1055 case 0 : /* check button */
1056 if (nbsel
&& !newMessagesOnly
) {
1057 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
1058 /* this is where you launch the open mail command */
1059 for (iS
= 0; iS
< nb_conf
; iS
++) {
1061 for (i
= 0, selectedmess
= 0; i
< pc
->numOfMessages
; i
++) {
1062 if (pc
->mails
[i
].todelete
) {
1069 printf(" launching selectedmesgcommand command for conf %d\n",
1073 if (is_for_each_mail(pc
->selectedmesgcommand
)) {
1075 if (!pc
->numOfMessages
) {
1076 printf(" command is for each mail but there's no mail\n");
1079 printf(" command is for each mail\n");
1081 for (i
= 0; i
< pc
->numOfMessages
; i
++)
1082 spawn_command(i
, pc
->selectedmesgcommand
, 0,
1086 spawn_command(-1, pc
->selectedmesgcommand
, 0,
1093 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
1094 for (iS
= 0; iS
< nb_conf
; iS
++)
1095 conf
[iS
]->forcedCheck
= YES
;
1098 case 1 : /* autocheck Button */
1099 if (autoChecking
== YES
){
1101 copyXPMArea(142, 38, 7, 11, 45, 48);
1105 for (iS
= 0; iS
< nb_conf
; iS
++)
1106 conf
[iS
]->nextCheckTime
= time(0) +
1107 (conf
[iS
]->mailCheckDelay
* SEC_IN_MIN
);
1108 copyXPMArea(142, 49, 7, 11, 45, 48);
1111 case 2: /* switch display Button */
1113 /* change view on # of messages */
1114 if( newMessagesOnly
== YES
) {
1115 newMessagesOnly
= NO
;
1116 copyXPMArea(149,38 , 7 , 11, 52, 48);
1118 copyXPMArea(128,49,14,11,18,48);
1121 copyXPMArea(128,27,14,11,18,48);
1125 newMessagesOnly
= YES
;
1126 copyXPMArea(149,49 , 7 , 11, 52, 48);
1127 copyXPMArea(128,27,14,11,18,48);
1133 case 3: /* delete button */
1134 copyXPMArea(143, 15, 14, 11, 4, 48);
1137 for (iS
= 0; iS
< nb_conf
; iS
++) {
1139 for (i
= 0, k
= 0; i
< pc
->numOfMessages
; i
++)
1140 k
+= pc
->mails
[i
].todelete
;
1142 /* clear the display */
1146 sprintf(pc
->delstatus
, "%-3s: Err", pc
->alias
);
1149 sprintf(pc
->delstatus
, "%-3s/D:%2d", pc
->alias
, k
);
1152 sprintf(pc
->delstatus
, "%-3s: ok", pc
->alias
);
1153 pc
->forcedCheck
= YES
;
1156 sprintf(pc
->delstatus
, "%-3s:none", pc
->alias
);
1159 /* clear the display */
1162 for (iS
= 0; iS
< nb_conf
; iS
++) {
1163 BlitString(conf
[iS
]->delstatus
, 10, 6*iS
+ TOP_MARGIN
, 0);
1167 sleep(displaydelay
);
1169 case 4: /* top arrow button pressed */
1177 case 5: /* bottom arrow button pressed */
1178 if (summess
> NB_LINE
) {
1180 if (index_vert
+ NB_LINE
> summess
)
1181 index_vert
= summess
- NB_LINE
;
1188 if (newMessagesOnly
== NO
) { /* message view mode */
1189 if ((5 < buttonStatus
) && (buttonStatus
<= 5 + NB_LINE
)) {
1190 if ((buttonStatus
- 6 + index_vert
) < summess
) {
1191 /* first update lines to del */
1192 *(linestodel
[buttonStatus
- 6]) =
1193 1 - *(linestodel
[buttonStatus
- 6]);
1195 printf(" button %d pressed, j'update lines to del\n",
1200 for (iS
= 0; iS
< nb_conf
; iS
++) {
1202 for (i
= 0; i
< pc
->numOfMessages
; i
++) {
1203 nbsel
+= pc
->mails
[i
].todelete
;
1205 printf(" conf %d, mail %d, todelete = %d\n",
1206 iS
, i
, pc
->mails
[i
].todelete
);
1210 /* display open or reload buttons */
1212 copyXPMArea(128,49,14,11,18,48);
1215 copyXPMArea(128,27,14,11,18,48);
1220 else { /* summary view mode */
1221 if ((5 < buttonStatus
) && (buttonStatus
<= 5 + nb_conf
)) {
1222 if ((Event
.xbutton
.x
> 10) &&
1223 (Event
.xbutton
.x
< (10 + (4 * (CHAR_WIDTH
+ 1))))) {
1225 printf(" launching command for conf %d\n",
1228 pc
= conf
[buttonStatus
- 6];
1229 if (is_for_each_mail(pc
->mailclient
)) {
1231 if (!pc
->numOfMessages
) {
1232 printf(" command is for each mail but there's no mail\n");
1235 for (i
= 0; i
< pc
->numOfMessages
; i
++)
1236 spawn_command(i
, pc
->mailclient
, nbnewmail
,
1240 spawn_command(-1, pc
->mailclient
, nbnewmail
,
1244 else if ((Event
.xbutton
.x
> (10 + (4 * (CHAR_WIDTH
+ 1)))) &&
1245 (Event
.xbutton
.x
< (10 + (8 * (CHAR_WIDTH
+ 1))))) {
1246 /* swap view mode */
1247 conf
[buttonStatus
- 6]->countunreadonly
=
1248 1 - conf
[buttonStatus
- 6]->countunreadonly
;
1250 printf(" swapping view mode for conf %d: %s\n",
1252 (conf
[buttonStatus
- 6]->countunreadonly
) ?
1253 "UnreadMessages" : "TotalMessages");
1258 else if ((5 + NB_LINE
) == buttonStatus
) {
1259 /* status summary line pressed */
1260 if ((Event
.xbutton
.x
> 10) &&
1261 (Event
.xbutton
.x
< (10 + (4 * (CHAR_WIDTH
+ 1))))) {
1262 /* select all messages */
1263 for (iS
= 0; iS
< nb_conf
; iS
++) {
1264 for (pc
= conf
[iS
], i
= 0; i
< pc
->numOfMessages
; i
++) {
1265 pc
->mails
[i
].todelete
= 1;
1269 else if ((Event
.xbutton
.x
> (10 + (4 * (CHAR_WIDTH
+ 1)))) &&
1270 (Event
.xbutton
.x
< (10 + (8 * (CHAR_WIDTH
+ 1))))) {
1271 /* unselect all messages */
1272 for (iS
= 0; iS
< nb_conf
; iS
++) {
1273 for (pc
= conf
[iS
], i
= 0; i
< pc
->numOfMessages
; i
++) {
1274 pc
->mails
[i
].todelete
= 0;
1284 if (buttonStatus
>= 0) {
1285 /* button has been pressed correctly but released somewhere else */
1286 switch(buttonStatus
) {
1287 case 0: /* check button was pressed */
1288 if ((NO
== newMessagesOnly
) && nbsel
)
1289 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
1291 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
1293 case 3: /* delete button was pressed */
1294 copyXPMArea(143, 15, 14, 11, 4, 48);
1305 usleep(sleeplenght
);
1311 * usage : Prints proper command parameters of wmpop3.
1315 fprintf(stdout
, "\nWMPop3LB - Louis-Benoit JOURDAIN (wmpop3lb@jourdain.org)\n");
1316 fprintf(stdout
, "based on the work by Scott Holden <scotth@thezone.net>\n\n");
1317 fprintf(stdout
, "usage:\n");
1318 fprintf(stdout
, " -display <display name>\n");
1319 fprintf(stdout
, " -geometry +XPOS+YPOS initial window position\n");
1320 fprintf(stdout
, " -c <filename> use specified config file\n");
1321 fprintf(stdout
, " -h this help screen\n");
1322 fprintf(stdout
, " -v print the version number\n");
1323 fprintf(stdout
, "\n");
1326 void printversion(void)
1328 fprintf(stdout
, "wmpop3 v%s\n", WMPOP3_VERSION
);
1331 // Blits a string at given co-ordinates
1332 void BlitString(char *name
, int x
, int y
, int fragment
)
1339 /* printf("--name: [%s] \n", name); */
1340 for (i
= 0, k
= x
; name
[i
]; i
++) {
1341 c
= toupper(name
[i
]);
1342 if (c
>= 'A' && c
<= 'Z') { /* its a letter */
1346 else if (c
>= '0' && c
<= '9') { /* its a number */
1388 /* printf("c:%2d (%c), fragment: %d, i:%d, k=%d ",
1389 c, name[i], fragment, i, k); */
1390 if (i
> 0 && i
< NB_DISP
) {
1391 copyXPMArea(c
* CHAR_WIDTH
, CH_COLOR(row
), CHAR_WIDTH
+ 1, CHAR_HEIGHT
,
1393 /* printf(" - k1: %d += %d + 1", k, CHAR_WIDTH); */
1394 k
+= CHAR_WIDTH
+ 1;
1397 copyXPMArea(c
* CHAR_WIDTH
+ fragment
, CH_COLOR(row
),
1398 CHAR_WIDTH
+ 1 - fragment
, CHAR_HEIGHT
,
1400 /* printf(" - k2: %d += %d + 1 - %d", k, CHAR_WIDTH, fragment); */
1401 k
+= CHAR_WIDTH
+ 1 - fragment
;
1403 else if (fragment
&& (NB_DISP
== i
)) {
1404 copyXPMArea(c
* CHAR_WIDTH
, CH_COLOR(row
), fragment
+ 1, CHAR_HEIGHT
,
1406 /* printf(" - k3: %d += %d ", k, fragment); */
1409 /* printf(" -- apres k=%d\n", k); */
1414 /* Blits number to given coordinates...*/
1416 void BlitNum(int num
, int x
, int y
, int todelete
)
1420 copyXPMArea(((num
- 1) * (SN_CHAR_W
+ 1)) + 1, CH_COLOR(SMALL_NUM
),
1421 SN_CHAR_W
, CHAR_HEIGHT
+ 1, x
, y
);
1424 int parsestring(char *buf
, char *data
, int max
, FILE *fp
)
1432 /* trim the leading spaces */
1433 memset(data
, 0, max
);
1434 for (deb
= buf
; *deb
&& isspace(*deb
); deb
++);
1442 printf(" line to parse: [%s]\n", deb
);
1444 /* get to the end of the line */
1445 for (end
= deb
; *end
&& ('"' != *end
); end
++);
1446 if (!*end
) { /* this is a multiline entry */
1447 linelen
+= (int) (end
- deb
);
1448 if (linelen
> max
) {
1450 printf(" maximum line length reached\n");
1454 memcpy(bal
, deb
, (int) (end
- deb
));
1455 bal
= data
+ linelen
;
1456 if (fgets(buf
, CONF_BUFLEN
, fp
)) {
1459 else { /* end of file reached */
1464 memcpy(bal
, deb
, end
- deb
);
1470 for (end
= deb
; *end
&& !isspace(*end
); end
++);
1471 memcpy(data
, deb
, ((end
- deb
) > max
) ? max
: end
- deb
);
1474 printf(" parsed string (len=%d) : [%s]\n", strlen(data
), data
);
1479 int parsenum(char *buf
, int *data
)
1485 memset(temp
, 0, 32);
1486 for (deb
= buf
; *deb
&& isspace(*deb
); deb
++);
1490 for (end
= ++deb
; *end
&& ('"' != *end
); end
++);
1493 memcpy(temp
, deb
, end
- deb
);
1497 for (end
= deb
; *end
&& !isspace(*end
); end
++);
1498 memcpy(temp
, deb
, end
- deb
);
1504 char **build_arg_list(char *buf
, int len
)
1510 /* count number of args */
1511 for (espaces
= 0, i
= 0; buf
[i
] && i
< len
; i
++)
1512 if (isspace(buf
[i
]))
1514 /* allocate space for the structure */
1515 if (NULL
== (retour
= (char **) malloc(sizeof(char *) * espaces
+ 2)))
1517 /* get each arg one by one */
1518 for (i
= 0, j
= 0; j
< len
&& i
< 256; i
++) {
1519 /* get the end of the arg */
1520 for (espaces
= j
; espaces
< len
&& !isspace(buf
[espaces
]); espaces
++);
1521 /* allocate space for the arg */
1522 if (0 == (retour
[i
] = malloc(sizeof(char) * (espaces
- j
) + 1))) {
1523 /* free what has been allocated */
1524 for (j
= 0; j
< i
; j
++)
1528 memcpy(retour
[i
], buf
+ j
, espaces
- j
);
1529 retour
[i
][espaces
- j
] = '\0';
1537 int readConfigFile( char *filename
){
1538 char buf
[CONF_BUFLEN
];
1539 char tmp
[CONF_BUFLEN
];
1543 if( (fp
= fopen( filename
, "r")) == 0 ){
1544 sprintf(config_file
, "%s/.wmpop3rc", getenv("HOME"));
1545 fprintf(stderr
, "-Config file does not exit : %s\n",config_file
);
1546 fprintf(stderr
, "+Trying to create new config file.\n");
1547 if((fp
= fopen(config_file
,"w")) == 0){
1548 fprintf(stderr
, "-Error creating new config file\n");
1551 fprintf(fp
, "#####################################################\n");
1552 fprintf(fp
, "# wmpop3lb configuration file #\n");
1553 fprintf(fp
, "# #\n");
1554 fprintf(fp
, "# for more information about wmpop3lb, please see: #\n");
1555 fprintf(fp
, "# http://wmpop3lb.jourdain.org #\n");
1556 fprintf(fp
, "# or send a mail to #\n");
1557 fprintf(fp
, "# wmpop3lb@jourdain.org #\n");
1558 fprintf(fp
, "#####################################################\n");
1559 fprintf(fp
, "autochecking 0 # 1 enables, 0 disables\n");
1560 fprintf(fp
, "displaydelay 2 # nb of seconds error info is displayed\n");
1561 fprintf(fp
, "scrollspeed 100 # percentage of original scrool speed\n");
1562 fprintf(fp
, "tempdir /tmp # directory for tmp files\n");
1563 fprintf(fp
, "viewallmessages 0 # 0 Shows the from and subject\n");
1564 fprintf(fp
, "# 1 Shows the number of messages\n");
1565 fprintf(fp
, "#\n# Replace all values with appropriate data\n#\n");
1566 fprintf(fp
, "[Server] # server section\n");
1567 fprintf(fp
, "alias \"3 alphanum. char. long alias\"\n");
1568 fprintf(fp
, "popserver \" pop3 server name \"\n");
1569 fprintf(fp
, "port 110 # default port\n");
1570 fprintf(fp
, "username \" pop3 login name \"\n");
1571 fprintf(fp
, "password \" pop3 password \"\n");
1572 fprintf(fp
, "mailcheckdelay 10 # default mail check time in minutes\n");
1573 fprintf(fp
, "countUnreadOnly 0 # count unread messages only\n");
1574 fprintf(fp
, "mailclient \"netscape -mail\" # for example...\n");
1575 fprintf(fp
, "newmailcommand \" specify new mail command \"\n");
1576 fprintf(fp
, "selectedmesgcommand \"specify command for selected mess\"\n");
1577 fprintf(fp
, "mailseparator \" separator when concatening messages\"\n");
1578 fprintf(fp
, "maxdlsize -1 # (no limit)\n");
1579 fprintf(fp
, "#\n# start new [server] section below (up to a total of 6)\n");
1580 fprintf(stderr
, "+New config file created : ~/.wmpop3rc\n\n");
1581 fprintf(stderr
, "+ ~/.wmpop3rc must be configured before running wmpop3.\n");
1589 while ((nb_conf
< 7) && fgets(buf
, CONF_BUFLEN
, fp
) != 0) {
1590 if (buf
[0] != '#') {
1591 if (!nb_conf
&& !strncasecmp( buf
, "autochecking", 12) ){
1592 if (parsenum(buf
+ 12, &autoChecking
))
1593 fprintf(stderr
, "syntax error for parameter autochecking\n");
1595 else if (!nb_conf
&& !strncasecmp( buf
, "scrollspeed", 11) ){
1596 if (parsenum(buf
+ 11, &scrollspeed
))
1597 fprintf(stderr
, "syntax error for parameter scrollspeed\n");
1599 else if (!nb_conf
&& !strncasecmp( buf
, "displaydelay", 12) ){
1600 if (parsenum(buf
+ 12, &displaydelay
))
1601 fprintf(stderr
, "syntax error for parameter displaydelay\n");
1603 else if (!nb_conf
&& !strncasecmp(buf
, "tempdir", 7)) {
1604 if (parsestring(buf
+ 7, tempdir
, 1024, fp
))
1605 fprintf(stderr
, "syntax error for parameter tempdir\n");
1607 else if (!strncasecmp(buf
, "[server]", 8)) {
1609 if (!(conf
[nb_conf
- 1] = pop3Create(nb_conf
))) {
1610 fprintf(stderr
, "Can't allocate memory for config structure\n");
1615 else if (nb_conf
&& !strncasecmp(buf
, "username", 8) ) {
1616 if (parsestring(buf
+ 8, conf
[nb_conf
-1]->username
, 256, fp
))
1617 fprintf(stderr
, "section %d: invalid syntax for username\n",
1620 else if (nb_conf
&& !strncasecmp( buf
, "password", 8) ){
1621 if (parsestring(buf
+ 8, conf
[nb_conf
- 1]->password
, 256, fp
))
1622 fprintf(stderr
, "section %d: invalid syntax for password\n",
1625 else if (nb_conf
&& !strncasecmp(buf
, "alias", 5) ) {
1626 if (parsestring(buf
+ 5, conf
[nb_conf
-1]->alias
, 3, fp
))
1627 fprintf(stderr
, "section %d: invalid syntax for alias\n", nb_conf
);
1629 else if (nb_conf
&& !strncasecmp( buf
, "popserver", 9) ){
1630 if (parsestring(buf
+ 9, conf
[nb_conf
- 1]->popserver
, 128, fp
))
1631 fprintf(stderr
, "section %d: invalid syntax for popserver\n",
1634 else if (nb_conf
&& !strncasecmp( buf
, "port", 4) ){
1635 if (parsenum(buf
+ 4, &(conf
[nb_conf
- 1]->serverport
)))
1636 fprintf(stderr
, "section %d: Invalid popserver port number.\n",
1639 else if (!nb_conf
&& !strncasecmp( buf
, "viewallmessages", 15) ){
1640 if (parsenum(buf
+ 15, &newMessagesOnly
))
1641 fprintf(stderr
, "section %d: Invalid number ( viewallmessages )\n",
1644 else if (nb_conf
&& !strncasecmp(buf
, "countunreadonly", 15)) {
1645 if (parsenum(buf
+ 15, &(conf
[nb_conf
- 1]->countunreadonly
)))
1646 fprintf(stderr
, "section %d: Invalid number ( countunreadonly )\n",
1649 else if (nb_conf
&& !strncasecmp( buf
, "mailcheckdelay", 14) ){
1650 if (parsenum(buf
+ 14, &(conf
[nb_conf
-1]->mailCheckDelay
)))
1651 fprintf(stderr
, "section %d: Invalid delay time.\n", nb_conf
);
1653 else if (nb_conf
&& !strncasecmp(buf
, "mailclient", 10)) {
1654 if (parsestring(buf
+ 10, tmp
, 256, fp
))
1655 fprintf(stderr
, "section %d: Invalid syntax for mailclient.\n",
1658 conf
[nb_conf
- 1]->mailclient
= build_arg_list(tmp
, strlen(tmp
));
1660 else if (nb_conf
&& !strncasecmp(buf
, "newmailcommand", 14)) {
1661 if (parsestring(buf
+ 14, tmp
, 256, fp
))
1662 fprintf(stderr
,"section %d: Invalid syntax for newmailcommand.\n",
1665 conf
[nb_conf
- 1]->newmailcommand
=
1666 build_arg_list(tmp
, strlen(tmp
));
1668 else if (nb_conf
&& !strncasecmp(buf
, "selectedmesgcommand", 19)) {
1669 if (parsestring(buf
+ 19, tmp
, 256, fp
))
1671 "section %d: Invalid syntax for selectedmesgcommand.\n",
1674 conf
[nb_conf
- 1]->selectedmesgcommand
=
1675 build_arg_list(tmp
, strlen(tmp
));
1677 else if (nb_conf
&& !strncasecmp(buf
, "mailseparator", 13)) {
1678 if (parsestring(buf
+ 13, conf
[nb_conf
- 1]->mailseparator
, 256, fp
))
1679 fprintf(stderr
, "section %d: Invalid syntax for mailseparator\n",
1682 else if (nb_conf
&& !strncasecmp( buf
, "maxdlsize", 9) ){
1683 if (parsenum(buf
+ 9, &(conf
[nb_conf
-1]->maxdlsize
)))
1684 fprintf(stderr
, "section %d: Invalid maxdlsize.\n", nb_conf
);
1687 if (*buf
&& (isalpha(*buf
) || isalnum(*buf
)))
1688 fprintf(stderr
, "section %d: Unknown indentifier : [%s]\n",
1692 for (bal
= buf
; *bal
&& !isalnum(*bal
); bal
++);
1694 fprintf(stderr
, "identifier outside Server section: [%s]\n", buf
);