Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Fmx TMemo unable to show a base64 string appropriately


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 3 - Last Post: Feb 4, 2016 6:46 PM Last Post By: Hugues Acker
Hugues Acker

Posts: 3
Registered: 2/8/12
Fmx TMemo unable to show a base64 string appropriately  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 1, 2016 2:57 PM
I need to show a base64 key in a TMemo. Unfortunately, it is impossible to show this base64 string appropriately: it is cut off at every '/' by a Carriage return, or at any '+' where it systematically starts a new line !
I tried everything in my knowledge to make this string in one long phrase (without carriage returns), but unsucessfully. I need this Tmemo doing a correct wraptext, with lines going to the right limit of the TMemo without being cut.
How is it possible to obtain a flat string in base64 (without carriage returns), if possible resizable automatically when the form and TMemo is resized ? Many thanks.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Fmx TMemo unable to show a base64 string appropriately  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 1, 2016 3:30 PM   in response to: Hugues Acker in response to: Hugues Acker
Hugues wrote:

I need to show a base64 key in a TMemo. Unfortunately, it is
impossible to show this base64 string appropriately: it is cut off at
every '/' by a Carriage return, or at any '+' where it systematically
starts a new line !

I find it hard to believe that a TMemo would do that. Those are not break
characters. Are you sure you are not chopping the data yourself before putting
it into the TMemo? Please show your actual code. Where is the base64 data
coming from? How exactly are you adding it to the TMemo?

I tried everything in my knowledge to make this string in one long
phrase (without carriage returns), but unsucessfully. I need this
Tmemo doing a correct wraptext, with lines going to the right limit of
the TMemo without being cut.

base64 does not really lend itself well to word-wrapping, the only characters
it uses that could be treated as logical word-wrap separators are '/' amd
'+', everything else is alpha-numeric. You may have to split the base64
yourself and add each substring to the TMemo separately, or insert explicit
line breaks where needed.

How is it possible to obtain a flat string in base64 (without carriage
returns), if possible resizable automatically when the form and TMemo
is resized ?

If what you say is true, it sounds like it is not possible.

--
Remy Lebeau (TeamB)
Hugues Acker

Posts: 3
Registered: 2/8/12
Re: Fmx TMemo unable to show a base64 string appropriately  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 2, 2016 8:47 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Hugues wrote:

I need to show a base64 key in a TMemo. Unfortunately, it is
impossible to show this base64 string appropriately: it is cut off at
every '/' by a Carriage return, or at any '+' where it systematically
starts a new line !

I find it hard to believe that a TMemo would do that. Those are not break
characters. Are you sure you are not chopping the data yourself before putting
it into the TMemo? Please show your actual code. Where is the base64 data
coming from? How exactly are you adding it to the TMemo?

I tried everything in my knowledge to make this string in one long
phrase (without carriage returns), but unsucessfully. I need this
Tmemo doing a correct wraptext, with lines going to the right limit of
the TMemo without being cut.

base64 does not really lend itself well to word-wrapping, the only characters
it uses that could be treated as logical word-wrap separators are '/' amd
'+', everything else is alpha-numeric. You may have to split the base64
yourself and add each substring to the TMemo separately, or insert explicit
line breaks where needed.

How is it possible to obtain a flat string in base64 (without carriage
returns), if possible resizable automatically when the form and TMemo
is resized ?

If what you say is true, it sounds like it is not possible.

--
Remy Lebeau (TeamB)

Thank you for your answer.
The base64 string is typed by the user (any user, from the keyboard), so the string is going into the Memo.
An editor like Fmx TMemo should illustrate exactly what the user types, without introducing CR+LF on its own at the '/' or just before the '+'. The TMemo should (when in wordwrap mode of course) extend the string normally to the bottom, at each time the caret is hitting the right side of the memo, or when resizing dynamically the form and the memo.
What is the point to cut a string at '/' or '+' ? Furthermore, the problem is with certain characters only (for example + and /, but not with '#' and '*'). If we use # and * at the place of + and /, then the memo works correctly. So, a TMemo which is not able to type as the user wants is a bugged component... Unless it is a 'FEATURE' which could be deactivated by the user. Maybe; so what to do to deactivate the feature ? Because it is impossible to introduce a flat B64 string in TMemo in one peace; it cuts itself at many places.
I am still reproducing the problem at this moment on a small demo appli: a TMemo on a form (wordwrap mode): impossible to have a flat string, like I say. This problem is not new.
I could send you this small demo to show you if you wish.

