Borland Online And The Cobb Group Present:


September, 1995 - Vol. 2 No. 9


Listing B: DCSTREAM.CPP
#include "dcstream.h"
#define NEWLINE   '\n'
#define TAB       '\t'
#define CRETURN   '\r'

dcstreambuf::dcstreambuf( unsigned int size ): 
  streambuf()
{ bufsiz = size;
  buf = new char[bufsiz];
  setbuf( buf, bufsiz );
  setp( buf, buf+bufsiz );
  tabType = TAB_HARD;
  x0 = x = y = itab = 0;
  tabs = NULL; }

dcstreambuf::~dcstreambuf( void )
{ delete buf;
  if( tabs )
   delete tabs; }

int dcstreambuf::overflow( int c )        
{ if( sync() )
    return sputc( c );
  else
    return EOF; }

int dcstreambuf::sync()                   
{ if( !out_waiting() )
    return TRUE;

  GetTextMetrics( hDC, &tm );

  char *b = pbase(), *p = pptr();
  BOOL ok = TRUE;
  unsigned int len;

  for( char *w = b; w != p; w++ )
  { switch( *w )
    { case TAB:
        len = (unsigned int)( w - b );
        ok = ok && TextOut( hDC, x, y, b, len );
        x += LOWORD( GetTextExtent( hDC, b, len ) );
        x = x0 + ( (tabType == TAB_ANSI)? ansitab(): 
                       hardtab() );
        b = w + 1;
        break;
      case NEWLINE:
        len = (unsigned int)( w - b );
        ok = ok && TextOut( hDC, x, y, b, len );
        x = x0;
        y += ydir * tm.tmHeight;
        itab = 0;
        b = w + 1;
        break;

      case CRETURN:
        len = (unsigned int)( w - b );
        ok = ok && TextOut( hDC, x, y, b, len );
        x = x0;
        b = w + 1;
        break;  } }
  len = (unsigned int)( w - b );
  TextOut( hDC, x, y, b, len );
  x += LOWORD( GetTextExtent( hDC, b, len ) );
  setp( buf, buf+bufsiz );
  return ok; }

int dcstreambuf::gettab( int n )                   
{ if( !n || !ntabs )
    return 0;
  else if( ntabs == 1 )
    return n*tabs[0];
  else if( n > ntabs )
    return (n-ntabs)*(tabs[ntabs-1] - tabs[ntabs-2]) 
              + tabs[ntabs-1];
  else return tabs[n-1]; }

void dcstreambuf::settabs( unsigned int n, int *t )
{ ntabs = n;

  if( tabs && tabs != t )
    delete tabs;
  tabs = new int[ntabs];

  memcpy( tabs, t, n*sizeof( *tabs ) ); }

int dcstreambuf::hardtab( void )
{ return tm.tmAveCharWidth * gettab( ++itab );}

int dcstreambuf::ansitab( void )
{ int &w = tm.tmAveCharWidth;
   for( itab++; x > w*gettab( itab ); itab++ );
   return w*gettab( itab ); }

int odcstream::x( int xnew )
{ dcstreambuf &sb = *(dcstreambuf*)rdbuf();
  int xold = sb.x;

  flush();
  sb.itab = 0;
  sb.x0 = sb.x = xnew;
  return xold; }

int odcstream::y( int ynew )
{ dcstreambuf &sb = *(dcstreambuf*)rdbuf();
  int yold = sb.y;

  flush();
  sb.itab = 0;
  sb.y = ynew;
  return yold; }

void odcstream::tabs( unsigned int n, ... )
{ va_list ap;
  va_start( ap, n );
  int *t = new int[n];

  for( int i = 0; i < n; i++ )
    t[i] = va_arg( ap, int );

  va_end( ap );
  ((dcstreambuf*)rdbuf())->settabs( n, t );
  delete t;
}

Return to "Streaming text to a device context"


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.