Page 1 of 1

How to apply specific formatting to some text using offsets?

Posted: Mon Jan 02, 2006 7:57 pm
by csterg
Hello,
i have been thinking and reading for almost 2 days on the best way to apply some formatting to a rv or rve and i am not sure what to do.

The problem is this:
I create a document that has many paragraphs in it (let's say 100 paragraphs). Each paragraph contains some text and for each paragraph i have a list of formatting and offsets i want to apply.
For example:
- for paragraph one, i want to apply the Bold style to all characters from position 5 to position 20. Also, i want yellow background for position 10 to position 25. Obviously, the formattings can overlay one another.
- The number of possible formatting is known (bold, italic, forecolor, backcolor, underline). What i have also (for each paragraph) is the start and end offset for each one of these formattings

Now, i have thought the following solutions:
1. Get the text of the paragraph (as simple text), and then break it apart in pieces using the information of the position of formattings and for each piece create a suitable style that combines all formatting that corresponds to that piece and use the AddXXX methods. This solution seems to be the faster but has a lot of overhead.

2. Add all the paragraphs, format the rv and then go through each paragraph (using the RVLinear unit), select the appropriate text for each one of these and use the ApplyStyleConversion method, which does what i would do in solution 1. The problem i see with this solution is that the method ApplyStyleConversion actually reformats the document so if there are many formattings to be applied, this method will be extremely slow.

Is there any other way to implement the above?

It is obvious that what i try to do is to allow the user to apply some formatting to the text but instead of saving the whole text as RTF or RVF, i want each formatting to be specified with indexes so i can then apply semantic information to it (e.g. red letters are for errros, yellow background for important notes, etc).

Thanks,
Costas

Posted: Tue Jan 03, 2006 10:32 am
by Sergey Tkachenko
Well, you listed 2 the most appropriate method for implementing your task. If made correctly, the resulting documents will be the same.
(do not forget to use RVStyle.TextStyles.FindSuchStyle to reuse existing styles when possible).
And you correctly assumed that the first way is much faster, if document is large and and there are many operations for changing style.

And, as I understand, you'll need to implement saving and loading in your file format.

Posted: Tue Jan 03, 2006 10:48 am
by csterg
Sergey Tkachenko wrote: And, as I understand, you'll need to implement saving and loading in your file format.
Almost true, this is the idea.

If i go with solution 2 (which seems a bit easier since the ApplyStyleConversion correctly splits items and duplicates their tags if needed, which is very useful), is there a way to 'Lock' the updates (re-formats) until i am done with all of them?

A workaround is to use LockWindowsUpdate: this has the drawback of screen flickering. The other solution is the following method which does the same job (just mentioning here because it is very useful) but with no flickering:

class procedure Utils.LockControl(c: TWinControl; lock: boolean);
begin
if (c=nil) or (c.Handle=0) then exit;

if lock then SendMessage(c.Handle,WM_SETREDRAW,0,0)
else begin
SendMessage(c.Handle,WM_SETREDRAW,1,0);
RedrawWindow(c.Handle,nil,0,
RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
end;

So, i could do:

Utils.LockControl(rv, true);
.... ApplyStyleConversion ...
Utils.LockControl(rv, false);

This method will not perform any redrawing, but the internal re-formatting always occurs (and slows down the process), so if there was a way to instruct the rv not to do it in the first place, it would be even better.
Costas

Posted: Tue Jan 03, 2006 10:55 am
by Sergey Tkachenko
Yes, using WM_SETREDRAW is the best solution to prevent redrawing.
No, it's not possible to lock reformatting.