Add support for tab-completion when selecting by rule
[alpine.git] / alpine / newmail.c
blobbd11a814a2e7c9a58d6284ef619454779a002b3d
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2009 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "../pith/headers.h"
16 #include "../pith/newmail.h"
17 #include "../pith/conf.h"
18 #include "../pith/flag.h"
19 #include "../pith/mailindx.h"
20 #include "../pith/msgno.h"
21 #include "../pith/bldaddr.h"
22 #include "../pith/stream.h"
23 #include "../pith/sort.h"
24 #include "../pith/status.h"
25 #include "../pith/util.h"
26 #include "../pith/thread.h"
27 #include "../pith/options.h"
28 #include "../pith/folder.h"
29 #include "../pith/ablookup.h"
31 #ifdef _WINDOWS
32 #include "../pico/osdep/mswin.h"
33 #endif
37 * Internal prototypes
39 void new_mail_win_mess(MAILSTREAM *, long);
40 void new_mail_mess(MAILSTREAM *, long, long, int);
41 void newmailfifo(int, char *, char *, char *);
44 /*----------------------------------------------------------------------
45 pith optional function to queue a newmail announcement
48 ----*/
49 void
50 newmail_status_message(MAILSTREAM *stream, long n, long t_nm_count)
52 #ifdef _WINDOWS
53 if(mswin_newmailwinon())
54 new_mail_win_mess(stream, t_nm_count);
55 #elif !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
56 if(ps_global->VAR_FIFOPATH)
57 new_mail_win_mess(stream, t_nm_count);
58 #endif
59 if(n){
60 new_mail_mess(stream, sp_mail_since_cmd(stream), n, 0);
66 * alert for each new message individually. new_mail_mess lumps
67 * messages together, we call new_mail_mess with 1 message at a time.
68 * This is currently for PC-Pine new mail window, but could probably
69 * be used more generally.
70 * stream - new mail stream
71 * number - number of new messages to alert for
73 void
74 new_mail_win_mess(MAILSTREAM *stream, long int number)
76 int n, i;
77 MESSAGECACHE *mc;
79 if(!stream)
80 return;
82 /*
83 * spare6, or MN_STMP, should be safe to use for now, we
84 * just want to set which messages to alert about before
85 * going to c-client.
87 for(n = stream->nmsgs, i = 0; n > 1L && i < number; n--){
88 if(!get_lflag(stream, NULL, n, MN_EXLD)){
89 mc = mail_elt(stream, n);
90 if(mc)
91 mc->spare6 = 1;
93 if(++i == number)
94 break;
96 else{
97 mc = mail_elt(stream, n);
98 if(mc)
99 mc->spare6 = 0;
103 * Here n is the first new message we want to notify about.
104 * spare6 will tell us which ones to use. We set spare6
105 * in case of new mail or expunge that could happen when
106 * we mail_fetchstructure in new_mail_mess.
108 for(; n <= stream->nmsgs; n++)
109 if(n > 0L && (mc = mail_elt(stream, n)) && mc->spare6){
110 mc->spare6 = 0;
111 new_mail_mess(stream, 1, n, 1);
116 /*----------------------------------------------------------------------
117 Format and queue a "new mail" message
119 Args: stream -- mailstream on which a mail has arrived
120 number -- number of new messages since last command
121 max_num -- The number of messages now on stream
122 for_new_mail_win -- for separate new mail window (curr. PC-Pine)
124 Not too much worry here about the length of the message because the
125 status_message code will fit what it can on the screen and truncation on
126 the right is about what we want which is what will happen.
127 ----*/
128 void
129 new_mail_mess(MAILSTREAM *stream, long int number, long int max_num, int for_new_mail_win)
131 char subject[MAILTMPLEN+1], subjtext[MAILTMPLEN+1], from[MAILTMPLEN+1],
132 *folder = NULL, intro[MAILTMPLEN+1];
133 ENVELOPE *e = NULL;
135 if(stream)
136 e = pine_mail_fetchstructure(stream, max_num, NULL);
138 if(stream){
139 if(sp_flagged(stream, SP_INBOX))
140 folder = NULL;
141 else{
142 folder = STREAMNAME(stream);
143 if(folder[0] == '?' && folder[1] == '\0')
144 folder = NULL;
148 format_new_mail_msg(folder, number, e, intro, from, subject, subjtext, sizeof(subject));
150 if(!for_new_mail_win)
151 q_status_message5(SM_ASYNC | SM_DING, 0, 60,
152 "%s%s%s%.80s%.80s", intro,
153 from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
154 from && from[0] ? "rom " : "",
155 from && from[0] ? from : "",
156 subjtext);
157 #if (!defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)) || defined(_WINDOWS)
158 else {
159 int is_us = 0;
160 ADDRESS *tadr;
162 if(e)
163 for(tadr = e->to; tadr; tadr = tadr->next)
164 if(address_is_us(tadr, ps_global)){
165 is_us = 1;
166 break;
168 #ifdef _WINDOWS
169 mswin_newmailwin(is_us, from, subject, folder);
170 #else
171 newmailfifo(is_us, from, subject, folder);
172 #endif
174 #endif
176 if(pith_opt_icon_text){
177 if(F_ON(F_ENABLE_XTERM_NEWMAIL, ps_global)
178 && F_ON(F_ENABLE_NEWMAIL_SHORT_TEXT, ps_global)){
179 long inbox_nm;
180 if(!sp_flagged(stream, SP_INBOX)
181 && (inbox_nm = sp_mail_since_cmd(sp_inbox_stream()))){
182 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "[%ld, %ld] %s",
183 inbox_nm > 1L ? inbox_nm : 1L,
184 number > 1L ? number: 1L,
185 ps_global->pine_name);
187 else
188 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "[%ld] %s", number > 1L ? number: 1L,
189 ps_global->pine_name);
191 else
192 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s%.80s", intro,
193 from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
194 from && from[0] ? "rom " : "",
195 from && from[0] ? from : "");
197 (*pith_opt_icon_text)(tmp_20k_buf, IT_NEWMAIL);
202 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
203 static char *fifoname = NULL;
204 static int fifoopenerrmsg = 0;
205 static int fifofd = -1;
206 static int fifoheader = 0;
208 void
209 init_newmailfifo(char *fname)
211 if(fifoname)
212 close_newmailfifo();
214 if(!(fname && *fname))
215 return;
217 if(!fifoname){
218 if(mkfifo(fname, 0600) == -1){
219 q_status_message2(SM_ORDER,3,3,
220 "Can't create NewMail FIFO \"%s\": %s",
221 fname, error_description(errno));
222 return;
224 else
225 q_status_message1(SM_ORDER,0,3, "NewMail FIFO: \"%s\"", fname);
227 fifoname = cpystr(fname);
232 void
233 close_newmailfifo(void)
235 if(fifoname){
236 if(fifofd >= 0)
237 (void) close(fifofd);
239 if(*fifoname)
240 our_unlink(fifoname);
242 fs_give((void **) &fifoname);
245 fifoheader = 0;
246 fifoname = NULL;
247 fifofd = -1;
248 fifoopenerrmsg = 0;
252 void
253 newmailfifo(int is_us, char *from, char *subject, char *folder)
255 char buf[MAX_SCREEN_COLS+1], buf2[MAX_SCREEN_COLS+1];
256 char buf3[MAX_SCREEN_COLS+1], buf4[MAX_SCREEN_COLS+1];
258 if(!(fifoname && *fifoname)){
259 if(fifoname)
260 close_newmailfifo();
262 return;
265 if(fifofd < 0){
266 fifofd = our_open(fifoname, O_WRONLY | O_NONBLOCK | O_BINARY, 0600);
267 if(fifofd < 0){
268 if(!fifoopenerrmsg){
269 if(errno == ENXIO)
270 q_status_message2(SM_ORDER,0,3, "Nothing reading \"%s\": %s",
271 fifoname, error_description(errno));
272 else
273 q_status_message2(SM_ORDER,0,3, "Can't open \"%s\": %s",
274 fifoname, error_description(errno));
276 fifoopenerrmsg++;
279 return;
283 if(fifofd >= 0){
284 int width;
285 int fromlen, subjlen, foldlen;
287 width = MIN(MAX(20, ps_global->nmw_width), MAX_SCREEN_COLS);
289 foldlen = .18 * width;
290 foldlen = MAX(5, foldlen);
291 fromlen = .28 * width;
292 subjlen = width - 2 - foldlen - fromlen;
294 if(!fifoheader){
295 time_t now;
296 char *tmtxt;
298 now = time((time_t *) 0);
299 tmtxt = ctime(&now);
300 if(!tmtxt)
301 tmtxt = "";
303 snprintf(buf, sizeof(buf), "New Mail window started at %.*s\n",
304 (int) MIN(100, strlen(tmtxt)-1), tmtxt);
305 (void) write(fifofd, buf, strlen(buf));
307 snprintf(buf, sizeof(buf), " %-*s%-*s%-*s\n",
308 fromlen, "From:",
309 subjlen, "Subject:",
310 foldlen, "Folder:");
311 (void) write(fifofd, buf, strlen(buf));
313 snprintf(buf, sizeof(buf), "%-*.*s\n", width, width, repeat_char(width, '-'));
314 (void) write(fifofd, buf, strlen(buf));
316 fifoheader++;
319 snprintf(buf, sizeof(buf), "%s %-*.*s %-*.*s %-*.*s\n", is_us ? "+" : " ",
320 fromlen - 1, fromlen - 1,
321 short_str(from ? from : "", buf2, sizeof(buf2), fromlen-1, EndDots),
322 subjlen - 1, subjlen - 1,
323 short_str(subject ? subject : "(no subject)",
324 buf3, sizeof(buf3), subjlen-1, EndDots),
325 foldlen, foldlen,
326 short_str(folder ? folder : "INBOX", buf4, sizeof(buf4), foldlen, FrontDots));
327 (void) write(fifofd, buf, strlen(buf));
330 #endif