bufferwriter.java
来自「A framework written in Java for implemen」· Java 代码 · 共 443 行
JAVA
443 行
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); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?