mutt stable branch with some hacks
at master 834 lines 19 kB view raw
1/* 2 * Copyright (C) 1996-2002,2012 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 "mapping.h" 26 27#include <string.h> 28#include <stdlib.h> 29#include <ctype.h> 30 31/* globals */ 32int *ColorQuote; 33int ColorQuoteUsed; 34int ColorDefs[MT_COLOR_MAX]; 35COLOR_LINE *ColorHdrList = NULL; 36COLOR_LINE *ColorBodyList = NULL; 37COLOR_LINE *ColorIndexList = NULL; 38 39/* local to this file */ 40static int ColorQuoteSize; 41 42#ifdef HAVE_COLOR 43 44#define COLOR_DEFAULT (-2) 45 46typedef struct color_list 47{ 48 short fg; 49 short bg; 50 short index; 51 short count; 52 struct color_list *next; 53} COLOR_LIST; 54 55static COLOR_LIST *ColorList = NULL; 56static int UserColors = 0; 57 58static const struct mapping_t Colors[] = 59{ 60 { "black", COLOR_BLACK }, 61 { "blue", COLOR_BLUE }, 62 { "cyan", COLOR_CYAN }, 63 { "green", COLOR_GREEN }, 64 { "magenta", COLOR_MAGENTA }, 65 { "red", COLOR_RED }, 66 { "white", COLOR_WHITE }, 67 { "yellow", COLOR_YELLOW }, 68#if defined (USE_SLANG_CURSES) || defined (HAVE_USE_DEFAULT_COLORS) 69 { "default", COLOR_DEFAULT }, 70#endif 71 { 0, 0 } 72}; 73 74#endif /* HAVE_COLOR */ 75 76static const struct mapping_t Fields[] = 77{ 78 { "hdrdefault", MT_COLOR_HDEFAULT }, 79 { "quoted", MT_COLOR_QUOTED }, 80 { "signature", MT_COLOR_SIGNATURE }, 81 { "indicator", MT_COLOR_INDICATOR }, 82 { "status", MT_COLOR_STATUS }, 83 { "tree", MT_COLOR_TREE }, 84 { "error", MT_COLOR_ERROR }, 85 { "normal", MT_COLOR_NORMAL }, 86 { "tilde", MT_COLOR_TILDE }, 87 { "markers", MT_COLOR_MARKERS }, 88 { "header", MT_COLOR_HEADER }, 89 { "body", MT_COLOR_BODY }, 90 { "message", MT_COLOR_MESSAGE }, 91 { "attachment", MT_COLOR_ATTACHMENT }, 92 { "search", MT_COLOR_SEARCH }, 93 { "bold", MT_COLOR_BOLD }, 94 { "underline", MT_COLOR_UNDERLINE }, 95 { "index", MT_COLOR_INDEX }, 96 { "prompt", MT_COLOR_PROMPT }, 97#ifdef USE_SIDEBAR 98 { "sidebar_divider", MT_COLOR_DIVIDER }, 99 { "sidebar_flagged", MT_COLOR_FLAGGED }, 100 { "sidebar_highlight",MT_COLOR_HIGHLIGHT }, 101 { "sidebar_indicator",MT_COLOR_SB_INDICATOR }, 102 { "sidebar_new", MT_COLOR_NEW }, 103 { "sidebar_spoolfile",MT_COLOR_SB_SPOOLFILE }, 104#endif 105 { NULL, 0 } 106}; 107 108#define COLOR_QUOTE_INIT 8 109 110static COLOR_LINE *mutt_new_color_line (void) 111{ 112 COLOR_LINE *p = safe_calloc (1, sizeof (COLOR_LINE)); 113 114 p->fg = p->bg = -1; 115 116 return (p); 117} 118 119static void mutt_free_color_line(COLOR_LINE **l, 120 int free_colors) 121{ 122 COLOR_LINE *tmp; 123 124 if(!l || !*l) 125 return; 126 127 tmp = *l; 128 129#ifdef HAVE_COLOR 130 if(free_colors && tmp->fg != -1 && tmp->bg != -1) 131 mutt_free_color(tmp->fg, tmp->bg); 132#endif 133 134 /* we should really introduce a container 135 * type for regular expressions. 136 */ 137 138 regfree(&tmp->rx); 139 mutt_pattern_free(&tmp->color_pattern); 140 FREE (&tmp->pattern); 141 FREE (l); /* __FREE_CHECKED__ */ 142} 143 144void ci_start_color (void) 145{ 146 memset (ColorDefs, A_NORMAL, sizeof (int) * MT_COLOR_MAX); 147 ColorQuote = (int *) safe_malloc (COLOR_QUOTE_INIT * sizeof (int)); 148 memset (ColorQuote, A_NORMAL, sizeof (int) * COLOR_QUOTE_INIT); 149 ColorQuoteSize = COLOR_QUOTE_INIT; 150 ColorQuoteUsed = 0; 151 152 /* set some defaults */ 153 ColorDefs[MT_COLOR_STATUS] = A_REVERSE; 154 ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE; 155 ColorDefs[MT_COLOR_SEARCH] = A_REVERSE; 156 ColorDefs[MT_COLOR_MARKERS] = A_REVERSE; 157#ifdef USE_SIDEBAR 158 ColorDefs[MT_COLOR_HIGHLIGHT] = A_UNDERLINE; 159#endif 160 /* special meaning: toggle the relevant attribute */ 161 ColorDefs[MT_COLOR_BOLD] = 0; 162 ColorDefs[MT_COLOR_UNDERLINE] = 0; 163 164#ifdef HAVE_COLOR 165 start_color (); 166#endif 167} 168 169#ifdef HAVE_COLOR 170 171#ifdef USE_SLANG_CURSES 172static char *get_color_name (char *dest, size_t destlen, int val) 173{ 174 static const char * const missing[3] = {"brown", "lightgray", "default"}; 175 int i; 176 177 switch (val) 178 { 179 case COLOR_YELLOW: 180 strfcpy (dest, missing[0], destlen); 181 return dest; 182 183 case COLOR_WHITE: 184 strfcpy (dest, missing[1], destlen); 185 return dest; 186 187 case COLOR_DEFAULT: 188 strfcpy (dest, missing[2], destlen); 189 return dest; 190 } 191 192 for (i = 0; Colors[i].name; i++) 193 { 194 if (Colors[i].value == val) 195 { 196 strfcpy (dest, Colors[i].name, destlen); 197 return dest; 198 } 199 } 200 201 /* Sigh. If we got this far, the color is of the form 'colorN' 202 * Slang can handle this itself, so just return 'colorN' 203 */ 204 205 snprintf (dest, destlen, "color%d", val); 206 return dest; 207} 208#endif 209 210int mutt_alloc_color (int fg, int bg) 211{ 212 COLOR_LIST *p = ColorList; 213 int i; 214 215#if defined (USE_SLANG_CURSES) 216 char fgc[SHORT_STRING], bgc[SHORT_STRING]; 217#endif 218 219 /* check to see if this color is already allocated to save space */ 220 while (p) 221 { 222 if (p->fg == fg && p->bg == bg) 223 { 224 (p->count)++; 225 return (COLOR_PAIR (p->index)); 226 } 227 p = p->next; 228 } 229 230 /* check to see if there are colors left */ 231 if (++UserColors > COLOR_PAIRS) return (A_NORMAL); 232 233 /* find the smallest available index (object) */ 234 i = 1; 235 FOREVER 236 { 237 p = ColorList; 238 while (p) 239 { 240 if (p->index == i) break; 241 p = p->next; 242 } 243 if (p == NULL) break; 244 i++; 245 } 246 247 p = (COLOR_LIST *) safe_malloc (sizeof (COLOR_LIST)); 248 p->next = ColorList; 249 ColorList = p; 250 251 p->index = i; 252 p->count = 1; 253 p->bg = bg; 254 p->fg = fg; 255 256#if defined (USE_SLANG_CURSES) 257 if (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT) 258 SLtt_set_color (i, NULL, get_color_name (fgc, sizeof (fgc), fg), get_color_name (bgc, sizeof (bgc), bg)); 259 else 260#elif defined (HAVE_USE_DEFAULT_COLORS) 261 if (fg == COLOR_DEFAULT) 262 fg = -1; 263 if (bg == COLOR_DEFAULT) 264 bg = -1; 265#endif 266 267 init_pair(i, fg, bg); 268 269 dprint (3, (debugfile,"mutt_alloc_color(): Color pairs used so far: %d\n", 270 UserColors)); 271 272 return (COLOR_PAIR (p->index)); 273} 274 275void mutt_free_color (int fg, int bg) 276{ 277 COLOR_LIST *p, *q; 278 279 p = ColorList; 280 while (p) 281 { 282 if (p->fg == fg && p->bg == bg) 283 { 284 (p->count)--; 285 if (p->count > 0) return; 286 287 UserColors--; 288 dprint(1,(debugfile,"mutt_free_color(): Color pairs used so far: %d\n", 289 UserColors)); 290 291 if (p == ColorList) 292 { 293 ColorList = ColorList->next; 294 FREE (&p); 295 return; 296 } 297 q = ColorList; 298 while (q) 299 { 300 if (q->next == p) 301 { 302 q->next = p->next; 303 FREE (&p); 304 return; 305 } 306 q = q->next; 307 } 308 /* can't get here */ 309 } 310 p = p->next; 311 } 312} 313 314#endif /* HAVE_COLOR */ 315 316 317#ifdef HAVE_COLOR 318 319static int 320parse_color_name (const char *s, int *col, int *attr, int is_fg, BUFFER *err) 321{ 322 char *eptr; 323 int is_bright = 0; 324 325 if (ascii_strncasecmp (s, "bright", 6) == 0) 326 { 327 is_bright = 1; 328 s += 6; 329 } 330 331 /* allow aliases for xterm color resources */ 332 if (ascii_strncasecmp (s, "color", 5) == 0) 333 { 334 s += 5; 335 *col = strtol (s, &eptr, 10); 336 if (!*s || *eptr || *col < 0 || 337 (*col >= COLORS && !option(OPTNOCURSES) && has_colors())) 338 { 339 snprintf (err->data, err->dsize, _("%s: color not supported by term"), s); 340 return (-1); 341 } 342 } 343 else if ((*col = mutt_getvaluebyname (s, Colors)) == -1) 344 { 345 snprintf (err->data, err->dsize, _("%s: no such color"), s); 346 return (-1); 347 } 348 349 if (is_bright) 350 { 351 if (is_fg) 352 { 353 *attr |= A_BOLD; 354 } 355 else if (COLORS < 16) 356 { 357 /* A_BLINK turns the background color brite on some terms */ 358 *attr |= A_BLINK; 359 } 360 else 361 { 362 /* Advance the color by 8 to get the bright version */ 363 *col += 8; 364 } 365 } 366 367 return 0; 368} 369 370#endif 371 372 373/* usage: uncolor index pattern [pattern...] 374 * unmono index pattern [pattern...] 375 */ 376 377static int 378_mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, 379 short parse_uncolor); 380 381 382#ifdef HAVE_COLOR 383 384int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, 385 BUFFER *err) 386{ 387 return _mutt_parse_uncolor(buf, s, data, err, 1); 388} 389 390#endif 391 392int mutt_parse_unmono (BUFFER *buf, BUFFER *s, unsigned long data, 393 BUFFER *err) 394{ 395 return _mutt_parse_uncolor(buf, s, data, err, 0); 396} 397 398static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, 399 BUFFER *err, short parse_uncolor) 400{ 401 int object = 0, do_cache = 0; 402 COLOR_LINE *tmp, *last = NULL; 403 COLOR_LINE **list; 404 405 mutt_extract_token (buf, s, 0); 406 407 if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) 408 { 409 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data); 410 return (-1); 411 } 412 413 if (mutt_strncmp (buf->data, "index", 5) == 0) 414 list = &ColorIndexList; 415 else if (mutt_strncmp (buf->data, "body", 4) == 0) 416 list = &ColorBodyList; 417 else if (mutt_strncmp (buf->data, "header", 7) == 0) 418 list = &ColorHdrList; 419 else 420 { 421 snprintf (err->data, err->dsize, 422 _("%s: command valid only for index, body, header objects"), 423 parse_uncolor ? "uncolor" : "unmono"); 424 return (-1); 425 } 426 427 if (!MoreArgs (s)) 428 { 429 snprintf (err->data, err->dsize, 430 _("%s: too few arguments"), parse_uncolor ? "uncolor" : "unmono"); 431 return (-1); 432 } 433 434 if( 435#ifdef HAVE_COLOR 436 /* we're running without curses */ 437 option (OPTNOCURSES) 438 || /* we're parsing an uncolor command, and have no colors */ 439 (parse_uncolor && !has_colors()) 440 /* we're parsing an unmono command, and have colors */ 441 || (!parse_uncolor && has_colors()) 442#else 443 /* We don't even have colors compiled in */ 444 parse_uncolor 445#endif 446 ) 447 { 448 /* just eat the command, but don't do anything real about it */ 449 do 450 mutt_extract_token (buf, s, 0); 451 while (MoreArgs (s)); 452 453 return 0; 454 } 455 456 do 457 { 458 mutt_extract_token (buf, s, 0); 459 if (!mutt_strcmp ("*", buf->data)) 460 { 461 for (tmp = *list; tmp; ) 462 { 463 if (!do_cache) 464 do_cache = 1; 465 last = tmp; 466 tmp = tmp->next; 467 mutt_free_color_line(&last, parse_uncolor); 468 } 469 *list = NULL; 470 } 471 else 472 { 473 for (last = NULL, tmp = *list; tmp; last = tmp, tmp = tmp->next) 474 { 475 if (!mutt_strcmp (buf->data, tmp->pattern)) 476 { 477 if (!do_cache) 478 do_cache = 1; 479 dprint(1,(debugfile,"Freeing pattern \"%s\" from color list\n", 480 tmp->pattern)); 481 if (last) 482 last->next = tmp->next; 483 else 484 *list = tmp->next; 485 mutt_free_color_line(&tmp, parse_uncolor); 486 break; 487 } 488 } 489 } 490 } 491 while (MoreArgs (s)); 492 493 494 if (do_cache && !option (OPTNOCURSES)) 495 { 496 int i; 497 set_option (OPTFORCEREDRAWINDEX); 498 /* force re-caching of index colors */ 499 for (i = 0; Context && i < Context->msgcount; i++) 500 Context->hdrs[i]->pair = 0; 501 } 502 return (0); 503} 504 505 506static int 507add_pattern (COLOR_LINE **top, const char *s, int sensitive, 508 int fg, int bg, int attr, BUFFER *err, 509 int is_index) 510{ 511 512 /* is_index used to store compiled pattern 513 * only for `index' color object 514 * when called from mutt_parse_color() */ 515 516 COLOR_LINE *tmp = *top; 517 518 while (tmp) 519 { 520 if (sensitive) 521 { 522 if (mutt_strcmp (s, tmp->pattern) == 0) 523 break; 524 } 525 else 526 { 527 if (mutt_strcasecmp (s, tmp->pattern) == 0) 528 break; 529 } 530 tmp = tmp->next; 531 } 532 533 if (tmp) 534 { 535#ifdef HAVE_COLOR 536 if (fg != -1 && bg != -1) 537 { 538 if (tmp->fg != fg || tmp->bg != bg) 539 { 540 mutt_free_color (tmp->fg, tmp->bg); 541 tmp->fg = fg; 542 tmp->bg = bg; 543 attr |= mutt_alloc_color (fg, bg); 544 } 545 else 546 attr |= (tmp->pair & ~A_BOLD); 547 } 548#endif /* HAVE_COLOR */ 549 tmp->pair = attr; 550 } 551 else 552 { 553 int r; 554 char buf[LONG_STRING]; 555 556 tmp = mutt_new_color_line (); 557 if (is_index) 558 { 559 int i; 560 561 strfcpy(buf, NONULL(s), sizeof(buf)); 562 mutt_check_simple (buf, sizeof (buf), NONULL(SimpleSearch)); 563 if((tmp->color_pattern = mutt_pattern_comp (buf, MUTT_FULL_MSG, err)) == NULL) 564 { 565 mutt_free_color_line(&tmp, 1); 566 return -1; 567 } 568 /* force re-caching of index colors */ 569 for (i = 0; Context && i < Context->msgcount; i++) 570 Context->hdrs[i]->pair = 0; 571 } 572 else if ((r = REGCOMP (&tmp->rx, s, (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) 573 { 574 regerror (r, &tmp->rx, err->data, err->dsize); 575 mutt_free_color_line(&tmp, 1); 576 return (-1); 577 } 578 tmp->next = *top; 579 tmp->pattern = safe_strdup (s); 580#ifdef HAVE_COLOR 581 if(fg != -1 && bg != -1) 582 { 583 tmp->fg = fg; 584 tmp->bg = bg; 585 attr |= mutt_alloc_color (fg, bg); 586 } 587#endif 588 tmp->pair = attr; 589 *top = tmp; 590 } 591 592 return 0; 593} 594 595static int 596parse_object(BUFFER *buf, BUFFER *s, int *o, int *ql, BUFFER *err) 597{ 598 int q_level = 0; 599 char *eptr; 600 601 if(!MoreArgs(s)) 602 { 603 strfcpy(err->data, _("Missing arguments."), err->dsize); 604 return -1; 605 } 606 607 mutt_extract_token(buf, s, 0); 608 if(!mutt_strncmp(buf->data, "quoted", 6)) 609 { 610 if(buf->data[6]) 611 { 612 *ql = strtol(buf->data + 6, &eptr, 10); 613 if(*eptr || q_level < 0) 614 { 615 snprintf(err->data, err->dsize, _("%s: no such object"), buf->data); 616 return -1; 617 } 618 } 619 else 620 *ql = 0; 621 622 *o = MT_COLOR_QUOTED; 623 } 624 else if ((*o = mutt_getvaluebyname (buf->data, Fields)) == -1) 625 { 626 snprintf (err->data, err->dsize, _("%s: no such object"), buf->data); 627 return (-1); 628 } 629 630 return 0; 631} 632 633typedef int (*parser_callback_t)(BUFFER *, BUFFER *, int *, int *, int *, BUFFER *); 634 635#ifdef HAVE_COLOR 636 637static int 638parse_color_pair(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err) 639{ 640 if (! MoreArgs (s)) 641 { 642 strfcpy (err->data, _("color: too few arguments"), err->dsize); 643 return (-1); 644 } 645 646 mutt_extract_token (buf, s, 0); 647 648 if (parse_color_name (buf->data, fg, attr, 1, err) != 0) 649 return (-1); 650 651 if (! MoreArgs (s)) 652 { 653 strfcpy (err->data, _("color: too few arguments"), err->dsize); 654 return (-1); 655 } 656 657 mutt_extract_token (buf, s, 0); 658 659 if (parse_color_name (buf->data, bg, attr, 0, err) != 0) 660 return (-1); 661 662 return 0; 663} 664 665#endif 666 667static int 668parse_attr_spec(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err) 669{ 670 671 if(fg) *fg = -1; 672 if(bg) *bg = -1; 673 674 if (! MoreArgs (s)) 675 { 676 strfcpy (err->data, _("mono: too few arguments"), err->dsize); 677 return (-1); 678 } 679 680 mutt_extract_token (buf, s, 0); 681 682 if (ascii_strcasecmp ("bold", buf->data) == 0) 683 *attr |= A_BOLD; 684 else if (ascii_strcasecmp ("underline", buf->data) == 0) 685 *attr |= A_UNDERLINE; 686 else if (ascii_strcasecmp ("none", buf->data) == 0) 687 *attr = A_NORMAL; 688 else if (ascii_strcasecmp ("reverse", buf->data) == 0) 689 *attr |= A_REVERSE; 690 else if (ascii_strcasecmp ("standout", buf->data) == 0) 691 *attr |= A_STANDOUT; 692 else if (ascii_strcasecmp ("normal", buf->data) == 0) 693 *attr = A_NORMAL; /* needs use = instead of |= to clear other bits */ 694 else 695 { 696 snprintf (err->data, err->dsize, _("%s: no such attribute"), buf->data); 697 return (-1); 698 } 699 700 return 0; 701} 702 703static int fgbgattr_to_color(int fg, int bg, int attr) 704{ 705#ifdef HAVE_COLOR 706 if(fg != -1 && bg != -1) 707 return attr | mutt_alloc_color(fg, bg); 708 else 709#endif 710 return attr; 711} 712 713/* usage: color <object> <fg> <bg> [ <regexp> ] 714 * mono <object> <attr> [ <regexp> ] 715 */ 716 717static int 718_mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err, 719 parser_callback_t callback, short dry_run) 720{ 721 int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0; 722 int r = 0; 723 724 if(parse_object(buf, s, &object, &q_level, err) == -1) 725 return -1; 726 727 if(callback(buf, s, &fg, &bg, &attr, err) == -1) 728 return -1; 729 730 /* extract a regular expression if needed */ 731 732 if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == MT_COLOR_INDEX) 733 { 734 if (!MoreArgs (s)) 735 { 736 strfcpy (err->data, _("too few arguments"), err->dsize); 737 return (-1); 738 } 739 740 mutt_extract_token (buf, s, 0); 741 } 742 743 if (MoreArgs (s)) 744 { 745 strfcpy (err->data, _("too many arguments"), err->dsize); 746 return (-1); 747 } 748 749 /* dry run? */ 750 751 if(dry_run) return 0; 752 753 754#ifdef HAVE_COLOR 755# ifdef HAVE_USE_DEFAULT_COLORS 756 if (!option (OPTNOCURSES) && has_colors() 757 /* delay use_default_colors() until needed, since it initializes things */ 758 && (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT) 759 && use_default_colors () != OK) 760 { 761 strfcpy (err->data, _("default colors not supported"), err->dsize); 762 return (-1); 763 } 764# endif /* HAVE_USE_DEFAULT_COLORS */ 765#endif 766 767 if (object == MT_COLOR_HEADER) 768 r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err,0); 769 else if (object == MT_COLOR_BODY) 770 r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0); 771 else if (object == MT_COLOR_INDEX) 772 { 773 r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1); 774 set_option (OPTFORCEREDRAWINDEX); 775 } 776 else if (object == MT_COLOR_QUOTED) 777 { 778 if (q_level >= ColorQuoteSize) 779 { 780 safe_realloc (&ColorQuote, (ColorQuoteSize += 2) * sizeof (int)); 781 ColorQuote[ColorQuoteSize-2] = ColorDefs[MT_COLOR_QUOTED]; 782 ColorQuote[ColorQuoteSize-1] = ColorDefs[MT_COLOR_QUOTED]; 783 } 784 if (q_level >= ColorQuoteUsed) 785 ColorQuoteUsed = q_level + 1; 786 if (q_level == 0) 787 { 788 ColorDefs[MT_COLOR_QUOTED] = fgbgattr_to_color(fg, bg, attr); 789 790 ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED]; 791 for (q_level = 1; q_level < ColorQuoteUsed; q_level++) 792 { 793 if (ColorQuote[q_level] == A_NORMAL) 794 ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED]; 795 } 796 } 797 else 798 ColorQuote[q_level] = fgbgattr_to_color(fg, bg, attr); 799 } 800 else 801 ColorDefs[object] = fgbgattr_to_color(fg, bg, attr); 802 803 return (r); 804} 805 806#ifdef HAVE_COLOR 807 808int mutt_parse_color(BUFFER *buff, BUFFER *s, unsigned long data, BUFFER *err) 809{ 810 int dry_run = 0; 811 812 if(option(OPTNOCURSES) || !has_colors()) 813 dry_run = 1; 814 815 return _mutt_parse_color(buff, s, err, parse_color_pair, dry_run); 816} 817 818#endif 819 820int mutt_parse_mono(BUFFER *buff, BUFFER *s, unsigned long data, BUFFER *err) 821{ 822 int dry_run = 0; 823 824#ifdef HAVE_COLOR 825 if(option(OPTNOCURSES) || has_colors()) 826 dry_run = 1; 827#else 828 if(option(OPTNOCURSES)) 829 dry_run = 1; 830#endif 831 832 return _mutt_parse_color(buff, s, err, parse_attr_spec, dry_run); 833} 834