[Avida-SVN] r1135 - in development/source: analyze drivers main targets/avida-viewer tools

ofria at myxo.css.msu.edu ofria at myxo.css.msu.edu
Mon Dec 11 20:12:56 PST 2006


Author: ofria
Date: 2006-12-11 23:12:56 -0500 (Mon, 11 Dec 2006)
New Revision: 1135

Added:
   development/source/targets/avida-viewer/cAnalyzeScreen.cc
   development/source/targets/avida-viewer/cAnalyzeScreen.h
   development/source/targets/avida-viewer/cAnalyzeView.cc
   development/source/targets/avida-viewer/cAnalyzeView.h
   development/source/targets/avida-viewer/cTabBox.h
   development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.cc
   development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.h
   development/source/targets/avida-viewer/cTextViewerDriver_Base.cc
   development/source/targets/avida-viewer/cTextViewerDriver_Base.h
   development/source/targets/avida-viewer/cView_Base.h
Modified:
   development/source/analyze/cAnalyze.cc
   development/source/analyze/cAnalyze.h
   development/source/analyze/cAnalyzeJobQueue.cc
   development/source/drivers/cDriverManager.cc
   development/source/drivers/cWorldDriver.h
   development/source/main/cEventList.cc
   development/source/main/cPopulationInterface.cc
   development/source/main/cSpatialCountElem.h
   development/source/main/cWorld.cc
   development/source/targets/avida-viewer/CMakeLists.txt
   development/source/targets/avida-viewer/SConscript
   development/source/targets/avida-viewer/cBaseTextWindow.h
   development/source/targets/avida-viewer/cEnvironmentScreen.cc
   development/source/targets/avida-viewer/cOptionsScreen.cc
   development/source/targets/avida-viewer/cStatsScreen.cc
   development/source/targets/avida-viewer/cTextViewerDriver.cc
   development/source/targets/avida-viewer/cTextViewerDriver.h
   development/source/targets/avida-viewer/cTextWindow.cc
   development/source/targets/avida-viewer/cTextWindow.h
   development/source/targets/avida-viewer/cView.cc
   development/source/targets/avida-viewer/cView.h
   development/source/targets/avida-viewer/cViewInfo.cc
   development/source/targets/avida-viewer/cViewInfo.h
   development/source/targets/avida-viewer/cZoomScreen.cc
   development/source/targets/avida-viewer/viewer.cc
   development/source/tools/cString.cc
   development/source/tools/cString.h
Log:
Added an analyze screen to the ncurses viewer.  If you hit 'A' in ncurses it
will take you into analyze mode; the main analyze screen is still boring, but
if you hit '<' or '>' you will switch to a working command line.

Setup pause to not use up CPU cycles.

Removed static methods and variables from viewer.



Modified: development/source/analyze/cAnalyze.cc
===================================================================
--- development/source/analyze/cAnalyze.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/analyze/cAnalyze.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -52,6 +52,7 @@
 #include "cResource.h"
 #include "tHashTable.h"
 #include "cWorld.h"
+#include "cWorldDriver.h"
 #ifdef WIN32
 #  include "win32_mkdir_hack.hh"
 #endif
@@ -67,14 +68,18 @@
 
 cAnalyze::cAnalyze(cWorld* world)
 : cur_batch(0)
