summaryrefslogtreecommitdiffstats
path: root/src/widgets/tqlcdnumber.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/tqlcdnumber.cpp')
-rw-r--r--src/widgets/tqlcdnumber.cpp1170
1 files changed, 1170 insertions, 0 deletions
diff --git a/src/widgets/tqlcdnumber.cpp b/src/widgets/tqlcdnumber.cpp
new file mode 100644
index 000000000..e6dbf453c
--- /dev/null
+++ b/src/widgets/tqlcdnumber.cpp
@@ -0,0 +1,1170 @@
+/****************************************************************************
+**
+** Implementation of TQLCDNumber class
+**
+** Created : 940518
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the widgets module of the TQt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free TQt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "tqlcdnumber.h"
+#ifndef TQT_NO_LCDNUMBER
+#include "tqbitarray.h"
+#include "tqpainter.h"
+
+
+/*!
+ \class TQLCDNumber tqlcdnumber.h
+
+ \brief The TQLCDNumber widget displays a number with LCD-like digits.
+
+ \ingroup basic
+ \mainclass
+
+ It can display a number in just about any size. It can display
+ decimal, hexadecimal, octal or binary numbers. It is easy to
+ connect to data sources using the display() slot, which is
+ overloaded to take any of five argument types.
+
+ There are also slots to change the base with setMode() and the
+ decimal point with setSmallDecimalPoint().
+
+ TQLCDNumber emits the overflow() signal when it is asked to display
+ something beyond its range. The range is set by setNumDigits(),
+ but setSmallDecimalPoint() also influences it. If the display is
+ set to hexadecimal, octal or binary, the integer equivalent of the
+ value is displayed.
+
+ These digits and other symbols can be shown: 0/O, 1, 2, 3, 4, 5/S,
+ 6, 7, 8, 9/g, minus, decimal point, A, B, C, D, E, F, h, H, L, o,
+ P, r, u, U, Y, colon, degree sign (which is specified as single
+ quote in the string) and space. TQLCDNumber substitutes spaces for
+ illegal characters.
+
+ It is not possible to retrieve the contents of a TQLCDNumber
+ object, although you can retrieve the numeric value with value().
+ If you really need the text, we recommend that you connect the
+ signals that feed the display() slot to another slot as well and
+ store the value there.
+
+ Incidentally, TQLCDNumber is the very oldest part of TQt, tracing
+ back to a BASIC program on the \link
+ http://www.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm
+ Sinclair Spectrum\endlink.
+
+ <img src=tqlcdnum-m.png> <img src=tqlcdnum-w.png>
+
+ \sa TQLabel, TQFrame
+*/
+
+/*!
+ \enum TQLCDNumber::Mode
+
+ This type determines how numbers are shown.
+
+ \value Hex Hexadecimal
+ \value Dec Decimal
+ \value Oct Octal
+ \value Bin Binary
+
+ If the display is set to hexadecimal, octal or binary, the integer
+ equivalent of the value is displayed.
+*/
+
+/*!
+ \enum TQLCDNumber::SegmentStyle
+
+ This type determines the visual appearance of the TQLCDNumber
+ widget.
+
+ \value Outline gives raised segments filled with the background brush.
+ \value Filled gives raised segments filled with the foreground brush.
+ \value Flat gives flat segments filled with the foreground brush.
+*/
+
+
+
+/*!
+ \fn void TQLCDNumber::overflow()
+
+ This signal is emitted whenever the TQLCDNumber is asked to display
+ a too-large number or a too-long string.
+
+ It is never emitted by setNumDigits().
+*/
+
+
+static TQString int2string( int num, int base, int ndigits, bool *oflow )
+{
+ TQString s;
+ bool negative;
+ if ( num < 0 ) {
+ negative = TRUE;
+ num = -num;
+ } else {
+ negative = FALSE;
+ }
+ switch( base ) {
+ case TQLCDNumber::HEX:
+ s.sprintf( "%*x", ndigits, num );
+ break;
+ case TQLCDNumber::DEC:
+ s.sprintf( "%*i", ndigits, num );
+ break;
+ case TQLCDNumber::OCT:
+ s.sprintf( "%*o", ndigits, num );
+ break;
+ case TQLCDNumber::BIN:
+ {
+ char buf[42];
+ char *p = &buf[41];
+ uint n = num;
+ int len = 0;
+ *p = '\0';
+ do {
+ *--p = (char)((n&1)+'0');
+ n >>= 1;
+ len++;
+ } while ( n != 0 );
+ len = ndigits - len;
+ if ( len > 0 )
+ s.fill( ' ', len );
+ s += TQString::fromLatin1(p);
+ }
+ break;
+ }
+ if ( negative ) {
+ for ( int i=0; i<(int)s.length(); i++ ) {
+ if ( s[i] != ' ' ) {
+ if ( i != 0 ) {
+ s[i-1] = '-';
+ } else {
+ s.insert( 0, '-' );
+ }
+ break;
+ }
+ }
+ }
+ if ( oflow )
+ *oflow = (int)s.length() > ndigits;
+ return s;
+}
+
+
+static TQString double2string( double num, int base, int ndigits, bool *oflow )
+{
+ TQString s;
+ if ( base != TQLCDNumber::DEC ) {
+ bool of = num >= 2147483648.0 || num < -2147483648.0;
+ if ( of ) { // oops, integer overflow
+ if ( oflow )
+ *oflow = TRUE;
+ return s;
+ }
+ s = int2string( (int)num, base, ndigits, 0 );
+ } else { // decimal base
+ int nd = ndigits;
+ do {
+ s.sprintf( "%*.*g", ndigits, nd, num );
+ int i = s.find('e');
+ if ( i > 0 && s[i+1]=='+' ) {
+ s[i] = ' ';
+ s[i+1] = 'e';
+ }
+ } while (nd-- && (int)s.length() > ndigits);
+ }
+ if ( oflow )
+ *oflow = (int)s.length() > ndigits;
+ return s;
+}
+
+
+static const char *getSegments( char ch ) // gets list of segments for ch
+{
+ static const char segments[30][8] =
+ { { 0, 1, 2, 4, 5, 6,99, 0}, // 0 0 / O
+ { 2, 5,99, 0, 0, 0, 0, 0}, // 1 1
+ { 0, 2, 3, 4, 6,99, 0, 0}, // 2 2
+ { 0, 2, 3, 5, 6,99, 0, 0}, // 3 3
+ { 1, 2, 3, 5,99, 0, 0, 0}, // 4 4
+ { 0, 1, 3, 5, 6,99, 0, 0}, // 5 5 / S
+ { 0, 1, 3, 4, 5, 6,99, 0}, // 6 6
+ { 0, 2, 5,99, 0, 0, 0, 0}, // 7 7
+ { 0, 1, 2, 3, 4, 5, 6,99}, // 8 8
+ { 0, 1, 2, 3, 5, 6,99, 0}, // 9 9 / g
+ { 3,99, 0, 0, 0, 0, 0, 0}, // 10 -
+ { 7,99, 0, 0, 0, 0, 0, 0}, // 11 .
+ { 0, 1, 2, 3, 4, 5,99, 0}, // 12 A
+ { 1, 3, 4, 5, 6,99, 0, 0}, // 13 B
+ { 0, 1, 4, 6,99, 0, 0, 0}, // 14 C
+ { 2, 3, 4, 5, 6,99, 0, 0}, // 15 D
+ { 0, 1, 3, 4, 6,99, 0, 0}, // 16 E
+ { 0, 1, 3, 4,99, 0, 0, 0}, // 17 F
+ { 1, 3, 4, 5,99, 0, 0, 0}, // 18 h
+ { 1, 2, 3, 4, 5,99, 0, 0}, // 19 H
+ { 1, 4, 6,99, 0, 0, 0, 0}, // 20 L
+ { 3, 4, 5, 6,99, 0, 0, 0}, // 21 o
+ { 0, 1, 2, 3, 4,99, 0, 0}, // 22 P
+ { 3, 4,99, 0, 0, 0, 0, 0}, // 23 r
+ { 4, 5, 6,99, 0, 0, 0, 0}, // 24 u
+ { 1, 2, 4, 5, 6,99, 0, 0}, // 25 U
+ { 1, 2, 3, 5, 6,99, 0, 0}, // 26 Y
+ { 8, 9,99, 0, 0, 0, 0, 0}, // 27 :
+ { 0, 1, 2, 3,99, 0, 0, 0}, // 28 '
+ {99, 0, 0, 0, 0, 0, 0, 0} }; // 29 empty
+
+ if (ch >= '0' && ch <= '9')
+ return segments[ch - '0'];
+ if (ch >= 'A' && ch <= 'F')
+ return segments[ch - 'A' + 12];
+ if (ch >= 'a' && ch <= 'f')
+ return segments[ch - 'a' + 12];
+
+ int n;
+ switch ( ch ) {
+ case '-':
+ n = 10; break;
+ case 'O':
+ n = 0; break;
+ case 'g':
+ n = 9; break;
+ case '.':
+ n = 11; break;
+ case 'h':
+ n = 18; break;
+ case 'H':
+ n = 19; break;
+ case 'l':
+ case 'L':
+ n = 20; break;
+ case 'o':
+ n = 21; break;
+ case 'p':
+ case 'P':
+ n = 22; break;
+ case 'r':
+ case 'R':
+ n = 23; break;
+ case 's':
+ case 'S':
+ n = 5; break;
+ case 'u':
+ n = 24; break;
+ case 'U':
+ n = 25; break;
+ case 'y':
+ case 'Y':
+ n = 26; break;
+ case ':':
+ n = 27; break;
+ case '\'':
+ n = 28; break;
+ default:
+ n = 29; break;
+ }
+ return segments[n];
+}
+
+
+/*!
+ Constructs an LCD number, sets the number of digits to 5, the base
+ to decimal, the decimal point mode to 'small' and the frame style
+ to a raised box. The segmentStyle() is set to \c Outline.
+
+ The \a parent and \a name arguments are passed to the TQFrame
+ constructor.
+
+ \sa setNumDigits(), setSmallDecimalPoint()
+*/
+
+TQLCDNumber::TQLCDNumber( TQWidget *parent, const char *name )
+ : TQFrame( parent, name )
+{
+ ndigits = 5;
+ init();
+}
+
+
+/*!
+ Constructs an LCD number, sets the number of digits to \a
+ numDigits, the base to decimal, the decimal point mode to 'small'
+ and the frame style to a raised box. The segmentStyle() is set to
+ \c Outline.
+
+ The \a parent and \a name arguments are passed to the TQFrame
+ constructor.
+
+ \sa setNumDigits(), setSmallDecimalPoint()
+*/
+
+TQLCDNumber::TQLCDNumber( uint numDigits, TQWidget *parent, const char *name )
+ : TQFrame( parent, name )
+{
+ ndigits = numDigits;
+ init();
+}
+
+/*!
+ \internal
+*/
+
+void TQLCDNumber::init()
+{
+ setFrameStyle( TQFrame::Box | TQFrame::Raised );
+ val = 0;
+ base = DEC;
+ smallPoint = FALSE;
+ setNumDigits( ndigits );
+ setSegmentStyle( Outline );
+ d = 0;
+ setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
+}
+
+/*!
+ Destroys the LCD number.
+*/
+
+TQLCDNumber::~TQLCDNumber()
+{
+}
+
+
+/*!
+ \property TQLCDNumber::numDigits
+ \brief the current number of digits displayed
+
+ Corresponds to the current number of digits. If \l
+ TQLCDNumber::smallDecimalPoint is FALSE, the decimal point occupies
+ one digit position.
+
+ \sa numDigits, smallDecimalPoint
+*/
+
+void TQLCDNumber::setNumDigits( int numDigits )
+{
+ if ( numDigits > 99 ) {
+#if defined(QT_CHECK_RANGE)
+ tqWarning( "TQLCDNumber::setNumDigits: (%s) Max 99 digits allowed",
+ name( "unnamed" ) );
+#endif
+ numDigits = 99;
+ }
+ if (numDigits < 0 ) {
+#if defined(QT_CHECK_RANGE)
+ tqWarning( "TQLCDNumber::setNumDigits: (%s) Min 0 digits allowed",
+ name( "unnamed" ) );
+#endif
+ numDigits = 0;
+ }
+ if ( digitStr.isNull() ) { // from constructor
+ ndigits = numDigits;
+ digitStr.fill( ' ', ndigits );
+ points.fill( 0, ndigits );
+ digitStr[ndigits - 1] = '0'; // "0" is the default number
+ } else {
+ bool doDisplay = ndigits == 0;
+ if ( numDigits == ndigits ) // no change
+ return;
+ int i;
+ int dif;
+ if ( numDigits > ndigits ) { // expand
+ dif = numDigits - ndigits;
+ TQString buf;
+ buf.fill( ' ', dif );
+ digitStr.insert( 0, buf );
+ points.resize( numDigits );
+ for ( i=numDigits-1; i>=dif; i-- )
+ points.setBit( i, points.testBit(i-dif) );
+ for ( i=0; i<dif; i++ )
+ points.clearBit( i );
+ } else { // shrink
+ dif = ndigits - numDigits;
+ digitStr = digitStr.right( numDigits );
+ TQBitArray tmpPoints = points.copy();
+ points.resize( numDigits );
+ for ( i=0; i<(int)numDigits; i++ )
+ points.setBit( i, tmpPoints.testBit(i+dif) );
+ }
+ ndigits = numDigits;
+ if ( doDisplay )
+ display( value() );
+ update();
+ }
+}
+
+
+/*!
+ \overload
+
+ Returns TRUE if \a num is too big to be displayed in its entirety;
+ otherwise returns FALSE.
+
+ \sa display(), numDigits(), smallDecimalPoint()
+*/
+
+bool TQLCDNumber::checkOverflow( int num ) const
+{
+ bool of;
+ int2string( num, base, ndigits, &of );
+ return of;
+}
+
+
+/*!
+ Returns TRUE if \a num is too big to be displayed in its entirety;
+ otherwise returns FALSE.
+
+ \sa display(), numDigits(), smallDecimalPoint()
+*/
+
+bool TQLCDNumber::checkOverflow( double num ) const
+{
+ bool of;
+ double2string( num, base, ndigits, &of );
+ return of;
+}
+
+
+/*!
+ \property TQLCDNumber::mode
+ \brief the current display mode (number base)
+
+ Corresponds to the current display mode, which is one of \c BIN,
+ \c OCT, \c DEC (the default) and \c HEX. \c DEC mode can display
+ floating point values, the other modes display the integer
+ equivalent.
+
+ \sa smallDecimalPoint(), setHexMode(), setDecMode(), setOctMode(), setBinMode()
+*/
+
+TQLCDNumber::Mode TQLCDNumber::mode() const
+{
+ return (TQLCDNumber::Mode) base;
+}
+
+void TQLCDNumber::setMode( Mode m )
+{
+ base = m;
+
+ display( val );
+}
+
+
+/*!
+ \property TQLCDNumber::value
+ \brief the displayed value
+
+ This property corresponds to the current value displayed by the
+ LCDNumber.
+
+ If the displayed value is not a number, the property has a value
+ of 0.
+*/
+
+double TQLCDNumber::value() const
+{
+ return val;
+}
+
+/*!
+ \overload
+
+ Displays the number \a num.
+*/
+void TQLCDNumber::display( double num )
+{
+ val = num;
+ bool of;
+ TQString s = double2string( num, base, ndigits, &of );
+ if ( of )
+ emit overflow();
+ else
+ internalSetString( s );
+}
+
+/*!
+ \property TQLCDNumber::intValue
+ \brief the displayed value rounded to the nearest integer
+
+ This property corresponds to the nearest integer to the current
+ value displayed by the LCDNumber. This is the value used for
+ hexadecimal, octal and binary modes.
+
+ If the displayed value is not a number, the property has a value
+ of 0.
+*/
+int TQLCDNumber::intValue() const
+{
+ return (int)(val < 0 ? val - 0.5 : val + 0.5);
+}
+
+
+/*!
+ \overload
+
+ Displays the number \a num.
+*/
+void TQLCDNumber::display( int num )
+{
+ val = (double)num;
+ bool of;
+ TQString s = int2string( num, base, ndigits, &of );
+ if ( of )
+ emit overflow();
+ else
+ internalSetString( s );
+}
+
+
+/*!
+ Displays the number represented by the string \a s.
+
+ This version of the function disregards mode() and
+ smallDecimalPoint().
+
+ These digits and other symbols can be shown: 0/O, 1, 2, 3, 4, 5/S,
+ 6, 7, 8, 9/g, minus, decimal point, A, B, C, D, E, F, h, H, L, o,
+ P, r, u, U, Y, colon, degree sign (which is specified as single
+ quote in the string) and space. TQLCDNumber substitutes spaces for
+ illegal characters.
+*/
+
+void TQLCDNumber::display( const TQString &s )
+{
+ val = 0;
+ bool ok = FALSE;
+ double v = s.toDouble( &ok );
+ if ( ok )
+ val = v;
+ internalSetString( s );
+}
+
+/*!
+ Calls setMode( HEX ). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setDecMode(), setOctMode(), setBinMode(), mode()
+*/
+
+void TQLCDNumber::setHexMode()
+{
+ setMode( HEX );
+}
+
+
+/*!
+ Calls setMode( DEC ). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setOctMode(), setBinMode(), mode()
+*/
+
+void TQLCDNumber::setDecMode()
+{
+ setMode( DEC );
+}
+
+
+/*!
+ Calls setMode( OCT ). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setDecMode(), setBinMode(), mode()
+*/
+
+void TQLCDNumber::setOctMode()
+{
+ setMode( OCT );
+}
+
+
+/*!
+ Calls setMode( BIN ). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setDecMode(), setOctMode(), mode()
+*/
+
+void TQLCDNumber::setBinMode()
+{
+ setMode( BIN );
+}
+
+
+/*!
+ \property TQLCDNumber::smallDecimalPoint
+ \brief the style of the decimal point
+
+ If TRUE the decimal point is drawn between two digit positions.
+ Otherwise it occupies a digit position of its own, i.e. is drawn
+ in a digit position. The default is FALSE.
+
+ The inter-digit space is made slightly wider when the decimal
+ point is drawn between the digits.
+
+ \sa mode
+*/
+
+void TQLCDNumber::setSmallDecimalPoint( bool b )
+{
+ smallPoint = b;
+}
+
+
+/*!
+ Draws the LCD number using painter \a p. This function is called
+ from TQFrame::paintEvent().
+*/
+
+
+void TQLCDNumber::drawContents( TQPainter *p )
+{
+ if ( smallPoint )
+ drawString( digitStr, *p, &points, FALSE );
+ else
+ drawString( digitStr, *p, 0, FALSE );
+}
+
+
+/*!
+ \internal
+*/
+
+void TQLCDNumber::internalDisplay( const TQString & )
+{
+ // Not used anymore
+}
+
+void TQLCDNumber::internalSetString( const TQString& s )
+{
+ TQString buffer;
+ int i;
+ int len = s.length();
+ TQBitArray newPoints(ndigits);
+
+ if ( !smallPoint ) {
+ if ( len == ndigits )
+ buffer = s;
+ else
+ buffer = s.right( ndigits ).rightJustify( ndigits, ' ' );
+ } else {
+ int index = -1;
+ bool lastWasPoint = TRUE;
+ newPoints.clearBit(0);
+ for ( i=0; i<len; i++ ) {
+ if ( s[i] == '.' ) {
+ if ( lastWasPoint ) { // point already set for digit?
+ if ( index == ndigits - 1 ) // no more digits
+ break;
+ index++;
+ buffer[index] = ' '; // 2 points in a row, add space
+ }
+ newPoints.setBit(index); // set decimal point
+ lastWasPoint = TRUE;
+ } else {
+ if ( index == ndigits - 1 )
+ break;
+ index++;
+ buffer[index] = s[i];
+ newPoints.clearBit(index); // decimal point default off
+ lastWasPoint = FALSE;
+ }
+ }
+ if ( index < ((int) ndigits) - 1 ) {
+ for( i=index; i>=0; i-- ) {
+ buffer[ndigits - 1 - index + i] = buffer[i];
+ newPoints.setBit( ndigits - 1 - index + i,
+ newPoints.testBit(i) );
+ }
+ for( i=0; i<ndigits-index-1; i++ ) {
+ buffer[i] = ' ';
+ newPoints.clearBit(i);
+ }
+ }
+ }
+
+ if ( buffer == digitStr )
+ return;
+
+ if ( backgroundMode() == FixedPixmap
+ || colorGroup().brush( TQColorGroup::Background ).pixmap() ) {
+ digitStr = buffer;
+ if ( smallPoint )
+ points = newPoints;
+ repaint( contentsRect() );
+ } else {
+ TQPainter p( this );
+ if ( !smallPoint )
+ drawString( buffer, p );
+ else
+ drawString( buffer, p, &newPoints );
+ }
+}
+
+/*!
+ \internal
+*/
+
+void TQLCDNumber::drawString( const TQString &s, TQPainter &p,
+ TQBitArray *newPoints, bool newString )
+{
+ TQPoint pos;
+
+ int digitSpace = smallPoint ? 2 : 1;
+ int xSegLen = width()*5/(ndigits*(5 + digitSpace) + digitSpace);
+ int ySegLen = height()*5/12;
+ int segLen = ySegLen > xSegLen ? xSegLen : ySegLen;
+ int xAdvance = segLen*( 5 + digitSpace )/5;
+ int xOffset = ( width() - ndigits*xAdvance + segLen/5 )/2;
+ int yOffset = ( height() - segLen*2 )/2;
+
+ for ( int i=0; i<ndigits; i++ ) {
+ pos = TQPoint( xOffset + xAdvance*i, yOffset );
+ if ( newString )
+ drawDigit( pos, p, segLen, s[i], digitStr[i].latin1() );
+ else
+ drawDigit( pos, p, segLen, s[i]);
+ if ( newPoints ) {
+ char newPoint = newPoints->testBit(i) ? '.' : ' ';
+ if ( newString ) {
+ char oldPoint = points.testBit(i) ? '.' : ' ';
+ drawDigit( pos, p, segLen, newPoint, oldPoint );
+ } else {
+ drawDigit( pos, p, segLen, newPoint );
+ }
+ }
+ }
+ if ( newString ) {
+ digitStr = s;
+ if ( (int)digitStr.length() > ndigits )
+ digitStr.truncate( ndigits );
+ if ( newPoints )
+ points = *newPoints;
+ }
+}
+
+
+/*!
+ \internal
+*/
+
+void TQLCDNumber::drawDigit( const TQPoint &pos, TQPainter &p, int segLen,
+ char newCh, char oldCh )
+{
+// Draws and/or erases segments to change display of a single digit
+// from oldCh to newCh
+
+ char updates[18][2]; // can hold 2 times number of segments, only
+ // first 9 used if segment table is correct
+ int nErases;
+ int nUpdates;
+ const char *segs;
+ int i,j;
+
+ const char erase = 0;
+ const char draw = 1;
+ const char leaveAlone = 2;
+
+ segs = getSegments(oldCh);
+ for ( nErases=0; segs[nErases] != 99; nErases++ ) {
+ updates[nErases][0] = erase; // get segments to erase to
+ updates[nErases][1] = segs[nErases]; // remove old char
+ }
+ nUpdates = nErases;
+ segs = getSegments(newCh);
+ for(i = 0 ; segs[i] != 99 ; i++) {
+ for ( j=0; j<nErases; j++ )
+ if ( segs[i] == updates[j][1] ) { // same segment ?
+ updates[j][0] = leaveAlone; // yes, already on screen
+ break;
+ }
+ if ( j == nErases ) { // if not already on screen
+ updates[nUpdates][0] = draw;
+ updates[nUpdates][1] = segs[i];
+ nUpdates++;
+ }
+ }
+ for ( i=0; i<nUpdates; i++ ) {
+ if ( updates[i][0] == draw )
+ drawSegment( pos, updates[i][1], p, segLen );
+ if (updates[i][0] == erase)
+ drawSegment( pos, updates[i][1], p, segLen, TRUE );
+ }
+}
+
+
+static void addPoint( TQPointArray &a, const TQPoint &p )
+{
+ uint n = a.size();
+ a.resize( n + 1 );
+ a.setPoint( n, p );
+}
+
+/*!
+ \internal
+*/
+
+void TQLCDNumber::drawSegment( const TQPoint &pos, char segmentNo, TQPainter &p,
+ int segLen, bool erase )
+{
+ TQPoint pt = pos;
+ int width = segLen/5;
+
+ const TQColorGroup & g = colorGroup();
+ TQColor lightColor,darkColor,fgColor;
+ if ( erase ){
+ lightColor = backgroundColor();
+ darkColor = lightColor;
+ fgColor = lightColor;
+ } else {
+ lightColor = g.light();
+ darkColor = g.dark();
+ fgColor = g.foreground();
+ }
+
+#define LINETO(X,Y) addPoint( a, TQPoint(pt.x() + (X),pt.y() + (Y)))
+#define LIGHT
+#define DARK
+
+ if ( fill ) {
+ TQPointArray a(0);
+
+ //The following is an exact copy of the switch below.
+ //don't make any changes here
+ switch ( segmentNo ) {
+ case 0 :
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(segLen - width - 1,width);
+ LINETO(width,width);
+ LINETO(0,0);
+ break;
+ case 1 :
+ pt += TQPoint(0 , 1);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,width);
+ DARK;
+ LINETO(width,segLen - width/2 - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 2 :
+ pt += TQPoint(segLen - 1 , 1);
+ p.moveTo(pt);
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width/2 - 2);
+ LIGHT;
+ LINETO(-width,width);
+ LINETO(0,0);
+ break;
+ case 3 :
+ pt += TQPoint(0 , segLen);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,-width/2);
+ LINETO(segLen - width - 1,-width/2);
+ LINETO(segLen - 1,0);
+ DARK;
+ if (width & 1) { // adjust for integer division error
+ LINETO(segLen - width - 3,width/2 + 1);
+ LINETO(width + 2,width/2 + 1);
+ } else {
+ LINETO(segLen - width - 1,width/2);
+ LINETO(width,width/2);
+ }
+ LINETO(0,0);
+ break;
+ case 4 :
+ pt += TQPoint(0 , segLen + 1);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,width/2);
+ DARK;
+ LINETO(width,segLen - width - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 5 :
+ pt += TQPoint(segLen - 1 , segLen + 1);
+ p.moveTo(pt);
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width - 2);
+ LIGHT;
+ LINETO(-width,width/2);
+ LINETO(0,0);
+ break;
+ case 6 :
+ pt += TQPoint(0 , segLen*2);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,-width);
+ LINETO(segLen - width - 1,-width);
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(0,0);
+ break;
+ case 7 :
+ if ( smallPoint ) // if smallpoint place'.' between other digits
+ pt += TQPoint(segLen + width/2 , segLen*2);
+ else
+ pt += TQPoint(segLen/2 , segLen*2);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 8 :
+ pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 9 :
+ pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+#if defined(QT_CHECK_RANGE)
+ default :
+ tqWarning( "TQLCDNumber::drawSegment: (%s) Internal error."
+ " Illegal segment id: %d\n",
+ name( "unnamed" ), segmentNo );
+#endif
+ }
+ // End exact copy
+ p.setPen( fgColor );
+ p.setBrush( fgColor );
+ p.drawPolygon( a );
+ p.setBrush( NoBrush );
+
+ pt = pos;
+ }
+#undef LINETO
+#undef LIGHT
+#undef DARK
+
+#define LINETO(X,Y) p.lineTo(TQPoint(pt.x() + (X),pt.y() + (Y)))
+#define LIGHT p.setPen(lightColor)
+#define DARK p.setPen(darkColor)
+ if ( shadow )
+ switch ( segmentNo ) {
+ case 0 :
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(segLen - width - 1,width);
+ LINETO(width,width);
+ LINETO(0,0);
+ break;
+ case 1 :
+ pt += TQPoint(0,1);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,width);
+ DARK;
+ LINETO(width,segLen - width/2 - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 2 :
+ pt += TQPoint(segLen - 1 , 1);
+ p.moveTo(pt);
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width/2 - 2);
+ LIGHT;
+ LINETO(-width,width);
+ LINETO(0,0);
+ break;
+ case 3 :
+ pt += TQPoint(0 , segLen);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,-width/2);
+ LINETO(segLen - width - 1,-width/2);
+ LINETO(segLen - 1,0);
+ DARK;
+ if (width & 1) { // adjust for integer division error
+ LINETO(segLen - width - 3,width/2 + 1);
+ LINETO(width + 2,width/2 + 1);
+ } else {
+ LINETO(segLen - width - 1,width/2);
+ LINETO(width,width/2);
+ }
+ LINETO(0,0);
+ break;
+ case 4 :
+ pt += TQPoint(0 , segLen + 1);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,width/2);
+ DARK;
+ LINETO(width,segLen - width - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 5 :
+ pt += TQPoint(segLen - 1 , segLen + 1);
+ p.moveTo(pt);
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width - 2);
+ LIGHT;
+ LINETO(-width,width/2);
+ LINETO(0,0);
+ break;
+ case 6 :
+ pt += TQPoint(0 , segLen*2);
+ p.moveTo(pt);
+ LIGHT;
+ LINETO(width,-width);
+ LINETO(segLen - width - 1,-width);
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(0,0);
+ break;
+ case 7 :
+ if ( smallPoint ) // if smallpoint place'.' between other digits
+ pt += TQPoint(segLen + width/2 , segLen*2);
+ else
+ pt += TQPoint(segLen/2 , segLen*2);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 8 :
+ pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 9 :
+ pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
+ p.moveTo(pt);
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+#if defined(QT_CHECK_RANGE)
+ default :
+ tqWarning( "TQLCDNumber::drawSegment: (%s) Internal error."
+ " Illegal segment id: %d\n",
+ name( "unnamed" ), segmentNo );
+#endif
+ }
+
+#undef LINETO
+#undef LIGHT
+#undef DARK
+}
+
+
+
+/*!
+ \property TQLCDNumber::segmentStyle
+ \brief the style of the LCDNumber
+
+ \table
+ \header \i Style \i Result
+ \row \i \c Outline
+ \i Produces raised segments filled with the background color
+ (this is the default).
+ \row \i \c Filled
+ \i Produces raised segments filled with the foreground color.
+ \row \i \c Flat
+ \i Produces flat segments filled with the foreground color.
+ \endtable
+
+ \c Outline and \c Filled will additionally use
+ TQColorGroup::light() and TQColorGroup::dark() for shadow effects.
+*/
+void TQLCDNumber::setSegmentStyle( SegmentStyle s )
+{
+ fill = ( s == Flat || s == Filled );
+ shadow = ( s == Outline || s == Filled );
+ update();
+}
+
+TQLCDNumber::SegmentStyle TQLCDNumber::segmentStyle() const
+{
+ Q_ASSERT( fill || shadow );
+ if ( !fill && shadow )
+ return Outline;
+ if ( fill && shadow )
+ return Filled;
+ return Flat;
+}
+
+
+/*!\reimp
+*/
+TQSize TQLCDNumber::sizeHint() const
+{
+ return TQSize( 10 + 9 * (numDigits() + (smallDecimalPoint() ? 0 : 1)), 23 );
+}
+
+#endif // TQT_NO_LCDNUMBER