Logo Search packages:      
Sourcecode: aee version File versions  Download package

Xcurse.c

/*
      $Header: /home/hugh/sources/aee/RCS/Xcurse.c,v 1.37 2001/01/19 03:35:38 hugh Exp hugh $
*/

char *XCURSE_copyright_notice = "Copyright (c) 1987, 1988, 1991, 1992, 1994, 1995, 1996, 1998, 1999 Hugh Mahon.";

char *XCURSE_version_string = "@(#) Xcurse.c $Revision: 1.37 $";

#include "Xcurse.h"
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>

#include "aee.h"

#ifdef HAS_STDLIB
#include <stdlib.h>
#endif

#if defined(__STDC__)
#include <stdarg.h>
#else
#include <varargs.h>
#endif

#ifdef HAS_UNISTD
#include <unistd.h>
#endif

#ifdef HAS_SYS_IOCTL
#include <sys/ioctl.h>
#endif

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif /* min */

extern int eightbit;

static WINDOW *virtual_scr;
WINDOW *curscr;
WINDOW *stdscr;
WINDOW *last_window_refreshed;

WINDOW *clear_win;

char *new_curse = "February 1988";

int STAND = FALSE;      /* is standout mode activated?                  */
int Curr_x;       /* current x position on screen                 */
int Curr_y;       /* current y position on the screen       */
int LINES;
int COLS;
int initialized = FALSE;      /* tells whether new_curse is initialized */
int Repaint_screen;     /* if an operation to change screen impossible, repaint screen    */
int Num_bits;     /* number of bits per character     */

int XKey_vals[] = {
      84, 83, 82, 81, 89, 90, 91, 
      92, 0, 0, 0, 0, 134, 133, 132, 135, 127, 119, 
      111, 103, 102, 110, 94, 
      0, 0, 0, 0, 255
};

/*
 |    names of keys used below obtained through XKeysymToString()
 */

char *Key_strings[] = {
      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", 
      "F11", "F12", "Up", "Down", "Left", "Right", "Next", "Prior", 
      "Delete", "hpDeleteLine", "hpInsertLine", "Insert", "End", 
      "hpInsertChar", "hpDeleteChar", "BackSpace", "Home", NULL
      };

int Key_vals[] = {
      KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7),
      KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), 
      KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_NPAGE, KEY_PPAGE,
      KEY_DC, KEY_DL, KEY_IL, KEY_IC, KEY_EOL, KEY_IC, KEY_DC, KEY_BACKSPACE,
      KEY_HOME
};

/* the following data should go into a data structure in a future version */

Window wid;       /* window id                        */
Display *dp;            /* display pointer                  */
int Xscreen;            /* screen                     */
char *font_name;  /* name of font to use              */
XFontStruct *xaefont;   /* font information                 */
int fontwidth, fontheight;    /* font information           */
XSetWindowAttributes win_attrib;    /* window attributes    */
XEvent event;           /* event                      */
XKeyEvent *keyevent;    /* keyboard event structure         */
char *background; /* name of background color         */
char *foreground; /* name of foreground color         */
char *geometry;         /* height, width, xoffset, yoffset  */
char reverse_video;     /* reverse fore- and back-ground    */
int fore_pixel;         /* the pixel value of the foreground color */
int back_pixel;         /* the pixel value of the background color */
int temp_pixel;         /* temporary storage                */
XColor Fore_color;      /* struct holding foreground color values */
XColor Back_color;      /* struct holding background color values */
XColor exact_def_return;
Pixmap Fore_pixmap;     /* foreground pixmap                */
Pixmap Back_pixmap;     /* background pixmap                */
short bits;
Colormap colormap;
GC gc, revgc, cursor_gc, cursor_revgc;
XGCValues gcvalues;
/* end of information to be put into a data structure at a future date  */

Pixmap Temp_pixmap;     /* temporary storage, used when reversing colors */

int xtemp, ytemp;

#define icon_width 48
#define icon_height 48
static char icon_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
   0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00,
   0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0xf8, 0x03,
   0x00, 0x04, 0x20, 0x00, 0x06, 0x0c, 0x00, 0x04, 0x20, 0x00, 0x01, 0x10,
   0x00, 0x02, 0x40, 0x80, 0x00, 0x20, 0x00, 0x02, 0x40, 0x40, 0x00, 0x40,
   0x00, 0x03, 0x80, 0x40, 0x00, 0x40, 0x00, 0xff, 0xff, 0x20, 0x00, 0x80,
   0x80, 0x00, 0x00, 0x21, 0x00, 0x80, 0x80, 0x00, 0x00, 0xe1, 0xff, 0xff,
   0x40, 0x00, 0x00, 0x22, 0x00, 0x80, 0x20, 0x00, 0x00, 0x26, 0x00, 0x00,
   0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
   0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x00, 0x00, 0x48, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x90, 0x00, 0x10, 0x04, 0x00, 0x00, 0x10, 0x01, 0x08,
   0x04, 0x00, 0x00, 0x20, 0x06, 0x04, 0x02, 0x00, 0x00, 0x20, 0xf8, 0x03};

Pixmap pixmap;

int *virtual_lines;


/*
 |    Copy the contents of one window to another.
 */

void 
copy_window(origin, destination)
WINDOW *origin, *destination;
{
      int row, column;
      struct _line *orig, *dest;

      orig = origin->first_line;
      dest = destination->first_line;

      for (row = 0; 
            row < (min(origin->Num_lines, destination->Num_lines)); 
                  row++)
      {
            for (column = 0; 
                column < (min(origin->Num_cols, destination->Num_cols)); 
                  column++)
            {
                  dest->row[column] = orig->row[column];
                  dest->attributes[column] = orig->attributes[column];
            }
            dest->changed = orig->changed;
            dest->scroll = orig->scroll;
            dest->last_char = min(orig->last_char, destination->Num_cols);
            orig = orig->next_screen;
            dest = dest->next_screen;
      }
      destination->LX = min((destination->Num_cols - 1), origin->LX);
      destination->LY = min((destination->Num_lines - 1), origin->LY);
      destination->Attrib = origin->Attrib;
      destination->scroll_up = origin->scroll_up;
      destination->scroll_down = origin->scroll_down;
      destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
}

void 
reinitscr() 
{
      WINDOW *local_virt;
      WINDOW *local_std;
      WINDOW *local_cur;

      local_virt = newwin(LINES, COLS, 0, 0);
      local_std = newwin(LINES, COLS, 0, 0);
      local_cur = newwin(LINES, COLS, 0, 0);
      copy_window(virtual_scr, local_virt);
      copy_window(stdscr, local_std);
      copy_window(curscr, local_cur);
      delwin(virtual_scr);
      delwin(stdscr);
      delwin(curscr);
      virtual_scr = local_virt;
      stdscr = local_std;
      curscr = local_cur;
      free(virtual_lines);
      virtual_lines = (int *) malloc(LINES * (sizeof(int)));
}

