Construction of TCollection_ExtendedString from plain C string is fixed to consider input string as UTF-8 in several places (identified as described in notes to #31113).
Message_MsgFile is corrected to load resource file as UTF-8 (unless it has BOM indicating use of UTF-16).
Added tests for use of Unicode in some DRAW commands (bugs demo bug14673_*)
Draw Harness hotkeys **W** (Wireframe) and **S** (Shaded) have been re-mapped to **Ctrl+W** and **Ctrl+S**.
Hotkey **A** has been remapped to **Backspace**.
Hotkeys WASD and Arrays are now mapped for walk-through navigation in 3D Viewer.
+
+@subsection upgrade_750_msgfile_utf8 Utf-8 encoding for message files
+
+Message files (with extension .msg) are now expected to be in UTF-8 encoding (unless they have UTF-16 BOM in which case UTF-16 is expected).
+This allows using arbitrary Unicode symbols for localization of messages.
+
+Existing message files containing 8-bit characters (previously interpreted as characters from Latin-1 code block) should be converted to UTF-8.
Standard_CString expr (arg[3]);
Handle(TDataStd_Relation) aR = TDataStd_Relation::Set(label);
- aR->SetRelation(expr);
+ aR->SetRelation(TCollection_ExtendedString (expr, Standard_True));
Handle(TDataStd_Variable) aV;
for (Standard_Integer i = 4; i < nb; i++)
if ((!isGuid && nb > 6) || (isGuid && nb > 8)) {
j = j + 2;
for(Standard_Integer i = From; i<=To; ++i) {
- A->SetValue(i, arg[j] );
+ TCollection_ExtendedString aVal (arg[j], Standard_True);
+ A->SetValue(i, aVal);
j++;
}
}
Handle(TDataStd_ExtStringArray) arr;
if (label.FindAttribute(TDataStd_ExtStringArray::GetID(), arr))
{
- arr->SetValue(index, arg[4]);
+ TCollection_ExtendedString aVal(arg[4], Standard_True);
+ arr->SetValue(index, aVal);
return 0;
}
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if(!anAtt->HasInteger(arg[3])) {
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if(!anAtt->HasInteger(aKey)) {
std::cout << "There is no data specified by Key = "<< arg[3] << std::endl;
return 1;
} else {
- std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetInteger(arg[3])<<std::endl;
+ std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetInteger(aKey)<<std::endl;
if(nb == 5)
- Draw::Set(arg[4], anAtt->GetInteger(arg[3]));
+ Draw::Set(arg[4], anAtt->GetInteger(aKey));
return 0;
}
}
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if(!anAtt->HasReal(arg[3])) {
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if(!anAtt->HasReal(aKey)) {
Message::SendFail() << "There is no data specified by Key = " << arg[3];
return 1;
} else {
- std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetReal(arg[3])<<std::endl;
+ std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetReal(aKey)<<std::endl;
if(nb == 5)
- Draw::Set(arg[4], anAtt->GetReal(arg[3]));
+ Draw::Set(arg[4], anAtt->GetReal(aKey));
return 0;
}
}
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if (!anAtt->HasString(arg[3]))
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if (!anAtt->HasString(aKey))
{
Message::SendFail() << "There is no data specified by Key = " << arg[3];
return 1;
}
else
{
- TCollection_AsciiString aValue (anAtt->GetString(arg[3]));
+ TCollection_AsciiString aValue (anAtt->GetString(aKey));
std::cout << "Key = " << arg[3] << " Value = " << aValue.ToCString() << std::endl;
if(nb == 5)
Draw::Set(arg[4], aValue.ToCString());
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if (!anAtt->HasByte(arg[3]))
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if (!anAtt->HasByte(aKey))
{
Message::SendFail() << "There is no data specified by Key = " << arg[3];
return 1;
}
else
{
- std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetByte(arg[3])<< std::endl;
+ std::cout << "Key = " << arg[3] << " Value = " <<anAtt->GetByte(aKey)<< std::endl;
if(nb == 5)
- Draw::Set(arg[4], anAtt->GetByte(arg[3]));
+ Draw::Set(arg[4], anAtt->GetByte(aKey));
return 0;
}
}
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if (!anAtt->HasArrayOfIntegers(arg[3]))
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if (!anAtt->HasArrayOfIntegers(aKey))
{
Message::SendFail() << "There is no data specified by Key = " << arg[3];
return 1;
{
std::cout << "Key = " << arg[3] <<std::endl;
- Handle(TColStd_HArray1OfInteger) anArrValue = anAtt->GetArrayOfIntegers(arg[3]);
+ Handle(TColStd_HArray1OfInteger) anArrValue = anAtt->GetArrayOfIntegers(aKey);
if(!anArrValue.IsNull()) {
Standard_Integer lower = anArrValue->Lower();
Standard_Integer upper = anArrValue->Upper();
std::cout <<std::endl;
std::cout <<"NamedData attribute at Label = " << arg[2] <<std::endl;
anAtt->LoadDeferredData();
- if(!anAtt->HasArrayOfReals(arg[3])) {
+ TCollection_ExtendedString aKey(arg[3], Standard_True);
+ if(!anAtt->HasArrayOfReals(aKey)) {
std::cout << "There is no data specified by Key = "<< arg[3] << std::endl;
return 1;
} else {
std::cout << "Key = " << arg[3] <<std::endl;
- Handle(TColStd_HArray1OfReal) anArrValue = anAtt->GetArrayOfReals(arg[3]);
+ Handle(TColStd_HArray1OfReal) anArrValue = anAtt->GetArrayOfReals(aKey);
if(!anArrValue.IsNull()) {
Standard_Integer lower = anArrValue->Lower();
Standard_Integer upper = anArrValue->Upper();
const char** a)
{
if (nb >= 3) {
- TCollection_ExtendedString path (a[1]);
+ TCollection_ExtendedString path (a[1], Standard_True);
Handle(TDocStd_Application) A = DDocStd::GetApplication();
Handle(TDocStd_Document) D;
Standard_Integer insession = A->IsInSession(path);
if (nb >= 3) {
Handle(TDocStd_Document) D;
if (!DDocStd::GetDocument(a[1],D)) return 1;
- TCollection_ExtendedString path (a[2]);
+ TCollection_ExtendedString path (a[2], Standard_True);
Handle(TDocStd_Application) A = DDocStd::GetApplication();
PCDM_StoreStatus theStatus;
const char** a)
{
if (nb == 2) {
- TDocStd_PathParser path (a[1]);
+ TDocStd_PathParser path (TCollection_ExtendedString (a[1], Standard_True));
di << "Trek : " << path.Trek() << "\n";
di << "Name : " << path.Name() << "\n";
di << "Extension : " << path.Extension() << "\n";
if (nb == 3) {
Handle(TDocStd_Document) D;
if (!DDocStd::GetDocument(a[1],D)) return 1;
- TCollection_ExtendedString comment (a[2]);
+ TCollection_ExtendedString comment (a[2], Standard_True);
// Handle(TDocStd_Application) A = DDocStd::GetApplication();
// A->AddComment(D,comment);
D->AddComment(comment);
return 1;
}
if(n > 1)
- sMultiTransactionManager->CommitCommand(a[1]);
+ sMultiTransactionManager->CommitCommand(TCollection_ExtendedString (a[1], Standard_True));
else
sMultiTransactionManager->CommitCommand();
return 0;
const TopoDS_Shape& aShape = DBRep::Get(a[3]);
if(aShape.IsNull()) return 1;
if(nb == 5) {
- TDataStd_Name::Set(L, a[4]);
+ TDataStd_Name::Set(L, TCollection_ExtendedString (a[4], Standard_True));
}
DNaming::LoadImportedShape(L, aShape);
Handle(TDataStd_UAttribute) anObj = AddObject (aDoc);
if(!anObj.IsNull()) {
if(nb == 3)
- TDataStd_Name::Set(anObj->Label(), a[2]);
+ TDataStd_Name::Set(anObj->Label(), TCollection_ExtendedString (a[2], Standard_True));
DDF::ReturnLabel(di, anObj->Label());
return 0;
}
//Called : from loadFile()
//=======================================================================
-template <class _Char> static inline Standard_Boolean
-getString (_Char *& thePtr,
+template <typename CharType> struct TCollection_String;
+template <> struct TCollection_String <Standard_Character> { typedef TCollection_AsciiString type; };
+template <> struct TCollection_String <Standard_ExtCharacter> { typedef TCollection_ExtendedString type; };
+
+template <class CharType> static inline Standard_Boolean
+getString (CharType *& thePtr,
TCollection_ExtendedString& theString,
Standard_Integer& theLeftSpaces)
{
- _Char * anEndPtr = thePtr;
- _Char * aPtr;
+ CharType * anEndPtr = thePtr;
+ CharType * aPtr;
Standard_Integer aLeftSpaces;
do
aLeftSpaces = 0;
for (;;)
{
- _Char aChar = * aPtr;
+ CharType aChar = * aPtr;
if (aChar == ' ') aLeftSpaces++;
else if (aChar == '\t') aLeftSpaces += 8;
else if (aChar == '\r' || * aPtr == '\n') aLeftSpaces = 0;
thePtr = anEndPtr;
if (*thePtr)
*thePtr++ = '\0';
- theString = TCollection_ExtendedString (aPtr);
+ theString = typename TCollection_String<CharType>::type (aPtr);
theLeftSpaces = aLeftSpaces;
return Standard_True;
}
Handle(TObj_Model) TObj_Assistant::FindModel
(const Standard_CString theName)
{
- TCollection_ExtendedString aName( theName );
+ TCollection_ExtendedString aName(theName, Standard_True);
Standard_Integer i = getModels().Length();
Handle(TObj_Model) aModel;
for(; i > 0; i --)
if ( aModel.IsNull() ) return 1;
Standard_Boolean isSaved = Standard_False;
if (argc > 2 )
- isSaved = aModel->SaveAs( argv[2] );
+ isSaved = aModel->SaveAs( TCollection_ExtendedString (argv[2], Standard_True) );
else
isSaved = aModel->Save();
Standard_Boolean isLoaded = Standard_False;
Handle(TObj_Model) aModel = getModelByName(argv[1]);
+ TCollection_ExtendedString aPath(argv[2], Standard_True);
if ( aModel.IsNull() )
{
// create new
aModel = new TObjDRAW_Model();
- isLoaded = aModel->Load( argv[2] );
+ isLoaded = aModel->Load(aPath);
if ( isLoaded )
{
Handle(TDocStd_Document) D = aModel->GetDocument();
}
}
else
- isLoaded = aModel->Load( argv[2] );
+ {
+ isLoaded = aModel->Load(aPath);
+ }
if (!isLoaded) {
return 1;
}
- TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
+ TCollection_ExtendedString aText (theArgVec[anArgIter + 2], Standard_True);
aColorScale->SetLabel (aText, anIndex);
aColorScale->SetLabelType (Aspect_TOCSD_USER);
anArgIter += 2;
TColStd_SequenceOfExtendedString aSeq;
for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
{
- aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
+ aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter], Standard_True));
}
aColorScale->SetLabels (aSeq);
aColorScale->SetLabelType (Aspect_TOCSD_USER);
Standard_ENABLE_DEPRECATION_WARNINGS
}
- aColorScale->SetTitle (theArgVec[anArgIter + 1]);
+ TCollection_ExtendedString aTitle(theArgVec[anArgIter + 1], Standard_True);
+ aColorScale->SetTitle (aTitle);
if (isTwoArgs)
{
anArgIter += 1;
return 1;
}
- Standard_CString Filename = argv[1];
+ TCollection_AsciiString Filename = argv[1];
Standard_CString DocName = argv[2];
if ( DDocStd::GetDocument(DocName, D, Standard_False) )
di << "Error: user name is expected.\n" << myCommand;
return 1;
}
- aUsername = argv[iarg];
+ aUsername = TCollection_ExtendedString (argv[iarg], Standard_True);
}
else if (opt == "--time")
{
di << "Error: timestamp is expected.\n" << myCommand;
return 1;
}
- aTimestamp = argv[iarg];
+ aTimestamp = TCollection_ExtendedString (argv[iarg], Standard_True);
}
}
di << "Error: user name is expected.\n" << myCommand;
return 1;
}
- aUsername = argv[iarg];
+ aUsername = TCollection_ExtendedString (argv[iarg], Standard_True);
}
else if (opt == "--time")
{
di << "Error: timestamp is expected.\n" << myCommand;
return 1;
}
- aTimestamp = argv[iarg];
+ aTimestamp = TCollection_ExtendedString (argv[iarg], Standard_True);
}
}
di << "Error: file path is expected.\n" << myCommand;
return 1;
}
- aFilename = argv[iarg];
+ aFilename = TCollection_ExtendedString (argv[iarg], Standard_True);
aFromFile = Standard_True;
}
else if (opt == "--data")
di << "Error: user name is expected.\n" << myCommand;
return 1;
}
- aUsername = argv[iarg];
+ aUsername = TCollection_ExtendedString (argv[iarg], Standard_True);
}
else if (opt == "--time")
{
di << "Error: timestamp is expected.\n" << myCommand;
return 1;
}
- aTimestamp = argv[iarg];
+ aTimestamp = TCollection_ExtendedString (argv[iarg], Standard_True);
}
}
else
{
Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
- TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName.ToCString());
+ TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
Draw::Set (aDestName.ToCString(), aDrawDoc);
}
}
else
{
Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc);
- TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName.ToCString());
+ TDataStd_Name::Set (aDoc->GetData()->Root(), aDestName);
Draw::Set (aDestName.ToCString(), aDrawDoc);
}
}
--- /dev/null
+puts "# ============================================================"
+puts "# 0014673: Provide true support for Unicode symbols"
+puts "# ============================================================"
+puts ""
+puts "# Use non-Ascii names for color scale"
+
+pload VISUALIZATION
+vinit
+vcolorscale languages -title "Языки Восточной Азии" -range 1 3 3 -colors red green blue \
+ -labelAtBorder off -labels "Japanese 日本語" "Korean 한국어" "Chinese 中文"
+
+vdump ${imagedir}/${casename}.png
--- /dev/null
+puts "# ============================================================"
+puts "# 0014673: Provide true support for Unicode symbols"
+puts "# ============================================================"
+puts ""
+puts "# Check that different file open / save commands can deal with Unicode"
+
+pload ALL
+
+# Name means "Japanese"
+set filePrefix "$imagedir/${casename}_日本語"
+
+proc checkFile {filepath} {
+ if { [file exists $filepath] } {
+ puts "File $filepath is ceated, OK"
+ } else {
+ puts "Error: Could not find file $filepath"
+ }
+}
+
+puts "# OCAF documents"
+NewDocument Xml XmlOcaf
+SaveAs Xml ${filePrefix}.xml
+checkFile ${filePrefix}.xml
+Close Xml
+Open ${filePrefix}.xml Xml
+
+NewDocument Bin BinOcaf
+SaveAs Bin ${filePrefix}.cbf
+checkFile ${filePrefix}.cbf
+Close Bin
+Open ${filePrefix}.cbf Bin
+
+puts "# STEP and IGES"
+box b 10 10 10
+NewDocument XDE BinOcaf
+XAddShape XDE b
+
+WriteStep XDE ${filePrefix}.stp
+checkFile ${filePrefix}.stp
+ReadStep Step ${filePrefix}.stp
+
+WriteIges XDE ${filePrefix}.igs
+checkFile ${filePrefix}.igs
+ReadIges Iges ${filePrefix}.igs
--- /dev/null
+puts "# ============================================================"
+puts "# 0014673: Provide true support for Unicode symbols"
+puts "# ============================================================"
+puts ""
+puts "# Check that resource file with messages saved in file with UTF-8"
+puts "# encoding is correctly loaded and processed"
+
+puts "# Prepare resource file to be used instead of standard XSTEP.us,"
+puts "# with Russian translation of one message"
+dsetenv CSF_LANGUAGE ru
+dsetenv CSF_XSMessage $imagedir
+set message "Б-сплайн поверхность не является гладкой"
+set fd [open $imagedir/XSTEP.ru w]
+fconfigure $fd -encoding utf-8
+puts $fd ".XSTEP_1\nMessage used to check file load\n.IGES_1250\n$message"
+close $fd
+
+puts "# Load IGES file which is known to generate the message, and check it"
+puts "REQUIRED 14673 ALL: $message"
+pload XSDRAW
+igesbrep [locate_data_file hammer.iges] a *
+tpstat c
--- /dev/null
+puts "# ============================================================"
+puts "# 0014673: Provide true support for Unicode symbols"
+puts "# ============================================================"
+puts ""
+puts "# Check that non-Ascii text strings can be saved and restored in OCAF"
+
+puts "# Prepare OCAF document with text strings in different languages"
+set strings [list "test" "l'épreuve" "опыт" "테스트" "größten 市"]
+
+pload OCAF
+NewDocument D XmlOcaf
+set i 0
+foreach str $strings {
+ SetName D 0:[incr i] $str
+}
+
+puts "# Save it and load back, then check the strings"
+SaveAs D $imagedir/${casename}.xml
+Close D
+Open $imagedir/${casename}.xml D
+
+set i 0
+foreach str $strings {
+ set res [GetName D 0:[incr i]]
+ if { $res != $str } {
+ puts "Error: string $str was restored as $res"
+ }
+}