From: SVN by r. <sv...@ca...> - 2009-01-25 13:59:51
|
Author: roy Date: 2009-01-25 14:59:44 +0100 (Sun, 25 Jan 2009) New Revision: 366 Modified: src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java Log: a lot of jcurses fixes.. still on some system jcurses works very well.... Modified: src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java =================================================================== --- src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2009-01-25 13:58:39 UTC (rev 365) +++ src/main/java/nl/improved/sqlclient/jcurses/SQLShellWindow.java 2009-01-25 13:59:44 UTC (rev 366) @@ -1,184 +1,255 @@ /* - * Copyright 2008 Roy van der Kuil (ro...@va...) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * To change this template, choose Tools | Templates + * and open the template in the editor. */ + package nl.improved.sqlclient.jcurses; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import jcurses.system.CharColor; import jcurses.system.InputChar; import jcurses.system.Toolkit; +import jcurses.widgets.DefaultLayoutManager; import jcurses.widgets.PopUpMenu; import jcurses.widgets.Window; +import jcurses.widgets.TextComponent; +import jcurses.widgets.WidgetsConstants; import nl.improved.sqlclient.AbstractSQLShellWindow; import nl.improved.sqlclient.InputKey; import nl.improved.sqlclient.Point; -import nl.improved.sqlclient.Screen; import nl.improved.sqlclient.SQLCommand; +import nl.improved.sqlclient.Screen; /** - * SQLShell window based on the jcurses library. - * @see http://jcurses.sourceforge.net/ + * The sqlshell window implementation for jcurses. * @author roy */ public class SQLShellWindow extends AbstractSQLShellWindow { - private Window window; - private boolean dontRepaint = false; - private boolean repaint = true; - private String debugString; + private SQLShellTextComponent textComponent; + private OutputStream debugOut; + private Window sqlShell; - private final Object lockObject = new Object(); - /** - * Default constructor. + * Constructor. + * @param textComponent the text component for rendering the text */ public SQLShellWindow() { + textComponent = new SQLShellTextComponent(); + /*this.textComponent = new TextComponent() { + + @Override + protected boolean handleInput(InputChar arg0) { + //return super.handleInput(arg0); + debug("handle input: "+ toInputKey(arg0)); + SQLShellWindow.this.handleInput(toInputKey(arg0)); + //return super.handleInput(arg0); + doPaint(); + return true; + } + + };*/ + try { + File tmpFile = File.createTempFile("jcurses", ".out"); + tmpFile.deleteOnExit(); + debugOut = new FileOutputStream(tmpFile); + } catch (IOException ex) { + Logger.getLogger(SQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + } } - /** - * Return the screen width. - * @return the screen width. - */ + private InputKey toInputKey(InputChar inputChar) { + if (inputChar.isSpecialCode()) { + if (inputChar.getCode() == InputChar.KEY_BACKSPACE) { + return new InputKey(InputKey.SpecialKey.BACKSPACE); + } + if (inputChar.getCode() == InputChar.KEY_DC) { + return new InputKey(InputKey.SpecialKey.DELETE); + } + if (inputChar.getCode() == InputChar.KEY_NPAGE) { + return new InputKey(InputKey.SpecialKey.PAGE_DOWN); + } + if (inputChar.getCode() == InputChar.KEY_PPAGE) { + return new InputKey(InputKey.SpecialKey.PAGE_UP); + } + if (inputChar.getCode() == InputChar.KEY_LEFT) { + return new InputKey(InputKey.SpecialKey.LEFT); + } + if (inputChar.getCode() == InputChar.KEY_RIGHT) { + return new InputKey(InputKey.SpecialKey.RIGHT); + } + if (inputChar.getCode() == InputChar.KEY_DOWN) { + return new InputKey(InputKey.SpecialKey.DOWN); + } + if (inputChar.getCode() == InputChar.KEY_UP) { + return new InputKey(InputKey.SpecialKey.UP); + } + if (inputChar.getCode() == InputChar.KEY_HOME) { + return new InputKey(InputKey.SpecialKey.HOME); + } + if (inputChar.getCode() == InputChar.KEY_END) { + return new InputKey(InputKey.SpecialKey.END); + } + return new InputKey(InputKey.SpecialKey.UNKNOWN); + } + return new InputKey(inputChar.getCharacter()); + } + @Override public int getScreenWidth() { return Toolkit.getScreenWidth(); } - /** - * Return the screen height. - * @return the screen height. - */ @Override public int getScreenHeight() { - return Toolkit.getScreenHeight(); + return Toolkit.getScreenHeight()-1; } /** - * Write a debug string. - * @param debug the debug to output + * Force repaint of the screen. */ - @Override - public void debug(String debug) { - debugString = debug; - repaint = true; + void repaintScreen() { + paint(getScreen()); } - - /** - * Set the window to be visible. - */ - public void show() { - if (window == null) { - window = new Window(getScreenWidth(), getScreenHeight(), true, "SQLShell") { - @Override - protected void handleInput(InputChar inputChar) { - SQLShellWindow.this.handleInput(toInputKey(inputChar)); - } - /** - * Paint the screen. - */ - @Override - protected synchronized void paint() { - SQLShellWindow.this.repaint(); - } - - private InputKey toInputKey(InputChar inputChar) { - if (inputChar.isSpecialCode()) { - if (inputChar.getCode() == InputChar.KEY_BACKSPACE) { - return new InputKey(InputKey.SpecialKey.BACKSPACE); - } - if (inputChar.getCode() == InputChar.KEY_DC) { - return new InputKey(InputKey.SpecialKey.DELETE); - } - if (inputChar.getCode() == InputChar.KEY_NPAGE) { - return new InputKey(InputKey.SpecialKey.PAGE_DOWN); - } - if (inputChar.getCode() == InputChar.KEY_PPAGE) { - return new InputKey(InputKey.SpecialKey.PAGE_UP); - } - if (inputChar.getCode() == InputChar.KEY_LEFT) { - return new InputKey(InputKey.SpecialKey.LEFT); - } - if (inputChar.getCode() == InputChar.KEY_RIGHT) { - return new InputKey(InputKey.SpecialKey.RIGHT); - } - if (inputChar.getCode() == InputChar.KEY_DOWN) { - return new InputKey(InputKey.SpecialKey.DOWN); - } - if (inputChar.getCode() == InputChar.KEY_UP) { - return new InputKey(InputKey.SpecialKey.UP); - } - if (inputChar.getCode() == InputChar.KEY_HOME) { - return new InputKey(InputKey.SpecialKey.HOME); - } - if (inputChar.getCode() == InputChar.KEY_END) { - return new InputKey(InputKey.SpecialKey.END); - } - return new InputKey(InputKey.SpecialKey.UNKNOWN); + @Override + public void paint(final Screen screen) { + if (screen.getPageUpCount() > 0) { + paintSlow(screen); + return; + } + int totalLineCount = 0; + final StringBuilder newText = new StringBuilder(); + final List<String> commandLines = formatCommandLines(screen.getShowPrompt() + , screen.getEmptyLine(),(List<CharSequence>) getCommand().getLines()); + for (int i = 0; i < commandLines.size(); i++) { + CharSequence seq = commandLines.get(i); + newText.append(seq.toString()); + if (i < commandLines.size()-1) { + newText.append("\n"); + } + totalLineCount++; + } + if (totalLineCount > getScreenHeight()-1) { + totalLineCount = getScreenHeight()-1; + } + int restLines = (getScreenHeight() -1) - totalLineCount; + if (restLines > 0) { + ArrayList<SQLCommand> commandList = new ArrayList<SQLCommand>(getUnprocessedCommands()); + Collections.reverse(commandList); + commandList: for (SQLCommand command : commandList) { + List<? extends CharSequence> lines = command.getLines(); + for (int i = lines.size() -1; i >=0; i--) { + newText.insert(0, lines.get(i) +"\n"); + restLines--; + totalLineCount++; + if(restLines == 0) { + break; } - return new InputKey(inputChar.getCharacter()); } - }; + } } - window.setVisible(true); - // repaint loop - while (isRunning()) { - Screen screen = getScreen(); - if (!dontRepaint && repaint) { - try { - synchronized(this) { - paintImpl(screen); - } - } catch(Throwable t) { - error(t); + if (restLines > 0) { + List<CharSequence> buffer = new ArrayList<CharSequence>(screen.getScreenBuffer()); + for (int i = buffer.size() -1; i>=0; i--) { + newText.insert(0, buffer.get(i)+"\n"); + restLines--; + totalLineCount++; + if(restLines == 0) { + break; } } - try { - synchronized(lockObject) { - lockObject.wait(1000); + } + + textComponent.setText(newText.toString(), true); + new Thread() { + + @Override + public void run() { + if (textComponent != null && textComponent.isVisible()) { + textComponent.draw(); } - } catch (InterruptedException ex) { - /* ignore */ } + + }.start(); + } + public void paintSlow(final Screen screen) { + int totalLineCount = 0; + StringBuilder newText = new StringBuilder(); + for (CharSequence seq: new ArrayList<CharSequence>(screen.getScreenBuffer())) { + newText.append(seq.toString()); + newText.append("\n"); + totalLineCount++; } - super.close(); - //window.close(); - window.hide(); - window.close(); + for (SQLCommand s : new ArrayList<SQLCommand>(getUnprocessedCommands())) { + for (CharSequence seq: s.getLines()) { + newText.append(screen.getEmptyLine().substring(0, Screen.PROMPT.length()) + ">"); + newText.append(seq.toString()); + newText.append("\n"); + totalLineCount++; + } + } + final List<String> commandLines = formatCommandLines(screen.getShowPrompt() + , screen.getEmptyLine(),(List<CharSequence>) getCommand().getLines()); + for (int i = 0; i < commandLines.size(); i++) { + CharSequence seq = commandLines.get(i); + newText.append(seq.toString()); + if (i < commandLines.size()-1) { + newText.append("\n"); + } + totalLineCount++; + } + if (totalLineCount > getScreenHeight()-1) { + totalLineCount = getScreenHeight()-1; + } + final int lineCount = totalLineCount; + final String trimmed = trim(newText, screen.getPageUpCount()); + textComponent.setText(trimmed); +/* Point cursorPos = screen.getCursorPosition(); + try { + int start = textComponent.getLineStartOffset(lineCount - (commandLines.size() - cursorPos.y)); + textComponent.setCaretPosition(start + cursorPos.x + (Screen.PROMPT+" >").length()); + } catch(Exception e) { + debug("ERROR: failed to calculate line end: "+ lineCount +"-"+ cursorPos.y +"/"+ getScreenHeight()); + } + textComponent.draw();*/ + // TODO } - /** - * Close the window. - */ @Override public void close() { - /* - super.close(); - window.close(); - */ + super.close(); + sqlShell.close(); + // TODO } - /** - * Shows a popupwindow to allow the user to make a selection from the list of possible matches. - * @param items the list of possible matches - * @param p the character x/y location to show the popupscreen on - */ @Override + public void beep() { + Toolkit.beep(); + } + + @Override + public void debug(String debug) { + if (debugOut != null) { + try { + debugOut.write((debug + "\n").getBytes()); + } catch (IOException ex) { + Logger.getLogger(SQLShellWindow.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + @Override public String select(List<String> items, Point p) { try { PopUpMenu menu = new PopUpMenu(p.x,Math.max(2, p.y-items.size()), "Find match"); @@ -186,114 +257,18 @@ while (iMatches.hasNext()) { menu.add(iMatches.next()); } - dontRepaint = true; + //dontRepaint = true; menu.show(); return menu.getSelectedItem(); } finally { - dontRepaint = false; + //dontRepaint = false; } } - /** - * Paint the screen. - * @param screen the screen information to be painted - */ @Override - public void paint(Screen screen) { - if (isRunning()) { - repaint = true; - synchronized(lockObject) { - lockObject.notify(); - } - } - } - - /** - * Actual implementation of the paint screen method. - * This is different from the normal paint method since this will only - * (and should be) called from the main thread to overcome painting errors. - * @param screen the screen to paint - */ - private void paintImpl(Screen screen) { - if (!isRunning()) { - return; - } - synchronized(lockObject) { - CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.BOLD, CharColor.BOLD); - - List<CharSequence> tmpList = clone(screen.getScreenBuffer()); - - //add prompt - List<SQLCommand> commandList = getUnprocessedCommands(); - //commandList.add(getCommand()); - boolean showPrompt = screen.getShowPrompt(); - for (SQLCommand commandLines : commandList) { - List<CharSequence> currentLines = clone((List<CharSequence>) commandLines.getLines()); - tmpList.addAll(formatCommandLines(showPrompt, screen.getEmptyLine(), currentLines)); - } - List<CharSequence> currentCommandLines = clone((List<CharSequence>) getCommand().getLines()); - tmpList.addAll(formatCommandLines(showPrompt, screen.getEmptyLine(), currentCommandLines)); - int startLine; - if (tmpList.size() > Toolkit.getScreenHeight()-1) { - startLine = tmpList.size() - (Toolkit.getScreenHeight()-1); - if (screen.getPageUpCount() > 0) { - startLine -= (screen.getPageUpCount() * Toolkit.getScreenHeight()/2); - if (startLine < 0) { - startLine = 0; - } - } - } else { - startLine = 0; - } - int lineNr; - for (lineNr = startLine;lineNr < tmpList.size() && lineNr - startLine < Toolkit.getScreenHeight()-1; lineNr++) { - CharSequence linePart = tmpList.get(lineNr); - String line = linePart.length() >= screen.getEmptyLine().length() ? linePart.toString() : linePart + screen.getEmptyLine().substring(linePart.length()); - Toolkit.printString(line - , 0, lineNr-startLine, color); - } - for (int lNr = lineNr; lNr < Toolkit.getScreenHeight(); lNr++) { - Toolkit.printString(screen.getEmptyLine(), 0, lNr, color); - } - - // paint cursor - color = new CharColor(CharColor.BLACK, CharColor.WHITE, CharColor.REVERSE, CharColor.REVERSE); - String cursorChar = " "; - Point cursorPosition = screen.getCursorPosition(); - //SQLCommand commandLines = getCommand(); - if (currentCommandLines.size() > 0) { - String tmp = currentCommandLines.get(cursorPosition.y).toString(); - if (cursorPosition.x < 0) { - debug("Cursor position was: "+ cursorPosition +" fixing"); - cursorPosition.x = 0; - } - if (cursorPosition.x < tmp.length()) { - cursorChar = tmp.substring(cursorPosition.x, cursorPosition.x+1); - } - } - Toolkit.printString(cursorChar, Screen.PROMPT.length() +"> ".length() + cursorPosition.x, lineNr-(currentCommandLines.size() -cursorPosition.y)-startLine, color); - if (debugString != null) { - if (debugString.length() > Toolkit.getScreenWidth()) { - debugString = debugString.substring(0, Toolkit.getScreenWidth()-1); - } - color = new CharColor(CharColor.BLUE, CharColor.YELLOW); - Toolkit.printString(debugString, 1, getScreenHeight()-1, color); - } - repaint = false; - } - } - - /** - * Fetch the login detail information. - * @param username the default username - * @param password the default password - * @return the login credential string array - * @throws java.sql.SQLException - */ - @Override protected String[] getLoginCredentials(String username, String password) throws SQLException { LoginDialog diag = new LoginDialog(username, password); - dontRepaint = true; + //dontRepaint = true; try { diag.show(); if (!diag.endedSuccessfully()) { @@ -301,53 +276,73 @@ } return new String[] {diag.getUsername(), diag.getPassword() }; } finally { - dontRepaint = false; + //dontRepaint = false; } - } + } - /** - * Override to allow painting on the main thread to overcome painting errors. - */ - @Override - protected void repaint() { - if (isRunning()) { - repaint = true; - synchronized(lockObject) { - lockObject.notify(); + private String trim(StringBuilder text, int pageUpCount) { + String strText = text.toString(); + if (strText.indexOf('\n') < 0) { + return strText; + } + int maxHeight = getScreenHeight(); + String[] lines = strText.split("\n"); + if (lines.length <= maxHeight) { + return strText; + } + StringBuilder newString = new StringBuilder(); + int offset = Math.max(0, lines.length - ((pageUpCount +1) * maxHeight)); + boolean endsWithReturn = strText.endsWith("\n"); + for (int i = 0; i < maxHeight; i++) { + newString.append(lines[i+offset]); + if (i+offset < lines.length-1 || endsWithReturn) { + newString.append('\n'); } } + return newString.toString(); } - /** - * Beep. - */ - @Override - public void beep() { - Toolkit.beep(); + public void show() { + sqlShell = new Window(0, 0, Toolkit.getScreenWidth(), Toolkit.getScreenHeight(), false, "SQLShell") { + @Override + protected void handleInput(InputChar arg0) { + //super.handleInput(arg0); + //debug("WINDOW: handle input: "+ toInputKey(arg0)); + SQLShellWindow.this.handleInput(toInputKey(arg0)); + } + }; + + DefaultLayoutManager layout = (DefaultLayoutManager) sqlShell.getRootPanel().getLayoutManager(); + + layout.addWidget(textComponent, 0, 0, getScreenWidth(), getScreenHeight(), WidgetsConstants.ALIGNMENT_CENTER, WidgetsConstants.ALIGNMENT_CENTER); + repaintScreen(); + sqlShell.pack(); + sqlShell.show(); } - /** - * Clone a list of charsequence to make sure it isn't modified later (during paint). - * @param screenBuffer the screenBuffer to clone - * @return a cloned list of charsequence objects. - */ - private static List<CharSequence> clone(List<CharSequence> screenBuffer) { - List<CharSequence> result = new ArrayList<CharSequence>(screenBuffer.size()); - for(CharSequence cs : screenBuffer) { - result.add(cs.toString()); + public class SQLShellTextComponent extends TextComponent { + + public SQLShellTextComponent() { + setColors(new CharColor(CharColor.BLACK, CharColor.WHITE)); + setTextComponentColors(new CharColor(CharColor.BLACK, CharColor.WHITE)); } - return result; - } + public void draw() { + if (isVisible()) { + Point cursorPos = getScreen().getCursorPosition(); + setCursorLocation(cursorPos.x, cursorPos.y); + //doPaint(); + focus(); // repaints and paints cursor + } + } - public static void main(String[] args) { - SQLShellWindow shell = new SQLShellWindow(); - shell.show(); - //Interpret first argument as a connect argument -/* if (args.length > 0) { - shell.executeCommand(new InputCommand("connect "+args[0])); + @Override + protected boolean handleInput(InputChar arg0) { + //return super.handleInput(arg0); + //debug("handle input: "+ toInputKey(arg0)); + SQLShellWindow.this.handleInput(toInputKey(arg0)); + return true; } - */ - } + } } |