unsigned char *buf_ptr = buf, c; int ch, vch, t, col, cnt, b_read;
unsigned char *buf_ptr = buf; int ch, vch, col, cnt, b_read;
display_line (FILE *f, long *last_pos, struct line_t **lineInfo, int n, 	      int *last, int *max, int flags, struct q_class_t **QuoteList,	      int *q_level, int *force_redraw, regex_t *SearchRE){  unsigned char buf[LONG_STRING], fmt[LONG_STRING];  unsigned char *buf_ptr = buf, c;  int ch, vch, t, col, cnt, b_read;  int buf_ready = 0, change_last = 0;  int special = 0, last_special = 0;  int offset;  int def_color;  int m;  ansi_attr a = {0,0,0,-1};  regmatch_t pmatch[1];  if (n == *last)  {    (*last)++;    change_last = 1;  }  if (*last == *max)  {    safe_realloc ((void **)lineInfo, sizeof (struct line_t) * (*max += LINES));    for (ch = *last; ch < *max ; ch++)    {      memset (&((*lineInfo)[ch]), 0, sizeof (struct line_t));      (*lineInfo)[ch].type = -1;      (*lineInfo)[ch].search_cnt = -1;      (*lineInfo)[ch].syntax = safe_malloc (sizeof (struct syntax_t));      ((*lineInfo)[ch].syntax)[0].first = ((*lineInfo)[ch].syntax)[0].last = -1;    }  }  /* only do color hiliting if we are viewing a message */  if (flags & (M_SHOWCOLOR | M_TYPES))  {    if ((*lineInfo)[n].type == -1)    {      /* determine the line class */      if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)      {	if (change_last)	  (*last)--;	return (-1);      }      resolve_types ((char *) fmt, *lineInfo, n, *last,		      QuoteList, q_level, force_redraw, flags & M_SHOWCOLOR);      /* avoid race condition for continuation lines when scrolling up */      for (m = n + 1; m < *last && (*lineInfo)[m].offset && (*lineInfo)[m].continuation; m++)	(*lineInfo)[m].type = (*lineInfo)[n].type;    }    /* this also prevents searching through the hidden lines */    if ((flags & M_HIDE) && (*lineInfo)[n].type == MT_COLOR_QUOTED)      flags = 0; /* M_NOSHOW */  }  /* At this point, (*lineInfo[n]).quote may still be undefined. We    * don't want to compute it every time M_TYPES is set, since this   * would slow down the "bottom" function unacceptably. A compromise   * solution is hence to call regexec() again, just to find out the   * length of the quote prefix.   */  if ((flags & M_SHOWCOLOR) && !(*lineInfo)[n].continuation &&      (*lineInfo)[n].type == MT_COLOR_QUOTED && (*lineInfo)[n].quote == NULL)  {    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)    {      if (change_last)	(*last)--;      return (-1);    }    regexec ((regex_t *) QuoteRegexp.rx, (char *) fmt, 1, pmatch, 0);    (*lineInfo)[n].quote = classify_quote (QuoteList,			    (char *) fmt + pmatch[0].rm_so,			    pmatch[0].rm_eo - pmatch[0].rm_so,			    force_redraw, q_level);  }  if ((flags & M_SEARCH) && !(*lineInfo)[n].continuation && (*lineInfo)[n].search_cnt == -1)   {    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)    {      if (change_last)	(*last)--;      return (-1);    }    offset = 0;    (*lineInfo)[n].search_cnt = 0;    while (regexec (SearchRE, (char *) fmt + offset, 1, pmatch, (offset ? REG_NOTBOL : 0)) == 0)    {      if (++((*lineInfo)[n].search_cnt) > 1)	safe_realloc ((void **) &((*lineInfo)[n].search),		      ((*lineInfo)[n].search_cnt) * sizeof (struct syntax_t));      else	(*lineInfo)[n].search = safe_malloc (sizeof (struct syntax_t));      pmatch[0].rm_so += offset;      pmatch[0].rm_eo += offset;      ((*lineInfo)[n].search)[(*lineInfo)[n].search_cnt - 1].first = pmatch[0].rm_so;      ((*lineInfo)[n].search)[(*lineInfo)[n].search_cnt - 1].last = pmatch[0].rm_eo;      if (pmatch[0].rm_eo == pmatch[0].rm_so)	offset++; /* avoid degenerate cases */      else	offset = pmatch[0].rm_eo;      if (!fmt[offset])	break;    }  }  if (!(flags & M_SHOW) && (*lineInfo)[n+1].offset > 0)  {    /* we've already scanned this line, so just exit */    return (0);  }  if ((flags & M_SHOWCOLOR) && *force_redraw && (*lineInfo)[n+1].offset > 0)  {    /* no need to try to display this line... */    return (1); /* fake display */  }  if ((b_read = fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, 			      sizeof (buf), &buf_ready)) < 0)  {    if (change_last)      (*last)--;    return (-1);  }  /* now chose a good place to break the line */  ch = -1; /* index of the last space or TAB */  cnt = 0;  col = option (OPTMARKERS) ? (*lineInfo)[n].continuation : 0;  while (col < COLS && cnt < b_read)  {    c = *buf_ptr++;    if (c == '\n')      break;    while (*buf_ptr == '\010' && cnt + 2 < b_read)    {      cnt += 2;      buf_ptr += 2;      c = buf[cnt];    }    if (*buf_ptr == '\033' && *(buf_ptr + 1) && *(buf_ptr + 1) == '[' && is_ansi (buf_ptr+2))    {      cnt = grok_ansi(buf, cnt+3, NULL);      cnt++;      buf_ptr = buf + cnt;      continue;    }    if (c == '\t')    {      ch = cnt;      /* expand TABs */      if ((t = (col & ~7) + 8) < COLS)      {	col = t;	cnt++;      }      else	break;    }    else if (IsPrint (c))    {      if (c == ' ')	ch = cnt;      col++;      cnt++;    }    else if (iscntrl (c) && c < '@')    {      if (c == '\r' && *buf_ptr == '\n')	cnt++;      else if (col < COLS - 1)      {	col += 2;	cnt++;      }      else	break;    }    else    {      col++;      cnt++;    }  }  /* move the break point only if smart_wrap is set */  if (option (OPTWRAP))  {    if (col == COLS)    {      if (ch != -1 && buf[cnt] != ' ' && buf[cnt] != '\t' && buf[cnt] != '\n' && buf[cnt] != '\r')      {	buf_ptr = buf + ch;	/* skip trailing blanks */	while (ch && (buf[ch] == ' ' || buf[ch] == '\t' || buf[ch] == '\r'))	  ch--;	cnt = ch + 1;      }      else	buf_ptr = buf + cnt; /* a very long word... */    }    if (!(flags & M_PAGER_NSKIP))      /* skip leading blanks on the next line too */      while (*buf_ptr == ' ' || *buf_ptr == '\t') 	buf_ptr++;  }  if (*buf_ptr == '\r')    buf_ptr++;  if (*buf_ptr == '\n')    buf_ptr++;  if ((int) (buf_ptr - buf) < b_read && !(*lineInfo)[n+1].continuation)    append_line (*lineInfo, n, (int) (buf_ptr - buf));  (*lineInfo)[n+1].offset = (*lineInfo)[n].offset + (long) (buf_ptr - buf);  /* if we don't need to display the line we are done */  if (!(flags & M_SHOW))    return 0;  if (flags & M_SHOWCOLOR)  {    m = ((*lineInfo)[n].continuation) ? ((*lineInfo)[n].syntax)[0].first : n;    if ((*lineInfo)[m].type == MT_COLOR_HEADER)      def_color = ((*lineInfo)[m].syntax)[0].color;    else      def_color = (*lineInfo)[m].type;    attrset (def_color);#ifdef HAVE_BKGDSET    bkgdset (def_color | ' ');#endif    clrtoeol ();    SETCOLOR (MT_COLOR_NORMAL);    BKGDSET (MT_COLOR_NORMAL);  }  else    clrtoeol ();    /* display the line */  col = option (OPTMARKERS) ? (*lineInfo)[n].continuation : 0;  for (ch = 0, vch = 0; ch < cnt; ch++, vch++)  {    special = 0;    c = buf[ch];    while (buf[ch+1] == '\010' && ch+2 < b_read)    {      if (buf[ch+2] == c)      {	special = (c == '_' && last_special == A_UNDERLINE)	  ? A_UNDERLINE : A_BOLD;	ch += 2;      }      else if (buf[ch] == '_' || buf[ch+2] == '_')      {	special = A_UNDERLINE;	ch += 2;	c = (buf[ch] == '_') ? buf[ch-2] : buf[ch];      }      else      {	special = 0; /* overstrike: nothing to do! */	ch += 2;	c = buf[ch];      }      last_special = special;    }    /* Handle ANSI sequences */    if (c == '\033' && buf[ch+1] == '[' && is_ansi (buf+ch+2))    {      ch = grok_ansi(buf, ch+2, &a);      c = buf[ch];      continue;    }    if (c == '\t')    {      if ((flags & (M_SHOWCOLOR | M_SEARCH | M_PAGER_MARKER)) || last_special	  || a.attr)      {	resolve_color (*lineInfo, n, vch, flags, special, &a);	if (!special)	  last_special = 0;      }      t = (col & ~7) + 8;      while (col < t)      {	addch (' ');	col++;      }    }    else if (IsPrint (c))    {      if ((flags & (M_SHOWCOLOR | M_SEARCH | M_PAGER_MARKER)) || special	  || last_special || a.attr)	resolve_color (*lineInfo, n, vch, flags, special, &a);      if (!special)	last_special = 0;      addch (c);      col++;    }    else if (iscntrl (c) && (c < '@' || c == 127))    {      if ((c != '\r' && c !='\n') || (buf[ch+1] != '\n' && buf[ch+1] != '\0'))      {	if ((flags & (M_SHOWCOLOR | M_SEARCH | M_PAGER_MARKER)) || last_special	    || a.attr)	{	  resolve_color (*lineInfo, n, vch, flags, special, &a);	  if (!special)	    last_special = 0;	}	addch ('^');	addch ((c + '@') & 127);	col += 2;      }    }    else    {      if ((flags & (M_SHOWCOLOR | M_SEARCH | M_PAGER_MARKER)) || last_special	  || a.attr)      {	resolve_color (*lineInfo, n, vch, flags, special, &a);	if (!special)	  last_special = 0;      }      if (ISSPACE (c))	addch (c);		/* unbreakable space */      else	addch ('?');      col++;    }  }  /* avoid a bug in ncurses... */#ifndef USE_SLANG_CURSES  if (col == 0)  {    SETCOLOR (MT_COLOR_NORMAL);    addch (' ');  }#endif  /* end the last color pattern (needed by S-Lang) */  if (last_special || (col != COLS && (flags & (M_SHOWCOLOR | M_SEARCH))))    resolve_color (*lineInfo, n, vch, flags, 0, &a);            /* ncurses always wraps lines when you get to the right side of the   * screen, but S-Lang seems to only wrap if the next character is *not*   * a newline (grr!).   */#ifndef USE_SLANG_CURSES    if (col < COLS)#endif      addch ('\n');  /* build a return code */  if (!(flags & M_SHOW))    flags = 0;  return (flags);}