001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2005, 2007, Red Hat Inc.
004    //
005    // FRYSK is free software; you can redistribute it and/or modify it
006    // under the terms of the GNU General Public License as published by
007    // the Free Software Foundation; version 2 of the License.
008    //
009    // FRYSK is distributed in the hope that it will be useful, but
010    // WITHOUT ANY WARRANTY; without even the implied warranty of
011    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012    // General Public License for more details.
013    // 
014    // You should have received a copy of the GNU General Public License
015    // along with FRYSK; if not, write to the Free Software Foundation,
016    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017    // 
018    // In addition, as a special exception, Red Hat, Inc. gives You the
019    // additional right to link the code of FRYSK with code not covered
020    // under the GNU General Public License ("Non-GPL Code") and to
021    // distribute linked combinations including the two, subject to the
022    // limitations in this paragraph. Non-GPL Code permitted under this
023    // exception must only link to the code of FRYSK through those well
024    // defined interfaces identified in the file named EXCEPTION found in
025    // the source code files (the "Approved Interfaces"). The files of
026    // Non-GPL Code may instantiate templates or use macros or inline
027    // functions from the Approved Interfaces without causing the
028    // resulting work to be covered by the GNU General Public
029    // License. Only Red Hat, Inc. may make changes or additions to the
030    // list of Approved Interfaces. You must obey the GNU General Public
031    // License in all respects for all of the FRYSK code and other code
032    // used in conjunction with FRYSK except the Non-GPL Code covered by
033    // this exception. If you modify this file, you may extend this
034    // exception to your version of the file, but you are not obligated to
035    // do so. If you do not wish to provide this exception without
036    // modification, you must delete this exception statement from your
037    // version and license this file solely under the GPL without
038    // exception.
039    
040    
041    package frysk.gui.register;
042    
043    import inua.eio.ByteOrder;
044    
045    import java.util.Observable;
046    import java.util.Observer;
047    import java.util.prefs.Preferences;
048    
049    import java.math.BigInteger;
050    
051    import org.gnu.glade.LibGlade;
052    import org.gnu.glib.CustomEvents;
053    import org.gnu.gtk.Button;
054    import org.gnu.gtk.CellRenderer;
055    import org.gnu.gtk.CellRendererText;
056    import org.gnu.gtk.DataColumn;
057    import org.gnu.gtk.DataColumnDouble;
058    import org.gnu.gtk.DataColumnObject;
059    import org.gnu.gtk.DataColumnString;
060    import org.gnu.gtk.ListStore;
061    import org.gnu.gtk.TreeIter;
062    import org.gnu.gtk.TreePath;
063    import org.gnu.gtk.TreeView;
064    import org.gnu.gtk.TreeViewColumn;
065    import org.gnu.gtk.Window;
066    import org.gnu.gtk.event.ButtonEvent;
067    import org.gnu.gtk.event.ButtonListener;
068    import org.gnu.gtk.event.CellRendererTextEvent;
069    import org.gnu.gtk.event.CellRendererTextListener;
070    import org.gnu.gtk.event.LifeCycleEvent;
071    import org.gnu.gtk.event.LifeCycleListener;
072    
073    import frysk.gui.common.IconManager;
074    import frysk.gui.common.UBigInteger;
075    import frysk.gui.prefs.PreferenceManager;
076    import frysk.gui.monitor.Saveable;
077    
078    import frysk.proc.Proc;
079    import frysk.proc.Task;
080    
081    import frysk.isa.registers.Register;
082    import frysk.isa.registers.RegisterGroup;
083    import frysk.isa.registers.Registers;
084    import frysk.isa.registers.RegistersFactory;
085    import frysk.stack.StackFactory;
086    import frysk.stepping.TaskStepEngine;
087    import frysk.value.ArithmeticType;
088    import frysk.value.IntegerType;
089    import frysk.value.UnsignedType;
090    import frysk.value.FloatingPointType;
091    import frysk.value.Format;
092    import frysk.value.Value;
093    
094    
095    public class RegisterWindow
096        extends Window
097        implements Saveable
098    {
099      public static String gladePath;
100      
101      private Task myTask;
102    
103      private LibGlade glade;
104    
105      private Preferences prefs;
106      
107      private DataColumnString registerNameColumn = new DataColumnString();
108      private DataColumnString decimalLittleEndianColumn = new DataColumnString();
109      private DataColumnString decimalBigEndianColumn = new DataColumnString();
110      private DataColumnString hexidecimalLittleEndianColumn = new DataColumnString();
111      private DataColumnString hexidecimalBigEndianColumn = new DataColumnString();
112      private DataColumnString octalLittleEndianColumn = new DataColumnString();
113      private DataColumnString octalBigEndianColumn = new DataColumnString();
114      private DataColumnString binaryLittleEndianColumn = new DataColumnString();
115      private DataColumnString binaryBigEndianColumn = new DataColumnString();
116      private DataColumnObject registerColumn = new DataColumnObject();
117      private DataColumnDouble alignmentColumn = new DataColumnDouble();
118      private DataColumnObject valueColumn = new DataColumnObject();
119      private DataColumnObject typeColumn = new DataColumnObject();
120      
121      private DataColumn[] cols = new DataColumn[] {registerNameColumn,
122                                    decimalLittleEndianColumn,
123                                    decimalBigEndianColumn,
124                                    hexidecimalLittleEndianColumn,
125                                    hexidecimalBigEndianColumn,
126                                    octalLittleEndianColumn,
127                                    octalBigEndianColumn,
128                                    binaryLittleEndianColumn,
129                                    binaryBigEndianColumn,
130                                    registerColumn,
131                                    alignmentColumn,
132                                    valueColumn,
133                                    typeColumn }; 
134      
135      protected static String[] colNames = { "Decimal (LE)", "Decimal (BE)",
136                                            "Hexadecimal (LE)", "Hexadecimal (BE)",
137                                            "Octal (LE)", "Octal (BE)",
138                                            "Binary (LE)", "Binary (BE)" };
139    
140      protected boolean[] colVisible = new boolean[cols.length];
141      {
142        java.util.Arrays.fill(colVisible, false);
143        colVisible[2] = true;
144      }
145    
146      private TreeViewColumn[] columns = new TreeViewColumn[8];
147    
148      private RegisterFormatDialog formatDialog;
149    
150      private TreeView registerView;
151      
152      private boolean RW_active = false;
153      
154      private Observable observable;
155      
156      private LockObserver lock;
157      
158      private boolean toggle = true;
159      
160      private boolean closed = false;
161    
162      /**
163       * The RegisterWindow allows the display and editing of the names and values of
164       * system registers. The values of the registers can be displayed in decimal,
165       * hexadecimal, octal, or binary. Manipulating the registers is only possible
166       * when the task is stopped, otherwise all functionality is disabled.
167       * 
168       * The RegisterWindow is created dynamically from the RegisterWindowFactory.
169       * 
170       * @param task The Task for which to display the registers
171       * @param glade The glade file for the register window
172       */
173      public RegisterWindow (LibGlade glade)
174      {
175        super(glade.getWidget("registerWindow").getHandle());
176        this.glade = glade;
177        this.formatDialog = new RegisterFormatDialog(this.glade);
178    
179        this.setIcon(IconManager.windowIcon);
180        this.lock = new LockObserver();
181      }
182      
183      /**
184       * Initializes the Glade file, the RegisterWindow itself, adds listeners and
185       * Assigns the Proc.
186       * 
187       * @param proc  The Proc to be examined by rw.
188       */
189      public void finishRegWin (Proc proc)
190      {
191        Preferences prefs = PreferenceManager.getPrefs();
192        load(prefs.node(prefs.absolutePath() + "/register"));
193    
194        if (!hasTaskSet())
195          {
196            setIsRunning(false);
197            setTask(proc.getMainTask());
198          }
199        else
200          this.showAll();
201        
202        this.RW_active = true;
203      }
204      
205      public void setObservable (Observable o)
206      {
207        this.observable = o;
208      }
209    
210      /**
211       * Check to see if the task to be examined has already been set.
212       * 
213       * @return    False if myTask is null, True otherwise.
214       */
215      public boolean hasTaskSet ()
216      {
217        return myTask != null;
218      }
219    
220      /**
221       * Sets the task to be examined by this RegisterWindow. Also initializes 
222       * the ISA used and does most of the work setting up the initial members
223       * used by this class.
224       * 
225       * @param myTask  The Task to be examined by this RegisterWindow.
226       */
227      public void setTask (Task myTask)
228      {
229        this.myTask = myTask;
230        this.setTitle(this.getTitle() + this.myTask.getProc().getCommand()
231                      + " " + this.myTask.getName());
232    
233        this.registerView = (TreeView) this.glade.getWidget("registerView");
234    
235        ListStore model = new ListStore(cols);
236        registerView.setModel(model);
237    
238        setValues(myTask, model);
239    
240        TreeViewColumn col = new TreeViewColumn();
241        col.setTitle("Name");
242        CellRenderer renderer = new CellRendererText();
243        col.packStart(renderer, true);
244        col.setReorderable(false);
245        col.addAttributeMapping(renderer, CellRendererText.Attribute.TEXT, registerNameColumn);
246        registerView.appendColumn(col);
247        
248        for (int i = 0; i < colNames.length; i++)
249          {
250            col = new TreeViewColumn();
251            col.setTitle(colNames[i]);
252            col.setReorderable(true);
253            renderer = new CellRendererText();
254            ((CellRendererText) renderer).setEditable(true);
255            boolean littleEndian = false;
256            switch (i)
257              {
258              case 0:
259                littleEndian = true; // fall through
260              case 1:
261                ((CellRendererText) renderer).addListener(new DecCellListener(
262                                                                              littleEndian));
263                break;
264              case 2:
265                littleEndian = true; // fall through
266              case 3:
267                ((CellRendererText) renderer).addListener(new HexCellListener(
268                                                                              littleEndian));
269                break;
270              case 4:
271                littleEndian = true; // fall through
272              case 5:
273                ((CellRendererText) renderer).addListener(new OctCellListener(
274                                                                              littleEndian));
275                break;
276              case 6:
277                littleEndian = true; // fall through
278              case 7:
279                ((CellRendererText) renderer).addListener(new BinCellListener(
280                                                                              littleEndian));
281                break;
282              }
283            col.packStart(renderer, false);
284            col.addAttributeMapping(renderer, CellRendererText.Attribute.TEXT,
285                                    cols[i + 1]);
286            col.addAttributeMapping(renderer, CellRendererText.Attribute.XALIGN, alignmentColumn);
287            registerView.appendColumn(col);
288    
289            col.setVisible(this.prefs.getBoolean(colNames[i], colVisible[i]));
290    
291            columns[i] = col;
292          }
293    
294        registerView.setAlternateRowColor(true);
295    
296        this.formatDialog.addListener(new LifeCycleListener()
297        {
298    
299          public boolean lifeCycleQuery (LifeCycleEvent arg0)
300          {
301            return false;
302          }
303    
304          public void lifeCycleEvent (LifeCycleEvent arg0)
305          {
306            if (arg0.isOfType(LifeCycleEvent.Type.HIDE))
307              RegisterWindow.this.refreshList();
308          }
309    
310        });
311    
312        ((Button) this.glade.getWidget("closeButton")).addListener(new ButtonListener()
313        {
314          public void buttonEvent (ButtonEvent arg0)
315          {
316            if (arg0.isOfType(ButtonEvent.Type.CLICK))
317              {
318                RegisterWindow.this.observable.deleteObserver(lock);
319                RegisterWindow.this.closed = true;
320                RegisterWindow.this.hideAll();
321              }
322          }
323        });
324    
325        ((Button) this.glade.getWidget("formatButton")).addListener(new ButtonListener()
326        {
327          public void buttonEvent (ButtonEvent arg0)
328          {
329            if (arg0.isOfType(ButtonEvent.Type.CLICK))
330              RegisterWindow.this.formatDialog.showAll();
331          }
332        });
333    
334        this.refreshList();
335      }
336    
337        private void setValues(Task myTask, ListStore model) {
338        
339            Registers registers = RegistersFactory.getRegisters(myTask.getISA());
340            RegisterGroup group = registers.getAllRegistersGroup();
341            
342            for (int i = 0; i < group.getRegisters().length; i++) {
343                Register register = group.getRegisters()[i];
344                TreeIter iter = model.appendRow();
345                
346                model.setValue(iter, registerNameColumn, register.getName());
347                model.setValue(iter, registerColumn, register);
348                model.setValue(iter, alignmentColumn, 1.0);
349                model.setValue(iter, typeColumn,
350                               register.getType());
351                
352                Value value = StackFactory.createFrame(myTask).getRegisterValue(register);
353                saveBinaryValue(value, iter.getPath());
354            }
355        }
356      
357      public void resetTask (Task task)
358      {
359        this.myTask = task;
360        this.setTitle(this.getTitle() + this.myTask.getProc().getCommand() + " "
361                      + this.myTask.getName());
362    
363        ListStore model = (ListStore) this.registerView.getModel();
364        model.clear();
365    
366        setValues(task, model);
367        
368        refreshList();
369      }
370    
371      /**
372       * Sets whether the task is running or not, and if it is diable the widgets in
373       * the window
374       * 
375       * @param running Whether the task is running TODO: Should we be listening to
376       *          the Task for some sort of an event in this regard?
377       */
378      public void setIsRunning (boolean running)
379      {
380        if (running)
381          {
382            this.glade.getWidget("registerView").setSensitive(false);
383            this.glade.getWidget("formatSelector").setSensitive(false);
384          }
385        else
386          {
387            this.glade.getWidget("registerView").setSensitive(true);
388            this.glade.getWidget("formatSelector").setSensitive(true);
389          }
390      }
391    
392      /**
393       * Saves the new preferences of this window.
394       * 
395       * @param prefs   The preference node to be saved.
396       */
397      public void save (Preferences prefs)
398      {
399        this.formatDialog.save(prefs);
400      }
401    
402      /**
403       * Loads the saved preferences of this window.
404       * 
405       * @param prefs   The preference node used to load preferences.
406       */
407      public void load (Preferences prefs)
408      {
409        this.prefs = prefs;
410        this.formatDialog.load(prefs);
411        this.refreshList();
412      }
413    
414      private String stringUsingValue(Value value, ArithmeticType type, Format format)
415      {
416          if (value == null)
417              return null;
418          return new Value(type, value.getLocation()).toPrint(format);
419      }
420    
421      private void resetList ()
422      {
423        ListStore model = (ListStore) this.registerView.getModel();
424        model.clear();
425        
426        setValues(myTask, model);
427        
428        refreshList();
429      }
430      
431      /**
432       * Refreshes the TreeView displayed to the user with values grabbed from
433       * the Register Objects in the model.
434       */
435      private void refreshList ()
436      {
437        // If there's no task, no point in refreshing
438        if (this.myTask == null)
439          return;
440    
441        // update values in the columns if one of them has been edited
442        ListStore model = (ListStore) this.registerView.getModel();
443        TreeIter iter = model.getFirstIter();
444    
445        while (iter != null)
446          {
447            // get the register
448            Register register 
449              = (Register)model.getValue(iter,
450                                         registerColumn);
451            Value value
452              = (Value)model.getValue(iter, valueColumn);
453            
454            ArithmeticType type;
455    
456            // XXX: This big/little re-formatting of the Register's type
457            // could be pushed into Format.  XXX: Registers can be more
458            // complex types such as union; this use of instanceof to
459            // re-create the type with a specific byte-order isn't going
460            // to scale.
461            if (register.getType() instanceof IntegerType)
462                type = new UnsignedType(register.getType().toPrint(),
463                                        ByteOrder.LITTLE_ENDIAN,
464                                        register.getType().getSize());
465            else if (register.getType() instanceof FloatingPointType)
466                type = new FloatingPointType(register.getType().toPrint(),
467                                             ByteOrder.LITTLE_ENDIAN,
468                                             register.getType().getSize());
469            else
470                throw new RuntimeException("type botch");
471    
472            // Binary little endian
473            model.setValue(iter, binaryLittleEndianColumn, 
474                           stringUsingValue(value, type, Format.BINARY));
475            // Decimal little endian
476            model.setValue(iter, decimalLittleEndianColumn, 
477                           stringUsingValue(value, type, Format.DECIMAL));
478            // Hex little endian
479            model.setValue(iter, hexidecimalLittleEndianColumn, 
480                           stringUsingValue(value, type, Format.HEXADECIMAL));
481            // Octal little endian
482            model.setValue(iter, octalLittleEndianColumn, 
483                           stringUsingValue(value, type, Format.OCTAL));
484    
485            //Switch endian-ness.   
486    
487            // XXX: This big/little re-formatting of the Register's type
488            // could be pushed into Format.  XXX: Registers can be more
489            // complex types such as union; this use of instanceof to
490            // re-create the type with a specific byte-order isn't going
491            // to scale.
492            if (register.getType() instanceof IntegerType)
493                type = new UnsignedType(register.getType().toPrint(),
494                                        ByteOrder.BIG_ENDIAN,
495                                        register.getType().getSize());
496            else if (register.getType() instanceof FloatingPointType)
497                type = new FloatingPointType(register.getType().toPrint(),
498                                             ByteOrder.BIG_ENDIAN,
499                                             register.getType().getSize());
500            else
501                throw new RuntimeException("type botch");
502    
503            // Binary big endian
504            model.setValue(iter, binaryBigEndianColumn, 
505                           stringUsingValue(value, type, Format.BINARY));
506            // Decimal big-endian
507            model.setValue(iter, decimalBigEndianColumn,
508                           stringUsingValue(value, type, Format.DECIMAL));
509            // Hex big-endian
510            model.setValue(iter, hexidecimalBigEndianColumn, 
511                           stringUsingValue(value, type, Format.HEXADECIMAL));
512            // Octal big-endian
513            model.setValue(iter, octalBigEndianColumn,
514                           stringUsingValue(value, type, Format.OCTAL));
515    
516            iter = iter.getNextIter();
517          }
518    
519        // update which columns are shown
520        for (int i = 0; i < RegisterWindow.colNames.length; i++)
521          this.columns[i].setVisible(this.prefs.getBoolean(
522                                                           RegisterWindow.colNames[i],
523                                                           this.colVisible[i]));
524    
525        this.showAll();
526      }
527    
528      /**
529       * Reverse the byte order of an integer.
530       * 
531       * @param val The value to be reversed
532       * @param bitLength   The number of bits in this value.
533       */
534      private static BigInteger swizzleByteOrder(BigInteger val, int bitLength)
535      {
536        int byteLength = bitLength / 8;
537        byte[] valBytes = val.toByteArray();
538        byte[] newbytes = new byte[byteLength];
539    
540        for (int i = 0; i < valBytes.length; i++)
541          {
542            newbytes[byteLength - 1 - i] = valBytes[i];
543          }
544        return new BigInteger(newbytes);
545      }
546    
547      /**
548       * Saves the incoming binary value to the model.
549       * 
550       * @param val The binary value to save
551       * @param path    The path used to get the TreeIter from the model.
552       */
553      private void saveBinaryValue (Value val, TreePath path)
554      {
555        ListStore model = (ListStore) this.registerView.getModel();
556        TreeIter iter = model.getIter(path);
557        model.setValue (iter, valueColumn, val);
558      }
559    
560      /**
561       * Writes the incoming binary value to the Register Object for this Task.
562       * 
563       * @param val The binary value to write
564       * @param path    The TreePath used to get the TreeIter from the model.
565       */
566      private void writeBinaryValue (BigInteger val, TreePath path)
567      {
568          //XXX: Implement frame.setRegister(Register reg, Value value)
569    //    ListStore model = (ListStore) this.registerView.getModel();
570    //    TreeIter iter = model.getIter(path);
571    //    Register register = (Register) model.getValue(iter,
572    //                                                  (DataColumnObject) cols[9]);
573    //    register.putBigInteger (myTask, val);
574    //    model.setValue (iter, (DataColumnObject)cols[11], val);
575      }
576    
577      /**
578       * Writes the incoming binary value to the Register Object for this Task.
579       * 
580       * If the string is not negative but the sign bit of the register
581       * will be set, ensure that the BigInteger value is negative.
582       * 
583       * @param rawString   The String containing the value to write.
584       * @param radix   The radix to convert rawString to.
585       * @param littleEndian    The endianness of the incoming value.
586       * @param path    The path used to get the TreeIter from this model.
587       */
588      private void writeBinaryValue (String rawString, int radix,
589                                    boolean littleEndian, TreePath path)
590      {
591        BigInteger value;
592        ListStore model = (ListStore)registerView.getModel();
593        TreeIter iter = model.getIter(path);
594        Register register = (Register)model.getValue(iter,
595                                                     registerColumn);
596        int bitLength = register.getType().getSize() * 8;
597    
598        try
599          {
600            value = new BigInteger(rawString, radix);
601          }
602        // Invalid format, do nothing XXX probably should throw some kind
603        // of error
604        catch (NumberFormatException e)
605          {
606            return;
607          }
608        if (!littleEndian)
609          value = swizzleByteOrder(value, bitLength);
610        value = UBigInteger.signExtend(value, bitLength);
611        writeBinaryValue(value, path);
612      }
613      
614      private void desensitize ()
615      {
616        this.registerView.setSensitive(false);
617      }
618      
619      private void resensitize ()
620      {
621        this.registerView.setSensitive(true);
622      }
623    
624      class DecCellListener
625          implements CellRendererTextListener
626      {
627    
628        boolean littleEndian;
629    
630        /**
631         * Listens to the Decimal cells for changes to write to the Register Object.
632         * @param littleEndian
633         */
634        public DecCellListener (boolean littleEndian)
635        {
636          this.littleEndian = littleEndian;
637        }
638    
639        /**
640         * Calls to write the new value to the Register and refreshes the TreeView.
641         * 
642         * @param arg0  The argument to write.
643         */
644        public void cellRendererTextEvent (CellRendererTextEvent arg0)
645        {
646          String text = arg0.getText();
647    
648          RegisterWindow.this.writeBinaryValue(text, 10, littleEndian,
649                                               new TreePath(arg0.getIndex()));
650          RegisterWindow.this.refreshList();
651        }
652    
653      }
654    
655      class HexCellListener
656          implements CellRendererTextListener
657      {
658    
659        boolean littleEndian;
660    
661        /**
662         * Listens to the Hexadecimal cells for changes to write to the Register Object.
663         * @param littleEndian
664         */
665        public HexCellListener (boolean littleEndian)
666        {
667          this.littleEndian = littleEndian;
668        }
669    
670        /**
671         * Calls to write the new value to the Register and refreshes the TreeView.
672         * 
673         * @param arg0  The argument to write.
674         */
675        public void cellRendererTextEvent (CellRendererTextEvent arg0)
676        {
677          String text = arg0.getText();
678    
679          if (text.indexOf("0x") != - 1)
680            text = text.substring(2);
681          RegisterWindow.this.writeBinaryValue(text, 16, littleEndian,
682                                               new TreePath(arg0.getIndex()));
683          RegisterWindow.this.refreshList();
684        }
685    
686      }
687    
688      class OctCellListener
689          implements CellRendererTextListener
690      {
691    
692        boolean littleEndian;
693    
694        /**
695         * Listens to the Octal cells for changes to write to the Register Object.
696         * @param littleEndian
697         */
698        public OctCellListener (boolean littleEndian)
699        {
700          this.littleEndian = littleEndian;
701        }
702    
703        /**
704         * Calls to write the new value to the Register and refreshes the TreeView.
705         * 
706         * @param arg0  The argument to write.
707         */
708        public void cellRendererTextEvent (CellRendererTextEvent arg0)
709        {
710          String text = arg0.getText();
711    
712          RegisterWindow.this.writeBinaryValue(text, 8, littleEndian,
713                                               new TreePath(arg0.getIndex()));
714          RegisterWindow.this.refreshList();
715        }
716    
717      }
718    
719      class BinCellListener
720          implements CellRendererTextListener
721      {
722    
723        boolean littleEndian;
724    
725        /**
726         * Listens to the Binary cells for changes to write to the Register Object.
727         * @param littleEndian
728         */
729        public BinCellListener (boolean littleEndian)
730        {
731          this.littleEndian = littleEndian;
732        }
733    
734        /**
735         * Calls to write the new value to the Register and refreshes the TreeView.
736         * 
737         * @param arg0  The argument to write.
738         */
739        public void cellRendererTextEvent (CellRendererTextEvent arg0)
740        {
741          String text = arg0.getText();
742    
743          RegisterWindow.this.writeBinaryValue(text, 2, littleEndian,
744                                               new TreePath(arg0.getIndex()));
745          RegisterWindow.this.refreshList();
746        }
747    
748      }
749      
750      /**
751       * Returns the Task being examined by this Window.
752       * 
753       * @return myTask The Task being examined.
754       */
755      public Task getMyTask()
756      {
757        return this.myTask;
758      }
759      
760      public boolean getClosed ()
761      {
762        return this.closed;
763      }
764      
765      public void setClosed (boolean closed)
766      {
767        this.closed = closed;
768      }
769      
770      /**
771       * Returns this RegisterWindow's LockObserver.
772       * 
773       * @return lock This RegisterWindow's LockObserver
774       */
775      public LockObserver getLockObserver()
776      {
777        return this.lock;
778      }
779      
780      /**
781       * Local Observer class used to poke this window from RunState when
782       * all the Tasks belonging to this window's Proc have been
783       * blocked. These Tasks could have ben running, stepping, or neither
784       * and were just blocked once to allow this window to finish
785       * building. This observer is synchronized between this windowand
786       * the Memory, Source, and Disassembly windows.
787       */
788      class LockObserver implements Observer
789      {
790        
791        /**
792         * Builtin Observer method - called whenever the Observable we're concerned
793         * with - in this case the RunState - has changed.
794         * 
795         * @param o The Observable we're watching
796         * @param arg An Object argument
797         */
798        public synchronized void update (Observable o, Object arg)
799        {
800          TaskStepEngine tse = (TaskStepEngine) arg;
801          if (!tse.getState().isStopped())
802            {
803              if (! RW_active)
804                {
805                  RegisterWindow.this.observable = o;
806                  finishRegWin(tse.getTask().getProc());
807                }
808              else
809                return;
810            }
811          else
812            {
813              /* The argument is null; its used here as a toggle. If the toggle is
814               * true, the window is sensitive and we set the toggle to false and 
815               * desensitize the important widgets. Otherwise, set the toggle 
816               * back to true, refresh the window information and resensitize it. */
817              if (toggle)
818                {
819                  CustomEvents.addEvent(new Runnable()
820                  {
821                    public void run ()
822                    {
823                      toggle = false;
824                      desensitize();
825                    }
826                  });
827                }
828              else
829                {
830                  CustomEvents.addEvent(new Runnable()
831                  {
832                    public void run ()
833                    {
834                      toggle = true;
835                      resetList();
836                      resensitize();
837                    }
838                  });
839                }
840            }
841        }
842        }
843      }
844      
845