"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.0/include/tin.h" (9 Jul 2021, 73752 Bytes) of package /linux/misc/tin-2.6.0.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 "tin.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.5_vs_2.6.0.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : tin.h
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2021-07-09
    7  *  Notes     : #include files, #defines & struct's
    8  *
    9  * Copyright (c) 1997-2021 Iain Lea <iain@bricbrac.de>, Rich Skrenta <skrenta@pbm.com>
   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 /*
   42  * OS specific doda's
   43  */
   44 
   45 #ifndef TIN_H
   46 #define TIN_H 1
   47 
   48 #ifdef HAVE_CONFIG_H
   49 #   ifndef TIN_AUTOCONF_H
   50 #       include <autoconf.h>    /* FIXME: normally we use 'config.h' */
   51 #   endif /* !TIN_AUTOCONF_H */
   52 #else
   53 #   ifndef HAVE_CONFDEFS_H
   54 #       error "configure run missing"
   55 #   endif /* !HAVE_CONFDEFS_H */
   56 #endif /* HAVE_CONFIG_H */
   57 
   58 
   59 /*
   60  * this causes trouble on Linux (forces nameserver lookups even for local
   61  * connections - this is an (unwanted) feature of getaddrinfo) see also
   62  * nntplib.c
   63  */
   64 /* IPv6 support */
   65 #if defined(HAVE_GETADDRINFO) && defined(HAVE_GAI_STRERROR) && defined(ENABLE_IPV6)
   66 #   define INET6
   67 #endif /* HAVE_GETADDRINFO && HAVE_GAI_STRERROR && ENABLE_IPV6 */
   68 
   69 
   70 /*
   71  * Native Language Support.
   72  */
   73 #ifndef NO_LOCALE
   74 #   ifdef HAVE_LOCALE_H
   75 #       include <locale.h>
   76 #   endif /* HAVE_LOCALE_H */
   77 #   ifndef HAVE_SETLOCALE
   78 #       define setlocale(Category, Locale) /* empty */
   79 #   endif /* !HAVE_SETLOCALE */
   80 #endif /* !NO_LOCALE */
   81 
   82 #define N_(Str) Str
   83 
   84 #if defined(ENABLE_NLS) && !defined(__BUILD__)
   85 #   ifdef HAVE_LIBINTL_H
   86 #       include <libintl.h>
   87 #   endif /* HAVE_LIBINTL_H */
   88 #   define _(Text)  gettext(Text)
   89 #else
   90 #   undef bindtextdomain
   91 #   define bindtextdomain(Domain, Directory) /* empty */
   92 #   undef textdomain
   93 #   define textdomain(Domain) /* empty */
   94 #   define _(Text) Text
   95 #endif /* ENABLE_NLS && !__BUILD__ */
   96 
   97 #ifndef LOCALEDIR
   98 #   define LOCALEDIR "/usr/share/locale"
   99 #endif /* !LOCALEDIR */
  100 
  101 #if defined(__amiga__) || defined(__amiga)
  102 #   define SMALL_MEMORY_MACHINE
  103 #endif /* __amiga__ || __amiga */
  104 
  105 #include <signal.h>
  106 
  107 enum context { cMain, cArt, cAttachment, cAttrib, cConfig, cFilter, cGroup, cInfopager, cPage, cPOSTED, cPost, cPostCancel, cPostFup, cReconnect, cScope, cSelect, cThread, cURL };
  108 enum icontext { cNone, cGetline, cPromptCONT, cPromptSLK, cPromptYN };
  109 enum resizer { cNo, cYes, cRedraw };
  110 enum rc_state { RC_IGNORE, RC_UPGRADE, RC_DOWNGRADE, RC_ERROR };
  111 
  112 #include <stdio.h>
  113 #ifdef HAVE_ERRNO_H
  114 #   include <errno.h>
  115 #else
  116 #   ifdef HAVE_SYS_ERRNO_H
  117 #       include <sys/errno.h>
  118 /*
  119     #   else
  120     #       error "No errno.h or sys/errno.h found"
  121 */
  122 #   endif /* HAVE_SYS_ERRNO_H */
  123 #endif /* HAVE_ERRNO_H */
  124 #if !defined(errno)
  125 #   ifdef DECL_ERRNO
  126         extern int errno;
  127 #   endif /* DECL_ERRNO */
  128 #endif /* !errno */
  129 #if !defined(EHOSTUNREACH)
  130 #   define EHOSTUNREACH 113
  131 #endif /* !EHOSTUNREACH */
  132 
  133 #ifdef HAVE_STDDEF_H
  134 #   include <stddef.h>
  135 #endif /* HAVE_STDDEF_H */
  136 #ifdef HAVE_SYS_TYPES_H
  137 #   include <sys/types.h>
  138 #endif /* HAVE_SYS_TYPES_H */
  139 
  140 #ifdef HAVE_SYS_STAT_H
  141 #   include <sys/stat.h>
  142 #endif /* HAVE_SYS_STAT_H */
  143 
  144 #ifdef TIME_WITH_SYS_TIME
  145 #   include <sys/time.h>
  146 #   include <time.h>
  147 #else
  148 #   ifdef HAVE_SYS_TIME_H
  149 #       include <sys/time.h>
  150 #   else
  151 #       include <time.h>
  152 #   endif /* HAVE_SYS_TIME_H */
  153 #endif /* TIME_WITH_SYS_TIME */
  154 
  155 #ifdef HAVE_SYS_TIMES_H
  156 #   include <sys/times.h>
  157 #endif /* HAVE_SYS_TIMES_H */
  158 
  159 #if defined(HAVE_LIBC_H) && defined(__NeXT__)
  160 #   include <libc.h>
  161 #endif /* HAVE_LIBC_H && __NeXT__ */
  162 
  163 #ifdef HAVE_UNISTD_H
  164 #   include <unistd.h>
  165 #endif /* HAVE_UNISTD_H */
  166 
  167 #ifdef HAVE_PWD_H
  168 #   include <pwd.h>
  169 #endif /* HAVE_PWD_H */
  170 
  171 #ifdef HAVE_SYS_PARAM_H
  172 #   include <sys/param.h>
  173 #endif /* HAVE_SYS_PARAM_H */
  174 
  175 #include <ctype.h>
  176 
  177 #ifdef HAVE_STDLIB_H
  178 #   include <stdlib.h>
  179 #endif /* HAVE_STDLIB_H */
  180 
  181 #include <stdarg.h>
  182 
  183 #ifdef HAVE_GETOPT_H
  184 #   include <getopt.h>
  185 #endif /* HAVE_GETOPT_H */
  186 
  187 #if defined(ENABLE_LONG_ARTICLE_NUMBERS) && !defined(SMALL_MEMORY_MACHINE)
  188 /*
  189  * defines and typedefs for 64 bit article numbers
  190  *
  191  * TODO: what if !CPP_DOES_CONCAT
  192  *       add configure check for PRIdLEAST64
  193  *       add configure check for SCNdLEAST64
  194  */
  195 #   if defined(HAVE_INT_LEAST64_T) && !defined(HAVE_INTTYPES_H)
  196 #       undef HAVE_INT_LEAST64_T
  197 #   endif /* HAVE_INT_LEAST64_T && !HAVE_INTTYPES_H */
  198 #   if defined(HAVE_INT_LEAST64_T) || defined(HAVE_LONG_LONG) || defined(quad_t)
  199 #       if defined(HAVE_ATOLL) || defined(HAVE_ATOQ)
  200 #           ifdef HAVE_STRTOLL
  201 #               define USE_LONG_ARTICLE_NUMBERS 1
  202 #           endif /* HAVE_STRTOLL */
  203 #       endif /* HAVE_ATOLL || HAVE_ATOQ */
  204 #   endif /* HAVE_INT_LEAST64_T || HAVE_LONG_LONG || quad_t */
  205 #   ifdef HAVE_STDINT_H
  206 #       include <stdint.h>
  207 #   endif   /* HAVE_STDINT_H */
  208 #endif /* ENABLE_LONG_ARTICLE_NUMBERS && !SMALL_MEMORY_MACHINE */
  209 #ifdef USE_LONG_ARTICLE_NUMBERS
  210 #   if defined(HAVE_INT_LEAST64_T) && defined(HAVE_INT64_C)
  211 #       include <inttypes.h>
  212         typedef int_least64_t t_artnum;
  213 #       define T_ARTNUM_PFMT PRIdLEAST64
  214 #       define T_ARTNUM_SFMT SCNdLEAST64
  215 #       define T_ARTNUM_CONST(v) INT64_C(v)
  216 #   else
  217         typedef long long t_artnum;
  218 #       define T_ARTNUM_PFMT "lld"
  219 #       define T_ARTNUM_SFMT "lld"
  220 #       define T_ARTNUM_CONST(v) v ## LL
  221 #   endif /* HAVE_INT_LEAST64_T && HAVE_INT64_C */
  222 #   ifdef HAVE_ATOLL
  223 #       define atoartnum atoll
  224 #   else
  225 #       define atoartnum atoq
  226 #   endif /* HAVE_ATOLL */
  227 #   define strtoartnum strtoll
  228 #else
  229     typedef long t_artnum;
  230 #   define T_ARTNUM_PFMT "ld"
  231 #   define T_ARTNUM_SFMT "ld"
  232 #   define T_ARTNUM_CONST(v) v ## L
  233 #   define atoartnum atol
  234 #   define strtoartnum strtol
  235 #endif /* USE_LONG_ARTICLE_NUMBERS */
  236 
  237 /*
  238  * FIXME: make this autoconf
  239  */
  240 #ifndef __QNX__
  241 #   ifdef HAVE_STRING_H
  242 #       include <string.h>
  243 #   else
  244 #       ifdef HAVE_STRINGS_H
  245 #           include <strings.h>
  246 #       endif /* HAVE_STRINGS_H */
  247 #   endif /* HAVE_STRING_H */
  248 #else
  249 #   ifdef HAVE_STRING_H
  250 #       include <string.h>
  251 #   endif /* HAVE_STRING_H */
  252 #   ifdef HAVE_STRINGS_H
  253 #       include <strings.h>
  254 #   endif /* HAVE_STRINGS_H */
  255 #endif /* !__QNX__ */
  256 
  257 /*
  258  * FIXME: make this autoconf
  259  */
  260 #ifdef SEIUX
  261 #   include <bsd/sys/time.h>
  262 #   include <bsd/sys/signal.h>
  263 #   include <bsd/sys/types.h>
  264 #   include <posix/unistd.h>
  265 #   include <bsd/netinet/in.h>
  266 #endif /* SEIUX */
  267 /* *-next-nextstep3 && *-next-openstep4 */
  268 #ifdef __NeXT__
  269 #   undef HAVE_SYS_UTSNAME_H
  270 #   undef HAVE_UNAME
  271 #   undef WEXITSTATUS
  272 #   undef WIFEXITED
  273 #   define IGNORE_SYSTEM_STATUS 1
  274 #   define HAVE_SYS_WAIT_H 1
  275 #   define NO_LOCKING 1
  276 #endif /* __NeXT__ */
  277 /* m68k-sun-sunos3.5 */
  278 #if defined(sun) || defined(__sun) && (!defined(__SVR4) || !defined(__svr4__)) && defined(BSD) && BSD < 199306
  279 #   define IGNORE_SYSTEM_STATUS 1
  280 #endif /* sun|| __sun && (!__SVR4 || __svr4__) && BSD && BSD < 199306 */
  281 
  282 #ifdef HAVE_FCNTL_H
  283 #   include <fcntl.h>
  284 #endif /* HAVE_FCNTL_H */
  285 
  286 #ifdef HAVE_SYS_IOCTL_H
  287 #   include <sys/ioctl.h>
  288 /* We don't need/use these, and they cause redefinition errors with SunOS 4.x
  289  * when we include termio.h or termios.h
  290  */
  291 #   if defined(sun) && !defined(__svr4)
  292 #       undef NL0
  293 #       undef NL1
  294 #       undef CR0
  295 #       undef CR1
  296 #       undef CR2
  297 #       undef CR3
  298 #       undef TAB0
  299 #       undef TAB1
  300 #       undef TAB2
  301 #       undef XTABS
  302 #       undef BS0
  303 #       undef BS1
  304 #       undef FF0
  305 #       undef FF1
  306 #       undef ECHO
  307 #       undef NOFLSH
  308 #       undef TOSTOP
  309 #       undef FLUSHO
  310 #       undef PENDIN
  311 #   endif /* sun && !__svr4 */
  312 #endif /* HAVE_SYS_IOCTL_H */
  313 
  314 #ifdef HAVE_PROTOTYPES_H
  315 #   include <prototypes.h>
  316 #endif /* HAVE_PROTOTYPES_H */
  317 
  318 #ifdef HAVE_SYS_UTSNAME_H
  319 #   include <sys/utsname.h>
  320 #endif /* HAVE_SYS_UTSNAME_H */
  321 
  322 /*
  323  * Needed for catching child processes
  324  */
  325 #ifdef HAVE_SYS_WAIT_H
  326 #   include <sys/wait.h>
  327 #endif /* HAVE_SYS_WAIT_H */
  328 
  329 #ifndef WEXITSTATUS
  330 #   define WEXITSTATUS(status)  ((int) (((status) >> 8) & 0xFF))
  331 #endif /* !WEXITSTATUS */
  332 
  333 #ifndef WIFEXITED
  334 #   define WIFEXITED(status)    ((int) (((status) & 0xFF) == 0))
  335 #endif /* !WIFEXITED */
  336 
  337 /*
  338  * Needed for timeout in user abort of indexing a group (BSD & SYSV variaties)
  339  */
  340 #ifdef HAVE_SYS_SELECT_H
  341 #   ifdef NEED_TIMEVAL_FIX
  342 #       define timeval fake_timeval
  343 #       include <sys/select.h>
  344 #       undef timeval
  345 #   else
  346 #       include <sys/select.h>
  347 #   endif /* NEED_TIMEVAL_FIX */
  348 #endif /* HAVE_SYS_SELECT_H */
  349 
  350 #if defined(HAVE_STROPTS_H) && !defined(__dietlibc__)
  351 #   include <stropts.h>
  352 #endif /* HAVE_STROPTS_H && !__dietlibc__ */
  353 
  354 #ifdef HAVE_POLL_H
  355 #   include <poll.h>
  356 #else
  357 #   ifdef HAVE_SYS_POLL_H
  358 #       include <sys/poll.h>
  359 #   endif /* HAVE_SYS_POLL_H */
  360 #endif /* HAVE_POLL_H */
  361 
  362 /*
  363  * Directory handling code
  364  */
  365 #ifdef HAVE_DIRENT_H
  366 #   include <dirent.h>
  367 /* #    define NAMLEN(dirent) strlen((dirent)->d_name) */
  368 #else
  369 #   define dirent direct
  370 /* #    define NAMLEN(dirent) (dirent)->d_namlen */
  371 #   ifdef HAVE_SYS_NDIR_H
  372 #       include <sys/ndir.h>
  373 #   endif /* HAVE_SYS_NDIR_H */
  374 #   ifdef HAVE_SYS_DIR_H
  375 #       include <sys/dir.h>
  376 #   endif /* HAVE_SYS_DIR_H */
  377 #   ifdef HAVE_NDIR_H
  378 #       include <ndir.h>
  379 #   endif /* HAVE_NDIR_H */
  380 #endif /* HAVE_DIRENT_H */
  381 
  382 #ifndef DIR_BUF
  383 #   define DIR_BUF struct dirent
  384 #endif /* !DIR_BUF */
  385 
  386 #ifndef HAVE_UNLINK
  387 #   define unlink(file) remove(file)
  388 #endif /* !HAVE_UNLINK */
  389 
  390 /*
  391  * If native OS hasn't defined STDIN_FILENO be a smartass and do it
  392  */
  393 #if !defined(STDIN_FILENO)
  394 #   define STDIN_FILENO 0
  395 #endif /* !STDIN_FILENO */
  396 
  397 /*
  398  * include <paths.h> if available to define _PATH_TMP
  399  */
  400 #ifdef HAVE_PATHS_H
  401 #   include <paths.h>
  402 #endif /* HAVE_PATHS_H */
  403 #ifndef _PATH_TMP
  404 #   define _PATH_TMP    "/tmp/"
  405 #endif /* _PATH_TMP */
  406 
  407 /*
  408  * If OS misses the isascii() function
  409  */
  410 #if !defined(HAVE_ISASCII) && !defined(isascii)
  411 #   define isascii(c) (!((c) & ~0177))
  412 #endif /* !HAVE_ISASCII && !isascii */
  413 
  414 
  415 /*
  416  * any pgp/gpp support possible and wanted
  417  * sort out possible conflicts: gpg is preferred over pgp5 over pgp
  418  */
  419 #if defined(HAVE_PGP) || defined(HAVE_PGPK) || defined(HAVE_GPG)
  420 #   define HAVE_PGP_GPG 1
  421 #   if defined(HAVE_PGP) && defined(HAVE_PGPK)
  422 #       undef HAVE_PGP
  423 #   endif /* HAVE_PGP && HAVE_PGPK */
  424 #   if defined(HAVE_PGPK) && defined(HAVE_GPG)
  425 #       undef HAVE_PGPK
  426 #   endif /* HAVE_PGPK && HAVE_GPG */
  427 #   if defined(HAVE_PGP) && defined(HAVE_GPG)
  428 #       undef HAVE_PGP
  429 #   endif /* HAVE_PGP && HAVE_GPG */
  430 #endif /* HAVE_PGP || HAVE_PGPK || HAVE_GPG */
  431 
  432 /*
  433  * slrnface requires some things
  434  */
  435 #if defined(HAVE_SLRNFACE) && defined(HAVE_MKFIFO) && defined(HAVE_FORK) && defined(HAVE_EXECLP) && defined(HAVE_WAITPID) && !defined(DONT_HAVE_PIPING) && !defined(X_DISPLAY_MISSING)
  436 #   define XFACE_ABLE
  437 #endif /* HAVE_SLRNFACE && HAVE_MKFIFO && HAVE_FORK && HAVE_EXECLP && HAVE_WAITPID && !DONT_HAVE_PIPING && !X_DISPLAY_MISSING */
  438 
  439 /*
  440  * Setup support for reading from NNTP
  441  */
  442 #if defined(NNTP_ABLE) || defined(NNTP_ONLY)
  443 #   ifndef NNTP_ABLE
  444 #       define NNTP_ABLE    1
  445 #   endif /* !NNTP_ABLE */
  446 #   ifndef NNTP_INEWS
  447 #       define NNTP_INEWS   1
  448 #   endif /* !NNTP_INEWS */
  449 #else
  450 #   ifdef XHDR_XREF
  451 #       undef XHDR_XREF
  452 #   endif /* XHDR_XREF */
  453 #   ifdef BROKEN_LISTGROUP
  454 #       undef BROKEN_LISTGROUP
  455 #   endif /* BROKEN_LISTGROUP */
  456 #endif /* NNTP_ABLE || NNTP_ONLY */
  457 
  458 #define FAKE_NNTP_FP        (FILE *) 9999
  459 
  460 /*
  461  * Max time between the first character of a VT terminal escape sequence
  462  * for special keys and the following characters to arrive (msec)
  463  */
  464 #define SECOND_CHARACTER_DELAY  200
  465 
  466 /*
  467  * Maximum time (seconds) for a VT terminal escape sequence
  468  */
  469 #define VT_ESCAPE_TIMEOUT   1
  470 
  471 /*
  472  * Determine machine configuration for external programs & directories
  473  */
  474 #if defined(BSD)
  475 /*
  476  * To catch 4.3 Net2 code base or newer
  477  * (e.g. FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 and below).
  478  * use
  479  * #if (defined(BSD) && (BSD >= 199103))
  480  *
  481  * To detect if the code is being compiled on a 4.4 code base or newer
  482  * (e.g. FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 or above).
  483  * use
  484  * #if (defined(BSD) && (BSD >= 199306))
  485  *
  486  * (defined in <sys/param.h>)
  487  */
  488 #   ifndef HAVE_MEMCMP
  489 #       define memcmp(s1, s2, n)    bcmp(s2, s1, n)
  490 #   endif /* !HAVE_MEMCMP */
  491 #   ifndef HAVE_MEMCPY
  492 #       define memcpy(s1, s2, n)    bcopy(s2, s1, n)
  493 #   endif /* !HAVE_MEMCPY */
  494 #   ifndef HAVE_MEMSET
  495 #       define memset(s1, s2, n)    bfill(s1, n, s2)
  496 #   endif /* !HAVE_MEMSET */
  497 #   ifndef HAVE_STRCHR
  498 #       define strchr(str, ch)  index(str, ch)
  499 #   endif /* !HAVE_STRCHR */
  500 #   ifndef HAVE_STRRCHR
  501 #       define strrchr(str, ch) rindex(str, ch)
  502 #   endif /* !HAVE_STRRCHR */
  503 #   if defined(__386BSD__) || defined(__bsdi__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
  504 #       define DEFAULT_PRINTER  "/usr/bin/lpr"
  505 #       define DEFAULT_SUM  "/usr/bin/cksum -o 1 <" /* use tailing <, otherwise get filename output too */
  506 #   else
  507 #       define DEFAULT_PRINTER  "/usr/ucb/lpr"
  508 #       define DEFAULT_SUM  "sum"
  509 #   endif /* __386BSD__ || __bsdi__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
  510 #   ifdef DGUX
  511 #       define USE_INVERSE_HACK
  512 #   endif /* DGUX */
  513 #   ifdef pyr
  514 #       define DEFAULT_MAILER   "/usr/.ucbucb/mail"
  515 #   endif /* pyr */
  516 #else /* !BSD */
  517 #   ifdef linux
  518 #       define DEFAULT_PRINTER  "/usr/bin/lpr"
  519 #   endif /* linux */
  520 #   ifdef QNX42
  521 #       ifndef DEFAULT_EDITOR
  522 #           define DEFAULT_EDITOR   "/bin/vedit"
  523 #       endif /* !DEFAULT_EDITOR */
  524 #   endif /* QNX42 */
  525 #   ifdef _AIX
  526 #       define DEFAULT_PRINTER  "/bin/lp"
  527 #       define READ_CHAR_HACK
  528 #   endif /* _AIX */
  529 #   ifdef sinix
  530 #       define DEFAULT_PRINTER  "/bin/lpr"
  531 #   endif /* sinix */
  532 #   ifdef sysV68
  533 #       define DEFAULT_MAILER   "/bin/rmail"
  534 #   endif /* sysV68 */
  535 #   ifdef UNIXPC
  536 #       define DEFAULT_MAILER   "/bin/rmail"
  537 #   endif /* UNIXPC */
  538 
  539 #   ifndef DEFAULT_PRINTER
  540 #       define DEFAULT_PRINTER  "/usr/bin/lp"
  541 #   endif /* !DEFAULT_PRINTER */
  542 #   ifndef PATH_SUM
  543 #       define DEFAULT_SUM  "sum -r"
  544 #   endif /* !PATH_SUM */
  545 #endif /* BSD */
  546 
  547 /*
  548  * fallback values
  549  */
  550 #ifndef DEFAULT_EDITOR
  551 #   define DEFAULT_EDITOR   "/usr/bin/vi"
  552 #endif /* !DEFAULT_EDITOR */
  553 #ifndef DEFAULT_MAILER
  554 #   define DEFAULT_MAILER   "/usr/lib/sendmail"
  555 #endif /* !DEFAULT_MAILER */
  556 #ifndef DEFAULT_MAILBOX
  557 #   define DEFAULT_MAILBOX  "/usr/spool/mail"
  558 #endif /* !DEFAULT_MAILBOX */
  559 
  560 
  561 /* FIXME: remove absolute-paths! */
  562 /*
  563  * Miscellaneous program-paths
  564  */
  565 #ifndef PATH_ISPELL
  566 #   define PATH_ISPELL  "ispell"
  567 #endif /* !PATH_ISPELL */
  568 
  569 #ifndef PATH_METAMAIL   /* only unset if !HAVE_METAMAIL */
  570 #   define PATH_METAMAIL    "metamail"
  571 #endif /* !PATH_METAMAIL */
  572 #define METAMAIL_CMD        PATH_METAMAIL" -e -p -m \"tin\""
  573 
  574 #define INTERNAL_CMD    "--internal"
  575 
  576 /*
  577  * Fix up the 'sum' path and parameter for './configure'd systems
  578  */
  579 #ifdef PATH_SUM
  580 #   ifdef DEFAULT_SUM
  581 #       undef DEFAULT_SUM
  582 #   endif /* DEFAULT_SUM */
  583 #   ifdef SUM_TAKES_DASH_R
  584 #       define DEFAULT_SUM PATH_SUM_R
  585 #   else
  586 #       define DEFAULT_SUM PATH_SUM
  587 #   endif /* SUM_TAKES_DASH_R */
  588 #endif /* PATH_SUM */
  589 
  590 #ifdef HAVE_LONG_FILE_NAMES
  591 #   define PATH_PART    "part"
  592 #   define PATH_PATCH   "patch"
  593 #   define INDEX_LOCK   "tin.%s.LCK"
  594 #else
  595 #   define PATH_PART    ""
  596 #   define PATH_PATCH   "p"
  597 #   define INDEX_LOCK   "%s.LCK"
  598 #endif /* HAVE_LONG_FILE_NAMES */
  599 
  600 /* inews.c:submit_inews() and save.c:save_and_process_art() */
  601 #define PATHMASTER  "not-for-mail"
  602 
  603 /*
  604  * How often should the active file be reread for new news
  605  */
  606 #ifndef REREAD_ACTIVE_FILE_SECS
  607 #   define REREAD_ACTIVE_FILE_SECS 1200 /* seconds (20 mins) */
  608 #endif /* !REREAD_ACTIVE_FILE_SECS */
  609 
  610 /*
  611  * Initial sizes of internal arrays for small (<4MB) & large memory machines
  612  */
  613 #ifdef SMALL_MEMORY_MACHINE
  614 #   define DEFAULT_ARTICLE_NUM  600
  615 #   define DEFAULT_SAVE_NUM 10
  616 #else
  617 #   define DEFAULT_ARTICLE_NUM  1200
  618 #   define DEFAULT_SAVE_NUM 30
  619 #endif /* SMALL_MEMORY_MACHINE */
  620 #define DEFAULT_ACTIVE_NUM  1800
  621 #define DEFAULT_NEWNEWS_NUM 5
  622 #define DEFAULT_MAPKEYS_NUM 100 /* ~remappable keys per level (avoid massiv reallocs) */
  623 #define DEFAULT_SCOPE_NUM   8
  624 
  625 #define RCDIR   ".tin"
  626 #define INDEX_MAILDIR   ".mail"
  627 #define INDEX_NEWSDIR   ".news"
  628 #define INDEX_SAVEDIR   ".save"
  629 
  630 #define ACTIVE_FILE "active"
  631 #define ACTIVE_MAIL_FILE    "active.mail"
  632 #define ACTIVE_SAVE_FILE    "active.save"
  633 #define ACTIVE_TIMES_FILE   "active.times"
  634 #define ATTRIBUTES_FILE "attributes"
  635 #define CONFIG_FILE "tinrc"
  636 #define SERVERCONFIG_FILE   "serverrc"
  637 #define DEFAULT_MAILDIR "Mail"
  638 #define DEFAULT_SAVEDIR "News"
  639 #define DEFAULT_URL_HANDLER "url_handler.pl"
  640 /* Prefixes saved attachments with no set filename */
  641 #define SAVEFILE_PREFIX     "unknown"
  642 
  643 
  644 /* MMDF-mailbox separator */
  645 #ifndef MMDFHDRTXT
  646 #   define MMDFHDRTXT "\01\01\01\01\n"
  647 #endif /* MMDFHDRTXT */
  648 
  649 
  650 /*
  651  * all regexps are extended -> # must be quoted!
  652  */
  653 #ifdef HAVE_COLOR
  654 /* case insensitive */
  655 #   define DEFAULT_QUOTE_REGEX  "^\\s{0,3}(?:[\\]{}>|:)]|\\w{1,3}[>|])(?!-)"
  656 #   define DEFAULT_QUOTE_REGEX2 "^\\s{0,3}(?:(?:[\\]{}>|:)]|\\w{1,3}[>|])\\s*){2}(?!-[})>])"
  657 #   define DEFAULT_QUOTE_REGEX3 "^\\s{0,3}(?:(?:[\\]{}>|:)]|\\w{1,3}[>|])\\s*){3}"
  658 #endif /* HAVE_COLOR */
  659 
  660 /* case insensitive */
  661 #if 0 /* single words only */
  662 #   define DEFAULT_SLASHES_REGEX    "(?:^|(?<=\\s))/[^\\s/]+/(?:(?=[,.!?;]?\\s)|$)"
  663 #   define DEFAULT_STARS_REGEX  "(?:^|(?<=\\s))\\*[^\\s*]+\\*(?:(?=[,.!?;]?\\s)|$)"
  664 #   define DEFAULT_UNDERSCORES_REGEX    "(?:^|(?<=\\s))_[^\\s_]+_(?:(?=[,.!?;]?\\s)|$)"
  665 #   define DEFAULT_STROKES_REGEX    "(?:^|(?<=\\s))-[^-\\s]+-(?:(?=[,.!?;]?\\s)|$)"
  666 #else /* multiple words */
  667 #   define DEFAULT_SLASHES_REGEX    "(?:^|(?<=\\s))/(?(?=[^-*/_\\s][^/\\s])[^-*/_\\s][^/]*[^-*/_\\s]|[^/\\s])/(?:(?=[,.!?;]?\\s)|$)"
  668 #   define DEFAULT_STARS_REGEX  "(?:^|(?<=\\s))\\*(?(?=[^-*/_\\s][^*\\s])[^-*/_\\s][^*]*[^-*/_\\s]|[^*\\s])\\*(?:(?=[,.!?;]?\\s)|$)"
  669 #   define DEFAULT_UNDERSCORES_REGEX    "(?:^|(?<=\\s))_(?(?=[^-*/_\\s][^_\\s])[^-*/_\\s][^_]*[^-*/_\\s]|[^_\\s])_(?:(?=[,.!?;]?\\s)|$)"
  670 #   define DEFAULT_STROKES_REGEX    "(?:^|(?<=\\s))-(?(?=[^-*/_\\s][^-\\s])[^-*/_\\s][^-]*[^-*/_\\s]|[^-\\s])-(?:(?=[,.!?;]?\\s)|$)"
  671 #endif /* 0 */
  672 
  673 /* case sensitive && ^-anchored */
  674 #define DEFAULT_STRIP_RE_REGEX  "(?:R[eE](?:\\^\\d+|\\[\\d+\\])?|A[wW]|Odp|Sv):\\s"
  675 /* case sensitive */
  676 #define DEFAULT_STRIP_WAS_REGEX "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\\xb3]o):.*\\)\\s*$"
  677 #define DEFAULT_U8_STRIP_WAS_REGEX  "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\\x{0142}]o):.*\\)\\s*$"
  678 /*
  679  * overkill regexp for balanced '()':
  680  * #define DEFAULT_STRIP_WAS_REGEX  "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\xb3]o):(?:(?:[^)(])*(?:\\([^)(]*\\))*)+\\)\\s*$"
  681  */
  682 
  683 /* case sensitive & ^-anchored */
  684 #define UUBEGIN_REGEX   "begin\\s\\s?[0-7]{3,4}\\s+"
  685 /* case sensitive & ^-anchored */
  686 #define UUBODY_REGEX    "(?:`|.[\\x20-\\x60]{1,61})$"
  687 
  688 /* case sensitive & ^-anchored */
  689 #define SHAR_REGEX  "\\#(?:!\\s?(?:/usr)?/bin/sh|\\s?(?i)this\\sis\\sa\\sshell\\sarchive)"
  690 
  691 /* slrn verbatim marks, case sensitive & ^-anchored */
  692 #define DEFAULT_VERBATIM_BEGIN_REGEX    "#v\\+\\s$"
  693 #define DEFAULT_VERBATIM_END_REGEX  "#v-\\s$"
  694 
  695 /* quoted text from external sources */
  696 #define DEFAULT_EXTQUOTE_REGEX "^\\|\\s"
  697 
  698 /*
  699  * URL related regexs:
  700  * add TELNET (RFC 4248), WAIS (RFC 4156), IMAP (RFC 2192), NFS (RFC 2224)
  701  *     LDAP (RFC 2255), POP (RFC 2384)
  702  * add IPv6 (RFC 2732, RFC 2373) support
  703  */
  704 /*
  705  * case insensitive
  706  * TODO: - split out ftp (only ftp allows username:passwd@, RFC 1738)?
  707  *       - test IDNA (RFC 3490) case
  708  */
  709 #define URL_REGEX   "\\b(?:https?|ftp|gopher)://(?:[^:@/\\s]*(?::[^:@/\\s]*)?@)?(?:(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?|xn--[^\\W_](?:-(?!-)|[^\\W_]){1,57}[^\\W_])\\.)+[a-z]{2,14}\\.?|localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)|\\[(?:(?:[0-9A-F]{0,4}:){1,7}[0-9A-F]{1,4}|(?:[0-9A-F]{0,4}:){1,3}(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))\\])(?::\\d+)?(?(?=[^\\)\\]\\>\"\\s]*\\()(?:/[^\\]\\>\"\\s]*|$|(?=[)\\]\\>\"\\s]))|(?:/[^)\\]\\>\"\\s]*|$|(?=[)\\]\\>\"\\s])))"
  710 /*
  711  * case insensitive
  712  * TOFO: check against RFC 6068
  713  */
  714 #define MAIL_REGEX  "\\b(?:mailto:(?:[-\\w$.+!*'(),;/?:@&=]|%[\\da-f]{2})+)(?<!\\))"
  715 /*
  716  * case insensitive
  717  * TODO: check against RFC 5538
  718  */
  719 #define NEWS_REGEX "\\b(?:s?news|nntp):(?:(?:(?://(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?|xn--[^\\W_](?:-(?!-)|[^\\W_]){1,57}[^\\W_])\\.)+[a-z]{2,14}\\.?|localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))(?::\\d+)?(?(?=[/])[^()\\^\\[\\]{}\\|\\x00-\\x1f\\x7f\\s\"<>'\\\\:,;]+|$))|[^\\^\\[\\]{}\\|\\x00-\\x1f\\x7f\\s<>\"():,;\\\\'/]+)\\b"
  720 
  721 #if 0 /* not implemented */
  722 /*
  723  * case insensitive
  724  */
  725 #   define TELNET_REGEX "\\btelnet://(?:[^:@/]*(?::[^:@/]*)?@)?(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?\\.)+[a-z]{2,14}\\.?||localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))(?::\\d+)?/?"
  726 #endif /* 0 */
  727 
  728 
  729 #define FILTER_FILE "filter"
  730 #define INPUT_HISTORY_FILE  ".inputhistory"
  731 #ifdef HAVE_MH_MAIL_HANDLING
  732 #   define MAILGROUPS_FILE  "mailgroups"
  733 #endif /* HAVE_MH_MAIL_HANDLING */
  734 #define NEWSRC_FILE ".newsrc"
  735 #define NEWSRCTABLE_FILE    "newsrctable"
  736 /* ifdef APPEND_PID (default) NEWNEWSRC_FILE will be .newnewsrc<pid> */
  737 #define NEWNEWSRC_FILE  ".newnewsrc"
  738 #define OLDNEWSRC_FILE  ".oldnewsrc"
  739 #ifndef OVERVIEW_FILE
  740 #   define OVERVIEW_FILE    ".overview"
  741 #endif /* !OVERVIEW_FILE */
  742 #define OVERVIEW_FMT    "overview.fmt"
  743 #define POSTED_FILE "posted"
  744 #define POSTPONED_FILE  "postponed.articles"
  745 #define SUBSCRIPTIONS_FILE  "subscriptions"
  746 #define NEWSGROUPS_FILE "newsgroups"
  747 #define KEYMAP_FILE "keymap"
  748 
  749 #define SIGDASHES "-- \n"
  750 
  751 #ifndef BOOL_H
  752 #   include "bool.h"
  753 #endif /* BOOL_H */
  754 
  755 /* Philip Hazel's Perl regular expressions library */
  756 #include <pcre.h>
  757 
  758 #ifdef HAVE_ICONV
  759 #   define CHARSET_CONVERSION 1
  760 #   ifdef HAVE_ICONV_H
  761 #       include <iconv.h>
  762 #   endif /* HAVE_ICONV_H */
  763 #endif /* HAVE_ICONV */
  764 
  765 #ifdef HAVE_LANGINFO_H
  766 #   include <langinfo.h>
  767 #else
  768 #   ifdef HAVE_NL_TYPES_H
  769 #       include <nl_types.h>
  770 #   endif /* HAVE_NL_TYPES_H */
  771 #endif /* HAVE_LANGINFO_H */
  772 #ifndef HAVE_NL_ITEM
  773     typedef int nl_item;
  774 #endif /* HAVE_NL_ITEM */
  775 #ifndef CODESET
  776 #   define CODESET ((nl_item) 1)
  777 #endif /* CODESET */
  778 
  779 #ifdef CHARSET_CONVERSION
  780 #   define IS_LOCAL_CHARSET(c)  (!strncasecmp(tinrc.mm_local_charset, c, strlen(c)))
  781 #else
  782 #   define IS_LOCAL_CHARSET(c)  (!strncasecmp(tinrc.mm_charset, c, strlen(c)))
  783 #endif /* CHARSET_CONVERSION */
  784 
  785 /* TODO: move up to the 'right' place */
  786 #ifdef HAVE_SYS_FILE_H
  787 #   include <sys/file.h>
  788 #endif /* HAVE_SYS_FILE_H */
  789 
  790 #ifdef HAVE_LIBUTF8_H
  791 #   include <libutf8.h>
  792 #else
  793 /*
  794  * order is important here:
  795  * - Solaris 2.5.1 requires wchar.h before wctype.h
  796  * - Tru64 with Desktop Toolkit C requires stdio.h before wchar.h
  797  * - BSD/OS 4.0.1 requires stddef.h, stdio.h and time.h before wchar.h
  798  */
  799 #   ifdef HAVE_WCHAR_H
  800 #       include <wchar.h>
  801 #   endif /* HAVE_WCHAR_H */
  802 #   ifdef HAVE_WCTYPE_H
  803 #       include <wctype.h>
  804 #   endif /* HAVE_WCTYPE_H */
  805 #endif /* HAVE_LIBUTF8_H */
  806 
  807 #ifndef MAX
  808 #   define MAX(a,b) (((a) > (b)) ? (a) : (b))
  809 #endif /* !MAX */
  810 #ifndef MIN
  811 #   define MIN(a,b) (((a) > (b)) ? (b) : (a))
  812 #endif /* !MIN */
  813 
  814 #ifndef forever
  815 /*@notfunction@*/
  816 #   define forever  for(;;)
  817 #endif /* !forever */
  818 
  819 /* safe strcpy into fixed-legth buffer */
  820 #define STRCPY(dst, src)    (dst[sizeof(dst) - 1] = '\0', strncpy(dst, src, sizeof(dst) - 1))
  821 
  822 #define STRCMPEQ(s1, s2)    (strcmp((s1), (s2)) == 0)
  823 #define STRNCMPEQ(s1, s2, n)    (strncmp((s1), (s2), n) == 0)
  824 #define STRNCASECMPEQ(s1, s2, n)    (strncasecmp((s1), (s2), n) == 0)
  825 
  826 /*
  827  * PATH_LEN    = max. path length (incl. terminating '\0')
  828  * NAME_LEN    = max. filename length (not incl. terminating '\0')
  829  * LEN         =
  830  * HEADER_LEN  = max. size of a news/mail header-line
  831  * NEWSRC_LINE =
  832  */
  833 
  834 #ifdef PATH_MAX
  835 #   define PATH_LEN PATH_MAX
  836 #else
  837 #   ifdef MAXPATHLEN
  838 #       define PATH_LEN MAXPATHLEN
  839 #   else
  840 #       ifdef _POSIX_PATH_MAX
  841 #           define PATH_LEN _POSIX_PATH_MAX
  842 #       else
  843 #           define PATH_LEN 255
  844 #       endif /* _POSIX_PATH_MAX */
  845 #   endif /* MAXPATHLEN */
  846 #endif /* PATH_MAX */
  847 #ifdef HAVE_LONG_FILE_NAMES
  848 #   ifdef NAME_MAX
  849 #       define NAME_LEN NAME_MAX
  850 #   else
  851 #       ifdef _POSIX_NAME_MAX
  852 #           define NAME_LEN _POSIX_NAME_MAX
  853 #       else
  854 #           define NAME_LEN 14
  855 #       endif /* _POSIX_NAME_MAX */
  856 #   endif /* NAME_MAX */
  857 #else
  858 #   define NAME_LEN 14
  859 #endif /* HAVE_LONG_FILE_NAMES */
  860 #define LEN 1024
  861 
  862 #define NEWSRC_LINE 8192
  863 #define HEADER_LEN  1024
  864 #define IMF_LINE_LEN 998 /* RFC 5322 2.1.1 */
  865 
  866 #define TABLE_SIZE  1409
  867 
  868 #define MODULO_COUNT_NUM    50
  869 
  870 #define DAY (60*60*24)      /* Seconds in a day */
  871 
  872 #define ctrl(c) ((c) & 0x1F)
  873 
  874 #ifndef DEFAULT_ISO2ASC
  875 #   define DEFAULT_ISO2ASC  "-1 "   /* ISO -> ASCII charset conversion */
  876 #endif /* !DEFAULT_ISO2ASC */
  877 
  878 #ifndef DEFAULT_COMMENT
  879 #   define DEFAULT_COMMENT  "> "    /* used when by follow-ups & replies */
  880 #endif /* !DEFAULT_COMMENT */
  881 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  882 #   define T_CHAR_FMT "lc"
  883 #else
  884 #   define T_CHAR_FMT "c"
  885 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  886 #ifndef ART_MARK_UNREAD
  887 #   define ART_MARK_UNREAD  '+' /* used to show that an art is unread */
  888 #endif /* !ART_MARK_UNREAD */
  889 #ifndef ART_MARK_RETURN
  890 #   define ART_MARK_RETURN  '-' /* used to show that an art will return */
  891 #endif /* !ART_MARK_RETURN */
  892 #ifndef ART_MARK_SELECTED
  893 #   define ART_MARK_SELECTED    '*' /* used to show that an art was auto selected */
  894 #endif /* !ART_MARK_SELECTED */
  895 #ifndef ART_MARK_RECENT
  896 #   define ART_MARK_RECENT  'o' /* used to show that an art is fresh */
  897 #endif /* !ART_MARK_RECENT */
  898 #ifndef ART_MARK_READ
  899 #   define ART_MARK_READ    ' ' /* used to show that an art was not read or seen */
  900 #endif /* !ART_MARK_READ */
  901 #ifndef ART_MARK_READ_SELECTED
  902 #   define ART_MARK_READ_SELECTED ':'   /* used to show that a read art is hot (kill_level >0) */
  903 #endif /* !ART_MARK_READ_SELECTED */
  904 #ifndef ART_MARK_KILLED
  905 #   define ART_MARK_KILLED 'K'      /* art has been killed (kill_level >0) */
  906 #endif /* !ART_MARK_KILLED */
  907 #ifndef ART_MARK_DELETED
  908 #   define ART_MARK_DELETED 'D' /* art has been marked for deletion (mailgroup) */
  909 #endif /* !ART_MARK_DELETED */
  910 #ifndef MARK_INRANGE
  911 #   define MARK_INRANGE '#' /* group/art within a range (# command) */
  912 #endif /* !MARK_INRANGE */
  913 
  914 
  915 /*
  916  * Unicode chars for thread and attachment tree and cursor (instead of "|+`->")
  917  * only available when IS_LOCAL_CHARSET("UTF-8")
  918  */
  919 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  920     /*
  921      * For CURSOR_ARROW and CURSOR_HORIZ tinrc.utf8_graphics ? :
  922      * is handled inside screen.c:draw_arrow_mark().
  923      */
  924 #   define CURSOR_ARROW     (wint_t) 0x25B6
  925 #   define CURSOR_HORIZ     (wint_t) 0x2500
  926 #   define TREE_ARROW       (wchar_t) (tinrc.utf8_graphics ? 0x25B6 : '>')
  927 #   define TREE_ARROW_WRAP  (wchar_t) (tinrc.utf8_graphics ? 0x25B7 : '>')
  928 #   define TREE_BLANK       (wchar_t) ' '
  929 #   define TREE_HORIZ       (wchar_t) (tinrc.utf8_graphics ? 0x2500 : '-')
  930 #   define TREE_UP_RIGHT    (wchar_t) (tinrc.utf8_graphics ? 0x2514 : '`')
  931 #   define TREE_VERT        (wchar_t) (tinrc.utf8_graphics ? 0x2502 : '|')
  932 #   define TREE_VERT_RIGHT  (wchar_t) (tinrc.utf8_graphics ? 0x251C : '+')
  933 #else
  934     /*
  935      * No need for CURSOR_ARROW and CURSOR_HORIZ here. This is handled inside
  936      * screen.c:draw_arrow_mark().
  937      */
  938 #   define TREE_ARROW       '>'
  939 #   define TREE_ARROW_WRAP  '>'
  940 #   define TREE_BLANK       ' '
  941 #   define TREE_HORIZ       '-'
  942 #   define TREE_UP_RIGHT    '`'
  943 #   define TREE_VERT        '|'
  944 #   define TREE_VERT_RIGHT  '+'
  945 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  946 
  947 #ifdef USE_INVERSE_HACK
  948 #   define BLANK_PAGE_COLS  2
  949 #else
  950 #   define BLANK_PAGE_COLS  0
  951 #endif /* USE_INVERSE_HACK */
  952 
  953 /*
  954  * Return values for tin_errno
  955  */
  956 #define TIN_ABORT       1           /* User requested abort or timeout */
  957 
  958 #define TINRC_CONFIRM_ACTION    (tinrc.confirm_choice == 1 || tinrc.confirm_choice == 4 || tinrc.confirm_choice == 5 || tinrc.confirm_choice == 7)
  959 #define TINRC_CONFIRM_TO_QUIT   (tinrc.confirm_choice == 3 || tinrc.confirm_choice == 4 || tinrc.confirm_choice == 6 || tinrc.confirm_choice == 7)
  960 #define TINRC_CONFIRM_SELECT    (tinrc.confirm_choice == 2 || tinrc.confirm_choice == 5 || tinrc.confirm_choice == 6 || tinrc.confirm_choice == 7)
  961 #define TINRC_CONFIRM_MAX   7
  962 
  963 /*
  964  * defines for tinrc.auto_cc_bcc
  965  */
  966 #define AUTO_CC                 1
  967 #define AUTO_BCC                2
  968 #define AUTO_CC_BCC             3
  969 
  970 /*
  971  * defines for tinrc.goto_next_unread
  972  */
  973 #define NUM_GOTO_NEXT_UNREAD    4
  974 #define GOTO_NEXT_UNREAD_PGDN   1
  975 #define GOTO_NEXT_UNREAD_TAB    2
  976 
  977 /*
  978  * defines for tinrc.trim_article_body
  979  */
  980 #define NUM_TRIM_ARTICLE_BODY   8
  981 #define SKIP_LEADING            1
  982 #define SKIP_TRAILING           2
  983 #define COMPACT_MULTIPLE        4
  984 
  985 /*
  986  * MIME Encodings
  987  */
  988 enum {
  989     MIME_ENCODING_8BIT = 0,
  990     MIME_ENCODING_BASE64,
  991     MIME_ENCODING_QP,
  992     MIME_ENCODING_7BIT
  993 };
  994 
  995 /*
  996  * Number of charset-traslation tables (iso2asci)
  997  */
  998 #define NUM_ISO_TABLES  7
  999 
 1000 /*
 1001  * Maximum permissible colour number
 1002  */
 1003 #define MAX_COLOR   15
 1004 #define MAX_BACKCOLOR   7
 1005 
 1006 /*
 1007  * Count of available attributes for highlighting
 1008  */
 1009 #define MAX_ATTR    6
 1010 
 1011 /*
 1012  * Maximal permissible word mark type
 1013  * 0 = nothing, 1 = mark, 2 = space
 1014  */
 1015 #define MAX_MARK    2
 1016 
 1017 /* Line number (starting at 0) of 1st non-header data on the screen */
 1018 /* ie, size of header */
 1019 #define INDEX_TOP   2
 1020 #define INDEX2LNUM(i)   (INDEX_TOP + (i) - currmenu->first)
 1021 #ifndef USE_CURSES
 1022 #   define INDEX2SNUM(i)    ((i) - currmenu->first)
 1023 #endif /* !USE_CURSES */
 1024 
 1025 #define GROUP_MATCH(s1, pat, case_s)        (wildmat(s1, pat, case_s))
 1026 
 1027 #define REGEX_FMT (tinrc.wildcard ? "%s" : "*%s*")
 1028 
 1029 #define IGNORE_ART(i)   ((tinrc.kill_level != KILL_THREAD && arts[i].killed) || (arts[i].thread == ART_EXPIRED))
 1030 /* only used for threading */
 1031 #define IGNORE_ART_THREAD(i)    (arts[i].thread != ART_UNTHREADED || (tinrc.kill_level == KILL_NOTHREAD && arts[i].killed))
 1032 
 1033 /*
 1034  * Is this part text/plain?
 1035  */
 1036 #define IS_PLAINTEXT(x) \
 1037             (x->type == TYPE_TEXT && strcasecmp("plain", x->subtype) == 0)
 1038 
 1039 /* TRUE if basenote has responses */
 1040 #define HAS_FOLLOWUPS(i)    (arts[base[i]].thread >= 0)
 1041 
 1042 /*
 1043  * Only close off our stream when reading on local spool
 1044  */
 1045 #ifdef NNTP_ABLE
 1046 #   define TIN_FCLOSE(x)    if (x != FAKE_NNTP_FP) fclose(x)
 1047 #else
 1048 #   define TIN_FCLOSE(x)    fclose(x)
 1049 #endif /* NNTP_ABLE */
 1050 
 1051 /*
 1052  * Often used macro to point to the group we are currently in
 1053  */
 1054 #define CURR_GROUP  (active[my_group[selmenu.curr]])
 1055 
 1056 /*
 1057  * Defines an unread group
 1058  */
 1059 #define UNREAD_GROUP(i)     (!active[my_group[i]].bogus && active[my_group[i]].newsrc.num_unread > 0)
 1060 
 1061 /*
 1062  * Expands to singular/plural version of string
 1063  */
 1064 #define PLURAL(x,y)         ((x == 1) ? _(y##_singular) : _(y##_plural))
 1065 
 1066 /*
 1067  * News/Mail group types
 1068  */
 1069 #define GROUP_TYPE_MAIL 0
 1070 #define GROUP_TYPE_NEWS 1
 1071 #define GROUP_TYPE_SAVE 2   /* saved news, read with tin -R */
 1072 
 1073 /*
 1074  * used by get_arrow_key()
 1075  */
 1076 #   define KEYMAP_UNKNOWN       0
 1077 #   define KEYMAP_UP        1
 1078 #   define KEYMAP_DOWN      2
 1079 #   define KEYMAP_LEFT      3
 1080 #   define KEYMAP_RIGHT     4
 1081 #   define KEYMAP_PAGE_UP       5
 1082 #   define KEYMAP_PAGE_DOWN 6
 1083 #   define KEYMAP_HOME      7
 1084 #   define KEYMAP_END       8
 1085 #   define KEYMAP_DEL       9
 1086 #   define KEYMAP_INS       10
 1087 #   define KEYMAP_MOUSE     11
 1088 
 1089 
 1090 /*
 1091  * used in main.c, curses.c and signal.c
 1092  * it's useless trying to run tin interactively below these sizes
 1093  * (values acquired by testing ;-) )
 1094  */
 1095 #define MIN_LINES_ON_TERMINAL        8
 1096 #define MIN_COLUMNS_ON_TERMINAL     40
 1097 
 1098 
 1099 /*
 1100  * indicate given cmd-line options
 1101  */
 1102 #define CMDLINE_GETART_LIMIT    1
 1103 #define CMDLINE_MAILDIR         2
 1104 #define CMDLINE_NNTPSERVER      4
 1105 #define CMDLINE_SAVEDIR         8
 1106 #define CMDLINE_USE_COLOR       16
 1107 
 1108 
 1109 /*
 1110  * used by feed_articles() & show_mini_help() & quick_filter & add_filter_rule
 1111  */
 1112 #define SELECT_LEVEL    1
 1113 #define GROUP_LEVEL 2
 1114 #define THREAD_LEVEL    3
 1115 #define PAGE_LEVEL  4
 1116 #define INFO_PAGER  5
 1117 #define SCOPE_LEVEL 6
 1118 #define CONFIG_LEVEL    7
 1119 #define ATTRIB_LEVEL    8
 1120 #define ATTACHMENT_LEVEL    9
 1121 #define URL_LEVEL   10
 1122 #define POSTED_LEVEL    11
 1123 
 1124 #define MINI_HELP_LINES     5
 1125 
 1126 #define FEED_MAIL       1
 1127 #define FEED_PIPE       2
 1128 #define FEED_PRINT      3
 1129 #define FEED_SAVE       4
 1130 #define FEED_AUTOSAVE   5
 1131 #define FEED_REPOST     6
 1132 #define FEED_MARK_READ      7
 1133 #define FEED_MARK_UNREAD    8
 1134 
 1135 
 1136 /*
 1137  * Threading strategies available
 1138  */
 1139 #define THREAD_NONE     0
 1140 #define THREAD_SUBJ     1
 1141 #define THREAD_REFS     2
 1142 #define THREAD_BOTH     3
 1143 #define THREAD_MULTI        4
 1144 #define THREAD_PERC     5
 1145 
 1146 #define THREAD_MAX      THREAD_PERC
 1147 
 1148 #define THREAD_PERC_DEFAULT 75
 1149 
 1150 /*
 1151  * Values for show_author
 1152  */
 1153 #define SHOW_FROM_NONE      0
 1154 #define SHOW_FROM_ADDR      1
 1155 #define SHOW_FROM_NAME      2
 1156 #define SHOW_FROM_BOTH      3
 1157 
 1158 /*
 1159  * Values for thread_score
 1160  */
 1161 #define THREAD_SCORE_MAX    0
 1162 #define THREAD_SCORE_SUM    1
 1163 #define THREAD_SCORE_WEIGHT 2
 1164 
 1165 /*
 1166  * Values for interactive_mailer
 1167  */
 1168 enum {
 1169     INTERACTIVE_NONE = 0,
 1170     INTERACTIVE_WITH_HEADERS,
 1171     INTERACTIVE_WITHOUT_HEADERS
 1172 };
 1173 
 1174 /*
 1175  * used in feed.c & save.c
 1176  */
 1177 #define POST_PROC_NO        0
 1178 #define POST_PROC_SHAR      1
 1179 #define POST_PROC_YES       2
 1180 
 1181 /*
 1182  * used in art.c
 1183  * sort types on arts[] array
 1184  */
 1185 #define SORT_ARTICLES_BY_NOTHING        0
 1186 #define SORT_ARTICLES_BY_SUBJ_DESCEND   1
 1187 #define SORT_ARTICLES_BY_SUBJ_ASCEND    2
 1188 #define SORT_ARTICLES_BY_FROM_DESCEND   3
 1189 #define SORT_ARTICLES_BY_FROM_ASCEND    4
 1190 #define SORT_ARTICLES_BY_DATE_DESCEND   5
 1191 #define SORT_ARTICLES_BY_DATE_ASCEND    6
 1192 #define SORT_ARTICLES_BY_SCORE_DESCEND  7
 1193 #define SORT_ARTICLES_BY_SCORE_ASCEND   8
 1194 #define SORT_ARTICLES_BY_LINES_DESCEND  9
 1195 #define SORT_ARTICLES_BY_LINES_ASCEND   10
 1196 
 1197 /*
 1198  * used in art.c
 1199  * sort types on base[] array
 1200  */
 1201 #define SORT_THREADS_BY_NOTHING         0
 1202 #define SORT_THREADS_BY_SCORE_DESCEND   1
 1203 #define SORT_THREADS_BY_SCORE_ASCEND    2
 1204 #define SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND   3
 1205 #define SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND    4
 1206 
 1207 /*
 1208  * Different values of strip_bogus - the ways to handle bogus groups
 1209  */
 1210 #define BOGUS_KEEP      0   /* not used */
 1211 #define BOGUS_REMOVE        1
 1212 #define BOGUS_SHOW      2
 1213 
 1214 /*
 1215  * Different extents to which we can hide killed articles
 1216  */
 1217 #define KILL_UNREAD     0       /* Kill only unread articles */
 1218 #define KILL_THREAD     1       /* Kill all articles and show as K */
 1219 #define KILL_NOTHREAD   2       /* Kill all articles, never show them */
 1220 
 1221 /*
 1222  * Various types of quoting behaviour
 1223  */
 1224 #define QUOTE_COMPRESS  1       /* Compress quotes */
 1225 #define QUOTE_SIGS      2       /* Quote signatures */
 1226 #define QUOTE_EMPTY     4       /* Quote empty lines */
 1227 
 1228 
 1229 /*
 1230  * used in save.c/main.c
 1231  */
 1232 #define CHECK_ANY_NEWS      0
 1233 #define START_ANY_NEWS      1
 1234 #define MAIL_ANY_NEWS       2
 1235 #define SAVE_ANY_NEWS       3
 1236 
 1237 
 1238 /*
 1239  * used in post.c
 1240  */
 1241 #define POSTED_NONE     0           /* Article wasn't posted */
 1242 #define POSTED_REDRAW       1           /* redraw needed in any case */
 1243 #define POSTED_OK       2           /* posted normally */
 1244 
 1245 
 1246 /*
 1247  * used in pager
 1248  */
 1249 #define UUE_NO          0       /* Don't hide uue data */
 1250 #define UUE_YES         1       /* Hide uue data */
 1251 #define UUE_ALL         2       /* Hide uue data harder */
 1252 
 1253 /*
 1254  * used in misc.c/rfc1524.c
 1255  */
 1256 enum quote_enum {
 1257     no_quote = 0,
 1258     dbl_quote,
 1259     sgl_quote
 1260 };
 1261 
 1262 
 1263 /*
 1264  * Values used in show_article_by_msid
 1265  */
 1266 enum {
 1267     LOOKUP_OK           = 0,
 1268     LOOKUP_FAILED       = -1,
 1269     LOOKUP_QUIT         = -2,
 1270     LOOKUP_UNAVAIL      = -3,
 1271     LOOKUP_REPLY        = -4,
 1272     LOOKUP_ART_UNAVAIL  = -5,
 1273     LOOKUP_NO_LAST      = -6
 1274 };
 1275 
 1276 /*
 1277  * index_point variable values used throughout tin
 1278  */
 1279 
 1280 /*
 1281  * -1 is kind of overloaded as an error from which_thread() and other functions
 1282  * where we wish to return to the next level up
 1283  */
 1284 enum {
 1285     GRP_RETSELECT   = -1,   /* Pager 'T' command only -> return to selection screen */
 1286     GRP_QUIT        = -2,   /* Set by 'Q' when coming all the way out */
 1287     GRP_NEXTUNREAD  = -3,   /* (After catchup) goto next unread item */
 1288     GRP_NEXT        = -4,   /* (After catchup) move to next item */
 1289     GRP_ARTUNAVAIL  = -5,   /* show_page() Article is unavailable */
 1290     GRP_ARTABORT    = -6,   /* show_page() User aborted article read */
 1291     GRP_KILLED      = -7,   /* ?? Thread was killed at pager level */
 1292     GRP_GOTOTHREAD  = -8,   /* show_page() only. Goto thread menu */
 1293     GRP_ENTER       = -9,   /* New group is set, spin in read_groups() */
 1294     GRP_EXIT        = -10   /* Normal return to higher level */
 1295 };
 1296 
 1297 #ifndef EXIT_SUCCESS
 1298 #   define EXIT_SUCCESS 0   /* Successful exit status */
 1299 #endif /* !EXIT_SUCCESS */
 1300 
 1301 #ifndef EXIT_FAILURE
 1302 #   define EXIT_FAILURE 1   /* Failing exit status */
 1303 #endif /* !EXIT_FAILURE */
 1304 
 1305 #define NEWS_AVAIL_EXIT 2
 1306 #define NNTP_ERROR_EXIT 3
 1307 
 1308 /*
 1309  * Assertion verifier
 1310  */
 1311 #ifdef assert
 1312 #   undef assert
 1313 #endif /* assert */
 1314 #ifdef NDEBUG
 1315 #   define assert(p)        ((void) 0)
 1316 #else
 1317 #   ifdef CPP_DOES_EXPAND
 1318 #       define assert(p)    if(!(p)) asfail(__FILE__, __LINE__, #p); else (void) 0;
 1319 #   else
 1320 #       define assert(p)    if(!(p)) asfail(__FILE__, __LINE__, "p"); else (void) 0;
 1321 #   endif /* CPP_DOES_EXPAND */
 1322 #endif /* NDEBUG */
 1323 
 1324 #define ESC 27
 1325 
 1326 /*
 1327  * filter entries expire after DEFAULT_FILTER_DAYS
 1328  */
 1329 #define DEFAULT_FILTER_DAYS     28
 1330 
 1331 /*
 1332  * art.thread
 1333  */
 1334 #define ART_UNTHREADED  -1
 1335 #define ART_EXPIRED     -2
 1336 
 1337 /*
 1338  * Where does this belong?? It is overloaded
 1339  */
 1340 #define ART_NORMAL      -1
 1341 
 1342 /*
 1343  * art.status
 1344  */
 1345 #define ART_READ        0
 1346 #define ART_UNREAD      1
 1347 #define ART_WILL_RETURN     2
 1348 #define ART_UNAVAILABLE     -1 /* Also used by msgid.article */
 1349 
 1350 /*
 1351  * art.killed
 1352  */
 1353 #define ART_NOTKILLED       0
 1354 #define ART_KILLED      1
 1355 #define ART_KILLED_UNREAD   2
 1356 
 1357 /*
 1358  * Additionally used for user aborts in art_open()
 1359  */
 1360 #define ART_ABORT       -2
 1361 
 1362 /*
 1363  * used by t_group & my_group[]
 1364  */
 1365 #define UNSUBSCRIBED    '!'
 1366 #define SUBSCRIBED  ':'
 1367 
 1368 /* Converts subscription status to char for .newsrc */
 1369 #define SUB_CHAR(x) (x ? SUBSCRIBED : UNSUBSCRIBED)
 1370 /* Converts .newsrc subscription char to boolean */
 1371 #define SUB_BOOL(x) (x == SUBSCRIBED)
 1372 
 1373 /*
 1374  * filter_type used in struct t_filter
 1375  */
 1376 #define SCORE_MAX       10000
 1377 
 1378 #define FILTER_SUBJ_CASE_SENSITIVE      0
 1379 #define FILTER_SUBJ_CASE_IGNORE     1
 1380 #define FILTER_FROM_CASE_SENSITIVE      2
 1381 #define FILTER_FROM_CASE_IGNORE     3
 1382 #define FILTER_MSGID        4
 1383 #define FILTER_MSGID_LAST   5
 1384 #define FILTER_MSGID_ONLY   6
 1385 #define FILTER_REFS_ONLY    7
 1386 #define FILTER_LINES        8
 1387 
 1388 #define FILTER_LINES_NO     0
 1389 #define FILTER_LINES_EQ     1
 1390 #define FILTER_LINES_LT     2
 1391 #define FILTER_LINES_GT     3
 1392 
 1393 /*
 1394  * default format strings for selection, group, thread level
 1395  * and the date display in the page header.
 1396  * Don't change without adjusting rc_update() and the like accordingly!
 1397  */
 1398 #define DEFAULT_SELECT_FORMAT   "%f %n %U  %G  %d"
 1399 #define DEFAULT_GROUP_FORMAT    "%n %m %R %L  %s  %F"
 1400 #define DEFAULT_THREAD_FORMAT   "%n %m  [%L]  %T  %F"
 1401 #define DEFAULT_DATE_FORMAT     "%a, %d %b %Y %H:%M:%S"
 1402 
 1403 /*
 1404  * unicode normalization
 1405  */
 1406 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1407 #   ifdef HAVE_LIBICUUC
 1408 #       define HAVE_UNICODE_NORMALIZATION 3
 1409 #   else
 1410 #       ifdef HAVE_LIBUNISTRING
 1411 #           define HAVE_UNICODE_NORMALIZATION 2
 1412 #       else
 1413 #           if defined(HAVE_LIBIDN) && defined(HAVE_STRINGPREP_H)
 1414 #               define HAVE_UNICODE_NORMALIZATION 1
 1415 #           endif /* HAVE_LIBIDN && HAVE_STRINGPREP_H */
 1416 #       endif /* HAVE_LIBUNISTRING */
 1417 #   endif /* HAVE_LIBICUUC */
 1418 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1419 
 1420 /*
 1421  * normalization forms, we prefer NFC (see RFC 6532) if possible
 1422  */
 1423 #ifdef HAVE_UNICODE_NORMALIZATION
 1424 enum {
 1425     NORMALIZE_NONE = 0,
 1426     NORMALIZE_NFKC = 1,
 1427 #   if (HAVE_UNICODE_NORMALIZATION >= 2)
 1428     NORMALIZE_NFKD = 2,
 1429     NORMALIZE_NFC = 3,
 1430     NORMALIZE_NFD = 4
 1431 #       ifdef HAVE_UNICODE_UNORM2_H
 1432     , NORMALIZE_NFKC_CF = 5
 1433 #       endif /* HAVE_UNICODE_UNORM2_H */
 1434 #   endif /* HAVE_UNICODE_NORMALIZATION >= 2 */
 1435 };
 1436 #   if (HAVE_UNICODE_NORMALIZATION >= 2)
 1437 #       ifdef HAVE_UNICODE_UNORM2_H
 1438 #           define NORMALIZE_MAX NORMALIZE_NFKC_CF
 1439 #       else
 1440 #           define NORMALIZE_MAX NORMALIZE_NFD
 1441 #       endif /* HAVE_UNICODE_UNORM2_H */
 1442 #       define DEFAULT_NORMALIZE NORMALIZE_NFC
 1443 #   else
 1444 #       define NORMALIZE_MAX NORMALIZE_NFKC
 1445 #       define DEFAULT_NORMALIZE NORMALIZE_NFKC
 1446 #   endif /* HAVE_UNICODE_NORMALIZATION >= 2 */
 1447 #endif /* HAVE_UNICODE_NORMALIZATION */
 1448 
 1449 #ifdef HAVE_LIBICUUC
 1450 #   ifdef HAVE_UNICODE_USTRING_H
 1451 #       include <unicode/ustring.h>
 1452 #   endif /* HAVE_UNICODE_USTRING_H */
 1453 #   ifdef HAVE_UNICODE_UNORM2_H
 1454 #       include <unicode/unorm2.h>
 1455 #   else
 1456 #       ifdef HAVE_UNICODE_UNORM_H
 1457 #           include <unicode/unorm.h>
 1458 #       endif /* HAVE_UNICODE_UNORM_H */
 1459 #   endif /* HAVE_UNICODE_UNORM2_H */
 1460 #   ifdef HAVE_UNICODE_UIDNA_H
 1461 #       include <unicode/uidna.h>
 1462 #   endif /* HAVE_UNICODE_UIDNA_H */
 1463 #   ifdef HAVE_UNICODE_UBIDI_H
 1464 #       include <unicode/ubidi.h>
 1465 #   endif /* HAVE_UNICODE_UBIDI_H */
 1466 #endif /* HAVE_LIBICUUC */
 1467 
 1468 
 1469 /*
 1470  * used in checking article header before posting
 1471  */
 1472 #define MAX_COL     78  /* Max. line length before issuing a warning */
 1473 #define MAX_SIG_LINES   4   /* Max. num. of signature lines before warning */
 1474 
 1475 typedef unsigned char   t_bitmap;
 1476 
 1477 /*
 1478  * Keys for add_msgid()
 1479  */
 1480 #define REF_REF             1       /* Add a ref->ref entry */
 1481 #define MSGID_REF           2       /* Add a msgid->ref entry */
 1482 
 1483 /*
 1484  * Size of hash tables for hash_str() and hash_msgid()
 1485  * Make sure it's prime!
 1486  */
 1487 #ifdef SMALL_MEMORY_MACHINE
 1488 #   define HASHNODE_TABLE_SIZE 2411
 1489 #   define MSGID_HASH_SIZE  2609
 1490 #else
 1491 #   define HASHNODE_TABLE_SIZE 222199
 1492 #   define MSGID_HASH_SIZE  222199
 1493 #endif /* MSGID_HASH_SIZE */
 1494 
 1495 /*
 1496  * cmd-line options
 1497  */
 1498 struct t_cmdlineopts {
 1499     int getart_limit;           /* getart_limit */
 1500     char maildir[PATH_LEN];     /* maildir */
 1501     char nntpserver[PATH_LEN];  /* nntpserver */
 1502     char savedir[PATH_LEN];     /* savedir */
 1503     unsigned int args:5;        /* given options */
 1504 };
 1505 
 1506 /*
 1507  * struct t_msgid - message id
 1508  */
 1509 struct t_msgid {
 1510     struct t_msgid *next;       /* Next in hash chain */
 1511     struct t_msgid *parent;     /* Message-id followed up to */
 1512     struct t_msgid *sibling;    /* Next followup to parent */
 1513     struct t_msgid *child;      /* First followup to this article */
 1514     int article;            /* index in arts[] or ART_NORMAL */
 1515     char txt[1];            /* The actual msgid */
 1516 };
 1517 
 1518 /*
 1519  * struct t_article - article header
 1520  *
 1521  * article.thread:
 1522  * the next article in thread
 1523  *  -1  (ART_UNTHREADED) article exists but is not (yet) threaded
 1524  *  -2  (ART_EXPIRED) article has expired (wasn't found in search of spool
 1525  *      directory for the group)
 1526  *  >=0 points to another arts[] (struct t_article)
 1527  *
 1528  * article.prev:
 1529  *  the previous article in thread
 1530  *  -1  (ART_NORMAL) initial default, first (no previous) article in thread
 1531  *  >=0 points to the previous arts[] (struct t_article)
 1532  */
 1533 struct t_article {
 1534     t_artnum artnum;        /* Article number in spool directory for group */
 1535     char *subject;          /* Subject: line from mail header */
 1536     char *from;         /* From: line from mail header (address) */
 1537     char *name;         /* From: line from mail header (full name) */
 1538     char *xref;         /* Xref: cross posted article reference line */
 1539     char *path;         /* Path: line */
 1540     /* NB: The msgid and refs are only retained until the reference tree is built */
 1541     char *msgid;            /* Message-ID: unique message identifier */
 1542     char *refs;         /* References: article reference id's */
 1543     struct t_msgid *refptr;     /* Pointer to us in the reference tree */
 1544     time_t date;            /* Date: line from header in seconds */
 1545     int line_count;         /* Lines: number of lines in article */
 1546     int gnksa_code;         /* From: line from mail header (GNKSA error code) */
 1547     int tagged;         /* 0 = not tagged, >0 = tagged */
 1548     int thread;
 1549     int prev;
 1550     int score;          /* score article has reached after filtering */
 1551     unsigned int status:2;  /* 0 = read, 1 = unread, 2 = will return */
 1552     unsigned int killed:2;  /* 0 = not killed, 1 = killed, 2 = killed unread */
 1553     t_bool zombie:1;    /* 1 = was alive (unread) before 'X' command */
 1554     t_bool delete_it:1; /* 1 = delete art when leaving group [mail group] */
 1555     t_bool selected:1;  /* FALSE = not selected, TRUE = selected */
 1556     t_bool inrange:1;   /* TRUE = article selected via # range command */
 1557     t_bool matched:1;   /* TRUE = article matched regex in feed.c */
 1558     t_bool keep_in_base:1;  /* TRUE = keep (read) article in base[] (show_only_unread_arts) */
 1559     t_bool multipart_subj:1;    /* TRUE = subject looks like multipart subject */
 1560 };
 1561 
 1562 
 1563 #ifdef NNTP_ABLE
 1564 /*
 1565  * struct t_article_range - holds ranges of article numbers to perform actions on parts of arts[]
 1566  */
 1567 struct t_article_range {
 1568     t_artnum start;
 1569     t_artnum end;
 1570     t_artnum cnt;
 1571     struct t_article_range *next;
 1572 };
 1573 #endif /* NNTP_ABLE */
 1574 
 1575 
 1576 /*
 1577  * struct t_newsheader - holds an array of which news headers to [not] display
 1578  */
 1579 struct t_newsheader {
 1580     char **header;  /* array of which headers to [not] display */
 1581     int num;        /* number of headers in array header */
 1582 };
 1583 
 1584 /*
 1585  * Use these macros to quiet gcc warnings when assigning into a bitfield.
 1586  */
 1587 #define CAST_MASK(value,bits)   (((1U << (bits)) - 1) & (unsigned) (value))
 1588 #define CAST_BOOL(value)    CAST_MASK(value, 1)
 1589 #define CAST_BITS(value,bits)   CAST_MASK(value, BITS_OF(bits))
 1590 #define BITS_OF(bits)       BITS_OF_ ## bits
 1591 
 1592 #define BoolField(value)    unsigned value:1
 1593 #define IntField(value) unsigned value:BITS_OF(value)
 1594 
 1595 #define BITS_OF_auto_cc_bcc     2
 1596 #define BITS_OF_mail_mime_encoding  2
 1597 #define BITS_OF_mm_network_charset  6
 1598 #define BITS_OF_post_mime_encoding  2
 1599 #define BITS_OF_post_process_type   2
 1600 #define BITS_OF_quick_kill_header   3
 1601 #define BITS_OF_quick_select_header 3
 1602 #define BITS_OF_show_author     2
 1603 #define BITS_OF_sort_article_type   4
 1604 #define BITS_OF_sort_threads_type   3
 1605 #define BITS_OF_thread_articles 3
 1606 #define BITS_OF_thread_perc     7
 1607 #define BITS_OF_trim_article_body   3
 1608 
 1609 /*
 1610  * struct t_attribute - configurable attributes on a per group basis
 1611  */
 1612 struct t_attribute {
 1613     char *maildir;              /* mail dir if other than ~/Mail */
 1614     char *savedir;              /* save dir if other than ~/News */
 1615     char *savefile;             /* save articles to specified file */
 1616     char *sigfile;              /* sig file if other than ~/.Sig */
 1617     char *group_format;         /* format string for group level */
 1618     char *thread_format;        /* format string for thread level */
 1619     char *date_format;          /* format string for the date display */
 1620     char *editor_format;        /* editor + parameters  %E +%N %F */
 1621     char *organization;         /* organization name */
 1622     char *fcc;                  /* Fcc folder for mail */
 1623     char *followup_to;          /* where posts should be redirected */
 1624     char *quick_kill_scope;     /* quick filter kill scope */
 1625     char *quick_select_scope;   /* quick filter select scope */
 1626     char *mailing_list;         /* mail list email address */
 1627     char *news_headers_to_display;  /* which headers to display */
 1628     char *news_headers_to_not_display;  /* which headers to not display */
 1629     char *x_headers;            /* extra headers for message header */
 1630     char *x_body;               /* boilerplate text for message body */
 1631     char *from;                 /* from line */
 1632     char *news_quote_format;    /* another way to begin a posting format */
 1633     char *quote_chars;          /* string to precede quoted text on each line */
 1634     char *mime_types_to_save;   /* MIME content major/minors we want to save */
 1635 #ifdef HAVE_ISPELL
 1636     char *ispell;               /* path to ispell and options */
 1637 #endif /* HAVE_ISPELL */
 1638 #ifdef CHARSET_CONVERSION
 1639     char *undeclared_charset;       /* charset of articles without MIME charset declaration */
 1640     IntField(mm_network_charset);       /* network charset */
 1641 #endif /* CHARSET_CONVERSION */
 1642     struct t_newsheader *headers_to_display;    /* array of which headers to display */
 1643     struct t_newsheader *headers_to_not_display;    /* array of which headers to not display */
 1644     BoolField(global);          /* global/group specific */
 1645     IntField(quick_kill_header);    /* quick filter kill header */
 1646     BoolField(quick_kill_expire);   /* quick filter kill limited/unlimited time */
 1647     BoolField(quick_kill_case);     /* quick filter kill case sensitive? */
 1648     IntField(quick_select_header);  /* quick filter select header */
 1649     BoolField(quick_select_expire); /* quick filter select limited/unlimited time */
 1650     BoolField(quick_select_case);   /* quick filter select case sensitive? */
 1651     BoolField(add_posted_to_filter);    /* add posted articles to filter */
 1652     BoolField(advertising);         /* add User-Agent: -header */
 1653     BoolField(alternative_handling);    /* skip multipart/alternative parts */
 1654     BoolField(ask_for_metamail);    /* ask before using MIME viewer */
 1655     IntField(auto_cc_bcc);          /* add your name to cc/bcc automatically */
 1656     BoolField(auto_list_thread);    /* list thread when entering it using right arrow */
 1657     BoolField(auto_select);         /* 0=show all unread, 1='X' just hot arts */
 1658     BoolField(batch_save);          /* 0=none, 1=save -S/mail -M */
 1659     BoolField(delete_tmp_files);    /* 0=leave, 1=delete */
 1660     BoolField(group_catchup_on_exit);   /* ask if read groups are to be marked read */
 1661     BoolField(mail_8bit_header);    /* allow 8bit chars. in header of mail message */
 1662     IntField(mail_mime_encoding);
 1663     BoolField(mark_ignore_tags);    /* Ignore tags for GROUP_MARK_THREAD_READ/THREAD_MARK_ARTICLE_READ */
 1664     BoolField(mark_saved_read);     /* mark saved article/thread as read */
 1665     BoolField(pos_first_unread);    /* position cursor at first/last unread article */
 1666     BoolField(post_8bit_header);    /* allow 8bit chars. in header when posting to newsgroup */
 1667     IntField(post_mime_encoding);
 1668     BoolField(post_process_view);   /* set TRUE to invoke mailcap viewer app */
 1669 #ifndef DISABLE_PRINTING
 1670     BoolField(print_header);        /* print all of mail header or just Subject: & From lines */
 1671 #endif /* !DISABLE_PRINTING */
 1672     BoolField(process_only_unread); /* save/print//mail/pipe unread/all articles */
 1673     BoolField(prompt_followupto);   /* display empty Followup-To header in editor */
 1674     BoolField(show_only_unread_arts);   /* 0=all, 1=only unread */
 1675     BoolField(sigdashes);           /* set TRUE to prepend every signature with dashes */
 1676     BoolField(signature_repost);    /* set TRUE to add signature when reposting articles */
 1677     IntField(thread_articles);          /* 0=unthread, 1=subject, 2=refs, 3=both, 4=multipart, 5=percentage */
 1678     BoolField(thread_catchup_on_exit);  /* catchup thread with left arrow key or not */
 1679     IntField(thread_perc);          /* percentage threading threshold */
 1680     IntField(show_author);          /* 0=none, 1=name, 2=addr, 3=both */
 1681     BoolField(show_signatures);     /* 0=none, 1=show signatures */
 1682     IntField(trim_article_body);    /* 0=Don't trim article body, 1=Skip leading blank lines,
 1683                         2=Skip trailing blank lines, 3=Skip leading and trailing blank lines,
 1684                         4=Compact multiple blank lines between textblocks,
 1685                         5=Compact multiple blank lines between textblocks and skip leading blank lines,
 1686                         6=Compact multiple blank lines between textblocks and skip trailing blank lines,
 1687                         7=Compact multiple blank lines between textblocks and skip leading and trailing
 1688                           blank lines */
 1689     BoolField(verbatim_handling);   /* 0=none, 1=detect verbatim blocks */
 1690 #ifdef HAVE_COLOR
 1691     BoolField(extquote_handling);       /* 0=none, 1=detect quoted text from external sources */
 1692 #endif /* HAVE_COLOR */
 1693     BoolField(wrap_on_next_unread); /* Wrap around threads when searching next unread article */
 1694     IntField(sort_article_type);        /* 0=none, 1=subj descend, 2=subj ascend,
 1695                            3=from descend, 4=from ascend,
 1696                            5=date descend, 6=date ascend,
 1697                            7=score descend, 8=score ascend */
 1698     IntField(sort_threads_type);    /* 0=none, 1=score descend, 2=score ascend,
 1699                            3=last posting date descend, 4=last posting date ascend */
 1700     IntField(post_process_type);    /* 0=none, 1=shar, 2=uudecode */
 1701     BoolField(x_comment_to);    /* insert X-Comment-To: in Followup */
 1702     BoolField(tex2iso_conv);    /* Convert TeX2ISO */
 1703     BoolField(mime_forward);    /* forward articles as attachment or inline */
 1704 };
 1705 
 1706 /*
 1707  * struct t_attribute_state - holds additional information
 1708  * about numeric attributes within a scope
 1709  */
 1710 struct t_attribute_state {
 1711     BoolField(add_posted_to_filter);
 1712     BoolField(advertising);
 1713     BoolField(alternative_handling);
 1714     BoolField(ask_for_metamail);
 1715     BoolField(auto_cc_bcc);
 1716     BoolField(auto_list_thread);
 1717     BoolField(auto_select);
 1718     BoolField(batch_save);
 1719     BoolField(date_format);
 1720     BoolField(delete_tmp_files);
 1721     BoolField(editor_format);
 1722     BoolField(fcc);
 1723     BoolField(followup_to);
 1724     BoolField(from);
 1725     BoolField(group_catchup_on_exit);
 1726     BoolField(group_format);
 1727 #ifdef HAVE_ISPELL
 1728     BoolField(ispell);
 1729 #endif /* HAVE_ISPELL */
 1730     BoolField(mail_8bit_header);
 1731     BoolField(mail_mime_encoding);
 1732     BoolField(maildir);
 1733     BoolField(mailing_list);
 1734     BoolField(mark_ignore_tags);
 1735     BoolField(mark_saved_read);
 1736     BoolField(mime_forward);
 1737     BoolField(mime_types_to_save);
 1738     BoolField(news_headers_to_display);
 1739     BoolField(news_headers_to_not_display);
 1740     BoolField(news_quote_format);
 1741     BoolField(organization);
 1742     BoolField(pos_first_unread);
 1743     BoolField(post_8bit_header);
 1744     BoolField(post_mime_encoding);
 1745     BoolField(post_process_view);
 1746     BoolField(post_process_type);
 1747 #ifndef DISABLE_PRINTING
 1748     BoolField(print_header);
 1749 #endif /* !DISABLE_PRINTING */
 1750     BoolField(process_only_unread);
 1751     BoolField(prompt_followupto);
 1752     BoolField(quick_kill_case);
 1753     BoolField(quick_kill_expire);
 1754     BoolField(quick_kill_header);
 1755     BoolField(quick_kill_scope);
 1756     BoolField(quick_select_case);
 1757     BoolField(quick_select_expire);
 1758     BoolField(quick_select_header);
 1759     BoolField(quick_select_scope);
 1760     BoolField(quote_chars);
 1761     BoolField(savedir);
 1762     BoolField(savefile);
 1763     BoolField(show_author);
 1764     BoolField(show_only_unread_arts);
 1765     BoolField(show_signatures);
 1766     BoolField(sigdashes);
 1767     BoolField(sigfile);
 1768     BoolField(signature_repost);
 1769     BoolField(sort_article_type);
 1770     BoolField(sort_threads_type);
 1771     BoolField(tex2iso_conv);
 1772     BoolField(thread_articles);
 1773     BoolField(thread_catchup_on_exit);
 1774     BoolField(thread_format);
 1775     BoolField(thread_perc);
 1776     BoolField(trim_article_body);
 1777 #ifdef CHARSET_CONVERSION
 1778     BoolField(undeclared_charset);
 1779     BoolField(mm_network_charset);
 1780 #endif /* CHARSET_CONVERSION */
 1781     BoolField(verbatim_handling);
 1782 #ifdef HAVE_COLOR
 1783     BoolField(extquote_handling);
 1784 #endif /* HAVE_COLOR */
 1785     BoolField(wrap_on_next_unread);
 1786     BoolField(x_body);
 1787     BoolField(x_comment_to);
 1788     BoolField(x_headers);
 1789 };
 1790 
 1791 /*
 1792  * struct t_scope
 1793  */
 1794 struct t_scope {
 1795     char *scope;                /* scope for these group attributes */
 1796     struct t_attribute *attribute;  /* the attributes itself */
 1797     struct t_attribute_state *state;    /* additional information about numeric attributes */
 1798     BoolField(global);          /* TRUE for scopes from global_attributes_file */
 1799 };
 1800 
 1801 /*
 1802  * struct t_newsrc - newsrc related info.
 1803  */
 1804 struct t_newsrc {
 1805     t_bool present:1;       /* update newsrc? */
 1806     t_artnum num_unread;        /* unread articles in group */
 1807     t_artnum xmax;          /* newsrc max */
 1808     t_artnum xmin;          /* newsrc min */
 1809     t_artnum xbitlen;           /* bitmap length (max-min+1) */
 1810     t_bitmap *xbitmap;  /* bitmap read/unread (max-min+1+7)/8 */
 1811 };
 1812 
 1813 /*
 1814  * struct t_group - newsgroup info from active file
 1815  */
 1816 struct t_group {
 1817     char *name;         /* newsgroup/mailbox name */
 1818     char *aliasedto;        /* =new.group in active file, NULL if not */
 1819     char *description;  /* text from NEWSLIBDIR/newsgroups file */
 1820     char *spooldir;     /* groups spool directory */
 1821     char moderated;     /* state of group moderation */
 1822     t_artnum count;     /* article number count */
 1823     t_artnum xmax;      /* max. article number */
 1824     t_artnum xmin;      /* min. article number */
 1825     unsigned int type:4;        /* grouptype - newsgroup/mailbox/savebox */
 1826     t_bool inrange:1;       /* TRUE if group selected via # range command */
 1827     t_bool read_during_session:1;   /* TRUE if group entered during session */
 1828     t_bool art_was_posted:1;    /* TRUE if art was posted to group */
 1829     t_bool subscribed:1;        /* TRUE if subscribed to group */
 1830     t_bool newgroup:1;      /* TRUE if group was new this session */
 1831     t_bool bogus:1;         /* TRUE if group is not in active list */
 1832     int next;           /* next active entry in hash chain */
 1833     struct t_newsrc newsrc;     /* newsrc bitmap specific info. */
 1834     struct t_attribute *attribute;  /* group specific attributes */
 1835     struct t_filters *glob_filter;  /* points to filter array */
 1836 };
 1837 
 1838 /*
 1839  * used in hashstr.c
 1840  */
 1841 struct t_hashnode {
 1842     struct t_hashnode *next;    /* chain for spillover */
 1843     int aptr;           /* used in subject threading */
 1844     char txt[1];            /* stub for the string data, \0 terminated */
 1845 };
 1846 
 1847 /*
 1848  * used for variable screen layout
 1849  *
 1850  * holds a preparsed format string, a date format string and some
 1851  * precalculated length
 1852  */
 1853 struct t_fmt {
 1854     char str[LEN];
 1855     char date_str[LEN];
 1856     size_t len_date;        /* %D Date */
 1857     size_t len_date_max;
 1858     size_t len_grpdesc;     /* %d newsgroup description */
 1859     size_t len_from;        /* %F From */
 1860     size_t len_grpname;     /* %G groupname */
 1861     size_t len_grpname_dsc;
 1862     size_t len_grpname_max;
 1863     size_t len_initials;    /* %I initials */
 1864     size_t len_linenumber;  /* %n linenumber on screen */
 1865     size_t len_linecnt;     /* %L line count (article) */
 1866     size_t len_msgid;       /* %M message-id */
 1867     size_t len_respcnt;     /* %R count, number of responses */
 1868     size_t len_score;       /* %S score */
 1869     size_t len_subj;        /* %s subject */
 1870     size_t len_ucnt;        /* %U unread count */
 1871     size_t flags_offset;
 1872     size_t mark_offset;
 1873     size_t ucnt_offset;
 1874     t_bool show_grpdesc;
 1875     t_bool d_before_f;
 1876     t_bool g_before_f;
 1877     t_bool d_before_u;
 1878     t_bool g_before_u;
 1879 };
 1880 
 1881 /*
 1882  * used in filter.c
 1883  *
 1884  * Create 2 filter arrays - global & local. Local will be part of group_t
 1885  * structure and will have priority over global filter. Should help to
 1886  * speed kill/selecting within a group. The long value number that is in
 1887  * ~/.tin/kill will be replaced by group name so that it is more human
 1888  * readable and that if hash routine is changed it will still work.
 1889  *
 1890  * Add time period to filter_t struct to allow timed kills & auto-selection
 1891  * Default kill & select time 28 days. Store as a long and compare when
 1892  * loading against present time. If time secs is passed set flag to save
 1893  * filter file and don't load expired entry. Renamed to filter because of
 1894  * future directions in adding other retrieval methods to present kill &
 1895  * auto selection.
 1896  *
 1897  * Also separate kill/select screen to allow ^K=kill ^A=auto-select
 1898  */
 1899 struct t_filters {
 1900     int max;
 1901     int num;
 1902     struct t_filter *filter;
 1903 };
 1904 
 1905 /*
 1906  * struct t_filter_comment: allow multiple comment-lines in filter-file.
 1907  */
 1908 struct t_filter_comment {
 1909     char *text;         /* One line of comment. */
 1910     struct t_filter_comment *next;  /* points to next comment-entry */
 1911 };
 1912 
 1913 /*
 1914  * struct t_filter - local & global filtering (ie. kill & auto-selection)
 1915  */
 1916 struct t_filter {
 1917     struct t_filter_comment *comment;
 1918     char *scope;            /* NULL='*' (all groups) or 'comp.os.*' */
 1919     char *subj;         /* Subject: line */
 1920     char *from;         /* From: line */
 1921     char *msgid;            /* Message-ID: line */
 1922     char *xref;         /* groups in xref line */
 1923     char *path;         /* server in path line */
 1924     struct t_filter *next;      /* next rule valid in group */
 1925     time_t time;            /* expire time in seconds */
 1926     int lines_num;          /* Lines: line */
 1927     int gnksa_num;          /* GNKSA code */
 1928     int score;          /* score to give if rule matches */
 1929     char lines_cmp;         /* Lines compare <> */
 1930     char gnksa_cmp;         /* GNKSA compare <> */
 1931     unsigned int inscope:4;     /* if group matches scope e.g. 'comp.os.*' */
 1932     unsigned int icase:2;       /* Case sensitive filtering */
 1933     unsigned int fullref:4;     /* use full references or last entry only */
 1934 };
 1935 
 1936 /*
 1937  * struct t_filter_rule - provides parameters to build filter rule from
 1938  */
 1939 struct t_filter_rule {
 1940     struct t_filter_comment *comment;
 1941     char text[PATH_LEN];
 1942     char scope[PATH_LEN];
 1943     int counter;
 1944     int icase;
 1945     int fullref;
 1946     int lines_cmp;
 1947     int lines_num;
 1948     int score;
 1949     int expire_time;
 1950     t_bool from_ok:1;
 1951     t_bool lines_ok:1;
 1952     t_bool msgid_ok:1;
 1953     t_bool subj_ok:1;
 1954     t_bool check_string:1;
 1955 };
 1956 
 1957 /*
 1958  * Filter cache structure using Philip Hazel's Perl regular expression
 1959  * library (see pcre/pcre.[ch] for details)
 1960  */
 1961 struct regex_cache {
 1962     pcre *re;
 1963     pcre_extra *extra;
 1964 };
 1965 
 1966 struct t_save {
 1967     char *path;
 1968     char *file;                 /* ptr to file part of *path */
 1969     t_bool mailbox:1;           /* Set if path is a mailbox */
 1970 };
 1971 
 1972 #ifndef USE_CURSES
 1973 struct t_screen {
 1974     char *col;
 1975 };
 1976 #endif /* !USE_CURSES */
 1977 
 1978 typedef struct posted {
 1979     char date[10];
 1980     char group[80];
 1981     char action;
 1982     char subj[120];
 1983     char mid[256];
 1984     struct posted *next;
 1985 } t_posted;
 1986 
 1987 struct t_art_stat {
 1988 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1989     wchar_t art_mark;       /* mark to use for this thread - not used for groups */
 1990 #else
 1991     char art_mark;      /* mark to use for this thread - not used for groups */
 1992 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1993     int total;      /* total article count */
 1994     int unread;     /* number of unread articles (does not include seen) arts */
 1995     int seen;       /* number of seen articles (ART_WILL_RETURN) */
 1996     int deleted;        /* number of articles marked for deletion (mailgroups) */
 1997     int inrange;        /* number of articles marked in a range */
 1998     int selected_total; /* total selected count */
 1999     int selected_unread;    /* selected and unread */
 2000     int selected_seen;  /* selected and seen */
 2001     int killed;     /* killed */
 2002     int score;      /* maximum score */
 2003     int multipart_total; /* 0=not multipart, >0 = number of articles in the multipart */
 2004     int multipart_have; /* number of articles we actually have found */
 2005     int multipart_compare_len; /* length of subject which contains non-specific multipart info */
 2006     time_t time;        /* latest time */
 2007 };
 2008 
 2009 
 2010 /*
 2011  * Used for detecting changes in active file size on different news servers
 2012  */
 2013 struct t_newnews {
 2014     char *host;
 2015     time_t time;
 2016 };
 2017 
 2018 typedef const char constext;
 2019 
 2020 /*
 2021  * Defines text strings used by a tinrc variable
 2022  */
 2023 struct opttxt {
 2024     constext *help;                 /* Helptext on Option Menu */
 2025     constext *opt;                  /* Text on body of Option Menu screen */
 2026     constext *tinrc;                /* (optional) Text written with variable to tinrc file */
 2027 };
 2028 
 2029 /*
 2030  * Used for building option menu
 2031  */
 2032 struct t_option {
 2033     int var_type;       /* type of variable (see tincfg.h) */
 2034     int var_index;      /* index in corresponding table */
 2035     int *variable;      /* ptr to variable to change */
 2036     constext **opt_list;    /* ptr to list entries if OPT_LIST */
 2037     struct opttxt *txt; /* ptr to information/help on option */
 2038 };
 2039 
 2040 /*
 2041  * Multipart article detection
 2042  */
 2043 typedef struct {
 2044     char *subject;
 2045     int subject_compare_len;
 2046     int part_number;
 2047     int total;
 2048     int arts_index;
 2049 } MultiPartInfo;
 2050 
 2051 
 2052 /*
 2053  * Key information about current menu screen
 2054  */
 2055 typedef struct {
 2056     int curr;                   /* Current cursor pos (cur_groupnum, index_point, thread_index_point) */
 2057     int max;                    /* Max # on current menu (group_top, top_base, top_thread) */
 2058     int first;                  /* First # on current menu */
 2059     void (*redraw) (void);      /* Redraw function */
 2060     void (*draw_arrow) (void);  /* Arrow draw */
 2061     void (*draw_item) (int item);   /* draw the specified item */
 2062 } t_menu;
 2063 
 2064 
 2065 /*
 2066  * Packet of data needed to enter pager
 2067  */
 2068 typedef struct {
 2069     int art;
 2070     t_bool ignore_unavail:1;
 2071 } t_pagerinfo;
 2072 
 2073 
 2074 /*
 2075  * Time functions.
 2076  */
 2077 typedef struct _TIMEINFO {
 2078     time_t time;
 2079     long usec;
 2080     long tzone;
 2081 } TIMEINFO;
 2082 
 2083 
 2084 struct t_tintime {
 2085     time_t tv_sec; /* seconds */
 2086     long tv_nsec; /* nanoseconds */
 2087 };
 2088 
 2089 
 2090 /*
 2091  * mailcap fields
 2092  * the x-token field is missing, we would need something like
 2093  * struct t_xtoken { char *xtoken; t_xtoken *next; } for that ...
 2094  */
 2095 typedef struct {
 2096     char *type;     /* content-type, mandatory */
 2097     char *command;  /* view-command, mandatory */
 2098     char *compose;
 2099     char *composetyped;
 2100     char *description;
 2101     char *edit;
 2102     char *nametemplate;
 2103     char *print;
 2104     char *test;
 2105     char *x11bitmap;
 2106     int textualnewlines;
 2107     t_bool needsterminal:1;
 2108     t_bool copiousoutput:1;
 2109 } t_mailcap;
 2110 
 2111 
 2112 typedef struct urllist {
 2113     char *url;
 2114     struct urllist *next;
 2115 } t_url;
 2116 
 2117 
 2118 /*
 2119  * Determine signal return type
 2120  */
 2121 #ifndef RETSIGTYPE
 2122 #   define RETSIGTYPE void
 2123 #endif /* !RETSIGTYPE */
 2124 
 2125 /*
 2126  * Determine qsort compare type
 2127  */
 2128 #ifdef HAVE_COMPTYPE_VOID
 2129 #   ifdef __STDC__
 2130         typedef const void *t_comptype;
 2131 #   else
 2132         typedef void *t_comptype;
 2133 #   endif /* __STDC__ */
 2134 #else
 2135 #   ifdef HAVE_COMPTYPE_CHAR
 2136         typedef char *t_comptype;
 2137 #   endif /* HAVE_COMPTYPE_CHAR */
 2138 #endif /* HAVE_COMPTYPE_VOID */
 2139 
 2140 /* Define a matching function pointer type */
 2141 typedef int (*t_compfunc)(t_comptype, t_comptype);
 2142 typedef void (*t_sortfunc)(void *, size_t, size_t, t_compfunc);
 2143 
 2144 #define _CDECL
 2145 
 2146 /* set to (void)heapsort or qsort */
 2147 #ifndef USE_HEAPSORT
 2148 #   define tin_sort qsort
 2149 #else
 2150 #   define MAX_SORT_FUNCS 1
 2151 #endif /* !USE_HEAPSORT */
 2152 
 2153 /* Separator between dir part of path & the filename */
 2154 #define DIRSEP  '/'
 2155 
 2156 /*
 2157  * mouse buttons for use in xterm
 2158  */
 2159 #define MOUSE_BUTTON_1      0
 2160 #define MOUSE_BUTTON_2      1
 2161 #define MOUSE_BUTTON_3      2
 2162 
 2163 
 2164 #define REDIRECT_OUTPUT     "> /dev/null 2>&1"
 2165 #define REDIRECT_PGP_OUTPUT     "> /dev/null"
 2166 #define ENV_VAR_MAILER      "MAILER"
 2167 #define ENV_VAR_SHELL       "SHELL"
 2168 #define TIN_EDITOR_FMT      "%E +%N %F"
 2169 #define MAILER_FORMAT       "%M -oi -t < %F"
 2170 #define TMPDIR  get_val("TMPDIR", _PATH_TMP)
 2171 #ifdef HAVE_KEY_PREFIX
 2172 #   define KEY_PREFIX       0x8f: case 0x9b
 2173 #endif /* HAVE_KEY_PREFIX */
 2174 
 2175 #if !defined(S_ISDIR)
 2176 #   define S_ISDIR(m)   (((m) & S_IFMT) == S_IFDIR)
 2177 #endif /* !S_ISDIR */
 2178 
 2179 #if !defined(S_ISREG)
 2180 #   define S_ISREG(m)   (((m) & S_IFMT) == S_IFREG)
 2181 #endif /* !S_ISREG */
 2182 
 2183 #ifndef S_IRWXU /* should be defined in <sys/stat.h> */
 2184 #   define S_IRWXU  0000700 /* read, write, execute permission (owner) */
 2185 #   define S_IRUSR  0000400 /* read permission (owner) */
 2186 #   define S_IWUSR  0000200 /* write permission (owner) */
 2187 #   define S_IXUSR  0000100 /* execute permission (owner) */
 2188 
 2189 #   define S_IRWXG  0000070 /* read, write, execute permission (group) */
 2190 #   define S_IRGRP  0000040 /* read permission (group) */
 2191 #   define S_IWGRP  0000020 /* write permission (group) */
 2192 #   define S_IXGRP  0000010 /* execute permission (group) */
 2193 
 2194 #   define S_IRWXO  0000007 /* read, write, execute permission (other) */
 2195 #   define S_IROTH  0000004 /* read permission (other) */
 2196 #   define S_IWOTH  0000002 /* write permission (other) */
 2197 #   define S_IXOTH  0000001 /* execute permission (other) */
 2198 #endif /* !S_IRWXU */
 2199 
 2200 /* the next two are needed for fcc 1.0 on linux */
 2201 #ifndef S_IFMT
 2202 #   define S_IFMT   0xF000  /* type of file */
 2203 #endif /* S_IFMT */
 2204 #ifndef S_IFREG
 2205 #   define S_IFREG  0x8000  /* regular */
 2206 #endif /* S_IFREG */
 2207 
 2208 #ifndef S_IRWXUGO
 2209 #   define S_IRWXUGO    (S_IRWXU|S_IRWXG|S_IRWXO)   /* read, write, execute permission (all) */
 2210 #   define S_IRUGO  (S_IRUSR|S_IRGRP|S_IROTH)   /* read permission (all) */
 2211 #   define S_IWUGO  (S_IWUSR|S_IWGRP|S_IWOTH)   /* write permission (all) */
 2212 #   define S_IXUGO  (S_IXUSR|S_IXGRP|S_IXOTH)   /* execute permission (all) */
 2213 #endif /* !S_IRWXUGO */
 2214 
 2215 #ifndef S_ISVTX
 2216 #   define S_ISVTX 0
 2217 #endif /* !S_ISVTX */
 2218 
 2219 #ifdef DONT_HAVE_PIPING
 2220 #   define TIN_PRINTFILE "tinprint%d.tmp"
 2221 #endif /* DONT_HAVE_PIPING */
 2222 
 2223 /*
 2224  * Defines for access()
 2225  */
 2226 #ifndef R_OK
 2227 #   define R_OK 4   /* Test for Read permission */
 2228 #endif /* !R_OK */
 2229 #ifndef W_OK
 2230 #   define W_OK 2   /* Test for Write permission */
 2231 #endif /* !W_OK */
 2232 #ifndef X_OK
 2233 #   define X_OK 1   /* Test for eXecute permission */
 2234 #endif /* !X_OK */
 2235 #ifndef F_OK
 2236 #   define F_OK 0   /* Test for existence of File */
 2237 #endif /* !F_OK */
 2238 
 2239 /* Various function redefinitions */
 2240 #if defined(USE_DBMALLOC) || defined(USE_DMALLOC)
 2241 #   define my_malloc(size)  malloc((size_t) (size))
 2242 #   define my_calloc(nmemb, size)   calloc((nmemb), (size_t) (size))
 2243 #   define my_realloc(ptr, size)    realloc((ptr), (size_t) (size))
 2244 #else
 2245 #   define my_malloc(size)  my_malloc1(__FILE__, __LINE__, (size_t) (size))
 2246 #   define my_calloc(nmemb, size)   my_calloc1(__FILE__, __LINE__, (nmemb), (size_t) (size))
 2247 #   define my_realloc(ptr, size)    my_realloc1(__FILE__, __LINE__, (ptr), (size_t) (size))
 2248 #endif /* USE_DBMALLOC || USE_DMALLOC */
 2249 
 2250 #define ARRAY_SIZE(array)   ((int) (sizeof(array) / sizeof(array[0])))
 2251 
 2252 #define FreeIfNeeded(p) if (p != NULL) free((void *) p)
 2253 #define FreeAndNull(p)  if (p != NULL) { free((void *) p); p = NULL; }
 2254 
 2255 #define BlankIfNull(p)  ((p) ? (p) : "")
 2256 
 2257 #define my_group_find(x)    add_my_group(x, FALSE, FALSE)
 2258 #define my_group_add(x, y)  add_my_group(x, TRUE, y)
 2259 #define for_each_group(x)   for (x = 0; x < num_active; x++)
 2260 #define for_each_art(x)     for (x = 0; x < top_art; x++)
 2261 #define for_each_art_in_thread(x, y)    for (x = (int) base[y]; x >= 0; x = arts[x].thread)
 2262 
 2263 /*
 2264  * Cast for the (few!) places where we need to examine 8-bit characters w/o
 2265  * sign-extension, and a corresponding test-macro.
 2266  */
 2267 #define EIGHT_BIT(ptr)  (unsigned char *)ptr
 2268 #define is_EIGHT_BIT(p) ((*EIGHT_BIT(p) < 32 && !isspace((int)*p)) || *EIGHT_BIT(p) > 127)
 2269 
 2270 /*
 2271  * function prototypes & extern definitions
 2272  */
 2273 
 2274 #ifndef SIG_ARGS
 2275 #   if defined(__STDC__)
 2276 #       define SIG_ARGS int sig
 2277 #   endif /* __STDC__ */
 2278 #endif /* !SIG_ARGS */
 2279 
 2280 #ifndef __LCLINT__ /* lclint doesn't like it */
 2281 /* stifle complaints about not-a-prototype from gcc */
 2282 #   ifdef DECL_SIG_CONST
 2283 #       undef   SIG_DFL
 2284 #       define SIG_DFL  (void (*)(SIG_ARGS))0
 2285 #       undef   SIG_IGN
 2286 #       define SIG_IGN  (void (*)(SIG_ARGS))1
 2287 #       undef   SIG_ERR
 2288 #       define SIG_ERR  (void (*)(SIG_ARGS))-1
 2289 #   endif /* DECL_SIG_CONST */
 2290 #endif /* !__LCLINT__ */
 2291 
 2292 /*
 2293  * tputs() function-param
 2294  */
 2295 #ifdef OUTC_RETURN
 2296 #   define OUTC_RETTYPE int
 2297 #else
 2298 #   define OUTC_RETTYPE void
 2299 #endif /* OUTC_RETURN */
 2300 
 2301 #ifndef OUTC_ARGS
 2302 #   define OUTC_ARGS    int c
 2303 #endif /* !OUTC_ARGS */
 2304 
 2305 #if __STDC__ || defined(__cplusplus)
 2306 #   define OUTC_FUNCTION(func)  OUTC_RETTYPE func (OUTC_ARGS)
 2307 #else
 2308 #   define OUTC_FUNCTION(func)  OUTC_RETTYPE func (c) int c;
 2309 #endif /* __STDC__ || __cplusplus */
 2310 
 2311 typedef OUTC_RETTYPE (*OutcPtr) (OUTC_ARGS);
 2312 typedef FILE TCP;
 2313 
 2314 #ifndef EXTERN_H
 2315 #   include "extern.h"
 2316 #endif /* !EXTERN_H */
 2317 #ifndef TINRC_H
 2318 #   include "tinrc.h"
 2319 #endif /* !TINRC_H */
 2320 #ifndef NNTPLIB_H
 2321 #   include "nntplib.h"
 2322 #endif /* !NNTPLIB_H */
 2323 
 2324 #ifndef __CPROTO__
 2325 #   ifndef PROTO_H
 2326 #       include "proto.h"
 2327 #   endif /* !PROTO_H */
 2328 #endif /* !__CPROTO__ */
 2329 
 2330 /*
 2331  * rfc1521/rfc1522 interface
 2332  */
 2333 typedef void (*BodyPtr) (char *, FILE *, int);
 2334 
 2335 #ifdef USE_DBMALLOC
 2336 #   undef strchr
 2337 #   undef strrchr
 2338 #   include <dbmalloc.h> /* dbmalloc 1.4 */
 2339 #endif /* USE_DBMALLOC */
 2340 
 2341 #ifdef USE_DMALLOC
 2342 #   include <dmalloc.h>
 2343 #   define DMALLOC_FUNC_CHECK
 2344 #   ifdef HAVE_STRDUP
 2345 #       define my_strdup(s) strdup((s))
 2346 #   endif /* HAVE_STRDUP */
 2347 #endif /* USE_DMALLOC */
 2348 
 2349 #ifdef DOALLOC
 2350     extern char *doalloc(char *, size_t);
 2351     extern char *docalloc(size_t, size_t);
 2352     extern void dofree(char *);
 2353 #   undef malloc
 2354 #   undef realloc
 2355 #   undef calloc
 2356 #   undef free
 2357 #   define malloc(n)    doalloc((char *) 0, n)
 2358 #   define realloc      doalloc
 2359 #   define calloc       docalloc
 2360 #   define free     dofree
 2361     extern void fail_alloc(char *, char *);
 2362     extern void Trace(char *, ...);
 2363     extern void Elapsed(char *);
 2364     extern void WalkBack(void);
 2365     extern void show_alloc(void);
 2366     extern void no_leaks(void);
 2367 #endif /* DOALLOC */
 2368 
 2369 /* define some standard places to look for a tin.defaults file */
 2370 #define TIN_DEFAULTS_BUILTIN "/etc/opt/tin","/etc/tin","/etc","/usr/local/lib/tin","/usr/local/lib","/usr/local/etc/tin","/usr/local/etc","/usr/lib/tin","/usr/lib",NULL
 2371 #ifdef TIN_DEFAULTS_DIR
 2372 #   define TIN_DEFAULTS TIN_DEFAULTS_DIR,TIN_DEFAULTS_BUILTIN
 2373 #else
 2374 #   define TIN_DEFAULTS TIN_DEFAULTS_BUILTIN
 2375 #endif /* TIN_DEFAULTS_DIR */
 2376 
 2377 /*
 2378  * We force this include-ordering since socks.h contains redefinitions of
 2379  * functions that probably are prototyped via other includes. The socks.h
 2380  * definitions have to be included everywhere, since they're making wrappers
 2381  * for the stdio functions as well as the network functions.
 2382  */
 2383 #ifdef USE_SOCKS5
 2384 #   define SOCKS
 2385 #   include <socks.h>
 2386 /* socks.h doesn't define prototypes for use */
 2387 extern size_t read(int, char *, size_t);
 2388 extern int dup(int);
 2389 extern int close(int);
 2390 extern int fprintf(FILE *, const char *, ...);
 2391 extern int fclose(FILE *);
 2392 extern struct tm *localtime(time_t *);
 2393 #endif /* USE_SOCKS5 */
 2394 
 2395 #ifdef SETVBUF_REVERSED
 2396 #   define SETVBUF(stream, buf, mode, size) setvbuf(stream, mode, buf, size)
 2397 #else
 2398 #   define SETVBUF(stream, buf, mode, size) setvbuf(stream, buf, mode, size)
 2399 #endif /* SETVBUF_REVERSED */
 2400 
 2401 #ifdef CLOSEDIR_VOID
 2402 #   define CLOSEDIR(DIR)    closedir(DIR)
 2403 #else
 2404 #   define CLOSEDIR(DIR)    if (closedir(DIR)) error_message(2, "closedir() failed: %s %d", __FILE__, __LINE__)
 2405 #endif /* CLOSEDIR_VOID */
 2406 
 2407 #ifdef HAVE_GETTIMEOFDAY
 2408 #   ifndef GETTIMEOFDAY_2ARGS
 2409 #       define gettimeofday(a,b) gettimeofday(a)
 2410 #   endif /* GETTIMEOFDAY_2ARGS */
 2411 #endif /* HAVE_GETTIMEOFDAY */
 2412 
 2413 /* libmss */
 2414 #ifdef MSS
 2415 #   ifdef strdup
 2416 #       undef strdup
 2417 #   endif /* strdup */
 2418 #   include <mss.h>
 2419 #   undef my_malloc
 2420 #   undef my_realloc
 2421 #   undef my_calloc
 2422 #   define my_malloc(size)  malloc((size_t)(size))
 2423 #   define my_realloc(ptr, size)    realloc((ptr), (size_t) (size))
 2424 #   define my_calloc(nmemb, size) calloc((nmemb), (size_t) (size))
 2425 #endif /* MSS */
 2426 
 2427 /* libcanlock */
 2428 #ifdef USE_CANLOCK
 2429 #   ifdef HAVE_LIBCANLOCK_3_CANLOCK_H
 2430 #       include <libcanlock-3/canlock.h>
 2431 #   else
 2432 #       include <canlock.h>
 2433 #   endif /* HAVE_LIBCANLOCK_3_CANLOCK_H */
 2434 #endif /* USE_CANLOCK */
 2435 
 2436 /* gsasl */
 2437 #ifdef USE_SASL
 2438 #   include <gsasl.h>
 2439 #endif /* USE_SASL */
 2440 
 2441 /*
 2442  * adapted from ncurses curses.priv.h:
 2443  * If we have va_copy(), use it for assigning va_list's.
 2444  */
 2445 #if defined(HAVE___VA_COPY)
 2446 #   define begin_va_copy(dst,src)   __va_copy(dst, src)
 2447 #   define end_va_copy(dst) va_end(dst)
 2448 #else
 2449 #   if defined(va_copy) || defined(HAVE_VA_COPY)
 2450 #       define begin_va_copy(dst,src)   va_copy(dst, src)
 2451 #       define end_va_copy(dst) va_end(dst)
 2452 #   else
 2453 #       if defined(HAVE___BUILTIN_VA_COPY)
 2454 #           define begin_va_copy(dst,src)   __builtin_va_copy(dst, src)
 2455 #           define end_va_copy(dst) va_end(dst)
 2456 #       else
 2457 #           if defined(ARRAY_VA_LIST)
 2458 #               define begin_va_copy(dst,src)   *(dst) = *(src)
 2459 #               define end_va_copy(dst) /* nothing */
 2460 #           else
 2461 #               define begin_va_copy(dst,src)   (dst) = (src)
 2462 #               define end_va_copy(dst) /* nothing */
 2463 #           endif /* ARRAY_VA_LIST */
 2464 #       endif /* HAVE___BUILTIN_VA_COPY */
 2465 #   endif /* va_copy || HAVE_VA_COPY */
 2466 #endif /* HAVE___VA_COPY */
 2467 
 2468 /* snprintf(), vsnprintf() */
 2469 #ifndef HAVE_SNPRINTF
 2470 #   define snprintf plp_snprintf
 2471 #endif /* HAVE_SNPRINTF */
 2472 #ifndef HAVE_VSNPRINTF
 2473 #   define vsnprintf    plp_vsnprintf
 2474 #endif /* HAVE_VSNPRINTF */
 2475 
 2476 /* gcc-specific attributes */
 2477 #if defined(__GNUC__) && !defined(__cplusplus) && !defined(__APPLE_CC__) && !defined(__NeXT__)
 2478 #   if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
 2479 #       define UNUSED(x) x __attribute__((unused))
 2480 #   else
 2481 #       define UNUSED(x) x
 2482 #   endif /* __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6) */
 2483 #else
 2484 #   define UNUSED(x) x
 2485 #endif /* __GNUC__ && !__cplusplus && !__APPLE_CC__ && !__NeXT__ */
 2486 
 2487 /* init_selfinfo() needs MM_CHARSET */
 2488 #ifndef MM_CHARSET
 2489 #   define MM_CHARSET "US-ASCII"
 2490 #endif /* !MM_CHARSET */
 2491 
 2492 
 2493 #if !defined(SEEK_SET)
 2494 #   define SEEK_SET 0L
 2495 #endif /* !SEEK_SET */
 2496 
 2497 #if !defined(EOF)
 2498 #   define EOF -1
 2499 #endif /* !EOF */
 2500 
 2501 /* various filenames used by tin */
 2502 #define TIN_ARTICLE_NAME    ".article"
 2503 #define TIN_CANCEL_NAME ".cancel"
 2504 #define TIN_LETTER_NAME ".letter"
 2505 #define TIN_BUGREPORT_NAME  ".bugreport"
 2506 
 2507 /* read_news_active_file() / open_newsgroups_fp() */
 2508 #ifndef DISABLE_PIPELINING
 2509 #   define PIPELINE_LIMIT 45
 2510 #else
 2511 #   define PIPELINE_LIMIT 1
 2512 #endif /* DISABLE_PIPELINING */
 2513 
 2514 #ifndef DEBUG_H
 2515 #   include "debug.h"
 2516 #endif /* !DEBUG_H */
 2517 
 2518 struct t_overview_fmt {
 2519     char *name;
 2520     enum f_type type;
 2521 };
 2522 
 2523 struct t_version {
 2524     enum rc_state state;
 2525     int file_version;       /* rc_majorv * 10000 + rc_minorv * 100 + rc_subv */
 2526 /*  int current_version;*/  /* c_majorv * 10000 + c_minorv * 100 + c_subv */
 2527 };
 2528 
 2529 #endif /* !TIN_H */