header:
======
protected:
    int defLang;

public:
    int  __fastcall GetLangID(bool selection=false);
    int __fastcall SetLangID(int langID, bool selection=false);
    int __fastcall GetDefLang();
    void __fastcall SetDefLang(int langID);
    int __fastcall GetFirstVisibleLine();
	int __fastcall GetLastVisibleLine();
    void __fastcall GetEdRec();
    //future extension
    int __fastcall GetBaseLineY(int lineIndex);

    RECT edrec;

cpp
===
in the constructor:

    defLang=GetUserDefaultLangID();

extensions:

//---------------------------------------------------------------------------
int  __fastcall TRichEditRawRtf::GetLangID(bool selection)
{
    AnsiString s=GetRtf(true);
    int pos=s.AnsiPos("\\deflang");
int lc=defLang;//GetUserDefaultLangID();
    if(pos>0) {
        s.Delete(1,pos);
        if(s.Length()>7) {
            s.Delete(1,7); //
            if(s.Length()>4)
                s.SetLength(4);
            lc=s.ToIntDef(lc);
            }
        }
    if(selection) {
        AnsiString s=GetRtf();
        pos=s.AnsiPos("\\lang");
        if(pos>0)
            lc=-1;
        }
return lc;
}
//---------------------------------------------------------------------------
int __fastcall TRichEditRawRtf::SetLangID(int langID, bool selection)
{
//1024==no lang/no spell check
    if(langID<1024)
        return -1; //invalid langID
    if(!selection) {
        AnsiString s="{\\lang  }";
        AnsiString idStr=AnsiString(langID);
        s.Insert(idStr,7);
        PutRtf(s);
        return langID;
        }
int saveLen=SelLength;
int saveStart=SelStart;

    Lines->BeginUpdate();
    SelStart=saveStart+1;
    SelLength=1;
AnsiString s0=GetRtf();

    try {
        SelStart=saveStart;
        SelLength=saveLen;
        Lines->EndUpdate();
        }
    catch(...) {
        Lines->EndUpdate();  //Executed even in case of an exception
        throw;
        }

AnsiString s="\\lang";
AnsiString idStr=AnsiString(langID);
AnsiString sel=GetRtf();
        s+=idStr;
        s+=" ";
        sel.Insert(s, s0.Length()-1-2); //-2 = what is it? why?
        sel+="}";
        PutRtf(sel);
return langID;
}
//---------------------------------------------------------------------------
void __fastcall TRichEditRawRtf::SetDefLang(int langID)
{
//a) if selection, set \lang for this selection
    if(SelLength)
        SetLangID(langID, true);

//b) set default language
//b0) save cursor position
    int saveLen=SelLength;
    int saveStart=SelStart;
//b1) select all
    SelectAll();
//b2) get rtf string
    AnsiString s=GetRtf();
//b3) replace \deflangXXXX to \deflang langID
    int pos=s.AnsiPos("\\deflang");
    if(pos>0) {
        AnsiString idStr=AnsiString(langID);
        s.Delete(pos+8, 4);//4: e.g. 1043
        s.Insert(idStr, pos+8);
        PutRtf(s);
        }
//b4) restore cursor position
    try {
        SelStart=saveStart;
        SelLength=saveLen;
        Lines->EndUpdate();
        }
    catch(...) {
        Lines->EndUpdate();  //Executed even in case of an exception
        throw;
        }
}
//---------------------------------------------------------------------------
int __fastcall TRichEditRawRtf::GetDefLang()
{
//b0) save cursor position
    int saveLen=SelLength;
    int saveStart=SelStart;

    Lines->BeginUpdate();
    SelStart=0;
    SelLength=0;
    int lc=GetLangID();

    try {
        SelStart=saveStart;
        SelLength=saveLen;
        Lines->EndUpdate();
        }
    catch(...) {
        Lines->EndUpdate();  //Executed even in case of an exception
        throw;
        }
return lc;
}
//---------------------------------------------------------------------------
int __fastcall TRichEditRawRtf::GetFirstVisibleLine()
{
int fivi=(int)SendMessage(Handle,EM_GETFIRSTVISIBLELINE,
                            (WPARAM)0, (LPARAM)0);
return fivi;
}
//---------------------------------------------------------------------------
int __fastcall TRichEditRawRtf::GetLastVisibleLine()
{
RECT rc;
	SendMessage(Handle, EM_GETRECT,
                (WPARAM)0, (LPARAM)(RECT*) &rc);
int x, y;
    x=(int)rc.left;
    y=(int)rc.bottom;
long l=x+y*65536; //or: DWORD MAKELONG(WORD x, WORD y);

int lac=(int)SendMessage(Handle, EM_CHARFROMPOS,
                         (WPARAM)0L,(LPARAM)&l);
    int lavi = SendMessage(Handle, EM_LINEFROMCHAR,
                      lac, 0);
return lavi;
}
//---------------------------------------------------------------------------
void __fastcall TRichEditRawRtf::GetEdRec()
{
//function as part of the future component for __property TRect edrec {set, get}
	SendMessage(Handle, EM_GETRECT, (WPARAM)0, (LPARAM)(RECT*) &edrec);
//used by the future funtion GetBaseLineY(int lineIndex);
//EM_CHARFROMPOS, EM_LINEFROMCHAR
}
//---------------------------------------------------------------------------
//  future extension
//---------------------------------------------------------------------------
int __fastcall TRichEditRawRtf::GetBaseLineY(int lineIndex)
{
/*
    AnsiString line=Lines->satirngs[lindIndex];
    edrec, EM_CHARFROMPOS, EM_LINEFROMCHAR ->baseLine
*/
return 0;
}
//---------------------------------------------------------------------------