merge
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 21 Mar 2015 02:06:59 +0000 (22:06 -0400)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 21 Mar 2015 02:06:59 +0000 (22:06 -0400)
1  2 
README.md
src/jexer/TTerminalWindow.java

diff --combined README.md
index 570a0170c095aaf55cc2f6d15ef4ad13839f633f,ce707711f14c465735302502487b991dd234b186..746b1686b171904fea0def6e1652015e9561ad60
+++ b/README.md
@@@ -20,9 -20,8 +20,9 @@@ Two backends are available
  
  * Java AWT UI.  This backend can be selected by setting
    jexer.AWT=true.  This is the default backend on Windows platforms.
 -  AWT is VERY experimental, please consider filing bugs when you
 -  encounter them.
 +  AWT is experimental, please consider filing bugs when you encounter
 +  them.  The default window size for AWT is 132x40, which is set in
 +  jexer.session.AWTSession.
  
  A demo application showing the existing UI controls is available via
  'java -jar jexer.jar' or 'java -Djexer.AWT=true -jar jexer.jar' .
@@@ -87,13 -86,11 +87,14 @@@ ambiguous.  This section describes suc
    ---------------
  
    - TTerminalWindow will hang on input from the remote if the
-     TApplication is exited before closing the TTerminalWindow.  This
-     is due to a Java limitation/interaction between blocking reads
-     (necessary to get UTF8 translation correct) and file streams.
+     TApplication is exited before the TTerminalWindow's process has
+     closed on its own.  This is due to a Java limitation/interaction
+     between blocking reads (which is necessary to get UTF8 translation
+     correct) and file streams.
  
 +  - See jexer.tterminal.ECMA48 for more specifics of terminal
 +    emulation limitations.
 +
  
  Roadmap
  -------
@@@ -102,15 -99,22 +103,22 @@@ Many tasks remain before calling this v
  
  0.0.2:
  
+ - Making TMenu keyboard accelerators active/inactive
  - AWT:
    - Blinking cursor
 -  - Fix mouse artifacts
 +  - Handle kbTab (disable focus traversal BS)
+   - Block cursor
  - ECMA48Backend running on socket
  - TTreeView
  - TDirectoryList
  - TFileOpen
  - Decide on naming convention: getText, getValue, getLabel: one or all
    of them?
+ - Refactor:
+   - TKeypress:
+     - getCh() --> getChar()
+     - getAlt/getCtrl/getShift --> isAltDown / isCtrlDown / isShiftDown
+   - Other boolean getters --> isSomething
  
  0.0.3:
  
  
  - Bugs
    - TSubMenu keyboard mnemonic not working
-   - Making TMenu keyboard accelerators active/inactive
    - TDirectoryList cannot be navigated only with keyboard
    - TTreeView cannot be navigated only with keyboard
    - RangeViolation after dragging scrollbar up/down
index 336c3ff8db7cd19c2a6761f98469cc869f0b6b78,90a95ae132abdbd5360a06c535f57b0fac2965ef..010cc4993eaa139f5b67ad2a5dedac36f00b3e44
@@@ -36,7 -36,6 +36,7 @@@ import java.io.OutputStream
  import java.io.UnsupportedEncodingException;
  import java.util.LinkedList;
  import java.util.List;
 +import java.util.Map;
  
  import jexer.bits.Cell;
  import jexer.bits.CellAttributes;
