void CText::wrap()

in graphics/nxwidgets/src/ctext.cxx [357:585]


void CText::wrap(int charIndex)
{
  // Declare vars in advance of loop

  int pos = 0;
  int lineWidth;
  int breakIndex;
  bool endReached = false;

  if (m_linePositions.size() == 0)
    {
      charIndex = 0;
    }

  // If we're wrapping from an offset in the text, ensure that any existing data
  // after the offset gets removed

  if (charIndex > 0)
    {
      // Remove wrapping data past this point

      // Get the index of the line in which the char index appears

      int lineIndex = getLineContainingCharIndex(charIndex);

      // Remove any longest line records that occur from the line index onwards

      while ((m_longestLines.size() > 0) &&
             (m_longestLines[m_longestLines.size() - 1].index >= lineIndex))
        {
          m_longestLines.pop_back();
        }

      // If there are any longest line records remaining, update the text pixel width
      // The last longest line record will always be the last valid longest line as
      // the vector is sorted by length

      if (m_longestLines.size() > 0)
        {
          m_textPixelWidth = m_longestLines[m_longestLines.size() - 1].width;
        }
      else
        {
          m_textPixelWidth = 0;
        }

      // Remove any wrapping data from after this line index onwards

      while ((m_linePositions.size() > 0) &&
             (m_linePositions.size() - 1 > (int)lineIndex))
       {
          m_linePositions.pop_back();
        }

      // Adjust start position of wrapping loop so that it starts with
      // the current line index

      if (m_linePositions.size() > 0)
        {
          pos = m_linePositions[m_linePositions.size() - 1];
        }
    }
  else
    {
      // Remove all wrapping data

      // Wipe the width variable

      m_textPixelWidth = 0;

      // Empty existing longest lines

      m_longestLines.clear();

      // Empty existing line positions

      m_linePositions.clear();

      // Push first line start into vector

      m_linePositions.push_back(0);
    }

  // Loop through string until the end

  CStringIterator *iterator = newStringIterator();

  while (!endReached)
    {
      breakIndex = 0;
      lineWidth = 0;

      if (iterator->moveTo(pos))
        {
          // Search for line breaks and valid breakpoints until we
          // exceed the width of the text field or we run out of
          // string to process

          while (lineWidth + m_font->getCharWidth(iterator->getChar()) <= m_width)
            {
              lineWidth += m_font->getCharWidth(iterator->getChar());

              // Check for line return

              if (iterator->getChar() == '\n')
                {
                  // Remember this breakpoint

                  breakIndex = iterator->getIndex();
                  break;
                }
              else if ((iterator->getChar() == ' ') ||
                       (iterator->getChar() == ',') ||
                       (iterator->getChar() == '.') ||
                       (iterator->getChar() == '-') ||
                       (iterator->getChar() == ':') ||
                       (iterator->getChar() == ';') ||
                       (iterator->getChar() == '?') ||
                       (iterator->getChar() == '!') ||
                       (iterator->getChar() == '+') ||
                       (iterator->getChar() == '=') ||
                       (iterator->getChar() == '/') ||
                       (iterator->getChar() == '\0'))
                {
                  // Remember the most recent breakpoint

                  breakIndex = iterator->getIndex();
                }

              // Move to the next character

              if (!iterator->moveToNext())
                {
                  // No more text; abort loop

                  endReached = true;
                  break;
                }
            }
        }
      else
        {
          endReached = true;
        }

      if ((!endReached) && (iterator->getIndex() > pos))
        {
          // Process any found data

          // If we didn't find a breakpoint split at the current position

          if (breakIndex == 0)
            {
              breakIndex = iterator->getIndex() - 1;
            }

          // Trim blank space from the start of the next line

          CStringIterator *breakIterator = newStringIterator();

          if (breakIterator->moveTo(breakIndex + 1))
            {
              while (breakIterator->getChar() == ' ')
                {
                  if (breakIterator->moveToNext())
                    {
                      breakIndex++;
                    }
                  else
                    {
                      break;
                    }
                }
            }

          delete breakIterator;

          // Add the start of the next line to the vector

          pos = breakIndex + 1;
          m_linePositions.push_back(pos);

          // Is this the longest line observed so far?

          if (lineWidth > m_textPixelWidth)
            {
              m_textPixelWidth = lineWidth;

              // Push the description of the line into the longest lines
              // vector (note that we store the index in m_linePositions that
              // refers to the start of the line, *not* the position of the
              // line in the char array)

              LongestLine line;
              line.index = m_linePositions.size() - 2;
              line.width = lineWidth;
              m_longestLines.push_back(line);
            }
        }
      else if (!endReached)
        {
          // Add a blank row if we're not at the end of the string

          pos++;
          m_linePositions.push_back(pos);
        }
    }

  // Add marker indicating end of text
  // If we reached the end of the text, append the stopping point

  if ((unsigned int)m_linePositions[m_linePositions.size() - 1] != getLength() + 1)
    {
      m_linePositions.push_back(getLength());
    }

  delete iterator;

  // Calculate the total height of the text

  m_textPixelHeight = getLineCount() * (m_font->getHeight() + m_lineSpacing);

  // Ensure height is always at least one row

  if (m_textPixelHeight == 0)
    {
      m_textPixelHeight = m_font->getHeight() + m_lineSpacing;
    }
}