int argc1;
char **argv1;


void 
get_options(argc, argv) /* get arguments from original command line     */
int argc;
char *argv[];
{
      char *buff;
      char *extens;
      int count;
      int ret_val;
      struct files *temp_names;
      int *x_off, *y_off;

      buff = ae_basename(argv[0]);
      if (!strcmp(buff, "rxae"))
      {
            restricted = TRUE;
            change_dir_allowed = FALSE;
      }

      argc1 = argc;
      argv1 = argv;
      x_off = (int *) &xtemp;
      y_off = (int *) &ytemp;
      if ((dp = XOpenDisplay(0)) == NULL)
      {
            printf("could not open display\n");
            exit(-1);
      }
      Xscreen = DefaultScreen(dp);
      geometry = NULL;
      reverse_video = FALSE;
      foreground = NULL;
      background = NULL;
      font_name = NULL;
      get_defaults();
      top_of_stack = NULL;
      echo_flag = TRUE;
      journ_on = TRUE;
      input_file = FALSE;
      recv_file = FALSE;
      recover = FALSE;
      count = 1;
      while (count < argc)
      {
            buff = argv[count];
            if (*buff == '-') /* options  */
            {
                  ++buff;
                  if (*buff == 'j') /* turn off recover file */
                        journ_on = FALSE;
                  else if (*buff == 'r')  /* recover from bad exit */
                        recover = TRUE;
                  else if (*buff == 'e')  /* turn off echo in init file */
                        echo_flag = FALSE;
                  else if (*buff == 'R')
                        reverse_video = TRUE;
                  else if (*buff == 'i')  /* turn off info window */
                        info_window = FALSE;
                  else if (!strcmp(argv[count], "-text"))
                  {
                        text_only = TRUE;
                  }
                  else if (!strcmp(argv[count], "-binary"))
                  {
                        text_only = FALSE;
                  }
                  else if (*buff == 't')  /* expand tabs to spaces */
                        expand = TRUE;
                  else if (*buff == 'n')  
                              /* turn off highlighting on menus*/
                        nohighlight = TRUE;
                  else if (!strcmp(argv[count], "-fg"))
                  {
                        count++;
                        foreground = argv[count];
                  }
                  else if (!strcmp(argv[count], "-bg"))
                  {
                        count++;
                        background = argv[count];
                  }
                  else if (!strcmp(argv[count], "-fn"))
                  {
                        count++;
                        font_name = argv[count];
                  }
                  else if (!strncmp(buff, "geometry", strlen(buff)))
                  {
                        count++;
                        geometry = argv[count];
                  }
            }
            else if (*buff == '+')
            {
                  buff++;
                  start_at_line = buff;
            }
            else  /* if the argument wasn't an option, must be a file name, right?  */
            {
                  if (top_of_stack == NULL)
                        temp_names = top_of_stack = name_alloc();
                  else
                  {
                        temp_names->next_name = name_alloc();
                        temp_names = temp_names->next_name;
                  }
                  temp_names->next_name = NULL;
                  extens = temp_names->name = xalloc(strlen(buff) + 1);

                  while (*buff != (char) NULL)
                  {
                        *extens = *buff;
                        buff++;
                        extens++;
                  }
                  *extens = (char) NULL;
                  input_file = TRUE;
                  recv_file = TRUE;
            }
            count++;
      }
      if (geometry != NULL)
            ret_val = XParseGeometry(geometry, x_off, y_off, &COLS, &LINES);
      if (COLS == 0)
            COLS = 80;
      if (LINES == 0)
            LINES = 24;
      if (xtemp == 0)
            xtemp = 10;
      if (ytemp == 0)
            ytemp = 15;
      win_height = LINES;
      win_width = COLS;
/*    if (top_of_stack == NULL)
      {
            fprintf(stderr, usage_str, argv[0]);
            exit(0);
      }
*/
}

void 
get_defaults()
{
      char *temp;

      geometry = XGetDefault(dp, "xae", "geometry");
      foreground = XGetDefault(dp, "xae", "foreground");
      background = XGetDefault(dp, "xae", "background");
      font_name = XGetDefault(dp, "xae", "font");
      temp = XGetDefault(dp, "xae", "ReverseVideo");
      if ((temp != NULL) && (!strcmp(temp, "on")))
            reverse_video = TRUE;
}

