/*************************************************************************
 ***                        output.c                     (JJB TEMPLAR) ***
 *** Date modifications begun: 7/8/89.                                 ***
 *** Last modified: 16/8/89.                                           ***
 *************************************************************************/
/*** High level routines for screen output.                            ***
 *************************************************************************/

#include "less.h"
#include "win.h"
#include "screen.h"

extern int  tty;
extern int  pr_type;
extern int  oldpr;

extern int  sc_width, sc_height;
extern int  twiddle;
extern int  fast_line;              /* In option.c */
extern char *line;

int     l_start = 0;
static char obuf[1024];
static char *ob = obuf;

UBYTE   chmap[32] = {      /* Determines which CTRL-chars to let through */
    1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1};
    /* Currently ESC and TAB are passed through */

void    put_line() /*====================================================*/
{                  /* Display line in cur buffer.                        */
register char   *p;              /* Note '\n' must be handled by caller. */
register int    len;

    if (!line) {
        if (twiddle) putc('~');
        return;
    }
    len = strlen(line) - l_start;
    if (len <= 0) return;

    line += l_start;    /* If l_start zero, no effect. Note that this   *
                         * ignores the problem of skipping ESC-chars,   *
                         * which results in unwanted effects.           */
  /* Very crude right side clip */
    if (len > sc_width + 20) line[len + 20] = 0;

    if (fast_line) puts(line);  /* Don't care about special chars */
    else for (p = line;  *p;  p++) {
        if (control_char((UBYTE)(*p))) {
            putc('^');
            putc(carat_char(*p));
        }
        else {
            switch (*p) {
                case ('~'): ul_enter(); break;
                case ('`'): ul_exit();  break;
                default:    putc(*p);
            }
        }
    }
    if (len > sc_width) {       /* May have crashed against right */
        flush();        /* <- annoying to have to do this */
        if (conpos() >= sc_width - 1) puts("[32;41m$[m");
    }
}

int     control_char(c) /*===============================================*/
register UBYTE  c;      /* Is c a control character? Note unsigned. */
{
    if ((c >= ' ') && (c != 0x7f)) return(0);
    return((c == 0x7f)? 1: (int)chmap[c]);
}

int     carat_char(c) /*=================================================*/
int     c;            /* Return ascii for control char (eg: C for ^C)    */
{
    return ((c == 0x7f)? '?': (c | 0x40));
}

void    flush() /*=======================================================*/
{
    if (!tty) ttopen();       /* tty: flag to indicate presence of console */

    ttflush();                /* flush obuf is different to ttflush obuf */
    tWrite(obuf,(ob-obuf));
    ob = obuf;
}

void    putc(c) /*=======================================================*/
int     c;      /* Output char. Write to buffer, flush buffer if full.   */
{
    if (ob >= &obuf[sizeof(obuf)]) flush();
    *ob++ = c;
}

void    puts(s) /*=======================================================*/
register char *s;
{
    while (*s) putc(*s++);          /* Ha. */
}

char    errmsg[100];

void    error(s,rw) /*===================================================*/
char    *s;
int     rw;         /* Really wait? */
{
register int    c;
    flush();        /* Hokay? Necessary for help/about */
    if (!rw) {      /* prompt() handles so_enter, etc */
        oldpr = pr_type;
        pr_type = PR_ERROR;
        strcpy(errmsg,s);
    }
    else {
        SetWindowTitles(Window,s,(char *)-1L);
        while ((c = getc()) != 0x44) bell();    /* Wait for <CR> */

     /* if (strlen(s) > sc_width) repaint();     No point if no auto-wrap */
    }
}
