mutt stable branch with some hacks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at jcs 812 lines 21 kB view raw
1/* 2 * Copyright (C) 1996-2000,2002,2007 Michael R. Elkins <me@mutt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#include "mutt_curses.h" 25#include "sort.h" 26#include "charset.h" 27#include "mutt_crypt.h" 28#include "mutt_idna.h" 29 30#include <ctype.h> 31#include <stdlib.h> 32#include <string.h> 33#include <locale.h> 34 35#ifdef HAVE_ALLOCA_H 36#include <alloca.h> 37#endif 38 39int mutt_is_mail_list (ADDRESS *addr) 40{ 41 if (!mutt_match_rx_list (addr->mailbox, UnMailLists)) 42 return mutt_match_rx_list (addr->mailbox, MailLists); 43 return 0; 44} 45 46int mutt_is_subscribed_list (ADDRESS *addr) 47{ 48 if (!mutt_match_rx_list (addr->mailbox, UnMailLists) 49 && !mutt_match_rx_list (addr->mailbox, UnSubscribedLists)) 50 return mutt_match_rx_list (addr->mailbox, SubscribedLists); 51 return 0; 52} 53 54/* Search for a mailing list in the list of addresses pointed to by adr. 55 * If one is found, print pfx and the name of the list into buf, then 56 * return 1. Otherwise, simply return 0. 57 */ 58static int 59check_for_mailing_list (ADDRESS *adr, char *pfx, char *buf, int buflen) 60{ 61 for (; adr; adr = adr->next) 62 { 63 if (mutt_is_subscribed_list (adr)) 64 { 65 if (pfx && buf && buflen) 66 snprintf (buf, buflen, "%s%s", pfx, mutt_get_name (adr)); 67 return 1; 68 } 69 } 70 return 0; 71} 72 73/* Search for a mailing list in the list of addresses pointed to by adr. 74 * If one is found, print the address of the list into buf, then return 1. 75 * Otherwise, simply return 0. 76 */ 77static int 78check_for_mailing_list_addr (ADDRESS *adr, char *buf, int buflen) 79{ 80 for (; adr; adr = adr->next) 81 { 82 if (mutt_is_subscribed_list (adr)) 83 { 84 if (buf && buflen) 85 snprintf (buf, buflen, "%s", adr->mailbox); 86 return 1; 87 } 88 } 89 return 0; 90} 91 92 93static int first_mailing_list (char *buf, size_t buflen, ADDRESS *a) 94{ 95 for (; a; a = a->next) 96 { 97 if (mutt_is_subscribed_list (a)) 98 { 99 mutt_save_path (buf, buflen, a); 100 return 1; 101 } 102 } 103 return 0; 104} 105 106static void make_from (ENVELOPE *hdr, char *buf, size_t len, int do_lists) 107{ 108 int me; 109 110 me = mutt_addr_is_user (hdr->from); 111 112 if (do_lists || me) 113 { 114 if (check_for_mailing_list (hdr->to, "To ", buf, len)) 115 return; 116 if (check_for_mailing_list (hdr->cc, "Cc ", buf, len)) 117 return; 118 } 119 120 if (me && hdr->to) 121 snprintf (buf, len, "To %s", mutt_get_name (hdr->to)); 122 else if (me && hdr->cc) 123 snprintf (buf, len, "Cc %s", mutt_get_name (hdr->cc)); 124 else if (me && hdr->bcc) 125 snprintf (buf, len, "Bcc %s", mutt_get_name (hdr->bcc)); 126 else if (hdr->from) 127 strfcpy (buf, mutt_get_name (hdr->from), len); 128 else 129 *buf = 0; 130} 131 132static void make_from_addr (ENVELOPE *hdr, char *buf, size_t len, int do_lists) 133{ 134 int me; 135 136 me = mutt_addr_is_user (hdr->from); 137 138 if (do_lists || me) 139 { 140 if (check_for_mailing_list_addr (hdr->to, buf, len)) 141 return; 142 if (check_for_mailing_list_addr (hdr->cc, buf, len)) 143 return; 144 } 145 146 if (me && hdr->to) 147 snprintf (buf, len, "%s", hdr->to->mailbox); 148 else if (me && hdr->cc) 149 snprintf (buf, len, "%s", hdr->cc->mailbox); 150 else if (hdr->from) 151 strfcpy (buf, hdr->from->mailbox, len); 152 else 153 *buf = 0; 154} 155 156static int user_in_addr (ADDRESS *a) 157{ 158 for (; a; a = a->next) 159 if (mutt_addr_is_user (a)) 160 return 1; 161 return 0; 162} 163 164/* Return values: 165 * 0: user is not in list 166 * 1: user is unique recipient 167 * 2: user is in the TO list 168 * 3: user is in the CC list 169 * 4: user is originator 170 * 5: sent to a subscribed mailinglist 171 */ 172int mutt_user_is_recipient (HEADER *h) 173{ 174 ENVELOPE *env = h->env; 175 176 if (!h->recip_valid) 177 { 178 h->recip_valid = 1; 179 180 if (mutt_addr_is_user (env->from)) 181 h->recipient = 4; 182 else if (user_in_addr (env->to)) 183 { 184 if (env->to->next || env->cc) 185 h->recipient = 2; /* non-unique recipient */ 186 else 187 h->recipient = 1; /* unique recipient */ 188 } 189 else if (user_in_addr (env->cc)) 190 h->recipient = 3; 191 else if (check_for_mailing_list (env->to, NULL, NULL, 0)) 192 h->recipient = 5; 193 else if (check_for_mailing_list (env->cc, NULL, NULL, 0)) 194 h->recipient = 5; 195 else 196 h->recipient = 0; 197 } 198 199 return h->recipient; 200} 201 202static char *apply_subject_mods (ENVELOPE *env) 203{ 204 if (env == NULL) 205 return NULL; 206 207 if (SubjectRxList == NULL) 208 return env->subject; 209 210 if (env->subject == NULL || *env->subject == '\0') 211 return env->disp_subj = NULL; 212 213 env->disp_subj = mutt_apply_replace(NULL, 0, env->subject, SubjectRxList); 214 return env->disp_subj; 215} 216 217 218/* %a = address of author 219 * %A = reply-to address (if present; otherwise: address of author 220 * %b = filename of the originating folder 221 * %B = the list to which the letter was sent 222 * %c = size of message in bytes 223 * %C = current message number 224 * %d = date and time of message using $date_format and sender's timezone 225 * %D = date and time of message using $date_format and local timezone 226 * %e = current message number in thread 227 * %E = number of messages in current thread 228 * %f = entire from line 229 * %F = like %n, unless from self 230 * %i = message-id 231 * %l = number of lines in the message 232 * %L = like %F, except `lists' are displayed first 233 * %m = number of messages in the mailbox 234 * %n = name of author 235 * %N = score 236 * %O = like %L, except using address instead of name 237 * %P = progress indicator for builtin pager 238 * %r = comma separated list of To: recipients 239 * %R = comma separated list of Cc: recipients 240 * %s = subject 241 * %S = short message status (e.g., N/O/D/!/r/-) 242 * %t = `to:' field (recipients) 243 * %T = $to_chars 244 * %u = user (login) name of author 245 * %v = first name of author, unless from self 246 * %X = number of MIME attachments 247 * %y = `x-label:' field (if present) 248 * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label) 249 * %Z = status flags */ 250 251static const char * 252hdr_format_str (char *dest, 253 size_t destlen, 254 size_t col, 255 int cols, 256 char op, 257 const char *src, 258 const char *prefix, 259 const char *ifstring, 260 const char *elsestring, 261 unsigned long data, 262 format_flag flags) 263{ 264 struct hdr_format_info *hfi = (struct hdr_format_info *) data; 265 HEADER *hdr, *htmp; 266 CONTEXT *ctx; 267 char fmt[SHORT_STRING], buf2[LONG_STRING], ch, *p; 268 int do_locales, i; 269 int optional = (flags & MUTT_FORMAT_OPTIONAL); 270 int threads = ((Sort & SORT_MASK) == SORT_THREADS); 271 int is_index = (flags & MUTT_FORMAT_INDEX); 272#define THREAD_NEW (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 1) 273#define THREAD_OLD (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 2) 274 size_t len; 275 276 hdr = hfi->hdr; 277 ctx = hfi->ctx; 278 279 dest[0] = 0; 280 switch (op) 281 { 282 case 'A': 283 if (hdr->env->reply_to && hdr->env->reply_to->mailbox) 284 { 285 mutt_format_s (dest, destlen, prefix, mutt_addr_for_display (hdr->env->reply_to)); 286 break; 287 } 288 /* fall through */ 289 290 case 'a': 291 if (hdr->env->from && hdr->env->from->mailbox) 292 { 293 mutt_format_s (dest, destlen, prefix, mutt_addr_for_display (hdr->env->from)); 294 } 295 else 296 dest[0] = '\0'; 297 break; 298 299 case 'B': 300 if (!first_mailing_list (dest, destlen, hdr->env->to) && 301 !first_mailing_list (dest, destlen, hdr->env->cc)) 302 dest[0] = 0; 303 if (dest[0]) 304 { 305 strfcpy (buf2, dest, sizeof(buf2)); 306 mutt_format_s (dest, destlen, prefix, buf2); 307 break; 308 } 309 /* fall through */ 310 311 case 'b': 312 if (ctx) 313 { 314 if ((p = strrchr (ctx->path, '/'))) 315 strfcpy (dest, p + 1, destlen); 316 else 317 strfcpy (dest, ctx->path, destlen); 318 } 319 else 320 strfcpy(dest, "(null)", destlen); 321 strfcpy (buf2, dest, sizeof(buf2)); 322 mutt_format_s (dest, destlen, prefix, buf2); 323 break; 324 325 case 'c': 326 mutt_pretty_size (buf2, sizeof (buf2), (long) hdr->content->length); 327 mutt_format_s (dest, destlen, prefix, buf2); 328 break; 329 330 case 'C': 331 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 332 snprintf (dest, destlen, fmt, hdr->msgno + 1); 333 break; 334 335 case 'd': 336 case 'D': 337 case '{': 338 case '[': 339 case '(': 340 case '<': 341 342 /* preprocess $date_format to handle %Z */ 343 { 344 const char *cp; 345 struct tm *tm; 346 time_t T; 347 348 p = dest; 349 350 cp = (op == 'd' || op == 'D') ? (NONULL (DateFmt)) : src; 351 if (*cp == '!') 352 { 353 do_locales = 0; 354 cp++; 355 } 356 else 357 do_locales = 1; 358 359 len = destlen - 1; 360 while (len > 0 && (((op == 'd' || op == 'D') && *cp) || 361 (op == '{' && *cp != '}') || 362 (op == '[' && *cp != ']') || 363 (op == '(' && *cp != ')') || 364 (op == '<' && *cp != '>'))) 365 { 366 if (*cp == '%') 367 { 368 cp++; 369 if ((*cp == 'Z' || *cp == 'z') && (op == 'd' || op == '{')) 370 { 371 if (len >= 5) 372 { 373 sprintf (p, "%c%02u%02u", hdr->zoccident ? '-' : '+', 374 hdr->zhours, hdr->zminutes); 375 p += 5; 376 len -= 5; 377 } 378 else 379 break; /* not enough space left */ 380 } 381 else 382 { 383 if (len >= 2) 384 { 385 *p++ = '%'; 386 *p++ = *cp; 387 len -= 2; 388 } 389 else 390 break; /* not enough space */ 391 } 392 cp++; 393 } 394 else 395 { 396 *p++ = *cp++; 397 len--; 398 } 399 } 400 *p = 0; 401 402 if (op == '[' || op == 'D') 403 tm = localtime (&hdr->date_sent); 404 else if (op == '(') 405 tm = localtime (&hdr->received); 406 else if (op == '<') 407 { 408 T = time (NULL); 409 tm = localtime (&T); 410 } 411 else 412 { 413 /* restore sender's time zone */ 414 T = hdr->date_sent; 415 if (hdr->zoccident) 416 T -= (hdr->zhours * 3600 + hdr->zminutes * 60); 417 else 418 T += (hdr->zhours * 3600 + hdr->zminutes * 60); 419 tm = gmtime (&T); 420 } 421 422 if (!do_locales) 423 setlocale (LC_TIME, "C"); 424 strftime (buf2, sizeof (buf2), dest, tm); 425 if (!do_locales) 426 setlocale (LC_TIME, ""); 427 428 mutt_format_s (dest, destlen, prefix, buf2); 429 if (len > 0 && op != 'd' && op != 'D') /* Skip ending op */ 430 src = cp + 1; 431 } 432 break; 433 434 case 'e': 435 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 436 snprintf (dest, destlen, fmt, mutt_messages_in_thread(ctx, hdr, 1)); 437 break; 438 439 case 'E': 440 if (!optional) 441 { 442 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 443 snprintf (dest, destlen, fmt, mutt_messages_in_thread(ctx, hdr, 0)); 444 } 445 else if (mutt_messages_in_thread(ctx, hdr, 0) <= 1) 446 optional = 0; 447 break; 448 449 case 'f': 450 buf2[0] = 0; 451 rfc822_write_address (buf2, sizeof (buf2), hdr->env->from, 1); 452 mutt_format_s (dest, destlen, prefix, buf2); 453 break; 454 455 case 'F': 456 if (!optional) 457 { 458 make_from (hdr->env, buf2, sizeof (buf2), 0); 459 mutt_format_s (dest, destlen, prefix, buf2); 460 } 461 else if (mutt_addr_is_user (hdr->env->from)) 462 optional = 0; 463 break; 464 465 case 'H': 466 /* (Hormel) spam score */ 467 if (optional) 468 { 469 optional = hdr->env->spam ? 1 : 0; 470 } 471 472 if (hdr->env->spam) 473 mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->spam->data)); 474 else 475 mutt_format_s (dest, destlen, prefix, ""); 476 477 break; 478 479 case 'i': 480 mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : "<no.id>"); 481 break; 482 483 case 'l': 484 if (!optional) 485 { 486 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 487 snprintf (dest, destlen, fmt, (int) hdr->lines); 488 } 489 else if (hdr->lines <= 0) 490 optional = 0; 491 break; 492 493 case 'L': 494 if (!optional) 495 { 496 make_from (hdr->env, buf2, sizeof (buf2), 1); 497 mutt_format_s (dest, destlen, prefix, buf2); 498 } 499 else if (!check_for_mailing_list (hdr->env->to, NULL, NULL, 0) && 500 !check_for_mailing_list (hdr->env->cc, NULL, NULL, 0)) 501 { 502 optional = 0; 503 } 504 break; 505 506 case 'm': 507 if (ctx) 508 { 509 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 510 snprintf (dest, destlen, fmt, ctx->msgcount); 511 } 512 else 513 strfcpy(dest, "(null)", destlen); 514 break; 515 516 case 'n': 517 mutt_format_s (dest, destlen, prefix, mutt_get_name (hdr->env->from)); 518 break; 519 520 case 'N': 521 if (!optional) 522 { 523 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 524 snprintf (dest, destlen, fmt, hdr->score); 525 } 526 else 527 { 528 if (hdr->score == 0) 529 optional = 0; 530 } 531 break; 532 533 case 'O': 534 if (!optional) 535 { 536 make_from_addr (hdr->env, buf2, sizeof (buf2), 1); 537 if (!option (OPTSAVEADDRESS) && (p = strpbrk (buf2, "%@"))) 538 *p = 0; 539 mutt_format_s (dest, destlen, prefix, buf2); 540 } 541 else if (!check_for_mailing_list_addr (hdr->env->to, NULL, 0) && 542 !check_for_mailing_list_addr (hdr->env->cc, NULL, 0)) 543 { 544 optional = 0; 545 } 546 break; 547 548 case 'M': 549 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 550 if (!optional) 551 { 552 if (threads && is_index && hdr->collapsed && hdr->num_hidden > 1) 553 snprintf (dest, destlen, fmt, hdr->num_hidden); 554 else if (is_index && threads) 555 mutt_format_s (dest, destlen, prefix, " "); 556 else 557 *dest = '\0'; 558 } 559 else 560 { 561 if (!(threads && is_index && hdr->collapsed && hdr->num_hidden > 1)) 562 optional = 0; 563 } 564 break; 565 566 case 'P': 567 strfcpy(dest, NONULL(hfi->pager_progress), destlen); 568 break; 569 570 case 'r': 571 buf2[0] = 0; 572 rfc822_write_address(buf2, sizeof(buf2), hdr->env->to, 1); 573 if (optional && buf2[0] == '\0') 574 optional = 0; 575 mutt_format_s (dest, destlen, prefix, buf2); 576 break; 577 578 case 'R': 579 buf2[0] = 0; 580 rfc822_write_address(buf2, sizeof(buf2), hdr->env->cc, 1); 581 if (optional && buf2[0] == '\0') 582 optional = 0; 583 mutt_format_s (dest, destlen, prefix, buf2); 584 break; 585 586 case 's': 587 { 588 char *subj; 589 if (hdr->env->disp_subj) 590 subj = hdr->env->disp_subj; 591 else if (SubjectRxList) 592 subj = apply_subject_mods(hdr->env); 593 else 594 subj = hdr->env->subject; 595 if (flags & MUTT_FORMAT_TREE && !hdr->collapsed) 596 { 597 if (flags & MUTT_FORMAT_FORCESUBJ) 598 { 599 mutt_format_s (dest, destlen, "", NONULL (subj)); 600 snprintf (buf2, sizeof (buf2), "%s%s", hdr->tree, dest); 601 mutt_format_s_tree (dest, destlen, prefix, buf2); 602 } 603 else 604 mutt_format_s_tree (dest, destlen, prefix, hdr->tree); 605 } 606 else 607 mutt_format_s (dest, destlen, prefix, NONULL (subj)); 608 } 609 break; 610 611 case 'S': 612 if (hdr->deleted) 613 ch = 'D'; 614 else if (hdr->attach_del) 615 ch = 'd'; 616 else if (hdr->tagged) 617 ch = '*'; 618 else if (hdr->flagged) 619 ch = '!'; 620 else if (hdr->replied) 621 ch = 'r'; 622 else if (hdr->read && (ctx && ctx->msgnotreadyet != hdr->msgno)) 623 ch = '-'; 624 else if (hdr->old) 625 ch = 'O'; 626 else 627 ch = 'N'; 628 629 /* FOO - this is probably unsafe, but we are not likely to have such 630 a short string passed into this routine */ 631 *dest = ch; 632 *(dest + 1) = 0; 633 break; 634 635 case 't': 636 buf2[0] = 0; 637 if (!check_for_mailing_list (hdr->env->to, "To ", buf2, sizeof (buf2)) && 638 !check_for_mailing_list (hdr->env->cc, "Cc ", buf2, sizeof (buf2))) 639 { 640 if (hdr->env->to) 641 snprintf (buf2, sizeof (buf2), "To %s", mutt_get_name (hdr->env->to)); 642 else if (hdr->env->cc) 643 snprintf (buf2, sizeof (buf2), "Cc %s", mutt_get_name (hdr->env->cc)); 644 } 645 mutt_format_s (dest, destlen, prefix, buf2); 646 break; 647 648 case 'T': 649 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 650 snprintf (dest, destlen, fmt, 651 (Tochars && ((i = mutt_user_is_recipient (hdr))) < Tochars->len) ? Tochars->chars[i] : " "); 652 break; 653 654 case 'u': 655 if (hdr->env->from && hdr->env->from->mailbox) 656 { 657 strfcpy (buf2, mutt_addr_for_display (hdr->env->from), sizeof (buf2)); 658 if ((p = strpbrk (buf2, "%@"))) 659 *p = 0; 660 } 661 else 662 buf2[0] = 0; 663 mutt_format_s (dest, destlen, prefix, buf2); 664 break; 665 666 case 'v': 667 if (mutt_addr_is_user (hdr->env->from)) 668 { 669 if (hdr->env->to) 670 mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->to)); 671 else if (hdr->env->cc) 672 mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->cc)); 673 else 674 *buf2 = 0; 675 } 676 else 677 mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->from)); 678 if ((p = strpbrk (buf2, " %@"))) 679 *p = 0; 680 mutt_format_s (dest, destlen, prefix, buf2); 681 break; 682 683 case 'Z': 684 685 ch = ' '; 686 687 if (WithCrypto && hdr->security & GOODSIGN) 688 ch = 'S'; 689 else if (WithCrypto && hdr->security & ENCRYPT) 690 ch = 'P'; 691 else if (WithCrypto && hdr->security & SIGN) 692 ch = 's'; 693 else if ((WithCrypto & APPLICATION_PGP) && 694 ((hdr->security & PGPKEY) == PGPKEY)) 695 ch = 'K'; 696 697 snprintf (buf2, sizeof (buf2), 698 "%c%c%s", (THREAD_NEW ? 'n' : (THREAD_OLD ? 'o' : 699 ((hdr->read && (ctx && ctx->msgnotreadyet != hdr->msgno)) 700 ? (hdr->replied ? 'r' : ' ') : (hdr->old ? 'O' : 'N')))), 701 hdr->deleted ? 'D' : (hdr->attach_del ? 'd' : ch), 702 hdr->tagged ? "*" : 703 (hdr->flagged ? "!" : 704 (Tochars && ((i = mutt_user_is_recipient (hdr)) < Tochars->len) ? Tochars->chars[i] : " "))); 705 mutt_format_s (dest, destlen, prefix, buf2); 706 break; 707 708 case 'X': 709 { 710 int count = mutt_count_body_parts (ctx, hdr); 711 712 /* The recursion allows messages without depth to return 0. */ 713 if (optional) 714 optional = count != 0; 715 716 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 717 snprintf (dest, destlen, fmt, count); 718 } 719 break; 720 721 case 'y': 722 if (optional) 723 optional = hdr->env->x_label ? 1 : 0; 724 725 mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->x_label)); 726 break; 727 728 case 'Y': 729 if (hdr->env->x_label) 730 { 731 i = 1; /* reduce reuse recycle */ 732 htmp = NULL; 733 if (flags & MUTT_FORMAT_TREE 734 && (hdr->thread->prev && hdr->thread->prev->message 735 && hdr->thread->prev->message->env->x_label)) 736 htmp = hdr->thread->prev->message; 737 else if (flags & MUTT_FORMAT_TREE 738 && (hdr->thread->parent && hdr->thread->parent->message 739 && hdr->thread->parent->message->env->x_label)) 740 htmp = hdr->thread->parent->message; 741 if (htmp && mutt_strcasecmp (hdr->env->x_label, 742 htmp->env->x_label) == 0) 743 i = 0; 744 } 745 else 746 i = 0; 747 748 if (optional) 749 optional = i; 750 751 if (i) 752 mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->x_label)); 753 else 754 mutt_format_s (dest, destlen, prefix, ""); 755 756 break; 757 758 case '@': 759 { 760 const char *end = src; 761 static unsigned char recurse = 0; 762 763 while (*end && *end != '@') 764 end++; 765 if ((*end == '@') && (recurse < 20)) 766 { 767 recurse++; 768 mutt_substrcpy (buf2, src, end, sizeof(buf2)); 769 mutt_FormatString (buf2, sizeof(buf2), col, cols, 770 NONULL (mutt_idxfmt_hook (buf2, ctx, hdr)), 771 hdr_format_str, (unsigned long) hfi, flags); 772 mutt_format_s (dest, destlen, prefix, buf2); 773 recurse--; 774 775 src = end + 1; 776 break; 777 } 778 } 779 /* else fall through */ 780 781 default: 782 snprintf (dest, destlen, "%%%s%c", prefix, op); 783 break; 784 } 785 786 if (optional) 787 mutt_FormatString (dest, destlen, col, cols, ifstring, hdr_format_str, (unsigned long) hfi, flags); 788 else if (flags & MUTT_FORMAT_OPTIONAL) 789 mutt_FormatString (dest, destlen, col, cols, elsestring, hdr_format_str, (unsigned long) hfi, flags); 790 791 return (src); 792#undef THREAD_NEW 793#undef THREAD_OLD 794} 795 796void 797_mutt_make_string (char *dest, size_t destlen, const char *s, CONTEXT *ctx, HEADER *hdr, format_flag flags) 798{ 799 struct hdr_format_info hfi; 800 801 hfi.hdr = hdr; 802 hfi.ctx = ctx; 803 hfi.pager_progress = 0; 804 805 mutt_FormatString (dest, destlen, 0, MuttIndexWindow->cols, s, hdr_format_str, (unsigned long) &hfi, flags); 806} 807 808void 809mutt_make_string_info (char *dst, size_t dstlen, int cols, const char *s, struct hdr_format_info *hfi, format_flag flags) 810{ 811 mutt_FormatString (dst, dstlen, 0, cols, s, hdr_format_str, (unsigned long) hfi, flags); 812}