void 
initscr(cols, lines)          /* initialize terminal for operations     */
int cols, lines;
{
      int temp_val;
      XSizeHints  xsh;
      XWMHints wmHints;

#ifdef DEBUG
{
/*
 |    The following code will start an hpterm which will in turn execute 
 |    a debugger and "adopt" the process, so it can be debugged.
 */

      int child_id;
      char command_line[256];

      child_id = getpid();
      if (!fork())
      {
          sprintf(command_line, 
            "hpterm -fg wheat -bg DarkSlateGrey -n %s -e xdb %s -P %d", 
                  "hello",  "xae", child_id);
            execl("/bin/sh", "sh", "-c", command_line, NULL);
            fprintf(stderr, "could not exec new window\n");
            exit(1);
      }

/*
 |    When in debugger, set child_id to zero (p child_id=0) to continue 
 |    executing the software.
 */

      while (child_id != 0)
            ;
}
#endif

      LINES = lines;
      COLS = cols;
      keyevent = (XKeyEvent *) &event;
      back_pixel = XWhitePixel(dp, Xscreen);
      fore_pixel = XBlackPixel(dp, Xscreen);
      colormap = XDefaultColormap(dp, Xscreen);
      if (DisplayPlanes(dp, Xscreen) > 1)
      {
            if (foreground == NULL)
                  foreground = "white";
            if (XParseColor(dp, colormap, foreground, &Fore_color) != 0)
            {
                  XAllocColor(dp, colormap, &Fore_color);
                  fore_pixel = Fore_color.pixel;
            }
            if (background == NULL)
                  background = "#6B002F003100";
            if (XParseColor(dp, colormap, background, &Back_color) != 0)
            {
                  XAllocColor(dp, colormap, &Back_color);
                  back_pixel = Back_color.pixel;
            }
      }
      if (reverse_video)
      {
            temp_pixel = fore_pixel;
            fore_pixel = back_pixel;
            back_pixel = temp_pixel;
            bits = 0x99;
      }
      if (font_name == NULL)
      {
            font_name = "6x10";
            if ((XDisplayHeight(dp, Xscreen) > (LINES * 15)) &&
                (XDisplayWidth(dp, Xscreen) > (COLS * 9)))
                  font_name = "9x15";
      }
      if ((xaefont = XLoadQueryFont(dp, font_name)) == NULL)
      {
            printf("could not open font \"%s\" \n", font_name);
            exit(-1);
      }
      fontwidth = xaefont->max_bounds.rbearing - xaefont->min_bounds.lbearing;
      fontheight = xaefont->max_bounds.ascent + xaefont->max_bounds.descent;

      if (xtemp < 0)
      {
            temp_val = XDisplayWidth(dp, Xscreen);
            xtemp = temp_val - ((COLS*fontwidth) - xtemp);
      }
      if (ytemp < 0)
      {
            temp_val = XDisplayHeight(dp, Xscreen);
            ytemp = (temp_val + ytemp) - (LINES*fontheight);
      }
      if ((wid = XCreateWindow(dp, RootWindow(dp, Xscreen), xtemp, ytemp, 
           (COLS*fontwidth), (LINES*fontheight), 2, 
           DefaultDepth(dp, Xscreen), InputOutput, 
           DefaultVisual(dp, Xscreen), (CWBackPixel | CWColormap), 
           &win_attrib)) == (Window) NULL)
      {
            printf("could not create window \n");
            exit(-1);
      }
/*
 |    Try to set up some default values and icon information
 */

      pixmap = XCreateBitmapFromData(dp, wid, icon_bits, icon_width, icon_height);
      xsh.height = fontheight * LINES;
      xsh.width = fontwidth * COLS;
      xsh.base_height = xsh.height;
      xsh.base_width = xsh.width;
      xsh.max_width = XDisplayWidth(dp, DefaultScreen(dp));
      xsh.max_height = XDisplayHeight(dp, DefaultScreen(dp));
      xsh.min_height = fontheight * 24;
      xsh.min_width = fontwidth * 40;
      xsh.x = xtemp;
      xsh.y = ytemp;
      xsh.width_inc = fontwidth;
      xsh.height_inc = fontheight;
      xsh.flags = (USPosition | PSize | PResizeInc );
      XSetStandardProperties(dp, wid, "xae", "xae", pixmap, argv1, argc1, &xsh);

      win_attrib.override_redirect = FALSE;
      XSetWindowBackground(dp, wid, back_pixel);
      XChangeWindowAttributes (dp, wid, CWOverrideRedirect, 
            &win_attrib);
      gcvalues.font = xaefont->fid;
      gcvalues.foreground = fore_pixel;
      gcvalues.background = back_pixel;
      gcvalues.function   = GXcopy;
      gc = XCreateGC(dp, wid, (GCFont | GCForeground | 
                  GCBackground | GCFunction), &gcvalues);
      gcvalues.background = fore_pixel;
      gcvalues.foreground = back_pixel;
      revgc = XCreateGC(dp, wid, (GCFont | GCForeground | 
                  GCBackground | GCFunction), &gcvalues);

      gcvalues.foreground = fore_pixel;
      gcvalues.background = back_pixel;
      gcvalues.function   = GXcopy;
      cursor_gc = XCreateGC(dp, wid, (GCFont | GCForeground | 
                  GCBackground | GCFunction), &gcvalues);
      gcvalues.background = fore_pixel;
      gcvalues.foreground = back_pixel;
      cursor_revgc = XCreateGC(dp, wid, (GCFont | GCForeground | 
                  GCBackground | GCFunction), &gcvalues);

      XSetLineAttributes(dp, gc,    1, LineSolid, CapButt, JoinMiter);
      XSetLineAttributes(dp, revgc, 1, LineSolid, CapButt, JoinMiter);
      XSetLineAttributes(dp, cursor_gc,    1, LineSolid, CapButt, JoinMiter);
      XSetLineAttributes(dp, cursor_revgc, 1, LineSolid, CapButt, JoinMiter);

      XMapWindow(dp, wid);
      XStoreName(dp, wid, "xae");

      wmHints.initial_state = NormalState;
      wmHints.icon_pixmap = pixmap;
      wmHints.flags = IconPixmapHint | StateHint;
      XSetWMHints(dp, wid, &wmHints);

      XSelectInput(dp, wid, (KeyPress | ButtonPress | ButtonRelease | Expose));
      XFlush(dp);
      Key_Get();
      virtual_lines = (int *) malloc(LINES * (sizeof(int)));
      virtual_scr = newwin(LINES, COLS, 0, 0);
      stdscr = newwin(LINES, COLS, 0, 0);
      curscr = newwin(LINES, COLS, 0, 0);
      wmove(stdscr, 0, 0);
      werase(stdscr);
      Repaint_screen = TRUE;
      initialized = TRUE;
}

void 
Key_Get()
{
      int counter;
      
      for (counter = 0; Key_strings[counter] != NULL; counter++)
            XKey_vals[counter] = XStringToKeysym(Key_strings[counter]);
}

struct _line *
Screenalloc(columns)
int columns;
{
      int i;
      struct _line *tmp;

      tmp = (struct _line *) malloc(sizeof (struct _line));
      tmp->row = malloc(columns + 1);
      tmp->attributes = malloc(columns + 1);
      tmp->prev_screen = NULL;
      tmp->next_screen = NULL;
      for (i = 0; i < columns; i++)
      {
            tmp->row[i] = ' ';
            tmp->attributes[i] = (char) NULL;
      }
      tmp->scroll = tmp->changed = FALSE;
      tmp->row[0] = (char) NULL;
      tmp->attributes[0] = (char) NULL;
      tmp->row[columns] = (char) NULL;
      tmp->attributes[columns] = (char) NULL;
      tmp->last_char = 0;
      return(tmp);
}

WINDOW *
newwin(lines, cols, start_l, start_c)
int lines, cols;  /* number of lines and columns to be in window  */
int start_l, start_c;   /* starting line and column to be inwindow      */
{
      WINDOW *Ntemp;
      struct _line *temp_screen;
      int i;

      Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
      Ntemp->SR = start_l;
      Ntemp->SC = start_c;
      Ntemp->Num_lines = lines;
      Ntemp->Num_cols = cols;
      Ntemp->LX = 0;
      Ntemp->LY = 0;
      Ntemp->scroll_down = Ntemp->scroll_up = 0;
      Ntemp->SCROLL_CLEAR = FALSE;
      Ntemp->Attrib = FALSE;
      Ntemp->first_line = temp_screen = Screenalloc(cols);
      Ntemp->first_line->number = 0;
      Ntemp->line_array = (struct _line **) malloc(LINES * sizeof(struct _line *));

      Ntemp->line_array[0] = Ntemp->first_line;

      for (i = 1; i < lines; i++)
      {
            temp_screen->next_screen = Screenalloc(cols);
            temp_screen->next_screen->number = i;
            temp_screen->next_screen->prev_screen = temp_screen;
            temp_screen = temp_screen->next_screen;
            Ntemp->line_array[i] = temp_screen;
      }
      Ntemp->first_line->prev_screen = NULL;
      temp_screen->next_screen = NULL;
      return(Ntemp);
}