Edited by: Hugues Acker on Feb 2, 2016 8:50 AM
Hugues Acker

Posts: 3
Registered: 2/8/12
Re: Fmx TMemo unable to show a base64 string appropriately  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 4, 2016 2:36 PM   in response to: Hugues Acker in response to: Hugues Acker
For those who are interested, the code below: a TForm with a TMemo (memo). This solution works for me for a flat Base64 string. At last no longer string cut-off at every / or +.
Maybe the solution below needs to be tuned, but it works enough for me. Of course, before to treat the b64 string in an application, it needs to be filtered to eliminate CR-LF but that's OK.
I use the events: OnKeyDown, OnResize, OnPainting of the TMemo.
I wrote a specific function formatMemo(..) which does the job of aligning the lines appropriately.
The code accepts only true B64 characters, and filters faulty cahacters if any.

#define IS_B64(c) (isalnum(c) || (c == '/') || (c == '+') || (c == '='))

//Adjustments work for Courier New, standard size:
const float FW=7.2;//Font width
const diff=25;//Room for vert. scroll bar

//Gives the number of characters in one line of the TMemo:
// width : width in pixels where to put the line of chars
// font_sz : the average width of a character
// returns the number of characters by line of the TMemo
inline int nchars(int width, float font_sz)
{
return int(float(width-diff)/font_sz);
}//nchars
//---------------------------------------------------------------------------

//Formats the memo to a certain length of characters:
// *p : the memo to format
// nc : the number of characters for each line.
void formatMemo(TMemo *p, int nc)
{
if(p==0) return;
AnsiString src, dest;//UnicodeString is less fast...
//Filter everything as B64 only:
for(int i=1; i<=p->Text.Length(); ++i) {//Indexing is "1-based" like on Delphi (except on mobiles)
if(IS_B64(p->Text[i])) dest += p->Text[i];
}
p->Lines->Clear();//Erases everyting
int length=dest.Length(), units=length/nc, remain=length%nc;
for( int k=0 ; k<units ; ++k) {
p->Lines->Append( dest.SubString(1+k*nc, nc) );
}
if(remain) {
p->Lines->Append( dest.SubString(1+units*nc, remain) );
}
}//formatMemo
//---------------------------------------------------------------------------

void __fastcall TForm1::memoKeyDown(TObject *Sender, WORD &Key, System::WideChar &KeyChar,
TShiftState Shift)
{
//This event is triggered before the character is sent in Text.
//Saves caret position:
TCaretPosition p={memo->CaretPosition.Line, memo->CaretPosition.Pos};
memo->Tag=0;//Don't do a format.

if(Key==0 && !IS_B64(KeyChar))//Printable KeyChar
{
//Changes the entry into '0':
KeyChar='0';
KeyDown(Key,KeyChar,Shift);

//Put a backspace to erase:
Key=vkBack; KeyChar=0;
KeyDown(Key,KeyChar,Shift);
}
else memo->Tag=1;//Programs a format in the OnPainting
memo->SetFocus();
memo->CaretPosition=p;//Repositions the caret
}
//---------------------------------------------------------------------------

//In case of resize, reformat the TMemo
void __fastcall TForm1::memoResize(TObject *Sender)
{
formatMemo(memo, nchars(memo->Width,FW));
}
//---------------------------------------------------------------------------

void __fastcall TForm1::memoPainting(TObject *Sender, TCanvas *Canvas, const TRectF &ARect)
{
//We will use the Tag of the memo as a parameter, to plan a reformat.
if(memo->Tag){//A format is asked by OnKeyDown.
TCaretPosition p={memo->CaretPosition.Line, memo->CaretPosition.Pos};
formatMemo(memo, nchars(memo->Width,FW));
memo->SetFocus();
memo->CaretPosition=p;
memo->Tag=0;//Done
}
}
//---------------------------------------------------------------------------

Edited by: Hugues Acker on Feb 4, 2016 6:34 PM
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02