📄 swedit.java
字号:
/* * @(#)SWediT.java 1.02 2004-04-19 * * Copyright (c) 2002, 2003, 2004 by James D. Ingraham. All Rights Reserved. * * The SWediT License is detailed below. Search for SweditLicense or * "SWEDIT LICENSE" to view the license. Alternately, you may have received * a copy of license.txt which contains the license information, or if you run * SWediT you can choose "License" from the Help menu. * */import java.io.*; import java.util.*;import org.eclipse.swt.*;import org.eclipse.swt.custom.*;import org.eclipse.swt.graphics.*;import org.eclipse.swt.widgets.*;import org.eclipse.swt.layout.*;import org.eclipse.swt.events.*;//=============================================================================/* SWediT is a minamilist text editor. The build and run requirements are fairlysimple; you must have Java development software compliant with J2SE 1.2 or later. You must have SWT (the Standard Widget Toolkit) from Eclipse.org. Tocompile you must have swt.jar in your classpath. To run, you must also have the shared library associated with swt.jar, generally a file called swt-win32-xxxx.dll on Windows or libswt-photon-xxxx.so on QNX Neutrino / Photon.With any luck, more information is available at swedit.sourceforge.netIf you see a comment with %%% in it, that's a flag that work needs to be donenear that comment. This is a simple thing to search for when trying to thinkof the next thing to work on.*///=============================================================================public final class SWediT implements VerifyKeyListener, ModifyListener, LineStyleListener, LineBackgroundListener, ShellListener {//============================================================================= // Global variables // SWT links everything to a display private static Display display = new Display(); // Keys-to-commands mapping private static Map keys = new HashMap(); // Individual text buffers private static Vector buffers = new Vector(); // Names associated with SWT constatns for keys, e.g. SWT.BS is "Backspace" private static Map keyNames = new HashMap(); private StyledText editor; // The actual text editor area private Shell shell; // SWT shell (think of a window) private Menu bar; // The Pull-down Menu bar private MenuItem linePos; // Line position is shown on the menu bar private MenuItem colPos; // Column position is shown on the menu bar private boolean changed; // Remember that the text has changed private boolean dosFormat; // File should be saved in DOS format? private boolean dosFormatDefault; // Files should default to DOS format? private Stack history; // Undo stack private Stack rehistory; // Redo stack private int currentBuffer; // Tracks the current buffer private String filename; // File name for the current buffer private boolean quitFlag; // Signal to quit the program private boolean cancelFlag; // For returning a cancel from dialogues private int numUntitled; // The number of untitled docs opened this session private String searchString; // Current search text; used in findNext private int lastColumn; // Column to place cursor in private boolean expandTabs; // Expand tabs into spaces automatically? private boolean askAboutTabs; // Ask what to do with tabs while loading a file? private int syndex; // Index to syntax highlighting record private String[] block; // Block cut, copy, and paste text private int blockStart; // Starting index of the block selection private int blockHeight; // Height of the block selection private int blockWidth; // Width of the block selection private Properties props; // The properties requested by the user private boolean debugMode; // Debug Mode displays extra data when exceptions occur private SweditColors colors; // Colors to use for syntax highlighting private boolean configLoaded; // Was a configuration file loaded? private SweditLicense sweditLicenseDialog; private PrintKeyMap printKeyMapDialog;//============================================================================= // Main does nothing but call the default constructor, which does all the work public static void main(String [] args) { SWediT swedit = new SWediT(args); }//============================================================================= // Default constructor, where everything happens. SWediT(String[] args) { // Initialize the global variables history = new Stack(); rehistory = new Stack(); searchString = new String(""); currentBuffer = -1; quitFlag = false; numUntitled = 1; lastColumn = 1; block = null; // Check for command line arguments. Anything besides "-p" is a filename // to be edited. String[] filenames = new String[args.length]; int filecount = 0; String propsFilename = null; // Go through the list of command line arguments for(int i=0; i < args.length; i++){ // a -p signifies the name of the properties (config) file to use if(args[i].equals("-p")){ // The NEXT argument is the properties file name i++; // Make sure the user didn't put a -p with nothing after it if(i < args.length){ propsFilename = args[i]; } }else if(args[i].startsWith("-p")){ // If the user didn't put a space, chop off the -p propsFilename = args[i].substring(2); }else{ filenames[filecount] = args[i]; filecount++; } } loadProperties(propsFilename); // Load the properties file first // Colors are referenced to a display, so they have to be loaded at runtime colors = new SweditColors(display); // Create the shell, which is the connection between Java and the GUI shell = new Shell(display); // Set the text on title bar to the name of the program shell.setText("SWediT - Untitled"); // Set the shell's layout to a FillLayout shell.setLayout(new FillLayout()); // Set up the size of the shell, in pixles // %%% Size shouldn't be greater than the current res. Remember the last setting? int width = 640; int height = 480; try{ height = Integer.parseInt(props.getProperty("Window_Height", "480")); }catch (Exception e){ exceptionMessage("Exception Parsing Window_Height Property: \n" + e); } try{ width = Integer.parseInt(props.getProperty("Window_Width", "640")); }catch (Exception e){ exceptionMessage("Exception Parsing Window_Width Property: \n" + e); } shell.setSize(width, height); // Set up the license and key map dialogs sweditLicenseDialog = new SweditLicense(); printKeyMapDialog = new PrintKeyMap(); // Create a new Menu bar for the shell bar = new Menu(shell, SWT.BAR); shell.setMenuBar(bar); setupMenu(); // create the styled text widget with scroll bars editor = new StyledText(shell, SWT.V_SCROLL | SWT.H_SCROLL); // Check all key strokes in the verifyKey method the SWediT class editor.addVerifyKeyListener(this); // Notice when text has changed editor.addModifyListener(this); // Update style when text has been redrawn editor.addLineStyleListener(this); // Update line background color editor.addLineBackgroundListener(this); // The font must be a fixed width font, of reasonable size // %%% Support other fonts besides Courier? int fontSize = 12; try{ fontSize = Integer.parseInt(props.getProperty("Font_Size", "12")); }catch (Exception e){ exceptionMessage("Exception Parsing Window_Width Property: \n" + e); } editor.setFont(new Font(display, "Courier", fontSize, SWT.NORMAL)); // Set the tab size try{ int tabsize = Integer.parseInt(props.getProperty("Tab_Size", "2")); editor.setTabs(tabsize); }catch(Exception e){ exceptionMessage("Exception Parsing Tab_Size Property: \n" + e); editor.setTabs(2); } // Really, SWediT only cares about a Close command so that files can be // saved before exiting, but there are 4 additional methods besides the // shellClosed method in the ShellListener interface. shell.addShellListener(this); // Prep the key stroke data setupKeyNames(keyNames); setupKeyMap(); // If filenames were passed, try to load them. boolean loaded=false; for (int i=0; i < filecount; i++){ if(load(filenames[i])){ loaded = true; } } if (!loaded){ // The editor always expects at least one buffer filename = new String("Untitled"); buffers.add(new Buffer("", filename, 0, 0, false, new Stack(), expandTabs, dosFormatDefault)); currentBuffer = 0; } // Get the property for Start Maximized shell.setMaximized( Boolean.valueOf(props.getProperty("Start_Maximized", "true")).booleanValue()); // Get this party started! shell.open(); // Standard SWT code while (!shell.isDisposed()) { if (!display.readAndDispatch()){ display.sleep(); } } // Don't forget to free things up. display.dispose(); } // End of constructor//============================================================================= // Handles a quit command from the OS, such as clicking the "X" box in the // top right or Alt-F4 public void shellClosed(ShellEvent e){ // Run the quit command runCommand(new SweditQuit()); // Don't let the command go through, since quit has already disposed the shell. e.doit = false; } // End of shellClosed//============================================================================= // Not used; needed if implementing ShellListener interface public void shellActivated(ShellEvent e){ } // Not used; needed if implementing ShellListener interface public void shellDeactivated(ShellEvent e){ } // Not used; needed if implementing ShellListener interface public void shellDeiconified(ShellEvent e){ } // Not used; needed if implementing ShellListener interface public void shellIconified(ShellEvent e){ }//============================================================================= // Remember that the text has changed so the app won't quit without saving public void modifyText(ModifyEvent modEvent){ if (history.empty()){ changed = false; }else{ changed = true; } }//============================================================================= // Syntax higlighting. lineGetStyle is part of SWT's LineStyleListener // interface, which works with the StyledText widget. // %%% Multi-line comments aren't handled // %%% Performance? public void lineGetStyle(LineStyleEvent styleEvent){ // Since the block selection can be anywhere anytime, figure out if this // line has a portion of the block selection int startBlockCol=-1, endBlockCol=-1; int blockLine = editor.getLineAtOffset(blockStart); int thisLine = editor.getLineAtOffset(styleEvent.lineOffset); if ((thisLine >= blockLine) && (thisLine < (blockLine + blockHeight))){ startBlockCol = blockStart - editor.getOffsetAtLine(blockLine); startBlockCol += styleEvent.lineOffset; endBlockCol = startBlockCol + blockWidth; } // Check if the buffer has a valid syntax for highlighting if ((syndex < 0) || (syndex >= Syntax.extensions.length)){ // If there's no block comment then there is nothing to do. if ((blockHeight <= 0) || (blockWidth <= 0) || (blockStart < 0)){ return; } // Find the start and end of the line currently being redisplayed int start = styleEvent.lineOffset; int end = start + styleEvent.lineText.length(); // If the block selection doesn't go through this line there is nothing to do if ((startBlockCol >= end) || (start >= endBlockCol)){ return; } // The styleEvent wants an array of StyleRanges, but we know there's only 1 StyleRange[] style = new StyleRange[1]; style[0] = new StyleRange(); style[0].background = colors.block; style[0].foreground = colors.normal; // The startBlockCol (as calculated above) can never be less than the // start of the line, and we've already checked to see if it's passed the // end so start position is easy. Length is easy because when block // selecting the code pads spaces onto the end of lines, so the blockWidth // will never be passed the end of the line. style[0].start = startBlockCol; style[0].length = blockWidth; // Set the style for the line. styleEvent.styles = style; // Nothing else to do. return; } // Loop through each character in the line of text, creating styles to // match what's found int start=0; // Always begin at the beginning ArrayList ranges = new ArrayList(); String text = styleEvent.lineText; // text could be modified, so use a temp var while (start < text.length()){ // Go through the whole line. int end = 0; // Everytime through reset the end position String word; // Current "unit" of text found int i; // counter char currChar = text.charAt(start); // Get the current character StyleRange style = new StyleRange(); // Create a style // %%% Multi-line comment highlighting Integer offsetInteger = new Integer(styleEvent.lineOffset); if (false){ end = text.indexOf("*/", start) + 2; if (end < 2){ end = text.length(); } style.foreground = colors.comment; style.start = start + styleEvent.lineOffset; style.length = end - start; // Single (' ') and double (" ") quotes }else if ((currChar == '\"') || (currChar == '\'')){ end = start + 1; boolean ignore=false; if (start > 0){ // Ignore quotes that are preceeded by a backslash if (text.charAt(start - 1) == '\\'){ ignore = true; } } if (!ignore){ // A rare do-while loop. I'm open to suggestions on how to invert it // Go until a closing quote is found that is not preceeded by a backslash do{ // Find the index of the next occuring quote (currChar remembers if // it's a single or double quote) end = text.indexOf(currChar, end) + 1; // indexOf() returns -1 if the character is not found; the +1 above // makes it 0. If not found, use the end of line and break out. if (end == 0){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -