A class to help create and modify text element in microstation develop

In microstation , how to write code to modify a text kind(tag,text node) element always be a nightmare to me.

For example, when you want to add some interfaces to modify text style separately, like "SetFont" ,"SetTextHeight".....

, you must write a lot code for each interface to accomplished . The question is the codes for those interface are almost same, but why we need to write them again and again , and when there is something going wrong in the code , we need to fix them one by one.


For conquer this problem I write a class to help us to write only 2 or 3 lines to modify a text kind element.

This would be easy and quick to learn and maintenance.

My code has been proved it can work well , and I m happy to share it with you.

If you have any question or any suggestion , you can contact me with the email address bellow.

 

My email address : bullseye.wang@bentley.com

calling example :

void __stdcall SetTxtFontDll(ulong typeface, ulong bold, ulong italic,
char *strHandle, DgnModelRefP pActiveDgnFile)
{
TextModifyHelper oModifyText(strHandle,pActiveDgnFile);
oModifyText.SetTextBold (&bold);
oModifyText.SetTextItalic (&italic);
oModifyText.SetTextFont(&typeface);
oModifyText.ApplyChanges();
}

 

void __stdcall SetTxtHeightDll(double height, char * handle, DgnModelRefP pActiveDgnFile)
{
TextModifyHelper oModifyText(handle,pActiveDgnFile);
oModifyText.SetTextHeight(&height);
oModifyText.ApplyChanges();
}

I don't know how to insert a attachment , so I pasted my codes bellow.

pre-define "XM" means XM or higher version micorstation

"TextHelper.h"