+, variables(26)
+, local_variables(26)
+, arg_variables(26)
+, exit_on_error(true)
 , m_world(world)
 , inst_set(world->GetHardwareManager().GetInstSet())
 , m_ctx(world->GetDefaultContext())
 , m_jobqueue(world)
 , interactive_depth(0)
 {
-  
   random.ResetSeed(m_world->GetConfig().RANDOM_SEED.Get());
+  if (m_world->GetDriver().IsInteractive()) exit_on_error = false;
   
   for (int i = 0; i < MAX_BATCHES; i++) {
     batch[i].Name().Set("Batch%d", i);
@@ -134,7 +139,8 @@
   
   cString filename = cur_string.PopWord();
   
-  cout << "Loading: " << filename << endl;
+  // Output information about loading file.
+  cout << "Loading: " << filename << '\n';
   
   // Setup the genome...
   cGenome genome( cInstUtil::LoadGenome(filename, inst_set) );
@@ -162,12 +168,12 @@
   
   cString filename = cur_string.PopWord();
   
-  cout << "Loading: " << filename << endl;
+  cout << "Loading: " << filename << '\n';
   
   cInitFile input_file(filename);
   if (!input_file.IsOpen()) {
     cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   input_file.Load();
   input_file.Compress();
@@ -199,17 +205,17 @@
 
 void cAnalyze::LoadDetailDump(cString cur_string)
 {
-  cout << "Warning: Use of LoadDetailDump() is deprecated.  Use \"LOAD\" instead." << endl;  
+  cerr << "Warning: Use of LOAD_DETAIL_DUMP is deprecated.  Use \"LOAD\" instead." << endl;
   // LOAD_DETAIL_DUMP
   
   cString filename = cur_string.PopWord();
   
-  cout << "Loading: " << filename << endl;
+  cout << "Loading: " << filename << '\n';
   
   cInitFile input_file(filename);
   if (!input_file.IsOpen()) {
     cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   input_file.Load();
   input_file.Compress();
@@ -285,9 +291,9 @@
   
   if (m_world->GetVerbosity() >= VERBOSE_ON) {
     cout << "Loading in " << num_steps
-    << " detail files from update " << start_UD
-    << " to update " << stop_UD
-    << endl;
+	 << " detail files from update " << start_UD
+	 << " to update " << stop_UD
+	 << endl;
   } else {
     cout << "Running LOAD_MULTI_DETAIL" << endl;
   }
@@ -302,7 +308,7 @@
     cInitFile input_file(filename);
     if (!input_file.IsOpen()) {
       cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
-      exit(1);
+      if (exit_on_error) exit(1);
     }
     input_file.Load();
     input_file.Compress();
@@ -787,7 +793,7 @@
   // Calculate the stats for the genotypes we're working with ...
   if ( genotype1->GetLength() != genotype2->GetLength() ) {
     cerr << "Error: Two genotypes don't have same length.(cAnalyze::IncreasedInfo)" << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   genotype1->Recalculate(m_ctx, m_testcpu);
@@ -949,7 +955,7 @@
   cInitFile input_file(filename);
   if (!input_file.IsOpen()) {
     cerr << "Error: Cannot load file: \"" << filename << "\"." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   input_file.Load();
   input_file.ReadHeader();
@@ -962,7 +968,7 @@
   if (filetype != "population_data" &&  // Depricated
       filetype != "genotype_data") {
     cerr << "Error: Cannot load files of type \"" << filetype << "\"." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   if (m_world->GetVerbosity() >= VERBOSE_ON) {
@@ -1919,7 +1925,7 @@
   }
   }
 
-void cAnalyze::CommandDetailAverage_Body(ostream& fp, int num_outputs,
+void cAnalyze::CommandDetailAverage_Body(ostream& fp, int nucoutputs,
                                          tListIterator< tDataEntryCommand<cAnalyzeGenotype> > & output_it)
 {
   // Loop through all of the genotypes in this batch...
@@ -1928,8 +1934,8 @@
   cAnalyzeGenotype * next_genotype = batch_it.Next();
   cAnalyzeGenotype * prev_genotype = NULL;
   
-  tArray<cDoubleSum> output_counts(num_outputs);
-  for (int i = 0; i < num_outputs; i++) { output_counts[i].Clear();} 
+  tArray<cDoubleSum> output_counts(nucoutputs);
+  for (int i = 0; i < nucoutputs; i++) { output_counts[i].Clear();} 
   int count; 
   while (cur_genotype != NULL) { 
     count = 0; 
@@ -1949,7 +1955,7 @@
     next_genotype = batch_it.Next();
   }
   fp << batch[cur_batch].Name() << " "; 
-  for (int i = 0; i < num_outputs; i++) {  
+  for (int i = 0; i < nucoutputs; i++) {  
     fp << output_counts[i].Average() << " ";
   } 
   fp << endl;   
@@ -2103,7 +2109,7 @@
   if (cur_string.CountNumWords() < 3) {
     cerr << "Error: must include filename, and min and max batch numbers."
     << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   // Load in the variables...
@@ -2114,7 +2120,7 @@
   if (max_batch < min_batch) {
     cerr << "Error: min_batch=" << min_batch
     << ", max_batch=" << max_batch << "  (incorrect order?)" << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   // Construct a linked list of details needed...
@@ -2670,7 +2676,7 @@
   for (; gen_iterator != genotype_database.end(); ++ gen_iterator) {
     if (gen_iterator->second->GetLength() != length_genome) {
       cerr << "Genotype " << gen_iterator->first << " has different genome length." << endl;
-      exit(1);
+      if (exit_on_error) exit(1);
     }
   }
   
@@ -2696,7 +2702,7 @@
   int size_community = community.size();
   if (size_community == 0) {
     cerr << "There is no genotype in this community." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   typedef pair<int,int> gen_pair;
   map<gen_pair, int> hamming_dist;
@@ -2966,7 +2972,7 @@
       }
       if (cur_total_prob > 1) {
         cout << "Total probability at " << line << " is greater than 0." << endl;
-        exit(1);
+        if (exit_on_error) exit(1);
       }
       double left_prob = 1 - cur_total_prob;
       
@@ -2993,7 +2999,7 @@
       }
       if (sum > 1.001 || sum < 0.999) {
         cout << "Sum of probability is not 1 at line " << line << endl;
-        exit(1);
+        if (exit_on_error) exit(1);
       }
     }
     
@@ -3039,7 +3045,7 @@
       }
       if (sum > 1.001 || sum < 0.999) {
         cout << "Sum of probability is not 1 at line " << line << " " << sum << endl;
-        exit(1);
+        if (exit_on_error) exit(1);
       }
     }
     
@@ -3069,7 +3075,7 @@
         information += entropy_before - entropy_given_env[line];
         if (information < 0) {
           cout << "Negative information at site " << line << endl;
-          exit(1);
+          if (exit_on_error) exit(1);
         }
       }
       
@@ -3411,7 +3417,7 @@
     genotype = community[i];
     if (genotype->GetLength() != length_genome) {
       cerr << "Genotypes in the community do not same genome length.\n";
-      exit(1);
+      if (exit_on_error) exit(1);
     }
     
     // Skip the dead organisms
@@ -3490,7 +3496,7 @@
           }
           cout << endl;
           
-          exit(1);
+          if (exit_on_error) exit(1);
         }
         
         new_info += initial_entropy - conditional_entropy;
@@ -4093,7 +4099,7 @@
     if (lib_null_inst == ko_inst_set.GetInstLib()->GetInstError()) {
       cout << "<cAnalyze::AnalyzeKnockouts> got error:" << endl
       << "  instruction 'NULL' not in current hardware type" << endl;
-      exit(1);
+      if (exit_on_error) exit(1);
     }
     // Add mapping to located instruction. 
     ko_inst_set.AddInst(lib_null_inst.GetOp());
@@ -4463,7 +4469,7 @@
         cout << "<cAnalyze::CommandMapTasks> got error:" << endl;
         cout << " --- instruction \"NULL\" isn't in the instruction library for the" << endl;
         cout << " --- current hardware type." << endl;
-        exit(1);
+        if (exit_on_error) exit(1);
       }
       // Add mapping to located instruction. 
       map_inst_set.AddInst(inst_lib_null_inst.GetOp());
@@ -4720,7 +4726,7 @@
             cout << " --- (probably to class method \"cHardware-of-some-type::initInstLib\"" << endl;
             cout << " --- in file named \"cpu/hardware-of-some-type.cc\".)" << endl;
             cout << " --- bailing-out." << endl;
-            exit(1);
+            if (exit_on_error) exit(1);
           }
           // Add mapping to located instruction. 
           map_inst_set.AddInst(inst_lib_null_inst.GetOp());
@@ -4935,7 +4941,7 @@
   const cInstruction lib_null = map_inst_set.GetInstLib()->GetInst("NULL");
   if (lib_null == map_inst_set.GetInstLib()->GetInstError()) {
     cerr << "Internal ERROR: Instruction 'NULL' not found." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
 
   // Add mapping to located instruction.
@@ -5187,7 +5193,7 @@
         cout << " --- (probably to class method \"cHardware-of-some-type::initInstLib\"" << endl;
         cout << " --- in file named \"cpu/hardware-of-some-type.cc\".)" << endl;
         cout << " --- bailing-out." << endl;
-        exit(1);
+        if (exit_on_error) exit(1);
       }
       // Add mapping to located instruction. 
       map_inst_set.AddInst(inst_lib_null_inst.GetOp());
@@ -5869,7 +5875,7 @@
     if (I_P_E == 0) {
       cerr << "Error: Information between parent and its enviroment is zero."
       << "(cAnalyze::AnalyzeNewInfo)" << endl;
-      exit(1);
+      if (exit_on_error) exit(1);
     }
     
     double H_C_E = AnalyzeEntropy(child_genotype, mu);
@@ -6944,7 +6950,7 @@
   if (m_world->GetVerbosity() >= VERBOSE_ON) cout << "Setting current batch to " << next_batch << endl;
   if (next_batch >= MAX_BATCHES) {
     cerr << "  Error: max batches is " << MAX_BATCHES << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   } else {
     cur_batch = next_batch;
   }
@@ -6999,7 +7005,7 @@
 {
   if (cur_string.GetSize() == 0) {
     cerr << "Duplicate Error: Must include from ID!" << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   int batch_from = cur_string.PopWord().AsInt();
   
@@ -7130,7 +7136,7 @@
 
 void cAnalyze::PrintDebug(cString cur_string)
 {
-  cerr << "::: " << cur_string << endl;
+  cout << "::: " << cur_string << '\n';
 }
 
 void cAnalyze::IncludeFile(cString cur_string)
@@ -7170,7 +7176,7 @@
   int num_args = cur_string.CountNumWords();
   if (num_args < 1) {
     cerr << "Error: Must provide function name when creating function.";
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   cString fun_name = cur_string.PopWord();
@@ -7178,7 +7184,7 @@
   if (FindAnalyzeCommandDef(fun_name) != NULL) {
     cerr << "Error: Cannot create function '" << fun_name
     << "'; already exists." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   if (m_world->GetVerbosity() >= VERBOSE_ON) cout << "Creating function: " << fun_name << endl;
@@ -7284,7 +7290,7 @@
   if (num_args < 3) {
     cerr << "  Error: Must give variable, min and max with FORRANGE!"
     << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   cString var = cur_string.PopWord();
@@ -7375,7 +7381,7 @@
   }
   else {
     cout << "  Error: unknown type " << gen_desc << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   return found_gen;
@@ -7387,7 +7393,7 @@
   if (var.GetSize() != 1 ||
       (var.IsLetter(0) == false && var.IsNumeric(0) == false)) {
     cerr << "Error: Illegal variable " << var << " being used." << endl;
-    exit(1);
+    if (exit_on_error) exit(1);
   }
   
   if (var.IsLowerLetter(0) == true) {
@@ -7516,7 +7522,7 @@
     if (command_fun != NULL) command_fun->Run(this, args, *cur_command);
     else if (!FunctionRun(command, args)) {
       cerr << "Error: Unknown analysis keyword '" << command << "'." << endl;
-      exit(1);
+      if (exit_on_error) exit(1);
     }    
   }
 }

Modified: development/source/analyze/cAnalyze.h
===================================================================
--- development/source/analyze/cAnalyze.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/analyze/cAnalyze.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -11,6 +11,7 @@
 #ifndef cAnalyze_h
 #define cAnalyze_h
 
+#include <iostream>
 #include <vector>
 
 #ifndef cAnalyzeJobQueue_h
@@ -50,6 +51,7 @@
 class cAnalyzeCommand;
 class cAnalyzeFunction;
 class cAnalyzeCommandDefBase;
+class cAnalyzeScreen;
 template <class T> class tDataEntryBase;
 class cInstSet;
 class cAnalyzeGenotype;
@@ -59,9 +61,8 @@
 class cTestCPU;
 class cWorld;
 
-
-class cAnalyze
-{
+class cAnalyze {
+  friend class cAnalyzeScreen;
 #if USE_tMemTrack
   tMemTrack<cAnalyze> mt;
 #endif
@@ -76,17 +77,18 @@
   tList<cAnalyzeCommand> command_list;
   tList<cAnalyzeFunction> function_list;
   tList<cAnalyzeCommandDefBase> command_lib;
-  cString variables[26];
-  cString local_variables[26];
-  cString arg_variables[10];
+  tArray<cString> variables;
+  tArray<cString> local_variables;
+  tArray<cString> arg_variables;
 
+  bool exit_on_error;
+
   cWorld* m_world;
   cInstSet& inst_set;
   cTestCPU* m_testcpu;
   cAvidaContext m_ctx;
   cAnalyzeJobQueue m_jobqueue;
 
-
   // This is the storage for the resource information from resource.dat.  It 
   // is a pair of the update and a vector of the resource concentrations
   std::vector<std::pair<int, std::vector<double> > > resources;
@@ -266,9 +268,8 @@
   void CommandForeach(cString cur_string, tList<cAnalyzeCommand> & clist);
   void CommandForRange(cString cur_string, tList<cAnalyzeCommand> & clist);
 
-  cAnalyze(const cAnalyze &); // @not_implemented
+  cAnalyze(const cAnalyze &); // Intentially not implemented
 
-
 public:
   cAnalyze(cWorld* world);
   ~cAnalyze();
@@ -278,6 +279,10 @@
   
   int GetCurrentBatchID() { return cur_batch; }
   cGenotypeBatch& GetCurrentBatch() { return batch[cur_batch]; }
+  cGenotypeBatch& GetBatch(int id) {
+    assert(id >= 0 && id < MAX_BATCHES);
+    return batch[id];
+  }
   cAnalyzeJobQueue& GetJobQueue() { return m_jobqueue; }
 };
 

Modified: development/source/analyze/cAnalyzeJobQueue.cc
===================================================================
--- development/source/analyze/cAnalyzeJobQueue.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/analyze/cAnalyzeJobQueue.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -42,7 +42,7 @@
   
   // Clean out any waiting jobs
   cAnalyzeJob* job;
-  while (job = m_queue.Pop()) delete job;
+  while ((job = m_queue.Pop())) delete job;
   
   // Set job count so that all workers receive NULL jobs
   m_jobs = num_workers;

Modified: development/source/drivers/cDriverManager.cc
===================================================================
--- development/source/drivers/cDriverManager.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/drivers/cDriverManager.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -28,12 +28,12 @@
 cDriverManager::~cDriverManager()
 {
   cAvidaDriver* adrv;
-  while (adrv = m_adrvs.Pop()) {
+  while ((adrv = m_adrvs.Pop())) {
     delete adrv;
   }
   
   cWorldDriver* wdrv;
-  while (wdrv = m_wdrvs.Pop()) {
+  while ((wdrv = m_wdrvs.Pop())) {
     delete wdrv;
   }
   

Modified: development/source/drivers/cWorldDriver.h
===================================================================
--- development/source/drivers/cWorldDriver.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/drivers/cWorldDriver.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -19,6 +19,7 @@
 # endif
 #endif
 
+#include <iostream>
 
 class cString;
 
@@ -30,7 +31,6 @@
 private:
   cWorldDriver(const cWorldDriver&); // @not_implemented
   cWorldDriver& operator=(const cWorldDriver&); // @not_implemented
-
 public:
   cWorldDriver() { ; }
   virtual ~cWorldDriver() { ; }
@@ -45,6 +45,11 @@
   // Notifications
   virtual void NotifyComment(const cString& in_string) = 0;
   virtual void NotifyWarning(const cString& in_string) = 0;
+
+  // Input/Output
+  virtual bool IsInteractive() { return false; }
+  virtual void Flush() { std::cout.flush(); std::cerr.flush(); }
+  virtual bool ProcessKeypress(int keypress) { return false; }
 };
 
 

Modified: development/source/main/cEventList.cc
===================================================================
--- development/source/main/cEventList.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/main/cEventList.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -109,15 +109,17 @@
   // Returns TRIGGER_END if invalid, TRIGGER_BEGIN for IMMEDIATE
   double t_val = TRIGGER_END;
   switch (trigger) {
-    case IMMEDIATE:
-      t_val = TRIGGER_BEGIN;
-      break;
-    case UPDATE:
-      t_val = m_world->GetStats().GetUpdate();
-      break;
-    case GENERATION:
-      t_val = m_world->GetStats().SumGeneration().Average();
-      break;
+  case IMMEDIATE:
+    t_val = TRIGGER_BEGIN;
+    break;
+  case UPDATE:
+    t_val = m_world->GetStats().GetUpdate();
+    break;
+  case GENERATION:
+    t_val = m_world->GetStats().SumGeneration().Average();
+    break;
+  case UNDEFINED:
+    break;
   }
   return t_val;
 }

Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/main/cPopulationInterface.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -103,7 +103,7 @@
 
 void cPopulationInterface::SpawnDeme()
 {
-  const int num_demes = m_world->GetPopulation().GetNumDemes();
+  // const int num_demes = m_world->GetPopulation().GetNumDemes();
 
   // Spawn the current deme; no target ID will put it into a random deme.
   const int deme_id = m_world->GetPopulation().GetCell(m_cell_id).GetDemeID();

Modified: development/source/main/cSpatialCountElem.h
===================================================================
--- development/source/main/cSpatialCountElem.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/main/cSpatialCountElem.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -29,8 +29,8 @@
   void Rate(double ratein) const { delta += ratein; }
   void State() { amount += delta; delta = 0.0; }
   const double GetAmount() const { return amount; }
-  const double SetAmount(double res) const { amount = res; }
-    void SetPtr(int innum, int inelempt, int inxdist, int  inydist, double indist);
+  void SetAmount(double res) const { amount = res; }
+  void SetPtr(int innum, int inelempt, int inxdist, int  inydist, double indist);
   int GetElemPtr(int innum) { return elempt[innum]; }
   int GetPtrXdist(int innum) { return xdist[innum]; }
   int GetPtrYdist(int innum) { return ydist[innum]; }

Modified: development/source/main/cWorld.cc
===================================================================
--- development/source/main/cWorld.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/main/cWorld.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -43,7 +43,6 @@
 
   // cleanup driver object, if needed
   if (m_own_driver) { assert(m_driver); delete m_driver; m_driver=0; }
-
 }
 
 void cWorld::Setup()

Modified: development/source/targets/avida-viewer/CMakeLists.txt
===================================================================
--- development/source/targets/avida-viewer/CMakeLists.txt	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/CMakeLists.txt	2006-12-12 04:12:56 UTC (rev 1135)
@@ -6,6 +6,8 @@
 )
 
 SET(libviewer_SOURCES
+  cAnalyzeScreen.cc
+  cAnalyzeView.cc
   cBarScreen.cc
   cEnvironmentScreen.cc
   cHistScreen.cc
@@ -15,7 +17,9 @@
   cScreen.cc
   cStatsScreen.cc
   cSymbolUtil.cc
+  cTextViewerAnalyzeDriver.cc
   cTextViewerDriver.cc
+  cTextViewerDriver_Base.cc
   cTextWindow.cc
   cView.cc
   cViewInfo.cc

Modified: development/source/targets/avida-viewer/SConscript
===================================================================
--- development/source/targets/avida-viewer/SConscript	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/SConscript	2006-12-12 04:12:56 UTC (rev 1135)
@@ -3,6 +3,8 @@
 
 environment.Library('cursesviewer',
   [
+    'cAnalyzeScreen.cc',
+    'cAnalyzeView.cc',
     'cBarScreen.cc',
     'cEnvironmentScreen.cc',
     'cHistScreen.cc',
@@ -12,7 +14,9 @@
     'cScreen.cc',
     'cStatsScreen.cc',
     'cSymbolUtil.cc',
+    'cTextViewerAnalyzeDriver.cc',
     'cTextViewerDriver.cc',
+    'cTextViewerDriver_Base.cc',
     'cTextWindow.cc',
     'cView.cc',
     'cViewInfo.cc',

Added: development/source/targets/avida-viewer/cAnalyzeScreen.cc
===================================================================
--- development/source/targets/avida-viewer/cAnalyzeScreen.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cAnalyzeScreen.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,592 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cAnalyzeScreen.h"
+
+#include "cAnalyze.h"
+#include "cAnalyzeCommand.h"
+#include "cAnalyzeCommandDefBase.h"
+#include "cAnalyzeFlowCommand.h"
+#include "cEnvironment.h"
+#include "cGenotype.h"
+#include "cPopulation.h"
+#include "cReaction.h"
+#include "cReactionProcess.h"
+#include "cResource.h"
+#include "cSpecies.h"
+#include "cStats.h"
+#include "cPopulationCell.h"
+#include "cOrganism.h"
+
+using namespace std;
+
+void cAnalyzeScreen::Notify(const cString & in_string)
+{
+  screen_hist.PushRear(in_string);
+}
+
+void cAnalyzeScreen::Draw()
+{
+  if (mode == ANALYZE_MODE_COMMAND_LINE) {
+    DrawCommandLine();
+  } else {
+    DrawMenu();
+  }
+  Update();
+}
+
+void cAnalyzeScreen::DrawCommandLine()
+{
+  // Bottom-right corner gives current mode.
+  PrintOption(Height() - 1, Width() - 25, "[<] Command Line [>]");
+
+  PrintOption(Height() - 1, 2, "Change mode to escape command line ---->");
+  
+  // Last 3 lines are command prompt.
+  SetColor(COLOR_WHITE);
+  Box(Height() - 4, 0, 3, Width(), true);
+}
+
+void cAnalyzeScreen::DrawMenu()
+{
+  // Bottom-right corner gives current mode.
+  PrintOption(Height() - 1, 1, "Use [TAB] and [SHIFT-TAB] to cycle through tabs.");
+  PrintOption(Height() - 1, Width() - 25, "[<] Analyze Menu [>]");
+  UpdateMenu();
+}
+
+
+void cAnalyzeScreen::Update()
+{
+  if (mode == ANALYZE_MODE_COMMAND_LINE) {
+    UpdateCommandLine();
+  } else {
+    UpdateMenu();
+  }
+  // Refresh();
+}
+
+
+void cAnalyzeScreen::UpdateCommandLine_Body()
+{
+  SetBoldColor(COLOR_YELLOW);
+  Print(Height() - 3, 3, "-> ");
+  for (int i = 0; i < nest_depth; i++) {
+    Print(Height() - 3, 6+i*2, "> ");
+  }
+
+  // Flush everything we have in the buffers.
+  m_world->GetDriver().Flush();
+
+  // Print history for the moment...
+  int hist_height = Height() - 6;
+  int start = 0;
+  if (hist_height < screen_hist.GetSize()) {
+    start = screen_hist.GetSize() - hist_height;
+  }
+  
+  int y_line = 1;
+  for (int i = start; i < screen_hist.GetSize(); i++) {
+    const cString & cur_line = screen_hist.GetLine(i);
+    if (cur_line.GetSize() == 0);
+    else if (cur_line[0] == '-') SetColor(COLOR_YELLOW);
+    else if (cur_line[0] == '!') SetBoldColor(COLOR_RED);
+    else SetColor(COLOR_CYAN);
+    Print(y_line, 1, cur_line);
+    ClearToEOL();
+    y_line++;
+  }
+  
+  // Print whatever the user is typing.
+  const int offset = 6 + nest_depth * 2;
+  SetBoldColor(COLOR_YELLOW);
+  Print(Height() - 3, offset, cur_input);
+  ClearToEOL();
+  Move(Height() - 3, offset+cursor_pos);
+  Refresh();
+}
+
+void cAnalyzeScreen::UpdateCommandLine()
+{
+  // Draw user input.
+  UpdateCommandLine_Body();
+  DoInput_CommandLine();
+}
+
+void cAnalyzeScreen::UpdateMenu_Body()
+{
+  // Most of the screen should be  menu of batches, with extra info at bottom.
+  tab_box.Draw();
+
+  // Now, fill in the active tab!
+  SetBoldColor(COLOR_CYAN);
+  switch (tab_box.GetActiveTab()) {
+  case ANALYZE_MENU_TAB_GENOTYPES:
+    UpdateMenu_Genotypes();
+    break;
+  case ANALYZE_MENU_TAB_VARIABLES:
+    UpdateMenu_Variables();
+    break;
+  case ANALYZE_MENU_TAB_COMMANDS:
+    UpdateMenu_Commands();
+    break;
+  case ANALYZE_MENU_TAB_FUNCTIONS:
+    UpdateMenu_Functions();
+    break;
+  }
+
+  Refresh();
+}
+
+void cAnalyzeScreen::UpdateMenu_Genotypes()
+{
+  cString cur_line;
+  cAnalyze& analyze = m_world->GetAnalyze();
+  int cur_batch = analyze.GetCurrentBatchID();
+  int line_num = 0;
+  const int col_width = (Width() - 2) / 3;
+  
+  // Column 1: Batch List
+  SetBoldColor(COLOR_WHITE);
+  Print(4, 3, "Batch  Count  Flags");
+
+  SetBoldColor(COLOR_CYAN);
+  for (int i = 0; i < MAX_BATCHES; i++) {
+    cGenotypeBatch & print_batch = analyze.GetBatch(i);
+    if (i == cur_batch || print_batch.List().GetSize() > 0) {
+      cur_line.Set("%5d  %5d  ", i, print_batch.List().GetSize());
+      if (i == cur_batch) cur_line += "C ";
+      else cur_line += "  ";
+      if (print_batch.IsLineage() == true) cur_line += "L ";
+      else cur_line += "  ";
+      if (print_batch.IsAligned() == true) cur_line += "A";
+      else cur_line += " ";
+      
+      Print(5+line_num, 3, cur_line);
+      line_num++;
+    }
+  }
+
+  SetBoldColor(COLOR_WHITE);
+  Print(6+line_num, 3, "C = Current Batch");
+  Print(7+line_num, 3, "L = Is Lineage");
+  Print(8+line_num, 3, "A = Is Aligned");
+
+  // Column 2: Genotype List
+  SetColor(COLOR_WHITE);
+  VLine(col_width, 2, Height()-3);
+
+  SetBoldColor(COLOR_WHITE);
+  Print(4, col_width+2, "ID       Fitness   Length");
+
+  // Column 3: Genotype Stats
+  SetColor(COLOR_WHITE);
+  VLine(2*col_width, 2, Height()-3);
+}
+
+void cAnalyzeScreen::UpdateMenu_Variables()
+{
+  Print(5, 3, "This will be a menu listing the state of all variables.");
+}
+
+void cAnalyzeScreen::UpdateMenu_Commands()
+{
+  Print(5, 3, "This will be a menu of available analyze commands.");
+}
+
+void cAnalyzeScreen::UpdateMenu_Functions()
+{
+  Print(5, 3, "This will be a menu of user-defined functions.");
+}
+
+
+void cAnalyzeScreen::UpdateMenu()
+{
+  UpdateMenu_Body();
+  DoInput_Menu();
+}
+
+void cAnalyzeScreen::DoInput_CommandLine()
+{
+  // Do not let go of input until told to.
+  NoDelay(false);
+  bool finished = false;
+  while (!finished) {
+    int cur_char = GetInput();
+    if (cur_char == ERR) continue;
+
+    // Determine if a recognized symbol was typed...
+    bool symbol = false;
+    if ((cur_char == ' ') || (cur_char == '!') || (cur_char == '@') ||
+	(cur_char == '#') || (cur_char == '$') || (cur_char == '%') ||
+	(cur_char == '^') || (cur_char == '&') || (cur_char == '*') ||
+	(cur_char == '(') || (cur_char == ')') || (cur_char == '-') ||
+	(cur_char == '_') || (cur_char == '+') || (cur_char == '=') ||
+	(cur_char == '{') || (cur_char == '}') || (cur_char == '[') ||
+	(cur_char == ']') || (cur_char == ':') || (cur_char == ';') ||
+	(cur_char == '"') || (cur_char == '\'') || (cur_char == '|') ||
+	(cur_char == '\\') || (cur_char == '<') || (cur_char == '>') ||
+	(cur_char == ',') || (cur_char == '.') || (cur_char == '?') ||
+	(cur_char == '/') || (cur_char == '~') || (cur_char == '`')) {
+      symbol = true;
+    }
+
+    // See if we should add the character typed to the regular input.
+    if ((cur_char >= 'a' && cur_char <= 'z') ||
+	(cur_char >= 'A' && cur_char <= 'Z') ||
+	(cur_char >= '0' && cur_char <= '9') ||
+	cur_input.GetSize() > 0 && symbol == true) {
+      // A legal character has been added to the command at the prompt.
+      // cur_input += (char) cur_char;
+      cur_input.Insert((char) cur_char, cursor_pos);
+      rollback_line = 0;
+      cursor_pos++;
+      UpdateCommandLine_Body();
+      continue;
+    }
+
+    // For other keystrokes, we can use a switch statement...
+    switch (cur_char) {
+    case KEY_BACKSPACE:
+      if (cursor_pos > 0) {
+	cur_input.Clip(cursor_pos-1, 1);
+	cursor_pos--;
+      }
+      rollback_line = 0;
+      break;
+
+    case 1:  // CTRL-A (jump to beginning of line)
+      cursor_pos = 0;
+      break;
+
+//  case 2: CTRL-B == move left (see KEY_LEFT below)
+
+    case 3: // CTRL-C (quit)
+      exit(0);
+      break;
+
+    case 4: // CTRL-D (delete)
+      if (cursor_pos < cur_input.GetSize()) {
+	cur_input.Clip(cursor_pos, 1);
+      }
+      rollback_line = 0;
+      break;
+
+    case 5: // CTRL-E (end-of-line);
+      cursor_pos = cur_input.GetSize();
+      break;
+
+//  case 6: CTRL-F == move right (see KEY_RIGHT below)
+
+    case 11: // CTRL-K (cut)
+      if (cursor_pos == cur_input.GetSize()) break;
+      cut_line = cur_input.Substring(cursor_pos, cur_input.GetSize() - cursor_pos);
+      cur_input.Clip(cursor_pos);
+      break;
+
+    case 21:     // CTRL-U (delete line)
+      cur_input = "";
+      cursor_pos = 0;
+      rollback_line = 0;
+      break;
+
+    case 25:     // CTRL-Y (paste)
+      if (cut_line.GetSize() > 0) {
+	cur_input.Insert(cut_line, cursor_pos);
+	cursor_pos += cut_line.GetSize();
+      }
+      break;
+
+    case 26:     // CTRL-Z (suspend process)
+      kill(getpid(), SIGTSTP);
+      break;
+
+    case '\n':
+    case '\r':
+      // Only look at non-empty lines...
+      if (cur_input != "") ProcessCommandLine();
+      break;
+
+    case '\t':
+      // @CAO TAB COMPLETE!
+      break;
+
+    case '<':
+    case ',':
+    case '>':
+    case '.':
+      mode = ANALYZE_MODE_MENU;
+      Clear();
+      Draw();
+      finished = true;
+      break;
+
+    case KEY_UP:
+      {
+	rollback_line++;
+	int id = command_hist.GetSize() - rollback_line;
+	if (id < 0) { id = 0; rollback_line = command_hist.GetSize(); }
+	if (command_hist.GetSize() > 0) cur_input = command_hist.GetLine(id);
+	cursor_pos = cur_input.GetSize();
+      }
+      break;
+      
+    case KEY_DOWN:
+      rollback_line--;
+      if (rollback_line > 0) {
+	int id = command_hist.GetSize() - rollback_line;
+	cur_input = command_hist.GetLine(id);
+      } else {
+	rollback_line = 0;
+	cur_input = "";
+      }
+      cursor_pos = cur_input.GetSize();
+      break;
+
+    case KEY_LEFT:
+    case 2:             // CTRL-B (move left)
+      cursor_pos--;
+      if (cursor_pos < 0) cursor_pos = 0;
+      break;
+
+    case KEY_RIGHT:
+    case 6:             // CTRL-F (move right)
+      cursor_pos++;
+      if (cursor_pos > cur_input.GetSize()) cursor_pos = cur_input.GetSize();
+      break;
+
+    default:
+      Print(10, 70, "** %d **", (int) cur_char);
+    }
+
+    // If we're not finished, refresh the screen...
+    // (remember: we only made it here if there *was* a keypress.)
+    if (finished == false) {
+      UpdateCommandLine_Body();
+    }
+  }
+
+  NoDelay(true);
+}
+
+
+void cAnalyzeScreen::DoInput_Menu()
+{
+  // Do not let go of input until told to.
+  NoDelay(false);
+  bool finished = false;
+
+  while (!finished) {
+    int cur_char = GetInput();
+    if (cur_char == ERR) continue;
+
+    // Test the keystroke...
+    switch (cur_char) {
+    case 25:     // CTRL-Y or SHIFT-TAB
+      tab_box.PrevTab();      
+      break;
+
+    case 26:     // CTRL-Z (suspend process)
+      kill(getpid(), SIGTSTP);
+      break;
+
+   case '\t':
+      tab_box.NextTab();
+      break;
+
+    case '<':
+    case ',':
+    case '>':
+    case '.':
+      mode = ANALYZE_MODE_COMMAND_LINE;
+      Clear();
+      Draw();
+      finished = true;
+      break;
+
+    case KEY_LEFT:
+      break;
+
+    case KEY_RIGHT:
+      break;
+
+    default:
+      {
+	int tab_result = tab_box.DoKeypress(cur_char);
+	if (tab_result == -1) {
+	  if (m_world->GetDriver().ProcessKeypress(cur_char) == true) {
+	    finished = true;
+	  } else {
+	    Print(10, 70, "** %d **", (int) cur_char);
+	  }
+	}
+      }
+    }
+
+    // If we're not finished, refresh the screen...
+    // (remember: we only made it here if there *was* a keypress.)
+    if (finished == false) {
+      UpdateMenu_Body();
+    }
+  }
+
+  NoDelay(true);
+}
+
+void cAnalyzeScreen::ProcessCommandLine()
+{
+  // Get the analyze module...
+  cAnalyze& analyze = m_world->GetAnalyze();
+
+  // Save the original input and divide up the rest into command and args.
+  cString orig_input = cur_input;
+  cString command = cur_input.PopWord();
+  cString command_args = cur_input;
+
+  // Reset various tracking values.
+  cur_input = "";
+  rollback_line = 0;
+  cursor_pos = 0;
+
+  // Grab the command portion of this input and set to uppercase.
+  command.ToUpper();
+  bool command_found = false;
+  
+  // Check some builtin commands.
+  if (command == "QUIT" || command == "EXIT") exit(0);
+  
+  // Check to see if we are ending a loop.
+  if (command == "END") {
+    if (nest_depth == 0) exit(0);
+    // Reduce the nest_depth.
+    nest_depth--;
+
+    // If the loop we finished is at the outermost level, execute it!
+    if (nest_depth == 0) {
+      cAnalyzeCommand * cur_command = nest_command.Pop();
+      command_args = cur_command->GetArgs();
+      analyze.PreProcessArgs(command_args);
+      cAnalyzeCommandDefBase* command_fun =
+	analyze.FindAnalyzeCommandDef(cur_command->GetCommand());
+      command_fun->Run(&analyze, command_args, *cur_command);
+    }
+    // Otherwise store it...
+    else {
+      cAnalyzeCommand * cur_command = nest_command.Pop();
+      nest_command.GetFirst()->GetCommandList()->PushRear(cur_command);
+    }
+
+    command_found = true;
+  }
+
+  // Check some other built-in commands.
+  if (command == "CLEAR") {
+    screen_hist.Clear();
+    command_found = true;
+  }
+
+  // Store this command in the history.
+  command_hist.PushRear(orig_input);
+  cString out_input("-> ");
+  for (int i = 0; i < nest_depth; i++) {
+    out_input +=  "> ";
+  }
+  out_input += orig_input;
+  screen_hist.PushRear(out_input);  
+
+  // If the command has already been found, stop here.
+  if (command_found == true) return;
+
+  // Check the analyze mode for the command.
+  cAnalyzeCommand* cur_command;
+  cAnalyzeCommandDefBase* command_fun = analyze.FindAnalyzeCommandDef(command);
+  
+  // First check for built-in functions...
+  if (command_fun != NULL) {
+    if (command_fun->IsFlowCommand()) {
+      // This is a flow command; it should have a body to it.
+      cur_command = new cAnalyzeFlowCommand(command, command_args);
+      nest_command.Push(cur_command);
+      nest_depth++;
+    } else {  // This is a regular command.
+      // If this command is at the outermost level, Execute it!
+      if (nest_depth == 0) {
+	cur_command = new cAnalyzeCommand(command, command_args);
+	analyze.PreProcessArgs(command_args);
+	command_fun->Run(&analyze, command_args, *cur_command);
+      }
+      // Otherwise store it...
+      else {
+	cur_command = new cAnalyzeCommand(command, command_args);
+	nest_command.GetFirst()->GetCommandList()->PushRear(cur_command);
+      }
+    }
+  }
+  // Then for user defined functions
+  else if (analyze.FunctionRun(command, command_args) == true) { }
+  // Otherwise, give an error.
+  else {
+    cString out_string = "! Error: Unknown command '";
+    out_string += command;
+    out_string += "'.";
+    screen_hist.PushRear(out_string);
+  }
+  
+  // Deal with collected feedback from analyze mode.
+  m_world->GetDriver().Flush();
+}
+
+void cAnalyzeScreen::DoInput(int in_char)
+{
+  // For the moment, redirect to update!
+  Update();
+
+
+  SetBoldColor(COLOR_CYAN);
+  
+  // Keys that work similarly in both modes.
+  switch (in_char) {
+  case '>':
+  case '.':
+  case '<':
+  case ',':
+    if (mode == ANALYZE_MODE_COMMAND_LINE) {
+      mode = ANALYZE_MODE_MENU;
+    } else {
+      mode = ANALYZE_MODE_COMMAND_LINE;
+    }
+    Clear();
+    Draw();
+    break;
+  }
+  
+  if (mode == ANALYZE_MODE_COMMAND_LINE) {
+    switch (in_char) {
+    case KEY_DOWN:
+      // Scroll down through previous selections.
+      Update();
+      break;
+    case KEY_UP:
+      Update();
+      break;
+    }
+  }
+  else if (mode == ANALYZE_MODE_MENU) {
+    switch (in_char) {
+    case KEY_DOWN:
+      // Scroll down through previous selections.
+      Update();
+      break;
+    case KEY_UP:
+      Update();
+      break;
+    }
+  }
+  else { // Invalid mode state!
+  }
+
+}

Added: development/source/targets/avida-viewer/cAnalyzeScreen.h
===================================================================
--- development/source/targets/avida-viewer/cAnalyzeScreen.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cAnalyzeScreen.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,108 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef cAnalyzeScreen_h
+#define cAnalyzeScreen_h
+
+#ifndef cTabBox_h
+#include "cTabBox.h"
+#endif
+
+#ifndef cStringList_h
+#include "cStringList.h"
+#endif
+
+#ifndef cScreen_h
+#include "cScreen.h"
+#endif
+
+class cAnalyzeCommand;
+class cWorld;
+
+class cAnalyzeScreen : public cScreen {
+protected:
+  cWorld* m_world;
+  int mode;
+
+  // Manage the menu mode.
+  cTabBox tab_box;
+
+  // Manage the command line.
+  cString cur_input;
+  cStringList command_hist;
+  cStringList screen_hist;
+  tList<cAnalyzeCommand> nest_command;
+  int rollback_line;
+  int cursor_pos;
+  int nest_depth;
+
+  cString cut_line;
+  
+  static const int ANALYZE_MODE_COMMAND_LINE = 0;
+  static const int ANALYZE_MODE_MENU = 1;
+
+  static const int ANALYZE_MENU_TAB_GENOTYPES = 0;
+  static const int ANALYZE_MENU_TAB_VARIABLES = 1;
+  static const int ANALYZE_MENU_TAB_COMMANDS = 2;
+  static const int ANALYZE_MENU_TAB_FUNCTIONS = 3;
+
+  void UpdateCommandLine_Body();
+  void DoInput_CommandLine();
+  void UpdateMenu_Body();
+  void UpdateMenu_Genotypes();
+  void UpdateMenu_Variables();
+  void UpdateMenu_Commands();
+  void UpdateMenu_Functions();
+  void DoInput_Menu();
+
+  void ProcessCommandLine();
+public:
+  cAnalyzeScreen(cWorld* world, int y_size, int x_size, int y_start, int x_start, cViewInfo& in_info)
+    : cScreen(y_size, x_size, y_start, x_start, in_info)
+    , m_world(world)
+    , tab_box(this, 0, 0, Height() - 1, Width())
+    , rollback_line(0)
+    , cursor_pos(0)
+    , nest_depth(0)
+    , cut_line(0)
+  {
+    mode = ANALYZE_MODE_MENU;
+
+    // Setup the tab box in menu mode.
+    tab_box.AddTab("[G]enotypes");
+    tab_box.AddTab("[V]ariables");
+    tab_box.AddTab("[C]ommands");
+    tab_box.AddTab("[F]unctions");
+  }
+  virtual ~cAnalyzeScreen() { ; }
+
+  void Notify(const cString & in_string);
+
+  // Virtual in base screen...
+  void Draw();
+  void Update();
+  void DoInput(int in_char);
+
+  void DrawCommandLine();
+  void DrawMenu();
+  void UpdateCommandLine();
+  void UpdateMenu();
+};
+
+
+#ifdef ENABLE_UNIT_TESTS
+namespace nEnvironmentScreen {
+  /**
+   * Run unit tests
+   *
+   * @param full Run full test suite; if false, just the fast tests.
+   **/
+  void UnitTests(bool full = false);
+}
+#endif  
+
+#endif

Added: development/source/targets/avida-viewer/cAnalyzeView.cc
===================================================================
--- development/source/targets/avida-viewer/cAnalyzeView.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cAnalyzeView.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,232 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cAnalyzeView.h"
+
+#include "cEnvironment.h"
+#include "cGenotype.h"
+#include "cOrganism.h"
+#include "cPhenotype.h"
+#include "cPopulation.h"
+#include "cPopulationCell.h"
+#include "cStats.h"
+#include "cTestUtil.h"
+#include "cHardwareBase.h"
+
+#include "cMenuWindow.h"
+#include "cTextWindow.h"
+#include "cBarScreen.h"
+#include "cAnalyzeScreen.h"
+
+#include <fstream>
+
+using namespace std;
+
+cTextWindow * cAnalyzeView::base_window = NULL;
+cBarScreen* cAnalyzeView::bar_screen = NULL;
+
+
+cAnalyzeView::cAnalyzeView(cWorld* world) : info(world, this)
+{
+  Setup("Avida");
+
+  analyze_screen = new cAnalyzeScreen(world, 0, 0, 3, 0, info);
+}
+
+cAnalyzeView::~cAnalyzeView()
+{
+  if (analyze_screen) delete analyze_screen;
+  EndProg(0);
+}
+
+void cAnalyzeView::Setup(const cString & in_name)
+{
+  // Setup text-interface
+  StartProg();
+
+  bar_screen = new cBarScreen(&info.GetWorld(), 3, 0, 0, 0, info, in_name);
+  base_window = new cTextWindow(0,0,3,0);
+  bar_screen->Draw();
+}
+
+void cAnalyzeView::Refresh()
+{
+  base_window->Redraw();
+  bar_screen->Redraw();
+  analyze_screen->Clear();
+  analyze_screen->Draw();
+}
+
+void cAnalyzeView::Redraw()
+{
+  bar_screen->Redraw();
+  analyze_screen->Redraw();
+}
+
+
+void cAnalyzeView::NotifyUpdate()
+{
+  bar_screen->Redraw();
+  analyze_screen->Redraw();
+  DoInputs();
+}
+
+void cAnalyzeView::NotifyError(const cString & in_string)
+{
+  cString out_string(in_string);
+  out_string.Insert("Error: ");
+  Notify(out_string);
+  EndProg(1);
+}
+
+void cAnalyzeView::NotifyWarning(const cString & in_string)
+{
+  cString out_string(in_string);
+  out_string.Insert("Warning: ");
+  Notify(out_string);
+}
+
+void cAnalyzeView::NotifyComment(const cString & in_string)
+{
+  analyze_screen->Notify(in_string);
+}
+
+void cAnalyzeView::NotifyOutput(const cString & in_string)
+{
+  analyze_screen->Notify(in_string);
+  analyze_screen->Refresh();
+}
+
+
+void cAnalyzeView::DoInputs()
+{
+  // @CAO For the moment, redirect to update!
+  //  analyze_screen->Update();
+
+  int cur_char = ERR;
+
+  // If there is any input in the buffer, process all of it.
+  while ((cur_char = GetInput()) != ERR) {
+    switch (cur_char) {
+    case 'q':
+      if (!Confirm("Are you sure you want to quit?")) break;
+    case 'Q':      // Note: Capital 'Q' quits w/o confirming.
+      // clear the windows before we go.  Do bar window last to end at top.
+      base_window->Redraw();
+      bar_screen->Clear();
+      bar_screen->Refresh();
+      EndProg(0);  // This implementation calls exit(), blowing us clean away
+      break;
+    case 12: // Ideally this is CTRL-L...
+      Refresh();
+      break;
+    default:
+      analyze_screen->DoInput(cur_char);
+      break;
+    }
+  }
+}
+
+
+int cAnalyzeView::Confirm(const cString & message)
+{
+  const int mess_length = message.GetSize();
+
+  // Create a confirm window, and draw it on the screen.
+
+  cTextWindow * conf_win
+    = new cTextWindow(3, mess_length + 10, 10, (base_window->Width() - 10 - mess_length) / 2);
+  conf_win->Box();
+  conf_win->SetBoldColor(COLOR_WHITE);
+  conf_win->Print(1, 2, "%s (y/n)", static_cast<const char*>(message));
+  conf_win->SetBoldColor(COLOR_CYAN);
+  conf_win->Print(1, mess_length + 4, 'y');
+  conf_win->Print(1, mess_length + 6, 'n');
+  conf_win->SetColor(COLOR_WHITE);
+  conf_win->Refresh();
+
+  // Wait for the results.
+  bool finished = false;
+  bool result = false;
+  int cur_char;
+
+  while (finished == false) {
+    cur_char = GetInput();
+    switch (cur_char) {
+    case 'q':
+    case 'Q':
+    case 'n':
+    case 'N':
+    case ' ':
+    case '\n':
+    case '\r':
+      finished = true;
+      result = false;
+      break;
+    case 'y':
+    case 'Y':
+      finished = true;
+      result = true;
+      break;
+    }
+  }
+
+  // Delete the window, redraw the screen, and return the results.
+  delete conf_win;
+  Redraw();
+  return result;
+}
+
+void cAnalyzeView::Notify(const cString & message)
+{
+  cString mess_copy(message);
+
+  // Setup all of the individual lines.
+  int num_lines = message.CountNumLines();
+  cString * line_array = new cString[num_lines];
+  int max_width = 0;
+  for (int i = 0; i < num_lines; i++) {
+    line_array[i] = mess_copy.PopLine();
+    if (line_array[i].GetSize() > max_width)
+      max_width = line_array[i].GetSize();
+  }
+
+  // Create a window and draw it on the screen.
+
+  cTextWindow * notify_win
+    = new cTextWindow(2 + num_lines, max_width + 4, (24 - num_lines - 3) / 2,
+		      (70 - max_width) / 2);
+  notify_win->Box();
+  notify_win->SetBoldColor(COLOR_WHITE);
+  for (int j = 0; j < num_lines; j++) {
+    notify_win->Print(1 + j, 2, "%s", static_cast<const char*>(line_array[j]));
+  }
+  notify_win->Refresh();
+
+  // Wait for the results.
+  bool finished = false;
+  int cur_char;
+
+  while (!finished) {
+    cur_char = GetInput();
+    switch (cur_char) {
+    case 'q':
+    case 'Q':
+    case ' ':
+    case '\n':
+    case '\r':
+      finished = true;
+      break;
+    }
+  }
+
+  // Delete the window and redraw the screen.
+  delete notify_win;
+  delete [] line_array;
+  Redraw();
+}
+

Added: development/source/targets/avida-viewer/cAnalyzeView.h
===================================================================
--- development/source/targets/avida-viewer/cAnalyzeView.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cAnalyzeView.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,79 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2001 California Institute of Technology             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef cAnalyzeView_h
+#define cAnalyzeView_h
+
+#ifndef cViewInfo_h
+#include "cViewInfo.h"
+#endif
+
+#ifndef cView_Base_h
+#include "cView_Base.h"
+#endif
+
+class cScreen;
+class cTextWindow;
+class cBarScreen;
+class cAnalyzeScreen;
+class cWorld;
+
+class cAnalyzeView : public cView_Base {
+private:
+  cViewInfo info;
+
+  // Window information...
+  static cTextWindow * base_window;
+  static cBarScreen * bar_screen;
+  cAnalyzeScreen * analyze_screen;
+
+  // Input function
+  void DoInputs();
+
+public:
+  cAnalyzeView(cWorld* world);
+  ~cAnalyzeView();
+
+  void Setup(const cString & in_name);
+  void SetViewMode(int in_mode) { (void) in_mode; }
+
+  bool ProcessKeypress(int keypress) { return false; }
+
+  void NewUpdate() { ; }
+  void NotifyUpdate();
+  void NotifyError(const cString & in_string);
+  void NotifyWarning(const cString & in_string);
+  void NotifyComment(const cString & in_string);
+  void NotifyOutput(const cString & in_string);
+  void Pause() { ; }
+  void DoBreakpoint() { ; }
+
+  int Confirm(const cString & message);
+  void Notify(const cString & message);
+
+  int GetStepOrganism() { return -1; }
+  void SetStepOrganism(int in_id) { (void) in_id; }
+
+  void Refresh();
+
+  // Methods called by sub-windows.
+  void Redraw();
+};
+
+
+#ifdef ENABLE_UNIT_TESTS
+namespace nAnalyzeView {
+  /**
+   * Run unit tests
+   *
+   * @param full Run full test suite; if false, just the fast tests.
+   **/
+  void UnitTests(bool full = false);
+}
+#endif  
+
+#endif

Modified: development/source/targets/avida-viewer/cBaseTextWindow.h
===================================================================
--- development/source/targets/avida-viewer/cBaseTextWindow.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cBaseTextWindow.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -129,7 +129,7 @@
   // coords and a length, they only draw the line from the specified start,
   // to the specified distance.
   virtual void Box() = 0;
-  virtual void Box(int x, int y, int w, int h) = 0;
+  virtual void Box(int y, int x, int h, int w, bool test) = 0;
   virtual void VLine(int in_x) = 0;
   virtual void HLine(int in_y) = 0;
   virtual void HLine(int in_y, int start_x, int length) = 0;

Modified: development/source/targets/avida-viewer/cEnvironmentScreen.cc
===================================================================
--- development/source/targets/avida-viewer/cEnvironmentScreen.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cEnvironmentScreen.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -84,7 +84,7 @@
   
   
   SetColor(COLOR_WHITE);
-  Box(0, res_lib.GetSize()+2, Width(), Height()-res_lib.GetSize()-2);
+  Box(res_lib.GetSize()+2, 0, Height()-res_lib.GetSize()-2, Width(), true);
   
   SetBoldColor(COLOR_YELLOW);
   Print(1, 58, "Resource View");
@@ -115,7 +115,7 @@
   }  
   
   SetColor(COLOR_WHITE);
-  Box(0, rxn_lib.GetSize()+2, Width(), Height()-rxn_lib.GetSize()-2);
+  Box(rxn_lib.GetSize()+2, 0, Height()-rxn_lib.GetSize()-2, Width(), true);
   
   SetBoldColor(COLOR_YELLOW);
   Print(1, 58, "Reaction View");

Modified: development/source/targets/avida-viewer/cOptionsScreen.cc
===================================================================
--- development/source/targets/avida-viewer/cOptionsScreen.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cOptionsScreen.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -65,7 +65,7 @@
   }
 
   SetColor(COLOR_WHITE);
-  Box(0, Height() - 7, Width(), 7);
+  Box(Height() - 7, 0, 7, Width(), true);
 
   SetBoldColor(COLOR_CYAN);
   Print(6, 15, "%dx%d", info.GetPopulation().GetWorldX(),

Modified: development/source/targets/avida-viewer/cStatsScreen.cc
===================================================================
--- development/source/targets/avida-viewer/cStatsScreen.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cStatsScreen.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -71,7 +71,7 @@
 
   SetColor(COLOR_WHITE);
 
-  Box(0, 14, Width(), task_rows + 2);
+  Box(14, 0, task_rows + 2, Width(), true);
 
   if (task_num < info.GetWorld().GetNumTasks() || task_offset != 0) {
     SetBoldColor(COLOR_WHITE);

Added: development/source/targets/avida-viewer/cTabBox.h
===================================================================
--- development/source/targets/avida-viewer/cTabBox.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTabBox.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,133 @@
+/*
+ *  cTabBox.h
+ *  Avida
+ *
+ *  Copyright 2006 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef cTabBox_h
+#define cTabBox_h
+
+#ifndef cStringList_h
+#include "cStringList.h"
+#endif
+
+#ifndef cTextWindow_h
+#include "cTextWindow.h"
+#endif
+
+#ifndef tArray_h
+#include "tArray.h"
+#endif
+
+class cTabBox {
+private:
+  cTextWindow * window;
+  int y;
+  int x;
+  int rows;
+  int cols;
+
+  tArray<cString> tabname_array;
+  tArray<char> optkey_array;
+  int active_tab;
+
+  // Find the position of the option character in a string.
+  int FindOption(const cString & option) {
+    const int found_pos = option.Find('[');
+    if (found_pos == -1) return -1;
+    return found_pos + 1;
+  }
+
+public:
+  cTabBox(cTextWindow * _window, int _y, int _x, int _rows, int _cols)
+    : window(_window), y(_y), x(_x), rows(_rows), cols(_cols)
+    , active_tab(0)
+  {
+    assert(rows > 4); // Need 4 rows to fit box and tabs; more for body!
+  }
+  ~cTabBox() { ; }
+
+  int GetNumTabs() const { return tabname_array.GetSize(); }
+  int GetActiveTab() const { return active_tab; }
+  void AddTab(const cString & name) {
+    // Save the name of the tab.
+    tabname_array.Push(name);
+
+    // Determine if we have a keypress associated with the tab.
+    const int opt_pos = FindOption(name);
+    char opt_char = 0; // Default key char to zero.
+    if (opt_pos > 0) {
+      // Determine the character and convert it to lowercase.
+      opt_char = name[opt_pos];
+      if (opt_char >= 'A' && opt_char <= 'Z') opt_char = opt_char - 'A' + 'a';
+    }
+    optkey_array.Push(opt_char);
+  }
+
+  void SetActiveTab(int tab_id) {
+    assert(tab_id >= 0 && tab_id < tabname_array.GetSize());
+    active_tab = tab_id;
+  }
+  void NextTab() { ++active_tab %= tabname_array.GetSize(); }
+  void PrevTab() { if (--active_tab < 0) active_tab = GetNumTabs()-1; }
+  int DoKeypress(int keypress) {
+    // Loop through all tabs to see if this keypress matches one of them.
+    for (int tab_id = 0; tab_id < optkey_array.GetSize(); tab_id++) {
+      if (keypress == optkey_array[tab_id]) {
+	SetActiveTab(tab_id);
+	return tab_id;
+      }
+    }
+    return -1;
+  }
+
+  void Draw() {
+    window->SetColor(COLOR_WHITE);
+    // Draw the main box...
+    for (int i = 2; i < rows-2; i++) {
+      window->Move(y+i, 0);
+      window->ClearToEOL();
+    }
+    window->Box(y+2, x, rows-2, cols, true);
+
+    // Draw tabs...
+    int offset = 2;
+    int active_offset;
+    for (int tab_id = 0; tab_id < tabname_array.GetSize(); tab_id++) {
+      const cString & cur_name = tabname_array[tab_id];
+      const int tab_width = cur_name.GetSize() + 4;
+      window->Box(y, x+offset, 3, tab_width, true);
+      if (tab_id == active_tab) active_offset = offset; //(come back to this!)
+      else {
+	window->Print(y+1, x+offset+2, cur_name);
+	window->SetColor(COLOR_YELLOW);
+	const int opt_pos = FindOption(cur_name);
+	window->Print(y+1, x+offset+2+opt_pos, cur_name[opt_pos]);
+	window->SetColor(COLOR_WHITE);
+      }
+      window->Print(y+2, x+offset, CHAR_BTEE);
+      offset += tab_width;
+      window->Print(y+2, x+offset-1, CHAR_BTEE);
+   }
+
+    // Draw in the active window.
+    const cString & active_name = tabname_array[active_tab];
+    const int active_width = active_name.GetSize() + 4;
+    window->Box(y, x+active_offset, 3, active_width, true);
+    window->SetBoldColor(COLOR_YELLOW);
+    window->Print(y+1, x+active_offset+2, active_name);
+    window->SetColor(COLOR_WHITE);
+    window->Print(y+2, x+active_offset, CHAR_LRCORNER);
+    window->Print(y+2, x+active_offset+active_width-1, CHAR_LLCORNER);
+
+    for (int i = 1; i < active_width - 1; i++) {
+      window->Print(y+2, x+active_offset+i, ' ');
+    }
+
+    window->Move(3, window->Width()-1);
+  }
+};
+
+#endif

Added: development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.cc
===================================================================
--- development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,78 @@
+/*
+ *  cTextViewerAnalyzeDriver.cc
+ *  Avida
+ *
+ *  Created by David on 12/11/05.
+ *  Copyright 2005-2006 Michigan State University. All rights reserved.
+ *
+ */
+
+#include "cTextViewerAnalyzeDriver.h"
+
+#include "cAnalyze.h"
+#include "cAnalyzeView.h"
+#include "cChangeList.h"
+#include "cClassificationManager.h"
+#include "cDriverManager.h"
+#include "cGenotype.h"
+#include "cHardwareBase.h"
+#include "cOrganism.h"
+#include "cPopulation.h"
+#include "cPopulationCell.h"
+#include "cStats.h"
+#include "cString.h"
+#include "cWorld.h"
+
+#include <stdlib.h>
+
+using namespace std;
+
+
+cTextViewerAnalyzeDriver::cTextViewerAnalyzeDriver(cWorld* world, bool inter)
+  : cTextViewerDriver_Base(world), m_interactive(inter)
+{
+  m_view = new cAnalyzeView(world);
+
+  cDriverManager::Register(static_cast<cAvidaDriver*>(this));
+  world->SetDriver(this);
+}
+
+cTextViewerAnalyzeDriver::~cTextViewerAnalyzeDriver()
+{
+  cDriverManager::Unregister(static_cast<cAvidaDriver*>(this));
+
+  if (m_view != NULL) EndProg(0);
+}
+
+
+void cTextViewerAnalyzeDriver::Run()
+{
+  // cAnalyze& analyze = m_world->GetAnalyze();
+  // cAvidaContext ctx(m_world->GetRandom());
+
+  while (!m_done) {
+    // Setup the viewer for the new update.
+    m_view->NotifyUpdate();
+  }
+}
+
+void cTextViewerAnalyzeDriver::RaiseException(const cString& in_string)
+{
+  m_view->NotifyError(in_string);
+}
+
+void cTextViewerAnalyzeDriver::RaiseFatalException(int exit_code, const cString& in_string)
+{
+  m_view->NotifyError(in_string);
+  exit(exit_code);
+}
+
+void cTextViewerAnalyzeDriver::NotifyComment(const cString& in_string)
+{
+  m_view->NotifyComment(in_string);
+}
+
+void cTextViewerAnalyzeDriver::NotifyWarning(const cString& in_string)
+{
+  m_view->NotifyWarning(in_string);
+}

Added: development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.h
===================================================================
--- development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerAnalyzeDriver.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,58 @@
+/*
+ *  cTextViewerAnalyzeDriver.h
+ *  Avida
+ *
+ *  Copyright 2006 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef cTextViewerAnalyzeDriver_h
+#define cTextViewerAnalyzeDriver_h
+
+#ifndef cTextViewerDriver_Base_h
+#include "cTextViewerDriver_Base.h"
+#endif
+
+class cAnalyzeView;
+
+class cTextViewerAnalyzeDriver : public cTextViewerDriver_Base
+{
+private:
+  cTextViewerAnalyzeDriver(); // @not_implemented
+  cTextViewerAnalyzeDriver(const cTextViewerAnalyzeDriver&); // @not_implemented
+  cTextViewerAnalyzeDriver& operator=(const cTextViewerAnalyzeDriver&); // @not_implemented
+  
+protected:
+  bool m_interactive;
+  
+public:
+  cTextViewerAnalyzeDriver(cWorld* world, bool inter = false);
+  ~cTextViewerAnalyzeDriver();
+  
+  void Run();
+  
+  // Driver Actions
+  void SignalBreakpoint() { return; }
+  void SetDone() { m_done = true; }
+  
+  void RaiseException(const cString& in_string);
+  void RaiseFatalException(int exit_code, const cString& in_string);
+  
+  // Notifications
+  void NotifyComment(const cString& in_string);
+  void NotifyWarning(const cString& in_string);
+};
+
+
+#ifdef ENABLE_UNIT_TESTS
+namespace nTextViewerAnalyzeDriver {
+  /**
+   * Run unit tests
+   *
+   * @param full Run full test suite; if false, just the fast tests.
+   **/
+  void UnitTests(bool full = false);
+}
+#endif  
+
+#endif

Modified: development/source/targets/avida-viewer/cTextViewerDriver.cc
===================================================================
--- development/source/targets/avida-viewer/cTextViewerDriver.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerDriver.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -27,7 +27,8 @@
 using namespace std;
 
 
-cTextViewerDriver::cTextViewerDriver(cWorld* world) : m_world(world), m_done(false), m_view(NULL)
+cTextViewerDriver::cTextViewerDriver(cWorld* world)
+  : cTextViewerDriver_Base(world)
 {
   m_view = new cView(world);
   m_view->SetViewMode(world->GetConfig().VIEW_MODE.Get());
@@ -39,7 +40,6 @@
 cTextViewerDriver::~cTextViewerDriver()
 {
   cDriverManager::Unregister(static_cast<cAvidaDriver*>(this));
-  delete m_world;
   
   if (m_view != NULL) EndProg(0);
 }

Modified: development/source/targets/avida-viewer/cTextViewerDriver.h
===================================================================
--- development/source/targets/avida-viewer/cTextViewerDriver.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerDriver.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -10,28 +10,15 @@
 #ifndef cTextViewerDriver_h
 #define cTextViewerDriver_h
 
-#ifndef cAvidaDriver_h
-#include "cAvidaDriver.h"
+#ifndef cTextViewerDriver_Base_h
+#include "cTextViewerDriver_Base.h"
 #endif
-#ifndef cWorldDriver_h
-#include "cWorldDriver.h"
-#endif
 
-class cString;
-class cView;
-class cWorld;
-
-class cTextViewerDriver : public cAvidaDriver, public cWorldDriver
+class cTextViewerDriver : public cTextViewerDriver_Base
 {
 private:
   cTextViewerDriver();  // not implemented
   
-protected:
-  cWorld* m_world;
-  bool m_done;  // This is set to true when run should finish.
-
-  cView* m_view;
-  
 public:
   cTextViewerDriver(cWorld* world);
   ~cTextViewerDriver();

Added: development/source/targets/avida-viewer/cTextViewerDriver_Base.cc
===================================================================
--- development/source/targets/avida-viewer/cTextViewerDriver_Base.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerDriver_Base.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,64 @@
+/*
+ *  cTextViewerDriver_Base.cc
+ *  Avida
+ *
+ *  Copyright 2006 Michigan State University. All rights reserved.
+ *
+ */
+
+#include "cTextViewerDriver_Base.h"
+
+#include "cAnalyze.h"
+#include "cString.h"
+#include "cStringList.h"
+#include "cView_Base.h"
+#include "cWorld.h"
+
+cTextViewerDriver_Base::cTextViewerDriver_Base(cWorld * world)
+  : m_world(world), m_view(NULL), m_done(false)
+{
+  std::cout.rdbuf(out_stream.rdbuf());
+  std::cerr.rdbuf(err_stream.rdbuf());
+}
+
+cTextViewerDriver_Base::~cTextViewerDriver_Base()
+{
+  delete m_world;
+}
+
+
+void cTextViewerDriver_Base::Flush()
+{
+  // @CAO -- this is currently inefficient!
+
+  // Pull everything from the streams and put it into strings.
+  cString out_string(out_stream.str().c_str());
+  cString err_string(err_stream.str().c_str());
+
+  // Clear the streams.
+  out_stream.str("");
+  err_stream.str("");
+
+  // Split it into lines.
+  cStringList out_list(out_string, '\n');
+  cStringList err_list(err_string, '\n');
+  const int new_line_count = out_list.GetSize() + err_list.GetSize();
+
+  // And notify the output...
+  while (out_list.GetSize() > 0) {
+    m_view->NotifyOutput(out_list.Pop());
+  }
+
+  while (err_list.GetSize() > 0) {
+    cString cur_string(err_list.Pop());
+    cur_string.Insert("! ");
+    m_view->NotifyOutput(cur_string);
+  }
+
+  if (new_line_count > 0) m_view->NotifyOutput("");
+}
+
+bool cTextViewerDriver_Base::ProcessKeypress(int keypress)
+{
+  return m_view->ProcessKeypress(keypress);
+}

Added: development/source/targets/avida-viewer/cTextViewerDriver_Base.h
===================================================================
--- development/source/targets/avida-viewer/cTextViewerDriver_Base.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextViewerDriver_Base.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,47 @@
+/*
+ *  cTextViewerDriver_Base.h
+ *  Avida
+ *
+ *  Copyright 2006 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef cTextViewerDriver_Base_h
+#define cTextViewerDriver_Base_h
+
+#ifndef cAvidaDriver_h
+#include "cAvidaDriver.h"
+#endif
+
+#ifndef cWorldDriver_h
+#include "cWorldDriver.h"
+#endif
+
+#include <sstream>
+#include <iostream>
+
+class cView_Base;
+class cWorld;
+
+class cTextViewerDriver_Base : public cAvidaDriver, public cWorldDriver {
+protected:
+  cWorld* m_world;
+  cView_Base* m_view;
+  bool m_done;  // This is set to true when run should finish.
+
+  std::stringstream out_stream;
+  std::stringstream err_stream;
+
+  // Protected constructor.
+  cTextViewerDriver_Base(cWorld * world);
+  ~cTextViewerDriver_Base();
+
+public:
+  // Override standard output and error.
+  bool IsInteractive() { return true; }
+  void Flush();
+
+  bool ProcessKeypress(int keypress);
+};
+
+#endif

Modified: development/source/targets/avida-viewer/cTextWindow.cc
===================================================================
--- development/source/targets/avida-viewer/cTextWindow.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextWindow.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -11,8 +11,8 @@
 
 using namespace std;
 
-void cTextWindow::NoDelay() {
-  nodelay(stdscr, 1);       // Don't wait for input if no key is pressed.
+void cTextWindow::NoDelay(bool setting) {
+  nodelay(stdscr, setting);       // Don't wait for input if no key is pressed.
 }
 
 cTextWindow::cTextWindow(int y_size, int x_size, int y_start, int x_start)
@@ -42,7 +42,7 @@
   keypad(win_id, 1);        // Allows the keypad to be used.
 }
 
-void cTextWindow::Box(int x, int y, int w, int h)
+void cTextWindow::Box(int y, int x, int h, int w, bool test)
 {
   int i;
   for (i = 1; i < h - 1; i++) {
@@ -68,6 +68,15 @@
   }
 }
 
+void cTextWindow::VLine(int in_x, int start_y, int length)
+{
+  mvwaddch(win_id, start_y, in_x, ACS_TTEE);
+  mvwaddch(win_id, start_y + length - 1, in_x, ACS_BTEE);
+  for (int i = 1; i < length - 1; i++) {
+    mvwaddch(win_id, start_y+i, in_x, ACS_VLINE);
+  }
+}
+
 void cTextWindow::HLine(int in_y)
 {
   mvwaddch(win_id, in_y, 0, ACS_LTEE);
@@ -94,7 +103,8 @@
 void StartProg()
 {
   initscr();                // Set up the terminal for curses.
-  cbreak();                 // Don't buffer input.
+  //  cbreak();                 // Don't buffer input.
+  raw();                    // Don't even buffer escape characters!
   noecho();                 // Don't echo keypresses to the screen.
   nonl();                   // No new line with CR (when echo is on)
 

Modified: development/source/targets/avida-viewer/cTextWindow.h
===================================================================
--- development/source/targets/avida-viewer/cTextWindow.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cTextWindow.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -59,7 +59,7 @@
 protected:
   WINDOW * win_id;
 
-  void NoDelay();
+  void NoDelay(bool setting=true);
 public:
   cTextWindow();
   cTextWindow(int y_size, int x_size, int y_start=0, int x_start=0);
@@ -93,8 +93,9 @@
   // coords and a length, they only draw the line from the specified start,
   // to the specified distance.
   inline void Box() { box(win_id, 0, 0); }
-  void Box(int x, int y, int w, int h);
+  void Box(int x, int y, int w, int h, bool test);
   void VLine(int in_x);
+  void VLine(int in_x, int start_y, int length);
   void HLine(int in_y);
   void HLine(int in_y, int start_x, int length);
 

Modified: development/source/targets/avida-viewer/cView.cc
===================================================================
--- development/source/targets/avida-viewer/cView.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cView.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -26,17 +26,14 @@
 #include "cOptionsScreen.h"
 #include "cZoomScreen.h"
 #include "cEnvironmentScreen.h"
+#include "cAnalyzeScreen.h"
 
 #include <fstream>
 
 using namespace std;
 
-cTextWindow * cView::base_window = NULL;
-cScreen* cView::cur_screen = NULL;
-cBarScreen* cView::bar_screen = NULL;
 
-
-cView::cView(cWorld* world) : info(world)
+cView::cView(cWorld* world) : info(world, this)
 {
   Setup("Avida");
 
@@ -46,6 +43,7 @@
   options_screen = new cOptionsScreen (0,0,3,0,info);
   zoom_screen    = new cZoomScreen    (0,0,3,0,info, world->GetPopulation());
   environment_screen = new cEnvironmentScreen (world, 0, 0, 3, 0, info);
+  analyze_screen = new cAnalyzeScreen(world, 0, 0, 3, 0, info);
 
   info.SetActiveCell( &( world->GetPopulation().GetCell(0) ) );
 }
@@ -58,6 +56,7 @@
   if (options_screen) delete options_screen;
   if (zoom_screen) delete zoom_screen;
   if (environment_screen) delete environment_screen;
+  if (analyze_screen) delete analyze_screen;
 
   EndProg(0);
 }
@@ -91,6 +90,8 @@
     cur_screen = zoom_screen;
   } else if (in_mode == MODE_ENVIRONMENT) {
     cur_screen = environment_screen;
+  } else if (in_mode == MODE_ANALYZE) {
+    cur_screen = analyze_screen;
   }
 }
 
@@ -140,10 +141,16 @@
 
 void cView::NotifyComment(const cString & in_string)
 {
-  cString out_string(in_string);
-  Notify(out_string);
+  if (cur_screen == analyze_screen) analyze_screen->Notify(in_string);
+  else Notify(in_string);
 }
 
+void cView::NotifyOutput(const cString & in_string)
+{
+  analyze_screen->Notify(in_string);
+  if (cur_screen == analyze_screen) analyze_screen->Refresh();
+}
+
 void cView::DoBreakpoint()
 {
   if (info.GetPauseLevel() == PAUSE_OFF ||
@@ -155,125 +162,139 @@
 
 void cView::DoInputs()
 {
+  // If we are paused, delay doing anything else until a key is pressed.
+  if (info.GetPauseLevel() != PAUSE_OFF) nodelay(stdscr, false);
+
   // If we are in step-wise mode, "finish" this step!
-
   if (info.GetPauseLevel() == PAUSE_ADVANCE_STEP) {
     info.DisEngageStepMode();
     info.SetPauseLevel(PAUSE_ON);
   }
 
+  // If there is any input in the buffer, process all of it.
   int cur_char = ERR;
-  // int cur_char = 0; // *** If GetBlockingInput works, use this ***
+  while ((cur_char = GetInput()) != ERR || info.GetPauseLevel() == PAUSE_ON) {
+    bool found_keypress = ProcessKeypress(cur_char);
 
-  // If there is any input in the buffer, process all of it.
+    // If we couldn't manage the keypress here, check the current screen.
+    if (found_keypress == false && cur_screen) cur_screen->DoInput(cur_char);
+  }
 
-  while ((cur_char = GetInput()) != ERR || info.GetPauseLevel() == PAUSE_ON) {
+  if (info.GetPauseLevel() == PAUSE_ADVANCE_UPDATE) {
+    info.SetPauseLevel(PAUSE_ON);
+  }
 
-  // *** If GetBlockingInput works, use this ***
-  // while( cur_char != ERR ){
-    // if paused, block on input
-    // if( info.GetPauseLevel() == PAUSE_ON ){
-      // cur_char = GetBlockingInput();
-    // }else{
-      // cur_char = GetInput();
-    // }
+  nodelay(stdscr, true);
+}
 
-    switch (cur_char) {
-      // Note: Capital 'Q' quits w/o confirming.
-    case 'q':
-      if (!Confirm("Are you sure you want to quit?")) break;
-    case 'Q':
-      // clear the windows before we go.  Do bar window last to end at top.
-      base_window->Redraw();
-      bar_screen->Clear();
-      bar_screen->Refresh();
-      EndProg(0);  // This implementation calls exit(), blowing us clean away
-      break;
-    case 'b':
-    case 'B':
-      ChangeCurScreen(NULL);
-      break;
-    case 'C':
-    case 'c':
-      NavigateMapWindow();
-      // Now we need to restore the proper window mode (already cleared)
-      ChangeCurScreen(cur_screen);
-      break;
-    case 'h':
-    case 'H':
-      ChangeCurScreen(hist_screen);
-      break;
-    case 'm':
-    case 'M':
-      ChangeCurScreen(map_screen);
-      break;
-    case 'n':
-    case 'N':
-      if (info.GetPauseLevel() == PAUSE_ON) {
-	info.SetPauseLevel(PAUSE_ADVANCE_UPDATE);
-	// parasite_zoom = false; // if executing, show code that is running
-	info.GetActiveCell()->GetOrganism()->GetPhenotype().SetFault("");
-      }
-      if (cur_screen) cur_screen->AdvanceUpdate();
-      break;
-    case 'o':
-    case 'O':
-      ChangeCurScreen(options_screen);
-      break;
-    case 'p':
-    case 'P':
-      TogglePause();
-      break;
-    case 'e':
-    case 'E':
-      //      if(info.GetPopulation().GetEnvironment().GetResourceLib().GetSize() > 0)
-	ChangeCurScreen(environment_screen);
-      break;
-    case 's':
-    case 'S':
-      ChangeCurScreen(stats_screen);
-      break;
-    case 'W':
-    case 'w':
-      CloneSoup();
-      break;
-    case 'X':
-    case 'x':
-      ExtractCreature();
-      break;
-    case 'z':
-    case 'Z':
-      ChangeCurScreen(zoom_screen);
-      break;
-    case 12: // Ideally this is CTRL-L...
-      Refresh();
-      break;
+bool cView::ProcessKeypress(int keypress)
+{
+  bool unknown = false;
 
-    case '*':   // Test Key!!!
-      if (true) {
-	Confirm("Starting Tests.");
-	cMenuWindow menu(50);
-	char message[40];
-	for (int j = 0; j < 50; j++) {
-	  sprintf(message, "Line %d", j);
-	  menu.AddOption(j, message);
-	}
-	menu.SetActive(3);
-	menu.Activate(base_window);
-	Redraw();
+  switch (keypress) {
+  case 'a':
+  case 'A':
+    ChangeCurScreen(analyze_screen);
+    break;
+  case 'b':
+  case 'B':
+    ChangeCurScreen(NULL);
+    break;
+  case 'C':
+  case 'c':
+    NavigateMapWindow();
+    // Now we need to restore the proper window mode (already cleared)
+    ChangeCurScreen(cur_screen);
+    break;
+  case 'e':
+  case 'E':
+    ChangeCurScreen(environment_screen);
+    break;
+  case 'h':
+  case 'H':
+    ChangeCurScreen(hist_screen);
+    break;
+  case 'm':
+  case 'M':
+    ChangeCurScreen(map_screen);
+    break;
+  case 'n':
+  case 'N':
+    if (info.GetPauseLevel() == PAUSE_ON) {
+      info.SetPauseLevel(PAUSE_ADVANCE_UPDATE);
+      // parasite_zoom = false; // if executing, show code that is running
+      info.GetActiveCell()->GetOrganism()->GetPhenotype().SetFault("");
+      nodelay(stdscr, true); // Don't delay for input; get to processing.
+    }
+    if (cur_screen) cur_screen->AdvanceUpdate();
+    break;
+  case 'o':
+  case 'O':
+    ChangeCurScreen(options_screen);
+    break;
+  case 'p':
+  case 'P':
+    TogglePause();
+    // We don't want to delay if we're unpaused.
+    if (info.GetPauseLevel() == PAUSE_OFF) nodelay(stdscr, true);
+    else nodelay(stdscr, false);
+    break;
+  case 'q':
+    if (!Confirm("Are you sure you want to quit?")) break;
+  case 'Q':      // Note: Capital 'Q' quits w/o confirming.
+    // clear the windows before we go.  Do bar window last to end at top.
+    base_window->Redraw();
+    bar_screen->Clear();
+    bar_screen->Refresh();
+    EndProg(0);  // This implementation calls exit(), blowing us clean away
+    break;
+  case 's':
+  case 'S':
+    ChangeCurScreen(stats_screen);
+    break;
+  case 'W':
+  case 'w':
+    CloneSoup();
+    break;
+  case 'X':
+  case 'x':
+    ExtractCreature();
+    break;
+  case 'z':
+  case 'Z':
+    ChangeCurScreen(zoom_screen);
+    break;
+  case 3: // CTRL-C...
+    exit(0);
+    break;
+  case 12: // CTRL-L...
+    Refresh();
+    break;
+  case 26: // CTRL-Z
+    kill(getpid(), SIGTSTP);
+    break;
+  case '*':   // Test Key!!!
+    if (true) {
+      Confirm("Starting Tests.");
+      cMenuWindow menu(50);
+      char message[40];
+      for (int j = 0; j < 50; j++) {
+	sprintf(message, "Line %d", j);
+	menu.AddOption(j, message);
       }
-      break;
-    case ERR:
-      break;
-    default:
-      if (cur_screen) cur_screen->DoInput(cur_char);
-      break;
+      menu.SetActive(3);
+      menu.Activate(base_window);
+      Redraw();
     }
+    break;
+  case ERR:
+    break;
+  default:
+    unknown = true;
+    break;
   }
 
-  if (info.GetPauseLevel() == PAUSE_ADVANCE_UPDATE) {
-    info.SetPauseLevel(PAUSE_ON);
-  }
+  return !unknown;
 }
 
 void cView::TogglePause()

Modified: development/source/targets/avida-viewer/cView.h
===================================================================
--- development/source/targets/avida-viewer/cView.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cView.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -12,6 +12,10 @@
 #include "cViewInfo.h"
 #endif
 
+#ifndef cView_Base_h
+#include "cView_Base.h"
+#endif
+
 #define MODE_BLANK   0
 #define MODE_MAP     1
 #define MODE_STATS   2
@@ -19,6 +23,7 @@
 #define MODE_OPTIONS 4
 #define MODE_ZOOM    5
 #define MODE_ENVIRONMENT 6
+#define MODE_ANALYZE 7
 
 class cScreen;
 class cTextWindow;
@@ -29,22 +34,24 @@
 class cOptionsScreen;
 class cZoomScreen;
 class cEnvironmentScreen;
+class cAnalyzeScreen;
 class cWorld;
 
-class cView {
+class cView : public cView_Base {
 private:
   cViewInfo info;
 
   // Window information...
-  static cTextWindow * base_window;
-  static cScreen * cur_screen;
-  static cBarScreen * bar_screen;
+  cTextWindow * base_window;
+  cScreen * cur_screen;
+  cBarScreen * bar_screen;
   cMapScreen * map_screen;
   cStatsScreen * stats_screen;
   cHistScreen * hist_screen;
   cOptionsScreen * options_screen;
   cZoomScreen * zoom_screen;
   cEnvironmentScreen * environment_screen;
+  cAnalyzeScreen * analyze_screen;
 
   // Window managing functions...
 
@@ -69,24 +76,27 @@
   void Setup(const cString & in_name);
   void SetViewMode(int in_mode);
 
+  bool ProcessKeypress(int keypress);
+
   void NewUpdate();
   void NotifyUpdate();
   void NotifyError(const cString & in_string);
   void NotifyWarning(const cString & in_string);
   void NotifyComment(const cString & in_string);
-  inline void Pause() { info.SetPauseLevel(PAUSE_ON); }
+  void NotifyOutput(const cString & in_string);
+  void Pause() { info.SetPauseLevel(PAUSE_ON); }
   void DoBreakpoint();
+  
+  int Confirm(const cString & message);
+  void Notify(const cString & message);
 
-  static int Confirm(const cString & message);
-  static void Notify(const cString & message);
-
   int GetStepOrganism() { return info.GetStepOrganism(); }
   void SetStepOrganism(int in_id) { info.SetStepOrganism(in_id); }
 
   void Refresh();
 
   // Methods called by sub-windows.
-  static void Redraw();
+  void Redraw();
 };
 
 

Modified: development/source/targets/avida-viewer/cViewInfo.cc
===================================================================
--- development/source/targets/avida-viewer/cViewInfo.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cViewInfo.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -24,7 +24,10 @@
 using namespace std;
 
 
-cViewInfo::cViewInfo(cWorld* world) : m_world(world), alt_inst_set(world)
+cViewInfo::cViewInfo(cWorld* world, cView_Base* view)
+  : m_world(world)
+  , m_view(view)
+  , alt_inst_set(world)
 {
   active_cell = NULL;
   pause_level = PAUSE_OFF;

Modified: development/source/targets/avida-viewer/cViewInfo.h
===================================================================
--- development/source/targets/avida-viewer/cViewInfo.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cViewInfo.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -49,10 +49,12 @@
 #define NUM_MAP_MODES 12
 
 #include "cWorld.h"
+#include "cView_Base.h"
 
 class cViewInfo {
 private:
   cWorld* m_world;
+  cView_Base* m_view;
   cPopulationCell * active_cell;
 
   int pause_level;
@@ -80,7 +82,7 @@
   void AddSpeciesChart(cSpecies * in_species);
   void AddInjectGenChart(cInjectGenotype * in_gen);
 public:
-  cViewInfo(cWorld* world);
+  cViewInfo(cWorld* world, cView_Base * view);
   ~cViewInfo() { ; }
 
   void UpdateSymbols();
@@ -100,6 +102,7 @@
   cAvidaConfig& GetConfig() { return m_world->GetConfig(); }
   cRandom& GetRandom() { return m_world->GetRandom(); }
   cWorld& GetWorld() { return *m_world; }
+  cView_Base& GetView() { return *m_view; }
 
   int GetNumSymbols() { return NUM_SYMBOLS; }
   cGenotype * GetGenotype(int index) { return genotype_chart[index]; }

Added: development/source/targets/avida-viewer/cView_Base.h
===================================================================
--- development/source/targets/avida-viewer/cView_Base.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cView_Base.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2006 Michigan State University                             //
+//                                                                          //
+// Read the COPYING and README files, or contact 'avida at alife.org',         //
+// before continuing.  SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE.     //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef cView_Base_h
+#define cView_Base_h
+
+class cString;
+
+class cView_Base {
+public:
+  cView_Base() { ; }
+  virtual ~cView_Base() { ; }
+  
+  virtual void Setup(const cString & in_name) = 0;
+  virtual void SetViewMode(int in_mode) { (void) in_mode; }
+
+  virtual bool ProcessKeypress(int keypress) = 0;
+
+  virtual void NewUpdate() { ; }
+  virtual void NotifyUpdate() { ; }
+  virtual void NotifyError(const cString & in_string) = 0;
+  virtual void NotifyWarning(const cString & in_string) = 0;
+  virtual void NotifyComment(const cString & in_string) = 0;
+  virtual void NotifyOutput(const cString & in_string) = 0;
+  virtual void Pause() { ; }
+  virtual void DoBreakpoint() { ; }
+
+  virtual int Confirm(const cString & message) = 0;
+  virtual void Notify(const cString & message) = 0;
+
+  virtual int GetStepOrganism() { return -1; }
+  virtual void SetStepOrganism(int in_id) { (void) in_id; }
+
+  virtual void Refresh() = 0;
+
+  // Methods called by sub-windows.
+  virtual void Redraw() = 0;
+};
+
+#endif

Modified: development/source/targets/avida-viewer/cZoomScreen.cc
===================================================================
--- development/source/targets/avida-viewer/cZoomScreen.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/cZoomScreen.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -139,7 +139,7 @@
   
   // --== Tasks ==--
   SetColor(COLOR_WHITE);
-  Box(TASK_X, TASK_Y, 30, Height()-TASK_Y);
+  Box(TASK_Y, TASK_X, Height()-TASK_Y, 30, true);
   
   
   int task_num = task_offset;
@@ -170,7 +170,7 @@
   SetColor(COLOR_WHITE);
   
   // --== Registers ==--
-  Box(REG_X, REG_Y, 19, 7);
+  Box(REG_Y, REG_X, 7, 19, true);
   Print(REG_Y + 1, REG_X + 2, "Registers");
   HLine(REG_Y + 2, REG_X, 19);
   
@@ -181,12 +181,12 @@
   SetColor(COLOR_WHITE);
   
   // --== Inputs ==--
-  Box(INPUT_X, INPUT_Y, 16, 7);
+  Box(INPUT_Y, INPUT_X, 7, 16, true);
   Print(INPUT_Y + 1, INPUT_X + 2, "Inputs");
   HLine(INPUT_Y + 2, INPUT_X, 16);
   
   // --== Mini-Map ==--
-  Box(MINI_MAP_X, MINI_MAP_Y, 17, 3);
+  Box(MINI_MAP_Y, MINI_MAP_X, 3, 17, true);
   Print(MINI_MAP_Y + 1, MINI_MAP_X + 2, "Mini-Map");
   // HLine(MINI_MAP_Y + 2, MINI_MAP_X, 19);
   
@@ -195,12 +195,12 @@
   SetColor(COLOR_WHITE);
   
   // --== Memory ==--
-  Box(MEMORY_X, MEMORY_Y, 36, 5 + MEMORY_PRE_SIZE + MEMORY_POST_SIZE);
+  Box(MEMORY_Y, MEMORY_X, 5 + MEMORY_PRE_SIZE + MEMORY_POST_SIZE, 36, true);
   Print(MEMORY_Y + 1, MEMORY_X + 2,  "Memory:");
   HLine(MEMORY_Y + 2, MEMORY_X, 36);
   
   // --== Stack ==--
-  Box(STACK_X, STACK_Y, 15, 7);
+  Box(STACK_Y, STACK_X, 7, 15, true);
   HLine(STACK_Y + 2, STACK_X, 15);
   
   // --== Options ==--
@@ -252,7 +252,7 @@
   SetColor(COLOR_WHITE);
   
   // --== Registers ==--
-  Box(REG_X, REG_Y-1, 19, 8);
+  Box(REG_Y-1, REG_X, 8, 19, true);
   Print(REG_Y, REG_X + 2, "Stacks:");
   HLine(REG_Y + 1, REG_X, 19);
   
@@ -264,12 +264,12 @@
   SetColor(COLOR_WHITE);
   
   // --== Inputs ==--
-  Box(INPUT_X, INPUT_Y-1, 16, 8);
+  Box(INPUT_Y-1, INPUT_X, 8, 16, true);
   Print(INPUT_Y, INPUT_X + 2, "Inputs:");
   HLine(INPUT_Y+1, INPUT_X, 16);
   
   // --== Mini-Map ==--
-  Box(MINI_MAP_X, MINI_MAP_Y, 17, 3);
+  Box(MINI_MAP_Y, MINI_MAP_X, 3, 17, true);
   Print(MINI_MAP_Y + 1, MINI_MAP_X + 2, "Mini-Map");
   //HLine(MINI_MAP_Y + 2, MINI_MAP_X, 19);
   
@@ -281,12 +281,12 @@
   SetColor(COLOR_WHITE);
   
   // --== Memory ==--
-  Box(MEMORY_X, MEMORY_Y, 36, 5 + MEMORY_PRE_SIZE + MEMORY_POST_SIZE);
+  Box(MEMORY_Y, MEMORY_X, 5 + MEMORY_PRE_SIZE + MEMORY_POST_SIZE, 36, true);
   Print(MEMORY_Y + 1, MEMORY_X + 2,  "Memory Space");
   HLine(MEMORY_Y + 2, MEMORY_X, 36);
   
   // --== Stack ==--
-  Box(STACK_X, STACK_Y-1, 15, 8);
+  Box(STACK_Y-1, STACK_X, 8, 15, true);
   HLine(STACK_Y + 1, STACK_X, 15);
   
   // --== Options ==--
@@ -1019,7 +1019,7 @@
   menu1.AddOption(INST_EDIT_REMOVE,     "[D]elete Instruction");
   menu1.SetActive(INST_EDIT_CHANGE);
   int edit_method = menu1.Activate(this);
-  cView::Redraw();
+  info.GetView().Redraw();
   
   // If we need to choose a new instruction, bring up a window for it.
   
@@ -1033,9 +1033,9 @@
     inst_menu.SetActive(edit_head.GetInst().GetOp());
     new_inst = inst_menu.Activate(this);
     
-    cView::Redraw();
+    info.GetView().Redraw();
     if (new_inst == -1) {
-      //  cView::Notify("Aborted!");
+      //  info.GetView().Notify("Aborted!");
       return;
     }
   }
@@ -1062,7 +1062,7 @@
       edit_head.RemoveInst();
       break;
     default:
-      //    cView::Notify("Aborted!");
+      //    info.GetView().Notify("Aborted!");
       break;
   }
   
@@ -1080,7 +1080,7 @@
   menu1.AddOption(THREAD_OPTIONS_LOCK, "[T]oggle Thread Lock");
   menu1.SetActive(THREAD_OPTIONS_VIEW);
   thread_method = menu1.Activate(this);
-  cView::Redraw();
+  info.GetView().Redraw();
   
   // Act on the view method!
   switch (thread_method) {
@@ -1173,7 +1173,7 @@
   }
   
   delete window;
-  cView::Redraw();
+  info.GetView().Redraw();
 }
 
 void cZoomScreen::ViewRegisters()
@@ -1217,7 +1217,7 @@
   }
   
   delete window;
-  cView::Redraw();
+  info.GetView().Redraw();
 }
 
 
@@ -1287,7 +1287,7 @@
   }
   
   delete window;
-  cView::Redraw();
+  info.GetView().Redraw();
 }
 
 
@@ -1330,7 +1330,7 @@
   }
   
   delete window;
-  cView::Redraw();
+  info.GetView().Redraw();
 }
 
 
@@ -1461,6 +1461,7 @@
       parasite_zoom = false;
       info.GetActiveCell()->GetOrganism()->GetPhenotype().SetFault("");
       info.EngageStepMode();
+      nodelay(stdscr, true); // Don't delay for input; get to processing.
       break;
     case '>':
     case '.':

Modified: development/source/targets/avida-viewer/viewer.cc
===================================================================
--- development/source/targets/avida-viewer/viewer.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/targets/avida-viewer/viewer.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -10,7 +10,7 @@
 
 #include "avida.h"
 #include "cAvidaConfig.h"
-#include "cDefaultAnalyzeDriver.h"
+#include "cTextViewerAnalyzeDriver.h"
 #include "cDriverManager.h"
 #include "cTextViewerDriver.h"
 #include "cWorld.h"
@@ -31,7 +31,7 @@
   cAvidaDriver* driver = NULL;
   
   if (world->GetConfig().ANALYZE_MODE.Get() > 0) {
-    driver = new cDefaultAnalyzeDriver(world, (world->GetConfig().ANALYZE_MODE.Get() == 2));
+    driver = new cTextViewerAnalyzeDriver(world, (world->GetConfig().ANALYZE_MODE.Get() == 2));
   } else {
     driver = new cTextViewerDriver(world);
   }

Modified: development/source/tools/cString.cc
===================================================================
--- development/source/tools/cString.cc	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/tools/cString.cc	2006-12-12 04:12:56 UTC (rev 1135)
@@ -615,6 +615,36 @@
 }
 
 
+cString cString::EjectStr(int pos, int excise )
+{
+  // Delete excise characters at pos and return the substring.
+
+  // Validate inputs:
+  assert (pos >= 0);                   // Negative position
+  assert (pos <= GetSize());           // Position past end of string
+  assert (excise > 0);                 // Must excise something...
+  assert (excise <= GetSize()-pos);    // Excise number too large
+
+  // Collect substring to output.
+  cString out_string(Substring(pos, excise));
+
+  // Allocate a new string
+  const int new_size = GetSize() - excise;
+  cStringData * new_value = new cStringData(new_size);
+  assert (new_value != NULL);  // Memory Allocation Error: Out of Memory
+
+  for(int i = 0; i < pos; i++){             // Copy self up to pos
+    (*new_value)[i] = this->operator[](i);
+  }
+  for(int i=pos+excise; i<GetSize(); ++i ){  // Copy post-excise self
+    (*new_value)[i-excise] = this->operator[](i);
+  }
+
+  TakeValue(new_value);                      // Reassing data to new data
+  return out_string;
+}
+
+
 int cString::FindStr(const char * in, const int in_size, int pos) const
 {
   assert (pos>=0);         // Negative position

Modified: development/source/tools/cString.h
===================================================================
--- development/source/tools/cString.h	2006-12-12 03:36:07 UTC (rev 1134)
+++ development/source/tools/cString.h	2006-12-12 04:12:56 UTC (rev 1135)
@@ -13,6 +13,7 @@
 
 #include <stdlib.h>
 #include <iostream>
+#include <string>
 #include <string.h>
 #include <assert.h>
 
@@ -141,6 +142,7 @@
     assert( value != NULL );    // Memory Allocation Error: Out of Memory
   }
   cString(const cString& in) { CopyString(in); }
+
   virtual ~cString() { if (value->RemoveRef() == 0) delete value; }
 
 
@@ -532,6 +534,15 @@
    **/
   bool IsSubstring(const cString & in_string, int start) const;
  
+  /**
+   * Clip a portion of the string and output it.
+   *
+   * @return Removed substring.
+   * @param pos the position to start the ejection.
+   * @param excise number of sites to eject.
+   **/
+  cString EjectStr(int pos, int excise);
+
   /*
   We have decided to not serialize information about data-sharing
   between cStrings (via cStringData). This leads to plausible memory




More information about the Avida-cvs mailing list