Recent

Author Topic: FPC SysUtils - WrapText not performing as expected.  (Read 587 times)

PJW

  • New Member
  • *
  • Posts: 12
FPC SysUtils - WrapText not performing as expected.
« on: November 25, 2020, 09:42:43 pm »
Tested using FPC 3.0.4 / Lazarus 2.0.8

The RTL WrapText function (SysUtils) has a "feature" where it does not wrap text within quotes.  I do not believe this is implemented properly.

For example, the following Text:

Democratic People's Republic of Korea ...
or
I can't do that today, perhaps tomorrow.

Will not wrap after the apostrophe no matter how long the string is.   I assume this is because it assumes everything after the apostrophe is quoted text.   

I'm also finding that the MaxCol parameter is pretty much treated as Minimum length instead of Maximum, as it does not wrap to keep the segments below the MaxCol, but instead wraps at the next space AFTER MaxCol.

Is this as designed? 

Am I misinterpreting what this RTL function is for and supposed to do?

lucamar

  • Hero Member
  • *****
  • Posts: 3432
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #1 on: November 25, 2020, 09:53:24 pm »
Except for the MaxCol thing, the rest works just as stated in the documentation, and even that might be inferred from it, if one forgets the badly chosen name (though, yes, it might be a bug).

Fact is WrapText() is a basic wrapping routine, at least in those aspects; if you want something a little more advanced (like, say, a more clever treatment of quotes) you'll have to do it yourself. It's not very difficult to do it "right" (meaning: "as you want it to work").
« Last Edit: November 25, 2020, 09:56:40 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.10/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PJW

  • New Member
  • *
  • Posts: 12
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #2 on: November 25, 2020, 11:10:40 pm »
It's not very difficult to do it "right" (meaning: "as you want it to work").

I'll agree here, ones interpretation how something should work is often tainted by how one would want it to work or what one wants it to do at the moment.

I have to disagree as to the quotes working as described.   From the page you linked:

"Portions of text that are between single or double quotes will be considered single words and the text will not be broken between the quotes."

Nothing in the example text is BETWEEN quotes.  Apostrophes are much more common in textual data than Quoted text.

That said, I've done as you suggested and written my own wrapping routine with some added features:
(1).  Wraps at the space immediately BEFORE the max length
(2).  Width is based on Canvas Width instead of character count making it work better with modern fonts.
(3).  Totally ignores quotes.
(4).  Allows the caller to chose if the want STRICT breaks at the specified length or if it's OK for the data to overrun the field with should no break opportunity be found.

It's doesn't handle the '-' break, but for my use I actually didn't want that.  I may add that back in later to make a more general routine but for now...

It's not extensively tested yet, but I've run some data thru it and it seems to work as I need it to.