void 
wmove(window, row, column)    /* move cursor to indicated position in window */
WINDOW *window;
int row, column;
{
      if ((row < window->Num_lines) && (column < window->Num_cols))
      {
            window->LX = column;
            window->LY = row;
      }
}

void 
clear_line(line, column, cols)
struct _line *line;
int column;
int cols;
{
      int j;

      if (column > line->last_char)
      {
            for (j = line->last_char; j < column; j++)
            {
                  line->row[j] = ' ';
                  line->attributes[j] = (char) NULL;
            }
      }
      line->last_char = column;
      line->row[column] = (char) NULL;
      line->attributes[column] = (char) NULL;
      line->changed = TRUE;
}

void 
werase(window)                /* clear the specified window       */
WINDOW *window;
{
      int i;
      struct _line *tmp;

      window->SCROLL_CLEAR = CLEAR;
      window->scroll_up = window->scroll_down = 0;
      for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
            clear_line(tmp, 0, window->Num_cols);
}

void 
wclrtoeol(window) /* erase from current cursor position to end of line */
WINDOW *window;
{
      int column, row;
      struct _line *tmp;

      window->SCROLL_CLEAR = CHANGE;
      column = window->LX;
      row = window->LY;
      for (row = 0, tmp = window->first_line; row < window->LY; row++)
            tmp = tmp->next_screen;
      clear_line(tmp, column, window->Num_cols);
}

void 
wrefresh(window)        /* flush all previous output        */
WINDOW *window;
{
      wnoutrefresh(window);
      doupdate();
      virtual_scr->SCROLL_CLEAR = FALSE;
      virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
      XFlush(dp);
}

void 
touchwin(window)
WINDOW *window;
{
      struct _line *user_line;
      int line_counter = 0;

      for (line_counter = 0, user_line = window->first_line; 
            line_counter < window->Num_lines; line_counter++)
      {
            user_line->changed = TRUE;
      }
      window->SCROLL_CLEAR = TRUE;
}

void 
wnoutrefresh(window)
WINDOW *window;
{
      struct _line *user_line;
      struct _line *virtual_line;
      int line_counter = 0;
      int user_col = 0;
      int virt_col = 0;

      cursor(virtual_scr, virtual_scr->LY, virtual_scr->LX, TRUE, FALSE);

      if (window->SR >= virtual_scr->Num_lines)
            return;
      user_line = window->first_line;
      virtual_line = virtual_scr->first_line;
      virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
      virtual_scr->LX = window->LX + window->SC;
      virtual_scr->LY = window->LY + window->SR;
      virtual_scr->scroll_up = window->scroll_up;
      virtual_scr->scroll_down = window->scroll_down;
      if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
            return;
      for (line_counter = 0; line_counter < window->SR; line_counter++)
      {
            virtual_line = virtual_line->next_screen;
      }
      for (line_counter = 0; (line_counter < window->Num_lines)
            && ((line_counter + window->SR) < virtual_scr->Num_lines); 
                  line_counter++)
      {
            if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
            {
                  for (user_col = 0, virt_col = window->SC; 
                        (virt_col < virtual_scr->Num_cols) 
                          && (user_col < user_line->last_char); 
                              virt_col++, user_col++)
                  {
                        virtual_line->row[virt_col] = user_line->row[user_col];
                        virtual_line->attributes[virt_col] = user_line->attributes[user_col];
                  }
                  for (user_col = user_line->last_char, 
                       virt_col = window->SC + user_line->last_char; 
                        (virt_col < virtual_scr->Num_cols) 
                          && (user_col < window->Num_cols); 
                              virt_col++, user_col++)
                  {
                        virtual_line->row[virt_col] = ' ';
                        virtual_line->attributes[virt_col] = (char) NULL;
                  }
            }
            if (virtual_scr->Num_cols != window->Num_cols)
            {
                  if (virtual_line->last_char < (user_line->last_char + window->SC))
                  {
                        if (virtual_line->row[virtual_line->last_char] == (char) NULL)
                              virtual_line->row[virtual_line->last_char] = ' ';
                        virtual_line->last_char = 
                              min(virtual_scr->Num_cols, 
                                (user_line->last_char + window->SC));
                  }
            }
            else
                  virtual_line->last_char = user_line->last_char;
            virtual_line->row[virtual_line->last_char] = (char) NULL;
            virtual_line->changed = user_line->changed;
            virtual_line = virtual_line->next_screen;
            user_line = user_line->next_screen;
      }
      window->SCROLL_CLEAR = FALSE;
      window->scroll_up = window->scroll_down = 0;
      last_window_refreshed = window;
}

void 
flushinp()              /* flush input                      */
{
}

int 
wgetch(window)                /* get character from specified window    */
WINDOW *window;
{
      int status;
      int in_value;
      char temp;
      KeySym keysym_return;

      if ((status = XLookupString(keyevent, &temp, 1, &keysym_return, NULL)))
            in_value = temp;
      else if ((IsModifierKey(keysym_return)) || (IsMiscFunctionKey(keysym_return)))
      {
            in_value = 0;
      }
      else
      {
/*          key_code = XKeysymToKeycode(dp, keysym_return); */
            in_value = look_up_key(keysym_return);
      }
      return(in_value);
}

int
look_up_key(key_code)         /* decode mapping of key            */
int key_code;
{
      int count;

      count = 0;
      while ((Key_vals[count] != 255) && (key_code != XKey_vals[count]))
            count++;
      if (XKey_vals[count] == key_code)
            return(Key_vals[count]);
      else
      {
#ifdef TEST
            wmove(stdscr, 0, 0);
            wclrtoeol(stdscr);
            wprintw(stdscr, "unknown keycode = %o", key_code);
            wrefresh(stdscr);
#endif
            return(0);
      }
}

