wx_debugging_base.cpp

Go to the documentation of this file.
00001 #ifndef WX_DEBUGGING_BASE_IMPLEMENTATION_FILE
00002 #define WX_DEBUGGING_BASE_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : wx_debugging_base                                                 *
00007 *  Author : Aaron Buchanan                                                    *
00008 *  Author : Chris Koeritz                                                     *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 1995-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #include "wx_debugging_base.h"
00020 
00021 #include <basis/convert_utf.h>
00022 #include <basis/function.h>
00023 #include <basis/istring.h>
00024 #include <basis/version_record.h>
00025 #include <data_struct/static_memory_gremlin.h>
00026 #include <loggers/file_logger.h>
00027 #ifdef LIGHTLINK_CODEBASE
00028   #include <uls/uls.h>
00029 #endif
00030 
00031 #undef GetClassInfo
00032 #include <wx/textctrl.h>
00033 
00034 using namespace portable;
00035 
00036 //#define DEBUG_DEBUGGING
00037   // uncomment for the noisy version of the debugging support.
00038 
00039 const u_int LENGTH_CHOP_FACTOR = 8192;
00040   // the amount clipped out of the window at one time.
00041 
00042 //hmmm: make this a configurable parameter.
00043 const int ULS_BUFFER_SIZE = 164 * KILOBYTE;
00044   // our uls stream size that's kept.
00045 
00046 // some strings we'll make constant to avoid recreating all the time.
00047 const wxString wxstring_crlf = to_unicode_wx("\r\n");
00048 const wxString wxstring_lf = to_unicode_wx("\n");
00049 
00050 #define DISABLE 
00051 #define REENABLE 
00052 
00054 
00055 wx_debugging_base::wx_debugging_base(wxTextCtrl &editor, int buffer_size, int file_size)
00056 : log_base(),
00057   _editor(editor),
00058   _length(0),
00059   _maximum_active_length(0),
00060   _file_limit(0),
00061   _log_name(new istring),
00062   _the_log(NIL)
00063 {
00064   buffer_limit(buffer_size);
00065   file_limit(file_size);
00066 }
00067 
00068 wx_debugging_base::~wx_debugging_base()
00069 {
00070   shut_down();
00071   WHACK(_log_name);
00072 }
00073 
00074 int wx_debugging_base::buffer_limit() { return _maximum_active_length; }
00075 
00076 void wx_debugging_base::buffer_limit(int new_limit)
00077 {
00078   _maximum_active_length = new_limit;
00079 }
00080 
00081 int wx_debugging_base::file_limit() const { return _file_limit; }
00082 
00083 //hmmm: if the file limit was zero and now it's not, we should
00084 //      open anew the logger.
00085 void wx_debugging_base::file_limit(int new_limit)
00086 {
00087   _file_limit = new_limit;
00088   if (!_file_limit) {
00089     // no length means no output file.
00090     WHACK(_the_log);
00091   }
00092   if (_the_log) {
00093 #ifndef LIGHTLINK_CODEBASE
00094     _the_log->limit(_file_limit);
00095 #else
00096     _the_log->reopen(name(), _maximum_active_length, _file_limit);
00097 #endif
00098   }
00099 }
00100 
00101 wxTextCtrl &wx_debugging_base::get_editor() { return _editor; }
00102 
00103 istring wx_debugging_base::name() const { return *_log_name; }
00104 
00105 void wx_debugging_base::name(const istring &new_name)
00106 {
00107   *_log_name = new_name;
00108   if (!_log_name->t()) {
00109     // if no name, then no log file.
00110     WHACK(_the_log);
00111   }
00112   if (_the_log) {
00113 #ifndef LIGHTLINK_CODEBASE
00114     _the_log->name(new_name);
00115 #else
00116     _the_log->reopen(new_name, _maximum_active_length, _file_limit);
00117 #endif
00118   }
00119 }
00120 
00121 void wx_debugging_base::setup()
00122 {
00123   _editor.SetMaxLength(0);
00124     // the zero used to be documented in msdn, but no longer.  i think it's
00125     // intended to indicate that there's no fixed limit.
00126 
00127   if (_file_limit && _log_name->t()) {
00128 #ifndef LIGHTLINK_CODEBASE
00129     _the_log = new file_logger(*_log_name, _file_limit);
00130 #else
00131     _the_log = new uls(*_log_name, ULS_BUFFER_SIZE, _file_limit);
00132 #endif
00133   }
00134 
00135 }
00136 
00137 void wx_debugging_base::shut_down()
00138 {
00139   // reset our uls prior to program close.
00140   WHACK(_the_log);
00141 }
00142 
00143 bool wx_debugging_base::get_selection(int &start, int &end)
00144 {
00145   DISABLE;
00146   long s, e;
00147   _editor.GetSelection(&s, &e);
00148   start = int(s);
00149   e = int(e);
00150   int curr = locked_current_length();
00151   if ( (start >= curr) && (end >= curr) ) {
00152     // the position is past where it could be a selection.
00153     REENABLE;
00154     return false;
00155   }
00156   REENABLE;
00157   return true;
00158 }
00159 
00160 void wx_debugging_base::select(int start, int end)
00161 {
00162   DISABLE;
00163   _editor.SetSelection(start, end);
00164   REENABLE;
00165 }
00166 
00167 int wx_debugging_base::current_length()
00168 {
00169   int to_return = 0;
00170   DISABLE;
00171   to_return = locked_current_length();
00172   REENABLE;
00173   return to_return;
00174 }
00175 
00176 int wx_debugging_base::locked_current_length()
00177 {
00178   long old_start, old_end;
00179   _editor.GetSelection(&old_start, &old_end);
00180   _editor.SetSelection(-1, -1);  // force selection of all.
00181   long new_start, new_end;
00182   _editor.GetSelection(&new_start, &new_end);
00183   _editor.SetSelection(old_start, old_end);  // redo the old selection.
00184   int len = int(new_end - new_start);
00185   _length = len;  // reset our internal length, since they gave us the chance.
00186   return len;
00187 }
00188 
00189 void wx_debugging_base::log_ending(const istring &to_show,
00190     int filter, line_ending ending)
00191 {
00192   line_ending temp = eol();
00193   eol(ending);
00194   log(to_show, filter);
00195   eol(temp);
00196 }
00197 
00198 outcome wx_debugging_base::log(const istring &to_show_in, int filter)
00199 {
00200   DISABLE;
00201     // turn off the user's ability to mess with this for a bit.
00202   // show in edit window if the message's filter is in filter set.
00203   if (member(filter)) {
00204     // set the file_logger's line ending temporarily.
00205     if (_the_log) {
00206       line_ending temp = _the_log->eol();
00207       if (eol() == NO_ENDING) _the_log->eol(NO_ENDING);
00208       _the_log->log(to_show_in, ALWAYS_PRINT);  // override the filter.
00209       _the_log->eol(temp);  // reset the ending.
00210     }
00211 
00212     wxString to_show = to_unicode_wx(to_show_in);
00213       // create a malleable copy of the text.
00214 
00215     // process the text to fix CRs.
00216     // the wxTextCtrl needs to not have any CRs in it.
00217     to_show.Replace(wxstring_crlf, wxstring_lf);
00218 
00219     // line break for edit boxes is now added to the message:
00220     if (eol() != NO_ENDING)
00221       to_show += to_unicode_wx(get_ending());
00222 
00223     _editor.Freeze();  // turn off redraw during the update.
00224 
00225     // record any selection / cursor position before the changes.
00226     long sel_start, sel_end;
00227     _editor.GetSelection(&sel_start, &sel_end);
00228     bool at_end = (sel_start == sel_end) && (sel_end >= _length);  
00229         // was the cursor at the end of the thing?
00230 
00231 #ifdef DEBUG_DEBUGGING
00232     to_show += istring(istring::SPRINTF, "<%d %d>:len=%d", sel_start,
00233         sel_end, _length);
00234     if (eol() != NO_ENDING) get_ending(to_show);
00235 #endif
00236 
00237     // iterate over the string in chunks to ensure that the window doesn't
00238     // get choked up and that we never go over our allocation limit for huge
00239     // strings.
00240     while (to_show.length() > 0) {
00241       locked_current_length();  // make sure we get the correct current size.
00242       int num_to_show = minimum(512, int(to_show.length()));
00243       wxString chunk_to_show = to_show.Left(num_to_show);
00244       to_show = to_show.Mid(num_to_show);
00245 
00246       // check to make sure the edit buffer isn't getting too long...
00247       if (_length + int(chunk_to_show.length()) >= _maximum_active_length) {
00248         // oops, it's going to be too big.  chop a chunk.
00249         locked_current_length();  // get the real current size.
00250         int old_len = _length;  // record the old actual size.
00251         // when the length gets unmanageable, a chunk is chopped out.
00252         _editor.Remove(0, LENGTH_CHOP_FACTOR);
00253         locked_current_length();  // make sure we get the correct new size.
00254         int difference = old_len - _length;
00255         // ensure that the selection skips back too.
00256         sel_start -= difference;
00257         sel_end -= difference;
00258         if ( (sel_start < 0) || (sel_end < 0) ) {
00259           // if the selected area was whacked, reset at the front.
00260           sel_start = 0;
00261           sel_end = 0;
00262         }
00263       }
00264       _editor.AppendText(chunk_to_show);
00265       // we add to the length to record the new text.
00266       _length += int(chunk_to_show.length());
00267     }
00268 
00269     // reset the selection to the prior value.  if it was at the end, select
00270     // the new end.
00271     if (at_end) {
00272       sel_start = _length;
00273       sel_end = _length;
00274     }
00275     _editor.Thaw();   // allow drawing again.
00276     _editor.SetSelection(sel_start, sel_end);
00277   }
00278   REENABLE;
00279   return common::OKAY;
00280 }
00281 
00282 void wx_debugging_base::go_to_end()
00283 {
00284   DISABLE;
00285   // make sure we know the real length.
00286   locked_current_length();
00287   // the edit box's text is selected at the last position.
00288   _editor.SetSelection(_length, _length);
00289   REENABLE;
00290 }
00291 
00292 bool wx_debugging_base::get_contents(istring &to_fill)
00293 {
00294   DISABLE;
00295   to_fill = from_unicode_wx(_editor.GetValue());
00296   REENABLE;
00297   return true;
00298 }
00299 
00300 void wx_debugging_base::reset()
00301 {
00302   DISABLE;
00303   _editor.Clear();
00304   locked_current_length();  // recalculate the length.
00305   REENABLE;
00306 }
00307 
00308 void wx_debugging_base::display_message(byte_array &message)
00309 {
00310   line_ending ending;
00311   int filter;
00312   istring to_show = debugger::crack_debug_message((void *)&message, ending, filter);
00313   log_ending(to_show, filter, ending);
00314 }
00315 
00316 #endif //WX_DEBUGGING_BASE_IMPLEMENTATION_FILE
00317 

Generated on Fri Nov 28 04:29:06 2008 for HOOPLE Libraries by  doxygen 1.5.1