Page 1 of 1

Hyphenation and Language

Posted: Thu Oct 24, 2013 9:58 pm
by dex
Hi,

I am new here, and from what I have read so far, TRichView is quite an impressive product.

Here are two questions, I couldn't find answers myself:

1. Let's assume I have a function HyphenateWord which will take a word as parameter and insert soft hyphens in it at appropriate hyphenation points. What would be the best way to go to implement hyphenation with current version of TRichView. By implementing hyphenation I mean hyphenating selection/paragraph/document.

2. Hyphenation is heavily dependant on language, so is there a "language text attribute" determining the language a word belongs to? (E.g. in document written in more than one language)

Thanks!
Dejan

Posted: Fri Oct 25, 2013 9:33 pm
by Sergey Tkachenko
1. Do you want to implement it as undoable operation?

2. By default, there is no Language property. However, if you define RVLANGUAGEPROPERTY in RV_Defs.inc and recompile the source code, this language will appear. This property will be saved to RTF/DocX/RVF. However, it will not be assigned automatically basing on the keyboard layout.
This property is a feature reserved for future use.

Posted: Wed Oct 30, 2013 11:52 pm
by dex
Yes, if it can be undoable even better. Unlike MS Word which hyphenates only few words located around end of line, I want to hyphenate every word from selection. Such text can be easily reused in DTP software (Illustrator, Quark, etc.)

In order to avoid changing of text formatting, I would like to do the following:

1. take all words from selection, one by one
2. hyphenate each word with separate HyphenateWord function
3. using the result just insert soft hyphens at appropriate locations directly in the word in text

Removing hyphenation should delete all soft hyphens from the selection.

If Language is the property which can be accessed for every word, then HyphenateWord would skip words not belonging to the desired Language.

How do I do this with RVE?

Posted: Thu Nov 21, 2013 8:41 pm
by dex
Any thoughts?

I tried to insert soft hyphen manually (Ctrl + -) using your demo projects, no success.

Posted: Mon Nov 25, 2013 6:12 pm
by Sergey Tkachenko
Here is an example how to hyphenate the selection.

Let we have a function
function HyphenateWords(var s: String; FirstIndex, LastIndex: Integer): Boolean;
This function hyphenates words in the substring of s from the FirstIndex-th to the LastIndex-th characters (index of the first character = 1). It must return True if the string is changed.

For example, I used this function for testing:

Code: Select all

function HyphenateWords(var s: String; FirstIndex, LastIndex: Integer): Boolean;
var i: Integer;
begin
  Result := False;
  for i := LastIndex-1 downto FirstIndex do
    if (s[i] in ['a'..'z']) and (s[i+1] in ['a'..'z']) then begin
      Insert('-', s, i+1);
      Result := True;
    end;
end;
This function adds '-' between lowercase English characters.

The following procedure hyphenates the selection:

Code: Select all

procedure HyphenateSelection(rve: TCustomRichViewEdit);

var Started: Boolean;

   procedure ChangeText(ItemNo: Integer; const s: String);
   begin
     if not Started then begin
       rve.BeginUpdate;
       rve.BeginUndoGroup(rvutModifyItem);
       rve.SetUndoGroupMode(True);
       Started := True;
     end;
     rve.SetItemTextEd(ItemNo, s);
   end;

var i, StartItemNo, StartOffs, EndItemNo, EndOffs, v: Integer;
    s: String;
begin
  rve := rve.TopLevelEditor;
  rve.GetSelectionBounds(StartItemNo, StartOffs, EndItemNo, EndOffs, True);
  if StartItemNo<0 then
    exit;
  Started := False;
  s := rve.GetItemText(StartItemNo);
  if StartItemNo=EndItemNo then begin
    v := Length(s)-(EndOffs-1);
    if HyphenateWords(s, StartOffs, EndOffs-1) then begin
      ChangeText(StartItemNo, s);
      rve.SetSelectionBounds(StartItemNo, StartOffs, EndItemNo, Length(s)-v+1);
    end;
    end
  else begin
    if HyphenateWords(s, StartOffs, Length(s)) then
      ChangeText(StartItemNo, s);
    for i := StartItemNo+1 to EndItemNo-1 do begin
      s := rve.GetItemText(i);
      if HyphenateWords(s, 1, Length(s)) then
        ChangeText(i, s);
    end;
    s := rve.GetItemText(EndItemNo);
    v := Length(s)-(EndOffs-1);
    if HyphenateWords(s, 1, EndOffs-1) then begin
      ChangeText(EndItemNo, s);
      rve.SetSelectionBounds(StartItemNo, StartOffs, EndItemNo, Length(s)-v+1);
    end;
  end;
  if Started then begin
    rve.SetUndoGroupMode(False);
    rve.EndUpdate;
  end;

end;

Posted: Mon Nov 25, 2013 6:18 pm
by Sergey Tkachenko
TRichViewEdit does not processes Ctrl+'-'.
You can process it itself (for example, by adding an action with this shortcut) and call RichViewEdit1.InsertTextW(WideChar($00AD));

Posted: Thu Dec 05, 2013 4:37 pm
by alexander halser
We implemented automatic hyphenation in our help authoring tool Help & Manual. The hyphenation is based on the free OpenOffice dictionaries and the open source spell checker Hunspell.

The Delphi implementation is available from our website:
http://www.helpandmanual.com/downloads_delphi.html

Once you have loaded a dicitionary, you can auto-hyphenate a word with this function:

Code: Select all

  procedure HyphenateWord(var AWord: string; const IntWordLen: integer);
  var
    l, k: integer;
    tmpWord: String;
  begin
    if intWordLen > 3 then
    try
      tmpWord := HyphenDictionary.Hyphenate(aWord)
      if (tmpWord <> aWord) then  //tmpWord has hyphenation breaks in the form of equal signs "="
      begin
        k := length(tmpWord);
        for l := 1 to k do
          case tmpWord[l] of
          '=': Insert(Char(UNI_SOFT_HYPHEN), AWord, l);
          end;
      end;
    except
    end;
  end;

Posted: Tue Dec 10, 2013 10:36 am
by dex
This is great!

Thanks, I'll give it a try.

Dejan