@@@ -80,9 -79,6 +80,9 @@@ public class TTerminalWindow extends TW
  
          super(application, "Terminal", x, y, 80 + 2, 24 + 2, flags);
  
 +        // Assume XTERM
 +        ECMA48.DeviceType deviceType = ECMA48.DeviceType.XTERM;
 +
          try {
              String [] cmdShellWindows = {
                  "cmd.exe"
                  "script", "-fqe", "/dev/null"
              };
              // Spawn a shell and pass its I/O to the other constructor.
 +
              ProcessBuilder pb;
              if (System.getProperty("os.name").startsWith("Windows")) {
                  pb = new ProcessBuilder(cmdShellWindows);
              } else {
                  pb = new ProcessBuilder(cmdShell);
              }
 -            // shell = Runtime.getRuntime().exec(cmdShell);
 -
 -            // TODO: add LANG, TERM, LINES, and COLUMNS
 +            Map<String, String> env = pb.environment();
 +            env.put("TERM", ECMA48.deviceTypeTerm(deviceType));
 +            env.put("LANG", ECMA48.deviceTypeLang(deviceType, "en"));
 +            env.put("COLUMNS", "80");
 +            env.put("LINES", "24");
              pb.redirectErrorStream(true);
              shell = pb.start();
 -            emulator = new ECMA48(ECMA48.DeviceType.XTERM,
 -                shell.getInputStream(),
 +            emulator = new ECMA48(deviceType, shell.getInputStream(),
                  shell.getOutputStream());
          } catch (IOException e) {
              e.printStackTrace();
              List<DisplayLine> display = emulator.getDisplayBuffer();
  
              // Put together the visible rows
 -            // System.err.printf("----------------------------\n");
 -            // System.err.printf("vScroller.value %d\n", vScroller.getValue());
              int visibleHeight = getHeight() - 2;
 -            // System.err.printf("visibleHeight %d\n", visibleHeight);
              int visibleBottom = scrollback.size() + display.size()
                  + vScroller.getValue();
 -            // System.err.printf("visibleBottom %d\n", visibleBottom);
              assert (visibleBottom >= 0);
  
              List<DisplayLine> preceedingBlankLines = new LinkedList<DisplayLine>();
              int visibleTop = visibleBottom - visibleHeight;
 -            // System.err.printf("visibleTop %d\n", visibleTop);
              if (visibleTop < 0) {
                  for (int i = visibleTop; i < 0; i++) {
                      preceedingBlankLines.add(emulator.getBlankDisplayLine());
              List<DisplayLine> displayLines = new LinkedList<DisplayLine>();
              displayLines.addAll(scrollback);
              displayLines.addAll(display);
 -            // System.err.printf("displayLines.size %d\n", displayLines.size());
  
              List<DisplayLine> visibleLines = new LinkedList<DisplayLine>();
              visibleLines.addAll(preceedingBlankLines);
              visibleLines.addAll(displayLines.subList(visibleTop,
                      visibleBottom));
 -            // System.err.printf("visibleLines.size %d\n", visibleLines.size());
  
              visibleHeight -= visibleLines.size();
 -            // System.err.printf("visibleHeight %d\n", visibleHeight);
              assert (visibleHeight >= 0);
  
              // Now draw the emulator screen
       * Handle window close.
       */
      @Override public void onClose() {
-         emulator.close();
+         if (shell != null) {
+             shell.destroy();
+             shell = null;
+         } else {
+             emulator.close();
+         }
      }
  
      /**
                      setTitle(emulator.getScreenTitle());
                  }
              }
 -            setMaximumWindowWidth(emulator.getWidth() + 2);
  
              // Check to see if the shell has died.
              if (!emulator.isReading() && (shell != null)) {
          } // synchronized (emulator)
      }
  
 +    /**
 +     * Check if a mouse press/release/motion event coordinate is over the
 +     * emulator.
 +     *
 +     * @param mouse a mouse-based event
 +     * @return whether or not the mouse is on the emulator
 +     */
 +    private final boolean mouseOnEmulator(final TMouseEvent mouse) {
 +
 +        synchronized (emulator) {
 +            if (!emulator.isReading()) {
 +                return false;
 +            }
 +        }
 +
 +        if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1)
 +            && (mouse.getAbsoluteX() <  getAbsoluteX() + getWidth() - 1)
 +            && (mouse.getAbsoluteY() >= getAbsoluteY() + 1)
 +            && (mouse.getAbsoluteY() <  getAbsoluteY() + getHeight() - 1)
 +        ) {
 +            return true;
 +        }
 +        return false;
 +    }
 +
      /**
       * Handle keystrokes.
       *
       */
      @Override
      public void onMouseDown(final TMouseEvent mouse) {
 +        if (inWindowMove || inWindowResize) {
 +            // TWindow needs to deal with this.
 +            super.onMouseDown(mouse);
 +            return;
 +        }
  
          if (mouse.getMouseWheelUp()) {
              vScroller.decrement();
              vScroller.increment();
              return;
          }
 +        if (mouseOnEmulator(mouse)) {
 +            synchronized (emulator) {
 +                mouse.setX(mouse.getX() - 1);
 +                mouse.setY(mouse.getY() - 1);
 +                emulator.mouse(mouse);
 +                readEmulatorState();
 +                return;
 +            }
 +        }
  
 -        // Pass to children
 +        // Emulator didn't consume it, pass it on
          super.onMouseDown(mouse);
      }
  
 +    /**
 +     * Handle mouse release events.
 +     *
 +     * @param mouse mouse button release event
 +     */
 +    @Override
 +    public void onMouseUp(final TMouseEvent mouse) {
 +        if (inWindowMove || inWindowResize) {
 +            // TWindow needs to deal with this.
 +            super.onMouseUp(mouse);
 +            return;
 +        }
 +
 +        if (mouseOnEmulator(mouse)) {
 +            synchronized (emulator) {
 +                mouse.setX(mouse.getX() - 1);
 +                mouse.setY(mouse.getY() - 1);
 +                emulator.mouse(mouse);
 +                readEmulatorState();
 +                return;
 +            }
 +        }
 +
 +        // Emulator didn't consume it, pass it on
 +        super.onMouseUp(mouse);
 +    }
 +
 +    /**
 +     * Handle mouse motion events.
 +     *
 +     * @param mouse mouse motion event
 +     */
 +    @Override
 +    public void onMouseMotion(final TMouseEvent mouse) {
 +        if (inWindowMove || inWindowResize) {
 +            // TWindow needs to deal with this.
 +            super.onMouseMotion(mouse);
 +            return;
 +        }
 +
 +        if (mouseOnEmulator(mouse)) {
 +            synchronized (emulator) {
 +                mouse.setX(mouse.getX() - 1);
 +                mouse.setY(mouse.getY() - 1);
 +                emulator.mouse(mouse);
 +                readEmulatorState();
 +                return;
 +            }
 +        }
 +
 +        // Emulator didn't consume it, pass it on
 +        super.onMouseMotion(mouse);
 +    }
 +
  }