void 
waddch(window, c) /* output the character in the specified window */
WINDOW *window;
int c;
{
      int column, j;
      int shift;  /* number of spaces to shift if a tab           */
      struct _line *tmpline;

      column = window->LX;
      if (c == '\t')
      {
            shift = (column + 1) % 8;
            if (shift == 0)
                  shift++;
            else
                  shift = 9 - shift;
            while (shift > 0)
            {
                  shift--;
                  waddch(window, ' ');
            }
      }
      else if ((!((window->LY >= (window->Num_lines - 1)) && (column >= (window->Num_cols - 1)))) && (column < window->Num_cols) && (window->LY < window->Num_lines))
      {
            if (( c != '\b') && (c != '\n') && (c != '\r'))
            {
                  tmpline = window->first_line; 
                  tmpline = window->line_array[window->LY];
                  tmpline->changed = TRUE;
                  tmpline->row[column] = c;
                  tmpline->attributes[column] = window->Attrib;
                  if (column >= tmpline->last_char)
                  {
                        if (column > tmpline->last_char)
                              for (j = tmpline->last_char; j < column; j++)
                              {
                                    tmpline->row[j] = ' ';
                                    tmpline->attributes[j] = (char) NULL;
                              }
                        tmpline->row[column + 1] = (char) NULL;
                        tmpline->attributes[column + 1] = (char) NULL;
                        tmpline->last_char = column + 1;
                  }
            }
            if (c == '\n')
            {
                  wclrtoeol(window);
                  window->LX = window->Num_cols;
            }
            else if (c == '\r')
                  window->LX = 0;
            else if (c == '\b')
                  window->LX--;
            else
                  window->LX++;
      }
      if (window->LX >= window->Num_cols)
      {
            window->LX = 0;
            window->LY++;
            if (window->LY >= window->Num_lines)
            {
                  window->LY = window->Num_lines - 1;
                  wmove(window, 0, 0);
                  wdeleteln(window);
                  wmove(window, window->LY, 0);
            }
      }
      window->SCROLL_CLEAR = CHANGE;
}

void 
winsertln(window) /* insert a blank line into the specified window */
WINDOW *window;
{
      int row, column;
      struct _line *tmp;
      struct _line *tmp1;

      window->scroll_down += 1;
      window->SCROLL_CLEAR = SCROLL;
      column = window->LX;
      row = window->LY;
      for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
            tmp = tmp->next_screen;
      if (tmp->prev_screen != NULL)
            tmp->prev_screen->next_screen = NULL;
      tmp1 = tmp;
      clear_line(tmp1, 0, window->Num_cols);
      tmp1->number = -1;
      for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
            tmp = tmp->next_screen;
      if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
      {
            tmp1->next_screen = tmp->next_screen;
            tmp->next_screen = tmp1;
            tmp->next_screen->prev_screen = tmp;
      }
      else if (window->Num_lines > 1)
      {
            if (tmp->prev_screen != NULL)
                  tmp->prev_screen->next_screen = tmp1;
            tmp1->prev_screen = tmp->prev_screen;
            tmp->prev_screen = tmp1;
            tmp1->next_screen = tmp;
            tmp->scroll = DOWN;
      }
      if (window->LY == 0)
            window->first_line = tmp1;

      for (row = 0, tmp1 = window->first_line; 
            row < window->Num_lines; row++)
      {
            window->line_array[row] = tmp1;
            tmp1 = tmp1->next_screen;
      }
}

void 
wdeleteln(window) /* delete a line in the specified window */
WINDOW *window;
{
      int row, column;
      struct _line *tmp;
      struct _line  *tmpline;

      if (window->Num_lines > 1)
      {
            window->scroll_up += 1;
            window->SCROLL_CLEAR = SCROLL;
            column = window->LX;
            row = window->LY;
            for (row = 0, tmp = window->first_line; row < window->LY; row++)
                  tmp = tmp->next_screen;
            if (window->LY == 0)
                  window->first_line = tmp->next_screen;
            if (tmp->prev_screen != NULL)
                  tmp->prev_screen->next_screen = tmp->next_screen;
            if (tmp->next_screen != NULL)
            {
                  tmp->next_screen->scroll = UP;
                  tmp->next_screen->prev_screen = tmp->prev_screen;
            }
            tmpline = tmp;
            clear_line(tmpline, 0, window->Num_cols);
            tmpline->number = -1;
            for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
            {
                  tmp = tmp->next_screen;
            }
            if (tmp != NULL)
            {
                  tmp->next_screen = tmpline;
                  tmp->next_screen->prev_screen = tmp;
                  tmp = tmp->next_screen;
            }
            else
                  tmp = tmpline;
            tmp->next_screen = NULL;

            for (row = 0, tmp = window->first_line; row < window->Num_lines; row++)
            {
                  window->line_array[row] = tmp;
                  tmp = tmp->next_screen;
            }
      }
      else
      {
            clear_line(window->first_line, 0, window->Num_cols);
      }
}

void 
wclrtobot(window) /* delete from current position to end of the window */
WINDOW *window;
{
      int row, column;
      struct _line *tmp;

      window->SCROLL_CLEAR |= CLEAR;
      column = window->LX;
      row = window->LY;
      for (row = 0, tmp = window->first_line; row < window->LY; row++)
            tmp = tmp->next_screen;
      clear_line(tmp, column, window->Num_cols);
      for (row = (window->LY + 1); row < window->Num_lines; row++)
      {
            tmp = tmp->next_screen;
            clear_line(tmp, 0, window->Num_cols);
      }
      wmove(window, row, column);
}

void 
wstandout(window) /* begin standout mode in window    */
WINDOW *window;
{
      window->Attrib |= A_STANDOUT;
}

void 
wstandend(window) /* end standout mode in window      */
WINDOW *window;
{
      window->Attrib &= ~A_STANDOUT;
}

void 
waddstr(window, string) /* write 'string' in window   */
WINDOW *window;
char *string;
{
      char *wstring;

      for (wstring = string; *wstring != (char) NULL; wstring++)
            waddch(window, *wstring);
}

void 
clearok(window, flag)   /* erase screen and redraw at next refresh      */
WINDOW *window;
int flag;
{
      Repaint_screen = TRUE;
      clear_win = window;
}

void 
echo()                  /* turn on echoing                        */
{

}

void 
noecho()          /* turn off echoing                       */
{

}

void 
raw()             /* set to read characters immediately           */
{
}

void 
noraw()                 /* set to normal character read mode            */
{

}

void 
nl()
{
}

void 
nonl()
{

}

void 
saveterm()
{
}

void 
fixterm()
{
}

void 
resetterm()
{
}

void 
nodelay(window, flag)
WINDOW *window;
int flag;
{
}

void 
idlok(window, flag)
WINDOW *window;
int flag;
{
}

void 
keypad(window, flag)
WINDOW *window;
int flag;
{
}

