All pastes #953923 Raw Edit

Anonymous

public text v1 · immutable
#953923 ·published 2008-03-23 14:38 UTC
rendered paste body
void TerminalDisplay::updateImage() 
{
  if ( !_screenWindow )
      return;

  // optimization - scroll the existing image where possible and 
  // avoid expensive text drawing for parts of the image that 
  // can simply be moved up or down
  scrollImage( _screenWindow->scrollCount() ,
               _screenWindow->scrollRegion() );
  _screenWindow->resetScrollCount();

  Character* const newimg = _screenWindow->getImage();
  int lines = _screenWindow->windowLines();
  int columns = _screenWindow->windowColumns();

  setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() );

  if (!_image)
     updateImageSize(); // Create _image

  Q_ASSERT( this->_usedLines <= this->_lines );
  Q_ASSERT( this->_usedColumns <= this->_columns );

  int y,x,len;

  QPoint tL  = contentsRect().topLeft();
  int    tLx = tL.x();
  int    tLy = tL.y();
  _hasBlinker = false;

  CharacterColor cf;       // undefined
  CharacterColor _clipboard;       // undefined
  int cr  = -1;   // undefined

  const int linesToUpdate = qMin(this->_lines, qMax(0,lines  ));
  const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));

  QChar *disstrU = new QChar[columnsToUpdate];
  char *dirtyMask = new char[columnsToUpdate+2]; 
  QRegion dirtyRegion;

  // debugging variable, this records the number of lines that are found to
  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
  // which therefore need to be repainted
  int dirtyLineCount = 0;

  for (y = 0; y < linesToUpdate; y++)
  {
    const Character*       currentLine = &_image[y*this->_columns];
    const Character* const newLine = &newimg[y*columns];

    bool updateLine = false;
    
    // The dirty mask indicates which characters need repainting. We also
    // mark surrounding neighbours dirty, in case the character exceeds
    // its cell boundaries
    memset(dirtyMask, 0, columnsToUpdate+2);
   
    for( x = 0 ; x < columnsToUpdate ; x++)
    {
        if ( newLine[x] != currentLine[x] ) 
        {
            dirtyMask[x] = true;
        }
    }

    if (!_resizing) // not while _resizing, we're expecting a paintEvent
    for (x = 0; x < columnsToUpdate; x++)
    {
      _hasBlinker |= (newLine[x].rendition & RE_BLINK);
    
      // Start drawing if this character or the next one differs.
      // We also take the next one into account to handle the situation
      // where characters exceed their cell width.
      if (dirtyMask[x])
      {
        quint16 c = newLine[x+0].character;
        if ( !c )
            continue;
        int p = 0;
        disstrU[p++] = c; //fontMap(c);
        bool lineDraw = isLineChar(c);
        bool doubleWidth = (newLine[x+1].character == 0);
        cr = newLine[x].rendition;
        _clipboard = newLine[x].backgroundColor;
        if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
        int lln = columnsToUpdate - x;
        for (len = 1; len < lln; len++)
        {
            const Character& ch = newLine[x+len];

            if (!ch.character)
                continue; // Skip trailing part of multi-col chars.

            if (  ch.foregroundColor != cf || 
                  ch.backgroundColor != _clipboard || 
                  ch.rendition != cr ||
                  !dirtyMask[x+len] || 
                  isLineChar(c) != lineDraw || 
                  (newLine[x+len+1].character == 0) != doubleWidth )
            break;

          disstrU[p++] = c; //fontMap(c);
        }

        QString unistr(disstrU, p);

        bool saveFixedFont = _fixedFont;
        if (lineDraw)
           _fixedFont = false;
        if (doubleWidth)
           _fixedFont = false;

        updateLine = true;

        _fixedFont = saveFixedFont;
        x += len - 1;
      }
      
    }

	//both the top and bottom halves of double height _lines must always be redrawn
	//although both top and bottom halves contain the same characters, only 
    //the top one is actually 
	//drawn.
    if (_lineProperties.count() > y)
        updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);

    // if the characters on the line are different in the old and the new _image
    // then this line must be repainted.    
    if (updateLine)
    {
        dirtyLineCount++;

        // add the area occupied by this line to the region which needs to be
        // repainted
        QRect dirtyRect = QRect( _leftMargin+tLx , 
                                 _topMargin+tLy+_fontHeight*y , 
                                 _fontWidth * columnsToUpdate , 
                                 _fontHeight ); 	

        dirtyRegion |= dirtyRect;
    }

    // replace the line of characters in the old _image with the 
    // current line of the new _image 
    memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));
  }

  // if the new _image is smaller than the previous _image, then ensure that the area
  // outside the new _image is cleared 
  if ( linesToUpdate < _usedLines )
  {
    dirtyRegion |= QRect(   _leftMargin+tLx , 
                            _topMargin+tLy+_fontHeight*linesToUpdate , 
                            _fontWidth * this->_columns , 
                            _fontHeight * (_usedLines-linesToUpdate) );
  }
  _usedLines = linesToUpdate;
  
  if ( columnsToUpdate < _usedColumns )
  {
    dirtyRegion |= QRect(   _leftMargin+tLx+columnsToUpdate*_fontWidth , 
                            _topMargin+tLy , 
                            _fontWidth * (_usedColumns-columnsToUpdate) , 
                            _fontHeight * this->_lines );
  }
  _usedColumns = columnsToUpdate;

  dirtyRegion |= _inputMethodData.previousPreeditRect;

  // update the parts of the display which have changed
  update(dirtyRegion);

  if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY ); 
  if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }
  delete[] dirtyMask;
  delete[] disstrU;

  showResizeNotification();
}