/*
   A very simple text editor window, which
   I implemented just to demo AlphaDraw. - Ken
*/

import java.awt.*;

public class TextEditor
{
   public TextEditor() {
      for (int i = 0 ; i < msg.length ; i++)
         msg[i] = "";
   }

   // PUBLIC METHODS

   public int stringWidth(Graphics g, String s) {
      return g.getFontMetrics(g.getFont()).stringWidth(s);
   }

   public void setBounds(int w, int h) { W = w; H = h; }

   public void render(Graphics g) {
      this.g = g;
      g.setColor(Color.red);
      int _cursor = Math.min(cursor, msg[line].length());
      int cx = stringWidth(g, msg[line].substring(0,_cursor));
      g.drawString("|", cx-1, 20 + 20 * line);

      g.setColor(Color.black);
      for (int l = 0 ; l < msg.length ; l++)
         for (int i = 0 ; i < msg[l].length() ; i++) {
	    boolean isSelected = 
	       l > sl1 && l < sl2 ||
               sl1 < sl2 && (l == sl1 && i >= sc1  ||
                             l == sl2 && i <  sc2) ||
               sl1 == sl2 && l == sl1 && i >= sc1 && i < sc2;
            String s = "" + msg[l].charAt(i);
	    int x = 5 + stringWidth(g,msg[l].substring(0,i));
	    int y = 20 + 20 * l;
            if (isSelected) {
               g.setColor(selectedColor);
	       g.fillRect(x, y-14, stringWidth(g,s), 20);
               g.setColor(Color.black);
            }
            g.drawString(s, x, y);
         }
   }

   public void placeCursor(int x, int y) {
      isOverText(x,y);
      if (line == xyLine && cursor == xyCursor)
         selectWord();  
      line = xyLine;
      cursor = xyCursor;
   }

   public boolean hasSelection() {
      return sl1 != sl2 || sc1 != sc2;
   }

   public void select(int x1, int y1, int x2, int y2) {
      isOverText(x1, y1); int sla = xyLine, sca = xyCursor;
      isOverText(x2, y2); int slb = xyLine, scb = xyCursor;
      if (sla == slb) {
         sl1 = sl2 = sla;
	 sc1 = Math.min(sca, scb);
	 sc2 = Math.max(sca, scb);
      }
      else if (sla < slb) {
	 sl1 = sla; sc1 = sca;
	 sl2 = slb; sc2 = scb;
      }
      else {
         sl1 = slb; sc1 = scb;
         sl2 = sla; sc2 = sca;
      }
   }

   public boolean isOverText(int x, int y) {
      boolean isTrue = false;
      xyLine = (y-5) / 20;
      String m = msg[xyLine];
      if (stringWidth(g, m) > x)
         for (xyCursor = 0 ; xyCursor < m.length() ; xyCursor++)
            if (stringWidth(g, m.substring(0,xyCursor+1)) > x) {
	       isTrue = true;
	       break;
            }
      return isTrue;
   }

   public void copy() {
      copyToCutBuffer();

      sl1 = sl2 = sc1 = sc2 = 0;
   }

   public void cut() {
      copyToCutBuffer();

      msg[sl1] = msg[sl1].substring(0,sc1) +
                 msg[sl2].substring(sc2, msg[sl2].length());
      for (int l = sl2+1 ; l < msg.length ; l++)
	 msg[l-(sl2-sl1)] = msg[l];
      if (line > sl1)
         line -= sl2 - sl1;
      else if (cursor > sc1)
         cursor = sc1;

      sl1 = sl2 = sc1 = sc2 = 0;
   }

   public void paste() {
      enterText(cutBuffer);
   }

   public void enterText(String s) {
      for (int i = 0 ; i < s.length() ; i++)
         enterChar(s.charAt(i));
   }

   // INTERNAL METHODS

   void copyToCutBuffer() {
      if (sl1 == sl2)
         cutBuffer = msg[sl1].substring(sc1,sc2);
      else {
         cutBuffer = msg[sl1].substring(sc1,msg[sl1].length()) + "\n";
         for (int l = sl1+1 ; l < sl2 ; l++)
	    cutBuffer += msg[l] + "\n";
         cutBuffer += msg[sl2].substring(0,sc2);
      }
   }

   void selectWord() {
      sl1 = line;
      for (sc1 = cursor ; sc1 >= 1 &&
                          ! isSpace(msg[sl1].charAt(sc1-1)) ; sc1--)
          ;

      sl2 = line;
      for (sc2 = cursor ; sc2 < msg[sl2].length() &&
                          ! isSpace(msg[sl2].charAt(sc2)) ; sc2++)
          ;
      for ( ; sc2 < msg[sl2].length() &&
              isSpace(msg[sl2].charAt(sc2)) ; sc2++)
          ;
   }

   boolean isSpace(int c) { return c == ' '; }

   void enterChar(int c) {
      switch (c) {
      case '\b': // BACKSPACE
         deleteChar();
         break;
      case '\n': // NEWLINE
         insertNewline();
	 break;
      case 1004: // UP ARROW
         cursorUp();
         break;
      case 1005: // DOWN ARROW
         cursorDown();
         break;
      case 1006: // LEFT ARROW
         cursorLeft();
         break;
      case 1007: // RIGHT ARROW
         cursorRight();
         break;
      case 27: // ESCAPE
         System.out.println("ESCAPE");
         break;
      case '\t': // TAB
         System.out.println("TAB");
         break;
      default:
         cursor = Math.min(cursor, msg[line].length());
         msg[line] = msg[line].substring(0,cursor) + (char)c +
                     msg[line].substring(cursor,msg[line].length());
         cursor++;
      }
   }


   void deleteChar() {
      cursor = Math.min(cursor, msg[line].length());
      if (msg[line].length() > 0 && cursor > 0) {
         msg[line] = msg[line].substring(0,cursor-1) +
                     msg[line].substring(cursor, msg[line].length());
         cursor--;
      }
      else if (line > 0) {
         line--;
         cursor = msg[line].length();
	 msg[line] = msg[line] + msg[line+1];
	 for (int l = line+1 ; l < msg.length-1 ; l++)
	    msg[l] = msg[l+1];
      }
   }
   void insertNewline() {
      for (int l = msg.length-1 ; l > line ; l--)
         msg[l] = msg[l-1];
      msg[line+1] = msg[line].substring(cursor, msg[line].length());
      msg[line] = msg[line].substring(0,cursor);
      line++;
      cursor = 0;
   }
   void cursorUp() {
      if (line > 0)
         line--;
   }
   void cursorDown() {
      if (line < msg.length)
         line++;
   }
   void cursorLeft() {
      if (cursor > 0)
         cursor--;
      else if (line > 0) {
         line--;
         cursor = msg[line].length();
      }
   }
   void cursorRight() {
      if (cursor < msg[line].length())
         cursor++;
      else if (line < msg.length) {
         line++;
         cursor = 0;
      }
   }




   String msg[] = new String[100];
   int line = 0, cursor = 0;
   String cutBuffer = "";
   Color selectedColor = new Color(200,200,200);
   Graphics g;
   int W, H;
   int sl1 = 0, sc1 = 0, sl2 = 0, sc2 = 0;
   int xyLine, xyCursor;
}


