⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guimltextctrl.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
   //  change?
   mTextBuffer.cut(rangeStart, rangeEnd - rangeStart);

   if (mCursorPosition <= rangeStart) 
   {
      // Cursor placed before deleted text, ignore
   }
   else if (mCursorPosition > rangeStart && mCursorPosition <= rangeEnd) 
   {
      // Cursor inside deleted text, set to start of range
      mCursorPosition = rangeStart;
   }
   else 
   {
      // Cursor after deleted text, decrement by number of chars deleted
      mCursorPosition -= (rangeEnd - rangeStart) + 1;
   }

   AssertFatal(mCursorPosition <= mTextBuffer.length(), "GuiMLTextCtrl::deleteChars: bad cursor position");
   mDirty = true;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::copyToClipboard(const U32 rangeStart, const U32 rangeEnd)
{
   AssertFatal(rangeStart < mTextBuffer.length() && rangeEnd < mTextBuffer.length(),
               avar("GuiMLTextCtrl::copyToClipboard: can't copy outside of current text (%d, %d, %d)",
                    rangeStart, rangeEnd, mTextBuffer.length()));
   AssertFatal(rangeStart <= rangeEnd, "GuiMLTextCtrl::copyToClipboard: invalid copy range");

   //copy the selection to the clipboard

   StringBuffer selection = mTextBuffer.substring(rangeStart, rangeEnd-rangeStart);
   FrameTemp<UTF8> selBuff(selection.length() * 3 + 1);
   selection.get(selBuff, selection.length() * 3 + 1);

   Platform::setClipboard(selBuff);
}