#pragma once
#include "api.h"
#ifdef _DEBUG
BOOL g_bMemview = FALSE;
#endif
//text element helper
typedef struct OverrideModifier
{
UInt32 ModifySizeParam:1;
UInt32 ModifyTextParamWide:1;
UInt32 ModifyValue:1;
UInt32 reserved:29;
}Modifier;
typedef struct IgonalStruct
{
UInt32 IgonalValue:1;
UInt32 IgonalOrg:1;
UInt32 reserved:30; /* reserved for future use */
}Igonaler;
class MStuff
{
#define DECLARE_SAVE_VARIABLE(type,var) \
protected: \
type* p##var; \
public: \
void Set##var(type* var ) { p##var = var; m_bModified = TRUE;} \
type* Get##var(){return p##var; }
public:
int m_nType;
MStuff(int nType,DgnModelRefP pModelRef,char* style,char* value,double* height,
double* widthfactor,double* slantangle,
ulong* font,ulong* bold,ulong* italic,ulong* color,
ulong* just,ulong* underline,MSElementDescr*Template):m_nType(nType),
m_bIsTag(nType == ATTRIBUTE_ELM),m_bIsTextNode(nType == TEXT_NODE_ELM),m_pModelRef(pModelRef),
pstyle(style),pvalue(value),pheight(height),
pwidthfactor(widthfactor),pslantangle(slantangle),
pfont(font),pbold(bold),pitalic(italic),pcolor(color),
pjust(just),punderline(underline),pTemplate(Template),
wString(NULL),
pTxtSizeParam(NULL),pTxtParamWide(NULL),pTagValue(NULL)

{
init();
}
MStuff(MStuff& mf):m_nType(mf.m_nType),
m_bIsTag(mf.m_bIsTag),m_bIsTextNode(mf.m_bIsTextNode),m_pModelRef(mf.m_pModelRef),
pstyle(mf.pstyle),pvalue(mf.pvalue),pheight(mf.pheight),
pwidthfactor(mf.pwidthfactor),pslantangle(mf.pslantangle),
pfont(mf.pfont),pbold(mf.pbold),pitalic(mf.pitalic),pcolor(mf.pcolor),
pjust(mf.pjust),punderline(mf.punderline),pTemplate(mf.pTemplate),
wString(NULL),
pTxtSizeParam(NULL),pTxtParamWide(NULL),pTagValue(NULL)
{
init();
}
~MStuff()
{
if(pTxtSizeParam != NULL)
{
delete pTxtSizeParam;
}
if(pTxtParamWide != NULL)
{
delete pTxtParamWide;
}
if(wString != NULL)
{
delete [] wString;
}
if(pTagValue!=NULL)
{
mdlTag_freeValue (pTagValue);
delete pTagValue;
}
}

 

public:
void SetLineSpacing()
{
#ifdef ATH
if(this->pTxtParamWide->exFlags.acadLineSpacingType==2)
this->pTxtParamWide->lineSpacing = pTxtSizeParam->size.height * 1.4;//0.056;
else
this->pTxtParamWide->lineSpacing = pTxtSizeParam->size.height * 0.056;
#else
switch(this->pTxtParamWide->exFlags.acadLineSpacingType)
{
case 2:
this->pTxtParamWide->lineSpacing = pTxtSizeParam->size.height * 1.4;//0.056;
break;
case 0:
this->pTxtParamWide->lineSpacing = pTxtSizeParam->size.height * 0.4;//0.056;
break;
default:
this->pTxtParamWide->lineSpacing = pTxtSizeParam->size.height * 0.056;
}
#endif
}
void RetSet()
{
if(m_bModified)
init();
}
inline void init()
{
UnitInfo ui;
mdlModelRef_getMasterUnit(m_pModelRef,&ui);
mdlModelRef_getSubUnit(m_pModelRef,&ui);

uor = mdlModelRef_getUorPerMaster(m_pModelRef);
if(pTxtSizeParam == NULL)
{
pTxtSizeParam = new TextSizeParam();
memset(pTxtSizeParam,0,sizeof(TextSizeParam));
}
if(pTxtParamWide == NULL)
{
pTxtParamWide = new TextParamWide();
memset(pTxtParamWide,0,sizeof(TextParamWide));
}
if(pTemplate)
ExtractWideTemplate();

if(pwidthfactor || pheight)
mfer.ModifySizeParam = 1;
else
mfer.ModifySizeParam = 0;

pjust || pbold || pcolor || pfont || pitalic || pslantangle || punderline ?
mfer.ModifyTextParamWide = 1:mfer.ModifyTextParamWide = 0;

pvalue ? mfer.ModifyValue = 1:mfer.ModifyValue = 0;

if(mfer.ModifyValue)
{
if(m_bIsTag)
{
if(pTagValue == NULL)
pTagValue = new TagValue();
}
else
{
if(wString == NULL)
wString = new MSWideChar[MAX_TEXT_LENGTH];
}
}

m_bModified = FALSE;
}

public:
BOOL IsNeedModify()
{
if(pTxtSizeParam==NULL && pTxtParamWide== NULL && wString == NULL && pTagValue == NULL)
return FALSE;
else
return TRUE;
}

void ApplyModify()
{
ApplyStyle();
ApplySize();
ApplyParamWide();
ApplyValue();

}
void Setstyle()
{
if(pTxtParamWide == NULL)
{
pTxtParamWide = new TextParamWide();
memset(pTxtParamWide,0,sizeof(TextParamWide));
}
if(pTxtSizeParam == NULL)
{
pTxtSizeParam = new TextSizeParam();
memset(pTxtSizeParam,0,sizeof(TextSizeParam));
}
short lineLength;
mdlTextStyle_getTextParamWideFromTCB (pTxtParamWide, &pTxtSizeParam->size.width, &pTxtSizeParam->size.height, &lineLength, m_bIsTextNode);
if(m_bIsTextNode)
SetLineSpacing();
}
static int GetType(MSElement const* el)
{
return mdlElement_getType(el);
}
static int GetType(MSElementDescr const* pDscr)
{
return mdlElement_getType(&(pDscr->el));
}
void ExtractWide(MSElementDescr* pDescr,MStuff* pMF,BOOL bGetValue = FALSE)
{
ASSERT(pDescr!=NULL);
int nType = mdlElement_getType(&pDescr->el);
switch(nType)
{
case ATTRIBUTE_ELM:
{
if(pTagValue == NULL)
pTagValue = new TagValue();
mdlTag_extract(NULL, &pMF->userOrigin, NULL, NULL,pMF->pTagValue,NULL,NULL, pMF->pTxtSizeParam, &pMF->rotMatrix,
pMF->pTxtParamWide , &pDescr->el, pDescr->h.dgnModelRef );
}
break;
case TEXT_ELM:
{
if(wString == NULL)
wString = new MSWideChar[1025];
mdlText_extractWide(pMF->wString,NULL,&pMF->userOrigin,&pMF->rotMatrix,pMF->pTxtSizeParam,pMF->pTxtParamWide,NULL,&pDescr->el);
}
break;
case TEXT_NODE_ELM:
{
mdlTextNode_extractWide(&pMF->userOrigin, &pMF->rotMatrix , pMF->pTxtSizeParam,pMF->pTxtParamWide,&pDescr->el, NULL);

}
break;
}
if(m_bIsTextNode)
SetLineSpacing();
}
protected:
inline void ExtractWideTemplate()
{
ExtractWide(pTemplate,this);
}

inline void ApplyValue()
{

if(!mfer.ModifyValue)
{
if(pTemplate!=NULL && !m_bIsTextNode)
{
if(!m_bIsTag && pTagValue!=NULL && pTagValue->type == MS_TAGTYPE_CHAR )
//this situation is a tag template and a text dest
{
int nLen = strlen(pTagValue->val.stringVal);
MSWideChar* pTmpString = new MSWideChar[nLen+1];
mdlCnv_convertMultibyteToUnicode(pTagValue->val.stringVal, -1,(MSWChar*) pTmpString, nLen+1);
if(wString)
{
delete[] wString;
wString = pTmpString;
}
else
{
wString = pTmpString;
}
mfer.ModifyValue = TRUE;
}
}
return;
}

if(m_bIsTag)
{
int nLen = strlen(pvalue);
if(pTagValue->type == MS_TAGTYPE_CHAR ||
(strcmp(pvalue,pTagValue->val.stringVal)==0))
{
mdlTag_freeValue (pTagValue);
delete pTagValue;
pTagValue = NULL;
}
else
{
mdlTag_freeValue (pTagValue);
delete pTagValue;
pTagValue = NULL;
pTagValue = new TagValue();
pTagValue->type = MS_TAGTYPE_CHAR;
pTagValue->val.stringVal = (char*)dlmSystem_mdlMalloc (nLen+1);
strcpy(pTagValue->val.stringVal,pvalue);
}
}
else
{
int nLen = strlen(pvalue);
MSWideChar* pTmpString = new MSWideChar[nLen+1];
mdlCnv_convertMultibyteToUnicode(pvalue, -1,(MSWChar*) pTmpString, nLen+1);
if(wcscmp((const wchar_t*)pTmpString,(const wchar_t*)wString)==0)
{
delete [] pTmpString;
delete [] wString;
wString = NULL;
}
else
{
delete[] wString;
wString = pTmpString;
}
}
}
inline void ApplyStyle()
{
if(pstyle!=NULL)
{
MdlTextStyle *pTextStyle = NULL;
ulong styleID = 0;
DgnModelRefP *ppModelRef;

MSWChar msStyleName[512];
mdlCnv_convertMultibyteToUnicode(pstyle, -1, msStyleName, 511);

if( SUCCESS != mdlTextStyle_getByName(&pTextStyle, &styleID, msStyleName, m_pModelRef, TRUE))
{
if(pTextStyle!=NULL)
mdlTextStyle_free (pTextStyle);
return;
}

//for a single text or a textnode element
if( SUCCESS != mdlTextStyle_getTextParamWideFromStyle(this->pTxtParamWide,
&(this->pTxtSizeParam->size.width), &(this->pTxtSizeParam->size.height), NULL, styleID, m_pModelRef,
m_bIsTextNode) )
{
if(pTextStyle!=NULL)
mdlTextStyle_free (pTextStyle);
return;
}
mdlTextStyle_free(pTextStyle);
}
}
inline void ApplyParamWide()
{

if(!mfer.ModifyTextParamWide)
return;
BOOL bIgonal = TRUE;

//NOTE: sequence of codes bellow two segments in this function should not change!
if(pitalic!=NULL)
{
if(pTxtParamWide->flags.slant != *pitalic)
{
bIgonal = FALSE;
pTxtParamWide->flags.slant = *pitalic;
if(*pitalic)
{
pTxtParamWide->slant = 0.523;
}
else
pTxtParamWide->slant = 0;
}
}
if(pslantangle!=NULL)
{
if(pTxtParamWide->slant != *pslantangle)
{
bIgonal = FALSE;
pTxtParamWide->slant = *pslantangle;
if(abs(pTxtParamWide->slant)>cZero)
pTxtParamWide->flags.slant = 1;
}
}
if(pfont!=NULL)
{
if(pTxtParamWide->font != *pfont)
{
bIgonal = FALSE;
pTxtParamWide->font = *pfont;
}
}
if(pbold!=NULL)
{
if(pTxtParamWide->exFlags.bold != *pbold)
{
bIgonal = FALSE;
pTxtParamWide->exFlags.bold = *pbold;
}
}

if(pcolor!=NULL)
{
if(pTxtParamWide->color != *pcolor)
{
bIgonal = FALSE;
pTxtParamWide->color = *pcolor;
}
}
if(pjust!=NULL)
{
if(pTxtParamWide->just != *pjust)
{
bIgonal = FALSE;
pTxtParamWide->just = *pjust;
}
}

if(punderline!=NULL)
{
if(pTxtParamWide->flags.underline != *punderline)
{
bIgonal = FALSE;
pTxtParamWide->flags.underline = *punderline;
}
}
//if(bIgonal)
//{
//delete pTxtParamWide;
//pTxtParamWide = NULL;
//}
}
inline void ApplySize()
{
//NOTE: sequence of codes bellow in this function should not change!
if(!mfer.ModifySizeParam)
return;

BOOL bIgonal = TRUE;
double fwidthfactor = 1;
double height = pTxtSizeParam->size.height;
if(pheight!=NULL)
{
ASSERT(pTxtSizeParam!=NULL);
fwidthfactor = pTxtSizeParam->size.width/pTxtSizeParam->size.height;
if(abs(pTxtSizeParam->size.height - (*pheight*uor))>cZero )
{
height = *pheight*uor;
bIgonal = FALSE;

}
}

double widthfactor = pTxtSizeParam->size.width / pTxtSizeParam->size.height;

if(pwidthfactor!=NULL)
{
ASSERT(pTxtSizeParam!=NULL);
widthfactor = *pwidthfactor;
if(!abs(pTxtSizeParam->size.width - (pTxtSizeParam->size.height * widthfactor)) {
bIgonal = FALSE;
}
}
if(!bIgonal)
//{
//delete pTxtSizeParam;
//pTxtSizeParam = NULL;
//}
//else
{
memset(pTxtSizeParam,0,sizeof(TextSizeParam));
pTxtSizeParam->mode = TXT_BY_TILE_SIZE;
pTxtSizeParam->size.height = height;
pTxtSizeParam->size.width = pTxtSizeParam->size.height*widthfactor;
if(this->pTxtParamWide!=NULL)
SetLineSpacing();
}
}
public:
DgnModelRefP m_pModelRef;
protected:
double uor;

DECLARE_SAVE_VARIABLE(char,style);
DECLARE_SAVE_VARIABLE(char,value);
DECLARE_SAVE_VARIABLE(double,height);
DECLARE_SAVE_VARIABLE(double,widthfactor);
DECLARE_SAVE_VARIABLE(double,slantangle);
DECLARE_SAVE_VARIABLE(ulong,font);
DECLARE_SAVE_VARIABLE(ulong,bold);
DECLARE_SAVE_VARIABLE(ulong,italic);
DECLARE_SAVE_VARIABLE(ulong,color);
DECLARE_SAVE_VARIABLE(ulong,just);
DECLARE_SAVE_VARIABLE(ulong,underline);
DECLARE_SAVE_VARIABLE(MSElementDescr,Template);
BOOL m_bIsTag;
BOOL m_bIsTextNode;
BOOL m_bModified;
Modifier mfer;
public:
DPoint3d userOrigin;
RotMatrix rotMatrix;
TextSizeParam* pTxtSizeParam;
TextParamWide* pTxtParamWide;
MSWideChar* wString;
TagValue* pTagValue;
BOOL bReWrite;
};
enum TextHelperClasses
{
clsText = 0,
clsTextBaseHelper = 1,
clsTextHelper = 2,
clsTagHelper = 3,
clsTextNodeHelper = 4,
clsTextModifyHelper = 5
};
class Text
{
public:
BOOL m_bGetByReference;
ulong m_type;
MStuff* m_pMF;
MSElementDescr* m_pDescr;
DgnModelRefP m_pModelRef;
Text():m_pMF(NULL),m_pDescr(NULL),m_pModelRef(NULL),m_bGetByReference(FALSE){}
virtual ~Text()
{
if(!m_bGetByReference && m_pDescr!=NULL)
{
mdlElmdscr_freeAll(&m_pDescr);
m_pDescr = NULL;
}
if(m_pMF != NULL)
{
delete m_pMF;
m_pMF = NULL;
}
}
protected:
virtual inline void InitMF()
{
if(m_pMF==NULL)
{
m_pMF = new MStuff(m_type,m_pModelRef,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
}
public:
inline MSElementDescr* getDSCR() const
{
return m_pDescr;
}
inline ElementID GetID() const
{
ASSERT(m_pDescr!=NULL);
if(m_pDescr!=NULL)
return m_pDescr->el.ehdr.uniqueId;
else
return 0;
}
virtual void SetMF(MStuff &mf)
{
if(m_pMF!=NULL);
{
delete m_pMF;
}
m_pMF = new MStuff(mf);

m_pMF->m_bIsTextNode = (m_type==TEXT_NODE_ELM);
m_pMF->m_bIsTag = (m_type==ATTRIBUTE_ELM);
}
inline void CatchDSCR(MSElementDescr* pDescr)
{
ASSERT(m_pDescr==NULL);
ASSERT(pDescr!=NULL);
m_pDescr = pDescr;
m_pModelRef = pDescr->h.dgnModelRef;
m_bGetByReference = TRUE;
}
inline void CatchDSCR(ElementId eID)
{
ASSERT(m_pDescr==NULL);
GetElementDscrByHandle(eID,&m_pDescr,m_pModelRef);
m_bGetByReference = FALSE;
}

inline void CatchDSCR(const char* strHandle)
{
ASSERT(m_pDescr==NULL);
ElementId eID = _atoi64(strHandle);
CatchDSCR(eID);
}


virtual inline TextHelperClasses GetClass() = 0;

inline BOOL IsTag()
{
return m_type == ATTRIBUTE_ELM;
}
inline void SetTextValue(char* pValue)
{
m_pMF->Setvalue(pValue);
}
inline void SetTextTemplate(MSElementDescr* pTemplate)
{
ASSERT(mdlElement_getType(&pTemplate->el) == ATTRIBUTE_ELM || mdlElement_getType(&pTemplate->el) == TEXT_ELM);
m_pMF->SetTemplate(pTemplate);
}
inline void SetTextHeight(double* pHeight)
{
m_pMF->Setheight(pHeight);
}
inline void SetTextWidthFactor(double* pWidthFactor)
{
m_pMF->Setwidthfactor(pWidthFactor);
}
inline void SetTextSlant(double* pSlant)
{
m_pMF->Setslantangle(pSlant);
}
inline void SetTextBold(ulong* pBold)
{
m_pMF->Setbold(pBold);
}
inline void SetTextItalic(ulong* pItalic)
{
m_pMF->Setitalic(pItalic);
}

inline void SetTextFont(ulong* pfont)
{
m_pMF->Setfont(pfont);
}
inline void SetTextStyle(char *strStyleName)
{
m_pMF->Setstyle(strStyleName);
}
inline void SetTextStyle()
{
m_pMF->Setstyle();
}
inline void SetTextJust(ulong* just)
{
m_pMF->Setjust(just);
}
inline void SetTextUnderline(ulong* underline)
{
m_pMF->Setunderline(underline);
}
};


class TextModifyHelper;
class TextBaseHelper:public Text
{
protected:
BOOL m_bNewCreated;
BOOL m_bUseTCB;

public:
virtual inline TextHelperClasses GetClass() = 0;

TextBaseHelper(DgnModelRefP pModelRef,int nType):m_bNewCreated(FALSE)
{
m_pDescr = NULL;
m_pModelRef =pModelRef;
m_type = nType;
InitMF();
}

public:
ulong Add()
{
return Add(m_pDescr,m_pModelRef);
}
static ulong Add(MSElementDescr* pDescr,DgnModelRefP pModelRef)
{
ASSERT(pDescr!=NULL);
if(pDescr!=NULL)
{
return mdlElmdscr_addByModelRef( pDescr,pModelRef);
}
return 0;
}

virtual BOOL Create(DPoint3d* ptOrg,RotMatrix* rotMatrix,char* strValue,BOOL bUseTCB)
{
ASSERT(m_pDescr==NULL);

m_bGetByReference = FALSE;
m_bUseTCB = bUseTCB;
m_bNewCreated = TRUE;
SetMFValue(strValue);
m_pMF->RetSet();//after all member variable set //before output things changes

//when we create a textnode element , we must use text node template to create.
BOOL bTextNodeWrongTemplate = FALSE;
if(m_pMF->GetTemplate()!=NULL)
bTextNodeWrongTemplate = (m_type == TEXT_NODE_ELM && m_type !=(m_pMF->GetType(&(m_pMF->GetTemplate()->el))));
if(bTextNodeWrongTemplate)
{
m_bUseTCB = TRUE;
}

if(m_pMF->GetTemplate()==NULL || bTextNodeWrongTemplate)
{
if(ptOrg!=NULL)
memcpy(&m_pMF->userOrigin,ptOrg,sizeof(DPoint3d));
if(rotMatrix!=NULL)
{
memcpy(&m_pMF->rotMatrix,rotMatrix,sizeof(RotMatrix));
}
else
{
memset(&m_pMF->rotMatrix,0,sizeof(RotMatrix));
m_pMF->rotMatrix.form3d[0][0] = 1;
m_pMF->rotMatrix.form3d[1][1] = 1;
m_pMF->rotMatrix.form3d[2][2] = 1;
}

if(bUseTCB)
{
SetTextStyle(NULL);
SetTextStyle();
}

}

m_pMF->ApplyModify();
return TRUE;

}

protected:

virtual void SetMFValue(char* strValue) = 0;
virtual inline BOOL Create() = 0;
};
class TextHelper:public TextBaseHelper
{
public:
TextHelper(DgnModelRefP pModelRef):TextBaseHelper(pModelRef,TEXT_ELM)
{

}
public:

virtual inline TextHelperClasses GetClass()
{
return clsTextHelper;
}

virtual BOOL Create(DPoint3d* ptOrg,RotMatrix* rotMatrx,char* strValue,BOOL bUseTCB)
{
TextBaseHelper::Create(ptOrg,rotMatrx,strValue,bUseTCB);
return Create();
}
static inline BOOL Create(MSElementDescr** pDescr,MStuff &mf)
{
ASSERT(*pDescr==NULL);
MSElement eleNew;

int nSuc = 0;
if(mf.GetTemplate()!=NULL)
nSuc = mdlText_createWide( &eleNew,&mf.GetTemplate()->el ,mf.wString,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide, NULL);
else
nSuc = mdlText_createWide( &eleNew,NULL,mf.wString,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide, NULL);
if(nSuc!= SUCCESS)
return FALSE;

nSuc = mdlElmdscr_new(pDescr,NULL,&eleNew);

if(nSuc!= SUCCESS)
return FALSE;
else
return TRUE;

//if(mdlWorkDgn_write(*pDescr,-1,mf.m_pModelRef)==0)
// return FALSE;
//return TRUE;


}

protected:

virtual void SetMFValue(char* strValue)
{
m_pMF->Setvalue(strValue);

}
virtual inline BOOL Create()
{
return Create(&m_pDescr,*m_pMF);
}

};
class TextNodeHelper:public TextBaseHelper
{
private:
char* m_pValue;


public:
TextNodeHelper(DgnModelRefP pModelRef):TextBaseHelper(pModelRef,TEXT_NODE_ELM),m_pValue(NULL)
{

}

public:
virtual BOOL Create(DPoint3d* ptOrg,RotMatrix* rotMatrx,char* strValue,BOOL bUseTCB)
{

TextBaseHelper::Create(ptOrg,rotMatrx,strValue,bUseTCB);
return Create();
}

virtual inline TextHelperClasses GetClass()
{
return clsTextNodeHelper;
}

static inline BOOL Create(MSElementDescr** pDescr,MStuff &mf)
{
ASSERT(*pDescr==NULL);
#if ATH
if(mdlTextNode_createEx(pDescr,NULL,NULL,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide)==SUCCESS)
return TRUE;
else
return FALSE;
#else
MSElement element;
if(mdlTextNode_createWide(&element,NULL,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide)==SUCCESS)
{
mdlElmdscr_new (pDescr ,NULL,&element);
return TRUE;
}
else
return FALSE;
#endif

}
BOOL AddTextLine(char* pValue)
{
ASSERT(m_pDescr!=NULL);
if(m_bNewCreated)
{
return AddTextLine(pValue,&m_pDescr,*m_pMF,m_bUseTCB);
}
else
{
if(m_pDescr->h.firstElem!=NULL)
{
MStuff mf(*m_pMF);
mf.m_bIsTag = FALSE;
mf.m_bIsTextNode = FALSE;
mf.ExtractWide(m_pDescr->h.firstElem,&mf);
return AddTextLine(pValue,&m_pDescr,mf,FALSE);
}
else
{
return AddTextLine(pValue,&m_pDescr,*m_pMF,m_bUseTCB);
}
}
}

static BOOL AddTextLine(char* pValue,MSElementDescr** pDescr,MStuff &mf,BOOL bUseTCB)
{
ASSERT(*pDescr!=NULL);
BOOL bRet = TRUE;
TextHelper* pTextHelper = new TextHelper((*pDescr)->h.dgnModelRef);
pTextHelper->SetMF(mf);

DPoint3d ptOrg={0,0,0};
bRet = pTextHelper->Create(&ptOrg,&mf.rotMatrix,pValue,bUseTCB);

if(bRet)
bRet = (SUCCESS == mdlTextNode_createEx(pDescr,NULL ,pTextHelper->getDSCR(),&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide));
if(pTextHelper!=NULL)
delete pTextHelper;

return bRet;
}

protected:

///set value for text or textnode
virtual void SetMFValue(char* strValue)
{
m_pValue = (char*)strValue;
m_pMF->Setvalue(NULL);
}
virtual inline BOOL Create()
{
BOOL bRet = Create(&m_pDescr,*m_pMF);
if(bRet && m_pValue!=NULL)
{
ulong nPos = AddTextLine(m_pValue);
if(nPos<=0)
{
return FALSE;
}
}
return bRet;
}

};

//class TagHelper:public TextBaseHelper
//{
//public:
// ElementID m_nTargetID;
//public:
// TagHelper(DgnModelRefP pModelRef,ElementID nTargetID):TextBaseHelper(pModelRef,ATTRIBUTE_ELM),m_nTargetID(nTargetID)
// {
// ASSERT(m_nTargetID != 0);
// }
// TagHelper(DgnModelRefP pModelRef,char* strHandle):TextBaseHelper(pModelRef,ATTRIBUTE_ELM)
// {
// m_nTargetID = _atoi64(arrStr[i]);
// ASSERT(m_nTargetID != 0);
// }
//public:
//
// virtual inline TagtHelperClasses GetClass()
// {
// return clsTagHelper;
// }
//
// virtual BOOL Create(DPoint3d* ptOrg,RotMatrix* rotMatrx,char* strValue,BOOL bUseTCB)
// {
// TextBaseHelper::Create(ptOrg,rotMatrx,strValue,bUseTCB);
// return Create();
// }
// static inline BOOL Create(MSElementDescr** pDescr,MStuff &mf)
// {
// ASSERT(*pDescr==NULL);
// MSElement eleNew;
// TagSpec tagSpec;
// tagSpec.tagName
// int nSuc = mdlTag_createWide( &eleNew,mf.pTemplate,mf.wString,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide, NULL);
// if(nSuc!= SUCCESS)
// return FALSE;
// MSElement* pElmIn ,
//TagSpec* tagSpec ,
//UShort* tagProps ,
//TagValue* value ,
//ElementID* targetID ,
//DPoint3d* dPoint ,
//TextSizeParam* txSizeWd ,
//RotMatrix* rMatrix ,
//TextParamWide* txtParams ,
//MSWChar* styleName
//
//
// nSuc = mdlElmdscr_new(pDescr,NULL,&eleNew);
//
// if(nSuc!= SUCCESS)
// return FALSE;
// else
// return TRUE;
//
// //if(mdlWorkDgn_write(*pDescr,-1,mf.m_pModelRef)==0)
// // return FALSE;
// //return TRUE;
//
//
// }
//
//protected:
//
// virtual void SetMFValue(char* strValue)
// {
// m_pMF->Setvalue(strValue);
//
// }
// virtual inline BOOL Create()
// {
// return Create(&m_pDescr,*m_pMF);
// }
//
//};
class TextModifyHelper:public Text
{

//inner struct declare
protected:
//variables delcare

//check whether the class variable m_pDescr come from a reference
protected:

inline void init()
{
if(m_pMF!=NULL)
{
delete m_pMF;
m_pMF = NULL;
}
m_type = mdlElement_getType(&m_pDescr->el);
InitMF();
}
public:

TextModifyHelper(MSElementDescr* pDescr):Text()
{
CatchDSCR(pDescr);
init();
}
TextModifyHelper(char* strHandle,DgnModelRefP pModelRef):Text()
{
m_pModelRef = pModelRef;
CatchDSCR(strHandle);
init();
}
TextModifyHelper(ElementID eID,DgnModelRefP pModelRef):Text()
{
m_pModelRef = pModelRef;
CatchDSCR(eID);
init();
}
virtual inline TextHelperClasses GetClass()
{
return clsTextModifyHelper;
}

void SetIgonalInChanges(int* igonal)
{
if(igonal == 0)
return;
Igonaler* ig = (Igonaler*)igonal;

m_pMF->RetSet();


if(ig->IgonalValue)
{
if(m_pMF->wString!=NULL)
{
delete [] m_pMF->wString;
m_pMF->wString = NULL;
}
if(m_pMF->pTagValue!=NULL)
{
delete m_pMF->pTagValue;
m_pMF->pTagValue = NULL;
}
}
if(ig->IgonalOrg)//need to extract from m_pDescr //until there are more vaiable should be set , this judgement show its function
{
ASSERT(m_pDescr!=NULL);
MStuff mf(m_type,m_pModelRef,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,m_pDescr);
if(ig->IgonalOrg)
{
memcpy(&(m_pMF->userOrigin),&(mf.userOrigin),sizeof(mf.userOrigin));
}
}

}
void ApplyChanges()
{
m_pMF->RetSet();
ElementID eID = m_pDescr->el.ehdr.uniqueId;
switch(m_type)
{
case ATTRIBUTE_ELM:
ModifyTag(*m_pMF,m_pDescr);
break;
case TEXT_ELM:
ModifyText(*m_pMF,m_pDescr);
break;
case TEXT_NODE_ELM:
ModifyTextNode(*m_pMF,m_pDescr);
break;
}
mdlElmdscr_freeAll(&m_pDescr);
m_pDescr = NULL;
CatchDSCR(eID);
init();
}
protected:
inline void ModifyTag(MStuff& mf,MSElementDescr* pDescr)
{
ASSERT(pDescr!=NULL);
MSElement newElm;

TagValue tagValue;
ulong lfilePos = mdlElmdscr_getFilePos(pDescr);
if(!mf.GetTemplate())
{
if( SUCCESS != mdlTag_extract(NULL, NULL, NULL, NULL,mf.pTagValue,NULL,
NULL, mf.pTxtSizeParam, NULL, mf.pTxtParamWide , &pDescr->el, pDescr->h.dgnModelRef ))
return;
}
mf.ApplyModify();
if(mf.IsNeedModify())
{
mdlElement_display(&pDescr->el, ERASE);
if( SUCCESS != mdlTag_create(&newElm, &pDescr->el,NULL, NULL, mf.pTagValue,
NULL, NULL, mf.pTxtSizeParam , NULL, mf.pTxtParamWide, NULL) )
{
mdlElement_display(&pDescr->el, NORMALDRAW);
return ;
}
mdlElement_rewrite(&newElm, &pDescr->el, lfilePos);
mdlElement_display(&newElm, NORMALDRAW);
}

}
inline void ModifyText(MStuff& mf,MSElementDescr* pDescr,BOOL bReplace = FALSE)
{
ASSERT(pDescr!=NULL);
MSElement newElm;
DPoint3d origin;

if(!mf.GetTemplate())
{
if( SUCCESS != mdlText_extractWide(mf.wString, &origin,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide,NULL,&pDescr->el))
return;
}
mf.ApplyModify();
if(mf.IsNeedModify())
{
mdlElement_display(&pDescr->el, ERASE);

if( SUCCESS != mdlText_createWide(&newElm, &pDescr->el, mf.wString,&mf.userOrigin, &mf.rotMatrix,mf.pTxtSizeParam ,mf.pTxtParamWide,NULL))
{
mdlElement_display(&pDescr->el, NORMALDRAW);
return;
}

if(bReplace)
mdlElmdscr_replaceElement(&pDescr, &newElm);
else
mdlElement_rewrite(&newElm, &pDescr->el, mdlElmdscr_getFilePos(pDescr));
mdlElement_display(&newElm, NORMALDRAW);

}

}

inline void ModifyTextNode(MStuff& mf,MSElementDescr* pDescr)//not add value modify to mulitline text yet.
{
ASSERT(pDescr!=NULL);
if(!mf.GetTemplate())
{
if( SUCCESS != mdlTextNode_extractWide(&mf.userOrigin, &mf.rotMatrix , mf.pTxtSizeParam,mf.pTxtParamWide,
&pDescr->el, NULL) )
return;
}
else
{
MStuff omf(TEXT_NODE_ELM,pDescr->h.dgnModelRef ,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
mdlTextNode_extractWide(&omf.userOrigin, &omf.rotMatrix , omf.pTxtSizeParam,omf.pTxtParamWide,
&pDescr->el, NULL);
mf.pTxtSizeParam->aspectRatio = omf.pTxtSizeParam->aspectRatio;
mf.pTxtParamWide->lineOffset = omf.pTxtParamWide->lineOffset;
mf.pTxtParamWide->exFlags.acadLineSpacingType = omf.pTxtParamWide->exFlags.acadLineSpacingType;
mf.SetLineSpacing();
mf.pTxtParamWide->nodeNumber = omf.pTxtParamWide->nodeNumber;
mf.pTxtParamWide->textnodeWordWrapLength = omf.pTxtParamWide->textnodeWordWrapLength;

}
mf.ApplyModify();
if(mf.IsNeedModify())
{

APIChangeTextStyles(pDescr,&mf);
}
return;
}

protected:
static int changestyles_processTextElement(MSElementUnion* pElement,MStuff* pMF,DgnModelRefP modelRef,MSElementDescr* pElmDscr,MSElementDescr** ppNewDscr)
{
ASSERT(pMF!=NULL);

int status = ERROR, elemType;
ElementID eID = mdlElement_getID(pElement);
elemType = mdlElement_getType (pElement);
if (TEXT_ELM == elemType)
{
MStuff mf(*pMF);

if(!mf.GetTemplate())
{
if( SUCCESS != mdlText_extractWide(mf.wString, NULL,&mf.userOrigin,&mf.rotMatrix,mf.pTxtSizeParam,mf.pTxtParamWide,NULL,pElement))
return NULL;
}
else
{
MStuff omf(TEXT_ELM,modelRef,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
mdlText_extractWide(mf.wString, NULL,NULL,NULL,NULL,omf.pTxtParamWide,NULL,pElement);//prepare for next line
mf.pTxtParamWide->exFlags.crCount = omf.pTxtParamWide->exFlags.crCount;
}

mf.ApplyModify();
pMF = &mf;
MSElementUnion newElement;

status = mdlText_createWide (&newElement, pElement,pMF->wString,&pMF->userOrigin ,&pMF->rotMatrix,pMF->pTxtSizeParam ,pMF->pTxtParamWide, NULL);

if (eID != 0L && 0 == mdlElement_getID (&newElement))
mdlAssoc_tagElementValue (NULL, &newElement, 0, eID);

if (SUCCESS == status)
{
pMF->bReWrite = TRUE;
mdlElmdscr_new (ppNewDscr, NULL, &newElement);
}
}
else if (TEXT_NODE_ELM == elemType)
{
MSElementUnion newElement;
MSElementDescr* pWorkingEd = NULL;
if (SUCCESS == mdlTextNode_createWide (&newElement, pElement,&pMF->userOrigin,&pMF->rotMatrix,pMF->pTxtSizeParam ,pMF->pTxtParamWide))
{
mdlElmdscr_duplicate (&pWorkingEd, pElmDscr);
mdlModify_elementDescr2 (&pWorkingEd->h.firstElem, ACTIVEMODEL, MODIFY_REQUEST_HEADERS, changestyles_processTextElement, pMF, 0l);
}

if (pMF->bReWrite)
mdlTextNode_createEx (ppNewDscr,&newElement, pWorkingEd->h.firstElem, &pMF->userOrigin,&pMF->rotMatrix,pMF->pTxtSizeParam ,pMF->pTxtParamWide);

if(pMF->GetTemplate()!=NULL)
{
//add 7 lines bellow for set user origin to text element of text node.
//it would be used when we have a template (which not a text node) to set text node .
DPoint3d userOrg;
mdlText_extractWide(NULL, NULL,&userOrg,NULL,NULL,NULL,NULL,&((*ppNewDscr)->h.firstElem->el));
mdlVec_subtractPoint(&userOrg,&pMF->userOrigin,&userOrg);
Transform tMatrix;
mdlTMatrix_getIdentity(&tMatrix);
mdlTMatrix_setTranslation (&tMatrix, &userOrg);
mdlElmdscr_transform(*ppNewDscr, &tMatrix);
}

mdlElmdscr_freeAll (&pWorkingEd);
}

return NULL != *ppNewDscr ? MODIFY_STATUS_REPLACEDSCR : MODIFY_STATUS_NOCHANGE;
}

static int APIChangeTextStyles(MSElementDescr* pEd,void* pMF)
{
MSElementDescr* pNewEd = NULL;
((MStuff*)pMF)->bReWrite = TRUE;
mdlElmdscr_duplicate (&pNewEd, pEd);
mdlModify_elementDescr2 (&pNewEd, ACTIVEMODEL, MODIFY_REQUEST_HEADERS, changestyles_processTextElement, pMF, 0l);
if (((MStuff*)pMF)->bReWrite)
mdlElmdscr_rewriteByModelRef (pNewEd, NULL, mdlElmdscr_getFilePos(pEd), pEd->h.dgnModelRef);
mdlElmdscr_freeAll (&pNewEd);
return SUCCESS;
}
public:
static void testcase()
{
MSElement eleNew;
DPoint3d pt = {0,0,0};

MSElementDescr * pDescr = NULL,*pDescr1 =NULL;
#if XM
mdlText_createWide( &eleNew,NULL ,(MSWideChar*)L"abc\n中文",&pt,NULL,NULL,NULL, NULL);
#else
mdlText_createWide( &eleNew,NULL ,(const MSWideChar*)L"abc\n中文",&pt,NULL,NULL,NULL, NULL);
#endif
mdlElmdscr_new(&pDescr1,NULL,&eleNew);
if(mdlTextNode_createEx(&pDescr,NULL,pDescr1,&pt,NULL,NULL,NULL)==SUCCESS)
mdlElmdscr_addByModelRef( pDescr,MASTERFILE);
mdlElmdscr_freeAll(&pDescr1);
mdlElmdscr_freeAll(&pDescr);
}
};