Code: Pascal  [Select][+][-]
  1. function RPTWrapText(
  2.   const nValue: string;          // The Text to be folded
  3.   const nMax:   longint;         // Max Length of field IN PIXELS not Characters
  4.   const nDelim: char;            // Delimeter to replace space character
  5.   C: TCanvas;                    // Canvas to base the length on.
  6.   const Strict: boolean = false  // Enable Strict Breaks
  7.   ): string;
  8.  
  9. var
  10.   LastSpace: longint;
  11.   NewValue:  string;
  12.   TestValue: string;
  13.   StartPos:  longint;
  14.   IDX:       longint;
  15.   L:         longint;
  16.   CH:        char;
  17.  
  18. begin
  19.   NewValue   := nValue;
  20.   StartPos   := 1;
  21.   LastSpace  := 0;
  22.  
  23.   IDX := 1;
  24.   while IDX <= length( NewValue ) do
  25.   begin
  26.  
  27.     CH := NewValue[ IDX ];
  28.     if ( CH in [' ', #9 ] ) then LastSpace := IDX;
  29.  
  30.     if ( CH = nDelim ) then begin
  31.       // A forced break from the original data
  32.       StartPos  := IDX + 1;
  33.       LastSpace := 0;
  34.     end else begin
  35.       // Calculate the length of the string from the last break (StartPos)
  36.       // to the Current position (IDX).
  37.       TestValue := copy( newValue, StartPos, (IDX-StartPos)+1 );
  38.       L := C.TextWidth( TestValue );
  39.  
  40.       //showmessage(inttostr(IDX)+':'+inttostr(L)+':'+inttostr(nMax)+':'+TestValue);
  41.  
  42.       if ( L > nMax ) then begin
  43.         if ( LastSpace > 0 ) then begin
  44.           NewValue[ LastSpace ] := nDelim;  // Set the Break Character
  45.           StartPos  := LastSpace + 1;       // Set Start Position to the Next Character
  46.           LastSpace := 0;
  47.         end else begin
  48.           if Strict then begin
  49.             NewValue := copy( NewValue, 1, IDX-1 )
  50.                       + nDelim
  51.                       + copy( NewValue, IDX, length(NewValue) );
  52.  
  53.             StartPos := IDX+1;
  54.           end; { Strict }
  55.         end;
  56.       end;
  57.     end;
  58.  
  59.     inc( IDX );
  60.   end; { while }
  61.  
  62.   exit(NewValue);
  63. end;  
 

lucamar

  • Hero Member
  • *****
  • Posts: 3432
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #3 on: November 26, 2020, 04:26:45 am »
I have to disagree as to the quotes working as described.   From the page you linked:

"Portions of text that are between single or double quotes will be considered single words and the text will not be broken between the quotes."

Nothing in the example text is BETWEEN quotes.  Apostrophes are much more common in textual data than Quoted text.

Yes, but note that "apostrophe" and "single quote" are normally the same character (in plain ASCII text), so when WrapText finds one it takes it as "start quote" and stops wrapping until it finds the closing one ... or a line break, which restarts wrapping (IIRC). The fact that it does so and that using that character as apostrophe is, arguably, more common than to find it used for quoting (at least in English) is one of the reasons I called it "basic". ;)

The most probable explanation for the behaviour of WrapText that I can think of is that it's intended mainly to be used to wrap (Pascal) source code, in which case it's quite logical how it works.
« Last Edit: November 26, 2020, 04:32:49 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.10/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2595
  • Compiler Developer
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #4 on: November 26, 2020, 09:19:38 am »
The most probable explanation for the behaviour of WrapText that I can think of is that it's intended mainly to be used to wrap (Pascal) source code, in which case it's quite logical how it works.

One would need to check whether Delphi's WrapText behaves the same and decide based on that...

440bx

  • Hero Member
  • *****
  • Posts: 2094
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #5 on: November 26, 2020, 09:29:57 am »
For example, the following Text:

Democratic People's Republic of Korea ...
or
I can't do that today, perhaps tomorrow.

Will not wrap after the apostrophe no matter how long the string is.   I assume this is because it assumes everything after the apostrophe is quoted text.   
In addition to @PascalDragon's suggestion, I would suggest you try using text such as "People''s" and "can''t".  WrapText _may_ (IOW, this is just a guess on my part) require use of a single quote to be denoted as two single quotes.

HTH.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

jamie

  • Hero Member
  • *****
  • Posts: 4039
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #6 on: November 26, 2020, 05:52:51 pm »
Wraptext inserts <CR><LF> into the string... It does not break it up.
so you end with a longer string.

and with Delphi it seems the numerical parameter is the min before it searches for a space to insert.

This seems to be a console mode function



The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 3432
Re: FPC SysUtils - WrapText not performing as expected.
« Reply #7 on: November 26, 2020, 06:13:21 pm »
Wraptext inserts <CR><LF> into the string... It does not break it up.
so you end with a longer string.

It inserts either BreakStr, if set, or the system-dependent LineEnding by default but yes, that's its function, a mere "visual" conversion.

IIRC, there's somewhere a function like it but returning an array or a TStrings object. Or was it a helper? Or a method of some class? I don't remember, sorry :-[

Quote
and with Delphi it seems the numerical parameter is the min before it searches for a space to insert.

That seems to be the behaviour in FreePascal too, only the parameter is called MaxCol, which is a bit misleading. And doesn't work with strings like the OP posted. :(
« Last Edit: November 26, 2020, 06:15:40 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.10/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018