"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/attrib.c" (9 Dec 2022, 83588 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "attrib.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.1_vs_2.6.2.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : attrib.c
    4  *  Author    : I. Lea
    5  *  Created   : 1993-12-01
    6  *  Updated   : 2022-06-29
    7  *  Notes     : Group attribute routines
    8  *
    9  * Copyright (c) 1993-2023 Iain Lea <iain@bricbrac.de>
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  *
   16  * 1. Redistributions of source code must retain the above copyright notice,
   17  *    this list of conditions and the following disclaimer.
   18  *
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * 3. Neither the name of the copyright holder nor the names of its
   24  *    contributors may be used to endorse or promote products derived from
   25  *    this software without specific prior written permission.
   26  *
   27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 
   41 #ifndef TIN_H
   42 #   include "tin.h"
   43 #endif /* !TIN_H */
   44 #ifndef VERSION_H
   45 #   include "version.h"
   46 #endif /* !VERSION_H */
   47 #ifndef TCURSES_H
   48 #   include "tcurses.h"
   49 #endif /* !TCURSES_H */
   50 
   51 
   52 /*
   53  * Global file offset for local_attributes_file
   54  */
   55 int attrib_file_offset;
   56 
   57 
   58 /*
   59  * Local prototypes
   60  */
   61 static t_bool skip_scope(struct t_scope *scope);
   62 static void set_attrib(int type, const char *scope, const char *line, void *data);
   63 static void set_default_attributes(struct t_attribute *attributes, struct t_attribute *scope, t_bool global);
   64 static void set_default_state(struct t_attribute_state *state);
   65 #ifdef DEBUG
   66     static void dump_attributes(void);
   67     static void dump_scopes(const char *fname);
   68 #   if 0 /* unused */
   69         static void debug_print_filter_attributes(void);
   70 #   endif /* 0 */
   71 #endif /* DEBUG */
   72 
   73 #define CopyBits(target,source) attributes->target = CAST_BITS(source,target)
   74 #define CopyBool(target,source) attributes->target = CAST_BOOL(source)
   75 
   76 /*
   77  * Per group attributes. This fills out a basic template of defaults
   78  * before the attributes in the current scope are applied.
   79  */
   80 static void
   81 set_default_attributes(
   82     struct t_attribute *attributes,
   83     struct t_attribute *scope,
   84     t_bool global)
   85 {
   86     attributes->global = (global ? TRUE : FALSE);   /* global/group specific */
   87     attributes->maildir = (scope ? scope->maildir : (global ? tinrc.maildir : NULL));
   88     attributes->savedir = (scope ? scope->savedir : (global ? tinrc.savedir : NULL));
   89     attributes->savefile = NULL;
   90     attributes->sigfile = (scope ? scope->sigfile : (global ? tinrc.sigfile : NULL));
   91     attributes->group_format = (scope ? scope->group_format : (global ? tinrc.group_format : NULL));
   92     attributes->thread_format = (scope ? scope->thread_format : (global ? tinrc.thread_format : NULL));
   93     attributes->date_format = (scope ? scope->date_format : (global ? tinrc.date_format : NULL));
   94     attributes->editor_format = (scope ? scope->editor_format : (global ? tinrc.editor_format : NULL));
   95     attributes->organization = (scope ? scope->organization : (global ? (*default_organization ? default_organization : NULL) : NULL));
   96     attributes->followup_to = NULL;
   97     attributes->mailing_list = NULL;
   98     attributes->x_headers = NULL;
   99     attributes->x_body = NULL;
  100     attributes->from = (scope ? scope->from : (global ? tinrc.mail_address : NULL));
  101     attributes->news_quote_format = (scope ? scope->news_quote_format : (global ? tinrc.news_quote_format : NULL));
  102     attributes->quote_chars = (scope ? scope->quote_chars : (global ? tinrc.quote_chars : NULL));
  103     attributes->mime_types_to_save = (scope ? scope->mime_types_to_save : (global ? my_strdup("*/*") : NULL));
  104 #ifdef HAVE_ISPELL
  105     attributes->ispell = NULL;
  106 #endif /* HAVE_ISPELL */
  107     attributes->quick_kill_scope = (scope ? scope->quick_kill_scope : (global ? (tinrc.default_filter_kill_global ? my_strdup("*") : NULL) : NULL));
  108     CopyBits(quick_kill_header, tinrc.default_filter_kill_header);
  109     CopyBool(quick_kill_case, tinrc.default_filter_kill_case);
  110     CopyBool(quick_kill_expire, tinrc.default_filter_kill_expire);
  111     attributes->quick_select_scope = (scope ? scope->quick_select_scope : (global ? (tinrc.default_filter_select_global ? my_strdup("*") : NULL) : NULL));
  112     CopyBits(quick_select_header, tinrc.default_filter_select_header);
  113     CopyBool(quick_select_case, tinrc.default_filter_select_case);
  114     CopyBool(quick_select_expire, tinrc.default_filter_select_expire);
  115     CopyBool(show_only_unread_arts, tinrc.show_only_unread_arts);
  116     CopyBits(thread_articles, tinrc.thread_articles);
  117     CopyBool(thread_catchup_on_exit, tinrc.thread_catchup_on_exit);
  118     CopyBits(thread_perc, tinrc.thread_perc);
  119     CopyBits(sort_article_type, tinrc.sort_article_type);
  120     CopyBits(sort_threads_type, tinrc.sort_threads_type);
  121     CopyBits(show_author, tinrc.show_author);
  122     CopyBool(show_signatures, tinrc.show_signatures);
  123 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  124     CopyBool(suppress_soft_hyphens, tinrc.suppress_soft_hyphens);
  125 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  126     CopyBits(trim_article_body, tinrc.trim_article_body);
  127     CopyBool(verbatim_handling, tinrc.verbatim_handling);
  128 #ifdef HAVE_COLOR
  129     CopyBool(extquote_handling, tinrc.extquote_handling);
  130 #endif /* HAVE_COLOR */
  131     CopyBool(wrap_on_next_unread, tinrc.wrap_on_next_unread);
  132     CopyBool(add_posted_to_filter, tinrc.add_posted_to_filter);
  133     CopyBool(advertising, tinrc.advertising);
  134     CopyBool(alternative_handling, tinrc.alternative_handling);
  135     CopyBool(ask_for_metamail, tinrc.ask_for_metamail);
  136     CopyBits(auto_cc_bcc, tinrc.auto_cc_bcc);
  137     CopyBool(auto_list_thread, tinrc.auto_list_thread);
  138     attributes->auto_select = FALSE;
  139     CopyBool(batch_save, tinrc.batch_save);
  140     attributes->delete_tmp_files = FALSE;
  141     CopyBool(group_catchup_on_exit, tinrc.group_catchup_on_exit);
  142     CopyBool(mail_8bit_header, tinrc.mail_8bit_header);
  143     CopyBits(mail_mime_encoding, tinrc.mail_mime_encoding);
  144     CopyBool(mark_ignore_tags, tinrc.mark_ignore_tags);
  145     CopyBool(mark_saved_read, tinrc.mark_saved_read);
  146     attributes->news_headers_to_display = (global ? tinrc.news_headers_to_display : NULL);
  147     attributes->headers_to_display = (scope ? (scope->headers_to_display ? scope->headers_to_display : NULL) : NULL);
  148     attributes->news_headers_to_not_display = (global ? tinrc.news_headers_to_not_display : NULL);
  149     attributes->headers_to_not_display = (scope ? (scope->headers_to_not_display ? scope->headers_to_not_display : NULL) : NULL);
  150     CopyBool(pos_first_unread, tinrc.pos_first_unread);
  151     CopyBool(post_8bit_header, tinrc.post_8bit_header);
  152     CopyBits(post_mime_encoding, tinrc.post_mime_encoding);
  153     CopyBool(post_process_view, tinrc.post_process_view);
  154     CopyBits(post_process_type, tinrc.post_process_type);
  155 #ifndef DISABLE_PRINTING
  156     CopyBool(print_header, tinrc.print_header);
  157 #endif /* !DISABLE_PRINTING */
  158     CopyBool(process_only_unread, tinrc.process_only_unread);
  159     CopyBool(prompt_followupto, tinrc.prompt_followupto);
  160     CopyBool(sigdashes, tinrc.sigdashes);
  161     CopyBool(signature_repost, tinrc.signature_repost);
  162     attributes->x_comment_to = FALSE;
  163     CopyBool(tex2iso_conv, tinrc.tex2iso_conv);
  164     attributes->mime_forward = FALSE;
  165     attributes->fcc = NULL;
  166 #ifdef CHARSET_CONVERSION
  167     CopyBits(mm_network_charset, tinrc.mm_network_charset);
  168     attributes->undeclared_charset = NULL;
  169 #endif /* CHARSET_CONVERSION */
  170 }
  171 
  172 
  173 static void
  174 set_default_state(
  175     struct t_attribute_state *state)
  176 {
  177     state->add_posted_to_filter = FALSE;
  178     state->advertising = FALSE;
  179     state->alternative_handling = FALSE;
  180     state->ask_for_metamail = FALSE;
  181     state->auto_cc_bcc = FALSE;
  182     state->auto_list_thread = FALSE;
  183     state->auto_select = FALSE;
  184     state->batch_save = FALSE;
  185     state->date_format = FALSE;
  186     state->delete_tmp_files = FALSE;
  187     state->editor_format = FALSE;
  188     state->fcc = FALSE;
  189     state->followup_to = FALSE;
  190     state->from = FALSE;
  191     state->group_catchup_on_exit = FALSE;
  192     state->group_format = FALSE;
  193 #ifdef HAVE_ISPELL
  194     state->ispell = FALSE;
  195 #endif /* HAVE_ISPELL */
  196     state->mail_8bit_header = FALSE;
  197     state->mail_mime_encoding = FALSE;
  198     state->maildir = FALSE;
  199     state->mailing_list = FALSE;
  200     state->mark_ignore_tags = FALSE;
  201     state->mark_saved_read = FALSE;
  202     state->mime_forward = FALSE;
  203     state->mime_types_to_save = FALSE;
  204     state->news_headers_to_display = FALSE;
  205     state->news_headers_to_not_display = FALSE;
  206     state->news_quote_format = FALSE;
  207     state->organization = FALSE;
  208     state->pos_first_unread = FALSE;
  209     state->post_8bit_header = FALSE;
  210     state->post_mime_encoding = FALSE;
  211     state->post_process_type = FALSE;
  212     state->post_process_view = FALSE;
  213 #ifndef DISABLE_PRINTING
  214     state->print_header = FALSE;
  215 #endif /* !DISABLE_PRINTING */
  216     state->process_only_unread = FALSE;
  217     state->prompt_followupto = FALSE;
  218     state->quick_kill_case = FALSE;
  219     state->quick_kill_expire = FALSE;
  220     state->quick_kill_header = FALSE;
  221     state->quick_kill_scope = FALSE;
  222     state->quick_select_case = FALSE;
  223     state->quick_select_expire = FALSE;
  224     state->quick_select_header = FALSE;
  225     state->quick_select_scope = FALSE;
  226     state->quote_chars = FALSE;
  227     state->savedir = FALSE;
  228     state->savefile = FALSE;
  229     state->show_author = FALSE;
  230     state->show_only_unread_arts = FALSE;
  231     state->show_signatures = FALSE;
  232     state->sigdashes = FALSE;
  233     state->sigfile = FALSE;
  234     state->signature_repost = FALSE;
  235     state->sort_article_type = FALSE;
  236     state->sort_threads_type = FALSE;
  237 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  238     state->suppress_soft_hyphens = FALSE;
  239 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  240     state->tex2iso_conv = FALSE;
  241     state->thread_articles = FALSE;
  242     state->thread_catchup_on_exit = FALSE;
  243     state->thread_format = FALSE;
  244     state->thread_perc = FALSE;
  245     state->trim_article_body = FALSE;
  246 #ifdef CHARSET_CONVERSION
  247     state->undeclared_charset = FALSE;
  248     state->mm_network_charset = FALSE;
  249 #endif /* CHARSET_CONVERSION */
  250     state->verbatim_handling = FALSE;
  251 #ifdef HAVE_COLOR
  252     state->extquote_handling = FALSE;
  253 #endif /* HAVE_COLOR */
  254     state->wrap_on_next_unread = FALSE;
  255     state->x_body = FALSE;
  256     state->x_comment_to = FALSE;
  257     state->x_headers = FALSE;
  258 }
  259 
  260 
  261 #define MATCH_BOOLEAN(pattern, type) \
  262     if (match_boolean(line, pattern, &flag)) { \
  263         num = (flag != FALSE); \
  264         set_attrib(type, scope, line, &num); \
  265         found = TRUE; \
  266         break; \
  267     }
  268 #define MATCH_INTEGER(pattern, type, maxval) \
  269     if (match_integer(line, pattern, &num, maxval)) { \
  270         set_attrib(type, scope, line, &num); \
  271         found = TRUE; \
  272         break; \
  273     }
  274 #define MATCH_STRING(pattern, type) \
  275     if (match_string(line, pattern, buf, sizeof(buf) - strlen(pattern))) { \
  276         set_attrib(type, scope, line, buf); \
  277         found = TRUE; \
  278         break; \
  279     }
  280 #define MATCH_LIST(pattern, type, table) \
  281     if (match_list(line, pattern, table, &num)) { \
  282         set_attrib(type, scope, line, &num); \
  283         found = TRUE; \
  284         break; \
  285     }
  286 #if !defined(CHARSET_CONVERSION) || !defined(HAVE_ISPELL) || defined(DISABLE_PRINTING)
  287 #   define SKIP_ITEM(pattern) \
  288         if (!strncmp(line, pattern, strlen(pattern))) { \
  289             found = TRUE; \
  290             break; \
  291         }
  292 #endif /* !CHARSET_CONVERSION || !HAVE_ISPELL || DISABLE_PRINTING */
  293 
  294 
  295 /*
  296  * read global/local attributes file
  297  */
  298 void
  299 read_attributes_file(
  300     t_bool global_file)
  301 {
  302     FILE *fp;
  303     char *file;
  304     char buf[LEN];
  305     char line[LEN];
  306     char scope[LEN];
  307     int i, num;
  308     struct t_version *upgrade = NULL;
  309     static t_bool startup = TRUE;
  310     t_bool flag, found = FALSE;
  311 
  312     if (!batch_mode || verbose)
  313         wait_message(0, _(txt_reading_attributes_file), (global_file ? _(txt_global) : ""));
  314     /*
  315      * Initialize global attributes even if there is no global file
  316      * These setting are used as the default for all groups unless overridden
  317      */
  318     if (global_file) {
  319         i = add_scope("_default_");
  320         scopes[i].global = TRUE;
  321         set_default_attributes(scopes[i].attribute, NULL, TRUE);
  322         build_news_headers_array(scopes[i].attribute, TRUE);
  323         build_news_headers_array(scopes[i].attribute, FALSE);
  324         file = global_attributes_file;
  325     } else {
  326         attrib_file_offset = 1;
  327         file = local_attributes_file;
  328     }
  329 
  330     if ((fp = fopen(file, "r")) != NULL) {
  331         scope[0] = '\0';
  332         /*
  333          * TODO: use tin_fgets() instead to handle long lines
  334          * (e.g. buggy translation)
  335          */
  336         while (fgets(line, (int) sizeof(line), fp) != NULL) {
  337             if (line[0] == '\n')
  338                 continue;
  339             if (line[0] == '#') {
  340                 if (!global_file) {
  341                     if (scope[0] == '\0')
  342                         attrib_file_offset++;
  343                     if (startup && upgrade == NULL && match_string(line, "# Group attributes file V", NULL, 0)) {
  344                         upgrade = check_upgrade(line, "# Group attributes file V", ATTRIBUTES_VERSION);
  345                         if (upgrade->state != RC_IGNORE)
  346                             upgrade_prompt_quit(upgrade, file); /* TODO: do something (more) useful here */
  347                     }
  348                 }
  349                 continue;
  350             }
  351 
  352             switch (my_tolower((unsigned char) line[0])) {
  353                 case 'a':
  354                     MATCH_BOOLEAN("add_posted_to_filter=", OPT_ATTRIB_ADD_POSTED_TO_FILTER);
  355                     MATCH_BOOLEAN("advertising=", OPT_ATTRIB_ADVERTISING);
  356                     MATCH_BOOLEAN("alternative_handling=", OPT_ATTRIB_ALTERNATIVE_HANDLING);
  357                     MATCH_BOOLEAN("ask_for_metamail=", OPT_ATTRIB_ASK_FOR_METAMAIL);
  358                     MATCH_INTEGER("auto_cc_bcc=", OPT_ATTRIB_AUTO_CC_BCC, AUTO_CC_BCC);
  359                     MATCH_BOOLEAN("auto_list_thread=", OPT_ATTRIB_AUTO_LIST_THREAD);
  360                     MATCH_BOOLEAN("auto_select=", OPT_ATTRIB_AUTO_SELECT);
  361                     break;
  362 
  363                 case 'b':
  364                     MATCH_BOOLEAN("batch_save=", OPT_ATTRIB_BATCH_SAVE);
  365                     break;
  366 
  367                 case 'd':
  368                     MATCH_STRING("date_format=", OPT_ATTRIB_DATE_FORMAT);
  369                     MATCH_BOOLEAN("delete_tmp_files=", OPT_ATTRIB_DELETE_TMP_FILES);
  370                     break;
  371 
  372                 case 'e':
  373                     MATCH_STRING("editor_format=", OPT_ATTRIB_EDITOR_FORMAT);
  374 #ifdef HAVE_COLOR
  375                     MATCH_BOOLEAN("extquote_handling=", OPT_ATTRIB_EXTQUOTE_HANDLING);
  376 #endif /* HAVE_COLOR */
  377 
  378                     break;
  379 
  380                 case 'f':
  381                     MATCH_STRING("fcc=", OPT_ATTRIB_FCC);
  382                     MATCH_STRING("followup_to=", OPT_ATTRIB_FOLLOWUP_TO);
  383                     MATCH_STRING("from=", OPT_ATTRIB_FROM);
  384                     break;
  385 
  386                 case 'g':
  387                     MATCH_BOOLEAN("group_catchup_on_exit=", OPT_ATTRIB_GROUP_CATCHUP_ON_EXIT);
  388                     MATCH_STRING("group_format=", OPT_ATTRIB_GROUP_FORMAT);
  389                     break;
  390 
  391                 case 'i':
  392 #ifdef HAVE_ISPELL
  393                     MATCH_STRING("ispell=", OPT_ATTRIB_ISPELL);
  394 #else
  395                     SKIP_ITEM("ispell=");
  396 #endif /* HAVE_ISPELL */
  397                     break;
  398 
  399                 case 'm':
  400                     MATCH_BOOLEAN("mail_8bit_header=", OPT_ATTRIB_MAIL_8BIT_HEADER);
  401                     MATCH_LIST("mail_mime_encoding=", OPT_ATTRIB_MAIL_MIME_ENCODING, txt_mime_encodings);
  402                     MATCH_STRING("maildir=", OPT_ATTRIB_MAILDIR);
  403                     MATCH_STRING("mailing_list=", OPT_ATTRIB_MAILING_LIST);
  404                     MATCH_BOOLEAN("mark_ignore_tags=", OPT_ATTRIB_MARK_IGNORE_TAGS);
  405                     MATCH_BOOLEAN("mark_saved_read=", OPT_ATTRIB_MARK_SAVED_READ);
  406                     MATCH_BOOLEAN("mime_forward=", OPT_ATTRIB_MIME_FORWARD);
  407                     MATCH_STRING("mime_types_to_save=", OPT_ATTRIB_MIME_TYPES_TO_SAVE);
  408 #ifdef CHARSET_CONVERSION
  409                     MATCH_LIST("mm_network_charset=", OPT_ATTRIB_MM_NETWORK_CHARSET, txt_mime_charsets);
  410 #else
  411                     SKIP_ITEM("mm_network_charset=");
  412 #endif /* CHARSET_CONVERSION */
  413                     break;
  414 
  415                 case 'n':
  416                     MATCH_STRING("news_headers_to_display=", OPT_ATTRIB_NEWS_HEADERS_TO_DISPLAY);
  417                     MATCH_STRING("news_headers_to_not_display=", OPT_ATTRIB_NEWS_HEADERS_TO_NOT_DISPLAY);
  418                     MATCH_STRING("news_quote_format=", OPT_ATTRIB_NEWS_QUOTE_FORMAT);
  419                     break;
  420 
  421                 case 'o':
  422                     MATCH_STRING("organization=", OPT_ATTRIB_ORGANIZATION);
  423                     break;
  424 
  425                 case 'p':
  426                     MATCH_BOOLEAN("pos_first_unread=", OPT_ATTRIB_POS_FIRST_UNREAD);
  427                     MATCH_BOOLEAN("post_8bit_header=", OPT_ATTRIB_POST_8BIT_HEADER);
  428                     MATCH_LIST("post_mime_encoding=", OPT_ATTRIB_POST_MIME_ENCODING, txt_mime_encodings);
  429                     MATCH_BOOLEAN("post_process_view=", OPT_ATTRIB_POST_PROCESS_VIEW);
  430                     MATCH_INTEGER("post_process_type=", OPT_ATTRIB_POST_PROCESS_TYPE, POST_PROC_YES);
  431 #ifndef DISABLE_PRINTING
  432                     MATCH_BOOLEAN("print_header=", OPT_ATTRIB_PRINT_HEADER);
  433 #else
  434                     SKIP_ITEM("print_header=");
  435 #endif /* !DISABLE_PRINTING */
  436                     MATCH_BOOLEAN("process_only_unread=", OPT_ATTRIB_PROCESS_ONLY_UNREAD);
  437                     MATCH_BOOLEAN("prompt_followupto=", OPT_ATTRIB_PROMPT_FOLLOWUPTO);
  438                     break;
  439 
  440                 case 'q':
  441                     MATCH_BOOLEAN("quick_kill_case=", OPT_ATTRIB_QUICK_KILL_CASE);
  442                     MATCH_BOOLEAN("quick_kill_expire=", OPT_ATTRIB_QUICK_KILL_EXPIRE);
  443                     MATCH_INTEGER("quick_kill_header=", OPT_ATTRIB_QUICK_KILL_HEADER, FILTER_LINES);
  444                     MATCH_STRING("quick_kill_scope=", OPT_ATTRIB_QUICK_KILL_SCOPE);
  445                     MATCH_BOOLEAN("quick_select_case=", OPT_ATTRIB_QUICK_SELECT_CASE);
  446                     MATCH_BOOLEAN("quick_select_expire=", OPT_ATTRIB_QUICK_SELECT_EXPIRE);
  447                     MATCH_INTEGER("quick_select_header=", OPT_ATTRIB_QUICK_SELECT_HEADER, FILTER_LINES);
  448                     MATCH_STRING("quick_select_scope=", OPT_ATTRIB_QUICK_SELECT_SCOPE);
  449                     if (match_string(line, "quote_chars=", buf, sizeof(buf))) {
  450                         if (upgrade && upgrade->file_version < 10010) { /* %s/%S changed to %I */
  451                             char *q = buf;
  452 
  453                             while (*q) {
  454                                 if (*q == '%' && (*(q + 1) == 's' || *(q + 1) == 'S'))
  455                                     *(++q) = 'I';
  456 
  457                                 q++;
  458                             }
  459                         }
  460                         quote_dash_to_space(buf);
  461                         set_attrib(OPT_ATTRIB_QUOTE_CHARS, scope, line, buf);
  462                         found = TRUE;
  463                         break;
  464                     }
  465                     break;
  466 
  467                 case 's':
  468                     MATCH_STRING("savedir=", OPT_ATTRIB_SAVEDIR);
  469                     MATCH_STRING("savefile=", OPT_ATTRIB_SAVEFILE);
  470                     if (match_string(line, "scope=", scope, sizeof(scope))) {
  471                         i = add_scope(scope);
  472                         scopes[i].global = global_file ? TRUE : FALSE;
  473                         found = TRUE;
  474                         break;
  475                     }
  476                     MATCH_INTEGER("show_author=", OPT_ATTRIB_SHOW_AUTHOR, SHOW_FROM_BOTH);
  477                     MATCH_BOOLEAN("show_only_unread_arts=", OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS);
  478                     MATCH_BOOLEAN("show_signatures=", OPT_ATTRIB_SHOW_SIGNATURES);
  479                     MATCH_BOOLEAN("sigdashes=", OPT_ATTRIB_SIGDASHES);
  480                     MATCH_BOOLEAN("signature_repost=", OPT_ATTRIB_SIGNATURE_REPOST);
  481                     MATCH_STRING("sigfile=", OPT_ATTRIB_SIGFILE);
  482                     MATCH_INTEGER("sort_article_type=", OPT_ATTRIB_SORT_ARTICLE_TYPE, SORT_ARTICLES_BY_LINES_ASCEND);
  483                     MATCH_INTEGER("sort_threads_type=", OPT_ATTRIB_SORT_THREADS_TYPE, SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND);
  484 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  485                     MATCH_BOOLEAN("suppress_soft_hyphens=", OPT_ATTRIB_SUPPRESS_SOFT_HYPHENS);
  486 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  487                     break;
  488 
  489                 case 't':
  490                     MATCH_BOOLEAN("tex2iso_conv=", OPT_ATTRIB_TEX2ISO_CONV);
  491                     MATCH_INTEGER("thread_articles=", OPT_ATTRIB_THREAD_ARTICLES, THREAD_MAX);
  492                     MATCH_BOOLEAN("thread_catchup_on_exit=", OPT_ATTRIB_THREAD_CATCHUP_ON_EXIT);
  493                     MATCH_STRING("thread_format=", OPT_ATTRIB_THREAD_FORMAT);
  494                     MATCH_INTEGER("thread_perc=", OPT_ATTRIB_THREAD_PERC, 100);
  495                     MATCH_INTEGER("trim_article_body=", OPT_ATTRIB_TRIM_ARTICLE_BODY, 7);
  496                     break;
  497 
  498                 case 'u':
  499 #ifdef CHARSET_CONVERSION
  500                     MATCH_STRING("undeclared_charset=", OPT_ATTRIB_UNDECLARED_CHARSET);
  501 #else
  502                     SKIP_ITEM("undeclared_charset=");
  503 #endif /* CHARSET_CONVERSION */
  504                     break;
  505 
  506                 case 'v':
  507                     MATCH_BOOLEAN("verbatim_handling=", OPT_ATTRIB_VERBATIM_HANDLING);
  508                     break;
  509 
  510                 case 'w':
  511                     MATCH_BOOLEAN("wrap_on_next_unread=", OPT_ATTRIB_WRAP_ON_NEXT_UNREAD);
  512                     break;
  513 
  514                 case 'x':
  515                     MATCH_STRING("x_body=", OPT_ATTRIB_X_BODY);
  516                     MATCH_BOOLEAN("x_comment_to=", OPT_ATTRIB_X_COMMENT_TO);
  517                     MATCH_STRING("x_headers=", OPT_ATTRIB_X_HEADERS);
  518                     break;
  519 
  520                 default:
  521                     break;
  522             }
  523 
  524             if (!global_file && upgrade && upgrade->state == RC_UPGRADE) {
  525                 int auto_cc_bcc;
  526                 int show_info;
  527                 t_bool auto_bcc = FALSE;
  528                 t_bool auto_cc = FALSE;
  529 
  530                 switch (my_tolower((unsigned char) line[0])) {
  531                     case 'a':
  532                         if (match_boolean(line, "auto_bcc=", &auto_bcc)) {
  533                             if (scopes[num_scope - 1].attribute->auto_cc_bcc & AUTO_CC)
  534                                 auto_cc_bcc = (auto_bcc ? AUTO_CC_BCC : AUTO_CC);
  535                             else
  536                                 auto_cc_bcc = (auto_bcc ? AUTO_BCC : 0);
  537                             set_attrib(OPT_ATTRIB_AUTO_CC_BCC, scope, line, &auto_cc_bcc);
  538                             found = TRUE;
  539                             break;
  540                         }
  541                         if (match_boolean(line, "auto_cc=", &auto_cc)) {
  542                             if (scopes[num_scope - 1].attribute->auto_cc_bcc & AUTO_BCC)
  543                                 auto_cc_bcc = (auto_cc ? AUTO_CC_BCC : AUTO_BCC);
  544                             else
  545                                 auto_cc_bcc = (auto_cc ? AUTO_CC : 0);
  546                             set_attrib(OPT_ATTRIB_AUTO_CC_BCC, scope, line, &auto_cc_bcc);
  547                             found = TRUE;
  548                             break;
  549                         }
  550                         /* option removed */
  551                         if (upgrade && upgrade->file_version < 10011) {
  552                             t_bool ignore;
  553 
  554                             if (match_boolean(line, "auto_save=", &ignore))
  555                                 found = TRUE;
  556                             break;
  557                         }
  558                         break;
  559 
  560                     case 'p':
  561                         MATCH_INTEGER("post_proc_type=", OPT_ATTRIB_POST_PROCESS_TYPE, POST_PROC_YES);
  562                         break;
  563 
  564                     case 's':
  565                         if (match_integer(line, "show_info=", &show_info, 3)) {
  566                             char *gbuf = my_malloc(23);
  567                             char *tbuf = my_malloc(23);
  568 
  569                             switch (show_info) {
  570                                 case 0:
  571                                     strcpy(gbuf, "%n %m %R  %s  %F");
  572                                     strcpy(tbuf, "%n %m  %T  %F");
  573                                     break;
  574 
  575                                 case 2:
  576                                     strcpy(gbuf, "%n %m %R %S  %s  %F");
  577                                     strcpy(tbuf, "%n %m  [%S]  %T  %F");
  578                                     break;
  579 
  580                                 case 3:
  581                                     strcpy(gbuf, "%n %m %R %L %S  %s  %F");
  582                                     strcpy(tbuf, "%n %m  [%L,%S]  %T  %F");
  583                                     break;
  584 
  585                                 default:
  586                                     strcpy(gbuf, DEFAULT_GROUP_FORMAT);
  587                                     strcpy(tbuf, DEFAULT_THREAD_FORMAT);
  588                                     break;
  589                             }
  590                             set_attrib(OPT_ATTRIB_GROUP_FORMAT, scope, line, gbuf);
  591                             set_attrib(OPT_ATTRIB_THREAD_FORMAT, scope, line, tbuf);
  592                             free(gbuf);
  593                             free(tbuf);
  594                             found = TRUE;
  595                             break;
  596                         }
  597                         /*
  598                          * previous versions has always passed groupname to external
  599                          * commands, now we look for %G
  600                          *
  601                          * 8 == sizeof("sigfile=")
  602                          */
  603                         if (match_string(line, "sigfile=", buf, sizeof(buf) - 8) && buf[0] == '!') {
  604                             /* just append %G if ATTRIBUTES_VERSION <= 1.0.8 */
  605                             if (upgrade && upgrade->file_version < 10009) {
  606                                 char *newbuf = my_malloc(sizeof(buf) - 8 + 4);
  607 
  608                                 sprintf(newbuf, "%s %s", buf, "%G");
  609                                 set_attrib(OPT_ATTRIB_SIGFILE, scope, line, newbuf);
  610                                 free(newbuf);
  611                             }
  612                             break;
  613                         }
  614                         MATCH_BOOLEAN("show_only_unread=", OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS);
  615                         MATCH_INTEGER("sort_art_type=", OPT_ATTRIB_SORT_ARTICLE_TYPE, SORT_ARTICLES_BY_LINES_ASCEND);
  616                         break;
  617 
  618                     case 't':
  619                         MATCH_INTEGER("thread_arts=", OPT_ATTRIB_THREAD_ARTICLES, THREAD_MAX);
  620                         break;
  621 
  622                     default:
  623                         break;
  624                 }
  625             }
  626 
  627             if (found)
  628                 found = FALSE;
  629             else {
  630                 /* TODO: even without DEBUG? */
  631                 error_message(1, _(txt_bad_attrib), line);
  632 #ifdef DEBUG
  633                 if (debug & (DEBUG_ATTRIB))
  634                     debug_print_file("ATTRIBUTES", txt_bad_attrib, line);
  635 #endif /* DEBUG */
  636             }
  637         }
  638         fclose(fp);
  639 
  640         /*
  641          * TODO: do something useful for the other cases
  642          */
  643         if (!global_file && upgrade && upgrade->state == RC_UPGRADE)
  644             write_attributes_file(file);
  645 
  646         FreeAndNull(upgrade);
  647 
  648     } else if (!global_file && startup) {
  649         /* no local attributes file, add some useful defaults and write file */
  650 
  651         add_scope("*");
  652         snprintf(buf, sizeof(buf), "%s", "~/.tin/headers");
  653         set_attrib(OPT_ATTRIB_X_HEADERS, "*", "", buf);
  654 
  655         add_scope("*sources*");
  656         num = POST_PROC_SHAR;
  657         set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*sources*", "", &num);
  658 
  659         add_scope("*binaries*");
  660         num = POST_PROC_YES;
  661         set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*binaries*", "", &num);
  662         num = FALSE;
  663         set_attrib(OPT_ATTRIB_TEX2ISO_CONV, "*binaries*", "", &num);
  664         num = TRUE;
  665         set_attrib(OPT_ATTRIB_DELETE_TMP_FILES, "*binaries*", "", &num);
  666         snprintf(buf, sizeof(buf), "%s", "poster");
  667         set_attrib(OPT_ATTRIB_FOLLOWUP_TO, "*binaries*", "", buf);
  668 
  669         write_attributes_file(file);
  670     }
  671     if (!global_file && startup)
  672         startup = FALSE;
  673 #ifdef DEBUG
  674     if (!global_file)
  675         dump_scopes("SCOPES-R");
  676 #endif /* DEBUG */
  677 }
  678 
  679 
  680 #define SET_STRING(string) \
  681     FreeIfNeeded(curr_scope->attribute->string); \
  682     curr_scope->attribute->string = my_strdup((char *) data); \
  683     curr_scope->state->string = TRUE; \
  684     break
  685 
  686 #define SET_INTEGER(value) \
  687     curr_scope->attribute->value = CAST_BITS(*((int *) data), value); \
  688     curr_scope->state->value = TRUE; \
  689     break
  690 
  691 #define SET_BOOLEAN(value) \
  692     curr_scope->attribute->value = CAST_BOOL(*((int *) data)); \
  693     curr_scope->state->value = TRUE; \
  694     break
  695 
  696 static void
  697 set_attrib(
  698     int type,
  699     const char *scope,
  700     const char *line,
  701     void *data)
  702 {
  703     struct t_scope *curr_scope;
  704 
  705     if (scope == NULL || *scope == '\0') {  /* No active scope set yet */
  706         error_message(2, _(txt_attrib_no_scope), line);
  707 #ifdef DEBUG
  708         if (debug & DEBUG_ATTRIB)
  709             debug_print_file("ATTRIBUTES", txt_attrib_no_scope, line);
  710 #endif /* DEBUG */
  711         return;
  712     }
  713 
  714     if (num_scope > 1) {
  715         curr_scope = &scopes[num_scope - 1];
  716         /*
  717          * Now set the required attribute
  718          */
  719         switch (type) {
  720             case OPT_ATTRIB_MAILDIR:
  721                 SET_STRING(maildir);
  722 
  723             case OPT_ATTRIB_SAVEDIR:
  724                 SET_STRING(savedir);
  725 
  726             case OPT_ATTRIB_SAVEFILE:
  727                 SET_STRING(savefile);
  728 
  729             case OPT_ATTRIB_ORGANIZATION:
  730                 SET_STRING(organization);
  731 
  732             case OPT_ATTRIB_FROM:
  733                 SET_STRING(from);
  734 
  735             case OPT_ATTRIB_SIGFILE:
  736                 SET_STRING(sigfile);
  737 
  738             case OPT_ATTRIB_FOLLOWUP_TO:
  739                 SET_STRING(followup_to);
  740 
  741             case OPT_ATTRIB_ADD_POSTED_TO_FILTER:
  742                 SET_BOOLEAN(add_posted_to_filter);
  743 
  744             case OPT_ATTRIB_ADVERTISING:
  745                 SET_BOOLEAN(advertising);
  746 
  747             case OPT_ATTRIB_ALTERNATIVE_HANDLING:
  748                 SET_BOOLEAN(alternative_handling);
  749 
  750             case OPT_ATTRIB_ASK_FOR_METAMAIL:
  751                 SET_BOOLEAN(ask_for_metamail);
  752 
  753             case OPT_ATTRIB_AUTO_CC_BCC:
  754                 SET_INTEGER(auto_cc_bcc);
  755 
  756             case OPT_ATTRIB_AUTO_LIST_THREAD:
  757                 SET_BOOLEAN(auto_list_thread);
  758 
  759             case OPT_ATTRIB_AUTO_SELECT:
  760                 SET_BOOLEAN(auto_select);
  761 
  762             case OPT_ATTRIB_BATCH_SAVE:
  763                 SET_BOOLEAN(batch_save);
  764 
  765             case OPT_ATTRIB_DATE_FORMAT:
  766                 SET_STRING(date_format);
  767 
  768             case OPT_ATTRIB_DELETE_TMP_FILES:
  769                 SET_BOOLEAN(delete_tmp_files);
  770 
  771             case OPT_ATTRIB_EDITOR_FORMAT:
  772                 SET_STRING(editor_format);
  773 
  774             case OPT_ATTRIB_GROUP_CATCHUP_ON_EXIT:
  775                 SET_BOOLEAN(group_catchup_on_exit);
  776 
  777             case OPT_ATTRIB_GROUP_FORMAT:
  778                 SET_STRING(group_format);
  779 
  780             case OPT_ATTRIB_MAIL_8BIT_HEADER:
  781                 SET_BOOLEAN(mail_8bit_header);
  782 
  783             case OPT_ATTRIB_MAIL_MIME_ENCODING:
  784                 SET_INTEGER(mail_mime_encoding);
  785 
  786             case OPT_ATTRIB_MARK_IGNORE_TAGS:
  787                 SET_BOOLEAN(mark_ignore_tags);
  788 
  789             case OPT_ATTRIB_MARK_SAVED_READ:
  790                 SET_BOOLEAN(mark_saved_read);
  791 
  792             case OPT_ATTRIB_NEWS_HEADERS_TO_DISPLAY:
  793                 FreeIfNeeded(curr_scope->attribute->news_headers_to_display);
  794                 curr_scope->attribute->news_headers_to_display = my_strdup((char *) data);
  795                 build_news_headers_array(curr_scope->attribute, TRUE);
  796                 curr_scope->state->news_headers_to_display = TRUE;
  797                 break;
  798 
  799             case OPT_ATTRIB_NEWS_HEADERS_TO_NOT_DISPLAY:
  800                 FreeIfNeeded(curr_scope->attribute->news_headers_to_not_display);
  801                 curr_scope->attribute->news_headers_to_not_display = my_strdup((char *) data);
  802                 build_news_headers_array(curr_scope->attribute, FALSE);
  803                 curr_scope->state->news_headers_to_not_display = TRUE;
  804                 break;
  805 
  806             case OPT_ATTRIB_POS_FIRST_UNREAD:
  807                 SET_BOOLEAN(pos_first_unread);
  808 
  809             case OPT_ATTRIB_POST_8BIT_HEADER:
  810                 SET_BOOLEAN(post_8bit_header);
  811 
  812             case OPT_ATTRIB_POST_MIME_ENCODING:
  813                 SET_INTEGER(post_mime_encoding);
  814 
  815             case OPT_ATTRIB_POST_PROCESS_VIEW:
  816                 SET_BOOLEAN(post_process_view);
  817 
  818 #ifndef DISABLE_PRINTING
  819             case OPT_ATTRIB_PRINT_HEADER:
  820                 SET_BOOLEAN(print_header);
  821 #endif /* !DISABLE_PRINTING */
  822 
  823             case OPT_ATTRIB_PROCESS_ONLY_UNREAD:
  824                 SET_BOOLEAN(process_only_unread);
  825 
  826             case OPT_ATTRIB_PROMPT_FOLLOWUPTO:
  827                 SET_BOOLEAN(prompt_followupto);
  828 
  829 #ifdef HAVE_COLOR
  830             case OPT_ATTRIB_EXTQUOTE_HANDLING:
  831                 SET_BOOLEAN(extquote_handling);
  832 #endif /* HAVE_COLOR */
  833 
  834             case OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS:
  835                 SET_BOOLEAN(show_only_unread_arts);
  836 
  837             case OPT_ATTRIB_SIGDASHES:
  838                 SET_BOOLEAN(sigdashes);
  839 
  840             case OPT_ATTRIB_SIGNATURE_REPOST:
  841                 SET_BOOLEAN(signature_repost);
  842 
  843             case OPT_ATTRIB_THREAD_ARTICLES:
  844                 SET_INTEGER(thread_articles);
  845 
  846             case OPT_ATTRIB_THREAD_CATCHUP_ON_EXIT:
  847                 SET_BOOLEAN(thread_catchup_on_exit);
  848 
  849             case OPT_ATTRIB_THREAD_FORMAT:
  850                 SET_STRING(thread_format);
  851 
  852             case OPT_ATTRIB_THREAD_PERC:
  853                 SET_INTEGER(thread_perc);
  854 
  855             case OPT_ATTRIB_SHOW_AUTHOR:
  856                 SET_INTEGER(show_author);
  857 
  858             case OPT_ATTRIB_SHOW_SIGNATURES:
  859                 SET_BOOLEAN(show_signatures);
  860 
  861 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  862             case OPT_ATTRIB_SUPPRESS_SOFT_HYPHENS:
  863                 SET_BOOLEAN(suppress_soft_hyphens);
  864 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  865 
  866             case OPT_ATTRIB_TRIM_ARTICLE_BODY:
  867                 SET_INTEGER(trim_article_body);
  868 
  869             case OPT_ATTRIB_VERBATIM_HANDLING:
  870                 SET_BOOLEAN(verbatim_handling);
  871 
  872             case OPT_ATTRIB_WRAP_ON_NEXT_UNREAD:
  873                 SET_BOOLEAN(wrap_on_next_unread);
  874 
  875             case OPT_ATTRIB_SORT_ARTICLE_TYPE:
  876                 SET_INTEGER(sort_article_type);
  877 
  878             case OPT_ATTRIB_SORT_THREADS_TYPE:
  879                 SET_INTEGER(sort_threads_type);
  880 
  881             case OPT_ATTRIB_POST_PROCESS_TYPE:
  882                 SET_INTEGER(post_process_type);
  883 
  884             case OPT_ATTRIB_QUICK_KILL_HEADER:
  885                 SET_INTEGER(quick_kill_header);
  886 
  887             case OPT_ATTRIB_QUICK_KILL_SCOPE:
  888                 SET_STRING(quick_kill_scope);
  889 
  890             case OPT_ATTRIB_QUICK_KILL_EXPIRE:
  891                 SET_BOOLEAN(quick_kill_expire);
  892 
  893             case OPT_ATTRIB_QUICK_KILL_CASE:
  894                 SET_BOOLEAN(quick_kill_case);
  895 
  896             case OPT_ATTRIB_QUICK_SELECT_HEADER:
  897                 SET_INTEGER(quick_select_header);
  898 
  899             case OPT_ATTRIB_QUICK_SELECT_SCOPE:
  900                 SET_STRING(quick_select_scope);
  901 
  902             case OPT_ATTRIB_QUICK_SELECT_EXPIRE:
  903                 SET_BOOLEAN(quick_select_expire);
  904 
  905             case OPT_ATTRIB_QUICK_SELECT_CASE:
  906                 SET_BOOLEAN(quick_select_case);
  907 
  908             case OPT_ATTRIB_MAILING_LIST:
  909                 SET_STRING(mailing_list);
  910 
  911 #ifdef CHARSET_CONVERSION
  912             case OPT_ATTRIB_MM_NETWORK_CHARSET:
  913                 SET_INTEGER(mm_network_charset);
  914 
  915             case OPT_ATTRIB_UNDECLARED_CHARSET:
  916                 SET_STRING(undeclared_charset);
  917 #endif /* CHARSET_CONVERSION */
  918 
  919             case OPT_ATTRIB_X_HEADERS:
  920                 SET_STRING(x_headers);
  921 
  922             case OPT_ATTRIB_X_BODY:
  923                 SET_STRING(x_body);
  924 
  925             case OPT_ATTRIB_X_COMMENT_TO:
  926                 SET_BOOLEAN(x_comment_to);
  927 
  928             case OPT_ATTRIB_FCC:
  929                 SET_STRING(fcc);
  930 
  931             case OPT_ATTRIB_NEWS_QUOTE_FORMAT:
  932                 SET_STRING(news_quote_format);
  933 
  934             case OPT_ATTRIB_QUOTE_CHARS:
  935                 SET_STRING(quote_chars);
  936 
  937             case OPT_ATTRIB_MIME_TYPES_TO_SAVE:
  938                 SET_STRING(mime_types_to_save);
  939 
  940             case OPT_ATTRIB_MIME_FORWARD:
  941                 SET_BOOLEAN(mime_forward);
  942 
  943 #ifdef HAVE_ISPELL
  944             case OPT_ATTRIB_ISPELL:
  945                 SET_STRING(ispell);
  946 #endif /* HAVE_ISPELL */
  947 
  948             case OPT_ATTRIB_TEX2ISO_CONV:
  949                 SET_BOOLEAN(tex2iso_conv);
  950 
  951             default:
  952                 break;
  953         }
  954     }
  955 }
  956 
  957 
  958 /*
  959  * Insert a new scope entry into scopes[] and return the index.
  960  */
  961 int
  962 add_scope(
  963     const char *scope)
  964 {
  965     if (!scope || !*scope)
  966         return 0;
  967 
  968     if ((num_scope >= max_scope) || (num_scope < 0) || (scopes == NULL))
  969         expand_scope();
  970 
  971     scopes[num_scope].scope = my_strdup(scope);
  972     scopes[num_scope].attribute = my_malloc(sizeof(struct t_attribute));
  973     set_default_attributes(scopes[num_scope].attribute, NULL, FALSE);
  974     scopes[num_scope].state = my_malloc(sizeof(struct t_attribute_state));
  975     set_default_state(scopes[num_scope].state);
  976     scopes[num_scope].global = FALSE;
  977     return num_scope++;
  978 }
  979 
  980 
  981 #define SET_ATTRIB(attr) do { \
  982         if (curr_scope->state->attr) \
  983             group->attribute->attr = curr_scope->attribute->attr; \
  984     } while (0)
  985 
  986 
  987 /*
  988  * Set the attributes of all groups
  989  */
  990 void
  991 assign_attributes_to_groups(
  992     void)
  993 {
  994     struct t_group *group;
  995     struct t_scope *default_scope, *curr_scope;
  996     t_bool found;
  997     int i, j;
  998     long processed = 0L;
  999 #ifdef CHARSET_CONVERSION
 1000     t_bool is_7bit;
 1001 #endif /* CHARSET_CONVERSION */
 1002 
 1003     if (!batch_mode || verbose)
 1004         wait_message(0, _("Processing attributes... ")); /* TODO: -> lang.c */
 1005 
 1006     default_scope = &scopes[0];
 1007     for_each_group(i) {
 1008         if (++processed % (MODULO_COUNT_NUM) == 0)
 1009             spin_cursor();
 1010         group = &active[i];
 1011         found = FALSE;
 1012         for (j = 1; j < num_scope; j++) {
 1013             curr_scope = &scopes[j];
 1014             if (match_group_list(group->name, curr_scope->scope)) {
 1015                 if (group->attribute == NULL || group->attribute == default_scope->attribute) {
 1016                     group->attribute = my_malloc(sizeof(struct t_attribute));
 1017                     set_default_attributes(group->attribute, default_scope->attribute, FALSE);
 1018                     found = TRUE;
 1019                 }
 1020                 if (!found) {
 1021                     set_default_attributes(group->attribute, default_scope->attribute, FALSE);
 1022                     found = TRUE;
 1023                 }
 1024                 SET_ATTRIB(maildir);
 1025                 SET_ATTRIB(savedir);
 1026                 SET_ATTRIB(savefile);
 1027                 SET_ATTRIB(sigfile);
 1028                 SET_ATTRIB(group_format);
 1029                 SET_ATTRIB(thread_format);
 1030                 SET_ATTRIB(date_format);
 1031                 SET_ATTRIB(editor_format);
 1032                 SET_ATTRIB(organization);
 1033                 SET_ATTRIB(fcc);
 1034                 SET_ATTRIB(followup_to);
 1035                 SET_ATTRIB(mailing_list);
 1036                 SET_ATTRIB(x_headers);
 1037                 SET_ATTRIB(x_body);
 1038                 SET_ATTRIB(from);
 1039                 SET_ATTRIB(news_quote_format);
 1040                 SET_ATTRIB(quote_chars);
 1041                 SET_ATTRIB(mime_types_to_save);
 1042 #ifdef HAVE_ISPELL
 1043                 SET_ATTRIB(ispell);
 1044 #endif /* HAVE_ISPELL */
 1045 #ifdef CHARSET_CONVERSION
 1046                 SET_ATTRIB(mm_network_charset);
 1047                 SET_ATTRIB(undeclared_charset);
 1048 #endif /* CHARSET_CONVERSION */
 1049                 SET_ATTRIB(quick_kill_scope);
 1050                 SET_ATTRIB(quick_kill_header);
 1051                 SET_ATTRIB(quick_kill_case);
 1052                 SET_ATTRIB(quick_kill_expire);
 1053                 SET_ATTRIB(quick_select_scope);
 1054                 SET_ATTRIB(quick_select_header);
 1055                 SET_ATTRIB(quick_select_case);
 1056                 SET_ATTRIB(quick_select_expire);
 1057                 SET_ATTRIB(show_only_unread_arts);
 1058                 SET_ATTRIB(thread_articles);
 1059                 SET_ATTRIB(thread_catchup_on_exit);
 1060                 SET_ATTRIB(thread_perc);
 1061                 SET_ATTRIB(sort_article_type);
 1062                 SET_ATTRIB(sort_threads_type);
 1063                 SET_ATTRIB(show_author);
 1064                 SET_ATTRIB(show_signatures);
 1065 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1066                 SET_ATTRIB(suppress_soft_hyphens);
 1067 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1068                 SET_ATTRIB(trim_article_body);
 1069                 SET_ATTRIB(verbatim_handling);
 1070 #ifdef HAVE_COLOR
 1071                 SET_ATTRIB(extquote_handling);
 1072 #endif /* HAVE_COLOR */
 1073                 SET_ATTRIB(wrap_on_next_unread);
 1074                 SET_ATTRIB(add_posted_to_filter);
 1075                 SET_ATTRIB(advertising);
 1076                 SET_ATTRIB(alternative_handling);
 1077                 SET_ATTRIB(ask_for_metamail);
 1078                 SET_ATTRIB(auto_cc_bcc);
 1079                 SET_ATTRIB(auto_list_thread);
 1080                 SET_ATTRIB(auto_select);
 1081                 SET_ATTRIB(batch_save);
 1082                 SET_ATTRIB(delete_tmp_files);
 1083                 SET_ATTRIB(group_catchup_on_exit);
 1084                 SET_ATTRIB(mail_8bit_header);
 1085                 SET_ATTRIB(mail_mime_encoding);
 1086                 SET_ATTRIB(mark_ignore_tags);
 1087                 SET_ATTRIB(mark_saved_read);
 1088                 if (curr_scope->state->news_headers_to_display)
 1089                     group->attribute->headers_to_display = curr_scope->attribute->headers_to_display;
 1090                 if (curr_scope->state->news_headers_to_not_display)
 1091                     group->attribute->headers_to_not_display = curr_scope->attribute->headers_to_not_display;
 1092                 SET_ATTRIB(pos_first_unread);
 1093                 SET_ATTRIB(post_8bit_header);
 1094                 SET_ATTRIB(post_mime_encoding);
 1095                 SET_ATTRIB(post_process_view);
 1096                 SET_ATTRIB(post_process_type);
 1097 #ifndef DISABLE_PRINTING
 1098                 SET_ATTRIB(print_header);
 1099 #endif /* !DISABLE_PRINTING */
 1100                 SET_ATTRIB(process_only_unread);
 1101                 SET_ATTRIB(prompt_followupto);
 1102                 SET_ATTRIB(sigdashes);
 1103                 SET_ATTRIB(signature_repost);
 1104                 SET_ATTRIB(x_comment_to);
 1105                 SET_ATTRIB(tex2iso_conv);
 1106                 SET_ATTRIB(mime_forward);
 1107             }
 1108         }
 1109         if (found) {
 1110             /*
 1111              * sort out conflicting settings
 1112              */
 1113 #ifdef CHARSET_CONVERSION
 1114             /*
 1115              * check if we have a 7bit charset but a !7bit encoding
 1116              * or a 8bit charset but a !8bit encoding, update encoding if needed
 1117              */
 1118             is_7bit = FALSE;
 1119             for (j = 0; txt_mime_7bit_charsets[j] != NULL; j++) {
 1120                 if (!strcasecmp(txt_mime_charsets[group->attribute->mm_network_charset], txt_mime_7bit_charsets[j])) {
 1121                     is_7bit = TRUE;
 1122                     break;
 1123                 }
 1124             }
 1125             if (is_7bit) {
 1126                 group->attribute->mail_mime_encoding = group->attribute->post_mime_encoding = MIME_ENCODING_7BIT;
 1127             } else {
 1128                 if (group->attribute->mail_mime_encoding == MIME_ENCODING_7BIT)
 1129                     group->attribute->mail_mime_encoding = MIME_ENCODING_QP;
 1130                 if (group->attribute->post_mime_encoding == MIME_ENCODING_7BIT)
 1131                     group->attribute->post_mime_encoding = MIME_ENCODING_8BIT;
 1132             }
 1133 #endif /* CHARSET_CONVERSION */
 1134             /* do not use 8 bit headers if mime encoding is not 8bit */
 1135             if (group->attribute->mail_mime_encoding != MIME_ENCODING_8BIT)
 1136                 group->attribute->mail_8bit_header = FALSE;
 1137             if (group->attribute->post_mime_encoding != MIME_ENCODING_8BIT)
 1138                 group->attribute->post_8bit_header = FALSE;
 1139         } else {
 1140             if (group->attribute && !group->attribute->global)
 1141                 free(group->attribute);
 1142             group->attribute = default_scope->attribute;
 1143         }
 1144     }
 1145 #ifdef DEBUG
 1146     dump_attributes();
 1147 #   if 0
 1148     debug_print_filter_attributes();
 1149 #   endif /* 0 */
 1150 #endif /* DEBUG */
 1151 
 1152     if (!batch_mode || verbose)
 1153         my_fputc('\n', stdout);
 1154 
 1155     if (!cmd_line && !batch_mode)
 1156         clear_message();
 1157 }
 1158 
 1159 
 1160 /*
 1161  * (re)build scope->headers_to_[not_]display array
 1162  */
 1163 void
 1164 build_news_headers_array(
 1165     struct t_attribute *scope,
 1166     t_bool header_to_display)
 1167 {
 1168     if (header_to_display) {
 1169         if (scope->headers_to_display == NULL)
 1170             scope->headers_to_display = my_malloc(sizeof(struct t_newsheader));
 1171         else {
 1172             if (scope->headers_to_display->header)
 1173                 FreeIfNeeded(*scope->headers_to_display->header);
 1174             FreeIfNeeded(scope->headers_to_display->header);
 1175         }
 1176         scope->headers_to_display->header = ulBuildArgv(scope->news_headers_to_display, &scope->headers_to_display->num);
 1177     } else {
 1178         if (scope->headers_to_not_display == NULL)
 1179             scope->headers_to_not_display = my_malloc(sizeof(struct t_newsheader));
 1180         else {
 1181             if (scope->headers_to_not_display->header)
 1182                 FreeIfNeeded(*scope->headers_to_not_display->header);
 1183             FreeIfNeeded(scope->headers_to_not_display->header);
 1184         }
 1185         scope->headers_to_not_display->header = ulBuildArgv(scope->news_headers_to_not_display, &scope->headers_to_not_display->num);
 1186     }
 1187 }
 1188 
 1189 
 1190 /*
 1191  * Save the scope attributes from scopes[] to ~/.tin/attributes
 1192  */
 1193 void
 1194 write_attributes_file(
 1195     const char *file)
 1196 {
 1197     FILE *fp;
 1198     char *new_file;
 1199     int i;
 1200     long fpos;
 1201 
 1202     if ((batch_mode || no_write || num_scope < 1) && file_size(file) != -1L)
 1203         return;
 1204 
 1205     new_file = get_tmpfilename(file);
 1206 
 1207     if ((fp = fopen(new_file, "w+")) == NULL) {
 1208         error_message(2, _(txt_filesystem_full_backup), ATTRIBUTES_FILE);
 1209         free(new_file);
 1210         return;
 1211     }
 1212 
 1213     wait_message(0, _(txt_writing_attributes_file));
 1214 
 1215 #ifdef DEBUG
 1216     dump_scopes("SCOPES-W");
 1217 #endif /* DEBUG */
 1218 
 1219     /*
 1220      * TODO: sort in a useful order
 1221      *       move strings to lang.c
 1222      */
 1223     fprintf(fp, "# Group attributes file V%s for the TIN newsreader\n", ATTRIBUTES_VERSION);
 1224     fprintf(fp, _("# Do not edit this comment block\n#\n"));
 1225     fprintf(fp, _("#  scope=STRING (eg. alt.*,!alt.bin*) [mandatory]\n"));
 1226     fprintf(fp, _("#  add_posted_to_filter=ON/OFF\n"));
 1227     fprintf(fp, _("#  advertising=ON/OFF\n"));
 1228     fprintf(fp, _("#  alternative_handling=ON/OFF\n"));
 1229     fprintf(fp, _("#  ask_for_metamail=ON/OFF\n"));
 1230     fprintf(fp, _("#  auto_cc_bcc=NUM\n"));
 1231     fprintf(fp, _("#    0=No, 1=Cc, 2=Bcc, 3=Cc and Bcc\n"));
 1232     fprintf(fp, _("#  auto_list_thread=ON/OFF\n"));
 1233     fprintf(fp, _("#  auto_select=ON/OFF\n"));
 1234     fprintf(fp, _("#  batch_save=ON/OFF\n"));
 1235     fprintf(fp, _("#  date_format=STRING (eg. %%a, %%d %%b %%Y %%H:%%M:%%S)\n"));
 1236     fprintf(fp, _("#  delete_tmp_files=ON/OFF\n"));
 1237     fprintf(fp, _("#  editor_format=STRING (eg. %%E +%%N %%F)\n"));
 1238     fprintf(fp, _("#  fcc=STRING (eg. =mailbox)\n"));
 1239     fprintf(fp, _("#  followup_to=STRING\n"));
 1240     fprintf(fp, _("#  from=STRING (just append wanted From:-line, don't use quotes)\n"));
 1241     fprintf(fp, _("#  group_catchup_on_exit=ON/OFF\n"));
 1242     fprintf(fp, _("#  group_format=STRING (eg. %%n %%m %%R %%L  %%s  %%F)\n"));
 1243     fprintf(fp, _("#  mail_8bit_header=ON/OFF\n"));
 1244     fprintf(fp, _("#  mail_mime_encoding=supported_encoding"));
 1245     for (i = 0; txt_mime_encodings[i] != NULL; i++) {
 1246         if (!(i % 5))
 1247             fprintf(fp, "\n#    ");
 1248         fprintf(fp, "%s, ", txt_mime_encodings[i]);
 1249     }
 1250     fprintf(fp, "\n");
 1251 #ifdef HAVE_ISPELL
 1252     fprintf(fp, _("#  ispell=STRING\n"));
 1253 #endif /* HAVE_ISPELL */
 1254     fprintf(fp, _("#  maildir=STRING (eg. ~/Mail)\n"));
 1255     fprintf(fp, _("#  mailing_list=STRING (eg. majordomo@example.org)\n"));
 1256     fprintf(fp, _("#  mime_types_to_save=STRING (eg. image/*,!image/bmp)\n"));
 1257     fprintf(fp, _("#  mark_ignore_tags=ON/OFF\n"));
 1258     fprintf(fp, _("#  mark_saved_read=ON/OFF\n"));
 1259     fprintf(fp, _("#  mime_forward=ON/OFF\n"));
 1260 #ifdef CHARSET_CONVERSION
 1261     fprintf(fp, _("#  mm_network_charset=supported_charset"));
 1262     for (i = 0; txt_mime_charsets[i] != NULL; i++) {
 1263         if (!(i % 5)) /* start new line */
 1264             fprintf(fp, "\n#    ");
 1265         fprintf(fp, "%s, ", txt_mime_charsets[i]);
 1266     }
 1267     fprintf(fp, "\n");
 1268     fprintf(fp, _("#  undeclared_charset=STRING (default is US-ASCII)\n"));
 1269 #endif /* CHARSET_CONVERSION */
 1270     fprintf(fp, _("#  news_headers_to_display=STRING\n"));
 1271     fprintf(fp, _("#  news_headers_to_not_display=STRING\n"));
 1272     fprintf(fp, _("#  news_quote_format=STRING\n"));
 1273     fprintf(fp, _("#  organization=STRING (if beginning with '/' read from file)\n"));
 1274     fprintf(fp, _("#  pos_first_unread=ON/OFF\n"));
 1275     fprintf(fp, _("#  post_8bit_header=ON/OFF\n"));
 1276     fprintf(fp, _("#  post_mime_encoding=supported_encoding"));
 1277     for (i = 0; txt_mime_encodings[i] != NULL; i++) {
 1278         if (!(i % 5))
 1279             fprintf(fp, "\n#    ");
 1280         fprintf(fp, "%s, ", txt_mime_encodings[i]);
 1281     }
 1282     fprintf(fp, "\n");
 1283     fprintf(fp, _("#  post_process_type=NUM\n"));
 1284     fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
 1285         POST_PROC_NO, _(txt_post_process_types[POST_PROC_NO]),
 1286         POST_PROC_SHAR, _(txt_post_process_types[POST_PROC_SHAR]),
 1287         POST_PROC_YES, _(txt_post_process_types[POST_PROC_YES]));
 1288     fprintf(fp, _("#  post_process_view=ON/OFF\n"));
 1289     fprintf(fp, _("#  quick_kill_scope=STRING (e.g. talk.*)\n"));
 1290     fprintf(fp, _("#  quick_kill_expire=ON/OFF\n"));
 1291     fprintf(fp, _("#  quick_kill_case=ON/OFF\n"));
 1292     fprintf(fp, _("#  quick_kill_header=NUM\n"));
 1293     fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
 1294     fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
 1295     fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
 1296     fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
 1297     fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
 1298     fprintf(fp, _("#  quick_select_scope=STRING\n"));
 1299     fprintf(fp, _("#  quick_select_expire=ON/OFF\n"));
 1300     fprintf(fp, _("#  quick_select_case=ON/OFF\n"));
 1301     fprintf(fp, _("#  quick_select_header=NUM\n"));
 1302     fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
 1303     fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
 1304     fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
 1305     fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
 1306     fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
 1307     fprintf(fp, _("#  quote_chars=STRING (%%I for initials)\n"));
 1308 #ifndef DISABLE_PRINTING
 1309     fprintf(fp, _("#  print_header=ON/OFF\n"));
 1310 #endif /* !DISABLE_PRINTING */
 1311     fprintf(fp, _("#  process_only_unread=ON/OFF\n"));
 1312     fprintf(fp, _("#  prompt_followupto=ON/OFF\n"));
 1313     fprintf(fp, _("#  savedir=STRING (eg. ~user/News)\n"));
 1314     fprintf(fp, _("#  savefile=STRING (eg. =linux)\n"));
 1315     fprintf(fp, _("#  sigfile=STRING (eg. $var/sig)\n"));
 1316     fprintf(fp, _("#  show_author=NUM\n"));
 1317     fprintf(fp, "#    %d=%s, %d=%s, %d=%s, %d=%s\n",
 1318         SHOW_FROM_NONE, _(txt_show_from[SHOW_FROM_NONE]),
 1319         SHOW_FROM_ADDR, _(txt_show_from[SHOW_FROM_ADDR]),
 1320         SHOW_FROM_NAME, _(txt_show_from[SHOW_FROM_NAME]),
 1321         SHOW_FROM_BOTH, _(txt_show_from[SHOW_FROM_BOTH]));
 1322     fprintf(fp, _("#  show_signatures=ON/OFF\n"));
 1323 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1324     fprintf(fp, _("#  suppress_soft_hyphens=ON/OFF\n"));
 1325 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1326     fprintf(fp, _("#  show_only_unread_arts=ON/OFF\n"));
 1327     fprintf(fp, _("#  sigdashes=ON/OFF\n"));
 1328     fprintf(fp, _("#  signature_repost=ON/OFF\n"));
 1329     fprintf(fp, _("#  sort_article_type=NUM\n"));
 1330     fprintf(fp, "#    %d=%s,\n",
 1331         SORT_ARTICLES_BY_NOTHING, _(txt_sort_a_type[SORT_ARTICLES_BY_NOTHING]));
 1332     fprintf(fp, "#    %d=%s, %d=%s,\n",
 1333         SORT_ARTICLES_BY_SUBJ_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_DESCEND]),
 1334         SORT_ARTICLES_BY_SUBJ_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_ASCEND]));
 1335     fprintf(fp, "#    %d=%s, %d=%s,\n",
 1336         SORT_ARTICLES_BY_FROM_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_DESCEND]),
 1337         SORT_ARTICLES_BY_FROM_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_ASCEND]));
 1338     fprintf(fp, "#    %d=%s, %d=%s,\n",
 1339         SORT_ARTICLES_BY_DATE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_DESCEND]),
 1340         SORT_ARTICLES_BY_DATE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_ASCEND]));
 1341     fprintf(fp, "#    %d=%s, %d=%s,\n",
 1342         SORT_ARTICLES_BY_SCORE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_DESCEND]),
 1343         SORT_ARTICLES_BY_SCORE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_ASCEND]));
 1344     fprintf(fp, "#    %d=%s, %d=%s\n",
 1345         SORT_ARTICLES_BY_LINES_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_DESCEND]),
 1346         SORT_ARTICLES_BY_LINES_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_ASCEND]));
 1347     fprintf(fp, _("#  sort_threads_type=NUM\n"));
 1348     fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
 1349         SORT_THREADS_BY_NOTHING, _(txt_sort_t_type[SORT_THREADS_BY_NOTHING]),
 1350         SORT_THREADS_BY_SCORE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_DESCEND]),
 1351         SORT_THREADS_BY_SCORE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_ASCEND]));
 1352     fprintf(fp, "#    %d=%s\n",
 1353         SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND]));
 1354     fprintf(fp, "#    %d=%s\n",
 1355         SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND]));
 1356     fprintf(fp, _("#  tex2iso_conv=ON/OFF\n"));
 1357     fprintf(fp, _("#  thread_catchup_on_exit=ON/OFF\n"));
 1358     fprintf(fp, _("#  thread_articles=NUM"));
 1359     for (i = 0; i <= THREAD_MAX; i++) {
 1360         if (!(i % 2))
 1361             fprintf(fp, "\n#    ");
 1362         fprintf(fp, "%d=%s, ", i, _(txt_threading[i]));
 1363     }
 1364     fprintf(fp, "\n");
 1365     fprintf(fp, _("#  thread_format=STRING (eg. %%n %%m [%%L]  %%T  %%F)\n"));
 1366     fprintf(fp, _("#  thread_perc=NUM\n"));
 1367     fprintf(fp, _("#  trim_article_body=NUM\n"));
 1368     fprintf(fp, _("#    0 = Don't trim article body\n"));
 1369     fprintf(fp, _("#    1 = Skip leading blank lines\n"));
 1370     fprintf(fp, _("#    2 = Skip trailing blank lines\n"));
 1371     fprintf(fp, _("#    3 = Skip leading and trailing blank lines\n"));
 1372     fprintf(fp, _("#    4 = Compact multiple blank lines between text blocks\n"));
 1373     fprintf(fp, _("#    5 = Compact multiple blank lines between text blocks and skip\n#        leading blank lines\n"));
 1374     fprintf(fp, _("#    6 = Compact multiple blank lines between text blocks and skip\n#        trailing blank lines\n"));
 1375     fprintf(fp, _("#    7 = Compact multiple blank lines between text blocks and skip\n#        leading and trailing blank lines\n"));
 1376     fprintf(fp, _("#  verbatim_handling=ON/OFF\n"));
 1377 #ifdef HAVE_COLOR
 1378     fprintf(fp, _("#  extquote_handling=ON/OFF\n"));
 1379 #endif /* HAVE_COLOR */
 1380     fprintf(fp, _("#  wrap_on_next_unread=ON/OFF\n"));
 1381     fprintf(fp, _("#  x_body=STRING (eg. ~/.tin/extra-body-text)\n"));
 1382     fprintf(fp, _("#  x_comment_to=ON/OFF\n"));
 1383     fprintf(fp, _("#  x_headers=STRING (eg. ~/.tin/extra-headers)\n"));
 1384     fprintf(fp, _("#\n# Note that it is best to put general (global scoping)\n"));
 1385     fprintf(fp, _("# entries first followed by group specific entries.\n#\n"));
 1386     fprintf(fp, _("############################################################################\n"));
 1387 
 1388     /*
 1389      * determine the file offset
 1390      * this is necessary because a changed locale setting
 1391      * may lead to an invalid offset
 1392      */
 1393     if ((fpos = ftell(fp)) <= 0) {
 1394         clearerr(fp);
 1395         fclose(fp);
 1396         unlink(new_file);
 1397         free(new_file);
 1398         error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
 1399         return;
 1400     }
 1401     rewind(fp);
 1402     attrib_file_offset = 1;
 1403     while ((i = fgetc(fp)) != EOF) {
 1404         if (i == '\n')
 1405             attrib_file_offset++;
 1406     }
 1407     if (fseek(fp, fpos, SEEK_SET)) {
 1408         clearerr(fp);
 1409         fclose(fp);
 1410         unlink(new_file);
 1411         free(new_file);
 1412         error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
 1413         return;
 1414     }
 1415 
 1416     if ((num_scope > 0) && (scopes != NULL)) {
 1417         struct t_scope *scope;
 1418 
 1419         for (i = 1; i < num_scope; i++) {
 1420             scope = &scopes[i];
 1421             if (!scope->global) {
 1422                 if (skip_scope(scope))
 1423                     continue;
 1424                 fprintf(fp, "\nscope=%s\n", scope->scope);
 1425                 if (scope->state->add_posted_to_filter)
 1426                     fprintf(fp, "add_posted_to_filter=%s\n", print_boolean(scope->attribute->add_posted_to_filter));
 1427                 if (scope->state->advertising)
 1428                     fprintf(fp, "advertising=%s\n", print_boolean(scope->attribute->advertising));
 1429                 if (scope->state->alternative_handling)
 1430                     fprintf(fp, "alternative_handling=%s\n", print_boolean(scope->attribute->alternative_handling));
 1431                 if (scope->state->ask_for_metamail)
 1432                     fprintf(fp, "ask_for_metamail=%s\n", print_boolean(scope->attribute->ask_for_metamail));
 1433                 if (scope->state->auto_cc_bcc)
 1434                     fprintf(fp, "auto_cc_bcc=%u\n", scope->attribute->auto_cc_bcc);
 1435                 if (scope->state->auto_list_thread)
 1436                     fprintf(fp, "auto_list_thread=%s\n", print_boolean(scope->attribute->auto_list_thread));
 1437                 if (scope->state->auto_select)
 1438                     fprintf(fp, "auto_select=%s\n", print_boolean(scope->attribute->auto_select));
 1439                 if (scope->state->batch_save)
 1440                     fprintf(fp, "batch_save=%s\n", print_boolean(scope->attribute->batch_save));
 1441                 if (scope->state->date_format && scope->attribute->date_format)
 1442                     fprintf(fp, "date_format=%s\n", scope->attribute->date_format);
 1443                 if (scope->state->delete_tmp_files)
 1444                     fprintf(fp, "delete_tmp_files=%s\n", print_boolean(scope->attribute->delete_tmp_files));
 1445                 if (scope->state->editor_format && scope->attribute->editor_format)
 1446                     fprintf(fp, "editor_format=%s\n", scope->attribute->editor_format);
 1447 #ifdef HAVE_COLOR
 1448                 if (scope->state->extquote_handling)
 1449                     fprintf(fp, "extquote_handling=%s\n", print_boolean(scope->attribute->extquote_handling));
 1450 #endif /* HAVE_COLOR */
 1451                 if (scope->state->fcc && scope->attribute->fcc)
 1452                     fprintf(fp, "fcc=%s\n", scope->attribute->fcc);
 1453                 if (scope->state->followup_to && scope->attribute->followup_to)
 1454                     fprintf(fp, "followup_to=%s\n", scope->attribute->followup_to);
 1455                 if (scope->state->from && scope->attribute->from)
 1456                     fprintf(fp, "from=%s\n", scope->attribute->from);
 1457                 if (scope->state->group_catchup_on_exit)
 1458                     fprintf(fp, "group_catchup_on_exit=%s\n", print_boolean(scope->attribute->group_catchup_on_exit));
 1459                 if (scope->state->group_format && scope->attribute->group_format)
 1460                     fprintf(fp, "group_format=%s\n", scope->attribute->group_format);
 1461                 if (scope->state->mail_8bit_header)
 1462                     fprintf(fp, "mail_8bit_header=%s\n", print_boolean(scope->attribute->mail_8bit_header));
 1463                 if (scope->state->mail_mime_encoding)
 1464                     fprintf(fp, "mail_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->mail_mime_encoding]);
 1465 #ifdef HAVE_ISPELL
 1466                 if (scope->state->ispell && scope->attribute->ispell)
 1467                     fprintf(fp, "ispell=%s\n", scope->attribute->ispell);
 1468 #endif /* HAVE_ISPELL */
 1469                 if (scope->state->maildir && scope->attribute->maildir)
 1470                     fprintf(fp, "maildir=%s\n", scope->attribute->maildir);
 1471                 if (scope->state->mailing_list && scope->attribute->mailing_list)
 1472                     fprintf(fp, "mailing_list=%s\n", scope->attribute->mailing_list);
 1473                 if (scope->state->mark_ignore_tags)
 1474                     fprintf(fp, "mark_ignore_tags=%s\n", print_boolean(scope->attribute->mark_ignore_tags));
 1475                 if (scope->state->mark_saved_read)
 1476                     fprintf(fp, "mark_saved_read=%s\n", print_boolean(scope->attribute->mark_saved_read));
 1477                 if (scope->state->mime_forward)
 1478                     fprintf(fp, "mime_forward=%s\n", print_boolean(scope->attribute->mime_forward));
 1479                 if (scope->state->mime_types_to_save && scope->attribute->mime_types_to_save)
 1480                     fprintf(fp, "mime_types_to_save=%s\n", scope->attribute->mime_types_to_save);
 1481 #ifdef CHARSET_CONVERSION
 1482                 if (scope->state->mm_network_charset)
 1483                     fprintf(fp, "mm_network_charset=%s\n", txt_mime_charsets[scope->attribute->mm_network_charset]);
 1484                 if (scope->state->undeclared_charset && scope->attribute->undeclared_charset)
 1485                     fprintf(fp, "undeclared_charset=%s\n", scope->attribute->undeclared_charset);
 1486 #endif /* CHARSET_CONVERSION */
 1487                 if (scope->state->news_headers_to_display && scope->attribute->news_headers_to_display)
 1488                     fprintf(fp, "news_headers_to_display=%s\n", scope->attribute->news_headers_to_display);
 1489                 if (scope->state->news_headers_to_not_display && scope->attribute->news_headers_to_not_display)
 1490                     fprintf(fp, "news_headers_to_not_display=%s\n", scope->attribute->news_headers_to_not_display);
 1491                 if (scope->state->news_quote_format && scope->attribute->news_quote_format)
 1492                     fprintf(fp, "news_quote_format=%s\n", scope->attribute->news_quote_format);
 1493                 if (scope->state->organization && scope->attribute->organization)
 1494                     fprintf(fp, "organization=%s\n", scope->attribute->organization);
 1495                 if (scope->state->pos_first_unread)
 1496                     fprintf(fp, "pos_first_unread=%s\n", print_boolean(scope->attribute->pos_first_unread));
 1497                 if (scope->state->post_8bit_header)
 1498                     fprintf(fp, "post_8bit_header=%s\n", print_boolean(scope->attribute->post_8bit_header));
 1499                 if (scope->state->post_mime_encoding)
 1500                     fprintf(fp, "post_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->post_mime_encoding]);
 1501                 if (scope->state->post_process_view)
 1502                     fprintf(fp, "post_process_view=%s\n", print_boolean(scope->attribute->post_process_view));
 1503                 if (scope->state->post_process_type)
 1504                     fprintf(fp, "post_process_type=%u\n", scope->attribute->post_process_type);
 1505 #ifndef DISABLE_PRINTING
 1506                 if (scope->state->print_header)
 1507                     fprintf(fp, "print_header=%s\n", print_boolean(scope->attribute->print_header));
 1508 #endif /* !DISABLE_PRINTING */
 1509                 if (scope->state->process_only_unread)
 1510                     fprintf(fp, "process_only_unread=%s\n", print_boolean(scope->attribute->process_only_unread));
 1511                 if (scope->state->prompt_followupto)
 1512                     fprintf(fp, "prompt_followupto=%s\n", print_boolean(scope->attribute->prompt_followupto));
 1513                 if (scope->state->quick_kill_scope && scope->attribute->quick_kill_scope)
 1514                     fprintf(fp, "quick_kill_scope=%s\n", scope->attribute->quick_kill_scope);
 1515                 if (scope->state->quick_kill_case)
 1516                     fprintf(fp, "quick_kill_case=%s\n", print_boolean(scope->attribute->quick_kill_case));
 1517                 if (scope->state->quick_kill_expire)
 1518                     fprintf(fp, "quick_kill_expire=%s\n", print_boolean(scope->attribute->quick_kill_expire));
 1519                 if (scope->state->quick_kill_header)
 1520                     fprintf(fp, "quick_kill_header=%u\n", scope->attribute->quick_kill_header);
 1521                 if (scope->state->quick_select_scope && scope->attribute->quick_select_scope)
 1522                     fprintf(fp, "quick_select_scope=%s\n", scope->attribute->quick_select_scope);
 1523                 if (scope->state->quick_select_case)
 1524                     fprintf(fp, "quick_select_case=%s\n", print_boolean(scope->attribute->quick_select_case));
 1525                 if (scope->state->quick_select_expire)
 1526                     fprintf(fp, "quick_select_expire=%s\n", print_boolean(scope->attribute->quick_select_expire));
 1527                 if (scope->state->quick_select_header)
 1528                     fprintf(fp, "quick_select_header=%u\n", scope->attribute->quick_select_header);
 1529                 if (scope->state->quote_chars && scope->attribute->quote_chars)
 1530                     fprintf(fp, "quote_chars=%s\n", quote_space_to_dash(scope->attribute->quote_chars));
 1531                 if (scope->state->savedir && scope->attribute->savedir)
 1532                     fprintf(fp, "savedir=%s\n", scope->attribute->savedir);
 1533                 if (scope->state->savefile && scope->attribute->savefile)
 1534                     fprintf(fp, "savefile=%s\n", scope->attribute->savefile);
 1535                 if (scope->state->show_author)
 1536                     fprintf(fp, "show_author=%u\n", scope->attribute->show_author);
 1537                 if (scope->state->show_only_unread_arts)
 1538                     fprintf(fp, "show_only_unread_arts=%s\n", print_boolean(scope->attribute->show_only_unread_arts));
 1539                 if (scope->state->show_signatures)
 1540                     fprintf(fp, "show_signatures=%s\n", print_boolean(scope->attribute->show_signatures));
 1541                 if (scope->state->sigdashes)
 1542                     fprintf(fp, "sigdashes=%s\n", print_boolean(scope->attribute->sigdashes));
 1543                 if (scope->state->sigfile && scope->attribute->sigfile)
 1544                     fprintf(fp, "sigfile=%s\n", scope->attribute->sigfile);
 1545                 if (scope->state->signature_repost)
 1546                     fprintf(fp, "signature_repost=%s\n", print_boolean(scope->attribute->signature_repost));
 1547                 if (scope->state->sort_article_type)
 1548                     fprintf(fp, "sort_article_type=%u\n", scope->attribute->sort_article_type);
 1549                 if (scope->state->sort_threads_type)
 1550                     fprintf(fp, "sort_threads_type=%u\n", scope->attribute->sort_threads_type);
 1551 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1552                 if (scope->state->suppress_soft_hyphens)
 1553                     fprintf(fp, "suppress_soft_hyphens=%s\n", print_boolean(scope->attribute->suppress_soft_hyphens));
 1554 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1555                 if (scope->state->tex2iso_conv)
 1556                     fprintf(fp, "tex2iso_conv=%s\n", print_boolean(scope->attribute->tex2iso_conv));
 1557                 if (scope->state->thread_articles)
 1558                     fprintf(fp, "thread_articles=%u\n", scope->attribute->thread_articles);
 1559                 if (scope->state->thread_catchup_on_exit)
 1560                     fprintf(fp, "thread_catchup_on_exit=%s\n", print_boolean(scope->attribute->thread_catchup_on_exit));
 1561                 if (scope->state->thread_format && scope->attribute->thread_format)
 1562                     fprintf(fp, "thread_format=%s\n", scope->attribute->thread_format);
 1563                 if (scope->state->thread_perc)
 1564                     fprintf(fp, "thread_perc=%u\n", scope->attribute->thread_perc);
 1565                 if (scope->state->trim_article_body)
 1566                     fprintf(fp, "trim_article_body=%u\n", scope->attribute->trim_article_body);
 1567                 if (scope->state->verbatim_handling)
 1568                     fprintf(fp, "verbatim_handling=%s\n", print_boolean(scope->attribute->verbatim_handling));
 1569                 if (scope->state->wrap_on_next_unread)
 1570                     fprintf(fp, "wrap_on_next_unread=%s\n", print_boolean(scope->attribute->wrap_on_next_unread));
 1571                 if (scope->state->x_headers && scope->attribute->x_headers)
 1572                     fprintf(fp, "x_headers=%s\n", scope->attribute->x_headers);
 1573                 if (scope->state->x_body && scope->attribute->x_body)
 1574                     fprintf(fp, "x_body=%s\n", scope->attribute->x_body);
 1575                 if (scope->state->x_comment_to)
 1576                     fprintf(fp, "x_comment_to=%s\n", print_boolean(scope->attribute->x_comment_to));
 1577             }
 1578         }
 1579     }
 1580 
 1581     /* rename_file() preserves mode, so this is safe */
 1582 #ifdef HAVE_FCHMOD
 1583     fchmod(fileno(fp), (mode_t) (S_IRUSR|S_IWUSR));
 1584 #else
 1585 #   ifdef HAVE_CHMOD
 1586     chmod(new_file, (mode_t) (S_IRUSR|S_IWUSR));
 1587 #   endif /* HAVE_CHMOD */
 1588 #endif /* HAVE_FCHMOD */
 1589 
 1590     if ((i = ferror(fp)) || fclose(fp)) {
 1591         error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
 1592         unlink(new_file);
 1593         if (i) {
 1594             clearerr(fp);
 1595             fclose(fp);
 1596         }
 1597     } else
 1598         rename_file(new_file, file);
 1599 
 1600     free(new_file);
 1601 }
 1602 
 1603 
 1604 /*
 1605  * Returns true if given scope is empty, i.e. no attribute is set
 1606  */
 1607 static t_bool
 1608 skip_scope(
 1609     struct t_scope *scope)
 1610 {
 1611     return !(scope->state->add_posted_to_filter
 1612         || scope->state->advertising
 1613         || scope->state->alternative_handling
 1614         || scope->state->ask_for_metamail
 1615         || scope->state->auto_cc_bcc
 1616         || scope->state->auto_list_thread
 1617         || scope->state->auto_select
 1618         || scope->state->batch_save
 1619         || (scope->state->date_format && scope->attribute->date_format)
 1620         || scope->state->delete_tmp_files
 1621         || (scope->state->editor_format && scope->attribute->editor_format)
 1622 #ifdef HAVE_COLOR
 1623         || scope->state->extquote_handling
 1624 #endif /* HAVE_COLOR */
 1625         || (scope->state->fcc && scope->attribute->fcc)
 1626         || (scope->state->followup_to && scope->attribute->followup_to)
 1627         || (scope->state->from && scope->attribute->from)
 1628         || scope->state->group_catchup_on_exit
 1629         || (scope->state->group_format && scope->attribute->group_format)
 1630         || scope->state->mail_8bit_header
 1631         || scope->state->mail_mime_encoding
 1632 #ifdef HAVE_ISPELL
 1633         || (scope->state->ispell && scope->attribute->ispell)
 1634 #endif /* HAVE_ISPELL */
 1635         || (scope->state->maildir && scope->attribute->maildir)
 1636         || (scope->state->mailing_list && scope->attribute->mailing_list)
 1637         || scope->state->mark_ignore_tags
 1638         || scope->state->mark_saved_read
 1639         || scope->state->mime_forward
 1640         || (scope->state->mime_types_to_save && scope->attribute->mime_types_to_save)
 1641 #ifdef CHARSET_CONVERSION
 1642         || scope->state->mm_network_charset
 1643         || (scope->state->undeclared_charset && scope->attribute->undeclared_charset)
 1644 #endif /* CHARSET_CONVERSION */
 1645         || (scope->state->news_headers_to_display && scope->attribute->news_headers_to_display)
 1646         || (scope->state->news_headers_to_not_display && scope->attribute->news_headers_to_not_display)
 1647         || (scope->state->news_quote_format && scope->attribute->news_quote_format)
 1648         || (scope->state->organization && scope->attribute->organization)
 1649         || scope->state->pos_first_unread
 1650         || scope->state->post_8bit_header
 1651         || scope->state->post_mime_encoding
 1652         || scope->state->post_process_view
 1653         || scope->state->post_process_type
 1654 #ifndef DISABLE_PRINTING
 1655         || scope->state->print_header
 1656 #endif /* !DISABLE_PRINTING */
 1657         || scope->state->process_only_unread
 1658         || scope->state->prompt_followupto
 1659         || (scope->state->quick_kill_scope && scope->attribute->quick_kill_scope)
 1660         || scope->state->quick_kill_case
 1661         || scope->state->quick_kill_expire
 1662         || scope->state->quick_kill_header
 1663         || (scope->state->quick_select_scope && scope->attribute->quick_select_scope)
 1664         || scope->state->quick_select_case
 1665         || scope->state->quick_select_expire
 1666         || scope->state->quick_select_header
 1667         || (scope->state->quote_chars && scope->attribute->quote_chars)
 1668         || (scope->state->savedir && scope->attribute->savedir)
 1669         || (scope->state->savefile && scope->attribute->savefile)
 1670         || scope->state->show_author
 1671         || scope->state->show_only_unread_arts
 1672         || scope->state->show_signatures
 1673         || scope->state->sigdashes
 1674         || (scope->state->sigfile && scope->attribute->sigfile)
 1675         || scope->state->signature_repost
 1676         || scope->state->sort_article_type
 1677         || scope->state->sort_threads_type
 1678 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1679         || scope->state->suppress_soft_hyphens
 1680 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1681         || scope->state->tex2iso_conv
 1682         || scope->state->thread_articles
 1683         || scope->state->thread_catchup_on_exit
 1684         || (scope->state->thread_format && scope->attribute->thread_format)
 1685         || scope->state->thread_perc
 1686         || scope->state->trim_article_body
 1687         || scope->state->verbatim_handling
 1688         || scope->state->wrap_on_next_unread
 1689         || (scope->state->x_headers && scope->attribute->x_headers)
 1690         || (scope->state->x_body && scope->attribute->x_body)
 1691         || scope->state->x_comment_to);
 1692 }
 1693 
 1694 
 1695 #ifdef DEBUG
 1696 #   if 0
 1697 static void
 1698 debug_print_filter_attributes(
 1699     void)
 1700 {
 1701     if (debug & DEBUG_ATTRIB) {
 1702         int i;
 1703         struct t_group *group;
 1704 
 1705         my_printf("\nBEG ***\n");
 1706 
 1707         for_each_group(i) {
 1708             group = &active[i];
 1709             my_printf("Grp=[%s] KILL   header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
 1710                 group->name, group->attribute->quick_kill_header,
 1711                 BlankIfNull(group->attribute->quick_kill_scope),
 1712                 txt_onoff[group->attribute->quick_kill_case != FALSE ? 1 : 0],
 1713                 txt_onoff[group->attribute->quick_kill_expire != FALSE ? 1 : 0]);
 1714             my_printf("Grp=[%s] SELECT header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
 1715                 group->name, group->attribute->quick_select_header,
 1716                 BlankIfNull(group->attribute->quick_select_scope),
 1717                 txt_onoff[group->attribute->quick_select_case != FALSE ? 1 : 0],
 1718                 txt_onoff[group->attribute->quick_select_expire != FALSE ? 1 : 0]);
 1719         }
 1720         my_printf("END ***\n");
 1721     }
 1722 }
 1723 #   endif /* 0 */
 1724 
 1725 
 1726 static void
 1727 dump_attributes(
 1728     void)
 1729 {
 1730     if (debug & DEBUG_ATTRIB) {
 1731         int i, j;
 1732         struct t_group *group;
 1733 
 1734         for_each_group(i) {
 1735             group = &active[i];
 1736             if (!group->attribute)
 1737                 continue;
 1738             debug_print_file("ATTRIBUTES", "group=%s", BlankIfNull(group->name));
 1739             debug_print_file("ATTRIBUTES", "\tGlobal=%d", group->attribute->global);
 1740             debug_print_file("ATTRIBUTES", "\tmaildir=%s", BlankIfNull(group->attribute->maildir));
 1741             debug_print_file("ATTRIBUTES", "\tsavedir=%s", BlankIfNull(group->attribute->savedir));
 1742             debug_print_file("ATTRIBUTES", "\tsavefile=%s", BlankIfNull(group->attribute->savefile));
 1743             debug_print_file("ATTRIBUTES", "\tsigfile=%s", BlankIfNull(group->attribute->sigfile));
 1744             debug_print_file("ATTRIBUTES", "\torganization=%s", BlankIfNull(group->attribute->organization));
 1745             debug_print_file("ATTRIBUTES", "\tfollowup_to=%s", BlankIfNull(group->attribute->followup_to));
 1746             debug_print_file("ATTRIBUTES", "\tmailing_list=%s", BlankIfNull(group->attribute->mailing_list));
 1747             debug_print_file("ATTRIBUTES", "\tx_headers=%s", BlankIfNull(group->attribute->x_headers));
 1748             debug_print_file("ATTRIBUTES", "\tx_body=%s", BlankIfNull(group->attribute->x_body));
 1749             debug_print_file("ATTRIBUTES", "\tfrom=%s", BlankIfNull(group->attribute->from));
 1750             debug_print_file("ATTRIBUTES", "\tnews_quote_format=%s", BlankIfNull(group->attribute->news_quote_format));
 1751             debug_print_file("ATTRIBUTES", "\tquote_chars=%s", quote_space_to_dash(BlankIfNull(group->attribute->quote_chars)));
 1752             debug_print_file("ATTRIBUTES", "\tmime_types_to_save=%s", BlankIfNull(group->attribute->mime_types_to_save));
 1753 #   ifdef HAVE_ISPELL
 1754             debug_print_file("ATTRIBUTES", "\tispell=%s", BlankIfNull(group->attribute->ispell));
 1755 #   endif /* HAVE_ISPELL */
 1756             debug_print_file("ATTRIBUTES", "\tshow_only_unread_arts=%s", print_boolean(group->attribute->show_only_unread_arts));
 1757             debug_print_file("ATTRIBUTES", "\tthread_articles=%d", group->attribute->thread_articles);
 1758             debug_print_file("ATTRIBUTES", "\tthread_perc=%d", group->attribute->thread_perc);
 1759             debug_print_file("ATTRIBUTES", "\tadd_posted_to_filter=%s", print_boolean(group->attribute->add_posted_to_filter));
 1760             debug_print_file("ATTRIBUTES", "\tadvertising=%s", print_boolean(group->attribute->advertising));
 1761             debug_print_file("ATTRIBUTES", "\talternative_handling=%s", print_boolean(group->attribute->alternative_handling));
 1762             debug_print_file("ATTRIBUTES", "\task_for_metamail=%s", print_boolean(group->attribute->ask_for_metamail));
 1763             debug_print_file("ATTRIBUTES", "\tauto_cc_bcc=%d", group->attribute->auto_cc_bcc);
 1764             debug_print_file("ATTRIBUTES", "\tauto_list_thread=%s", print_boolean(group->attribute->auto_list_thread));
 1765             debug_print_file("ATTRIBUTES", "\tauto_select=%s", print_boolean(group->attribute->auto_select));
 1766             debug_print_file("ATTRIBUTES", "\tbatch_save=%s", print_boolean(group->attribute->batch_save));
 1767             debug_print_file("ATTRIBUTES", "\tdate_format=%s", BlankIfNull(group->attribute->date_format));
 1768             debug_print_file("ATTRIBUTES", "\tdelete_tmp_files=%s", print_boolean(group->attribute->delete_tmp_files));
 1769             debug_print_file("ATTRIBUTES", "\teditor_format=%s", BlankIfNull(group->attribute->editor_format));
 1770 #   ifdef HAVE_COLOR
 1771             debug_print_file("ATTRIBUTES", "\textquote_handling=%s", print_boolean(group->attribute->extquote_handling));
 1772 #   endif /* HAVE_COLOR */
 1773             debug_print_file("ATTRIBUTES", "\tgroup_catchup_on_exit=%s", print_boolean(group->attribute->group_catchup_on_exit));
 1774             debug_print_file("ATTRIBUTES", "\tgroup_format=%s", BlankIfNull(group->attribute->group_format));
 1775             debug_print_file("ATTRIBUTES", "\tmail_8bit_header=%s", print_boolean(group->attribute->mail_8bit_header));
 1776             debug_print_file("ATTRIBUTES", "\tmail_mime_encoding=%s", txt_mime_encodings[group->attribute->mail_mime_encoding]);
 1777             debug_print_file("ATTRIBUTES", "\tmark_ignore_tags=%s", print_boolean(group->attribute->mark_ignore_tags));
 1778             debug_print_file("ATTRIBUTES", "\tmark_saved_read=%s", print_boolean(group->attribute->mark_saved_read));
 1779             debug_print_file("ATTRIBUTES", "\tnews_headers_to_display=%s", BlankIfNull(group->attribute->news_headers_to_display));
 1780             if (group->attribute->headers_to_display) {
 1781                 debug_print_file("ATTRIBUTES", "\theaders_to_display->num=%d", group->attribute->headers_to_display->num);
 1782                 for (j = 0; j < group->attribute->headers_to_display->num; j++)
 1783                     debug_print_file("ATTRIBUTES", "\theaders_to_display->header[%d]=%s", j, group->attribute->headers_to_display->header[j]);
 1784             }
 1785             debug_print_file("ATTRIBUTES", "\tnews_headers_to_not_display=%s", BlankIfNull(group->attribute->news_headers_to_not_display));
 1786             if (group->attribute->headers_to_not_display) {
 1787                 debug_print_file("ATTRIBUTES", "\theaders_to_not_display->num=%d", group->attribute->headers_to_not_display->num);
 1788                 for (j = 0; j < group->attribute->headers_to_not_display->num; j++)
 1789                     debug_print_file("ATTRIBUTES", "\theaders_to_not_display->header[%d]=%s", j, group->attribute->headers_to_not_display->header[j]);
 1790             }
 1791             debug_print_file("ATTRIBUTES", "\tpos_first_unread=%s", print_boolean(group->attribute->pos_first_unread));
 1792             debug_print_file("ATTRIBUTES", "\tpost_8bit_header=%s", print_boolean(group->attribute->post_8bit_header));
 1793             debug_print_file("ATTRIBUTES", "\tpost_mime_encoding=%s", txt_mime_encodings[group->attribute->post_mime_encoding]);
 1794             debug_print_file("ATTRIBUTES", "\tpost_process_view=%s", print_boolean(group->attribute->post_process_view));
 1795 #   ifndef DISABLE_PRINTING
 1796             debug_print_file("ATTRIBUTES", "\tprint_header=%s", print_boolean(group->attribute->print_header));
 1797 #   endif /* !DISABLE_PRINTING */
 1798             debug_print_file("ATTRIBUTES", "\tprocess_only_unread=%s", print_boolean(group->attribute->process_only_unread));
 1799             debug_print_file("ATTRIBUTES", "\tprompt_followupto=%s", print_boolean(group->attribute->prompt_followupto));
 1800             debug_print_file("ATTRIBUTES", "\tsort_article_type=%d", group->attribute->sort_article_type);
 1801             debug_print_file("ATTRIBUTES", "\tsort_threads_type=%d", group->attribute->sort_threads_type);
 1802             debug_print_file("ATTRIBUTES", "\tshow_author=%d", group->attribute->show_author);
 1803             debug_print_file("ATTRIBUTES", "\tshow_signatures=%s", print_boolean(group->attribute->show_signatures));
 1804             debug_print_file("ATTRIBUTES", "\tsigdashes=%s", print_boolean(group->attribute->sigdashes));
 1805             debug_print_file("ATTRIBUTES", "\tsignature_repost=%s", print_boolean(group->attribute->signature_repost));
 1806 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1807             debug_print_file("ATTRIBUTES", "\tsuppress_soft_hyphens=%s", print_boolean(group->attribute->suppress_soft_hyphens));
 1808 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1809             debug_print_file("ATTRIBUTES", "\tthread_catchup_on_exit=%s", print_boolean(group->attribute->thread_catchup_on_exit));
 1810             debug_print_file("ATTRIBUTES", "\tthread_format=%s", BlankIfNull(group->attribute->thread_format));
 1811             debug_print_file("ATTRIBUTES", "\ttrim_article_body=%d", group->attribute->trim_article_body);
 1812             debug_print_file("ATTRIBUTES", "\tverbatim_handling=%s", print_boolean(group->attribute->verbatim_handling));
 1813             debug_print_file("ATTRIBUTES", "\twrap_on_next_unread=%s", print_boolean(group->attribute->wrap_on_next_unread));
 1814             debug_print_file("ATTRIBUTES", "\tpost_process_type=%d", group->attribute->post_process_type);
 1815             debug_print_file("ATTRIBUTES", "\tquick_kill_scope=%s", BlankIfNull(group->attribute->quick_kill_scope));
 1816             debug_print_file("ATTRIBUTES", "\tquick_kill_case=%s", print_boolean(group->attribute->quick_kill_case));
 1817             debug_print_file("ATTRIBUTES", "\tquick_kill_expire=%s", print_boolean(group->attribute->quick_kill_expire));
 1818             debug_print_file("ATTRIBUTES", "\tquick_kill_header=%d", group->attribute->quick_kill_header);
 1819             debug_print_file("ATTRIBUTES", "\tquick_select_scope=%s", BlankIfNull(group->attribute->quick_select_scope));
 1820             debug_print_file("ATTRIBUTES", "\tquick_select_case=%s", print_boolean(group->attribute->quick_select_case));
 1821             debug_print_file("ATTRIBUTES", "\tquick_select_expire=%s", print_boolean(group->attribute->quick_select_expire));
 1822             debug_print_file("ATTRIBUTES", "\tquick_select_header=%d", group->attribute->quick_select_header);
 1823             debug_print_file("ATTRIBUTES", "\tx_comment_to=%s", print_boolean(group->attribute->x_comment_to));
 1824             debug_print_file("ATTRIBUTES", "\tfcc=%s", BlankIfNull(group->attribute->fcc));
 1825             debug_print_file("ATTRIBUTES", "\ttex2iso_conv=%s", print_boolean(group->attribute->tex2iso_conv));
 1826             debug_print_file("ATTRIBUTES", "\tmime_forward=%s", print_boolean(group->attribute->mime_forward));
 1827 #   ifdef CHARSET_CONVERSION
 1828             debug_print_file("ATTRIBUTES", "\tmm_network_charset=%s", txt_mime_charsets[group->attribute->mm_network_charset]);
 1829             debug_print_file("ATTRIBUTES", "\tundeclared_charset=%s", BlankIfNull(group->attribute->undeclared_charset));
 1830 #   endif /* CHARSET_CONVERSION */
 1831             debug_print_file("ATTRIBUTES", "");
 1832         }
 1833     }
 1834 }
 1835 
 1836 
 1837 #define DEBUG_PRINT_STATE(attrib) (scope->state->attrib ? "+ " : "  ")
 1838 #define DEBUG_PRINT_STRING(attrib) (scope->attribute->attrib ? scope->attribute->attrib : "NULL")
 1839 
 1840 
 1841 static void
 1842 dump_scopes(
 1843     const char *fname)
 1844 {
 1845     if (!scopes)
 1846         return;
 1847 
 1848     if (debug & DEBUG_ATTRIB) {
 1849         int i, j;
 1850         struct t_scope *scope;
 1851 
 1852         for (i = 0; i < num_scope; i++) {
 1853             scope = &scopes[i];
 1854             debug_print_file(fname, "scopes[%d]", i);
 1855             debug_print_file(fname, "scope=%s", scope->scope ? scope->scope : "NULL");
 1856             debug_print_file(fname, "\t  global=%d", scope->global);
 1857             debug_print_file(fname, "\t%smaildir=%s", DEBUG_PRINT_STATE(maildir), DEBUG_PRINT_STRING(maildir));
 1858             debug_print_file(fname, "\t%ssavedir=%s", DEBUG_PRINT_STATE(savedir), DEBUG_PRINT_STRING(savedir));
 1859             debug_print_file(fname, "\t%ssavefile=%s", DEBUG_PRINT_STATE(savefile), DEBUG_PRINT_STRING(savefile));
 1860             debug_print_file(fname, "\t%ssigfile=%s", DEBUG_PRINT_STATE(sigfile), DEBUG_PRINT_STRING(sigfile));
 1861             debug_print_file(fname, "\t%sorganization=%s", DEBUG_PRINT_STATE(organization), DEBUG_PRINT_STRING(organization));
 1862             debug_print_file(fname, "\t%sfollowup_to=%s", DEBUG_PRINT_STATE(followup_to), DEBUG_PRINT_STRING(followup_to));
 1863             debug_print_file(fname, "\t%smailing_list=%s", DEBUG_PRINT_STATE(mailing_list), DEBUG_PRINT_STRING(mailing_list));
 1864             debug_print_file(fname, "\t%sx_headers=%s", DEBUG_PRINT_STATE(x_headers), DEBUG_PRINT_STRING(x_headers));
 1865             debug_print_file(fname, "\t%sx_body=%s", DEBUG_PRINT_STATE(x_body), DEBUG_PRINT_STRING(x_body));
 1866             debug_print_file(fname, "\t%sfrom=%s", DEBUG_PRINT_STATE(from), DEBUG_PRINT_STRING(from));
 1867             debug_print_file(fname, "\t%snews_quote_format=%s", DEBUG_PRINT_STATE(news_quote_format), DEBUG_PRINT_STRING(news_quote_format));
 1868             debug_print_file(fname, "\t%squote_chars=%s", DEBUG_PRINT_STATE(quote_chars), quote_space_to_dash(DEBUG_PRINT_STRING(quote_chars)));
 1869             debug_print_file(fname, "\t%smime_types_to_save=%s", DEBUG_PRINT_STATE(mime_types_to_save), DEBUG_PRINT_STRING(mime_types_to_save));
 1870 #   ifdef HAVE_ISPELL
 1871             debug_print_file(fname, "\t%sispell=%s", DEBUG_PRINT_STATE(ispell), DEBUG_PRINT_STRING(ispell));
 1872 #   endif /* HAVE_ISPELL */
 1873             debug_print_file(fname, "\t%sshow_only_unread_arts=%s", DEBUG_PRINT_STATE(show_only_unread_arts), print_boolean(scope->attribute->show_only_unread_arts));
 1874             debug_print_file(fname, "\t%sthread_articles=%d", DEBUG_PRINT_STATE(thread_articles), scope->attribute->thread_articles);
 1875             debug_print_file(fname, "\t%sthread_perc=%d", DEBUG_PRINT_STATE(thread_perc), scope->attribute->thread_perc);
 1876             debug_print_file(fname, "\t%sadd_posted_to_filter=%s", DEBUG_PRINT_STATE(add_posted_to_filter), print_boolean(scope->attribute->add_posted_to_filter));
 1877             debug_print_file(fname, "\t%sadvertising=%s", DEBUG_PRINT_STATE(advertising), print_boolean(scope->attribute->advertising));
 1878             debug_print_file(fname, "\t%salternative_handling=%s", DEBUG_PRINT_STATE(alternative_handling), print_boolean(scope->attribute->alternative_handling));
 1879             debug_print_file(fname, "\t%sask_for_metamail=%s", DEBUG_PRINT_STATE(ask_for_metamail), print_boolean(scope->attribute->ask_for_metamail));
 1880             debug_print_file(fname, "\t%sauto_cc_bcc=%d", DEBUG_PRINT_STATE(auto_cc_bcc), scope->attribute->auto_cc_bcc);
 1881             debug_print_file(fname, "\t%sauto_list_thread=%s", DEBUG_PRINT_STATE(auto_list_thread), print_boolean(scope->attribute->auto_list_thread));
 1882             debug_print_file(fname, "\t%sauto_select=%s", DEBUG_PRINT_STATE(auto_select), print_boolean(scope->attribute->auto_select));
 1883             debug_print_file(fname, "\t%sbatch_save=%s", DEBUG_PRINT_STATE(batch_save), print_boolean(scope->attribute->batch_save));
 1884             debug_print_file(fname, "\t%sdate_format=%s", DEBUG_PRINT_STATE(date_format), DEBUG_PRINT_STRING(date_format));
 1885             debug_print_file(fname, "\t%sdelete_tmp_files=%s", DEBUG_PRINT_STATE(delete_tmp_files), print_boolean(scope->attribute->delete_tmp_files));
 1886             debug_print_file(fname, "\t%seditor_format=%s", DEBUG_PRINT_STATE(editor_format), DEBUG_PRINT_STRING(editor_format));
 1887 #   ifdef HAVE_COLOR
 1888             debug_print_file(fname, "\t%sextquote_handling=%s", DEBUG_PRINT_STATE(extquote_handling), print_boolean(scope->attribute->extquote_handling));
 1889 #   endif /* HAVE_COLOR */
 1890             debug_print_file(fname, "\t%sgroup_catchup_on_exit=%s", DEBUG_PRINT_STATE(group_catchup_on_exit), print_boolean(scope->attribute->group_catchup_on_exit));
 1891             debug_print_file(fname, "\t%sgroup_format=%s", DEBUG_PRINT_STATE(group_format), DEBUG_PRINT_STRING(group_format));
 1892             debug_print_file(fname, "\t%smail_8bit_header=%s", DEBUG_PRINT_STATE(mail_8bit_header), print_boolean(scope->attribute->mail_8bit_header));
 1893             debug_print_file(fname, "\t%smail_mime_encoding=%s", DEBUG_PRINT_STATE(mail_mime_encoding), txt_mime_encodings[scope->attribute->mail_mime_encoding]);
 1894             debug_print_file(fname, "\t%smark_ignore_tags=%s", DEBUG_PRINT_STATE(mark_ignore_tags), print_boolean(scope->attribute->mark_ignore_tags));
 1895             debug_print_file(fname, "\t%smark_saved_read=%s", DEBUG_PRINT_STATE(mark_saved_read), print_boolean(scope->attribute->mark_saved_read));
 1896             debug_print_file(fname, "\t%snews_headers_to_display=%s", DEBUG_PRINT_STATE(news_headers_to_display), DEBUG_PRINT_STRING(news_headers_to_display));
 1897             if (scope->attribute->headers_to_display) {
 1898                 debug_print_file(fname, "\t    headers_to_display->num=%d", scope->attribute->headers_to_display->num);
 1899                 for (j = 0; j < scope->attribute->headers_to_display->num; j++)
 1900                     debug_print_file(fname, "\t    headers_to_display->header[%d]=%s", j, scope->attribute->headers_to_display->header[j]);
 1901             }
 1902             debug_print_file(fname, "\t%snews_headers_to_not_display=%s", DEBUG_PRINT_STATE(news_headers_to_not_display), DEBUG_PRINT_STRING(news_headers_to_not_display));
 1903             if (scope->attribute->headers_to_not_display) {
 1904                 debug_print_file(fname, "\t    headers_to_not_display->num=%d", scope->attribute->headers_to_not_display->num);
 1905                 for (j = 0; j < scope->attribute->headers_to_not_display->num; j++)
 1906                     debug_print_file(fname, "\t    headers_to_not_display->header[%d]=%s", j, scope->attribute->headers_to_not_display->header[j]);
 1907             }
 1908             debug_print_file(fname, "\t%spos_first_unread=%s", DEBUG_PRINT_STATE(pos_first_unread), print_boolean(scope->attribute->pos_first_unread));
 1909             debug_print_file(fname, "\t%spost_8bit_header=%s", DEBUG_PRINT_STATE(post_8bit_header), print_boolean(scope->attribute->post_8bit_header));
 1910             debug_print_file(fname, "\t%spost_mime_encoding=%s", DEBUG_PRINT_STATE(post_mime_encoding), txt_mime_encodings[scope->attribute->post_mime_encoding]);
 1911             debug_print_file(fname, "\t%spost_process_view=%s", DEBUG_PRINT_STATE(post_process_view), print_boolean(scope->attribute->post_process_view));
 1912 #   ifndef DISABLE_PRINTING
 1913             debug_print_file(fname, "\t%sprint_header=%s", DEBUG_PRINT_STATE(print_header), print_boolean(scope->attribute->print_header));
 1914 #   endif /* !DISABLE_PRINTING */
 1915             debug_print_file(fname, "\t%sprocess_only_unread=%s", DEBUG_PRINT_STATE(process_only_unread), print_boolean(scope->attribute->process_only_unread));
 1916             debug_print_file(fname, "\t%sprompt_followupto=%s", DEBUG_PRINT_STATE(prompt_followupto), print_boolean(scope->attribute->prompt_followupto));
 1917             debug_print_file(fname, "\t%ssort_article_type=%d", DEBUG_PRINT_STATE(sort_article_type), scope->attribute->sort_article_type);
 1918             debug_print_file(fname, "\t%ssort_threads_type=%d", DEBUG_PRINT_STATE(sort_threads_type), scope->attribute->sort_threads_type);
 1919             debug_print_file(fname, "\t%sshow_author=%d", DEBUG_PRINT_STATE(show_author), scope->attribute->show_author);
 1920             debug_print_file(fname, "\t%sshow_signatures=%s", DEBUG_PRINT_STATE(show_signatures), print_boolean(scope->attribute->show_signatures));
 1921             debug_print_file(fname, "\t%ssigdashes=%s", DEBUG_PRINT_STATE(sigdashes), print_boolean(scope->attribute->sigdashes));
 1922             debug_print_file(fname, "\t%ssignature_repost=%s", DEBUG_PRINT_STATE(signature_repost), print_boolean(scope->attribute->signature_repost));
 1923 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1924             debug_print_file(fname, "\t%ssuppress_soft_hyphens=%s", DEBUG_PRINT_STATE(suppress_soft_hyphens), print_boolean(scope->attribute->suppress_soft_hyphens));
 1925 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1926             debug_print_file(fname, "\t%sthread_catchup_on_exit=%s", DEBUG_PRINT_STATE(thread_catchup_on_exit), print_boolean(scope->attribute->thread_catchup_on_exit));
 1927             debug_print_file(fname, "\t%sthread_format=%s", DEBUG_PRINT_STATE(thread_format), DEBUG_PRINT_STRING(thread_format));
 1928             debug_print_file(fname, "\t%strim_article_body=%d", DEBUG_PRINT_STATE(trim_article_body), scope->attribute->trim_article_body);
 1929             debug_print_file(fname, "\t%sverbatim_handling=%s", DEBUG_PRINT_STATE(verbatim_handling), print_boolean(scope->attribute->verbatim_handling));
 1930             debug_print_file(fname, "\t%swrap_on_next_unread=%s", DEBUG_PRINT_STATE(wrap_on_next_unread), print_boolean(scope->attribute->wrap_on_next_unread));
 1931             debug_print_file(fname, "\t%spost_process_type=%d", DEBUG_PRINT_STATE(post_process_type), scope->attribute->post_process_type);
 1932             debug_print_file(fname, "\t%squick_kill_scope=%s", DEBUG_PRINT_STATE(quick_kill_scope), DEBUG_PRINT_STRING(quick_kill_scope));
 1933             debug_print_file(fname, "\t%squick_kill_case=%s", DEBUG_PRINT_STATE(quick_kill_case), print_boolean(scope->attribute->quick_kill_case));
 1934             debug_print_file(fname, "\t%squick_kill_expire=%s", DEBUG_PRINT_STATE(quick_kill_expire), print_boolean(scope->attribute->quick_kill_expire));
 1935             debug_print_file(fname, "\t%squick_kill_header=%d", DEBUG_PRINT_STATE(quick_kill_header), scope->attribute->quick_kill_header);
 1936             debug_print_file(fname, "\t%squick_select_scope=%s", DEBUG_PRINT_STATE(quick_select_scope), DEBUG_PRINT_STRING(quick_select_scope));
 1937             debug_print_file(fname, "\t%squick_select_case=%s", DEBUG_PRINT_STATE(quick_select_case), print_boolean(scope->attribute->quick_select_case));
 1938             debug_print_file(fname, "\t%squick_select_expire=%s", DEBUG_PRINT_STATE(quick_select_expire), print_boolean(scope->attribute->quick_select_expire));
 1939             debug_print_file(fname, "\t%squick_select_header=%d", DEBUG_PRINT_STATE(quick_select_header), scope->attribute->quick_select_header);
 1940             debug_print_file(fname, "\t%sx_comment_to=%s", DEBUG_PRINT_STATE(x_comment_to), print_boolean(scope->attribute->x_comment_to));
 1941             debug_print_file(fname, "\t%sfcc=%s", DEBUG_PRINT_STATE(fcc), DEBUG_PRINT_STRING(fcc));
 1942             debug_print_file(fname, "\t%stex2iso_conv=%s", DEBUG_PRINT_STATE(tex2iso_conv), print_boolean(scope->attribute->tex2iso_conv));
 1943             debug_print_file(fname, "\t%smime_forward=%s", DEBUG_PRINT_STATE(mime_forward), print_boolean(scope->attribute->mime_forward));
 1944 #   ifdef CHARSET_CONVERSION
 1945             debug_print_file(fname, "\t%smm_network_charset=%s", DEBUG_PRINT_STATE(mm_network_charset), txt_mime_charsets[scope->attribute->mm_network_charset]);
 1946             debug_print_file(fname, "\t%sundeclared_charset=%s", DEBUG_PRINT_STATE(undeclared_charset), DEBUG_PRINT_STRING(undeclared_charset));
 1947 #   endif /* CHARSET_CONVERSION */
 1948             debug_print_file(fname, "");
 1949         }
 1950     }
 1951 }
 1952 #endif /* DEBUG */