BufferWriter.java :  » Scripting » Kawa » gnu » jemacs » buffer » Java Open Source

Java Open Source » Scripting » Kawa 
Kawa » gnu » jemacs » buffer » BufferWriter.java
package gnu.jemacs.buffer;
import java.awt.Color;

/** A Writer that writes at a Buffer's point or a Marker. */

public class BufferWriter extends java.io.Writer implements Runnable
{
  Marker marker;
  Object style;
  Object stylePlain;
  boolean adjustPoint;

  /** We are not handling escape sequences. */
  static final int NO_ESCAPES_STATE = 1;
  /** We are ready to handle escape sequences. */
  static final int NORMAL_STATE = 0;
  /** Last character was a graphic in the last column.
   * If next char is graphic, first move one column right
   * (and line warp) before displaying it. */
  static final int LAST_COLUMN_STATE = 1;
  /** Seen an Escape character. */
  static final int SEEN_ESC_STATE = 2;
  /** We're in the middle of an escape sequence.
   * What we've seen so far is in the savedOutput buffer. */
  static final int SEEN_ESC_LBRAC_STATE = 3;
  static final int SEEN_ESC_RBRAC_STATE = 4;
  int state = NORMAL_STATE;

  static final int ESC = 033;

  boolean insertMode = false;

  char[] savedOutput;
  int savedCount;

  public BufferWriter (Marker marker, boolean adjustPoint)
  {
    this.marker = marker;
    EToolkit toolkit = EToolkit.getInstance();
    this.stylePlain = toolkit.getFace("output", true);
    this.style = stylePlain;
    this.adjustPoint = adjustPoint;
    // StyleConstants.setItalic(this.style, true);
  }

  public BufferWriter (Buffer buffer)
  {
    this(buffer.pointMarker, false);
  }

  boolean bold = false;
  boolean underline = false;
  boolean blink = false;  // not implemented
  boolean inverse;
  boolean invisible;
  String foregroundName;
  String backgroundName;
  Color foreground;
  Color background;
  StringBuffer styleNameBuf;
  String styleName;

  void resetAttributes()
  {
    bold = false;
    underline = false;
    blink = false;
    inverse = false;
    invisible = false;
    foregroundName = null;
    backgroundName = null;
    foreground = null;
    background = null;
  }

  void updateStyle()
  {
    if (styleNameBuf == null)
      styleNameBuf = new StringBuffer(60);
    styleNameBuf.setLength(0);
    if (underline) styleNameBuf.append("underlined,");
    if (bold) styleNameBuf.append("bold,");
    if (foreground != null)
      {
  styleNameBuf.append("fg=");
  styleNameBuf.append(foregroundName != null ? foregroundName
          : foreground.toString());
  styleNameBuf.append(',');
      }
    if (background != null)
      {
  styleNameBuf.append("bg=");
  styleNameBuf.append(backgroundName != null ? backgroundName
          : background.toString());
  styleNameBuf.append(',');
      }
    int slen = styleNameBuf.length();
    if (slen == 0)
      {
  style = stylePlain;
  styleName = "output";
  return;
      }
    styleNameBuf.setLength(slen-1); // Remove final comma.
    styleName = styleNameBuf.toString();
    EToolkit toolkit = EToolkit.getInstance();
    style = toolkit.getFace(styleName, false);
    if (style != null)
      return;
    style = toolkit.getFace(styleName, true);
    toolkit.setUnderline(style, underline);
    toolkit.setBold(style, bold);
    if (foreground != null)
      toolkit.setForeground(style, foreground);
    if (background != null)
      toolkit.setBackground(style, background);
  }

