001: /*
002: * GotoFile.java
003: *
004: * Copyright (C) 1998-2002 Peter Graves
005: * $Id: GotoFile.java,v 1.1.1.1 2002/09/24 16:09:17 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import gnu.regexp.RE;
025: import gnu.regexp.REMatch;
026: import gnu.regexp.UncheckedRE;
027: import java.awt.AWTEvent;
028: import java.awt.event.MouseEvent;
029:
030: public final class GotoFile implements Constants {
031: public static void gotoFile() {
032: final Editor editor = Editor.currentEditor();
033:
034: // If this method is invoked via a mouse event mapping, move dot to
035: // location of mouse click first.
036: AWTEvent event = editor.getDispatcher().getLastEvent();
037: if (event instanceof MouseEvent)
038: editor.mouseMoveDotToPoint((MouseEvent) event);
039:
040: String filename = gotoFileGetFileName(editor);
041: if (filename == null)
042: return;
043: int lineNumber = -1;
044:
045: // See if there's a line number at the end of the filename.
046: int index = filename.lastIndexOf(" line ");
047: if (index >= 0) {
048: // "test.pl line 3"
049: try {
050: lineNumber = Integer.parseInt(filename
051: .substring(index + 6)) - 1;
052: // Shorten filename to exclude line number.
053: filename = filename.substring(0, index);
054: } catch (NumberFormatException e) {
055: // Not a valid number.
056: }
057: } else {
058: index = filename.lastIndexOf(':');
059: if (index >= 0) {
060: // "Position.java:140"
061: try {
062: lineNumber = Integer.parseInt(filename
063: .substring(index + 1)) - 1;
064: // Shorten filename to exclude line number.
065: filename = filename.substring(0, index);
066: } catch (NumberFormatException e) {
067: // Not a valid number.
068: }
069: }
070: }
071:
072: boolean tryCurrentDirectory = true;
073:
074: if (filename.length() >= 2 && filename.charAt(0) == '<'
075: && filename.charAt(filename.length() - 1) == '>') {
076: // We'll only get the angle brackets if we're in C or C++ mode.
077: // Strip the angle brackets and don't look for the file in the
078: // current directory.
079: filename = filename.substring(1, filename.length() - 1);
080: tryCurrentDirectory = false;
081: }
082:
083: File file = null;
084:
085: if (Utilities.isFilenameAbsolute(filename)) {
086: file = File.getInstance(editor.getCurrentDirectory(),
087: filename);
088: } else {
089: // The filename is not absolute.
090: if (tryCurrentDirectory)
091: // Try current directory first.
092: file = File.getInstance(editor.getCurrentDirectory(),
093: filename);
094:
095: // Try source and include paths if applicable.
096: if (file == null || (file.isLocal() && !file.exists()))
097: file = Utilities.findFile(editor, filename);
098: }
099:
100: if (file != null) {
101: Buffer buf = editor.getBuffer(file);
102: if (buf != null) {
103: final Frame frame = editor.getFrame();
104: editor.makeNext(buf);
105: editor.switchToBuffer(buf);
106: // Switching buffers might have closed the original editor.
107: Editor ed = frame.contains(editor) ? editor : frame
108: .getCurrentEditor();
109: if (ed.getBuffer() == buf) {
110: if (lineNumber >= 0) {
111: if (ed.getDot() != null) {
112: if (ed.getDotLineNumber() != lineNumber) {
113: ed.addUndo(SimpleEdit.MOVE);
114: ed.unmark();
115: ed.gotoline(lineNumber);
116: ed.moveCaretToDotCol();
117: }
118: }
119: }
120: ed.updateDisplay();
121: }
122: }
123: }
124: }
125:
126: private static String gotoFileGetFileName(Editor editor) {
127: if (editor.getDot() == null)
128: return null;
129: final Line dotLine = editor.getDotLine();
130: final int dotOffset = editor.getDotOffset();
131: if (editor.getMark() != null && editor.getMarkLine() == dotLine) {
132: // Use selection.
133: return new Region(editor).toString();
134: }
135: final int modeId = editor.getModeId();
136: if (modeId == HTML_MODE) {
137: RE re = new UncheckedRE("(href|src)=\"([^\"]+)\"",
138: RE.REG_ICASE);
139: REMatch match = null;
140: final String text = dotLine.getText();
141: int index = 0;
142: REMatch m;
143: while ((m = re.getMatch(text, index)) != null) {
144: match = m;
145: if (match.getEndIndex() > dotOffset)
146: break; // All subsequent matches will be further away.
147: index = match.getEndIndex();
148: }
149: if (match != null)
150: return match.toString(2);
151: } else if (modeId == JAVA_MODE) {
152: String fileName = getFileNameFromImport(editor.getBuffer(),
153: dotLine.getText());
154: if (fileName != null)
155: return fileName;
156: } else if ((modeId == C_MODE || modeId == CPP_MODE)) {
157: String fileName = getFileNameFromInclude(dotLine.getText());
158: if (fileName != null)
159: return fileName;
160: } else if (editor.getBuffer().getType() == Buffer.TYPE_SHELL) {
161: String s = dotLine.getText().trim();
162: REMatch match = Directory.getNativeMoveToFilenameRegExp()
163: .getMatch(s);
164: if (match != null)
165: return s.substring(match.getEndIndex());
166: }
167: return editor.getFilenameAtDot();
168: }
169:
170: private static String getFileNameFromImport(Buffer buffer, String s) {
171: if (s.indexOf('*') >= 0)
172: return null;
173: s = s.trim();
174: if (!s.startsWith("import"))
175: return null;
176: s = s.substring(6);
177: if (s.length() == 0)
178: return null;
179: if (s.charAt(0) != ' ' && s.charAt(0) != '\t')
180: return null;
181: s = s.trim();
182: FastStringBuffer sb = new FastStringBuffer();
183: for (int i = 0; i < s.length(); i++) {
184: char c = s.charAt(i);
185: if (c == ' ' || c == '\t' || c == ';')
186: break;
187: sb.append(c);
188: }
189: File file = JavaSource.findSource(buffer, sb.toString(), true);
190: return file != null ? file.canonicalPath() : null;
191: }
192:
193: private static final RE includeRE = new UncheckedRE(
194: "[ \t]*#[ \t]*include[ \t]");
195:
196: private static final String getFileNameFromInclude(String s) {
197: REMatch match = includeRE.getMatch(s);
198: if (match == null)
199: return null;
200: s = s.substring(match.getEndIndex()).trim();
201: // Need at least one char plus quotes or angle brackets.
202: if (s.length() < 3)
203: return null;
204: char c = s.charAt(0);
205: if (c == '"') {
206: int index = s.indexOf('"', 1);
207: if (index >= 0)
208: return s.substring(1, index);
209: return null;
210: }
211: if (c == '<') {
212: int index = s.indexOf('>', 1);
213: if (index >= 0)
214: return s.substring(0, index + 1); // Include angle brackets.
215: }
216: return null;
217: }
218: }
|