Source Code Cross Referenced for LispInput.java in  » Scripting » Jatha » org » jatha » display » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Jatha » org.jatha.display 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Jatha - a Common LISP-compatible LISP library in Java.
003:         * Copyright (C) 1997-2005 Micheal Scott Hewett
004:         *
005:         * This library is free software; you can redistribute it and/or
006:         * modify it under the terms of the GNU Lesser General Public
007:         * License as published by the Free Software Foundation; either
008:         * version 2.1 of the License, or (at your option) any later version.
009:         *
010:         * This library is distributed in the hope that it will be useful,
011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013:         * Lesser General Public License for more details.
014:         *
015:         * You should have received a copy of the GNU Lesser General Public
016:         * License along with this library; if not, write to the Free Software
017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018:         *
019:         *
020:         * For further information, please contact Micheal Hewett at
021:         *   hewett@cs.stanford.edu
022:         *
023:         */
024:        package org.jatha.display;
025:
026:        import org.jatha.dynatype.LispValue;
027:        import org.jatha.Jatha;
028:
029:        import javax.swing.*;
030:        import javax.swing.event.CaretListener;
031:        import javax.swing.event.CaretEvent;
032:        import javax.swing.text.*;
033:        import java.awt.*;
034:        import java.awt.event.ActionListener;
035:        import java.awt.event.KeyListener;
036:        import java.awt.event.ActionEvent;
037:        import java.awt.event.KeyEvent;
038:        import java.util.Iterator;
039:        import java.util.ArrayList;
040:
041:        // @date    Wed Mar  5 09:03:03 1997
042:        /**
043:         * LispInput is a text field that does parenthesis
044:         * matching and sends its input off to a Lisp
045:         * Evaluator.
046:         *
047:         * @see java.awt.TextField
048:         * @author  Micheal S. Hewett    hewett@cs.stanford.edu
049:         *
050:         */
051:        class LispInput extends JPanel implements  Runnable, ActionListener,
052:                KeyListener {
053:            public static boolean DEBUG = false;
054:
055:            /* ------------------  PRIVATE variables   ------------------------------ */
056:            protected JTextArea f_inputArea = null;
057:
058:            protected int f_matchingPosition = -1;
059:            protected boolean f_flashing = false;
060:            protected Thread f_myThread = null;
061:            protected Graphics f_myGraphics = null;
062:            protected String f_input;
063:
064:            // GUI stuff
065:            JButton f_largerAreaButton = new JButton("larger");
066:            JButton f_smallerAreaButton = new JButton("smaller");
067:            JButton f_evalButton = new JButton("EVAL");
068:
069:            // Font info
070:            protected FontMetrics fontInfo = null;
071:            protected int fontWidth = 0;
072:            protected int fontHeight = 0;
073:            protected Color fgColor = null;
074:            protected Color bgColor = null;
075:
076:            protected int hFudge = 8;
077:            protected int vFudge = 7;
078:
079:            protected Listener f_parent;
080:
081:            protected String f_saveBuffer = "";
082:            protected String f_lastCommand = "";
083:            protected boolean f_firstCharOfCommand = true;
084:            protected int f_commandMultiplier = 1;
085:
086:            protected Font f_defaultFont = new Font("Courier", Font.PLAIN, 12);
087:
088:            // Used when matching parentheses
089:            protected Highlighter.HighlightPainter f_goodPainter = new DefaultHighlighter.DefaultHighlightPainter(
090:                    Color.cyan);
091:            protected Highlighter.HighlightPainter f_badPainter = new DefaultHighlighter.DefaultHighlightPainter(
092:                    Color.magenta);
093:
094:            protected java.util.List f_highlights = new ArrayList(10);
095:            protected Integer f_highlightLock = new Integer(17);
096:
097:            /**
098:             * Edit this to change the size of the input area.
099:             * (mh) 2005 Nov 06
100:             */
101:            protected int f_defaultNumberOfInputLines = 15;
102:
103:            private Jatha f_lisp = null;
104:
105:            /* ------------------  CONSTRUCTOR   ------------------------------ */
106:
107:            public LispInput(Jatha lisp, Listener parent, int rows, int cols) {
108:                super ();
109:
110:                f_lisp = lisp;
111:                f_parent = parent;
112:
113:                this .setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
114:                setBackground(new Color(170, 170, 170)); // new Color(255, 255, 153)); // yellow
115:
116:                // Set up the input area
117:                f_inputArea = new JTextArea(rows, cols);
118:                f_inputArea.setFont(f_defaultFont);
119:                f_inputArea.addKeyListener(this );
120:                f_inputArea.addCaretListener(new BracketMatcher(this ));
121:
122:                JScrollPane scroller = new JScrollPane(f_inputArea,
123:                        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
124:                        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
125:                add(scroller);
126:
127:                f_largerAreaButton.addActionListener(this );
128:                f_largerAreaButton.setActionCommand("largerArea");
129:                f_largerAreaButton.setBackground(this .getBackground());
130:
131:                f_smallerAreaButton.addActionListener(this );
132:                f_smallerAreaButton.setActionCommand("smallerArea");
133:                f_smallerAreaButton.setBackground(this .getBackground());
134:
135:                f_evalButton.addActionListener(this );
136:                f_evalButton.setActionCommand("eval");
137:                f_evalButton.setBackground(this .getBackground());
138:
139:                // Submit/Expand/Shrink buttons
140:                Box buttonPanel = new Box(BoxLayout.X_AXIS);
141:                buttonPanel.add(f_evalButton);
142:                buttonPanel.add(Box.createHorizontalGlue());
143:                buttonPanel.add(f_largerAreaButton);
144:                buttonPanel.add(f_smallerAreaButton);
145:
146:                add(buttonPanel);
147:
148:                /*
149:                myThread = new Thread(this, "Parenthesis Matching");
150:                myThread.start();
151:                 */
152:            }
153:
154:            /* ------------------  PUBLIC methods   ------------------------------ */
155:
156:            // Set the font - can't do this until it is visible.
157:            public void setFontInfo() {
158:                f_myGraphics = this .getGraphics();
159:
160:                fontInfo = this .getFontMetrics(this .getFont());
161:                fontWidth = fontInfo.charWidth('A');
162:                fontHeight = fontInfo.getHeight();
163:                fgColor = this .getForeground();
164:                bgColor = this .getBackground().brighter(); // Motif is doing something to us.
165:
166:                // hFudge     = fontWidth - 2;
167:            }
168:
169:            /**
170:             * Input should be a regular string, which is parsed and evaluated.
171:             */
172:            public void eval(String inputString) {
173:                f_parent.message(inputString + "\n", true);
174:                LispValue result = f_lisp.load(inputString, true);
175:                if (result.basic_null())
176:                    f_parent.message(
177:                            ";; *** ERROR - unbalanced parentheses in input\n",
178:                            false);
179:                else {
180:                    f_parent.addHistoryItem(inputString);
181:
182:                    // f_parent.message(f_lisp.eval(input));   // result will be printed in the Output window.
183:                    f_lastCommand = inputString;
184:
185:                    // Select all the text in the input box
186:                    setText(f_lastCommand);
187:                    clearHighlights();
188:                    selectAll();
189:                }
190:
191:                //    LispParser parser = new LispParser(f_lisp, inputString + " ");
192:                //    LispValue value = f_lisp.NIL;
193:                //    boolean valid   = true;
194:                //
195:                //    try {
196:                //      value = parser.parse();
197:                //      if (DEBUG)
198:                //        System.err.println("Parser produced: " + value);
199:                //    }
200:                //    catch (EOFException ex)
201:                //    { // display a dialog?
202:                //      f_parent.message("\n*** Incomplete LISP Input - fix it and try again.\n");
203:                //      valid = false;
204:                //    }
205:                //
206:                //    if (valid)
207:                //    {
208:                //      eval(value);
209:                //
210:                f_parent.checkForWindowSettingsChanges();
211:                //    }
212:            }
213:
214:            /**
215:             * Input should be a LispString.
216:             * @param input a LispString containing a command.
217:             */
218:            public void eval(LispValue input) {
219:                f_parent.addHistoryItem(input.toString());
220:
221:                f_parent.message(input, true);
222:                f_parent.message(f_lisp.eval(input)); // result will be printed in the Output window.
223:
224:                f_lastCommand = input.toString();
225:
226:                // Select all the text in the input box
227:                setText(f_lastCommand);
228:                selectAll();
229:            }
230:
231:            // This is called when the user hits RETURN in the input window.
232:            public void actionPerformed(ActionEvent e) {
233:                if (DEBUG)
234:                    System.err.println("ActionPerformed: "
235:                            + e.getActionCommand());
236:
237:                String command = e.getActionCommand();
238:
239:                if (command.equals("comboBoxEdited") || command.equals("eval")) {
240:                    String inStr = f_inputArea.getText();
241:                    if (DEBUG)
242:                        System.err.println("Retrievd typed input: " + inStr);
243:
244:                    if (inStr.trim().equals(""))
245:                        return;
246:
247:                    if (DEBUG)
248:                        System.err.println("LispInput: got input: " + inStr);
249:
250:                    eval(inStr);
251:                    f_firstCharOfCommand = true;
252:                }
253:
254:                else if (e.getActionCommand().equals("largerArea"))
255:                    incrementEditorLines(1);
256:
257:                else if (e.getActionCommand().equals("smallerArea"))
258:                    incrementEditorLines(-1);
259:
260:            }
261:
262:            public void incrementEditorLines(int increment) {
263:                int numRows = f_inputArea.getRows() + increment;
264:                if (numRows > 0) {
265:                    f_inputArea.setRows(numRows);
266:                    f_parent.redraw();
267:
268:                    if (DEBUG)
269:                        System.err.println("Listener input now has " + numRows
270:                                + " rows");
271:
272:                    f_inputArea.setText("(setq *LISTENER-INPUT-ROWS* "
273:                            + numRows + ")");
274:                    ActionEvent newEvent = new ActionEvent(f_inputArea,
275:                            ActionEvent.ACTION_PERFORMED, "comboBoxEdited");
276:                    actionPerformed(newEvent);
277:                }
278:            }
279:
280:            public void keyPressed(KeyEvent e) {
281:            }
282:
283:            public void keyReleased(KeyEvent e) {
284:            }
285:
286:            /**
287:             * Implements parenthesis matching
288:             */
289:            public void keyTyped(KeyEvent e) {
290:                char key = e.getKeyChar();
291:
292:                // System.err.println("LispInput.keyTyped: " + key + " (" + e.getKeyCode() +")");
293:                if ((key == Character.LINE_SEPARATOR) && (e.isControlDown()))
294:                    //   Toolkit.getDefaultToolkit().
295:                    //       getSystemEventQueue().
296:                    //      postEvent(new ActionEvent(e.getSource(),
297:                    //                                ActionEvent.ACTION_PERFORMED,
298:                    //                                 "comboBoxEdited"));
299:                    actionPerformed(new ActionEvent(e.getSource(),
300:                            ActionEvent.ACTION_PERFORMED, "comboBoxEdited"));
301:
302:                //int    quoteCount = 0;
303:                //int    parenCount = 0;
304:
305:                // Check for editing characters
306:                //if (handleEmacsCommand(e))
307:                //  return;
308:
309:                // Reset command multiplier
310:                //f_commandMultiplier = 1;
311:
312:                /*
313:                // Interrupt the parenthesis matching if it's in progress
314:                synchronized (myThread)
315:                {
316:                  if (flashing)
317:                  {
318:                    myThread.interrupt();
319:                  }
320:                }
321:
322:                // PARENTHESIS MATCHING
323:                if (key == ')')
324:                {
325:                  input = f_comboBox.getSelectedItem().toString() + " ";
326:
327:                  // Count doublequotes - don't check if we are in a string
328:                  for (int i=0; i<input.length(); ++i)
329:                    if (input.charAt(i) == '"') ++ quoteCount;
330:
331:                  if ((quoteCount % 2) == 0)    // Do a paren match
332:                  {
333:                    for (int i=input.length()-1; i>=0; --i)
334:                      if (input.charAt(i) == '"')
335:                        while (input.charAt(--i) != '"');
336:                      else
337:                        if (input.charAt(i) == ')')
338:                          ++parenCount;
339:                        else if (input.charAt(i) == '(')
340:                        {
341:                          --parenCount;
342:                          if (parenCount == 0)  // Highlight the paren for an instant
343:                          {
344:                            matchingPosition = i;
345:                            // Determine whether the matchingPosition is visible
346:                            if ((f_comboBox.getCaretPosition() - matchingPosition) < this.getColumns())
347:                            {
348:                              synchronized(myThread) { myThread.notify(); }
349:                            }
350:                          }
351:                        }
352:                  }
353:                }
354:                 */
355:            }
356:
357:            /**
358:             * Returns true if no further event handling is necessary.
359:             */
360:            boolean handleEmacsCommand(KeyEvent e) {
361:                //char     key     = e.getKeyChar();
362:                //int      type    = e.getID();
363:                // boolean  delChar = true;
364:
365:                return false;
366:
367:                /*
368:                // 29 Sep 2003 (mh)
369:                // TextField no longer enters Emacs commands into the field
370:                // so we don't need to delete the character when it is typed.
371:
372:                // If they type an editing command as the first character of
373:                // a command, the old command will be deleted, which we don't
374:                // want.  So we check for first characters and restore the text.
375:
376:                if (key >= 27)    // not a Control character
377:                {
378:                  FirstCharOfCommand = false;
379:                  return false;
380:                }
381:
382:                if (FirstCharOfCommand)
383:                {
384:                  f_comboBox.setSelectedItem(LastCommand);
385:                  FirstCharOfCommand = false;
386:                  // delChar = false;
387:                }
388:
389:                // EMACS bindings
390:                if (key == 1)     // CTRL-A, Beginning of Line
391:                {
392:                  //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
393:                  /*
394:                  if (type == KeyEvent.KEY_TYPED)
395:                    this.setCaretPosition(0);
396:                 */
397:                /*
398:                 CommandMultiplier = 1;
399:                 return true;
400:                 }
401:
402:                 if (key == 2)   // CTRL-B BACKWARD one space
403:                 {
404:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
405:
406:                 int p = getCaretPosition();
407:
408:                 for (int i=0; i<CommandMultiplier; ++i)
409:                 if (p > 0)
410:                 this.setCaretPosition(this.getCaretPosition() - 1);
411:
412:                 CommandMultiplier = 1;
413:                 return true;
414:                 }
415:
416:                 if (key == 4)   // CTRL-D DELETE forward
417:                 {
418:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
419:
420:                 for (int i=0; i<CommandMultiplier; ++i)
421:                 {
422:                 this.setCaretPosition(this.getCaretPosition() + 1);
423:                 eraseLastCharTyped();  // Deletes the previous character.
424:                 }
425:
426:                 CommandMultiplier = 1;
427:                 return true;
428:                 }
429:
430:                 if (key == 5)   // CTRL-E,  EOL
431:                 {
432:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
433:                 if (type == KeyEvent.KEY_TYPED)
434:                 this.setCaretPosition(this.getText().length()+1);
435:
436:                 CommandMultiplier = 1;
437:                 return true;
438:                 }
439:
440:                 if (key == 6)   // CTRL-F FORWARD one space
441:                 {
442:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
443:                 for (int i=0; i<CommandMultiplier; ++i)
444:                 this.setCaretPosition(this.getCaretPosition() + 1);
445:
446:                 CommandMultiplier = 1;
447:                 return true;
448:                 }
449:
450:                 if (key == 11)  // CTRL-K Kill to end of line
451:                 {
452:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
453:
454:                 saveText(killToEndOfLine());
455:
456:                 CommandMultiplier = 1;
457:                 return true;
458:                 }
459:
460:                 if (key == 21)  // CTRL-U Command repeat x4
461:                 {
462:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
463:
464:                 CommandMultiplier *= 4;
465:                 return true;
466:                 }
467:
468:                 if (key == 25)  // CTRL-Y Yank kill buffer
469:                 {
470:                 //if (delChar) eraseLastCharTyped();  // Stupid TextField doesn't let us filter characters.
471:                 for (int i=0; i<CommandMultiplier; ++i)
472:                 restoreText();
473:
474:                 CommandMultiplier = 1;
475:                 return true;
476:                 }
477:
478:                 return false;
479:                 */
480:            }
481:
482:            // Editing command - used to erase control characters.
483:            void eraseLastCharTyped() {
484:                /*    String s = getText();
485:                 int    p = getCaretPosition();
486:                 if (p > 0)
487:                 {
488:                 this.setText(s.substring(0, p-1) + s.substring(p));
489:                 this.setCaretPosition(p-1);
490:                 }
491:                 */
492:            }
493:
494:            // Editing - deletes string to end of line.
495:            String killToEndOfLine() {
496:                /*
497:                String s = getText();
498:                int    p = getCaretPosition();
499:                String killed;
500:
501:                killed = s.substring(p);
502:                this.setText(s.substring(0, p));
503:
504:                return killed;
505:                 */
506:                return "";
507:            }
508:
509:            // Editing - save deleted text in a buffer
510:            void saveText(String s) {
511:                f_saveBuffer = s;
512:            }
513:
514:            // Editing - restore deleted text from a buffer
515:            void restoreText() {
516:                /*
517:                String s = getText();
518:                int    p = getCaretPosition();
519:
520:                setText(s.substring(0, p) + SaveBuffer + s.substring(p));
521:                setCaretPosition(p + SaveBuffer.length());
522:                 */
523:            }
524:
525:            public void run() {
526:                int h, v; // Top left corner of character to be boxed.
527:
528:                synchronized (f_myThread) {
529:                    while (true) {
530:                        try {
531:                            f_myThread.wait();
532:                        } // Wait to be notified to start flashing
533:                        catch (InterruptedException e) {
534:                        }
535:
536:                        // can't do this until we are visible.
537:                        if (fontInfo == null)
538:                            setFontInfo();
539:
540:                        f_flashing = true;
541:                        // draw a box around the matching character.
542:                        /* Fixed-width font
543:                        // The font is a fixed-width font.
544:                        // h = matchingPosition * fontWidth + hFudge;
545:                         */
546:
547:                        // Variable-width font
548:                        h = hFudge
549:                                + fontInfo.stringWidth(f_input.substring(0,
550:                                        f_matchingPosition));
551:                        v = vFudge;
552:
553:                        f_myGraphics.setXORMode(Color.white);
554:                        f_myGraphics.fillRect(h, v, fontWidth, fontHeight);
555:
556:                        // Sleep for 0.5 sec or until user types another key
557:                        try {
558:                            f_myThread.wait(500L);
559:                        } catch (InterruptedException e) {
560:                        } finally {
561:                            f_flashing = false;
562:                            f_myGraphics.fillRect(h, v, fontWidth, fontHeight);
563:                            f_myGraphics.setPaintMode();
564:                        }
565:                    }
566:                }
567:            }
568:
569:            public String getText() {
570:                return f_inputArea.getText();
571:            }
572:
573:            public void setText(String newText) {
574:                f_inputArea.setText(newText);
575:            }
576:
577:            public void selectAll() {
578:                f_inputArea.selectAll();
579:                //((JTextComponent)f_comboBox.getEditor().getEditorComponent()).selectAll();
580:            }
581:
582:            public int getColumns() {
583:                return f_inputArea.getColumns();
584:            }
585:
586:            public void setColumns(int newValue) {
587:                f_inputArea.setColumns(newValue);
588:            }
589:
590:            public void setRows(int newValue) {
591:                f_inputArea.setRows(newValue);
592:            }
593:
594:            public int getRows() {
595:                return f_inputArea.getRows();
596:            }
597:
598:            public void addGoodHighlight(int start, int end) {
599:                addHighlight(start, end, f_goodPainter);
600:            }
601:
602:            public void addBadHighlight(int start, int end) {
603:                addHighlight(start, end, f_badPainter);
604:            }
605:
606:            public void addHighlight(int start, int end,
607:                    Highlighter.HighlightPainter painter) {
608:                Highlighter highlighter = f_inputArea.getHighlighter();
609:
610:                synchronized (f_highlightLock) {
611:                    try {
612:                        f_highlights.add(highlighter.addHighlight(start, end,
613:                                painter));
614:                    } catch (BadLocationException ble) {
615:                        // ignore
616:                    }
617:                }
618:            }
619:
620:            public void clearHighlights() {
621:                Highlighter highlighter = f_inputArea.getHighlighter();
622:
623:                if (highlighter != null) {
624:                    synchronized (f_highlightLock) {
625:                        for (Iterator iterator = f_highlights.iterator(); iterator
626:                                .hasNext();) {
627:                            Highlighter.Highlight highlight = (Highlighter.Highlight) iterator
628:                                    .next();
629:                            highlighter.removeHighlight(highlight);
630:                        }
631:                        f_highlights.clear();
632:                    }
633:                }
634:            }
635:
636:        }
637:
638:        class BracketMatcher implements  CaretListener {
639:            protected LispInput f_input;
640:
641:            public BracketMatcher(LispInput input) {
642:                f_input = input;
643:            }
644:
645:            public void caretUpdate(CaretEvent e) {
646:                JTextComponent source = (JTextComponent) e.getSource();
647:                int pos = e.getDot();
648:                Document doc = source.getDocument();
649:                char key = ' ';
650:
651:                f_input.clearHighlights();
652:
653:                try {
654:                    key = doc.getText(e.getDot() - 1, 1).charAt(0);
655:                } catch (BadLocationException ble) { // ?? when does this happen?
656:                    return;
657:                }
658:
659:                // PARENTHESIS MATCHING
660:                if (key == ')') {
661:                    String input = f_input.getText();
662:                    int quoteCount = 0;
663:                    int parenCount = 0;
664:
665:                    // Count doublequotes - don't check if we are in a string
666:                    for (int i = 0; i < pos; ++i)
667:                        if (input.charAt(i) == '"')
668:                            ++quoteCount;
669:
670:                    if ((quoteCount % 2) != 0) // Don't do a paren match if we are inside a string
671:                        return;
672:
673:                    // Find the matching paren
674:                    for (int i = pos - 1; i >= 0; --i) {
675:                        if (input.charAt(i) == '"')
676:                            while (input.charAt(--i) != '"')
677:                                ;
678:                        else if (input.charAt(i) == ')')
679:                            ++parenCount;
680:                        else if (input.charAt(i) == '(') {
681:                            --parenCount;
682:                            if (parenCount == 0) // Highlight the paren for an instant
683:                            {
684:                                f_input.addGoodHighlight(i, i + 1);
685:                                f_input.addGoodHighlight(pos - 1, pos);
686:                                return;
687:                            }
688:                        }
689:                    }
690:
691:                    // If we get here, we didn't match anything.
692:                    f_input.addBadHighlight(pos - 1, pos);
693:
694:                }
695:            }
696:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.