void 
savetty()         /* save current tty stats                 */
{

}

void 
resetty()         /* restore previous tty stats             */
{

}

void 
endwin()          /* end windows                            */
{
      keypad(stdscr, FALSE);
      free(stdscr);
      initialized = FALSE;
}

void 
delwin(window)          /* delete the window structure                  */
WINDOW *window;
{
      int i;

      for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
      {
            window->first_line = window->first_line->next_screen;
            free(window->first_line->prev_screen->row);
            free(window->first_line->prev_screen->attributes);
            free(window->first_line->prev_screen);
      }
      if (window->first_line != NULL)
      {
            free(window->first_line->row);
            free(window->first_line->attributes);
            free(window->first_line);
            free(window);
      }
}

#ifndef __STDC__
void 
wprintw(va_alist)
va_dcl
#else /* __STDC__ */
void 
wprintw(WINDOW *window, const char *format, ...)
#endif /* __STDC__ */
{
#ifndef __STDC__
      WINDOW *window;
      char *format;
      va_list ap;
#else
      va_list ap;
#endif
      int value;
      char *fpoint;
      char *wtemp;

#ifndef __STDC__
      va_start(ap);
      window = va_arg(ap, WINDOW *);
      format = va_arg(ap, char *);
#else /* __STDC__ */
      va_start(ap, format);
#endif /* __STDC__ */

      fpoint = (char *) format;
      while (*fpoint != (char) NULL)
      {
            if (*fpoint == '%')
            {
                  fpoint++;
                  if (*fpoint == 'd')
                  {
                        value = va_arg(ap, int);
                        iout(window, value, 10);
                  }
                  else if (*fpoint == 'c')
                  {
                        value = va_arg(ap, int);
                        waddch(window, value);
                  }
                  else if (*fpoint == 's')
                  {
                        wtemp = va_arg(ap, char *);
                              waddstr(window, wtemp);
                  }
                  fpoint++;
            }
            else if (*fpoint == '\\')
            {
                  fpoint++;
                  if (*fpoint == 'n')
                        waddch(window, '\n');
                  else if ((*fpoint >= '0') && (*fpoint <= '9'))
                  {
                        value = 0;
                        while ((*fpoint >= '0') && (*fpoint <= '9'))
                        {
                              value = (value * 8) + (*fpoint - '0');
                              fpoint++;
                        }
                        waddch(window, value);
                  }
                  fpoint++;
            }
            else
                  waddch(window, *fpoint++);
      }
#ifdef __STDC__
      va_end(ap);
#endif /* __STDC__ */
}

void 
iout(window, value, base)     /* output characters          */
WINDOW *window;
int value;
int base;   /* base of number to be printed                 */
{
      int i;

      if ((i = value / base) != 0)
            iout(window, i, base);
      waddch(window, ((value % base) + '0'));
}

int 
Comp_line(line1, line2)       /* compare lines  */
struct _line *line1;
struct _line *line2;
{
      int count1;
      int i;
      char *att1, *att2;
      char *c1, *c2;

      if (line1->last_char != line2->last_char)
            return(2);

      c1 = line1->row;
      c2 = line2->row;
      att1 = line1->attributes;
      att2 = line2->attributes;
      i = 0;
      while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i]))
            i++;
      count1 = i + 1;
      if ((count1 == 1) && (c1[i] == (char) NULL) && (c2[i] == (char) NULL))
            count1 = 0;             /* both lines blank     */
      else if ((c1[i] == (char) NULL) && (c2[i] == (char) NULL))
            count1 = -1;                  /* equal          */
      else
            count1 = 1;             /* lines unequal  */
      return(count1);
}

struct _line *
Insert_line(row, end_row, window)   /* insert line into screen */
int row;
int end_row;
WINDOW *window;
{
      int i;
      struct _line *tmp;
      struct _line *tmp1;
      int wind_y_offset;

      for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
            tmp = tmp->next_screen;
      if ((end_row + window->SR) == 0)
            curscr->first_line = curscr->first_line->next_screen;
      top_of_win = tmp;
      for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
            tmp = tmp->next_screen;
      if (tmp->prev_screen != NULL)
            tmp->prev_screen->next_screen = tmp->next_screen;
      if (tmp->next_screen != NULL)
            tmp->next_screen->prev_screen = tmp->prev_screen;
      tmp1 = tmp;
      clear_line(tmp, 0, window->Num_cols);
      tmp1->number = -1;
      for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
            tmp = tmp->next_screen;
      top_of_win = tmp;
      for (i = 0, tmp = top_of_win; i < row; i++)
            tmp = tmp->next_screen;

      if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
            tmp->prev_screen->next_screen = tmp1;

      tmp1->prev_screen = tmp->prev_screen;
      tmp->prev_screen = tmp1;
      tmp1->next_screen = tmp;
      if ((row + window->SR) == 0)
            curscr->first_line = tmp1;

      if (tmp1->next_screen != NULL)
            tmp1 = tmp1->next_screen;
      wind_y_offset = window->SR * fontheight;
      XCopyArea(dp, wid, wid, gc, 0, (wind_y_offset + (row * fontheight)), (COLS * fontwidth), ((end_row - row) * fontheight), 0, (wind_y_offset + ((1 + row) * fontheight)));
      XClearArea(dp, wid, 0, (wind_y_offset + (row * fontheight)), (COLS * fontwidth), fontheight, FALSE);
      XFlush(dp);

      for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
            top_of_win = top_of_win->next_screen;

      return(tmp1);
}

struct _line *
Delete_line(row, end_row, window)   /* delete a line on screen */
int row;
int end_row;
WINDOW *window;
{
      int i;
      struct _line *tmp;
      struct _line *tmp1;
      struct _line *tmp2;
      int wind_y_offset;

      i = 0;
      tmp = curscr->first_line;
      while (i < window->SR)
      {
            i++;
            tmp = tmp->next_screen;
      }
      top_of_win = tmp;
      if ((row + window->SR) == 0)
            curscr->first_line = top_of_win->next_screen;
      for (i = 0, tmp = top_of_win; i < row; i++)
            tmp = tmp->next_screen;
      if (tmp->prev_screen != NULL)
            tmp->prev_screen->next_screen = tmp->next_screen;
      if (tmp->next_screen != NULL)
            tmp->next_screen->prev_screen = tmp->prev_screen;
      tmp2 = tmp->next_screen;
      tmp1 = tmp;
      clear_line(tmp1, 0, window->Num_cols);
      tmp1->number = -1;
      for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
            tmp = tmp->next_screen;
      top_of_win = tmp;
      for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
            tmp = tmp->next_screen;
      tmp1->next_screen = tmp;
      tmp1->prev_screen = tmp->prev_screen;
      if (tmp1->prev_screen != NULL)
            tmp1->prev_screen->next_screen = tmp1;
      tmp->prev_screen = tmp1;
      wind_y_offset = window->SR * fontheight;
      XCopyArea(dp, wid, wid, gc, 0, (wind_y_offset + ((row + 1) * fontheight)), (COLS * fontwidth), ((end_row - row) * fontheight), 0, (wind_y_offset + (row * fontheight)));
      XClearArea(dp, wid, 0, (wind_y_offset + (end_row * fontheight)), (COLS * fontwidth), fontheight, FALSE);
      XFlush(dp);
/*    if (row == (window->Num_lines-1))
            tmp2 = tmp1;
      if ((row + window->SR) == 0)
            curscr->first_line = top_of_win = tmp2;*/

      return(tmp2);
}

