Article 2760 of comp.sources.unix:
Submitted-By: mik@cs.su.oz.au (Michael Koelling)
Posting-Number: Volume 29, Issue 100
Archive-Name: red-96/part05

#!/bin/sh
# This is `part05' (part 5 of a multipart archive).
# Do not concatenate these parts, unpack them in order with `/bin/sh'.
# File `Red/Red/editor_display.i' is being continued...
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  echo 'WARNING: not restoring timestamps.  Consider getting and'
  echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if test ! -r _sharseq.tmp; then
  echo 'Please unpack part 1 first!'
  exit 1
fi
shar_sequence=`cat _sharseq.tmp`
if test "$shar_sequence" != 5; then
  echo "Please unpack part $shar_sequence next!"
  exit 1
fi
if test ! -f _sharnew.tmp; then
  echo 'x - still skipping Red/Red/editor_display.i'
else
  echo 'x - continuing file Red/Red/editor_display.i'
  sed 's/^X//' << 'SHAR_EOF' >> 'Red/Red/editor_display.i' &&
X//			screen pos: current position
X//	The selection must be off. The cursor must be at the right position.
X//	Positions cursor to point position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::screen_update_from (BUFFERPOS pos)
X{
X  assert (!buffer->selection_on);
X
X  screen->cursor_on (False);			// hide the cursor
X  display_from (pos);
X  show_point ();
X  utility->set_scrollbar (scrollbar, top.line_no, 
X				bottom.line_no - top.line_no + 1,
X				buffer->lines + 1);
X  screen->cursor_on (True);			// show the cursor
X}
X
X// -------------------------------------------------------------------------
X//  display_from: Display the buffer from the position indicated in pos
X//	on the screen starting at the current screen cursor position.
X//	So this redisplays a part of the screen from an arbitrary position
X//	to the bottom of the screen.
X//	'line' maybe endmark (the line marking the end of the text). In that
X//	case nothing is displayed.
X//	If the text ends before the end of the screen, the rest of the 
X//	screen is cleared.
X//	This routine should be called with the screen cursor off.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::display_from (BUFFERPOS pos)
X{
X  int parts, lines_written, current_index;
X  int length1, length2, length3, lines2;
X  Boolean first = True;
X
X  char* str = "";
X  int length = 0;
X  int screenline = screen->line;
X
X  if ((pos.line->select == InSelection) || (pos.line->select == SelectionEnd))
X    screen->set_selection (True);
X
X  while (!buffer->is_end (pos.line)) {		// while not AFTER text
X    if (first) {
X      current_index = pos.column;
X      first = False;
X    }
X    else {
X      screen->next_line ();
X      current_index = 0;
X      screenline = screen->line;
X    }
X    buffer->get_text_in_line (pos.line, current_index, str, length);
X
X    #ifndef RED_ONLY
X      screen->set_tag ((ScreenTag)buffer->get_tag (pos.line));
X    #endif
X    screen->clear_wrap_mark ();
X
X    switch (pos.line->select) {		// look at selection status of line
X      case NoSelection:			// no selection here
X      case InSelection:			// line is within selection
X	parts = 1;
X        length1 = length;
X        break;
X      case SelectionStart:		// selection starts in this line
X	parts = 2;
X        length1 = buffer->pt2.column - pos.column;
X	if (length1 < 0) length1 = 0;
X	length2 = length-length1;
X        break;
X      case SelectionEnd:		// selection ends in this line
X	parts = 2;
X        length1 = buffer->pt.column - pos.column;
X	if (length1 < 0) length1 = 0;
X	length2 = length-length1;
X        break;
X      case ContainsSelection:		// selection lies entirely in this line
X	parts = 3;
X        length1 = buffer->pt2.column - pos.column;
X	if (length1 < 0) length1 = 0;
X	if (pos.column>buffer->pt2.column)
X	  length2 = buffer->pt.column - pos.column;
X	else
X	  length2 = buffer->pt.column - buffer->pt2.column;
X	if (length2 < 0) length2 = 0;
X	length3 = length-length2-length1;
X        break;
X    }
X
X    screen->write_string (str, length1, lines_written, current_index);
X    if (parts>1) {
X        screen->toggle_selection ();
X        screen->write_string (&str[length1], length2, lines2, current_index);
X	lines_written = lines_written + lines2 - 1;
X
X	if (parts>2) {
X	    screen->toggle_selection ();
X            screen->write_string (&str[length1+length2], length3, 
X				  lines2, current_index);
X	    lines_written = lines_written + lines2 - 1;
X	}
X    }
X    buffer->next_line (pos);
X    
X    if (screen->cursor_at_bottom ()) break;
X  }
X  screen->set_selection (False);
X
X  // Now line points behind last displayed line and screen cursor is in last
X  // used screen line behind last character. Update bottom and blanklines.
X
X  buffer->prev_line (pos);
X  bottom.line = pos.line;
X  bottom.line_no = pos.line_no;
X  bottom.column = current_index;
X  blanklines = screen->lines - screen->line - 1;
X
X  if (blanklines>0)
X    screen->clear_to_eos ();
X}
X
X// -------------------------------------------------------------------------
X//  show_point: Display point on the screen (just placing the cursor, if the 
X//	location is currently visible, or redisplaying in case the location
X//	is out of screen).
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::show_point ()
X{
X  if (buffer->pt.is_before (top))
X  {
X    redisplay ();		// point above screen - redisplay
X    return;
X  }
X
X  if (buffer->pt.is_behind (bottom))
X  {
X    redisplay ();		// point below screen - redisplay
X    return;
X  }
X
X  // Now we know: point is on screen. Find screen position and place cursor.
X
X  place_cursor_on_screen ();
X}
X
X// -------------------------------------------------------------------------
X//  place_cursor_on_screen: Place the cursor on the screen according to 
X//	point.  This function assumes that point and top line are up to date
X//	and that point is on screen.
X//	PRE: cursor position is on screen
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::place_cursor_on_screen ()
X{
X  int screenline, col;
X
X  buffer_pos_to_screen_pos (buffer->pt.line, buffer->pt.column, 
X			    screenline, col);
X  screen->cursor_to (col, screenline);
X}
X
X// -------------------------------------------------------------------------
X//  buffer_pos_to_screen_pos: Given a position in the buffer (bufline, 
X//	bufcol) the function returns the position on the screen where that
X//	buffer position is displayed (scrline, scrcol).
X//	It is assumed that the position is visible on the screen and that
X//	top is set correctly.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::buffer_pos_to_screen_pos (LINE* bufline, int bufcol,
X			       int& scrline, int& scrcol)
X{
X  BUFFERPOS pos = top;
X  int ln, column;
X  char* str;
X  int length;
X
X  // find offset of top line of screen top (0 if normal, negativ, if top in
X  //  long line)
X
X  if (pos.column==0)
X    scrline = 0;
X  else {
X    buffer->get_text_in_line (pos.line, 0, str, length);
X    scrline =  -(screen->nr_of_lines (str, pos.column, 0));
X  }
X
X  while (pos.line != bufline) {
X    buffer->get_text_in_line (pos.line, 0, str, length);
X    scrline += screen->nr_of_lines (str, length, 0);
X    buffer->next_line (pos);
X  }
X
X  // now we found bufline
X
X  buffer->get_text_in_line (pos.line, 0, str, length);
X  if (bufcol < length)
X    column = bufcol;
X  else
X    column = length;
X  screen->index_to_square (str, column, ln, scrcol, True);
X  scrline += ln;
X  if (scrline<0) {			// check: (-1,maxcol) can happen for
X    assert (scrline == -1);		//  long lines; make it (0,0)
X    assert (scrcol == screen->columns);
X    scrline = scrcol = 0;
X  }
X}
X
X// -------------------------------------------------------------------------
X//  set_point_to_square: Find out what buffer position is at a square on the
X//	screen and set point to it.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::set_point_to_square (int x, int y)
X{
X  BUFFERPOS pos = top;
X  int screenline = 0;
X  int col, length;
X  char* str;
X
X  while (true) {
X    buffer->get_text_in_line (pos.line, pos.column, str, length);
X    col = screen->square_to_index (str, length, screenline, x, y);
X    if (col != -1)
X      break;			// found buffer position on square
X    screenline++;
X    if (buffer->is_last (pos.line)) {
X      col = pos.line->length;
X      break;
X    }
X    buffer->next_line (pos);
X  }
X  pos.column += col;
X  buffer->point_to (pos);
X}
SHAR_EOF
  echo 'File Red/Red/editor_display.i is complete' &&
  $shar_touch -am 0512222696 'Red/Red/editor_display.i' &&
  chmod 0640 'Red/Red/editor_display.i' ||
  echo 'restore of Red/Red/editor_display.i failed'
  shar_count="`wc -c < 'Red/Red/editor_display.i'`"
  test 11569 -eq "$shar_count" ||
    echo "Red/Red/editor_display.i: original size 11569, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/editor_edit.i ==============
