From ef639438cb153ee62c4f5071d4a78b48b08be789 Mon Sep 17 00:00:00 2001 From: Edouard Dupin Date: Tue, 14 Feb 2012 19:31:25 +0100 Subject: [PATCH] Change the FileChooser comportement, and Create the Unicode string ==> etk::UString (must be used in all the Gui application) --- Sources/libetk/etk/UString.cpp | 735 ++++++++++++++++++ Sources/libetk/etk/UString.h | 115 +++ Sources/libetk/etk/unicode.cpp | 72 +- Sources/libetk/etk/unicode.h | 3 +- Sources/libetk/file.mk | 1 + Sources/libewol/ewol/widget/Entry.cpp | 7 +- Sources/libewol/ewol/widget/Entry.h | 1 + Sources/libewol/ewol/widget/List.cpp | 2 +- .../libewol/ewol/widgetMeta/FileChooser.cpp | 18 +- 9 files changed, 944 insertions(+), 10 deletions(-) create mode 100644 Sources/libetk/etk/UString.cpp create mode 100644 Sources/libetk/etk/UString.h diff --git a/Sources/libetk/etk/UString.cpp b/Sources/libetk/etk/UString.cpp new file mode 100644 index 00000000..38664f6b --- /dev/null +++ b/Sources/libetk/etk/UString.cpp @@ -0,0 +1,735 @@ +/** + ******************************************************************************* + * @file etk/UString.cpp + * @brief Ewol Tool Kit : normal Unicode string management... (sources) + * @author Edouard DUPIN + * @date 14/02/2012 + * @par Project + * Ewol TK + * + * @par Copyright + * Copyright 2011 Edouard DUPIN, all right reserved + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY. + * + * Licence summary : + * You can modify and redistribute the sources code and binaries. + * You can send me the bug-fix + * + * Term of the licence in in the file licence.txt. + * + ******************************************************************************* + */ + +#include +#include +#include + +int32_t strlen(const uniChar_t * data) +{ + if (NULL == data) { + return 0; + } + int32_t iii=0; + while (*data != 0) { + data++; + iii++; + if (iii > 0x7FFFFFF0) { + return iii; + } + } + return iii; +} + +#undef __class__ +#define __class__ "etk::UString" + +etk::CCout& etk::operator <<(etk::CCout &os, const etk::UString &obj) +{ + etk::VectorType output_UTF8; + unicode::convertUnicodeToUtf8(obj.m_data, output_UTF8); + output_UTF8.PushBack('\0'); + os << &output_UTF8[0]; + return os; +} + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +etk::UString::~UString(void) +{ + m_data.Clear(); +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +etk::UString::UString(void) +{ + //TK_INFO("new etk::UString()"); + m_data.Clear(); + m_data.PushBack('\0'); +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +etk::UString::UString(const char* inputData, int32_t len) +{ + m_data.Clear(); + m_data.PushBack('\0'); + Set(inputData, len); +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +etk::UString::UString(const uniChar_t* inputData, int32_t len) +{ + m_data.Clear(); + m_data.PushBack('\0'); + Set(inputData, len); +} + +void etk::UString::Set(const char * inputData, int32_t len) +{ + if (NULL == inputData) { + // nothing to add ... + return; + } + // overwrite the len if needed : + if ((-1) == len) { + len = strlen(inputData); + } + // convert the string + etk::VectorType tmpChar; + for (int32_t iii=0; iii 0 ) { + // copy all data : + Set(inputData, len); + } + return *this; +} + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +const etk::UString& etk::UString::operator= (const uniChar_t * inputData) +{ + m_data.Clear(); + m_data.PushBack('\0'); + if (NULL == inputData) { + return *this; + } + // calculate the size : + int32_t len = strlen(inputData); + // check the new size ... + if (len > 0 ) { + // copy all data : + Set(inputData, len); + } + return *this; +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +const etk::UString& etk::UString::operator= (etk::VectorType inputData) +{ + etk::VectorType output_Unicode; + unicode::convertUtf8ToUnicode(inputData, output_Unicode); + *this = output_Unicode; + return *this; +} + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +const etk::UString& etk::UString::operator= (etk::VectorType inputData) +{ + m_data = inputData; + if (m_data.Size()>0) { + if (m_data[m_data.Size()-1] != '\0') { + m_data.PushBack('\0'); + } + } + //TK_DEBUG("m_dataLen="<= m_data.Size() ) { + return true; + } else { + return false; + } +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +int32_t etk::UString::Size(void) const +{ + if (m_data.Size() == 0) { + return 0; + } else { + return m_data.Size() - 1; + } +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +void etk::UString::Add(int32_t currentID, const char* inputData) +{ + etk::UString tmpString(inputData); + Add(currentID, tmpString.pointer() ); +} + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +void etk::UString::Add(int32_t currentID, const uniChar_t* inputData) +{ + // get the input lenght + int32_t len = strlen(inputData); + if (0 == len) { + TK_WARNING("no data to add on the current UString"); + return; + } else if (currentID < 0) { + TK_WARNING("Curent ID(" << currentID << ") < 0 ==> Add at the start"); + currentID = 0; + } else if (currentID > Size() ) { + TK_ERROR("Curent ID(" << currentID << ") > maxSize ... (" << Size() << ") ==> add at the end ..."); + m_data.PushBack(inputData, len); + return; + } + m_data.Insert(currentID, inputData, len); +} + + +/** + * @brief + * + * @param[in,out] + * + * @return + * + */ +void etk::UString::Remove(int32_t currentID, int32_t len) +{ + if (0 >= len) { + TK_ERROR("no data to remove on the current UString"); + return; + } + // TODO : check the size of the data + m_data.EraseLen(currentID, len); +} + + +/** + * @brief Remove all element in the UString + * + * @param --- + * + * @return --- + * + */ +void etk::UString::Clear(void) +{ + m_data.Clear(); + m_data.PushBack('\0'); +} + + + +/** + * @brief find the first accurence after the position indicated + * + * @param[in] element Element that might be find in the UString + * @param[in] startPos Stert position to begin the search + * + * @return the position of the first occurence or -1 if not find... + * + */ +int32_t etk::UString::FindForward(const uniChar_t element, int32_t startPos) +{ + if (startPos < 0) { + startPos = 0; + } else if (startPos >= Size() ) { + return -1; + } + for (int32_t iii=startPos; iii< Size(); iii++) { + if (m_data[iii] == element) { + return iii; + } + } + return -1; +} + + +/** + * @brief find the first accurence before the position indicated. + * + * @param[in] element Element that might be find in the UString + * @param[in] startPos Stert position to begin the search + * + * @return the position of the first occurence begining by the end or -1 if not find... + * + */ +int32_t etk::UString::FindBack(const uniChar_t element, int32_t startPos) +{ + if (startPos < 0) { + return -1; + } else if (startPos >= Size() ) { + startPos = Size(); + } + for (int32_t iii=startPos; iii>=0; iii--) { + if (m_data[iii] == element) { + return iii; + } + } + return -1; +} + + +/** + * @brief Extract data from the data between two position + * + * @param[in] posStart Start position where to extract data + * @param[in] posEnd End position where to extract data + * + * @return the extracted UString + * + */ +etk::UString etk::UString::Extract(int32_t posStart, int32_t posEnd) +{ + etk::UString out; + if (posStart < 0) { + posStart = 0; + } else if (posStart >= Size() ) { + return out; + } + if (posEnd < 0) { + return out; + } else if (posEnd >= Size() ) { + posEnd = Size(); + } + out.m_data = m_data.Extract(posStart, posEnd); + out.m_data.PushBack('\0'); + return out; +} + + +/** + * @brief Get a basic vector in int8 data with no \0 at the end of the UString + * + * @param --- + * + * @return The desired vector with data + * + */ +etk::VectorType etk::UString::GetVector(void) +{ + etk::VectorType out = m_data; + out.PopBack(); + return out; +} + diff --git a/Sources/libetk/etk/UString.h b/Sources/libetk/etk/UString.h new file mode 100644 index 00000000..6a059761 --- /dev/null +++ b/Sources/libetk/etk/UString.h @@ -0,0 +1,115 @@ +/** + ******************************************************************************* + * @file etk/String.h + * @brief Ewol Tool Kit : normal sting management... (header) + * @author Edouard DUPIN + * @date 26/01/2011 + * @par Project + * Ewol TK + * + * @par Copyright + * Copyright 2011 Edouard DUPIN, all right reserved + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY. + * + * Licence summary : + * You can modify and redistribute the sources code and binaries. + * You can send me the bug-fix + * + * Term of the licence in in the file licence.txt. + * + ******************************************************************************* + */ + +#ifndef __ETK_USTRING_H__ +#define __ETK_USTRING_H__ + +#include +#include + +namespace etk +{ + class UString + { + public: + // Constructeurs + UString(void); + UString(const uniChar_t* inputData, int32_t len = -1); + UString(const char* inputData, int32_t len = -1); + void Set(const uniChar_t* inputData, int32_t len=-1); + void Set(const char* inputData, int32_t len=-1); + // basic convertion integer en string + UString(int inputData); + UString(unsigned int inputData); + UString(const etk::UString &etkS); + // destructor : + ~UString(void); + + /***************************************************** + * = assigment + *****************************************************/ + const etk::UString& operator= (const etk::UString &etkS ); + const etk::UString& operator= (const char * inputData); + const etk::UString& operator= (const uniChar_t * inputData); + const etk::UString& operator= (etk::VectorType inputData); + const etk::UString& operator= (etk::VectorType inputData); + /***************************************************** + * == operator + *****************************************************/ + bool operator== (const etk::UString& etkS) const; + bool operator== (const uniChar_t * inputData) const; + bool operator== (const char * inputData) const; + /***************************************************** + * != operator + *****************************************************/ + bool operator!= (const etk::UString& etkS) const; + bool operator!= (const uniChar_t * inputData) const; + bool operator!= (const char * inputData) const; + /***************************************************** + * += operator + *****************************************************/ + const etk::UString& operator+= (const etk::UString &etkS); + const etk::UString& operator+= (const char * inputData); + const etk::UString& operator+= (const uniChar_t * inputData); + /***************************************************** + * + operator + *****************************************************/ + etk::UString operator+ (const etk::UString &etkS); + etk::UString operator+ (const char * inputData); + etk::UString operator+ (const uniChar_t * inputData); + /***************************************************** + * * operator + *****************************************************/ + friend etk::CCout& operator <<( etk::CCout &os,const etk::UString &obj); + + bool IsEmpty(void) const; + int32_t Size(void) const; + + void Add(int32_t currentID, const char* inputData); + void Add(int32_t currentID, const uniChar_t* inputData); + void Remove(int32_t currentID, int32_t len); + void Clear(void); + + etk::VectorType GetVector(void); + uniChar_t * pointer(void) { return &m_data[0]; }; + + // Sting operation : + int32_t FindForward(const uniChar_t element, int32_t startPos=0); + int32_t FindBack(const uniChar_t element, int32_t startPos=0x7FFFFFFF); + etk::UString Extract(int32_t posStart=0, int32_t posEnd=0x7FFFFFFF); + + private : + etk::VectorType m_data; + }; + + etk::CCout& operator <<(etk::CCout &os, const etk::UString &obj); + +} + +int32_t strlen(const uniChar_t * data); + + + +#endif + diff --git a/Sources/libetk/etk/unicode.cpp b/Sources/libetk/etk/unicode.cpp index 51a2794e..c4a1c78d 100644 --- a/Sources/libetk/etk/unicode.cpp +++ b/Sources/libetk/etk/unicode.cpp @@ -202,16 +202,25 @@ void unicode::convertUtf8ToUnicode(char * input_UTF8, uniChar_t &output_Unicode) } -int32_t unicode::convertUnicodeToUtf8(etk::VectorType& input_Unicode, etk::VectorType& output_UTF8) +int32_t unicode::convertUnicodeToUtf8(const etk::VectorType& input_Unicode, etk::VectorType& output_UTF8) { - TK_WARNING("TODO : not coded..."); - return 0; + char output[10]; + + for (int32_t iii=0; iii& input_UTF8, etk::VectorType& output_Unicode) { - bool baseValid; char tmpData[20]; int32_t pos = 0; while (pos < input_UTF8.Size()) { @@ -261,6 +270,61 @@ int32_t unicode::convertUtf8ToUnicode(etk::VectorType& input_UTF8, etk::Ve return 0; } +int32_t unicode::convertUtf8ToUnicode(char * input_UTF8, etk::VectorType& output_Unicode) +{ + char tmpData[20]; + int32_t pos = 0; + if (NULL == input_UTF8) { + return 0; + } + int32_t len = strlen(input_UTF8); + while (pos < len) { + int32_t lenMax = len - pos; + //4 case + if( 1<=lenMax + && 0x00 == (input_UTF8[pos+0] & 0x80) ) + { + tmpData[0] = input_UTF8[pos+0]; + tmpData[1] = '\0'; + pos += 1; + } else if( 2<=lenMax + && 0xC0 == (input_UTF8[pos+0] & 0xE0) + && 0x80 == (input_UTF8[pos+1] & 0xC0) ) { + tmpData[0] = input_UTF8[pos+0]; + tmpData[1] = input_UTF8[pos+1]; + tmpData[2] = '\0'; + pos += 1; + } else if( 3<=lenMax + && 0xE0 == (input_UTF8[pos+0] & 0xF0) + && 0x80 == (input_UTF8[pos+1] & 0xC0) + && 0x80 == (input_UTF8[pos+2] & 0xC0)) { + tmpData[0] = input_UTF8[pos+0]; + tmpData[1] = input_UTF8[pos+1]; + tmpData[2] = input_UTF8[pos+2]; + tmpData[3] = '\0'; + pos += 1; + } else if( 4<=lenMax + && 0xF0 == (input_UTF8[pos+0] & 0xF8) + && 0x80 == (input_UTF8[pos+1] & 0xC0) + && 0x80 == (input_UTF8[pos+2] & 0xC0) + && 0x80 == (input_UTF8[pos+3] & 0xC0)) { + tmpData[0] = input_UTF8[pos+0]; + tmpData[1] = input_UTF8[pos+1]; + tmpData[2] = input_UTF8[pos+2]; + tmpData[3] = input_UTF8[pos+3]; + tmpData[4] = '\0'; + pos += 1; + } else { + tmpData[0] = '\0'; + pos += 1; + } + uniChar_t tmpUnicode; + convertUtf8ToUnicode(tmpData, tmpUnicode); + output_Unicode.PushBack(tmpUnicode); + } + return 0; +} + // Transform ISO <==> UTF-8 void unicode::convertIsoToUtf8(charset_te inputCharset, char input_ISO, char * output_UTF8) diff --git a/Sources/libetk/etk/unicode.h b/Sources/libetk/etk/unicode.h index c4a61ca5..d9344b0c 100644 --- a/Sources/libetk/etk/unicode.h +++ b/Sources/libetk/etk/unicode.h @@ -54,8 +54,9 @@ namespace unicode { // Transform UTF-8 <==> Unicode void convertUnicodeToUtf8( uniChar_t input_Unicode, char * output_UTF8); void convertUtf8ToUnicode( char * input_UTF8, uniChar_t& output_Unicode); - int32_t convertUnicodeToUtf8( etk::VectorType& input_Unicode, etk::VectorType& output_UTF8); + int32_t convertUnicodeToUtf8( const etk::VectorType& input_Unicode, etk::VectorType& output_UTF8); int32_t convertUtf8ToUnicode( etk::VectorType& input_UTF8, etk::VectorType& output_Unicode); + int32_t convertUtf8ToUnicode( char * input_UTF8, etk::VectorType& output_Unicode); // Transform ISO <==> UTF-8 void convertIsoToUtf8( charset_te inputCharset, char input_ISO, char * output_UTF8); void convertUtf8ToIso( charset_te inputCharset, char * input_UTF8, char & output_ISO); diff --git a/Sources/libetk/file.mk b/Sources/libetk/file.mk index 6f24347c..94b009cc 100644 --- a/Sources/libetk/file.mk +++ b/Sources/libetk/file.mk @@ -7,6 +7,7 @@ FILE_LIST = \ etk/unicode.cpp \ etk/unicodeTable.cpp \ etk/String.cpp \ + etk/UString.cpp \ etk/Stream.cpp \ etk/File.cpp \ etk/RegExp.cpp diff --git a/Sources/libewol/ewol/widget/Entry.cpp b/Sources/libewol/ewol/widget/Entry.cpp index 82212a54..3bcbed0f 100644 --- a/Sources/libewol/ewol/widget/Entry.cpp +++ b/Sources/libewol/ewol/widget/Entry.cpp @@ -30,8 +30,9 @@ #include -extern const char * const ewolEventEntryClick = "ewol Entry click"; -extern const char * const ewolEventEntryEnter = "ewol Entry Enter"; +extern const char * const ewolEventEntryClick = "ewol-Entry-click"; +extern const char * const ewolEventEntryEnter = "ewol-Entry-Enter"; +extern const char * const ewolEventEntryModify = "ewol-Entry-Modify"; @@ -43,6 +44,7 @@ void ewol::Entry::Init(void) { AddEventId(ewolEventEntryClick); AddEventId(ewolEventEntryEnter); + AddEventId(ewolEventEntryModify); m_displayStartPosition = 0; m_displayCursorPos = 0; m_userSize = 50; @@ -189,6 +191,7 @@ bool ewol::Entry::OnEventKb(eventKbType_te typeEvent, uniChar_t unicodeData) unicode::convertUnicodeToUtf8(unicodeData, UTF8_data); m_data += UTF8_data; } + GenEventInputExternal(ewolEventEntryModify, -1, -1); UpdateTextPosition(); MarkToReedraw(); return true; diff --git a/Sources/libewol/ewol/widget/Entry.h b/Sources/libewol/ewol/widget/Entry.h index e9edb4f4..e604758f 100644 --- a/Sources/libewol/ewol/widget/Entry.h +++ b/Sources/libewol/ewol/widget/Entry.h @@ -31,6 +31,7 @@ extern const char * const ewolEventEntryClick; extern const char * const ewolEventEntryEnter; +extern const char * const ewolEventEntryModify; namespace ewol { class Entry :public ewol::Widget diff --git a/Sources/libewol/ewol/widget/List.cpp b/Sources/libewol/ewol/widget/List.cpp index 5c160ebe..c676e892 100644 --- a/Sources/libewol/ewol/widget/List.cpp +++ b/Sources/libewol/ewol/widget/List.cpp @@ -114,7 +114,7 @@ void ewol::List::OnRegenerateDisplay(void) startRaw = 0; } // We display only compleate lines ... - EWOL_DEBUG("Request drawing list : " << startRaw << "-->" << (startRaw+displayableRaw) << " in " << nbRaw << "raws"); + EWOL_VERBOSE("Request drawing list : " << startRaw << "-->" << (startRaw+displayableRaw) << " in " << nbRaw << "raws"); for(uint32_t iii=startRaw; iiiSubWidgetAdd(myLabel); myEntry = new ewol::Entry(m_folder); m_widgetCurrentFolderId = myEntry->GetWidgetId(); + myEntry->ExternLinkOnEvent(ewolEventEntryModify, GetWidgetId(), ewolEventFileChooserEntryFolder); myEntry->SetExpendX(true); myEntry->SetFillX(true); myEntry->SetWidth(200); @@ -379,6 +382,7 @@ ewol::FileChooser::FileChooser(void) mySizerHori->SubWidgetAdd(myLabel); myEntry = new ewol::Entry(m_file); m_widgetCurrentFileNameId = myEntry->GetWidgetId(); + myEntry->ExternLinkOnEvent(ewolEventEntryModify, GetWidgetId(), ewolEventFileChooserEntryFile); myEntry->SetExpendX(true); myEntry->SetFillX(true); myEntry->SetWidth(200); @@ -489,9 +493,19 @@ void ewol::FileChooser::SetFileName(etk::String filename) bool ewol::FileChooser::OnEventAreaExternal(int32_t widgetID, const char * generateEventId, const char * data, etkFloat_t x, etkFloat_t y) { EWOL_INFO("Receive Event from the LIST ... : widgetid=" << widgetID << "\"" << generateEventId << "\" ==> data=\"" << data << "\"" ); - if (ewolEventFileChooserCancel == generateEventId) { + if (ewolEventFileChooserEntryFolder == generateEventId) { + //==> change the folder name + // TODO : Change the folder, if it exit ... + } else if (ewolEventFileChooserEntryFile == generateEventId) { + //==> change the file name + ewol::Entry * tmpWidget = (ewol::Entry*)ewol::widgetManager::Get(m_widgetCurrentFileNameId); + if (NULL != tmpWidget) { + m_file = tmpWidget->GetValue(); + } + // TODO : Remove file selection + } else if (ewolEventFileChooserCancel == generateEventId) { //==> Auto remove ... - + // TODO : ... } else if (ewolEventFileChooserHidenFileChange == generateEventId) { // regenerate the display ... UpdateCurrentFolder();