void 
CLEAR_TO_EOL(window, row, column)
WINDOW *window;
int row, column;
{
      int x, y, width, height;
      struct _line *tmp1;

      for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
            tmp1 = tmp1->next_screen;
      for (x = column; x<window->Num_cols; x++)
      {
            tmp1->row[x] = ' ';
            tmp1->attributes[x] = (char) NULL;
      }
      tmp1->row[column] = (char) NULL;
      tmp1->last_char = column;
      if (column <= tmp1->last_char)
      {
            x = column * fontwidth;
            y = (row + window->SR) * fontheight;
            width = (COLS - column) * fontwidth;
            height = fontheight;
            XClearArea(dp, wid, x, y, width, height, FALSE);
      }
}


void 
doupdate()
{
      WINDOW *window;
      int similar;
      int diff;
      int begin_old, begin_new;
      int count1, j;
      int i;
      int from_top, tmp_ft, offset;
      int changed;
      int first_same;         /* first line from bottom where diffs occur */
      int last_same;          /* first line from top which is same          */
      int bottom;

      struct _line *curr;
      struct _line *virt;
      struct _line *old;

      struct _line *new;

      struct _line *old1, *new1;

      char *cur_lin;
      char *vrt_lin;
      char *cur_att;
      char *vrt_att;

      window = virtual_scr;

      if (Repaint_screen)
      {
            for (i = 0, curr = curscr->first_line; i < curscr->Num_lines; i++, curr = curr->next_screen)
            {
                  Position(curscr, i, 0);
                  for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++)
                  {
                        Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
                  }
                  if (STAND)
                        STAND = FALSE;
            }
            Repaint_screen = FALSE;
      }

      similar = 0;
      diff = FALSE;
      top_of_win = curscr->first_line;

      for (from_top = 0, curr = top_of_win, virt = window->first_line; 
                  from_top < window->Num_lines; from_top++)
      {
            virtual_lines[from_top] = TRUE;
            if ((similar = Comp_line(curr, virt)) > 0)
            {
                  virtual_lines[from_top] = FALSE;
                  diff = TRUE;
            }
            curr = curr->next_screen;
            virt = virt->next_screen;
      }

      from_top = 0;
      virt = window->first_line;
      curr = top_of_win;
      similar = 0;
      /*
       |  if the window has lines that are different
       */
      if (diff)
      {
            last_same = -1;
            changed = FALSE;
            for (first_same = window->Num_lines; 
                (first_same > from_top) && (virtual_lines[first_same - 1]);
                 first_same--)
                  ;
            for (last_same = 0; 
                (last_same < window->Num_lines) && (virtual_lines[last_same] == FALSE);
                 last_same++)
                  ;

            while (from_top < first_same) 
                              /* check entire lines for diffs     */
            {


                  if (from_top >= last_same)
                  {
                        for (last_same = from_top; 
                             (last_same < window->Num_lines) && 
                             (virtual_lines[last_same] == FALSE);
                              last_same++)
                              ;
                  }
                  if (!virtual_lines[from_top])
                  {
                        diff = TRUE;
                        /*
                         |    check for lines deleted (scroll up)
                         */
                        for (tmp_ft = from_top+1, old = curr->next_screen; 
                              ((window->scroll_up) && (diff) && 
                              (tmp_ft < last_same) && 
                              (!virtual_lines[tmp_ft]));
                                    tmp_ft++)
                        {
                              if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
                              {
                                    /*
                                     |    Find the bottom of the 
                                     |    area that should be 
                                     |    scrolled.
                                     */
                                    for (bottom = tmp_ft, 
                                         old1 = old, new1 = virt,
                                         count1 = 0;
                                          (bottom < window->Num_lines) && 
                                                (Comp_line(old1, new1) <= 0);
                                                bottom++, old1 = old1->next_screen, 
                                                new1 = new1->next_screen, count1++)
                                          ;
                                    if (count1 > 3)
                                    {
                                          for (offset = (tmp_ft - from_top); (offset > 0); offset--)
                                          {
                                                old = Delete_line(from_top, min((bottom - 1), (window->Num_lines - 1)), window);
                                                diff = FALSE;
                                          }
                                          top_of_win = curscr->first_line;
                                          curr = top_of_win;
                                          for (offset = 0; offset < from_top; offset++)
                                                curr = curr->next_screen;
                                          for (offset = from_top, old=curr, new=virt; 
                                             offset < window->Num_lines; 
                                             old=old->next_screen, new=new->next_screen,
                                             offset++)
                                          {
                                                similar = Comp_line(old, new);
                                                virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
                                          }
                                    }
                              }
                              else
                                    old = old->next_screen;
                        }
                        /*
                         |    check for lines inserted (scroll down)
                         */
                        for (tmp_ft = from_top-1, old = curr->prev_screen; 
                              ((window->scroll_down) && (tmp_ft >= 0) && 
                              (diff) && 
                              (!virtual_lines[tmp_ft])); 
                                tmp_ft--)
                        {
                              if (Comp_line(old, virt) == -1)
                              {
                                    /*
                                     |    Find the bottom of the 
                                     |    area that should be 
                                     |    scrolled.
                                     */
                                    for (bottom = from_top, old1 = old, 
                                         new1 = virt, count1 = 0;
                                          (bottom < window->Num_lines) && 
                                                (Comp_line(old1, new1) <= 0);
                                                bottom++, old1 = old1->next_screen, 
                                                new1 = new1->next_screen, 
                                                count1++)
                                          ;
                                    if (count1 > 3)
                                    {
                                          for (offset = (from_top - tmp_ft); (offset > 0); offset--)
                                          {
                                                old = Insert_line(tmp_ft, min((bottom - 1), (window->Num_lines -1)), window);
                                                diff = FALSE;
                                          }
                                          top_of_win = curscr->first_line;
                                          curr = top_of_win;
                                          for (offset = 0; offset < from_top; offset++)
                                                curr = curr->next_screen;
                                          for (offset = from_top, old=curr, new=virt; 
                                             offset < window->Num_lines; 
                                             old=old->next_screen, new=new->next_screen,
                                             offset++)
                                          {
                                                similar = Comp_line(old, new);
                                                virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
                                          }
                                    }
                              }
                              else
                                    old = old->prev_screen;
                        }
                  }
                  from_top++;
                  curr = curr->next_screen;
                  virt = virt->next_screen;
            }
      }
      for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
            curr = curr->next_screen;
      top_of_win = curr;
      for (from_top = 0, curr = top_of_win, virt = window->first_line; from_top < window->Num_lines; from_top++, curr = curr->next_screen, virt = virt->next_screen)
      {
            if (Comp_line(curr, virt) > 0)
            {
                  j = 0;
                  cur_lin = curr->row;
                  cur_att = curr->attributes;
                  vrt_lin = virt->row;
                  vrt_att = virt->attributes;
                  while ((j < window->Num_cols) && (vrt_lin[j] != (char) NULL))
                  {
                        while ((cur_lin[j] == vrt_lin[j]) && (cur_att[j] == vrt_att[j]) && (j < window->Num_cols) && (vrt_lin[j] != (char) NULL))
                              j++;
                        begin_old = j;
                        begin_new = j;
                        if ((j < window->Num_cols) && (vrt_lin[j] != (char) NULL))
                        {
                              Position(window, from_top, begin_old);
                              for (j = begin_old; (vrt_lin[j] != (char) NULL) && (j < window->Num_cols); j++)
                                    Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
                        }
                  }
                  if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL))
