"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.1/src/signal.c" (22 Dec 2021, 14488 Bytes) of package /linux/misc/tin-2.6.1.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 "signal.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.0_vs_2.6.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : signal.c
    4  *  Author    : I.Lea
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2021-09-30
    7  *  Notes     : signal handlers for different modes and window resizing
    8  *
    9  * Copyright (c) 1991-2022 Iain Lea <iain@bricbrac.de>
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  *
   16  * 1. Redistributions of source code must retain the above copyright notice,
   17  *    this list of conditions and the following disclaimer.
   18  *
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * 3. Neither the name of the copyright holder nor the names of its
   24  *    contributors may be used to endorse or promote products derived from
   25  *    this software without specific prior written permission.
   26  *
   27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 
   41 #ifndef TIN_H
   42 #   include "tin.h"
   43 #endif /* !TIN_H */
   44 #ifndef TCURSES_H
   45 #   include "tcurses.h"
   46 #endif /* !TCURSES_H */
   47 #ifndef included_trace_h
   48 #   include "trace.h"
   49 #endif /* !included_trace_h */
   50 #ifndef VERSION_H
   51 #   include "version.h"
   52 #endif /* !VERSION_H */
   53 
   54 /*
   55  * Needed for resizing under an xterm
   56  */
   57 #ifdef HAVE_TERMIOS_H
   58 #   include <termios.h>
   59 #else
   60 #   ifdef HAVE_TERMIO_H
   61 #       include <termio.h>
   62 #   endif /* HAVE_TERMIO_H */
   63 #endif /* HAVE_TERMIOS_H */
   64 
   65 #ifdef NEED_PTEM_H
   66 #   include <sys/stream.h>
   67 #   include <sys/ptem.h>
   68 #endif /* NEED_PTEM_H */
   69 
   70 #if defined(SIGWINCH) && !defined(DONT_HAVE_SIGWINCH)
   71 #   if !defined(TIOCGWINSZ) && !defined(TIOCGSIZE)
   72 #       ifdef HAVE_SYS_STREAM_H
   73 #           include <sys/stream.h>
   74 #       endif /* HAVE_SYS_STREAM_H */
   75 #       ifdef HAVE_SYS_PTY_H
   76 #           if !defined(_h_BSDTYPES) && defined(HAVE_SYS_BSDTYPES_H)
   77 #               include <sys/bsdtypes.h>
   78 #           endif /* !_h_BSDTYPES && HAVE_SYS_BSDTYPES_H */
   79 #           include <sys/pty.h>
   80 #       endif /* HAVE_SYS_PTY_H */
   81 #   endif /* !TIOCGWINSZ && !TIOCGSIZE */
   82 #endif /* SIGWINCH && !DONT_HAVE_SIGWINCH */
   83 
   84 #ifdef MINIX
   85 #   undef SIGTSTP
   86 #endif /* MINIX */
   87 
   88 /*
   89  * local prototypes
   90  */
   91 static const char *signal_name(int code);
   92 #ifdef SIGTSTP
   93     static void handle_suspend(void);
   94 #endif /* SIGTSTP */
   95 static void _CDECL signal_handler(SIG_ARGS);
   96 
   97 
   98 #ifdef SIGTSTP
   99     static t_bool do_sigtstp = FALSE;
  100 #endif /* SIGTSTP */
  101 #if defined(SIGWINCH) || defined(SIGTSTP)
  102     static t_bool redraw_after_suspend;
  103 #endif /* SIGWINCH || SIGTSTP */
  104 
  105 int signal_context = cMain;
  106 int input_context = cNone;
  107 int need_resize = cNo;
  108 /*
  109  * # lines of non-static data available for display
  110  */
  111 int NOTESLINES;
  112 
  113 
  114 #ifndef __LCLINT__ /* lclint doesn't like it */
  115 static const struct {
  116     int code;
  117     const char *name;
  118 } signal_list[] = {
  119 #   ifdef SIGINT
  120     { SIGINT,   "SIGINT" }, /* ctrl-C */
  121 #   endif /* SIGINT */
  122 #   ifdef SIGQUIT
  123     { SIGQUIT,  "SIGQUIT" },    /* ctrl-\ */
  124 #   endif /* SIGQUIT */
  125 #   ifdef SIGILL
  126     { SIGILL,   "SIGILL" }, /* illegal instruction */
  127 #   endif /* SIGILL */
  128 #   ifdef SIGFPE
  129     { SIGFPE,   "SIGFPE" }, /* floating point exception */
  130 #   endif /* SIGFPE */
  131 #   ifdef SIGBUS
  132     { SIGBUS,   "SIGBUS" }, /* bus error */
  133 #   endif /* SIGBUS */
  134 #   ifdef SIGSEGV
  135     { SIGSEGV,  "SIGSEGV" },    /* segmentation violation */
  136 #   endif /* SIGSEGV */
  137 #   ifdef SIGPIPE
  138     { SIGPIPE,  "SIGPIPE" },    /* broken pipe */
  139 #   endif /* SIGPIPE */
  140 #   ifdef SIGALRM
  141     { SIGALRM,  "SIGALRM" },    /* real-time timer expired */
  142 #   endif /* SIGALRM */
  143 #   ifdef SIGCHLD
  144     { SIGCHLD,  "SIGCHLD" },    /* death of a child process */
  145 #   endif /* SIGCHLD */
  146 #   ifdef SIGPWR
  147     { SIGPWR,   "SIGPWR" }, /* powerfail */
  148 #   endif /* SIGPWR */
  149 #   ifdef SIGTSTP
  150     { SIGTSTP,  "SIGTSTP" },    /* terminal-stop */
  151 #   endif /* SIGTSTP */
  152 #   ifdef SIGHUP
  153     { SIGHUP,   "SIGHUP" }, /* hang up */
  154 #   endif /* SIGHUP */
  155 #   ifdef SIGUSR1
  156     { SIGUSR1,  "SIGUSR1" },    /* User-defined signal 1 */
  157 #   endif /* SIGUSR1 */
  158 #   ifdef SIGUSR2
  159     { SIGUSR2,  "SIGUSR2" },    /* User-defined signal 2 */
  160 #   endif /* SIGUSR2 */
  161 #   ifdef SIGTERM
  162     { SIGTERM,  "SIGTERM" },    /* termination */
  163 #   endif /* SIGTERM */
  164 #   if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
  165     { SIGWINCH, "SIGWINCH" },   /* window-size change */
  166 #   endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
  167 };
  168 #endif /* !__LCLINT__ */
  169 
  170 
  171 #ifdef HAVE_NESTED_PARAMS
  172     RETSIGTYPE (*sigdisp(int signum, RETSIGTYPE (_CDECL *func)(SIG_ARGS)))(SIG_ARGS)
  173 #else
  174     RETSIGTYPE (*sigdisp(signum, func))(SIG_ARGS)
  175     int signum;
  176     RETSIGTYPE (_CDECL *func)(SIG_ARGS);
  177 #endif /* HAVE_NESTED_PARAMS */
  178 {
  179 #ifdef HAVE_POSIX_JC
  180 #   define RESTORE_HANDLER(x, y)
  181     struct sigaction sa, osa;
  182 
  183     sa.sa_handler = func;
  184     sigemptyset(&sa.sa_mask);
  185     sa.sa_flags = 0;
  186 #   ifdef SA_RESTART
  187         sa.sa_flags |= SA_RESTART;
  188 #   endif /* SA_RESTART */
  189     if (sigaction(signum, &sa, &osa) < 0)
  190         return SIG_ERR;
  191     return (osa.sa_handler);
  192 #else
  193 #   define RESTORE_HANDLER(x, y)    signal(x, y)
  194     return (signal(signum, func));
  195 #endif /* HAVE_POSIX_JC */
  196 }
  197 
  198 
  199 /*
  200  * Block/unblock SIGWINCH/SIGTSTP restarting syscalls
  201  */
  202 void
  203 allow_resize(
  204     t_bool allow)
  205 {
  206 #ifdef HAVE_POSIX_JC
  207     struct sigaction sa, osa;
  208 
  209     sa.sa_handler = signal_handler;
  210     sigemptyset(&sa.sa_mask);
  211     sa.sa_flags = 0;
  212 #   ifdef SA_RESTART
  213     if (!allow)
  214         sa.sa_flags |= SA_RESTART;
  215 #   endif /* SA_RESTART */
  216 #   if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
  217     sigaction(SIGWINCH, &sa, &osa);
  218 #   endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
  219 #   ifdef SIGTSTP
  220     sigaction(SIGTSTP, &sa, &osa);
  221 #   endif /* SIGTSTP */
  222 #endif /* HAVE_POSIX_JC */
  223 }
  224 
  225 
  226 static const char *
  227 signal_name(
  228     int code)
  229 {
  230     size_t n;
  231     const char *name = "unknown";
  232 
  233     for (n = 0; n < ARRAY_SIZE(signal_list); n++) {
  234         if (signal_list[n].code == code) {
  235             name = signal_list[n].name;
  236             break;
  237         }
  238     }
  239     return name;
  240 }
  241 
  242 
  243 /*
  244  * Rescale the display buffer and redraw the contents according to
  245  * the current context
  246  * This should NOT be called from an interrupt context
  247  */
  248 void
  249 handle_resize(
  250     t_bool repaint)
  251 {
  252 #if defined(SIGWINCH) || defined(SIGTSTP)
  253 #   ifdef SIGWINCH
  254     repaint |= set_win_size(&cLINES, &cCOLS);
  255 #   endif /* SIGWINCH */
  256 
  257     if (cLINES < MIN_LINES_ON_TERMINAL || cCOLS < MIN_COLUMNS_ON_TERMINAL) {
  258         ring_bell();
  259         tin_done(EXIT_FAILURE, _(txt_screen_too_small_exiting), tin_progname);
  260     }
  261 
  262     TRACE(("handle_resize(%d:%d)", signal_context, repaint));
  263 
  264     if (!repaint)
  265         return;
  266 
  267 #   ifdef USE_CURSES
  268 #       ifdef HAVE_RESIZETERM
  269     resizeterm(cLINES + 1, cCOLS);
  270     my_retouch();                   /* seems necessary if win size unchanged */
  271 #       else
  272     my_retouch();
  273 #       endif /* HAVE_RESIZETERM */
  274 #   endif /* USE_CURSES */
  275 
  276     switch (signal_context) {
  277         case cArt:
  278             ClearScreen();
  279             show_art_msg(CURR_GROUP.name);
  280             break;
  281 
  282         case cAttrib:
  283         case cConfig:
  284             refresh_config_page(SIGNAL_HANDLER);
  285             break;
  286 
  287         case cFilter:
  288             refresh_filter_menu();
  289             break;
  290 
  291         case cInfopager:
  292             display_info_page(0);
  293             break;
  294 
  295         case cAttachment:
  296         case cGroup:
  297         case cPOSTED:
  298         case cScope:
  299         case cSelect:
  300         case cThread:
  301         case cURL:
  302             ClearScreen();
  303             currmenu->redraw();
  304             break;
  305 
  306         case cPage:
  307             resize_article(TRUE, &pgart);
  308             draw_page(curr_group->name, 0);
  309             break;
  310 
  311         case cPost:
  312         case cPostCancel:
  313             refresh_post_screen(signal_context);
  314             break;
  315 
  316         case cPostFup:
  317             resize_article(TRUE, &pgart);
  318             draw_page(curr_group->name, 0);
  319             /*
  320              * Reset signal_context because draw_page()
  321              * sets signal_context to cPage.
  322              */
  323             signal_context = cPostFup;
  324             refresh_post_screen(signal_context);
  325             break;
  326 
  327         case cReconnect:
  328             ClearScreen();
  329             show_title(tin_progname);
  330             break;
  331 
  332         case cMain:
  333             break;
  334     }
  335     switch (input_context) {
  336         case cGetline:
  337             gl_redraw();
  338             break;
  339 
  340         case cPromptCONT:
  341             if (redraw_after_suspend)
  342                 info_message(_(txt_return_key));
  343             break;
  344 
  345         case cPromptSLK:
  346             prompt_slk_redraw();
  347             break;
  348 
  349         case cPromptYN:
  350             prompt_yn_redraw();
  351             break;
  352 
  353         default:
  354             break;
  355     }
  356     my_fflush(stdout);
  357     redraw_after_suspend = FALSE;
  358 #endif /* SIGWINCH || SIGTSTP */
  359 }
  360 
  361 
  362 #ifdef SIGTSTP
  363 static void
  364 handle_suspend(
  365     void)
  366 {
  367     t_bool save_cmd_line = cmd_line;
  368     t_bool save_state = (!batch_mode || !cmd_line);
  369 
  370     TRACE(("handle_suspend(%d)", signal_context));
  371 
  372     set_keypad_off();
  373     if (!cmd_line)
  374         set_xclick_off();
  375 
  376     if (save_state) {
  377         EndWin();
  378         Raw(FALSE);
  379     }
  380 
  381     wait_message(0, _(txt_suspended_message), tin_progname);
  382 
  383     kill(0, SIGSTOP);               /* Put ourselves to sleep */
  384 
  385     RESTORE_HANDLER(SIGTSTP, signal_handler);
  386 
  387     if (save_state) {
  388         Raw(TRUE);
  389         InitWin();
  390         cmd_line = save_cmd_line;
  391         if (!cmd_line)
  392             my_retouch();
  393         need_resize = cRedraw;      /* Flag a redraw */
  394         redraw_after_suspend = TRUE;
  395     }
  396     set_keypad_on();
  397     if (!cmd_line)
  398         set_xclick_on();
  399 }
  400 #endif /* SIGTSTP */
  401 
  402 
  403 static void _CDECL
  404 signal_handler(
  405     int sig)
  406 {
  407 #ifdef SIGCHLD
  408 #   ifdef HAVE_TYPE_UNIONWAIT
  409     union wait wait_status;
  410 #   else
  411     int wait_status = 1;
  412 #   endif /* HAVE_TYPE_UNIONWAIT */
  413 #endif /* SIGCHLD */
  414 
  415     /* In this case statement, we handle only the non-fatal signals */
  416     switch (sig) {
  417 #ifdef SIGINT
  418         case SIGINT:
  419             RESTORE_HANDLER(sig, signal_handler);
  420             return;
  421 #endif /* SIGINT */
  422 
  423 /*
  424  * fatal error but we don't want the "signal handler caught signal"
  425  * message here
  426  */
  427 #if defined(HAVE_ALARM) && defined(SIGALRM)
  428         case SIGALRM:
  429 #   ifdef DEBUG
  430             if ((debug & DEBUG_NNTP) && verbose > 1)
  431                 debug_print_file("NNTP", "get_server() %d sec elapsed without response", tinrc.nntp_read_timeout_secs);
  432 #   endif /* DEBUG */
  433             tin_done(NNTP_ERROR_EXIT, _("NNTP connection error. Exiting..."));
  434             return;
  435 #endif /* HAVE_ALARM && SIGALRM */
  436 
  437 #ifdef SIGCHLD
  438         case SIGCHLD:
  439             wait(&wait_status);
  440             RESTORE_HANDLER(sig, signal_handler);   /* death of a child */
  441             system_status = WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : 0;
  442             return;
  443 #endif /* SIGCHLD */
  444 
  445 #ifdef SIGTSTP
  446         case SIGTSTP:
  447             handle_suspend();
  448             return;
  449 #endif /* SIGTSTP */
  450 
  451 #ifdef SIGWINCH
  452         case SIGWINCH:
  453             need_resize = cYes;
  454             RESTORE_HANDLER(sig, signal_handler);
  455             return;
  456 #endif /* SIGWINCH */
  457 
  458 #ifdef SIGUSR2
  459         case SIGUSR2:
  460             if (!no_write) /* TODO: add more config-files to be saved */
  461                 write_newsrc();
  462             RESTORE_HANDLER(sig, signal_handler);
  463             return;
  464 #endif /* SIGUSR2 */
  465 
  466         default:
  467             break;
  468     }
  469 
  470     fprintf(stderr, "\n%s: signal handler caught %s signal (%d).\n", tin_progname, signal_name(sig), sig);
  471 
  472     switch (sig) {
  473 #ifdef SIGHUP
  474         case SIGHUP:
  475 #endif /* SIGHUP */
  476 #ifdef SIGUSR1
  477         case SIGUSR1:
  478 #endif /* SIGUSR1 */
  479 #ifdef SIGTERM
  480         case SIGTERM:
  481 #endif /* SIGTERM */
  482 #if defined(SIGHUP) || defined(SIGUSR1) || defined(SIGTERM)
  483             dangerous_signal_exit = TRUE;
  484             tin_done(-sig, NULL);
  485             /* NOTREACHED */
  486             break;
  487 #endif /* SIGHUP || SIGUSR1 || SIGTERM */
  488 
  489 #ifdef SIGSEGV
  490         case SIGSEGV:
  491 #   if defined(SIGBUS) && (SIGSEGV != SIGBUS) /* on Haiku SIGSEGV == SIGBUS */
  492         case SIGBUS:
  493 #   endif /* SIGBUS && SIGSEGV != SIGBUS */
  494 #else
  495 #   ifdef SIGBUS
  496         case SIGBUS:
  497 #   endif /* SIGBUS */
  498 #endif /* SIGSEGV */
  499 
  500 #if defined(SIGBUS) || defined(SIGSEGV)
  501             my_fprintf(stderr, _(txt_send_bugreport), tin_progname, VERSION, RELEASEDATE, RELEASENAME, bug_addr);
  502             my_fflush(stderr);
  503             break;
  504 #endif /* SIGBUS || SIGSEGV */
  505 
  506         default:
  507             break;
  508     }
  509 
  510     cleanup_tmp_files();
  511 
  512 #if 1
  513 /* #if defined(apollo) || defined(HAVE_COREFILE) */
  514     /* do this so we can get a traceback (doesn't dump core) */
  515     abort();
  516 #else
  517     giveup();
  518 #endif /* 1 */ /* apollo || HAVE_COREFILE */
  519 }
  520 
  521 
  522 /*
  523  * Turn on (flag != FALSE) our signal handler for TSTP and WINCH
  524  * Otherwise revert to the default handler
  525  */
  526 void
  527 set_signal_catcher(
  528     int flag)
  529 {
  530 #ifdef SIGTSTP
  531     if (do_sigtstp)
  532         sigdisp(SIGTSTP, flag ? signal_handler : SIG_DFL);
  533 #endif /* SIGTSTP */
  534 
  535 #if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
  536     sigdisp(SIGWINCH, flag ? signal_handler : SIG_DFL);
  537 #endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
  538 }
  539 
  540 
  541 void
  542 set_signal_handlers(
  543     void)
  544 {
  545     size_t n;
  546     int code;
  547 #ifdef SIGTSTP
  548     RETSIGTYPE (*ptr)(SIG_ARGS);
  549 #endif /* SIGTSTP */
  550 
  551     for (n = 0; n < ARRAY_SIZE(signal_list); n++) {
  552         switch ((code = signal_list[n].code)) {
  553 #ifdef SIGPIPE
  554         case SIGPIPE:
  555             sigdisp(code, SIG_IGN);
  556             break;
  557 #endif /* SIGPIPE */
  558 
  559 #ifdef SIGTSTP
  560         case SIGTSTP:
  561             ptr = sigdisp(code, SIG_DFL);
  562             sigdisp(code, ptr);
  563             if (ptr != SIG_IGN) {
  564                 /*
  565                  * SIGTSTP is ignored when starting from shells
  566                  * without job-control
  567                  */
  568                 do_sigtstp = TRUE;
  569                 sigdisp(code, signal_handler);
  570             }
  571             break;
  572 #endif /* SIGTSTP */
  573 
  574         default:
  575             sigdisp(code, signal_handler);
  576         }
  577     }
  578 }
  579 
  580 
  581 /*
  582  * Size the display at startup or rescale following a SIGWINCH etc.
  583  */
  584 t_bool
  585 set_win_size(
  586     int *num_lines,
  587     int *num_cols)
  588 {
  589     int old_lines;
  590     int old_cols;
  591 #ifdef TIOCGSIZE
  592     struct ttysize win;
  593 #else
  594 #   ifdef TIOCGWINSZ
  595     struct winsize win;
  596 #   endif /* TIOCGWINSZ */
  597 #endif /* TIOCGSIZE */
  598 
  599     old_lines = *num_lines;
  600     old_cols = *num_cols;
  601 
  602 #ifdef HAVE_XCURSES
  603     *num_lines = LINES - 1;     /* FIXME */
  604     *num_cols = COLS;
  605 #else /* curses/ncurses */
  606 
  607 #   ifndef USE_CURSES
  608     init_screen_array(FALSE);       /* deallocate screen array */
  609 #   endif /* !USE_CURSES */
  610 
  611 #   ifdef TIOCGSIZE
  612     if (ioctl(0, TIOCGSIZE, &win) == 0) {
  613         if (win.ts_lines != 0)
  614             *num_lines = win.ts_lines - 1;
  615         if (win.ts_cols != 0)
  616             *num_cols = win.ts_cols;
  617     }
  618 #   else
  619 #       ifdef TIOCGWINSZ
  620     if (ioctl(0, TIOCGWINSZ, &win) == 0) {
  621         if (win.ws_row != 0)
  622             *num_lines = win.ws_row - 1;
  623         if (win.ws_col != 0)
  624             *num_cols = win.ws_col;
  625     }
  626 #       else
  627 #       endif /* TIOCGWINSZ */
  628 #   endif /* TIOCGSIZE */
  629 
  630 #   ifndef USE_CURSES
  631     init_screen_array(TRUE);        /* allocate screen array for resize */
  632 #   endif /* !USE_CURSES */
  633 
  634 #endif /* HAVE_XCURSES */
  635 
  636     set_noteslines(*num_lines);
  637     return (*num_lines != old_lines || *num_cols != old_cols);
  638 }
  639 
  640 
  641 void
  642 set_noteslines(
  643     int num_lines)
  644 {
  645     NOTESLINES = num_lines - INDEX_TOP - (tinrc.beginner_level ? MINI_HELP_LINES : 1);
  646     if (NOTESLINES <= 0)
  647         NOTESLINES = 1;
  648 }