if test -f 'Red/Red/editor_edit.i' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/editor_edit.i (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/editor_edit.i (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/editor_edit.i' &&
X// =========================================================================
X//
X// FILE: editor_edit.i	- part of editor.cc			  -mik- 1995
X//
X// This part contains implementations of the functions that actually change
X// the text in the editor (insertion and deletion functions).  It is part of
X// the implementation of class EDITOR.
X//
X// =========================================================================
X
X// -------------------------------------------------------------------------
X//  insert_char: Insert a character into the buffer at the current cursor 
X//	position and do all the display stuff.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::insert_char (char ch)
X{
X  int orig_lines, lines_written, length, last_index;
X  BUFFERPOS display_pos;
X  char* str;
X  ACTION* action;
X  int startline, startcol;
X
X  if (check_selection (True, True))	// if selection, cut it
X    ;
X
X  startline = buffer->pt.line_no;
X  startcol = buffer->pt.column;
X
X  // first check how many screen lines this line uses currently
X
X  buffer->get_text_to_eol (str, length);
X  orig_lines = screen->nr_of_lines (str, length, screen->column);
X
X  buffer->insert_char (ch);
X  buffer->get_text_to_eol (str, length);	// have to get it again!
X						// address of line might have
X						// changed
X  // now write the new line onto the screen
X
X  screen->cursor_on (False);			// hide the cursor
X  screen->write_string (--str, length+1, lines_written, last_index);
X
X  // if used number of lines has changed, update the rest of the screen
X
X  if (lines_written > orig_lines) {		// if we used a new screen line
X    if (!screen->cursor_at_bottom()) {		//  then update rest of screen
X      screen->next_line ();
X      display_pos = buffer->pt;			// take point...
X      buffer->next_line (display_pos);		// move to beg. of next line..
X      display_from (display_pos);		// and display from there
X    }
X    place_cursor_on_screen ();
X  }
X  else if (length>0)			// if insertion was in middle of line
X    place_cursor_on_screen ();		//  put cursor where it belongs
X
X  screen->cursor_on (True);
X
X  // store information about this on undo-stack
X
X  action = undo_stack->new_action ();		// get action record
X  action->set_insertion (startline, startcol, 
X			 buffer->pt.line_no, buffer->pt.column, false);
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  insert_new_line: Insert at newline at point position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::insert_new_line (Boolean indent)
X{
X  ACTION* action;
X  int startline, startcol;
X  BUFFERPOS display_pos;
X
X  if (check_selection (True, True))	// if selection, cut it
X    ;
X
X  startline = buffer->pt.line_no;
X  startcol = buffer->pt.column;
X
X  buffer->insert_newline ();
X  display_pos = buffer->pt;
X  if (indent)
X    (void) buffer->indent ();	// discard result -- doesn't matter
X
X  screen->cursor_on (False);		// clear rest of current line
X  screen->clear_wrap_mark ();
X  screen->clear_to_eol ();
X
X  if (!screen->cursor_at_bottom ()) {	// if cursor remains on screen...
X    screen->next_line ();		// ...display rest of screen
X    display_from (display_pos);
X    place_cursor_on_screen ();
X    screen->cursor_on (True);
X    utility->set_scrollbar (scrollbar, top.line_no, 
X			    bottom.line_no - top.line_no + 1,
X			    buffer->lines + 1);
X  }
X  else {
X    utility->set_scrollbar (scrollbar, top.line_no, 
X				bottom.line_no - top.line_no + 1,
X				buffer->lines + 1);
X    redisplay ();
X  }
X
X  // store information about this on undo-stack
X
X  action = undo_stack->new_action ();		// get action record
X  action->set_insertion (startline, startcol, 
X			 buffer->pt.line_no, buffer->pt.column, false);
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  insert: Insert the string in str into the buffer (no display). The string
X//	may contain line breaks marked by the C NewLine character ('\n'). 
X//	Does not redisplay.  NOTE: The selection HAS TO BE OFF before calling
X//	this -- it does not delete the selection.
X//	This insert function should be used only for interactive insertion
X//	(user editing).  There is another insert function (insert_text) in
X//	editor.cc for text insertion done by the program itself.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::insert (char* str)
X{
X  ACTION* action;
X  int startline, startcol;
X  char* s;	// current check position
X
X  startline = buffer->pt.line_no;
X  startcol = buffer->pt.column;
X
X  // now insert the string...
X
X  s = str;
X  while (*s) {				// while not end of str
X      while ((*s) && (*s!='\n'))
X	s++;
X      buffer->insert_string (str, s-str);
X      if (*s) {
X	buffer->insert_newline ();
X	str = s+1;			// set to next line
X	s = str;
X      }
X  }
X
X  // store information about this on undo-stack
X
X  action = undo_stack->new_action ();		// get action record
X  action->set_insertion (startline, startcol, 
X			 buffer->pt.line_no, buffer->pt.column, false);
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  delete: Delete the current selection from the buffer.  No display.  Undo
X//	information is recorded.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::delete_between_points ()
X{
X  char* text;
X  ACTION* action;
X
X  text = buffer->selection_to_string ();	// get text to be deleted
X  buffer->cut ();				// delete it
X
X  action = undo_stack->new_action ();		// get action record to store
X  action->set_deletion (buffer->pt.line_no, buffer->pt.column, text, 'x', 
X			false);
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  self_insert_char: Insert the character typed to invoke this command into
X//	the text. Printable characters and TAB characters are the only ones
X//	handled properly.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::self_insert_char ()
X{
X  insert_char (last_char);
X}
X
X// -------------------------------------------------------------------------
X//  new_line: Insert at newline at point position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::new_line ()
X{
X  insert_new_line (False);
X}
X
X// -------------------------------------------------------------------------
X//  open_line: Open a new line, but leave cursor on the current line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::open_line ()
X{
X  new_line ();
X  assert (buffer->point_backward());	// should always succeed...
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  tab_to_tab_stop: Insert a Tab into the text
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::tab_to_tab_stop ()
X{
X  insert_char ('\t');
X}
X
X// -------------------------------------------------------------------------
X//  half_tab: Insert half a tab (tab stop to multiples of 4) in the current
X//	line of in every line in the current selection, depending on whether
X//	the selection is on or not.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::half_tab ()
X{
X  ACTION* action;
X  int startline, startcol;
X  int new_chars;
X  int i;
X  char* spaces;
X
X  if (check_selection (True, True))	// if selection, cut it
X    ;
X
X  startline = buffer->pt.line_no;
X  startcol = buffer->pt.column;
X
X  new_chars = buffer->insert_half_tab ();
X
X  // store information about this on undo-stack
X
X  if (new_chars > 0) {				// spaces inserted
X    action = undo_stack->new_action ();
X    action->set_insertion (startline, startcol, 
X			   buffer->pt.line_no, buffer->pt.column, false);
X  }
X  else {
X    if (new_chars < 0) {			// spaces were deleted
X      spaces = new char [-new_chars+1];
X      for (i=0; i<-new_chars; i++)
X        spaces[i] = ' ';
X      spaces[-new_chars] = '\0';
X      action = undo_stack->new_action ();
X      action->set_deletion (startline, startcol+new_chars, spaces, 'x', false);
X      action = undo_stack->new_action ();
X      action->set_insertion (buffer->pt.line_no, buffer->pt.column-1,
X			     buffer->pt.line_no, buffer->pt.column, true);
X    }
X    else {					// just a TAB inserted
X      action = undo_stack->new_action ();
X      action->set_insertion (buffer->pt.line_no, buffer->pt.column-1,
X			     buffer->pt.line_no, buffer->pt.column, false);
X    }
X  }
X  screen_update_from_bol ();	// update from beginning of current line
X}
X
X// -------------------------------------------------------------------------
X//  indent: Indent cursor to start of next word in previous nonblank line.
X//	If there is no previous nonblank line, or it is too short, insert a
X//	TAB instead.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::indent ()
X{
X  ACTION* action;
X  BUFFERPOS pt_pos;		// temp store current position
X  char* old_text;
X
X  if (check_selection (False, False))	// if selection on, switch it off
X    ;
X
X  buffer->get_point (pt_pos);		// save original text for undo
X  buffer->point_to_bol ();
X  buffer->set_pt2 ();  
X  buffer->point_to (pt_pos);
X  old_text = buffer->selection_to_string ();
X
X  if (buffer->indent ()) {		// is relative indent pos was found..
X    screen_update_from_bol ();		// update from beginning of current line
X//    screen->cursor_to (0, screen->line);    // error on long line!!!
X//    screen_update_from (buffer->pt2);
X
X    // Store information on undo-stack. Indent gets stored as deletion of text
X    // in line before point followed by insertion of new text before point.
X
X    action = undo_stack->new_action ();		// get action record to store
X    action->set_deletion (buffer->pt.line_no, 0, old_text, 'x', false);
X    action = undo_stack->new_action ();
X    action->set_insertion (buffer->pt.line_no, 0, 
X			   buffer->pt.line_no, buffer->pt.column, true);
X    set_saved (False);
X  }
X  else					// otherwise insert TAB
X    insert_char ('\t');
X}
X
X// -------------------------------------------------------------------------
X//  shift_line_right: Shift the current line one character to the right.
X//	Buffer only, no screen update.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::shift_line_right ()
X{
X  buffer->inc_indent ();
X}
X
X// -------------------------------------------------------------------------
X//  shift_right: Shift the current line or the current selection (depending
X//	on whether the selection is on) one character to the right. Update
X//	the screen.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::shift_right ()
X{
X  if (buffer->selection_on)
X    block_operation (&EDITOR::shift_line_right);
X  else {
X    shift_line_right ();
X    screen_update_from_bol ();	// update from beginning of current line
X  }
X  undo_stack->clear ();
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  shift_line_left: Shift the current line one character to the left.
X//	Buffer only, no screen update.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::shift_line_left ()
X{
X  buffer->dec_indent ();
X}
X
X// -------------------------------------------------------------------------
X//  shift_left: Shift the current line or the current selection (depending
X//	on whether the selection is on) one character to the left. Update
X//	the screen.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::shift_left ()
X{
X  if (buffer->selection_on)
X    block_operation (&EDITOR::shift_line_left);
X  else {
X    shift_line_left ();
X    screen_update_from_bol ();	// update from beginning of current line
X  }
X  undo_stack->clear ();
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  new_line_and_indent: Insert a new line and indent as line above.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::new_line_and_indent ()
X{
X  insert_new_line (True);
X}
X
X// -------------------------------------------------------------------------
X//  delete_char: Delete the character at point. If point is at end of line,
X//	the line is joined with the next one.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::delete_char ()
X{
X  int orig_lines, lines_written, last_index, length, screen_x, screen_y;
X  unsigned char del_result;
X  BUFFERPOS display_pos;
X  char* str;
X  ACTION* action;
X
X  if (check_selection (True, True))	// if selection, cut it
X    return;
X
X  buffer->get_text_to_eol (str, length);
X  orig_lines = screen->nr_of_lines (str, length, screen->column);
X
X  del_result = buffer->delete_char();
X
X  if (del_result == '\0') {		// end of buffer
X    info->warning ("End of text", "");
X    return;
X  }
X
X  screen->cursor_on (False);				// hide the cursor
X  screen_x = screen->column;
X  screen_y = screen->line;
X  buffer->get_text_to_eol (str, length);
X
X  if ((length == 0) && (screen_x == 0) && (buffer->pt.column != 0)) {
X    // wrapping line has shrunk to fit on one line now
X    screen_y--;
X    screen_x = screen->columns;
X    display_pos = buffer->pt;			// take point...
X    buffer->next_line (display_pos);		// move to beg. of next line..
X    display_from (display_pos);			// and display from there
X  }
X  else {
X    screen->write_string (str, length, lines_written, last_index);
X
X    if ((del_result == NewLine) || (lines_written < orig_lines)) {
X      screen->clear_wrap_mark ();
X      if (!screen->cursor_at_bottom()) {
X        screen->next_line ();
X	display_pos = buffer->pt;		// take point...
X	buffer->next_line (display_pos);	// move to beg. of next line..
X	display_from (display_pos);		// and display from there
X      }
X      utility->set_scrollbar (scrollbar, top.line_no,
X				bottom.line_no - top.line_no + 1,
X				buffer->lines + 1);
X    }
X  }
X
X  screen->cursor_to (screen_x, screen_y);
X  screen->cursor_on (True);
X
X  // record on undo stack
X
X  action = undo_stack->new_action ();		// get action record to store
X  action->set_deletion (buffer->pt.line_no, buffer->pt.column, NULL, 
X		        del_result, false);
X  set_saved (False);
X}
X
X// -------------------------------------------------------------------------
X//  backward_delete_char: Delete the character left of point. Includes wrap
X//	around if point is at beginning of line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::backward_delete_char ()
X{
X  if (check_selection (True, True))	// if selection, cut it
X    return;
X
X  if (buffer->point_backward()) {
X    show_point ();
X    delete_char();
X  }
X  else
X    info->warning ("Beginning of text", "");
X}
X
X// -------------------------------------------------------------------------
X//  backward_delete_untab: Like backward_delete_char, but if character to be
X//	deleted is a Tab, turn it into spaces first.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::backward_delete_untab ()
X{
X  buffer->untabify ();
X  backward_delete_char ();
X}
X
X// -------------------------------------------------------------------------
X//  cut_word:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut_word ()
X{
X  if (buffer->selection_on) {
X    info->message ("cut-word: ", "Not possible while selection is on", 
X		   "(Place cursor before calling this function)");
X    return;
X  }
X
X  buffer->point_backward_word ();
X  buffer->set_pt2 ();
X  buffer->point_forward_word ();
X  make_selection ();				// copy to paste buffer
X  delete_selection ();				// delete from text
X}
X
X// -------------------------------------------------------------------------
X//  cut_to_end_of_word:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut_to_end_of_word ()
X{
X  if (buffer->selection_on) {
X    info->message ("cut-to-end-of-word: ", "Not possible while selection is on", 
X		   "(Place cursor before calling this function)");
X    return;
X  }
X
X  buffer->set_pt2 ();
X  buffer->point_forward_word ();
X  make_selection ();				// copy to paste buffer
X  delete_selection ();				// delete from text
X}
X
X// -------------------------------------------------------------------------
X//  cut_line: Cut the complete current line to the paste buffer.
X//	If there is a selection, cut the selection instead.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut_line ()
X{
X  if (buffer->selection_on)
X    cut ();
X  else {
X    buffer->point_to_bol ();
X    buffer->set_pt2 ();
X    buffer->point_down (0);
X    make_selection ();				// copy to paste buffer
X    delete_selection ();			// delete from text
X  }
X}
X
X// -------------------------------------------------------------------------
X//  cut_to_end_of_line: Cut to the end of the current line to the paste
X//	buffer. If there is a selection, cut_to_end_of_line can not be   
X//	executed. Print a warning instead.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut_to_end_of_line ()
X{
X  if (buffer->selection_on) {
X    info->message ("cut-to-end-of-line: ", "Not possible while selection is on", 
X		   "(Place cursor before calling this function)");
X    return;
X  }
X
X  buffer->set_pt2 ();
X  if (buffer->pt.at_eoln ())
X    buffer->point_forward ();    
X  else
X    buffer->point_to_eol ();
X  make_selection ();				// copy to paste buffer
X  delete_selection ();				// delete from text
X}
X
X// -------------------------------------------------------------------------
X//  cut_region: Cut the current region to the paste buffer.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut_region ()
X{
X    info->warning ("cut-region: Not yet implemented", 
X		   "(sorry)");
X}
X
X
X// =========================================================================
X//				selection functions
X// =========================================================================
X
X// -------------------------------------------------------------------------
X//  select_region: Select or unselect the region between mark and 
X//	point.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::select_region ()
X{
X  if (buffer->selection_on) {
X    toggle_selection ();
X    screen->cursor_on (True);
X    show_point ();
X  }
X  else {
X    if (!buffer->set_pt2_to_mark ()) {
X      info->warning ("select-region: No mark has been set.", "");
X      return;
X    }
X    toggle_selection ();
X  }
X}
X
X// -------------------------------------------------------------------------
X//  select_word: Select the whole current word.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::select_word ()
X{
X  if (buffer->selection_on) {		// add next word to selection
X    buffer->unselect ();
X    buffer->point_forward_word ();
X    toggle_selection ();
X  }
X  else					// select current word
X    if (buffer->point_forward()) {
X      buffer->point_backward_word ();
X      buffer->set_pt2 ();
X      buffer->point_forward_word ();
X      toggle_selection ();
X    }
X}
X
X// -------------------------------------------------------------------------
X//  select_line: Select the whole current line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::select_line ()
X{
X  if (buffer->selection_on) {		// add next line to selection
X    buffer->unselect ();
X    buffer->point_to_bol ();
X    if (buffer->pt.is_before (buffer->pt2))
X      buffer->set_pt2 ();
X    buffer->point_down (0);
X    toggle_selection ();
X  }
X  else {				// select current line
X    buffer->point_to_bol ();
X    buffer->set_pt2 ();
X    if (!buffer->point_down (0))	// in last line...
X      buffer->point_to_eol ();		// ...select to end
X    toggle_selection ();
X  }
X}
X
X// -------------------------------------------------------------------------
X//  toggle_selection: Switches the selection on or off, depending on its 
X//	previous state.  This is done both internally and on screen.  The
X//	selection is set to the region between point and mark. After
X//	completion of this function, the selection has been shown or removed
X//	on screen, point is set internally, but NOT displayed on screen.
X//	Returns true on success, False if no mark was set.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::toggle_selection ()
X{
X  BUFFERPOS start_pos;
X  int screenline, col;
X
X  if (buffer->selection_on) {
X    buffer->unselect ();
X    dragging = False;
X  }
X  else {
X    buffer->select_point_point ();	// switch selection on
X    make_selection ();			// copy selection to paste buffer
X    if (!buffer->selection_on)		// if there was no selection...
X      return;
X  }
X
X  // select/unselect has been finished internally, now update the screen
X
X  if ((buffer->pt.is_before (top)) || (buffer->pt2.is_behind(bottom)))
X    return;
X    // nothing else to do -- selection is not on screen
X
X  screen->cursor_on (False);
X
X  if (buffer->pt2.is_before (top))		// adjust start position
X    start_pos = top;
X  else
X    start_pos = buffer->pt2;
X
X  buffer_pos_to_screen_pos (start_pos.line, start_pos.column, screenline, col);
X  screen->cursor_to (col, screenline);
X  display_from (start_pos);
X}
X
X// -------------------------------------------------------------------------
X//  extend_highlight: extend (or shrink) the current highlight to the region
X//	from the current beginning to screen_x, screen_y.  If the highlight
X//	is on, pt2 is expected to be at the beginning of it.  If it is not
X//	yet on, we turn it on here and set pt2 to the beginning.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::extend_highlight (int screen_x, int screen_y)
X{
X  BUFFERPOS minpos;
X  int screenline, col;
X
X  if (buffer->selection_on)
X    buffer->unselect ();	// if selected, unselect, pt2 already at beg
X  else {
X    buffer->set_pt2 ();		// else set pt2 to beginning of selection
X    screen->cursor_on (False);
X  }
X
X  set_point_to_square (screen_x, screen_y);
X  buffer->select_point_point ();
X
X  if (buffer->pt2.is_before (top))
X    minpos = top;
X  else
X    minpos = buffer->pt2;
X  
X  buffer_pos_to_screen_pos (minpos.line, minpos.column, screenline, col);
X  screen->cursor_to (col, screenline);
X  display_from (minpos);
X}
X
X// -------------------------------------------------------------------------
X//  drag_highlight: extend (or shrink) the current highlight to the region
X//	from drag_start to to screen_x, screen_y.  (screen_x and screen_y
X//	are column and row and must within the screen bounds.)
X//	The highlight has to be on, dragging has to be true.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::drag_highlight (int screen_x, int screen_y)
X{
X  BUFFERPOS minpos;
X  int screenline, col;
X
X  buffer->unselect ();
X
X  if (drag_start.equal (buffer->pt2)) {		// dragging forward
X    minpos = buffer->pt;			// current end of selection
X    set_point_to_square (screen_x, screen_y);
X    buffer->select_point_point ();
X
X    if (buffer->pt.is_before (minpos))
X      minpos = buffer->pt;
X  }
X  else {					// dragging backwards
X    minpos = buffer->pt2;			// current start of selection
X    set_point_to_square (screen_x, screen_y);
X    buffer->set_pt2 ();
X    buffer->point_to (drag_start);
X    buffer->select_point_point ();
X
X    if (buffer->pt2.is_before (minpos))
X      minpos = buffer->pt2;
X  }  
X
X  if (minpos.is_before (top))
X    minpos = top;
X  
X  buffer_pos_to_screen_pos (minpos.line, minpos.column, screenline, col);
X  screen->cursor_to (col, screenline);
X  display_from (minpos);
X}
X
X// -------------------------------------------------------------------------
X//  make_selection: Copy the current selection (pt2 to pt) into the paste 
X//	buffer. The selection does not necessarily have to be turned on, as
X//	long as pt2 and pt are set properly (pt2 must be <= pt!).
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::make_selection ()
X{
X  char* sel_text;
X  char* new_buffer;
X
X  if (buffer->pt.equal (buffer->pt2)) {		// empty selection
X    if (buffer->selection_on)
X      buffer->unselect ();
X    screen->cursor_on (True);
X    show_point ();
X    return;
X  }
X
X  sel_text = buffer->selection_to_string ();
X
X  // now, if the prevoius function was a cut function, append this text,
X  // otherwise discard previous text
X
X  if ((last_func >= UFCutWord) && (last_func <= UFCut) && (red->paste_buffer))
X  {
X    new_buffer = new char [strlen (red->paste_buffer) + strlen (sel_text)];
X    strcpy (new_buffer, red->paste_buffer);
X    strcat (new_buffer, sel_text);
X    delete [] sel_text;
X    delete [] red->paste_buffer;
X    red->paste_buffer = new_buffer;
X  }
X  else {
X    delete [] red->paste_buffer;
X    red->paste_buffer = sel_text;
X  }
X  utility->own_selection (da, x_tell_selection_cb, x_selection_lost_cb, 
X			  CurrentTime);
X}
X
X// -------------------------------------------------------------------------
X//  check_selection: If the selection is currently on, turn it off.
X//	If cut_it is true, delete the selection.
X//	If forwd is true, leave the cursor at the end of the selection,
X//	otherwise at the beginning. Return true.  If the selection is not
X//	on, return false.
X// -------------------------------------------------------------------------
X
XBoolean EDITOR::check_selection (Boolean cut_it, Boolean forwd)
X{
X  if (buffer->selection_on) {
X    if (cut_it) {
X      delete_selection ();
X      return True;
X    }
X
X    toggle_selection ();
X    dragging = False;
X    if (!forwd)
X      buffer->point_to (buffer->pt2);
X
X    screen->cursor_on (True);
X    show_point ();
X    return True;
X  }
X  else
X    return False;
X}
X
X// -------------------------------------------------------------------------
X//  delete_selection: Delete the current selection and redisplay. The 
X//	selection does not have to be switched on -- this function just 
X//	deletes between pt and pt2. After this function is executed,
X//	the selection is off.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::delete_selection ()
X{
X  Boolean out_of_screen;
X
X  out_of_screen = (buffer->pt2.is_before (top))
X		  || (buffer->pt2.is_behind(bottom));
X
X  delete_between_points ();		// deletes region between pt2 and pt
X
X  if (out_of_screen)			// full redisplay
X    redisplay ();
X  else {				// display from cursor position
X    screen->cursor_on (False);
X    place_cursor_on_screen ();		// put screen cursor according to point
X    display_from (buffer->pt);		// display from cursor
X    place_cursor_on_screen ();		// and put cursor back up
X  }
X
X  screen->cursor_on (True);
X  utility->set_scrollbar (scrollbar, top.line_no,
X			  bottom.line_no - top.line_no + 1,
X			  buffer->lines + 1);
X}
X
X// -------------------------------------------------------------------------
X//  block_operation: apply a function to every line in the selection.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::block_operation (CodePtr func)
X{
X  BUFFERPOS pt_pos;
X
X  assert (buffer->selection_on);
X
X  if ((buffer->pt2.column != 0) || (buffer->pt.column != 0)) {
X    buffer->unselect ();
X    buffer->pt2.column = 0;			// extend selection to beg.
X    if (!buffer->is_last (buffer->pt.line))
X      buffer->next_line (buffer->pt);		//  of first line and end of
X    buffer->select_point_point ();		//  last line
X  }
X
X  buffer->get_point (pt_pos);
X
X  for (;;) {
X    buffer->prev_line (buffer->pt);
X    (this->*func)();			// call user function on each line
X    if (buffer->pt.line == buffer->pt2.line)
X      break;
X  }
X  buffer->point_to (buffer->pt2);
X  show_point ();
X  buffer->point_to (pt_pos);
X  display_from (buffer->pt2);
X}
SHAR_EOF
  $shar_touch -am 0512222696 'Red/Red/editor_edit.i' &&
  chmod 0640 'Red/Red/editor_edit.i' ||
  echo 'restore of Red/Red/editor_edit.i failed'
  shar_count="`wc -c < 'Red/Red/editor_edit.i'`"
  test 27831 -eq "$shar_count" ||
    echo "Red/Red/editor_edit.i: original size 27831, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/editor_event.i ==============
if test -f 'Red/Red/editor_event.i' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/editor_event.i (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/editor_event.i (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/editor_event.i' &&
X// =========================================================================
X//
X// FILE: editor_event.i	- part of editor.cc			  -mik- 1995
X//
X// This part contains implementations of all event handling functions in
X// the editor.  It is part of the implementation of class EDITOR.
X//
X// The first group of functions handles the incoming events from the 
X// callbacks.  It then forks off into the second group of functions, which
X// provide one function for each event type to handle each event 
X// individually.
X//
X// =========================================================================
X
X// -------------------------------------------------------------------------
X//  handle_event: The editor window received an event.  The event could be a
X//	mouse click, mouse motion, keypress or expose event. Check which and
X//	call the appropriate function.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_event (XEvent *event)
X{
X  switch (event->type) {
X  
X    case ButtonPress:
X	handle_mouseclick ( (XButtonEvent*)event);
X	break;
X    case ButtonRelease:
X	handle_buttonup ( (XButtonEvent*)event);
X	break;
X    case MotionNotify:
X        handle_motion ( (XMotionEvent*)event);
X	break;
X    case KeyPress:
X	handle_keypress ( ((XKeyPressedEvent*)event));
X	break;
X    case Expose:
X	handle_expose ( (XExposeEvent*)event);
X	break;
X    default:
X	; // ignore everything else
X  }
X}
X
X// -------------------------------------------------------------------------
X//  scroll_event: The scroll bar was clicked somewhere. Call the appropriate
X//	scroll function depending on the part that was clicked (reason).
X//	value is the new scroll value.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_event (int reason, int value)
X{
X  last_func = NOT_BOUND;
X  switch (reason) {
X
X    case XmCR_DECREMENT:
X      scroll_line_up ();
X      break;
X
X    case XmCR_INCREMENT:
X      scroll_line_down ();
X      break;
X
X    case XmCR_PAGE_DECREMENT:
X      previous_page ();
X      break;
X
X    case XmCR_PAGE_INCREMENT:
X      next_page ();
X      break;
X
X    case XmCR_DRAG:
X      scroll_drag (value);
X      break;
X
X    default:
X      assert (False);
X  }
X}
X
X// -------------------------------------------------------------------------
X//  resize: The window has been resized. Call the screen resize function
X//	to update the screen parameters. Then do as in an expose event:
X//	redisplay the text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::resize ()
X{
X  if (XtIsRealized(edit_window)) {		// only if screen is visible
X    top.column = 0;
X    screen->resize ();
X  }
X}
X
X// -------------------------------------------------------------------------
X//  menu_item: A menu item was selected. Call the appropriate 
X//	function for this item.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::menu_item (MenuItemId item)
X{
X  UserFuncId func;
X
X  func = red->userfunc->translate_item (item);
X  call_userfunction (func);
X}
X
X// -------------------------------------------------------------------------
X//  tool_button_press: Called when a button from the toolbar was pressed.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::tool_button_press (int button_no)
X{
X  UserFuncId func;
X
X  func = red->userfunc->translate_toolbutton (button_no);
X  call_userfunction (func);
X}
X
X
X// =========================================================================
X//  sub-functions of handle_event: one function for each event type:
X// =========================================================================
X
X
X// -------------------------------------------------------------------------
X//  handle_keypress: A key has been pressed in the edit window.  Use
X//	the keymaps to map the key to an editor function, then call that
X//	function.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_keypress (XKeyPressedEvent *event)
X{
X  char str[2];
X  KeySym keysym;
X  unsigned int modifierMask, modifiers;
X  UserFuncId func;
X
X  modifierMask = ShiftMask | ControlMask | Mod1Mask;
X  modifiers = event->state & modifierMask;
X
X  // get keysym and string of the key that was pressed
X
X  assert (XLookupString (event, str, 1, &keysym, NULL) <= 1);
X  last_char = str[0];			// keep the key that was pressed
X
X  func = red->userfunc->translate_key (keysym, modifiers);
X
X  if (func == UNKNOWN_KEY)		// do nothing. probably modifier key, 
X    return;				// or something we don't want to handle
X
X  call_userfunction (func);
X}
X
X// -------------------------------------------------------------------------
X//  handle_mouseclick: Mouse click in editor window. Find out which button
X//	and call the appropriate routine.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_mouseclick (XButtonEvent *event)
X{
X  const int DOUBLE_CLICK_TIME=250;	// time in milliseconds
X  Boolean in_tag;
X
X  info->clear();
X  last_func = NOT_BOUND;
X  screen->point_to_square (event->x, event->y, mouse_col, mouse_line, in_tag);
X
X  switch (event->button) {
X
X    case Button1:
X      if (in_tag)
X	click_in_tag_line (mouse_line);
X      else {
X        button1_down = True;
X	if (event->time - button1_uptime < DOUBLE_CLICK_TIME)  // double click
X
X	  if (double_click)			// was already double -> triple
X	    if (event->state & ShiftMask)
X		select_word ();
X	    else
X		select_line ();
X	  else {				// real double click
X	    double_click = True;
X	    select_word ();
X	  }
X	else {
X	  double_click = False;
X	  cursor_to (mouse_col, mouse_line);
X	}
X      }
X      break;
X
X    case Button2:
X      if (!in_tag) {
X	cursor_to (mouse_col, mouse_line);
X	paste ();
X      }
X      break;
X
X    case Button3:
X      if (!in_tag) {
X	extend_highlight (mouse_col, mouse_line);
X        make_selection ();			   // copy to paste buffer
X      }
X      break;
X
X  }
X}
X
X// -------------------------------------------------------------------------
X//  handle_buttonup: Called whenever the mouse button is released.  The only
X//	interesting case at the moment is when we were dragging to select
X//	text.  Then the button release ends the dragging and the current
X//	selection has to be copied to the paste buffer.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_buttonup (XButtonEvent *event)
X{
X  switch (event->button) {
X
X    case Button1:  button1_down = False;
X		   if (dragging) {
X		     dragging = False;
X		     make_selection ();		// copy to paste buffer
X		   }
X		   button1_uptime = event->time;
X		   break;
X
X    case Button2:  break;
X
X    case Button3:  break;
X
X  }
X
X}
X
X// -------------------------------------------------------------------------
X//  handle_motion: Mouse is dragged while button is pressed. Find out which
X//	button and call the appropriate routine.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_motion (XMotionEvent *event)
X{
X  int line, col;
X  Boolean in_tag;
X
X  if (!button1_down) return;			// was not button 1 then
X
X  screen->point_to_square (event->x, event->y, col, line, in_tag);
X
X  if ((!in_tag) && ((mouse_col != col) || (mouse_line != line))) {
X
X    mouse_line = line;			// store for next time round
X    mouse_col = col;
X
X    if (!dragging) {			// just starting to drag
X      dragging = True;
X      drag_start = buffer->pt;
X      extend_highlight (mouse_col, mouse_line);
X    }
X    else
X      drag_highlight (mouse_col, mouse_line);
X  }
X}
X
X// -------------------------------------------------------------------------
X//  handle_expose: Handle an expose event. If this is the very first expose,
X//	there are several special things to do: pixmaps must be created,
X//	the icon must be created. This can only be done after the first 
X//	expose (not on creation), so it is done here.
X//	Then handle the normal expose event.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::handle_expose (XExposeEvent* event)
X{
X  int ac;
X  Arg al[20];
X  XSetWindowAttributes xswa;
X
X  if (first_expose) {		
X
X    // first time, change some settings that need to be set up after window
X    // is realized for the first time
X
X      utility->create_pixmaps (edit_window, da);
X
X      ac=0;
X      XtSetArg (al[ac], XmNiconPixmap, utility->edit_icon); ac++;
X      XtSetValues (edit_window, al, ac);
X
X    // change gravity to Forget, so that resize always generates exposure
X    // events
X
X      xswa.bit_gravity = ForgetGravity;
X      XChangeWindowAttributes (XtDisplay(da), XtWindow(da),
X				CWBitGravity, &xswa);
X
X      first_expose = False;
X
X      screen->expose ();
X      info->expose ();
X      redisplay ();
X  }
X  else 
X      if (event->count == 0) {		// only if there are no more expose
X	  screen->expose ();		//  events coming...
X	  info->expose ();
X	  display ();
X      }
X}
X
X// -------------------------------------------------------------------------
X//  click_in_tag_line: A mouse click in the tag line occured.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::click_in_tag_line (int line)
X{
X#ifndef RED_ONLY
X  BUFFERPOS pt_pos;		// temp store current position
X
X  buffer->get_point (pt_pos);
X  cursor_to (0, line);
X  toggle_breakpoint ();
X  buffer->point_to (pt_pos);
X  show_point ();
X#endif
X}
X
X// -------------------------------------------------------------------------
X//  call_userfunction: Call the user function 'func' points to.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::call_userfunction (UserFuncId func)
X{
X  CodePtr code;
X
X  if (param_prompt)
X    get_param (func);
X  else {
X    if (func == NOT_BOUND)			// no function on this key
X      info->warning ("undefined key","");
X    else {					// call the function
X      info->clear();
X      code = red->userfunc->code_pointer(func);	// get pointer to the code
X      (this->*code)();				// call the function
X    }
X    last_func = func;			// save the last function executed
X  }
X}
X
X// -------------------------------------------------------------------------
X//  get_param: We are currently reading a parameter in the info area.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::get_param (UserFuncId func)
X{
X  if (last_func == UFDescribeKey) {
X    do_describe (func);
X    param_prompt = NULL;
X  }
X  else {
X      switch (func) {
X	case UFSelfInsert:
X	  strncat (parameter, &last_char, 1);
X	  info->message (param_prompt, parameter, "");
X	  break;
X	case UFBackDeleteChar:
X	  if (strlen(parameter)>0)
X		parameter[strlen(parameter)-1] = '\0';
X	  info->message (param_prompt, parameter, "");
X	  break;
X	case UFNewLine:
X	  goto_line ();
X	  break;
X	default:
X	  XBell (XtDisplay(edit_window), 0);
X      }
X  }
X}
X
SHAR_EOF
  $shar_touch -am 0512222696 'Red/Red/editor_event.i' &&
  chmod 0640 'Red/Red/editor_event.i' ||
  echo 'restore of Red/Red/editor_event.i failed'
  shar_count="`wc -c < 'Red/Red/editor_event.i'`"
  test 10814 -eq "$shar_count" ||
    echo "Red/Red/editor_event.i: original size 10814, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/editor_func.i ==============
if test -f 'Red/Red/editor_func.i' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/editor_func.i (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/editor_func.i (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/editor_func.i' &&
X// =========================================================================
X//
X// FILE: editor_func.i	- part of editor.cc			  -mik- 1995
X//
X// This part contains implementations of all the user functions.
X//
X// It is part of the implementation of class EDITOR.
X//
X// =========================================================================
X
X#ifdef RED_ONLY
X
X  // -------------------------------------------------------------------------
X  //  new_window: Open new, empty editor.
X  // -------------------------------------------------------------------------
X
X  void EDITOR::new_window ()
X  {
X    (void) red->edit_file (NULL, False);
X  }
X
X  // -------------------------------------------------------------------------
X  //  open_other: Open another editor showing some file. (That is: show a file
X  //	selection dialog first.)  This is done by actually calling Red
X  //	(open_request) -- Red handles the file selection dialog.  If this
X  //	editor has an empty unused buffer, use this editor to load the file
X  //	into (indicated by passing a pointer to this editor).  If not, 
X  //	(passing NULL), Red will create a new editor.
X  // -------------------------------------------------------------------------
X
X  void EDITOR::open_other ()
X  {
X    if ((*basename(filename) == '\0') && (save_state == Saved))	// unused buffer
X      red->open_request (this, dirname (filename));	// use this editor
X    else
X      red->open_request (NULL, dirname (filename));	// use new one
X  }
X
X  // -------------------------------------------------------------------------
X  //  save_as: Save buffer under new name.
X  // -------------------------------------------------------------------------
X
X  void EDITOR::save_as ()
X  {
X    red->save_as_request (this, dirname (filename));
X  }
X
X#endif
X
X// -------------------------------------------------------------------------
X// save: Save the buffer to disk under current filename.  If it hasen't got
X//	a filename, call save_as instead.
X// -------------------------------------------------------------------------
X
X// save is implemented in "editor.cc" since it is an interface function.
X
X// -------------------------------------------------------------------------
X// revert: Revert has been chosen. Ask "Really?" and get "really_revert" 
X//	called if the answer is yes.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::revert ()
X{
X  if (save_state == Saved) {
X    info->message ("The text is still equal to the last saved version", "",
X		   "(\"Revert\" does not do anything.)");
X    return;
X  }
X
X  if (*basename(filename) == '\0') 
X    info->warning ("Can not revert - this text was never saved!",
X		   "(\"Revert\" reverts to the last saved state.)");
X  else
X    messages->show_question (edit_window, QuRevert, EDITOR__do_revert, this);
X}
X
X// -------------------------------------------------------------------------
X// do_revert: Revert the buffer contents to the last saved version.  Do
X//	not ask any question - just do it.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::do_revert ()
X{
X  if (!(buffer->load(filename)))
X    info->warning ("ERROR: The file seems to have disappeared!", "");
X  redisplay ();
X}
X
X// -------------------------------------------------------------------------
X//  print: Print the buffer contents to a printer.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::print ()
X{
X  info->warning ("Printing is not yet implemented.", "(Sorry)");
X}
X
X// -------------------------------------------------------------------------
X//  close: The editor has been closed. Hide the editor window.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::close ()
X{
X  #ifdef RED_ONLY
X    red->close_request (this, edit_window, save_state == Changed);
X  #else 				// integrated in Blue
X    save ();
X    src_class->end_edit ();
X    red->close_request (this, edit_window, False);
X  #endif
X
X}
X
X// -------------------------------------------------------------------------
X//  undo: Undo the last action (insertion or deletion).
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::undo ()
X{
X  int line, col, endline, endcol;
X  char ch;
X  char *text;
X  ACTION* action;
X  BUFFERPOS start;
X
X  // if the previous function was not an undo, reset the undo stack
X  if (last_func != UFUndo)
X    undo_stack->reset ();
X
X  do {
X    action = undo_stack->get_action ();
X    if (action == NULL) {
X      info->warning ("No further undo information available.", "");
X      return;
X    }
X
X    if (check_selection (False, True))	// if selection, switch it off
X      ;
X
X    if (action->get_type() == InsAction) {	// action was insertion
X      action->get_ins_info (line, col, endline, endcol);
X      buffer->goto_pos (line, col);
X      show_point ();
X      buffer->set_pt2 ();
X      buffer->goto_pos (endline, endcol);
X      delete_between_points ();
X      screen_update_from (buffer->pt);
X    }
X    else {					// action was deletion
X      action->get_del_info (line, col, text, ch);
X      buffer->goto_pos (line, col);
X      show_point ();
X      if (text == NULL) {
X	if ((unsigned char)ch == NewLine)
X	  new_line ();
X	else
X	  insert_char (ch);
X      }
X      else {
X	buffer->get_point (start);
X	insert (text);
X	screen_update_from (start);
X      }
X    }
X  } while (action->is_linked ());
X}
X
X// -------------------------------------------------------------------------
X//  cut: Cut out the current selection and put it into the paste buffer.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cut ()
X{
X  int lines;
X
X  if (buffer->selection_on) {	// if selection was on...
X    make_selection ();
X    lines = buffer->lines;
X    delete_selection ();
X    if (lines-1 > buffer->lines)
X      info->int_message (lines - buffer->lines, " lines cut to paste buffer.",
X			 "");
X  }
X  else
X    info->warning ("Cut: No selection!",
X		   "(You need to select text first before you can cut it.)");
X}
X
X// -------------------------------------------------------------------------
X//  paste: User function paste - request the text of the X selection.  When
X//	the text is recieved, 'do_paste' will be called.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::paste ()
X{
X  utility->get_selection (this, da, x_paste_cb, CurrentTime);
X}
X
X// -------------------------------------------------------------------------
X//  do_paste: Paste 'text' into the buffer at the current position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::do_paste (char* text)
X{
X  BUFFERPOS start;
X  int lines;
X
X  if (text == NULL)
X    info->warning ("Paste buffer is empty.", "");
X  else {
X    if (check_selection (True, True))	// if selection, cut it
X      ;
X    buffer->set_mark ();
X    lines = buffer->lines;
X
X    buffer->get_point (start);
X    insert (text);
X    screen_update_from (start);
X    if (lines+1 < buffer->lines)
X      info->int_message (buffer->lines - lines, " lines pasted.",
X			 "(Mark set at beginning of pasted text.)");
X  }
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::interface_toggle ()
X{
X  info->warning ("Interface button", "not yet implemented");
X}
X
X
X// -------------------------------------------------------------------------
X//  find: The find function has been called. Call the finder to start the 
X//	find dialog.  The finder will pop up the dialog and, when called 
X//	back, call the "do_find" function below.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::find ()
X{
X  red->finder->show_dialog (False, this, False);
X}
X
X// -------------------------------------------------------------------------
X//  find: The find function has been called. Call the finder to start the 
X//	find dialog.  The finder will pop up the dialog and, when called 
X//	back, call the "do_find" function below.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::find_backward ()
X{
X  red->finder->show_dialog (False, this, True);
X}
X
X// -------------------------------------------------------------------------
X//  find_next: Find either the text selected or, if there is no selection,
X//	the same pattern as in the last find operation. 
X//	Call the finder to get information about the last find
X//	operation and then perform the operation again. This is done by 
X//	calling do_find below.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::find_next ()
X{
X  char* pattern;
X  SearchDir direction;
X  Boolean case_matters, whole_word;
X
X  red->finder->get_find_info (pattern, direction, case_matters, whole_word);
X  if (buffer->selection_on) {
X    pattern = buffer->selection_to_string ();
X    red->finder->set_find_string (pattern);
X  }
X  if (pattern == NULL)
X    info->warning ("find-next: No search pattern has been defined yet",
X		   "(Use \"find\" first or select some text to search for)");
X  else
X    do_find (pattern, direction, case_matters, whole_word); 
X    // discard result
X}
X
X// -------------------------------------------------------------------------
X//  find_next_reverse: Like "find_next", but reverse direction of search.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::find_next_reverse ()
X{
X  char* pattern;
X  SearchDir direction;
X  Boolean case_matters, whole_word;
X
X  red->finder->get_find_info (pattern, direction, case_matters, whole_word);
X  if (buffer->selection_on) {
X    pattern = buffer->selection_to_string ();
X    red->finder->set_find_string (pattern);
X  }
X  if (pattern == NULL)
X    info->warning ("find-next-reverse: No search pattern has been defined yet",
X		   "(Use \"find\" first or select some text to search for)");
X  else
X    if (direction==forwd)
X      do_find (pattern, backwd, case_matters, whole_word);
X    else
X      do_find (pattern, forwd, case_matters, whole_word);
X    // discard result
X}
X
X// -------------------------------------------------------------------------
X//  replace: Pop up the replace dialog. The actual replacing (when the 
X//	"replace" or "replace all" button in the dialog is pressed) is done
X//	in the do_replace function.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::replace ()
X{
X  red->finder->show_dialog (True, this, False);
X}
X
X
X// -------------------------------------------------------------------------
X//  define_macro:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::define_macro ()
X{
X    info->warning ("define-macro: Not yet implemented", 
X		   "(sorry)");
X}
X
X// -------------------------------------------------------------------------
X//  end_macro:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::end_macro ()
X{
X    info->warning ("end-macro: Not yet implemented", 
X		   "(sorry)");
X}
X
X// -------------------------------------------------------------------------
X//  run_macro:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::run_macro ()
X{
X    info->warning ("run-macro: Not yet implemented", 
X		   "(sorry)");
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::preferences ()
X{
X  red->show_pref_dialog (edit_window);
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::key_bindings ()
X{
X  red->userfunc->show_dialog (edit_window);
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::edit_toolbar ()
X{
X  red->edit_toolbar ();
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::fonts ()
X{
X  red->show_font_dialog ();
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::colours ()
X{
X  red->show_colour_dialog ();
X}
X
X// -------------------------------------------------------------------------
X//  manual: Start up a WWW browser defined in the application resources to
X//	display the user manual.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::manual ()
X{
X  char command[120];
X
X  strncpy (command, rsrc->man_browser, 38);
X  strcat (command, " ");
X  strncat (command, rsrc->man_url, 80);
X  strcat (command, "&");
X  system(command);
X}
X
X// -------------------------------------------------------------------------
X//  goto_line: Interactive. Ask for line number and set cursor to that line.
X//	If the number is greater than last line, goto last line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::goto_line ()
X{
X  int line_no;
X
X  if (param_prompt) {			// got parameter - analyse and do it
X    param_prompt = NULL;
X    line_no = atoi (parameter);
X    if (check_selection (False,True))	// make sure selection is off
X      ;
X    buffer->point_to_bob ();
X    buffer->goto_pos (line_no, 0);
X    show_point ();
X    show_line ();
X  }
X  else {				// prompt for parameter
X    param_prompt = "Goto line: ";
X    strcpy (parameter, "");
X    info->message (param_prompt, "", "");
X  }
X}
X
X// -------------------------------------------------------------------------
X//  show_line: Display the current line number.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::show_line ()
X{
X  info->message_int ("Line ", buffer->pt.line_no, "");
X}
X
X// -------------------------------------------------------------------------
X//  describe_key: 
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::describe_key ()
X{
X  param_prompt =  "Describe key: ";
X  info->message (param_prompt, "", "");
X}
X
X// -------------------------------------------------------------------------
X//  do_describe: 
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::do_describe (UserFuncId func)
X{
X  char* name;
X
X  if (func == NOT_BOUND)			// no function on this key
X    info->message ("This key is undefined","","");
X  else {
X    XmStringGetLtoR (red->userfunc->funcname(func), 
X			XmSTRING_DEFAULT_CHARSET, &name);
X    info->message ("This key calls the function ", name, "");
X  }
X}
X
X// -------------------------------------------------------------------------
X//  set_mark: Set mark at cursor position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::set_mark ()
X{
X  buffer->set_mark ();
X  info->message ("Mark set", "", "");
X}
X
X// -------------------------------------------------------------------------
X//  swap_point_mark: Swap mark and cursor position.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::swap_point_mark ()
X{
X  if (check_selection (False,True))	// make sure selection is off
X    ;
X  if (buffer->swap_point_mark ())
X    show_point ();
X  else
X    info->warning ("No mark has been set", 
X		   "(You tried to swap point and mark)");
X}
X
X// -------------------------------------------------------------------------
X//  blue_new_routine: Insert a new Blue routine skeleton.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::blue_new_routine ()
X{
X  BUFFERPOS start;
X
X  if (check_selection (True, True))	// if selection, cut it
X    ;
X
X  buffer->get_point (start);
X  insert ("    NAME () -> () is\n"
X	  "	-- COMMENT\n"
X	  "      --precondition\n"
X	  "      do\n"
X	  "	-- ROUTINE BODY\n"
X	  "      --postcondition\n"
X	  "      end NAME\n"
X	  "\n\n");
X
X  screen_update_from (start);
X}
X
X// -------------------------------------------------------------------------
X//  edit_debug: Print out some debug information
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::edit_debug ()
X{
X  soft_error ("\neditor status");
X  soft_error_i ("No of lines: ", buffer->lines);
X  soft_error_i ("top line no: ", top.line_no);
X  soft_error_i ("top column: ", top.column);
X  soft_error_i ("bottom line no: ", bottom.line_no);
X  soft_error_i ("bottom column: ", bottom.column);
X  soft_error_i ("point line no: ", buffer->pt.line_no);
X  soft_error_i ("point column: ", buffer->pt.column);
X  soft_error_i ("blank lines: ", blanklines);
X  if (buffer->selection_on)
X    soft_error ("selection is on");
X  else
X    soft_error ("selection is off");
X}
X
X// -------------------------------------------------------------------------
X//  empty_function: Dummy used for key bindings that call functions in one
X//	version of red (integrated or stand-alone) but not in the other.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::empty_function ()
X{
X  info->warning ("undefined key","");
X}
SHAR_EOF
  $shar_touch -am 0512222696 'Red/Red/editor_func.i' &&
  chmod 0640 'Red/Red/editor_func.i' ||
  echo 'restore of Red/Red/editor_func.i failed'
  shar_count="`wc -c < 'Red/Red/editor_func.i'`"
  test 17266 -eq "$shar_count" ||
    echo "Red/Red/editor_func.i: original size 17266, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/editor_init.i ==============
if test -f 'Red/Red/editor_init.i' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/editor_init.i (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/editor_init.i (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/editor_init.i' &&
X// =========================================================================
X//
X// FILE: editor_init.i	- part of editor.cc			  -mik- 1995
X//
X// This part contains implementations of all editor initialisation routines
X// that don't have anything to do with the graphical interface (these are
X// in editor_init_win.i).  Things inluded here are definition of user
X// functions and their bindings to keys.
X//
X// It is part of the implementation of class EDITOR.
X//
X// =========================================================================
X
X// -------------------------------------------------------------------------
X//  init_window: do all the Motif initialisation: create the widgets but
X//	don't realize them yet (that is: don't show them on the screen).
X//	The main widget is the global 'edit_window', which can be realized
X//	later to make the window visible on the screen.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::init_window (Widget toplevel, Boolean show_tool, Boolean compiled, 
X			  Boolean iconic)
X{
X  int ac;
X  Arg al[20];
X
X  int i;
X  Widget main_form;
X  Widget menu, item, tool_button;
X  Atom WM_DELETE_WINDOW;
X
X  /* create top level editor window */
X  ac=0;
X  if (iconic)
X    { XtSetArg (al[ac], XmNinitialState, IconicState); ac++; }
X  XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
X  edit_window = XtAppCreateShell ("red", "Red", applicationShellWidgetClass,
X				  XtDisplay(toplevel), al, ac);
X
X  /* Add callback for WM_DELETE_WINDOW protocol */
X
X  WM_DELETE_WINDOW = XmInternAtom (XtDisplay (toplevel), "WM_DELETE_WINDOW", False);
X  XmAddWMProtocolCallback (edit_window, WM_DELETE_WINDOW, EDITOR__window_close, this);
X
X  /* create a form in the edit_window */
X
X  ac=0;
X  XtSetArg (al[ac], XmNhorizontalSpacing, 8); ac++;
X  XtSetArg (al[ac], XmNverticalSpacing, 8); ac++;
X  main_form = XmCreateForm (edit_window, "mainForm", al, ac);
X  XtManageChild (main_form);
X
X  /* create menu bar and menus */
X
X  menu_bar = utility->create_menu_bar (main_form, "menuBar");
X
X    /* the Object menu */
X    menu = utility->create_menu (menu_bar, _CLASS_, False);
X    #ifdef RED_ONLY
X      item = utility->create_item (menu, "New", EDITOR__menu_item, NewItem, this);
X      item = utility->create_item (menu, "Open", EDITOR__menu_item, OpenItem, this);
X      item = utility->create_item (menu, "Save", EDITOR__menu_item, SaveItem, this);
X      item = utility->create_item (menu, "Save As...", EDITOR__menu_item, SaveAsItem, this);
X    #else
X      item = utility->create_item (menu, "Save", EDITOR__menu_item, SaveItem, this);
X    #endif
X    item = utility->create_item (menu, "Revert", EDITOR__menu_item, RevertItem, this);
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Print", EDITOR__menu_item, PrintItem, this);
X      utility->set_sensitive (item, False); // NOT IMPLEMENTED
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Close", EDITOR__menu_item, CloseItem, this);
X
X    /* the Edit menu */
X    menu = utility->create_menu (menu_bar, "Edit", False);
X    item = utility->create_item (menu, "Undo", EDITOR__menu_item, UndoItem, this);
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Cut", EDITOR__menu_item, CutItem, this);
X    item = utility->create_item (menu, "Paste", EDITOR__menu_item, PasteItem, this);
X
X    /* the View menu */
X  #ifndef RED_ONLY
X      menu = utility->create_menu (menu_bar, "View", False);
X      item = utility->create_item (menu, "Interface", EDITOR__menu_item, InterfaceItem, this);
X  #endif
X
X    /* the Tools menu */
X    menu = utility->create_menu (menu_bar, "Tools", False);
X    item = utility->create_item (menu, "FindItem", EDITOR__menu_item, FindItem, this);
X    item = utility->create_item (menu, "FindNextItem", EDITOR__menu_item, FindNextItem, this);
X    item = utility->create_item (menu, "ReplaceItem", EDITOR__menu_item, ReplaceItem, this);
X    item = utility->create_item (menu, "GotoLineItem", EDITOR__menu_item, GotoLineItem, this);
X    item = utility->create_item (menu, "ShowLineItem", EDITOR__menu_item, ShowLineItem, this);
X  #ifndef RED_ONLY
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Compile", EDITOR__menu_item, CompileItem, this);
X    item = utility->create_item (menu, "GotoErrItem", EDITOR__menu_item, GotoErrItem, this);
X    utility->create_separator (menu);
X    interface_item = utility->create_item (menu, "Interface", EDITOR__menu_item, InterfaceItem, this);
X
X    /* the Debug menu */
X    menu = utility->create_menu (menu_bar, "Debug", False);
X    break_item = utility->create_item (menu, "SetBreakItem", EDITOR__menu_item, SetBreakItem, this);
X    clr_break_item = utility->create_item (menu, "ClearBreakItem", EDITOR__menu_item, ClearBreakItem, this);
X    utility->create_separator (menu);
X    watch_item = utility->create_item (menu, "WatchItem", EDITOR__menu_item, WatchItem, this);
X    examine_item = utility->create_item (menu, "PrintVarItem", EDITOR__menu_item, PrintVarItem, this);
X    utility->create_separator (menu);
X    step_item = utility->create_item (menu, "Step", EDITOR__menu_item, StepItem, this);
X    step_into_item = utility->create_item (menu, "StepIntoItem", EDITOR__menu_item, StepIntoItem, this);
X    cont_item = utility->create_item (menu, "Continue", EDITOR__menu_item, ContinueItem, this);
X    term_item = utility->create_item (menu, "Terminate", EDITOR__menu_item, TerminateItem, this);
X
X    if (!compiled) {
X      utility->set_sensitive (break_item, compiled);
X      utility->set_sensitive (clr_break_item, compiled);
X      utility->set_sensitive (watch_item, compiled);
X    }
X
X    set_debug (false);
X  #endif
X
X    /* the Options menu */
X    menu = utility->create_menu (menu_bar, "Options", False);
X    item = utility->create_item (menu, "PrefItem", EDITOR__menu_item, PrefItem, this);
X    item = utility->create_item (menu, "KeyItem", EDITOR__menu_item, KeyBindItem, this);
X    item = utility->create_item (menu, "Edit Toolbar...", EDITOR__menu_item, EditToolbarItem, this);
X      utility->set_sensitive (item, False); // NOT IMPLEMENTED
X    item = utility->create_item (menu, "Fonts...", EDITOR__menu_item, FontsItem, this);
X      utility->set_sensitive (item, False); // NOT IMPLEMENTED
X    item = utility->create_item (menu, "Colours...", EDITOR__menu_item, ColoursItem, this);
X      utility->set_sensitive (item, False); // NOT IMPLEMENTED
X
X    /* the Help menu */
X    menu = utility->create_help_menu (menu_bar, "Help");
X    item = utility->create_item (menu, "About Red...", show_help, HlpAbout, this);
X    item = utility->create_item (menu, "Copyright Notice...", show_help, HlpCopyright, this);
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Functions and Keys...", EDITOR__menu_item, FunctionsItem, this);
X    item = utility->create_item (menu, "DescribeItem", EDITOR__menu_item, DescribeItem, this);
X    item = utility->create_item (menu, "Mouse Buttons...", show_help, HlpMouse, this);
X    item = utility->create_item (menu, "ManualItem", EDITOR__menu_item, ManualItem, this);
X    utility->create_separator (menu);
X    item = utility->create_item (menu, "Reporting Errors...", show_help, HlpErrors, this);
X
X  /* create label for status (saved/changed) */
X
X  status_area = utility->create_rc_area (main_form, "statusArea", XmHORIZONTAL,
X			XmALIGNMENT_CENTER);
X  utility->attach (status_area, NULL, AtForm, NULL, AtForm);
X
X  saved_label = utility->create_label (status_area, "savedLabel");
X  ac=0;
X  XtSetArg (al[ac], XmNrecomputeSize, false); ac++;
X  XtSetArg (al[ac], XmNheight, 25); ac++;
X  XtSetValues (saved_label, al, ac);
X  utility->set_label (saved_label, "saved");
X
X  /* create information area (draw area) */
X
X  ac=0;
X  XtSetArg (al[ac], XmNborderWidth, 1); ac++;
X  XtSetArg (al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
X  XtSetArg (al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
X  XtSetArg (al[ac], XmNrightWidget, status_area); ac++;
X  XtSetArg (al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
X  XtSetArg (al[ac], XmNtopWidget, status_area); ac++;
X  XtSetArg (al[ac], XmNtopOffset, 0); ac++;
X  XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
X  XtSetArg (al[ac], XmNbottomWidget, status_area); ac++;
X  XtSetArg (al[ac], XmNbottomOffset, 0); ac++;
X  XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
X  info_area = XmCreateDrawingArea (main_form, "infoArea", al, ac);
X  XtManageChild (info_area);
X
X  /* create toolbar area  */
X
X  toolbar = utility->create_rc_area (main_form, "toolBar", XmHORIZONTAL,
X			XmALIGNMENT_CENTER);
X  utility->attach (toolbar, AtForm, NULL, menu_bar, NULL);
X
X      /*create toolbar buttons */
X
X      for (i=0; i<9; i++)
X        tool_button = utility->create_button (toolbar, red->userfunc->toolbutton_name (i),
X						EDITOR__tool_button_press, i, this);
X
X  /* create text window widget */
X  ac=0;
X  XtSetArg (al[ac], XmNscrollBarDisplayPolicy, XmSTATIC); ac++;
X  XtSetArg (al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
X  XtSetArg (al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
X  XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
X  XtSetArg (al[ac], XmNtopWidget, toolbar); ac++;
X  XtSetArg (al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
X  XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
X  XtSetArg (al[ac], XmNbottomWidget, info_area); ac++;
X  text_area = XmCreateScrolledWindow (main_form, "scrolledWindow", al, ac);
X  XtManageChild (text_area);
X
X    /* create scrollbar and drawing area */
X    ac=0;
X    XtSetArg (al[ac], XmNminimum, 1); ac++;
X    XtSetArg (al[ac], XmNmaximum, 100); ac++;
X    scrollbar = XmCreateScrollBar (text_area, "scrollBar", al, ac);
X    XtManageChild (scrollbar);
X    XtAddCallback (scrollbar, XmNincrementCallback, EDITOR__scroll_event, this);  
X    XtAddCallback (scrollbar, XmNdecrementCallback, EDITOR__scroll_event, this);  
X    XtAddCallback (scrollbar, XmNpageIncrementCallback, EDITOR__scroll_event, this);  
X    XtAddCallback (scrollbar, XmNpageDecrementCallback, EDITOR__scroll_event, this);  
X    XtAddCallback (scrollbar, XmNdragCallback, EDITOR__scroll_event, this);  
X
X    ac=0;
X    XtSetArg (al[ac], XmNuserData, this); ac++;
X    da = XmCreateDrawingArea (text_area, "editArea", al, ac);
X    XtManageChild (da);
X    XtAddCallback (da, XmNresizeCallback, EDITOR__resize, this);  
X    XtAddEventHandler (da, ButtonPressMask | ButtonReleaseMask | KeyPressMask |
X	ButtonMotionMask | ExposureMask, False, EDITOR__handle_event, this);
X
X    /* link scrollbar and drawing area to scrolled window */
X    XmScrolledWindowSetAreas (text_area, NULL, scrollbar, da);
X
X  if (!show_tool)			// if the toolbar is not on, hide it
X    show_toolbar (False);
X}
SHAR_EOF
  $shar_touch -am 0512222696 'Red/Red/editor_init.i' &&
  chmod 0640 'Red/Red/editor_init.i' ||
  echo 'restore of Red/Red/editor_init.i failed'
  shar_count="`wc -c < 'Red/Red/editor_init.i'`"
  test 10726 -eq "$shar_count" ||
    echo "Red/Red/editor_init.i: original size 10726, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/editor_move.i ==============
if test -f 'Red/Red/editor_move.i' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/editor_move.i (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/editor_move.i (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/editor_move.i' &&
X// =========================================================================
X//
X// FILE: editor_move.i	- part of editor.cc			  -mik- 1995
X//
X// This part contains implementations of all functions to move the cursor or
X// the view window in the editor.  It is part of the implementation of class
X// EDITOR.
X//
X// =========================================================================
X
X// -------------------------------------------------------------------------
X//  forward_char: Move cursor one character forward. Check for end of text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::forward_char ()
X{
X  if (check_selection (False, True)) {	// if selection on, swith it off
X    show_point ();
X    return;
X  }
X  if (buffer->point_forward())
X    show_point ();
X  else
X    info->warning ("End of text", "");
X}
X
X// -------------------------------------------------------------------------
X//  backward_char: Move cursor one character bachward. Check for beginning
X//	 of text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::backward_char ()
X{
X  if (check_selection (False, False)) {	// if selection on, swith it off
X    show_point ();
X    return;
X  }
X  if (buffer->point_backward())
X    show_point ();
X  else
X    info->warning ("Beginning of text", "");
X}
X
X// -------------------------------------------------------------------------
X//  forward_word: Move cursor one word forward. Check for end of text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::forward_word ()
X{
X  if (check_selection (False, True))	// if selection on, swith it off
X    ;
X  buffer->point_forward_word ();
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  backward_word: Move cursor one word bachward. Check for beginning
X//	 of text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::backward_word ()
X{
X  if (check_selection (False, False))	// if selection on, swith it off
X    ;
X  buffer->point_backward_word ();
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  next_line: Move cursor one line down (on screen and in buffer).
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::next_line ()
X{
X  if (check_selection (False, True))	// if selection on, swith it off
X    show_point ();
X
X  if ((last_func != UFNextLine) && (last_func != UFPrevLine))
X    screen_column = screen->column;
X
X  if (buffer->point_down(screen_column))
X    show_point ();
X  else
X    info->warning ("End of text", "");
X}
X
X// -------------------------------------------------------------------------
X//  previous_line: Move cursor one line up (on screen and in buffer).
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::previous_line ()
X{
X  if (check_selection (False, False))	// if selection on, swith it off
X    show_point ();
X
X  if ((last_func != UFNextLine) && (last_func != UFPrevLine))
X    screen_column = screen->column;
X
X  if (buffer->point_up(screen_column))
X    show_point ();
X  else
X    info->warning ("Beginning of text", "");
X}
X
X// -------------------------------------------------------------------------
X//  scroll_line_down: Scroll view window on line down.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_line_down ()
X{
X  if (blanklines > 0) {
X    info->warning ("End of text","");
X    return;
X  }
X
X  if (!forward_screenline (top))	// move display down one screen line
X    assert (False);
X  display ();
X}
X
X// -------------------------------------------------------------------------
X//  scroll_line_up:  Scroll view window on line up.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_line_up ()
X{
X  if (!backward_screenline (top))	// move display up one screen line
X    info->warning ("Beginning of text","");
X  else
X    display ();
X}
X
X// -------------------------------------------------------------------------
X//  scroll_half_page_down:
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_half_page_down ()
X{
X  int lines = screen->lines / 2;
X
X  if (blanklines > 0) {
X    info->warning ("End of text","");
X    return;
X  }
X
X  while (lines-- > 0) {
X    if (!forward_screenline (top))
X      break;
X    display ();
X  }
X}
X
X// -------------------------------------------------------------------------
X//  scroll_half_page_up: 
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_half_page_up ()
X{
X  int lines = screen->lines / 2;
X
X  if ((top.line_no == 1) && (top.column == 0)) {
X    info->warning ("Beginning of text","");
X    return;
X  }
X
X  while (lines-- > 0) {
X    if (!backward_screenline (top))
X      break;
X    display ();
X  }
X}
X
X// -------------------------------------------------------------------------
X//  next_page: Move view window one page down.  Keep cursor on screen.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::next_page ()
X{
X  int lines;
X
X  if (blanklines > 0) {
X    info->warning ("End of text","");
X    return;
X  }
X
X  lines = screen->lines-2;
X
X  while (lines-- > 0)
X    if (!forward_screenline (top))
X      assert (False);
X  display ();
X}
X
X// -------------------------------------------------------------------------
X//  previous_page: Move view window one page up.  Keep cursor on screen.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::previous_page ()
X{
X  int lines;
X
X  if ((top.line_no == 1) && (top.column == 0)) {
X    info->warning ("Beginning of text","");
X    return;
X  }
X
X  lines = screen->lines-2;
X
X  while ( lines-- > 0)
X    if (!backward_screenline (top))
X      break;
X  display ();
X}
X
X// -------------------------------------------------------------------------
X//  scroll_drag: Called when scollbar slider is draged to a new value. Set
X//	top line to the according line number and display the text from 
X//	there.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::scroll_drag (int value)
X{
X  while (value > top.line_no)
X    buffer->next_line (top);
X  while (value < top.line_no)
X    buffer->prev_line (top);
X  display ();
X}
X
X// -------------------------------------------------------------------------
X//  beginning_of_line: Set cursor to the beginning of the current line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::beginning_of_line ()
X{
X  if (check_selection (False, False))	// if selection on, swith it off
X    ;
X  buffer->point_to_bol ();
X  show_point ();
X}
X  
X// -------------------------------------------------------------------------
X//  end_of_line: Set cursor to the end of the current line.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::end_of_line ()
X{
X  if (check_selection (False, True))	// if selection on, swith it off
X    ;
X  buffer->point_to_eol ();
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  beginning_of_text: Set cursor to the beginning of the text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::beginning_of_text ()
X{
X  if (check_selection (False,False))	// make sure selection is off
X    ;
X  set_mark ();
X  buffer->point_to_bob ();
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  end_of_text: Set cursor to the end of the text.
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::end_of_text ()
X{
X  if (check_selection (False,True))	// make sure selection is off
X    ;
X  set_mark ();
X  buffer->point_to_eob ();
X  show_point ();
X}
X
X// -------------------------------------------------------------------------
X//  cursor_to: set cursor to coordinates on screen
X// -------------------------------------------------------------------------
X
Xvoid EDITOR::cursor_to (int screen_x, int screen_y)
X{
X  if (buffer->selection_on)
X    toggle_selection ();
X 
X  screen->cursor_on (True);
X  set_point_to_square (screen_x, screen_y);
X  place_cursor_on_screen ();
X}
X
X// -------------------------------------------------------------------------
X// -------------------------------------------------------------------------
X
XBoolean EDITOR::forward_screenline (BUFFERPOS& pos)
X{
X  int length, ln=0, col;
X  char* str;
X
X  buffer->get_text_in_line (pos.line, pos.column, str, length);
X  col = screen->square_to_index (str, length, ln, 0, 1);
X
X  if (col == -1) {			// next screenline not in line
X    if (buffer->is_last (pos.line))
X      return False;
X    else {
X      buffer->next_line (pos);
X    }
X  }
X  else
X    pos.column += col;
X  return True;
X}
X
X// -------------------------------------------------------------------------
X//  backward_screenline: Set pos to the position that is one line above it 
X//	on the screen. For short lines that means: set it to the beginning
X//	of the previous line. For long line the position that appears in
X//	column 0 on the screen has to be calculated.
X//	Pos has to be a position that is in screen column 0. (This function
X//	is normally used for 'top'.)
X// -------------------------------------------------------------------------
X
XBoolean EDITOR::backward_screenline (BUFFERPOS& pos)
X{
X  int lines, stln=0, ln=0, col, length;
X  char* str;
X
X  if (pos.column == 0)			// we are at a beginning of a line, so
X    if (buffer->is_top (pos.line))	//  find last screen line in prev line
X      return False;
X    else {
X      buffer->prev_line (pos);		// to beginning of prev. line
X      buffer->get_text_in_line (pos.line, 0, str, length);
X      lines = screen->nr_of_lines (str, length, 0);
X      if (lines != 1)
X	pos.column = screen->square_to_index (str, length, stln, 0, lines-1);
X    }
X  else {
X    buffer->get_text_in_line (pos.line, 0, str, length);
X    screen->index_to_square (str, pos.column, ln, col, False);
X    assert ((ln>0) && (col==0));
X    pos.column = screen->square_to_index (str, length, stln, 0, ln-1);
X  }
X  return True;
X}
SHAR_EOF
  $shar_touch -am 0512222696 'Red/Red/editor_move.i' &&
  chmod 0640 'Red/Red/editor_move.i' ||
  echo 'restore of Red/Red/editor_move.i failed'
  shar_count="`wc -c < 'Red/Red/editor_move.i'`"
  test 10232 -eq "$shar_count" ||
    echo "Red/Red/editor_move.i: original size 10232, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= Red/Red/finder.cc ==============
if test -f 'Red/Red/finder.cc' && test X"$1" != X"-c"; then
  echo 'x - skipping Red/Red/finder.cc (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting Red/Red/finder.cc (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Red/Red/finder.cc' &&
X// ============================================================================
SHAR_EOF
  : || echo 'restore of Red/Red/finder.cc failed'
fi
echo 'End of archive part 5'
echo 'File Red/Red/finder.cc is continued in part 6'
echo 6 > _sharseq.tmp
exit 0