  private String name;
  private Color color;
  private void getColor(int index, boolean bright /*ignored, for now*/)
  {
    switch (index)
      {
      case 0:  color = Color.black;   name = "black";   break;
      case 1:  color = Color.red;     name = "red";     break;
      case 2:  color = Color.green;   name = "green";   break;
      case 3:  color = Color.yellow;  name = "yellow";  break;
      case 4:  color = Color.blue;    name = "blue";    break;
      case 5:  color = Color.magenta; name = "magenta"; break;
      case 6:  color = Color.cyan;    name = "cyan";    break;
      case 7:  color = Color.white;   name = "white";   break;
      default: color = null;          name = null;
      }
  }

  /**
   * Process an SGR command with the given code.
   * @param param parameter value from the escape sequence
   * @param position following offset in savedOutput array
   * @return updated value of position, if we gobble multiple parameters
   */
  public int handleSetCharacterRendition(int param, int position)
  {
    switch (param)
      {
      case -1: case 0:
  resetAttributes();
      case 1:
  bold = true;
  break;
      case 4:
  underline = true;
  break;
      case 22:
  bold = false;
  break;
      case 24:
  underline = false;
  break;
      default:
  if (param >= 30 && param <= 39)
    {
      getColor(param - 30, false);
      foreground = color;
      foregroundName = name;
    }
  else if (param >= 40 && param <= 49)
    {
      getColor(param - 40, false);
      background = color;
      backgroundName = name;
    }
  else if (param >= 90 && param <= 97)
    {
      getColor(param - 90, true);
      background = color;
      backgroundName = name;
    }
  else if (param >= 100 && param <= 107)
    {
      getColor(param - 100, true);
      background = color;
      backgroundName = name;
    }
  // else ignore
      }
    return position;
  }

  public void handleOperatingSystemCommand(char ch)
  {
    if (ch == '\007') /* BEL */
      {
  // ignore, for now
  state = NORMAL_STATE;
      }
    else if (savedCount >= savedOutput.length)
      {
  // Seems rather excessive ...  Probably error.
  int i;
  for (i = 0;  i < savedCount && savedOutput[i] != '\n';) i++;
  if (i < savedCount || ch == '\n')
    state = NORMAL_STATE; // Seen '\n' - OK time to bail.
  else
    savedCount = 0;  // No '\n' yet - drop what we've seen so far.
      }
    else
      savedOutput[savedCount++] = ch;
  }

  /**
   * Process a single command following CSI.
   * CSI is "Control Sequence Introducer" - i.e. ESC [.
   * @param ch the control command
   * @param param parameter value from the escape sequence
   * @param position following offset in savedOutput array
   * @return updated value of position, if we gobble multiple parameters
   */
  public int handleCSICommand(char ch, int param, int position)
  {
    switch (ch)
      {
      case 'C':  // \E[C - cursor right
  moveColumns(param > 0 ? param : 1);
  break;
      case 'D':  // \E[D - cursor left
  moveColumns(- (param > 0 ? param : 1));
  break;
      case 'h':  // \E[?h - DEC Private Mode Set
  if (param == 4)
    insertMode = true;
  break;
      case 'l':  // \E[?l - DEC Private Mode Reset
  if (param == 4)
    insertMode = false;
  break;
      case 'm':
  return handleSetCharacterRendition(param, position);
      }
    return position;
  }

  public void handleEscapeBracket(char ch)
  {
    if (ch == ';' || (ch >= '0' && ch <= '9'))
      {
  if (savedCount >= savedOutput.length)
    savedCount = 0;  // Overflow - drop excess parameters.
  savedOutput[savedCount++] = ch;
      }
    else
      {
  int value = -1;
  for (int i = 0;  i < savedCount;  i++)
    {
      ch = savedOutput[i];
      if (ch >= '0' && ch <= '9')
        value = (value <= 0 ? 0 : 10 * value) + (ch - '0');
      else
        {
    i = handleCSICommand('m', value, i);
    value = -1;
        }
    }
  handleCSICommand('m', value, savedCount);
  updateStyle();
  state = NORMAL_STATE;
      }
  }

  public void unTabifyRestOfLine()
  {
    // FIXME
  }

