September, 1995 - Vol. 2 No. 9
#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.