/*                if (j < curr->last_char) */
                  {
                        Position(window, from_top, j);
                        CLEAR_TO_EOL(window, from_top, j);
                  }
                  if (STAND)
                  {
                        STAND = FALSE;
                  }
                  curr->last_char = virt->last_char;
                  virt->number = from_top;
            }
      }

      for (count1 = 0, virt = window->first_line; count1 < window->Num_lines; count1++)
      {
            window->line_array[count1] = virt;
            virt = virt->next_screen;
      }

      cursor(window, window->LY, window->LX, FALSE, FALSE);
}

void 
Position(window, row, col)    /* position the cursor for output on the screen */
WINDOW *window;
int row;
int col;
{
      int pos_row;
      int pos_column;

      pos_row = row + window->SR;
      pos_column = col + window->SC;
      Curr_x = pos_column;
      Curr_y = pos_row;
}

/*
 |    the following routines are responsible for actually handling window
 |    output
 */

void 
Char_out(newc, newatt, line, attrib, offset)    /* output character with proper attribute */
char newc;
char newatt;
char *line;
char *attrib;
int offset;
{
      int x, y;

      if ((newatt) && (!STAND))
            STAND = TRUE;
      else if ((STAND) && (!newatt))
            STAND = FALSE;
      if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
      {
            x = Curr_x * fontwidth;
            y = Curr_y * fontheight + xaefont->ascent;
            if (!STAND)
                  XDrawImageString(dp, wid, gc, x, y, &newc, 1);
            else
                  XDrawImageString(dp, wid, revgc, x, y, &newc, 1);
      Curr_x++;
      line[offset] = newc;
      attrib[offset] = newatt;
      }
}

void 
draw_cursor(visible)
int visible;            /* specify if cursor is to be visible */
{
      cursor(virtual_scr, virtual_scr->LY, virtual_scr->LX, FALSE, visible);
}

void 
cursor(window, row, col, erase, visible)  /* draw the cursor at the designated position */
WINDOW *window;
int row;
int col;
int erase;  /* erase the cursor on the screen */
int visible;
{
      int x, y, y1;
      int reverse;
      int pos_row;
      int pos_column;
      static int last_row = -1;
      static int last_col = -1;
      static int last_x = -1;
      static int last_y = -1;
      struct _line *tmp1;
      char output_char;
      static int cursor_state = TRUE;

      if ((erase) && (last_row == -1))
            return;
      tmp1 = curscr->first_line;
      if (erase)
      {
            Curr_x = last_col;
            Curr_y = last_row;
            /*
             |    make sure the previous cursor position is still within
             |    the window, since a resize could have made the window
             |    smaller
             */
            if ((Curr_y >= window->Num_lines) || (Curr_x >= window->Num_cols))
                  return;

            tmp1 = window->line_array[last_row];
      }
      else
      {
            pos_row = row + window->SR;
            pos_column = col + window->SC;
            last_col = Curr_x = pos_column;
            last_row = Curr_y = pos_row;

            /*
             |    make sure the previous cursor position is still within
             |    the window, since a resize could have made the window
             |    smaller
             */
            if ((Curr_y >= window->Num_lines) || (Curr_x >= window->Num_cols))
                  return;

            tmp1 = window->line_array[pos_row];
      }
      output_char = tmp1->row[Curr_x];
      reverse = (tmp1->attributes[last_col] & A_STANDOUT);
      if (tmp1->row[Curr_x] == (char) NULL)
      {
            output_char = ' ';
            reverse = 0;
      }
      x = Curr_x * fontwidth;
      y = Curr_y * fontheight + xaefont->ascent;
      y1 = (1 + Curr_y) * fontheight ;

      if (erase)
      {
            if (!reverse)
            {
                  XDrawImageString(dp, wid, gc, x, y, &output_char, 1);
            }
            else
            {
                  XDrawImageString(dp, wid, revgc, x, y, &output_char, 1);
            }
      }
      else
      {

            if ((last_y == last_row) && (last_x == last_col))
            {
                  if ((cursor_state) && (!visible))
                  {
                        if (reverse)
                              XDrawImageString(dp, wid, revgc, x, y, &output_char, 1);
                        else
                              XDrawImageString(dp, wid, gc, x, y, &output_char, 1);
                  }
                  else
                  {
                        if (reverse)
                              XDrawLine(dp, wid, cursor_revgc, x, y1, x, (y1 - fontheight));
                        else
                              XDrawLine(dp, wid, cursor_gc,    x, y1, x, (y1 - fontheight));
                  }

                  cursor_state = !cursor_state;
            }
            else
            {
                        XDrawLine(dp, wid, cursor_gc,    x, y1, x, (y1 - fontheight));
                        cursor_state = TRUE;
            }

            if (visible)
                  cursor_state = TRUE;

            last_y = last_row;
            last_x = last_col;
      }
}


Generated by  Doxygen 1.6.0   Back to index