  /** Delete characters - but only in current screen line. */
  public void removeChars(int count)
  {
    int save = marker.getOffset();
    moveColumns(count);
    marker.removeChar(marker.getOffset() - save);
  }

  /** Move some number of columns right (or left if count < 0). */
  public void moveColumns(int count)
  {
    marker.moveToColumn(marker.currentColumn() + count, true);
  }

  /*
  public synchronized void put(int x)
  {
    if (insertMode)
      unTabifyRestOfLine();
    else if (marker.getOffset() < marker.buffer.maxDot())
      removeChars(1);
    AbstractDocument document = marker.buffer;
    boolean mustAdjustPoint
      = adjustPoint && marker.getOffset() == marker.buffer.getDot();
    marker.insert((char) x, 1, x == '\n' ? stylePlain : style);
    if (mustAdjustPoint)
      marker.buffer.setDot(marker.getOffset());
  }
  */

  public synchronized void put (char[] data, int off, int len)
  {
    if (len == 0)
      return;
    if (insertMode)
      unTabifyRestOfLine();
    else
      removeChars(len);
    boolean mustAdjustPoint
      = adjustPoint && marker.getOffset() == marker.buffer.getDot();
    marker.insert(new String(data, off, len), style);
    if (mustAdjustPoint)
      marker.buffer.setDot(marker.getOffset());
  }

  char[] buf1 = new char[1];

  public synchronized void write(int ch)
  {
    boolean move = marker.getOffset() == marker.buffer.getDot();
    write1(ch);
    if (move) marker.buffer.setDot(marker.getOffset());
  }

  public synchronized void write1(int ch)
  {
    if (state <= NORMAL_STATE)
      {
  if (ch >= ' ' || ch == '\n' || state < NORMAL_STATE)
    {
      buf1[0] = (char) ch;
      put(buf1, 0, 1);
    }
  else if (ch == ESC)
    state = SEEN_ESC_STATE;
  else if (ch == '\b')
    moveColumns(-1);
  else if (ch == '\t')
    {
      int col = marker.currentColumn();
      marker.moveToColumn(col + 8 - (col & 7), true);
    }
  else if (ch == '\r')
    {
      // FIXME - until we handle '\n' more generally.
      // marker.moveToColumn(0, false);
    }
  else
    System.err.println("received ctrl-"+(char)(ch+64));
      }
    else if (state == SEEN_ESC_STATE)
      {
  switch (ch)
    {
    case '[':
      state = SEEN_ESC_LBRAC_STATE;
      if (savedOutput == null)
        savedOutput = new char[100];
      savedCount = 0;
      break;
    case ']':
      state = SEEN_ESC_RBRAC_STATE;
      if (savedOutput == null)
        savedOutput = new char[100];
      savedCount = 0;
      break;
    default:
      state = NORMAL_STATE;
      break;
    }
      }
    else if (state == SEEN_ESC_LBRAC_STATE)
      {
  handleEscapeBracket((char) ch);
      }
    else /* if (state == SEEN_ESC_RBRAC_STATE) */
      {
  handleOperatingSystemCommand((char) ch);
      }
  }

  public synchronized void write (char[] data, int off, int len)
  {
    boolean move = marker.getOffset() == marker.buffer.getDot();
    while (len > 0)
      {
  if (state > NORMAL_STATE)
    {
      write1(data[off++]);
      len--;
    }
  else
    {
      int i;
      if (state == NO_ESCAPES_STATE)
        i = len;
      else
        {
    for (i = 0;  i < len;  i++)
      {
        char ch = data[off+i];
        if (ch < ' ')
          break;
      }
        }
      if (i > 0)
        {
    put(data, off, i);
    off += i;
    len -= i;
        }
      if (i < len)
        {
    write1(data[off++]);
    len--;
        }
    }
      }
    if (move) marker.buffer.setDot(marker.getOffset());
  }

  public synchronized void flush()
  {
  }

  public synchronized void close()
  {
  }

  char[] buffer;
  int count;
  public void run()
  {
    write(buffer, 0, count);
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.