001: /*
002: * WebBuffer.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: WebBuffer.java,v 1.9 2003/08/13 15:13:51 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 java.awt.AWTEvent;
025: import java.awt.Cursor;
026: import java.awt.Image;
027: import java.awt.Rectangle;
028: import java.awt.event.MouseEvent;
029: import java.io.InputStream;
030: import java.util.Hashtable;
031: import javax.swing.SwingUtilities;
032:
033: public final class WebBuffer extends Buffer implements WebConstants {
034: private String ref;
035: private WebHistory history;
036: private Hashtable refs;
037: private String contentType;
038: private String errorText;
039:
040: private WebBuffer(File file, File cache, String ref) {
041: super ();
042: setFile(file);
043: setCache(cache);
044: this .ref = ref;
045: init();
046: }
047:
048: private void init() {
049: initializeUndo();
050: type = TYPE_NORMAL;
051: forceReadOnly = true;
052: mode = Editor.getModeList().getMode(WEB_MODE);
053: formatter = new WebFormatter(this );
054: setInitialized(true);
055: }
056:
057: public final WebHistory getHistory() {
058: return history;
059: }
060:
061: public final void setHistory(WebHistory history) {
062: this .history = history;
063: }
064:
065: public final String getContentType() {
066: return contentType;
067: }
068:
069: public final void setContentType(String contentType) {
070: this .contentType = contentType;
071: }
072:
073: private int maxChars;
074:
075: private final int maxChars() {
076: if (maxChars == 0) {
077: Display display = Editor.currentEditor().getDisplay();
078: int charWidth = display.getCharWidth();
079: if (charWidth > 0)
080: maxChars = display.getWidth() / charWidth - 2;
081: else
082: maxChars = 80;
083: }
084: return maxChars;
085: }
086:
087: public Position getInitialDotPos() {
088: if (ref != null) {
089: Position pos = findRef(ref);
090: if (pos != null)
091: return pos;
092: }
093: return new Position(getFirstLine(), 0);
094: }
095:
096: public static void browse(Editor editor, File file, String ref) {
097: if (file == null)
098: return;
099: Buffer buf = null;
100: // Look for existing buffer.
101: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
102: Buffer b = it.nextBuffer();
103: if (b instanceof WebBuffer && b.getFile().equals(file)) {
104: buf = b;
105: break;
106: }
107: }
108: if (buf == null)
109: buf = createWebBuffer(file, null, ref);
110: editor.makeNext(buf);
111: editor.switchToBuffer(buf);
112: }
113:
114: public static WebBuffer createWebBuffer(File file, File cache,
115: String ref) {
116: return new WebBuffer(file, cache, ref);
117: }
118:
119: public Position findRef(String ref) {
120: if (ref != null && refs != null) {
121: Object obj = refs.get(ref);
122: if (obj instanceof Integer) {
123: Position pos = getPosition(((Integer) obj).intValue());
124: if (pos != null)
125: pos.skipWhitespace();
126: return pos;
127: }
128: }
129: return null;
130: }
131:
132: public static void viewPage() {
133: final Editor editor = Editor.currentEditor();
134: if (editor.getModeId() != HTML_MODE)
135: return;
136: final Buffer buffer = editor.getBuffer();
137: File file = buffer.getFile();
138: if (file == null)
139: return;
140: Buffer buf = null;
141: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
142: Buffer b = it.nextBuffer();
143: if (b instanceof WebBuffer && file.equals(b.getFile())) {
144: buf = b;
145: break;
146: }
147: }
148: if (buf == null) {
149: buf = WebBuffer.createWebBuffer(file, buffer.getCache(),
150: null);
151: ((WebBuffer) buf).setContentType("text/html");
152: }
153: editor.makeNext(buf);
154: editor.activate(buf);
155: }
156:
157: public static void viewSource() {
158: final Editor editor = Editor.currentEditor();
159: final Buffer buffer = editor.getBuffer();
160: if (!(buffer instanceof WebBuffer))
161: return;
162: final Line dotLine = editor.getDotLine();
163: File file = buffer.getFile();
164: Buffer buf = Editor.getBufferList().findBuffer(file);
165: if (buf == null)
166: buf = Buffer.createBuffer(file, buffer.getCache(), null);
167: if (buf != null) {
168: editor.makeNext(buf);
169: editor.activate(buf);
170: if (dotLine instanceof WebLine) {
171: int sourceOffset = ((WebLine) dotLine)
172: .getSourceOffset();
173: Position pos = buf.getPosition(sourceOffset);
174: editor.moveDotTo(pos);
175: }
176: }
177: }
178:
179: private boolean empty = true;
180:
181: public int load() {
182: if (getFirstLine() == null)
183: setText("");
184: setLoaded(true);
185: go(getFile(), 0, contentType);
186: return LOAD_COMPLETED;
187: }
188:
189: protected void loadFile(File localFile) {
190: WebLoader loader = new WebLoader(localFile);
191: LineSequence lines = loader.load();
192: if (lines != null) {
193: try {
194: lockWrite();
195: } catch (InterruptedException e) {
196: Log.debug(e);
197: return;
198: }
199: try {
200: setFirstLine(lines.getFirstLine());
201: setLastLine(lines.getLastLine());
202: renumberOriginal();
203: empty = false;
204: } finally {
205: unlockWrite();
206: }
207: }
208: refs = loader.getRefs();
209: final File file = getFile();
210: if (file != null && file.equals(localFile))
211: setLastModified(localFile.lastModified());
212: setLoaded(true);
213: }
214:
215: public Cursor getDefaultCursor(Position pos) {
216: if (pos != null && pos.getLine() instanceof WebLine) {
217: HtmlLineSegment segment = ((WebLine) pos.getLine())
218: .findSegment(pos.getOffset());
219: if (segment != null && segment.getLink() != null)
220: return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
221: }
222: return super .getDefaultCursor();
223: }
224:
225: public final int getMaximumColumns() {
226: return maxChars();
227: }
228:
229: public static void followLink() {
230: followLink(false);
231: }
232:
233: public static void mouseFollowLink() {
234: final Editor editor = Editor.currentEditor();
235: // If this method is invoked via a mouse event mapping, move dot to
236: // location of mouse click first.
237: AWTEvent e = editor.getDispatcher().getLastEvent();
238: if (e instanceof MouseEvent)
239: editor.mouseMoveDotToPoint((MouseEvent) e);
240: followLink(true);
241: }
242:
243: public static void followLink(boolean exact) {
244: final Editor editor = Editor.currentEditor();
245: final Buffer buffer = editor.getBuffer();
246: if (!(buffer instanceof WebBuffer))
247: return;
248: final WebBuffer wb = (WebBuffer) buffer;
249: if (wb.getFile() == null)
250: return;
251: final Line dotLine = editor.getDotLine();
252: if (!(dotLine instanceof WebLine))
253: return;
254:
255: final File historyFile = wb.getFile();
256: final int historyOffset = wb.getAbsoluteOffset(editor.getDot());
257: final String historyContentType = wb.getContentType();
258:
259: final int dotOffset = editor.getDotOffset();
260:
261: Link link = null;
262: HtmlLineSegment segment = ((WebLine) dotLine)
263: .findSegment(dotOffset);
264: if (segment != null)
265: link = segment.getLink();
266: if (link == null) {
267: if (exact)
268: return;
269: segment = findLink(dotLine, dotOffset);
270: if (segment == null)
271: return;
272: link = segment.getLink();
273: }
274: if (link == null)
275: return;
276: Debug.assertTrue(link == segment.getLink());
277: final String target = link.getTarget();
278: if (target == null) {
279: Debug.bug("target is null");
280: return;
281: }
282: if (target.startsWith("mailto:")) {
283: MessageDialog.showMessageDialog(editor,
284: "Sorry, mailto URLs are not yet supported.",
285: "Sorry...");
286: return;
287: }
288:
289: int index = target.indexOf('#');
290: if (index == 0) {
291: // It's a fragment identifier referring to a location in the same
292: // buffer.
293: Position pos = wb.findRef(target.substring(1));
294: if (pos != null) {
295: wb.saveHistory(historyFile, historyOffset,
296: historyContentType);
297: editor.moveDotTo(pos);
298: editor.setUpdateFlag(REFRAME);
299: }
300: return;
301: }
302:
303: String filename;
304: String ref = null;
305: if (index >= 0) {
306: filename = target.substring(0, index);
307: ref = target.substring(index + 1);
308: } else
309: filename = target;
310:
311: final File destination = resolve(wb.getFile().getParentFile(),
312: filename);
313:
314: if (destination.equals(wb.getFile())) {
315: Position pos = wb.findRef(ref);
316: if (pos != null) {
317: wb.saveHistory(historyFile, historyOffset,
318: historyContentType);
319: editor.moveDotTo(pos);
320: }
321: return;
322: }
323:
324: final HtmlLineSegment theSegment = segment;
325: final Link theLink = link;
326: if (destination instanceof HttpFile) {
327: final String theRef = ref;
328: final HttpLoadProcess httpLoadProcess = new HttpLoadProcess(
329: wb, (HttpFile) destination);
330: Runnable successRunnable = new Runnable() {
331: public void run() {
332: final String contentType = httpLoadProcess
333: .getContentType();
334: Log.debug("content-type = " + contentType);
335: boolean isImage = false;
336: if (contentType != null
337: && contentType.toLowerCase().startsWith(
338: "image/"))
339: isImage = true;
340: else {
341: String extension = Utilities
342: .getExtension(destination);
343: if (extension != null) {
344: extension = extension.toLowerCase();
345: if (extension.equals(".jpg")
346: || extension.equals(".gif")
347: || extension.equals(".png"))
348: isImage = true;
349: }
350: }
351: if (isImage) {
352: if (theLink instanceof ImageLink) {
353: ImageLoader loader = new ImageLoader(
354: httpLoadProcess.getCache());
355: java.awt.Image image = loader.loadImage();
356: if (image != null)
357: wb.insertImage(editor, dotLine,
358: theSegment, image);
359: } else {
360: // Normal link.
361: // BUG!! This isn't right either. We should display the image in
362: // the current buffer.
363: ImageBuffer buf = ImageBuffer
364: .createImageBuffer(destination,
365: httpLoadProcess.getCache(),
366: null);
367: editor.makeNext(buf);
368: editor.activate(buf);
369: editor.updateDisplay();
370: }
371: return;
372: }
373: if (wb.loadLocalFile(httpLoadProcess.getCache(),
374: contentType, httpLoadProcess.getCache()
375: .getEncoding())) {
376: wb.saveHistory(historyFile, historyOffset,
377: historyContentType);
378: wb.setFile(httpLoadProcess.getFile());
379: wb.setCache(httpLoadProcess.getCache());
380: Position pos = null;
381: if (theRef != null)
382: pos = wb.findRef(theRef);
383: if (pos == null)
384: pos = new Position(wb.getFirstLine(), 0);
385: wb.update(pos);
386: }
387: for (EditorIterator it = new EditorIterator(); it
388: .hasNext();) {
389: Editor ed = it.nextEditor();
390: if (ed != null && ed.getBuffer() == wb)
391: ed.setDefaultCursor();
392: }
393: }
394: };
395: ErrorRunnable errorRunnable = new ErrorRunnable(
396: "Operation failed") {
397: public void run() {
398: Log.debug("followLink errorRunnable.run");
399: String errorText = httpLoadProcess.getErrorText();
400: if (errorText == null || errorText.length() == 0)
401: errorText = "Unable to load "
402: + destination.netPath();
403: setMessage(errorText);
404: super .run();
405: }
406: };
407: httpLoadProcess.setSuccessRunnable(successRunnable);
408: httpLoadProcess.setErrorRunnable(errorRunnable);
409: httpLoadProcess
410: .setProgressNotifier(new StatusBarProgressNotifier(
411: wb));
412: editor.setWaitCursor();
413: new Thread(httpLoadProcess).start();
414: } else {
415: // Local file.
416: String extension = Utilities.getExtension(destination);
417: if (extension != null) {
418: extension = extension.toLowerCase();
419: if (extension.equals(".jpg")
420: || extension.equals(".gif")
421: || extension.equals(".png")) {
422: if (theLink instanceof ImageLink) {
423: ImageLoader loader = new ImageLoader(
424: destination);
425: java.awt.Image image = loader.loadImage();
426: if (image != null)
427: wb.insertImage(editor, dotLine, theSegment,
428: image);
429: } else {
430: // BUG!! Should display image in same buffer.
431: ImageBuffer buf = ImageBuffer
432: .createImageBuffer(destination, null,
433: null);
434: editor.makeNext(buf);
435: editor.activate(buf);
436: editor.updateDisplay();
437: }
438: return;
439: }
440: }
441: if (wb.loadLocalFile(destination)) {
442: wb.saveHistory(historyFile, historyOffset,
443: historyContentType);
444: wb.setFile(destination);
445: wb.setCache(null);
446: Position pos = null;
447: if (ref != null)
448: pos = wb.findRef(ref);
449: if (pos == null)
450: pos = new Position(wb.getFirstLine(), 0);
451: wb.update(pos);
452: }
453: }
454: }
455:
456: public static HtmlLineSegment findLink(Line line, int offset) {
457: HtmlLineSegment segment = null;
458: if (line instanceof WebLine) {
459: LineSegmentList segmentList = ((WebLine) line)
460: .getSegmentList();
461: if (segmentList != null) {
462: int where = 0;
463: final int size = segmentList.size();
464: for (int i = 0; i < size; i++) {
465: HtmlLineSegment seg = (HtmlLineSegment) segmentList
466: .getSegment(i);
467: if (seg.getLink() != null) {
468: if (segment == null || where < offset)
469: segment = seg;
470: }
471: where += seg.length();
472: if (where > offset && segment != null)
473: break;
474: }
475: }
476: }
477: return segment;
478: }
479:
480: private static File resolve(File base, String fileName) {
481: while (fileName.startsWith("../")) {
482: File parent = base.getParentFile();
483: if (parent != null) {
484: base = parent;
485: fileName = fileName.substring(3);
486: } else
487: break;
488: }
489: // Strip any remaining (i.e. bogus) lead dots.
490: while (fileName.startsWith("../")) {
491: fileName = fileName.substring(3);
492: }
493: return File.getInstance(base, fileName);
494: }
495:
496: // BUG!! Optimize this - containsImageLine flag
497: public int getDisplayHeight() {
498: int height = 0;
499: for (Line line = getFirstLine(); line != null; line = line
500: .nextVisible())
501: height += line.getHeight();
502: return height;
503: }
504:
505: private void insertImage(final Editor editor, final Line line,
506: final HtmlLineSegment segment, final Image image) {
507: final int imageHeight = image.getHeight(null);
508: if (imageHeight == 0)
509: return;
510:
511: LineSegmentList segments = ((WebLine) line).getSegmentList();
512: segments.removeSegment(segment);
513:
514: // Force next call to line.getText() to enumerate the segments again.
515: line.setText(null);
516:
517: Line before;
518: if (line.isBlank() && line.previous() != null) {
519: // Current line is blank. Put image in its place.
520: before = line.previous();
521: } else {
522: // Put image after current line.
523: before = line;
524: }
525:
526: final int lineHeight = new TextLine("").getHeight();
527: final int imageWidth = image.getWidth(null);
528: Line dotLine = null;
529: for (int y = 0; y < imageHeight; y += lineHeight) {
530: Rectangle r = new Rectangle(0, y, imageWidth, Math.min(
531: lineHeight, imageHeight - y));
532: ImageLine imageLine = new ImageLine(image, r);
533: imageLine.insertAfter(before);
534: before = imageLine;
535: if (dotLine == null)
536: dotLine = imageLine;
537: }
538: renumber();
539: Debug.assertTrue(dotLine != null);
540: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
541: Editor ed = it.nextEditor();
542: if (ed.getBuffer() == this ) {
543: ed.getDot().moveTo(dotLine, 0);
544: ed.setMark(null); // Enforce sanity.
545: ed.setUpdateFlag(REFRAME | REPAINT);
546: ed.updateDisplay();
547: }
548: }
549: }
550:
551: public void saveHistory(File historyFile, int historyOffset,
552: String historyContentType) {
553: if (history == null)
554: history = new WebHistory();
555: else
556: history.truncate();
557: history.append(historyFile, historyOffset, historyContentType);
558: history.reset();
559: }
560:
561: private boolean loadLocalFile(File localFile) {
562: return loadLocalFile(localFile, "text/html");
563: }
564:
565: private boolean loadLocalFile(File localFile, String contentType) {
566: return loadLocalFile(localFile, contentType, null);
567: }
568:
569: private boolean loadLocalFile(File localFile, String contentType,
570: String encoding) {
571: // Look for Unicode byte order mark. If we find it, use it to
572: // determine the encoding.
573: InputStream inputStream;
574: try {
575: inputStream = localFile.getInputStream();
576: } catch (Exception e) {
577: Log.error(e);
578: errorText = "File not found";
579: return false; // File not found.
580: }
581: byte[] buf = new byte[2];
582: try {
583: int bytesRead = inputStream.read(buf);
584: inputStream.close();
585: if (bytesRead == 2) {
586: byte byte1 = buf[0];
587: byte byte2 = buf[1];
588: if (byte1 == (byte) 0xfe && byte2 == (byte) 0xff)
589: encoding = "UnicodeBig";
590: else if (byte1 == (byte) 0xff && byte2 == (byte) 0xfe)
591: encoding = "UnicodeLittle";
592: }
593: } catch (Exception e) {
594: Log.error(e);
595: return false;
596: }
597: try {
598: inputStream = localFile.getInputStream();
599: } catch (Exception e) {
600: Log.error(e);
601: errorText = "File not found";
602: return false; // File not found.
603: }
604: boolean isHtml = false;
605: if (contentType != null) {
606: if (contentType.toLowerCase().startsWith("text/html"))
607: isHtml = true;
608: } else {
609: if (Editor.getModeList().modeAccepts(HTML_MODE,
610: localFile.getName()))
611: isHtml = true;
612: }
613: try {
614: lockWrite();
615: } catch (InterruptedException e) {
616: Log.debug(e);
617: return false;
618: }
619: try {
620: empty();
621: if (isHtml) {
622: loadFile(localFile);
623: setContentType(contentType);
624: setFormatter(new WebFormatter(this ));
625: } else {
626: super .load(inputStream, encoding);
627: if (getFirstLine() == null) {
628: // New or 0-byte file.
629: appendLine("");
630: lineSeparator = System
631: .getProperty("line.separator");
632: }
633: renumberOriginal();
634: setContentType(contentType);
635: Mode mode = Editor.getModeList().getModeForContentType(
636: contentType);
637: if (mode == null) {
638: File file = getFile();
639: if (file != null)
640: mode = Editor.getModeList().getModeForFileName(
641: file.getName());
642: }
643: if (mode != null) {
644: setFormatter(mode.getFormatter(this ));
645: formatter.parseBuffer();
646: } else
647: setFormatter(new PlainTextFormatter(this ));
648: }
649: } finally {
650: unlockWrite();
651: }
652: return true;
653: }
654:
655: public static void back() {
656: final Editor editor = Editor.currentEditor();
657: final Buffer buffer = editor.getBuffer();
658: if (!(buffer instanceof WebBuffer))
659: return;
660: final WebBuffer wb = (WebBuffer) buffer;
661: WebHistory history = wb.getHistory();
662: if (history == null)
663: return;
664: boolean atEnd = history.atEnd();
665: WebHistoryEntry current = history.getCurrent();
666: WebHistoryEntry previous = history.getPrevious();
667: if (previous != null) {
668: if (atEnd)
669: history.append(wb.getFile(), wb
670: .getAbsoluteOffset(editor.getDot()), wb
671: .getContentType());
672: else if (current != null)
673: current
674: .setOffset(wb
675: .getAbsoluteOffset(editor.getDot()));
676: else
677: Debug.bug();
678: if (previous.getFile().equals(wb.getFile()))
679: wb.update(previous.getOffset());
680: else
681: wb.go(previous.getFile(), previous.getOffset(),
682: previous.getContentType());
683: }
684: }
685:
686: public static void forward() {
687: final Editor editor = Editor.currentEditor();
688: final Buffer buffer = editor.getBuffer();
689: if (!(buffer instanceof WebBuffer))
690: return;
691: final WebBuffer wb = (WebBuffer) buffer;
692: WebHistory history = wb.getHistory();
693: if (history == null)
694: return;
695: WebHistoryEntry current = history.getCurrent();
696: WebHistoryEntry next = history.getNext();
697: if (next != null) {
698: if (current != null)
699: current
700: .setOffset(wb
701: .getAbsoluteOffset(editor.getDot()));
702: else
703: Debug.bug();
704: if (next.getFile().equals(wb.getFile()))
705: wb.update(next.getOffset());
706: else
707: wb.go(next.getFile(), next.getOffset(), next
708: .getContentType());
709: }
710: }
711:
712: public static void refresh() {
713: final Editor editor = Editor.currentEditor();
714: final Buffer buffer = editor.getBuffer();
715: if (buffer instanceof WebBuffer)
716: ((WebBuffer) buffer).reload(editor);
717: }
718:
719: private void reload(Editor editor) {
720: final File file = getFile();
721: if (file instanceof HttpFile) {
722: HttpFile httpFile = (HttpFile) file;
723: File cache = httpFile.getCache();
724: if (cache != null) {
725: if (cache.isFile())
726: cache.delete();
727: httpFile.setCache(null);
728: }
729: }
730: int offset = getAbsoluteOffset(editor.getDot());
731: go(file, offset, contentType);
732: }
733:
734: public void go(final File destination, final int offset,
735: String contentType) {
736: if (destination == null)
737: return;
738:
739: if (destination.isLocal()) {
740: if (loadLocalFile(destination, contentType)) {
741: setFile(destination);
742: update(offset);
743: setLastModified(destination.lastModified());
744: } else {
745: // Error!
746: Runnable errorRunnable = new Runnable() {
747: public void run() {
748: if (empty
749: && Editor.getBufferList().contains(
750: WebBuffer.this ))
751: kill();
752: for (EditorIterator it = new EditorIterator(); it
753: .hasNext();) {
754: Editor ed = it.nextEditor();
755: if (empty
756: || ed.getBuffer() == WebBuffer.this ) {
757: ed.updateLocation();
758: ed.updateDisplay();
759: }
760: }
761: if (errorText == null)
762: errorText = "Unable to load "
763: + destination.canonicalPath();
764: MessageDialog.showMessageDialog(errorText,
765: "Error");
766: }
767: };
768: SwingUtilities.invokeLater(errorRunnable);
769: }
770: return;
771: }
772:
773: // Destination is not local.
774: if (destination.equals(getFile())) {
775: File cache = getCache();
776: if (cache != null && cache.isFile()) {
777: // We have a cache.
778: if (loadLocalFile(cache, contentType)) {
779: setFile(destination);
780: update(offset);
781: }
782: return;
783: }
784: }
785:
786: Debug.assertTrue(destination instanceof HttpFile);
787: final HttpFile httpFile = (HttpFile) destination;
788: File cache = httpFile.getCache();
789: if (cache != null) {
790: if (cache.isFile()) {
791: if (contentType == null)
792: contentType = httpFile.getContentType();
793: if (loadLocalFile(cache, contentType)) {
794: setFile(destination);
795: setCache(cache);
796: update(offset);
797: }
798: return;
799: }
800: cache = null;
801: httpFile.setCache(null);
802: }
803:
804: Debug.assertTrue(cache == null);
805: Log.debug("go cache is null");
806: final File oldFile = getFile();
807: setFile(destination);
808: final HttpLoadProcess httpLoadProcess = new HttpLoadProcess(
809: this , httpFile);
810: Runnable httpSuccessRunnable = new Runnable() {
811: public void run() {
812: File localCache = httpLoadProcess.getCache();
813: if (localCache != null && localCache.isFile()) {
814: if (loadLocalFile(localCache, httpLoadProcess
815: .getContentType(), localCache.getEncoding())) {
816: setFile(httpLoadProcess.getFile());
817: setCache(localCache);
818: setContentType(httpLoadProcess.getContentType());
819: update(offset);
820: }
821: }
822: }
823: };
824: Runnable httpCancelRunnable = new Runnable() {
825: public void run() {
826: setFile(oldFile);
827: setBusy(false);
828: if (empty
829: && Editor.getBufferList().contains(
830: WebBuffer.this ))
831: kill();
832: for (EditorIterator it = new EditorIterator(); it
833: .hasNext();) {
834: Editor ed = it.nextEditor();
835: if (ed != null && ed.getBuffer() == WebBuffer.this ) {
836: ed.status("Transfer cancelled");
837: ed.setDefaultCursor();
838: }
839: }
840: Editor.currentEditor().updateDisplay();
841: MessageDialog.showMessageDialog("Transfer cancelled",
842: httpFile.netPath());
843: }
844: };
845: ErrorRunnable httpErrorRunnable = new ErrorRunnable(
846: "Load failed") {
847: public void run() {
848: setFile(oldFile);
849: setBusy(false);
850: if (empty
851: && Editor.getBufferList().contains(
852: WebBuffer.this ))
853: kill();
854: if (!httpLoadProcess.cancelled()) {
855: errorText = httpLoadProcess.getErrorText();
856: if (errorText == null || errorText.length() == 0)
857: errorText = "Unable to load "
858: + httpFile.netPath();
859: setMessage(errorText);
860: }
861: super .run();
862: }
863: };
864: httpLoadProcess.setSuccessRunnable(httpSuccessRunnable);
865: httpLoadProcess.setCancelRunnable(httpCancelRunnable);
866: httpLoadProcess.setErrorRunnable(httpErrorRunnable);
867: httpLoadProcess
868: .setProgressNotifier(new StatusBarProgressNotifier(
869: WebBuffer.this ));
870: httpLoadProcess.start();
871: }
872:
873: private void update(int offset) {
874: Position pos = getPosition(offset);
875: if (pos == null)
876: pos = new Position(getFirstLine(), 0);
877: setBusy(false);
878: update(pos);
879: }
880:
881: private void update(Position pos) {
882: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
883: Editor ed = it.nextEditor();
884: if (ed.getBuffer() == this ) {
885: ed.setDot(pos.copy());
886: ed.setMark(null);
887: ed.moveCaretToDotCol();
888: ed.setTopLine(getFirstLine());
889: ed.setUpdateFlag(REFRAME);
890: ed.repaintDisplay();
891: ed.updateDisplay();
892: ed.updateLocation();
893: }
894: }
895: Sidebar.setUpdateFlagInAllFrames(SIDEBAR_BUFFER_LIST_CHANGED);
896: Sidebar.repaintBufferListInAllFrames();
897: Editor.currentEditor().status("Loading complete");
898: }
899:
900: public boolean isTransient() {
901: if (super .isTransient())
902: return true;
903: File file = getFile();
904: if (file != null && file.isLocal()) {
905: if (file.equals(Help.getBindingsFile()))
906: return true;
907: File dir = file.getParentFile();
908: if (dir != null
909: && dir.equals(Help.getDocumentationDirectory()))
910: return true;
911: }
912: return false;
913: }
914:
915: public boolean save() {
916: // We shouldn't be trying to save a WebBuffer.
917: Debug.bug();
918: return true;
919: }
920:
921: public static void copyLink() {
922: final Editor editor = Editor.currentEditor();
923: final Buffer buffer = editor.getBuffer();
924: if (buffer instanceof WebBuffer) {
925: Position pos = editor.getDot();
926: if (pos != null && pos.getLine() instanceof WebLine) {
927: HtmlLineSegment segment = ((WebLine) pos.getLine())
928: .findSegment(pos.getOffset());
929: if (segment != null) {
930: Link link = segment.getLink();
931: if (link == null)
932: return;
933: String copy = null;
934: String target = link.getTarget();
935: if (target == null)
936: return;
937: if (target.startsWith("mailto:")) {
938: copy = target;
939: } else {
940: int index = target.indexOf('#');
941: String filename;
942: String ref = null;
943: if (index == 0) {
944: filename = buffer.getFile().netPath();
945: ref = target;
946: } else if (index > 0) {
947: filename = target.substring(0, index);
948: ref = target.substring(index);
949: } else
950: filename = target;
951: final File destination = resolve(buffer
952: .getFile().getParentFile(), filename);
953: if (destination != null) {
954: copy = destination.netPath();
955: if (ref != null)
956: copy = copy.concat(ref);
957: }
958: }
959: if (copy != null) {
960: KillRing killRing = editor.getKillRing();
961: killRing.appendNew(copy);
962: killRing.copyLastKillToSystemClipboard();
963: editor.status("Link copied to clipboard");
964: }
965: }
966: }
967: }
968: }
969: }
|