Esempio n. 1
0
static void refresh_screen()
{
	erase_both ();
	show_pic ();
	blit_both ();
	commit_both ();
	put_screen ();
}
Esempio n. 2
0
int main (void)
#endif // __ANDROID__
{
  char version_string [80];

  /* We need to install a handler for SIGSEGV and friends so rowan and his
     friends can't drop a core file! */

  signal (SIGSEGV, signal_handler);
  signal (SIGBUS, signal_handler);
  signal (SIGQUIT, signal_handler);

  store_term_default ();
  set_term_raw ();

#ifndef __ANDROID__
  log_usage ();
#endif
  init_level_maps ();

  draw_frame ();
  put_screen (intro_pixmap);
  
  sprintf (version_string, "Version %s - %s %d, %d", GLIDER_VERSION, GLIDER_MONTHSTR, GLIDER_DAY, GLIDER_YEAR);
  centre_text (version_string, 12, MAX_SCR_COLS);
  
  park_cursor ();
  wait_for_key ();
  put_screen (notes_0);
  park_cursor ();
  wait_for_key ();
  put_screen (notes_1);
  park_cursor ();
  wait_for_key ();
  put_screen (notes_2);
  park_cursor ();
  wait_for_key ();

  menu ();

  ansi_Position (1, 1);
  ansi_ClearScreen ();
  set_term_default ();

  return (0); /* Exit cleanly */
}
Esempio n. 3
0
void menu (void)
{
  int option;
  
  while (1)
    {
      option = menu_get_input ();
      
      switch (option)
	{
	case 0:
	  game ();
	  break;
	case 3:
   	  draw_frame ();
	  put_screen (credits);
	  wait_for_key ();
	  break;
	case 4:
	  draw_frame ();
	  put_screen (help_1);
	  wait_for_key ();
	  put_screen (help_2);
	  wait_for_key ();
	  break;
	case 5:
	  return;
	default:
	  ansi_Position (1, MAX_SCR_ROWS);
	  ansi_SetAttr (ATTR_reverse);
	  ansi_printf ("This option is currently not supported");
	  ansi_SetAttr (ATTR_normal);
	  break;
	}
    }
}
Esempio n. 4
0
void cibyl_set_screen_size (display_zoom zoom)
{
  switch (zoom)
  {
  case NORMAL:
    x_corr = (screen_width - GFX_WIDTH) / 2;
    y_corr = (screen_height - (GFX_HEIGHT + 20)) / 2;  // +20 => input row
    gfx_cibyl.put_block = cibyl_put_block;
    gfx_cibyl.put_pixels = cibyl_put_pixels;
    break;

  case STRETCHED_VERTICALLY:
    x_corr = (screen_width - (GFX_WIDTH + GFX_WIDTH / 2)) / 2;
    y_corr = (screen_height - (GFX_HEIGHT * 2 + 20)) / 2;
    gfx_cibyl.put_block = cibyl_put_block_x1_5;
    gfx_cibyl.put_pixels = cibyl_put_pixels_x1_5;
    break;

  case DOUBLE_SIZE:
    x_corr = (screen_width - GFX_WIDTH * 2) / 2;
    y_corr = (screen_height - (GFX_HEIGHT * 2 + 20)) / 2;
    gfx_cibyl.put_block = cibyl_put_block_x2;
    gfx_cibyl.put_pixels = cibyl_put_pixels_x2;
    break;

  default:
    /* Should never happen */
    break;
  }

  if (x_corr < 0)
    x_corr = 0;
  if (y_corr < 0)
    y_corr = 0;

  NOPH_Graphics_setColor_int(graphics, 0xff666666);
  NOPH_Graphics_fillRect(graphics, 0, 0, screen_width, screen_height);
  flush_screen();
  put_screen();
  cur_zoom = zoom;
}
Esempio n. 5
0
void game_win (void)
{
  int x, y, prev_x, prev_y;
  int count;
  
  x = 53;
  y = 6;

/* Pilot appears out of aircraft */

  put_picture (x, y, MAX_SCR_PILOT_X, MAX_SCR_PILOT_Y, pilot, IMAGE_CLEAR);

  prev_y = y;
  
/* Pilot moves down ladder */
  
  for (y = 7; y <= 19; y++)
    {
      move_picture (x, prev_y, x, y, MAX_SCR_PILOT_X, MAX_SCR_PILOT_Y, pilot, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_y = y;
      terminal_sleep (0, WAIT_PILOT);
    }

/* Move the pilot a bit to the left now */

  prev_x = x;
  y--;

  for (x = 52; x >= 44; x--)
    {
      move_picture (prev_x, y, x, y, MAX_SCR_PILOT_X, MAX_SCR_PILOT_Y, pilot, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_x = x;
      terminal_sleep (0, WAIT_PILOT);
    }

  /* Pilot is in position - move in the helicopter from the right*/

  y = 13;
  prev_x = 79;

  for (x = 79; x >= 34; x--)
    {
      move_picture (prev_x, y, x, y, MAX_SCR_HELICOPTER_X, MAX_SCR_HELICOPTER_Y, helicopter, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_x = x;
      terminal_sleep (0, WAIT_HELICOPTER);
    }


  /* Pilot waves */

  for (count = 0; count <= 3; count++)
    {
      terminal_sleep (0, WAIT_PILOT);
           
      ansi_Position (44, 19);
      ansi_printf ("\\O/");
      ansi_Position (44, 20);
      ansi_printf (" | ");

      terminal_sleep (0, WAIT_PILOT);
      ansi_Position (44, 19);
      ansi_printf (" O ");
      ansi_Position (44, 20);
      ansi_printf ("/|\\");
    }

  /* Helicopter lowers rope */

  for (y = 16; y <= 19; y++)
    {
      terminal_sleep (0, WAIT_PILOT);
      ansi_Position (40, y);
      ansi_putchar ('|');
    }

/* Pilot now moves under the rope */

  y = 19;
  prev_x = 44;
  for (x = 43; x >= 39; x--)
    {
      move_picture (prev_x, y, x, y, MAX_SCR_PILOT_X, MAX_SCR_PILOT_Y, pilot, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_x = x;
      terminal_sleep (0, WAIT_PILOT);
    }

  prev_y = y;
  x = 39;

  for (y = 18; y >= 15; y--)
    {
      move_picture (x, prev_y, x, y, MAX_SCR_PILOT_X, MAX_SCR_PILOT_Y, pilot, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_y = y;
      terminal_sleep (0, WAIT_PILOT);
    }

/* Erase pilot */

  y = 15;
  for (count = y; count < y + 3; count++)
    ansi_PutString (39, count, "   ");
  y = 13;
  x = 34;
  put_picture (x, y, MAX_SCR_HELICOPTER_X, MAX_SCR_HELICOPTER_Y, helicopter, IMAGE_SOLID);

/* Move the helicopter off the screen */

  prev_x = x;

  for (x = 33; x >= -MAX_SCR_HELICOPTER_X; x--)
    {
      move_picture (prev_x, y, x, y, MAX_SCR_HELICOPTER_X, MAX_SCR_HELICOPTER_Y, helicopter, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [LAST_LEVEL].map);
      prev_x = x;
      terminal_sleep (0, WAIT_HELICOPTER);
    }

  for (count = LAST_LEVEL - 1; count >= 0; count--)
    {
      put_screen (level_data [count].map);
      sleep (WAIT_FOR_UPDATE);
      
      prev_x = 80;
      for (x = 79; x >= -MAX_SCR_HELICOPTER_X; x--)
	{
	  move_picture (prev_x, y, x, y, MAX_SCR_HELICOPTER_X, MAX_SCR_HELICOPTER_Y, helicopter, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [count].map);
	  prev_x = x;
	  terminal_sleep (0, WAIT_HELICOPTER);
	}
    }
}
Esempio n. 6
0
static int cibyl_get_key (void)
{
  static char *cur_input_word = NULL;
  int code = keycode;
  int tx, ty = 0;

  keycode = 0;
  key_pressed = 0;

  tx = 0 + x_corr;
  ty = screen_height - 40;

  if (code < 0)
    {
      if (code == -5) /* Enter */
        s9_input = DONE;
      else if (code == -8) /* Backspace */
        code = '<';
      else if (code >= -8) /* Handle through the table */
        return keycode_table_walk_special[-code];
    }
  /* Enter */
  if (code == 10)
	  s9_input = DONE;


  if (input_mode == 0 || input_mode == 1)
    {
      if (code == '1')
        {
          if (bound_to_1 != 0) /* Special cases */
            {
            if (bound_to_1 == 1)
              {
                s9_input_reset();
                s9_input_set_translation("31");
                s9_input = DONE;
                cur_input_word = NULL;
              }
            else
              return bound_to_1;
            }
        }

      /* If we have s9 input, return this first */
      if (s9_input == DONE)
        {
          int cur;

          key_pressed = 1;
          if (cur_input_word == NULL)
            {
              cur_input_word = strdup(s9_input_get_translation());
              s9_ptr = 0;
            }
          else if (s9_ptr >= strlen(cur_input_word))
            {
              free(cur_input_word);
              cur_input_word = NULL;
              s9_input = NONE;
              s9_input_reset();
              s9_ptr = 0;
              put_screen();

              return KEY_ENTER;
            }

          cur = cur_input_word[s9_ptr++];

          if (cur == '\0')
            {
              free(cur_input_word);
              cur_input_word = NULL;

              NOPH_Graphics_setColor_int(graphics, 0xffffffff);
              NOPH_Graphics_fillRect(graphics, tx, ty, 160, 20);
              /* Finished! */
              s9_input = NONE;
              s9_ptr = 0;
              s9_input_reset();

              return KEY_ENTER;
            }

          return cur;
        }

      if ( (code >= '0' && code <= '9') || code == '*' || code == '#' || code == '<' )
        {
          s9_input_handle_keypress(code);
          NOPH_Graphics_setColor_int(graphics, 0xffffffff);
          NOPH_Graphics_fillRect(graphics, tx, ty, 160, 20);
          NOPH_Graphics_setColor_int(graphics, 0);
          s9_input_draw(graphics, tx, ty);
          NOPH_GameCanvas_flushGraphics_rect(canvas, tx, ty, 160, 20);

          return 0;
        }
    }

  if (input_mode == 2)
    {
      if (code >= '0' && code <= '9')
        {
        code = fkeys_table[ ( code - 48 ) ];
        }

      if (code == -5) return KEY_ENTER;
    }

  if (code == 10)
    return KEY_ENTER;

  /* Fall-through for f-keys etc */
  return code; /* s9 input */
}
Esempio n. 7
0
int view_pictures ()
{
	int ec = err_OK;
	char x[64];
	int i, pic = 0, dir = 1;

	game.line_min_print = 1;

	for (i = 0; ec == err_OK; i = 1) {
		while (game.dir_pic[pic].offset == _EMPTY) {
			pic += dir;
			if (pic < 0)
				pic = MAX_DIRS - 1;

			if (pic > MAX_DIRS - 1) {
				pic = 0;
				if (i == 0) {		/* no pics? */
					ec = 1;
					fprintf (stderr, "No pictures found\n");
					goto end_view;
				}
			}
		}
		
		_D ("picture = %d", pic);
		if ((ec = agi_load_resource (rPICTURE, pic)) != err_OK) {
			_D (_D_CRIT "Whoops. bad pic %d", pic);
			ec = err_OK;
			pic += dir;
			goto next_pic;
		}

		print_text ("[drawing]", 0, 16, 0, strlen (x) + 1, 0, 15);

		/* decodes the raw data to useable form */
		decode_picture (pic, TRUE);

		show_pic ();
		put_screen ();
		
update_statusline:
#ifdef USE_HIRES
		sprintf (x, "Picture:%3i                  Hi-res: %3s",
			pic, opt.hires ? " on" : "off");
#else
		sprintf (x, "Picture:%3i                  Hi-res: N/A", pic);
#endif
		print_text (x, 0, 0, 0, strlen (x) + 1, 0, 15);
		sprintf (x, "H:Hi-res    P:Vis/Prio   +:Next   -:Prev");
		print_text (x, 0, 0, 23, strlen (x) + 1, 15, 0);
		sprintf (x, "R:Redraw      D:Screen dump       Q:Quit");
		print_text (x, 0, 0, 24, strlen (x) + 1, 15, 0);

		while (42) {
			decode_picture (pic, TRUE);
    			switch (picviewer_get_key()) {
    			case 'q':
				goto end_view;
#ifdef USE_HIRES
#ifdef USE_MOUSE
			case BUTTON_RIGHT:
#endif
    			case 'h':
				opt.hires = !opt.hires;
				show_pic ();
				put_screen ();
				goto update_statusline;
#endif
    			case 'p':
				debug.priority = !debug.priority;
				show_pic ();
				put_screen ();
    				break;
			case 'd':
				/*opt.showscreendraw = !opt.showscreendraw;*/
				screen_dump();
				goto update_statusline;
			case 'r':
				goto next_pic;
#ifdef USE_MOUSE
			case BUTTON_LEFT:
				if (mouse.x < GFX_WIDTH / 2) 
					goto previous_pic;
#endif
				/* fall through */
    			case '+':
				_D ("next pic");
 				if (pic < MAX_DIRS - 1)
    					pic++;
    				else
    					pic = 0;
    				dir = 1;
				goto next_pic;
    			case '-':
			previous_pic:
				_D ("previous pic");
    				if (pic > 0)
    					pic--;
    				else
    					pic = MAX_DIRS - 1;
    				i = 0;
    				dir = -1;
				goto next_pic;
    			}
    		}
next_pic:
    		agi_unload_resource (rPICTURE, pic);
    		
	}

end_view:
	return ec;
}
Esempio n. 8
0
int menu_get_input (void)
{
  int cx, cy;
  int option = 0;
  int prev_option = 1;
  int x, y;
  int KeyPressed;
  struct termios stored_terminal;

  struct get_arrow_keys num_keypad = { '8', '2', '4', '6' };
  struct get_arrow_keys alpha_keypad = { 'j', 'm', ',', '.' };
 
  get_term_settings (stored_terminal);
  set_term_raw ();

/* Paint the screen with the bitmap */
  
  put_screen (menu_picture);
  
/* Put the buttons on the screen */      

  for (cx = 0; cx <= MAX_MENU_COLS-1; cx++)
    for (cy = 0; cy <= MAX_MENU_ROWS-1; cy++)
      {
	x = MENU_COL+MENU_COL_GAP*cx;
	y = MENU_ROW+MENU_ROW_GAP*cy;
	ansi_PutString (x+1, y+1, menu_options [cy*MAX_MENU_COLS+cx]);
	draw_box_XY (x, y, x+MENU_ITEM_WIDTH, y+MENU_ITEM_HEIGHT, CHAR_hyphen, CHAR_pipe, CHAR_plus);
      }

/* Keep looping until 'select' or 'Q' has been pressed and then return the option selected to the parent function */
  
  while (1)
    {
      if (prev_option != option)
	{
	  cx = prev_option % 2;
	  cy = prev_option / 2;
	  ansi_DefaultAttr ();
	  x = MENU_COL+MENU_COL_GAP*cx;
	  y = MENU_ROW+MENU_ROW_GAP*cy;
	  ansi_PutString (x+1, y+1, menu_options [cy*MAX_MENU_COLS+cx]);
	  draw_box_XY (x, y, x+MENU_ITEM_WIDTH, y+MENU_ITEM_HEIGHT, CHAR_hyphen, CHAR_pipe, CHAR_plus);
	  
	  cx = option % 2;
	  cy = option / 2;
	  ansi_SetAttr (ATTR_reverse);
	  x = MENU_COL+MENU_COL_GAP*cx;
	  y = MENU_ROW+MENU_ROW_GAP*cy;
	  ansi_PutString (x+1, y+1, menu_options [cy*MAX_MENU_COLS+cx]);
	  draw_box_XY (x, y, x+MENU_ITEM_WIDTH, y+MENU_ITEM_HEIGHT, CHAR_hyphen, CHAR_pipe, CHAR_plus);
          ansi_SetAttr (ATTR_normal);
	}
      prev_option = option;
      
      wait_for_keypress ();
      
      switch (get_arrow (TRUE, &alpha_keypad, &num_keypad))
	{
	case DIR_up:
	  if ((option != 0) && (option != 1))
	    option-=2;
	  break;
	case DIR_down:
	  if ((option != 4) && (option != 5))
	    option+=2;
	  break;
	case DIR_left:
	  if (option % 2 == 1)
	    option--;
	  break;
	case DIR_right:
	  if (option % 2 == 0)
	    option++;
	  break;
	case DIR_unknown:
	  KeyPressed = terminal_getchar ();

	  if ((KeyPressed == MENU_SELECT_1) || (KeyPressed == MENU_SELECT_2) || (KeyPressed == MENU_SELECT_3))
	    {
	      set_term_settings (stored_terminal);
	      return (option);
	    }
	  if (toupper (KeyPressed) == 'Q')
	    {
	      set_term_settings (stored_terminal);
	      return (5);
	    }
	  break;
	}
    }
}
Esempio n. 9
0
int play_level (int level, long int *score, int lives, int total_score)
{
  int aircraft_x = 2, prev_aircraft_x = aircraft_x;
  float aircraft_y_float = 8.0;
  int aircraft_y = aircraft_y_float, prev_aircraft_y = aircraft_y;
  int direction = DIR_FORWARD;
  int aircraft_stats;
  int x_offset = 0;
  float y_offset = 0.0;
  char KeyPressed = 0;
  struct timeval start_time, end_time;
  struct timezone start_timezone, end_timezone;
  long int bonus = 0;
  struct termios stored_terminal;

  struct get_arrow_keys num_keypad = { '8', '2', '4', '6' };
  struct get_arrow_keys alpha_keypad = { 0, 0, ',', '.' };

  get_term_settings (stored_terminal);
  set_term (0, 0);
  draw_frame ();
  put_screen (level_data [level].map);
  ansi_Position (2, MAX_SCR_ROWS);
  ansi_SetAttr (ATTR_reverse);
  ansi_printf (" Game Info  -  Score: [%6d]  Lives Remaining: [%2d]  Current Level: [%2d]", total_score, lives, level);
  ansi_SetAttr (ATTR_normal);
  park_cursor ();
  ansi_fflush ();
  sleep (WAIT_FOR_UPDATE); /* Really slow terminals need a few seconds to catch up */
  start_time ();
  
  put_plane (aircraft_x, aircraft_y, aircraft);

  do
    {
      aircraft_x += x_offset;
      aircraft_y_float += y_offset;
      aircraft_y = aircraft_y_float;
      
      move_picture (prev_aircraft_x, prev_aircraft_y, aircraft_x, aircraft_y, MAX_SCR_PLANE_X, MAX_SCR_PLANE_Y, aircraft, MAX_SCR_COLS, MAX_SCR_ROWS, level_data [level].map);

      prev_aircraft_x = aircraft_x;
      prev_aircraft_y = aircraft_y;
      
      if (delay_for_key (WAIT_TIME_Sec, WAIT_TIME_uSec))
	switch (get_arrow (TRUE, &num_keypad, &alpha_keypad))
	  {
	  case DIR_left: direction = DIR_BACKWARD; break;
	  case DIR_right: direction = DIR_FORWARD; break;
	  default: KeyPressed = terminal_getchar (); break;
	  }
      
      aircraft_stats = check_aircraft (aircraft_x, aircraft_y, level, aircraft);
      
/* Check to see if any 'events' have happened */
      
      if (aircraft_stats != OBJ_NOTHING)
	{
	  if ((aircraft_stats & OBJ_COLLISION) == OBJ_COLLISION)
	    {
	      set_term_settings (stored_terminal);
	      return (MSG_COLLISION);
	    }

	  if ((aircraft_stats & OBJ_FIRE) == OBJ_FIRE)
	    {
	      set_term_settings (stored_terminal);
	      return (MSG_FIRE);
	    }
	  
	  if ((aircraft_stats & OBJ_WATER) == OBJ_WATER)
	    {
	      set_term_settings (stored_terminal);
	      return (MSG_WATER);
	    }
	  
	  if ((aircraft_stats & OBJ_FLOOR) == OBJ_FLOOR)
	    {
	      set_term_settings (stored_terminal);	  
	      return (MSG_FLOOR);
	    }
	  
	  if ((aircraft_stats & OBJ_RIGHTWALL) == OBJ_RIGHTWALL)
	    {
	      end_time ();
	      *score = calculate_score (diff_time (), bonus, level);
	      set_term_settings (stored_terminal);
	      return (MSG_WINLEVEL);
	    }
	  
	  if ((aircraft_stats & OBJ_WINGAME) == OBJ_WINGAME)
	    {
	      end_time ();
	      *score = calculate_score (diff_time (), bonus, level);
	      set_term_settings (stored_terminal);
	      return (MSG_WINGAME);
	    }
	}
      
      if ((aircraft_stats & OBJ_BONUS) == OBJ_BONUS)
	bonus++;
      
      /* Ok, the Glider has not crashed and the level has not ended, we must now move it appropriately */
      
      x_offset = direction;
      y_offset = STEP_DOWN;
      
      if ((aircraft_stats & OBJ_VENT) == OBJ_VENT)
	y_offset = STEP_VENT;
      if ((aircraft_stats & OBJ_ROOF) == OBJ_ROOF)
	if ((aircraft_stats & OBJ_VENT) == OBJ_VENT)
	  y_offset = 0.0;
      if ((aircraft_stats & OBJ_LEFTWALL) == OBJ_LEFTWALL)
	if (direction == DIR_BACKWARD)
	  x_offset = 0;
    } while (toupper (KeyPressed) != 'Q');
  set_term_settings (stored_terminal); 
  return (MSG_QUIT);
}
Esempio n. 10
0
/* <crt_text>:
 * Display the given text 'bfr', at the specified line (range 0..lpp-1),
 * with the 'mark' code for graphics-rendition (1=highlight, 0=normal).
 *
 * Use the 'crtvec[]' array to store the previous state of the given line,
 * to trade string copy/compare against screen I/O.
 *
 * 'crtvec[]' uses bit-7 as the flag for highlighting, allowing the display
 * driver to highlight part of any line.
 *
 * Do the blanking based on 'col_x' after all other changes have been made
 * to the line, to avoid an extra cursor movement.
 */
void	crt_text(
	char*	bfr,		/* "new" text to display		*/
	int	line,		/* index (0 to lpp-1) of line on screen	*/
	int	mode)		/* sgr-code if "highlighting"		*/
{
	static $DESCRIPTOR(DSC_line,"");

	register int	col_l;
	register int	col_r;
	register int	col_x;
	register char	*c1_	= bfr;
	register char	*c2_;
	register int	column = 0;
	register int	eql;
	register int	chg;

	char	bfr1	[CRT_COLS];
	char	bfr2	[CRT_COLS];
	static
	BYTE	to_chg[CRT_COLS],	/* distance til changed-column	*/
		to_eql[CRT_COLS];	/* distance til difference	*/

	line = max(0, min(lpp1, line));
	sgrvec[line] = mode;

	/*
	 * Copy the input string to a temporary buffer, suppressing nongraphic
	 * characters, and then trimming trailing blanks.  Explicit test for
	 * space is used to avoid problems with highlighting.
	 */
	for (c1_ = bfr1, c2_ = bfr; *c2_; c2_++)
	{
		if (isprint(toascii(*c2_)))	*c1_++ = *c2_;
		else if (toascii(*c2_) == '\t')	*c1_++ = *c2_ + (' ' - '\t');
		if ((c1_-bfr1) >= (width-1))	break;
	}
	*c1_ = EOS;
	for (c1_ = bfr1 + strlen(bfr1) - 1;
		(c1_ > bfr1) && (*c1_ == ' '); *c1_-- = EOS);

	/*
	 * Set highlighting to default, if caller uses defaults:
	 */
	if (mode == 0)
		mode	= (line >= lpp1) ? sgrBOLD : sgrREVERSE;

	/*
	 * Do string comparison to determine the limits of difference between
	 * the latest line and the prior contents.  If the older text is longer
	 * than the newer, also set index 'col_x' to show the erase-point.
	 *
	 * If the new text is longer than the old, skip leading spaces in the
	 * special case that no difference has been encountered (e.g., writing
	 * a word in the right margin on a blank line).
	 */

	col_l = col_r = col_x = 0;
	for (c1_ = bfr1, c2_ = crtvec[line]; *c1_ && *c2_; c1_++, c2_++)
	{
		if (*c1_ != *c2_)
		{
			column = c1_ - bfr1 + 1;
			if (col_l)	col_r = column;
			else		col_l = column;
		}
	}

	if (*c2_)		/* Was the old line longer than new ?	*/
		col_x = c1_ - bfr1 + 1;
	else if (*c1_)		/* If new is longer, extend right-col	*/
	{
		if (col_l == 0)	/* If no difference yet, skip leading spaces */
		{
			while (*c1_ == ' ')	c1_++;
			col_l = c1_ - bfr1 + 1;
		}
		col_r = strlen(bfr1);
	}
	if (col_l && (col_r == 0))
		col_r = col_l;

	/*
	 * If we have differences, compute a distance-vector, so that if
	 * there are long gaps of similarity, then we can set up a jump.
	 */
	if (col_l | col_r)
	{
		int	oldlen = strlen(c2_ = crtvec[line]);

		/*
		 * Pad the old string out to the length of the new part,
		 * so that the difference loop below will work.  (The
		 * column-index ranges from 1 to the length of the string.)
		 */
		c2_--;
		while (oldlen < col_r)	c2_[++oldlen] = ' ';

		/*
		 * First pass: find the length of gaps in the difference,
		 * (to_chg) and the length of the difference-sections (to_eql).
		 *
		 * Example:
		 *	'xxx...yyy' - new
		 *	'xxx!!!yyy' - old
		 *	 321000321  - chg
		 *	 000321000  - eql
		 */
		for (column = col_r, chg = eql = 0; column >= col_l; column--)
		{
			if (bfr1[column-1] == c2_[column])
			{
				to_chg[column] = ++chg;
				to_eql[column] = eql = 0;
			}
			else
			{
				to_chg[column] = chg = 0;
				to_eql[column] = ++eql;
			}
		}

		/*
		 * Second pass: consolidate difference-sections which are
		 * too close together to jump economically.
		 * (patch: should make JUMP bigger still if there is a change
		 * in graphic-rendition on the seams.)
		 */
#define	JUMP	10
		for (column = col_l; column <= col_r;)
		{
loop:			if ((eql = column + to_eql[column]) > col_r)
				break;
			if ((chg = to_chg[eql]) < JUMP)
			{
				chg += eql;
				to_eql[column] += to_chg[eql] + to_eql[chg];
				goto loop;
			}
			else
				column = eql + to_chg[eql];
		}

		/*
		 * Finally, update the actual screen, where it has changed.
		 */
		strcpy (crtvec[line], bfr1);	/* Update internal buffer */
		strcpy (bfr2, bfr1);		/* strip parity bit */
		{ register char *s = bfr2; while (*s) *s++ &= 0x7f; }
		while (col_l <= col_r)	/* Update partial highlighting */
		{
			int	inx	= col_l - 1,
				right	= to_eql[col_l] + inx,
				mark;

			while (col_l <= right)
			{
#define	MARK	ishigh(bfr1[inx])
				inx	= col_l - 1;
				DSC_line.dsc$a_pointer = &bfr2[inx];
				for (mark = MARK;
					(inx < right) && (mark == MARK);
						inx++);
				DSC_line.dsc$w_length  = inx - col_l + 1;
				crt_move (line+1, col_l);
				lastx	+= DSC_line.dsc$w_length;
				mark	= (mark ? mode : 0);
				lib$put_screen (&DSC_line, 0, 0, &mark);
				col_l	= inx + 1;
			}
			col_l	= right + 1;
			if (col_l < col_r)	col_l += to_chg[col_l];
		}
	}
	else if (col_x)		/* (entire line was blanked) */
		strcpy (crtvec[line], bfr1);

	if (col_x)	crt__EL (line+1, col_x);
}