//--------------------------------------------------------------------------
bool GuiMLTextCtrl::isSelectionActive() const
{
   return mSelectionActive;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::clearSelection()
{
   mSelectionActive = false;
   mSelectionStart  = 0;
   mSelectionEnd    = 0;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::scrollToTag( U32 id )
{
   // If the parent control is not a GuiScrollContentCtrl, then this call is invalid:
   GuiScrollCtrl *pappy = dynamic_cast<GuiScrollCtrl*>(getParent());
   if ( !pappy )
      return;

   // Find the indicated tag:
   LineTag* tag = NULL;
   for ( tag = mTagList; tag; tag = tag->next )
   {
      if ( tag->id == id )
         break;
   }

   if ( !tag )
   {
      Con::warnf( ConsoleLogEntry::General, "GuiMLTextCtrl::scrollToTag - tag id %d not found!", id );
      return;
   }
	pappy->scrollRectVisible(RectI(0, tag->y, 1, 1));
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::scrollToTop()
{
   // If the parent control is not a GuiScrollContentCtrl, then this call is invalid:
   GuiScrollCtrl *pappy = dynamic_cast<GuiScrollCtrl*>(getParent());
   if ( !pappy )
      return;
	pappy->scrollRectVisible(RectI(0,0,0,0));
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::scrollToBottom()
{
   // If the parent control is not a GuiScrollContentCtrl, then this call is invalid:
   GuiScrollCtrl *pappy = dynamic_cast<GuiScrollCtrl*>(getParent());
   if ( !pappy )
      return;

   // Figure bounds for the bottom left corner
   RectI cornerBounds (0, getPosition().y + getExtent().y, 1, 1);
   pappy->scrollRectVisible(cornerBounds);
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::Atom *GuiMLTextCtrl::findHitAtom(const Point2I localCoords)
{
   AssertFatal(mAwake, "Can't get the text position of a sleeping control.");
   if(mDirty)
      reflow();
   for(Line *walk = mLineList; walk; walk = walk->next)
   {
      if(localCoords.y < walk->y)
         return NULL;

      if(localCoords.y >= walk->y && localCoords.y < walk->y + walk->height)
      {
         for(Atom *awalk = walk->atomList; awalk; awalk = awalk->next)
         {
            if(localCoords.x < awalk->xStart)
               return NULL;
            if(localCoords.x >= awalk->xStart + awalk->width)
               continue;
            return awalk;
         }
      }
   }
   return NULL;
}

//--------------------------------------------------------------------------
S32 GuiMLTextCtrl::getTextPosition(const Point2I& localCoords)
{
   AssertFatal(mAwake, "Can't get the text position of a sleeping control.");
   if(mDirty)
      reflow();
   U32 last = 0;

   for(Line *walk = mLineList; walk; walk = walk->next)
   {
      if((S32)localCoords.y < (S32)walk->y)
         return walk->textStart;

      if(localCoords.y >= walk->y && localCoords.y < walk->y + walk->height)
      {
         for(Atom *awalk = walk->atomList; awalk; awalk = awalk->next)
         {
            if(localCoords.x < awalk->xStart)
               return awalk->textStart;
            if(localCoords.x >= awalk->xStart + awalk->width)
               continue;
            // it's in the text block...
            U32 x = awalk->xStart;
            GFont *font = awalk->style->font->fontRes;

				/// Chinese
            //FrameTemp<UTF8> tmp( (awalk->textStart - awalk->textStart) * 3 + 1 );
            //StringBuffer tmpBuff = mTextBuffer.substring(awalk->textStart, awalk->textStart - awalk->textStart);
            //tmpBuff.get(tmp, (awalk->textStart - awalk->textStart) * 3 + 1 );
            //U32 bp = font->getBreakPos(tmp, tmpBuff.length(), localCoords.x - awalk->xStart, false);

				UTF16* tmp = mTextBuffer.getBuffer(awalk->textStart);
            U32 bp = font->getBreakPos(tmp, 1, localCoords.x - awalk->xStart, false);

            return awalk->textStart + bp;
         }
         return walk->textStart + walk->len;
      }
   }
   return mTextBuffer.length() - 1;
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::Font *GuiMLTextCtrl::allocFont(char *faceName, U32 faceNameLen, U32 size)
{
   // check if it's in the font list currently:
   for(Font *walk = mFontList; walk; walk = walk->next)
      if(faceNameLen == walk->faceNameLen &&
         !dStrncmp(walk->faceName, faceName, faceNameLen) &&
         size == walk->size)
         return walk;

   // Create!
   Font *ret;
   ret = constructInPlace((Font *) mResourceChunker.alloc(sizeof(Font)));
   ret->faceName = new char[faceNameLen+1];
   dStrncpy(ret->faceName, faceName, faceNameLen);
   ret->faceName[faceNameLen] = '\0';
   ret->faceNameLen = faceNameLen;
   ret->size = size;
   ret->next = mFontList;
   ret->fontRes = GFont::create(ret->faceName, size, GuiControlProfile::sFontCacheDirectory);
   if(bool(ret->fontRes))
   {
      ret->next = mFontList;
      mFontList = ret;
      return ret;
   }
   return NULL;
}

#ifdef TGE_RPG
GuiMLTextCtrl::Bitmap *GuiMLTextCtrl::allocIcon(char *iconName, U32 nameLen)
{
	STE sBmpName = StringTable->insertn(iconName,nameLen,true);
   for(Bitmap *walk = mBitmapList; walk; walk = walk->next)
      if(walk->bitmapName == sBmpName)
         return walk;

   Bitmap *ret = constructInPlace((Bitmap *) mResourceChunker.alloc(sizeof(Bitmap)));
   ret->bitmapName		= sBmpName;
	ret->bmpType			= BT_ICON;

	RPG::g_pGameIconMan->GetIconTexture(sBmpName,
										ret->bitmapHandle,
										ret->bmpRect);

   if(bool(ret->bitmapHandle))
   {
      ret->next = mBitmapList;
      mBitmapList = ret;
      return ret;
   }
   return NULL;
}
#endif

//--------------------------------------------------------------------------
GuiMLTextCtrl::Bitmap *GuiMLTextCtrl::allocBitmap(char *bitmapName, U32 bitmapNameLen)
{
#ifdef TGE_RPG
	STE sBmpName = StringTable->insertn(bitmapName,bitmapNameLen,true);
   for(Bitmap *walk = mBitmapList; walk; walk = walk->next)
      if(walk->bitmapName == sBmpName)
         return walk;

   Bitmap *ret = constructInPlace((Bitmap *) mResourceChunker.alloc(sizeof(Bitmap)));
   ret->bitmapName = sBmpName;

	ret->bmpType	 = BT_BMP;
   //char nameBuffer[256];
   //dStrncpy(nameBuffer, bitmapName, bitmapNameLen);
   //nameBuffer[bitmapNameLen] = 0;
   ret->bitmapHandle = TextureHandle(sBmpName, BitmapTexture);
   if(bool(ret->bitmapHandle))
   {
	ret->bmpRect.set(0,0,ret->bitmapHandle.getWidth(),ret->bitmapHandle.getHeight());
      ret->next = mBitmapList;
      mBitmapList = ret;
      return ret;
   }
   return NULL;

#else

   for(Bitmap *walk = mBitmapList; walk; walk = walk->next)
      if(bitmapNameLen == walk->bitmapNameLen &&
         !dStrncmp(walk->bitmapName, bitmapName, bitmapNameLen))
         return walk;

   Bitmap *ret = constructInPlace((Bitmap *) mResourceChunker.alloc(sizeof(Bitmap)));
   ret->bitmapName = bitmapName;
   ret->bitmapNameLen = bitmapNameLen;
   char nameBuffer[256];
   dStrncpy(nameBuffer, bitmapName, bitmapNameLen);
   nameBuffer[bitmapNameLen] = 0;
   ret->bitmapHandle = TextureHandle(nameBuffer, BitmapTexture);
   if(bool(ret->bitmapHandle))
   {
      ret->next = mBitmapList;
      mBitmapList = ret;
      return ret;
   }
   return NULL;
#endif
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::LineTag *GuiMLTextCtrl::allocLineTag(U32 id)
{
   for ( LineTag* walk = mTagList; walk; walk = walk->next )
   {
      if ( walk->id == id )
      {
         Con::warnf( ConsoleLogEntry::General, "GuiMLTextCtrl - can't add duplicate line tags!" );
         return( NULL );
      }
   }
   LineTag* newTag = (LineTag*) mViewChunker.alloc( sizeof( LineTag ) );
   newTag->id = id;
   newTag->y = mCurY;
   newTag->next = mTagList;
   mTagList = newTag;

   return( newTag );
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::emitNewLine(U32 textStart)
{
   //clear any clipping
   mCurClipX = 0;

   Line *l = (Line *) mViewChunker.alloc(sizeof(Line));
#ifdef TGE_RPG
	l->height = m_nLineHeightMin  > 0 ? 
						getMax(m_nLineHeightMin,(S32)mCurStyle->font->fontRes->getHeight()) 
						: mCurStyle->font->fontRes->getHeight();
#else
   l->height = mCurStyle->font->fontRes->getHeight();
#endif
   l->y = mCurY;
   l->textStart = mLineStart;
   l->len = textStart - l->textStart;
   mLineStart = textStart;
   l->atomList = mLineAtoms;
   l->next = 0;
   l->divStyle = mCurDiv;
   *mLineInsert = l;
   mLineInsert = &(l->next);
   mCurX = mCurLMargin;
   mCurTabStop = 0;

   if(mLineAtoms)
   {
      // scan through the atoms in the line, get the largest height
      U32 maxBaseLine = 0;
      U32 maxDescent = 0;
      Atom* walk;

      for(walk = mLineAtoms; walk; walk = walk->next)
      {
         if(walk->baseLine > maxBaseLine)
            maxBaseLine = walk->baseLine;
         if(walk->descent > maxDescent)
            maxDescent = walk->descent;
         if(!walk->next)
         {
            l->len = walk->textStart + walk->len - l->textStart;
            mLineStart = walk->textStart + walk->len;
         }
      }
      l->height = maxBaseLine + maxDescent;
#ifdef TGE_RPG
		l->height = m_nLineHeightMin  > 0 ? getMax(m_nLineHeightMin,(S32)l->height) : l->height;
#endif
      for(walk = mLineAtoms; walk; walk = walk->next)
         walk->yStart = mCurY + maxBaseLine - walk->baseLine;
   }
   mCurY += l->height;
   mLineAtoms = NULL;
   mLineAtomPtr = &mLineAtoms;

   // clear out the blocker list
   BitmapRef **blockList = &mBlockList;
   while(*blockList)
   {
      BitmapRef *blk = *blockList;
      if(blk->point.y + blk->extent.y <= mCurY)
         *blockList = blk->nextBlocker;
      else
         blockList = &(blk->nextBlocker);
   }
   if(mCurY > mMaxY)
      mMaxY = mCurY;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::emitBitmapToken(GuiMLTextCtrl::Bitmap *bmp, U32 textStart, bool bitmapBreak)
{
   if(mCurRMargin <= mCurLMargin)
      return;
#ifdef TGE_RPG
   if(mCurRMargin - mCurLMargin < bmp->bmpRect.extent.x)
      return;
#else
   if(mCurRMargin - mCurLMargin < bmp->bitmapHandle.getWidth())
      return;
#endif

   BitmapRef *ref = (BitmapRef *) mViewChunker.alloc(sizeof(BitmapRef));
   ref->bitmap = bmp;
   ref->next = mBitmapRefList;
   mBitmapRefList = ref;

   // now we gotta insert it into the blocker list and figure out where it's spos to go...
#ifdef TGE_RPG
   ref->extent = bmp->bmpRect.extent;
#else
   ref->extent.x = bmp->bitmapHandle.getWidth();
   ref->extent.y = bmp->bitmapHandle.getHeight();
#endif

   // find the first space in the blocker list that will fit this thats > curLMargin

   while(bitmapBreak && mBlockList != &mSentinel)
      emitNewLine(textStart);

   for(;;)
   {
      // loop til we find a line that fits...
      // we'll have to emitLine repeatedly to clear out the block lists...

      BitmapRef **walk = &mBlockList;
      U32 minx = mCurX;
      U32 maxx = mCurRMargin;

      while(*walk)
      {
         BitmapRef *blk = *walk;

         if(blk->point.x > minx)
         {
            U32 right = maxx;
            if(blk->point.x < right)
               right = blk->point.x;
            U32 width = right - minx;

            if(right > minx && width >= ref->extent.x) // we've found the spot...
            {
               // insert it:
               U32 x = minx;
               if(mCurJustify == CenterJustify)
                  x += (width - ref->extent.x) >> 1;
               else if(mCurJustify == RightJustify)
                  x += width - ref->extent.x;
               ref->point.x = x;
               ref->point.y = mCurY;
               ref->nextBlocker = blk;
               *walk = ref;
               if(ref->point.y + ref->extent.y > mMaxY)
                  mMaxY = ref->point.y + ref->extent.y;

               return;
            }
         }
         if(minx < blk->point.x + blk->extent.x)
            minx = blk->point.x + blk->extent.x;
         // move on to the next blocker...
         walk = &(blk->nextBlocker);
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -