Re: Redirecting cout to a TextBuffer



2008/5/12 Charles McLachlan <cim20 metropolis-data co uk>:
> On Sat, 10 May 2008, Søren Hauberg wrote:
>
>> Hi all,
>>  I'm using gtksourceviewmm as terminal-like widget, and I want to
>> redirect std::cout to this widget. Currently I'm doing something like
>> this in my constructor:
>>
>>   std::ostringstream outs;
>>   std::cout.rdbuf (outs.rdbuf ());
>
> Caveat: I don't know much about gtksourcemm but I do know something about
> STL streambufs.
>
> If the above code works (its an interesting idea that I have not seen
> before), then my advice would be subclass your own streambuf. You'll need to
> overload the the sync and overflow members. These have slightly weird
> actions and (on first viewing) appear non trivial.
>
> The advantage of this appreoach is that the source view will only be updated
> when 1) the buffer runs out, 2) the stream explicitly asks for it, usually
> via stream.sync() being called. This (correctly) puts the control of the
> updates in the hands of the user of the stream, rather than having to wait
> for timeouts.

So, I finally got my act together and implemented your idea, so I
thought I'd report back. Basically, your idea works great. Some
modifications were necessary, so I thought I'd post the code in case
anybody wanted something similar:

class ogsbuf : public std::streambuf
{
private:
  const static int kZBufferSize = 2048;
  Glib::RefPtr<Gtk::TextBuffer> destination;
  char *buffer;

public:
  explicit ogsbuf (Glib::RefPtr<Gtk::TextBuffer> &_destination)
   : destination (_destination)
  {
    buffer = (char*)malloc (sizeof (char) * kZBufferSize);
    setp (buffer, buffer + kZBufferSize);
  }

  ~ogsbuf ()
  {
    sync ();
    clear ();
  }

  void clear ()
  {
    free (buffer);
  }

protected:
  inline int sync()
  {
    // pbase () is an unsigned char * pointing to the data to be
written to the destination
    // pptr () is an end pointer for the data.
    destination->insert (destination->end (), pbase (), pptr ());
    setp (buffer, buffer + kZBufferSize);

    return 0;
  }

  inline int overflow (int ch = traits_type::eof ())
  {
    const int ret = sync ();
    *pptr () = ch;
    pbump (1);
    return ret;
  }
};

Thanks,
Søren


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]