/**********************************************************************************/
/*                                                                                */
/*      Implementation des fonctions du package text.pkg                          */
/*                                                                                */
/**********************************************************************************/

#include "x/Version.h"
#include "x/scolplugin.h"


#include <stdio.h>
#include <string.h>

#include "objstr.h"
#include "tests.h"
#include "utils.h"
#include "objects/font.h"
#include "events.h"
   


WNDPROC TextProc = NULL ;





char GBuf [ MAX_TEXT ] ;




/***************************************************************************************/
/*                                                                                     */
/*  LRESULT CALLBACK TextProc2( HWND hwnd, unsigned msg,                               */
/*                                     UINT wParam, LONG lParam )                      */
/*                                                                                     */
/*  Fonction winproc pour les objets texte transparent                                 */
/*                                                                                     */
/***************************************************************************************/


LRESULT CALLBACK TextProc2( HWND hwnd, unsigned msg,
                                     UINT wParam, LONG lParam )
{
    HDC Hdc ;   
   

//    MMechostr(MSKDEBUG,"%d\n",msg);
    switch ( msg )
    {                     
        case WM_ERASEBKGND :        
            Hdc = ( HDC ) wParam ;
            //MMechostr(MSKDEBUG,"test transparent\n");
            GRTestTextTransparent ( hwnd, Hdc ) ;             
            return 0 ;
        
        case WM_PAINT :
            Hdc = ( HDC ) wParam ;

            break ;
        case WM_MOVE :   
            SCOLEventMoveText ( mm,hwnd,LOWORD(lParam),HIWORD(lParam)) ;
            tstscoldead(202) ;
            break ;
        case WM_SIZE :        
            SCOLEventSizeText ( mm,hwnd,LOWORD(lParam),HIWORD(lParam )) ;
            tstscoldead(203) ;
            break ;     
      
        case WM_CHAR:
            /* faut verifier que l'objet est un objet line */

            if ( wParam == 13 ) if (GRTestReflexLine ( hwnd )) return 0;
            if ( wParam == 9 )
            {
              // To avoid the event on new focused window
              msg = 0;
              GRTestTabFocus ( hwnd , OBJTYPTEXT ) ;
            }

            tstscoldead(204);
            break ;
        case WM_DROPFILES : SCOLDropFiles ( mm,hwnd,(HANDLE)wParam,OBJTYPTEXT,RFLTEXT_DROPFILE);
            break; 
    }
  return CallWindowProc ( TextProc , hwnd , msg , wParam , lParam ) ;
}




/***************************************************************************************/
/*                                                                                     */
/*  LRESULT CALLBACK TextProc3 ( HWND hwnd , unsigned msg , UINT wParam , LONG lParam )*/
/*                                                                                     */
/*  Cette fonction est la winproc des objets texte quand ils ne sont pas transparant   */
/*                                                                                     */
/***************************************************************************************/

LRESULT CALLBACK TextProc3 ( HWND hwnd , unsigned msg , UINT wParam , LONG lParam )
{
    //MMechostr ( 1 , "Msg %d Limite %d\n" , msg , SendMessage ( hwnd , EM_GETLIMITTEXT , 0 , 0 )) ;

    switch ( msg )
    {
     case WM_MOVE :   
        SCOLEventMoveText ( mm,hwnd,LOWORD(lParam),HIWORD(lParam)) ;
        tstscoldead(205) ;
        break ;
      
     case WM_SIZE :        
        SCOLEventSizeText ( mm,hwnd,LOWORD(lParam),HIWORD(lParam )) ;
        tstscoldead(206) ;
        break ;
      
      case WM_CHAR:
            /* faut verifier que l'objet est un objet line */         

            if ( wParam == 13 ) if (GRTestReflexLine ( hwnd )) return 0;
            if ( wParam == 9 )
            {
              // To avoid the event on new focused window
              msg = 0;
              GRTestTabFocus ( hwnd , OBJTYPTEXT ) ;
            }
            tstscoldead(207);
            break ;

      case WM_DROPFILES : 
            //MMechostr(MSKDEBUG,"Passage DROPFILES OK\n");
            SCOLDropFiles ( mm,hwnd,(HANDLE)wParam,OBJTYPTEXT,RFLTEXT_DROPFILE);
            break; 

    default : break ;
    }


    return CallWindowProc ( TextProc , hwnd , msg , wParam , lParam ) ;
}


/****************************************************************************************/
/*                                                                                      */
/*  HWND NewObjEditText ( PtrObjText Txt , char * Text , HWND Parent )                  */
/*                                                                                      */
/*                                                                                      */
/*  cree un nouvelle objet d'edition de texte multiligne                                */
/*                                                                                      */
/****************************************************************************************/

HWND NewObjEditText ( PtrObjText Txt , char * Text , HWND Parent , int Dialog )
{
int Flags ;
int Txt_Flags ;
int Ex_Flag = 0 ;

        Txt_Flags = Txt->Flags ;
        Flags = ES_MULTILINE | ES_WANTRETURN  ;
        if ( Parent != NULL ) Flags |= WS_CHILD  ;
        
        if ( Txt_Flags & ET_AHSCROLL ) Flags |= ES_AUTOHSCROLL ;
        if ( Txt_Flags & ET_AVSCROLL ) Flags |= ES_AUTOVSCROLL ;
        if ( Txt_Flags & ET_ALIGN_CENTER ) Flags |= ES_CENTER ;
        if ( Txt_Flags & ET_ALIGN_LEFT ) Flags |= ES_LEFT ;
        if ( Txt_Flags & ET_ALIGN_RIGHT ) Flags |= ES_RIGHT ;
        if ( Txt_Flags & ET_LOWERCASE ) Flags |= ES_LOWERCASE ;
        if ( Txt_Flags & ET_BORDER ) Flags |= WS_BORDER ;
        if ( Txt_Flags & ET_UPBORDER ) Flags |= WS_DLGFRAME ;
        if ( Txt_Flags & ET_HSCROLL ) Flags |= WS_HSCROLL ;
        if ( Txt_Flags & ET_VSCROLL ) Flags |= WS_VSCROLL ;
        if ( Txt_Flags & ET_TABFOCUS ) Flags |= WS_TABSTOP ;
        if ( Txt_Flags & ET_SIZEBOX ) Flags |= WS_SIZEBOX ;
        if ( Txt_Flags & ET_DOWN ) Ex_Flag |= WS_EX_CLIENTEDGE ;
        if ( Txt_Flags & ET_DRAGDROP ) Ex_Flag |= WS_EX_ACCEPTFILES ;
        if ( Txt_Flags & ET_NUMBER  ) Flags |= ES_NUMBER ;

        ReadyText ( Text ) ;
        return CreateWindowEx ( Ex_Flag ,
                        "Edit" ,
                        Text , Flags ,
                        Txt->PosX , Txt->PosY ,
                        Txt->TailleW , Txt->TailleH ,
                        Parent , NULL ,
                        (HINSTANCE)SCgetExtra("this_inst") , NULL ) ;
}



/****************************************************************************************/
/*                                                                                      */
/* HWND NewObjText ( PtrObjText Txt , char * Text , HWND Parent )                       */
/*                                                                                      */
/* creation d'un texte statique d'apres une description ( PtrObjText ) et un pointeur   */
/*  sur un texte ( char * Text )                                                        */
/*                                                                                      */
/****************************************************************************************/

HWND NewObjText ( PtrObjText Txt , char * Text , HWND Parent , int Dialog )
{
int Flags ;
int Txt_Flags ;
int Ex_Flag = 0 ;

        Txt_Flags = Txt->Flags ;        
        Flags = ES_MULTILINE | ES_READONLY | ES_WANTRETURN ;
        if ( Parent != NULL ) Flags |= WS_CHILD ;
        
        if (( Txt_Flags & ET_TABFOCUS ) && Dialog ) Flags |= WS_TABSTOP ;
        if ( Txt_Flags & ET_AHSCROLL ) Flags |= ES_AUTOHSCROLL ;
        if ( Txt_Flags & ET_AVSCROLL ) Flags |= ES_AUTOVSCROLL ;
        if ( Txt_Flags & ET_ALIGN_CENTER ) Flags |= ES_CENTER ;
        if ( Txt_Flags & ET_ALIGN_LEFT ) Flags |= ES_LEFT ;
        if ( Txt_Flags & ET_ALIGN_RIGHT ) Flags |= ES_RIGHT ;
        if ( Txt_Flags & ET_LOWERCASE ) Flags |= ES_LOWERCASE ;
        if ( Txt_Flags & ET_BORDER ) Flags |= WS_BORDER ;
        if ( Txt_Flags & ET_UPBORDER ) Flags |= WS_DLGFRAME ;
        if ( Txt_Flags & ET_HSCROLL ) Flags |= WS_HSCROLL ;
        if ( Txt_Flags & ET_VSCROLL ) Flags |= WS_VSCROLL ;
        if ( Txt_Flags & ET_SIZEBOX ) Flags |= WS_SIZEBOX ;
        if ( Txt_Flags & ET_DOWN ) Ex_Flag |= WS_EX_CLIENTEDGE ;
        if ( Txt_Flags & ET_DRAGDROP ) Ex_Flag |= WS_EX_ACCEPTFILES ;
        if ( Txt_Flags & ET_NUMBER ) Flags |= ES_NUMBER ;

        ReadyText ( Text ) ;
        
        return CreateWindowEx ( Ex_Flag ,
                        "Edit" ,
                        Text , Flags ,
                        Txt->PosX , Txt->PosY ,
                        Txt->TailleW , Txt->TailleH ,
                        Parent , NULL ,
                        (HINSTANCE)SCgetExtra("this_inst") , NULL ) ;
}
 


/****************************************************************************************/
/*                                                                                      */
/* void GetText ( HWND HW , char * Buffer )                                             */
/*                                                                                      */
/*  saisie la totalite du texte conten udans un objet texte                             */
/*                                                                                      */
/****************************************************************************************/

void GetText ( HWND HW , char * Buffer )
{
        int Ligne ;
        int i , t  ;
        

        Ligne = SendMessage ( HW , EM_GETLINECOUNT , 0 , 0 ) ;       

        if ( Ligne == 0 )
        {
           *( ( int * ) GBuf ) = MAX_TEXT ;
           t = SendMessage ( HW , EM_GETLINE , 0 ,  ( LPARAM ) GBuf ) ;
           GBuf [ t ] = 0 ;
		   strcpy(Buffer,GBuf); // modif 00/05/16
        }
        else
        { 
            * Buffer = 0 ;
            for ( i = 0 ; i < Ligne ; i ++ )
            {
                * ( ( int * ) GBuf ) = MAX_TEXT ;
                t = SendMessage ( HW , EM_GETLINE , i , ( LPARAM ) GBuf ) ;
                GBuf [ t ] = 0 ;
                if ( GBuf [ t -1 ] == '\n' && GBuf [ t-2 ] == '\r' ) GBuf [ t-2 ] = 0 ;
                strcat ( Buffer , GBuf ) ;
                if ( i < Ligne - 1) strcat ( Buffer , "\n" ) ;
            }            
 
        } 
}

/****************************************************************************************/
/*                                                                                      */
/*  int GetLinecount ( HWND h )                                                         */
/*                                                                                      */
/* retourne le nombre de ligne d'un objet texte                                         */
/*                                                                                      */
/****************************************************************************************/

int GetLineCount ( HWND h )
{
        return SendMessage ( h , EM_GETLINECOUNT , 0 , 0 ) ;
}

/****************************************************************************************/
/*                                                                                      */
/* void AddText ( HWND h , char * Text ) ;                                              */
/*                                                                                      */
/* ajoute du texte au texte existant dans un objet texte                                */
/*                                                                                      */
/****************************************************************************************/

void AddText ( HWND h , char * Text )
{
        
        GetText ( h , GBuf ) ;
        /*strcat ( GBuf , Text ) ;*/
        /*SetText ( h , FBuf2 ) ; */
        strcpy ( Text , GBuf ) ;
}


/****************************************************************************************/
/*                                                                                      */
/*  void SetText ( HWND HW , char * Texte )                                             */
/*                                                                                      */
/* remplace le texte existant d'une fenetre de texte                                    */
/*                                                                                      */
/****************************************************************************************/

void SetText ( HWND HW , char * Texte )
{
    ReadyText ( Texte ) ;
    SetWindowText ( HW , Texte ) ;
}





/****************************************************************************************/
/*                                                                                      */
/*   void GetLine ( HWND HW , char * Buffer , int Line )                                */
/*                                                                                      */
/*   recupere la neme ligne d'un texte                                                  */
/*                                                                                      */
/****************************************************************************************/

void GetLine ( HWND HW , char * Buffer , int Line  )
{
    int * First ;
    int Long , i ;

    First = ( int * ) Buffer ;
    * First = 256 ;

    Long = SendMessage ( HW , EM_GETLINE , Line , ( LPARAM ) ( LPCSTR ) Buffer ) ;
        
    Buffer [ Long ] = 0 ;
    strcpy ( GBuf,Buffer);
    i = 0 ; 
    Long = 0 ;
    while ( GBuf[i])
    {
        if ( GBuf[i]!= '\r') 
            Buffer[Long++] = GBuf [ i ] ;
        i ++ ;
    }

    Buffer [Long] = 0 ;

    
}

/****************************************************************************************/
/*                                                                                      */
/*  HWND NewObjEditLine ( PtrObjText Txt , char * Text , HWND Parent )                  */
/*                                                                                      */
/*  Cree une fenetre d'edition d'une simple ligne de texte                              */
/*                                                                                      */
/****************************************************************************************/
   
HWND NewObjEditLine ( PtrObjText Txt , char * Text , HWND Parent , int Dialog )
{
int Flags ;
int Txt_Flags ;
int Ex_Flag = 0 ;

        Txt_Flags = Txt->Flags ;
        Flags = 0 ;
        if ( Parent != NULL ) Flags |= WS_CHILD ;
        
        if ( Txt_Flags & ET_AHSCROLL        ) Flags |= ES_AUTOHSCROLL   ;
        if ( Txt_Flags & ET_ALIGN_CENTER    ) Flags |= ES_CENTER        ;
        if ( Txt_Flags & ET_ALIGN_LEFT      ) Flags |= ES_LEFT          ;
        if ( Txt_Flags & ET_LOWERCASE       ) Flags |= ES_LOWERCASE     ;
        if ( Txt_Flags & ET_BORDER          ) Flags |= WS_BORDER        ;
        if ( Txt_Flags & ET_UPBORDER        ) Flags |= WS_DLGFRAME      ;
        if ( Txt_Flags & ET_HSCROLL         ) Flags |= WS_HSCROLL       ;
        if ( Txt_Flags & ET_TABFOCUS        ) Flags |= WS_TABSTOP       ;
        if ( Txt_Flags & ET_PASSWORD        ) Flags |= ES_PASSWORD      ;
        if (( Txt->Flags & ET_TABFOCUS ) && Dialog ) Flags |= WS_TABSTOP       ;
        if ( Txt->Flags & ET_DOWN           ) Ex_Flag |= WS_EX_CLIENTEDGE ;
        if ( Txt->Flags & ET_DRAGDROP       ) Ex_Flag |= WS_EX_ACCEPTFILES ;
        if ( Txt->Flags & ET_NUMBER         ) Flags |= ES_NUMBER         ;

         return CreateWindowEx ( Ex_Flag ,
                        "Edit" ,
                        Text , Flags ,
                        Txt->PosX , Txt->PosY ,
                        Txt->TailleW , Txt->TailleH ,
                        Parent , NULL ,
                        (HINSTANCE)SCgetExtra("this_inst") , NULL ) ;
}









/*****************************************************************************/
/*                                                                           */
/*  fonction int GRCreateText ( mmachine m )                                 */
/*                                                                           */
/*  Cette fonction C correcpond a la fonction magma                          */
/*  Obj _create_text ( Obj Parent , int PosX , int PosY , int TailleW ,      */
/*     int TailleH , int Flags , int MHandler , char * Texte ) ;             */
/*  laquelle cree une fenetre de texte formatée statique                     */
/*                                                                           */
/*****************************************************************************/

int GRCreateText ( mmachine m )
{
int s,l,dummy,s2,res;
int dialog = 0 ;
PtrObjVoid O , OP ;
PtrObjText Txt ;
PtrObjWindow PW ;
HWND Parent , HW ;
char TEXT [ MAX_TEXT ] ;
char * Tst ;

    /******************************* DEBUG 2D *******************************/   
    #ifdef TRACE2D
           MMechostr (1,"DBG _create_text\n");
           FDebug2D ( m ) ;
    #endif
    /************************************************************************/
    

    /* test channel NIL */
    if (MMget(m,7)==NIL)
    {
        MMechostr(MSKDEBUG,"_CRtext : channel NIL\n");
        m->pp+=7;
        return 0;
    }

    /* test parent NIL */
    if ( MMget(m,6)==NIL)
    {
        MMechostr(MSKDEBUG,"_CRtext : parent NIL\n");
        m->pp+=7;
        MMset(m,0,NIL);
        return 0;
    }

    dummy       = MMpull(m)  ;
    
    /* test de la taille du texte */
    if ( dummy == NIL ) strcpy ( TEXT , "" ) ;
    else
    {
        Tst = ( char * ) MMstart(m,(dummy >> 1) + 1) ; 
        if ( strlen ( Tst ) >= MAX_TEXT )
        {
            MMechostr ( 1 , "String too long\n" ) ;
            strcpy ( TEXT , "" ) ;
        } else strcpy ( TEXT ,  Tst ) ;
    }

    if ( Mpushstrbloc ( m , TEXT )) return MERRMEM ;

    /* creation de la zone memoire de l'objet general */
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL )
    {
                MMechostr(MSKDEBUG,"_create_text : Can't Alloc MAGMA Memory\n" ) ;             
                return MERRMEM ;
    }    
    if ( MMpush(m,(s<<1)+1)) return MERRMEM;
    /* on rempile l'addresse au cas ou il y aurait un GC par la suite */

    /* creation de la zone memoire pour les donnees relatives aux objets textes */
    l = ( sizeof ( struct ObjText ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL )
    {
                MMechostr(MSKDEBUG,"_create_text : Can't alloc MAGMA Memory\n" ) ;              
                return MERRMEM ;
    }


    Txt = ( PtrObjText ) MMstart(m, s2 ) ;
    s = MMpull (m ) ; /* recupere l'addresse de l'objet de base */    
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    O -> Tab = MMpull(m) ; /* recupere le pointeur sur la chaine de caractere du texte */

    O->Type     = OBJ_TYPE_TEXT << 1 ;   
    Txt -> Flags          = MMpull(m) >> 1 ;
    Txt -> TailleH        = MMpull(m) >> 1 ;
    Txt -> TailleW        = MMpull(m) >> 1 ;
    Txt -> PosY           = MMpull(m) >> 1 ;
    Txt -> PosX           = MMpull(m) >> 1 ;
    O -> Father           = MMpull(m) ;
    O -> Buffer           = ( s2 << 1 ) + 1 ;

    /* recuperation du handler window du parent, si parent il y a */
    if ( O -> Father == NIL ) Parent = NULL ;
    else
    {
        OP = ( PtrObjVoid ) MMstart(m, (O->Father>>1) ) ;
        /* on verifie que le pere est bien du type fenetre */
        if ( OP->Type != OBJ_TYPE_WINDOW << 1 )
        {               
                MMechostr ( 1 , "_create_text Parent of a text object must be a window\n" );
                MMset(m,0,NIL) ;
                return 0;
        } 
        
        PW = ( PtrObjWindow ) MMstart(m, (OP->Buffer>>1) ) ;           
        if ( PW->Flags & WN_DIALOG ) dialog = 1 ;
        Parent = PW->WHandler;
    }   
    
    HW = NewObjText ( Txt , TEXT , Parent , dialog ) ;    
    if ( ! HW )
    {
        MMechostr (1,"_create_text : Error in creating the WIN95 Object - Check the values\n" ) ;
        MMset(m,0,NIL) ;
        return 0;
    }
    Txt->WHandler = HW ;

    if ( TextProc == NULL ) TextProc = ( WNDPROC ) GetWindowLong ( HW , GWL_WNDPROC ) ;
    /*if (Txt->Flags & ET_TRANSPARENT )
          SetWindowLong ( HW , GWL_WNDPROC , ( long ) TextProc2 ) ;*/
/*    else*/ SetWindowLong ( HW , GWL_WNDPROC , ( long ) TextProc3 ) ;

    if ( DefaultFont != NULL ) 
      SendMessage ( HW , WM_SETFONT , ( WPARAM ) DefaultFont , ( LPARAM ) TRUE ) ;      

    if ( Txt->Flags & ET_HIDDEN ) ShowWindow ( HW , SW_HIDE ) ;
    else ShowWindow(HW,SW_SHOW);
    UpdateWindow(HW);    

    if (MMpush ( m , s )) return MERRMEM  ;
    res = OBJcreate(m,OBJTYPTEXT,(int)HW,OBJTYPWINDOW,(int)Parent) ;

    /************************* DEBUG 2D *****************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _create_text done\n" ) ;
    #endif
    /*****************************************************************************/

    return res ;
       
}

/*****************************************************************************/
/*                                                                           */
/*  fonction int GRSetText ( mmachine m ) ;                                  */
/*                                                                           */
/*   cette fonction C correspond a la fonction magma                         */
/*   Obj _set_test ( Obj objet , S texte )                                   */
/*   laquelle remplace le texte existant d'un objet de type TEXT , EDIT_LINE */
/*   ou EDIT_TEXT par un nouveau texte                                       */
/*                                                                           */
/*****************************************************************************/

int GRSetText ( mmachine m )
{
    int s , st , res ;
    PtrObjVoid O ;
    PtrObjWindow OP ;
    int Type ;
    char TEXT [MAX_TEXT] ;
    char * Tst ;

    /*************************** DEBUG 2D *************************************/
    #ifdef TRACE2D
        MMechostr ( 1,"DEBUG _set_text.\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /***************************************************************************/
    
    s = MMpull(m);
    if ( s == NIL ) strcpy ( TEXT , "" ) ;
    else
    {
        Tst = ( char * ) MMstart(m,(s >> 1) + 1) ; 
        if ( strlen ( Tst ) >= MAX_TEXT )
        {
            MMechostr ( 1 , "String too long in _set_text\n" ) ;
            return 0 ; 
        } else strcpy ( TEXT ,  Tst ) ;
    }

    s = MMpull(m);
    if ( s == NIL ) return MMpush(m,NIL );
    O = ( PtrObjVoid ) MMstart(m, ( s >> 1 ) ) ;
    Type = O->Type >> 1 ;

    if (( Type != OBJ_TYPE_TEXT ) && ( Type != OBJ_TYPE_EDIT_TEXT ) 
          && ( Type != OBJ_TYPE_EDIT_LINE ) && ( Type != OBJ_TYPE_RICH_TEXT ))
    {
        MMechostr ( 1 , "SetTExt : Object must be a Text Object ( static text , edition of line or edition of text )\n" ) ;
        return MMpush(m,s) ;
    }
    
    if ( Type == OBJ_TYPE_TEXT )
    {
        if ( MMpush(m,s)) return MERRMEM ;
        if ( Mpushstrbloc(m,TEXT)) return MERRMEM ;
        st = MMpull(m);
        s = MMpull(m) ;
        O = ( PtrObjVoid ) MMstart(m, ( s >> 1 ) ) ;        
        O->Tab = st ;
    }
        
    OP = ( PtrObjWindow ) MMstart(m, ( O->Buffer >> 1 ) ) ;   
    SetText ( OP->WHandler ,TEXT ) ;
    res = MMpush (m,s) ;

    /*********************************** DEBUG 2D ***************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _set_text done\n" ) ;
    #endif
    /************************************************************************/

    return res ;
}


/*****************************************************************************/
/*                                                                           */
/*  fonction  int GRGetLine ( mmachine m ) ;                                 */
/*                                                                           */
/*  cette fonction C correspond a la fonction magma                          */
/*  S get_line ( Obj objet , I ligne )                                       */
/*  laquelle retourne une ligne provenant d'un objet texte                   */
/*  la premiere ligne etant toujours la 0. L'argument ligne est sans         */
/*  effet si sur un objet EDIT_LINE                                          */
/*                                                                           */
/*****************************************************************************/

int GRGetLine ( mmachine m )
{
        int s , l , res ;
        PtrObjVoid O ;
        PtrObjWindow OP ;
        char TEXT [ MAX_TEXT ] ;
        
        /******************** DEBUG 2D ***************************************/
        #ifdef TRACE2D
                MMechostr ( 1,"DBG _get_line\n" ) ;
                FDebug2D ( m ) ;
        #endif
        /*********************************************************************/

        l = MMpull(m) >> 1 ;
        s = MMpull(m);
        if ( s == NIL )
        {
            MMechostr ( 1 , "_get_line : Object is NIL\n" ) ;
            return MMpush(m,NIL) ;
        }
        O = ( PtrObjVoid ) MMstart(m, ( s >> 1 ) ) ;          
                   
        OP = ( PtrObjWindow ) MMstart(m, (O->Buffer >> 1 ) ) ;        
        GetLine ( OP->WHandler , TEXT , l ) ;
        l = strlen ( TEXT ) ;
        MMechostr ( 1,"getline last char : %d %d\n",TEXT[l-2],TEXT[l-1]);
        res = Mpushstrbloc ( m , TEXT ) ; 

        /***************************** DEBUG 2D **********************************/
        #ifdef TRACE2D
            FDebug2D ( m ) ;
            MMechostr ( 1 , "_get_line done = %s\n" , TEXT ) ;
        #endif
        /****************************************************************************/
        return res ;
                
}        

/*****************************************************************************/
/*                                                                           */
/*   fonction int GRCreateEditLine ( mmachine m ) ;                          */
/*                                                                           */
/*   Cette fonction C correspond a la fonction magma                         */
/*   Obj _create_edit_line ( Obj Parent , int PosX , int PosY , int TailleW ,*/
/*      int TailleH , int Flags , int MHandler , char * Texte )              */
/*   laquelle cree une fenetre d'edition/saisie de texte dont on fournit     */
/*   le texte initial                                                        */
/*                                                                           */
/*****************************************************************************/    

int GRCreateEditLine ( mmachine m )
{
int s,l,dummy,s2,res;
int dialog=0;
PtrObjVoid O , OP ;
PtrObjText Txt ;
PtrObjWindow PW ;
HWND Parent , HW ;
char TEXT [ MAX_TEXT ] ;
char * Tst ;
    
   /****************************** DEBUG 2D ********************************/
   #ifdef TRACE2D
          MMechostr (1,"DEBUG CreateEditLine\n" ) ;
          FDebug2D ( m ) ;
   #endif
    /************************************************************************/

    /* test channel NIL */
    if (MMget(m,7)==NIL)
    {
        MMechostr(MSKDEBUG,"_CReditLine : channel NIL\n");
        m->pp+=7;
        return 0;
    }

    /* test parent NIL */
    if ( MMget(m,6)==NIL)
    {
        MMechostr(MSKDEBUG,"_CReditLine : parent NIL\n");
        m->pp+=7;
        MMset(m,0,NIL);
        return 0;
    }
          
    dummy       = MMpull(m)  ;
    /* Ici ajouter avant le strcpy un test sur la taille du texte envoye    */
    /* test de la taille du texte */
    if ( dummy == NIL ) strcpy ( TEXT , "" ) ;
    else
    {
        Tst = ( char * ) MMstart(m,(dummy >> 1) + +1) ; 
        if ( strlen ( Tst ) >= MAX_TEXT )
        {
            MMechostr ( 1 , "String too long\n" ) ;
            strcpy ( TEXT , "" ) ;
        } else strcpy ( TEXT ,  Tst ) ;
    }
   
 

    /* creation de la zone memoire de l'objet general */
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL )
    {
        MMechostr(MSKDEBUG,"_create_edit_line : Error in alloc MAGMA Memory\n" ) ;
        return MERRMEM ;
    }
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    /* on rempile l'addresse au cas ou il y aurait un GC par la suite */

    /* creation de la zone memoire pour les donnees relatives aux objets textes */
    l = ( sizeof ( struct ObjText ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL )
   {
        MMechostr(MSKDEBUG,"_create_edit_line : Error in Alloc MAGMA Memory\n" ) ;
        return MERRMEM ;
   }


    Txt = ( PtrObjText ) MMstart(m, s2 ) ;
    s = MMpull (m ) ; /* recupere l'addresse de l'objet de base */
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;

    O->Type               = OBJ_TYPE_EDIT_LINE << 1 ;   
    Txt -> Flags          = MMpull(m) >> 1 ;
    Txt -> TailleH        = MMpull(m) >> 1 ;
    Txt -> TailleW        = MMpull(m) >> 1 ;
    Txt -> PosY           = MMpull(m) >> 1 ;
    Txt -> PosX           = MMpull(m) >> 1 ;
    O -> Father           = MMpull(m) ;
    O -> Buffer           = ( s2 << 1 ) + 1 ;
    O -> Tab              = NIL ;

    /* recuperation du handler window du parent, si parent il y a */
    if ( O -> Father == NIL ) Parent = NULL ;
    else
    {
        OP = ( PtrObjVoid ) MMstart(m, (O->Father>>1) ) ;
        if ( OP->Type != OBJ_TYPE_WINDOW << 1 )
        {
            MMechostr (1,"Parent of a Edit Line must be a window\n" ) ;
			MMpull(m);
            return MMpush(m,NIL)  ;
        }
        PW = ( PtrObjWindow ) MMstart(m, (OP->Buffer>>1)) ;
        if ( PW->Flags & WN_DIALOG ) dialog = 1 ;
        Parent = PW->WHandler ;
    }
    

    HW = NewObjEditLine ( Txt , TEXT , Parent , dialog ) ;    
    if ( ! HW )
    {
        MMechostr(MSKDEBUG,"_create_edit_line : Error in creating the WIN Object - Check the values\n" ) ;
		MMpull(m);
        return MMpush(m,NIL) ;
    }
    Txt->WHandler = HW ;

    if ( TextProc == NULL ) TextProc = ( WNDPROC ) GetWindowLong ( HW , GWL_WNDPROC ) ;
/*    if (Txt->Flags & ET_TRANSPARENT ) SetWindowLong ( HW , GWL_WNDPROC , ( long ) TextProc2 ) ;*/
/*    else*/ SetWindowLong (HW , GWL_WNDPROC , ( long ) TextProc3 ) ;

    if ( DefaultFont != NULL ) 
      SendMessage ( HW , WM_SETFONT , ( WPARAM ) DefaultFont , ( LPARAM ) TRUE ) ;      

    if ( Txt->Flags & ET_HIDDEN ) ShowWindow ( HW , SW_HIDE ) ;
    else ShowWindow(HW,SW_SHOW);
    UpdateWindow(HW);  
  
    MMpush ( m , s ) ;
    res = OBJcreate (m,OBJTYPTEXT,(int)HW,OBJTYPWINDOW,(int)Parent) ;

    /********************************* DEBUG 2D *******************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG 2D _create_edit_line Done\n" ) ;
    #endif
    /**************************************************************************/

    return res ;
}

/*****************************************************************************/
/*                                                                           */
/* fonction int GRCreateEditText ( mmachine m ) ;                            */
/*                                                                           */
/* cette fonction C correspond a la fonction magma                           */
/* Obj _create_edit_text ( Obj objet , int posX , int PosY , int TailleW ,   */
/*     int TailleH , int Flags ,int MHandler , char * Texte ) ;              */
/*  laquelle cree une fenetre de texte editable dont on indique le texte     */
/*   initiale                                                                */
/*****************************************************************************/


int GRCreateEditText ( mmachine m )
{
int s,l,dummy,s2,res;
int dialog = 0 ;
PtrObjVoid O , OP ;
PtrObjText Txt ;
PtrObjWindow PW ;
HWND Parent , HW ;
char TEXT [ MAX_TEXT ] ;
char * Tst ;
    
    /******************************* DEBUG 2D ****************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _create_edit_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /*********************************************************************/
    /* test channel NIL */
    if (MMget(m,7)==NIL)
    {
        MMechostr(MSKDEBUG,"_CReditText : channel NIL\n");
        m->pp+=7;
        return 0;
    }

    /* test parent NIL */
    if ( MMget(m,6)==NIL)
    {
        MMechostr(MSKDEBUG,"_CReditText : parent NIL\n");
        m->pp+=7;
        MMset(m,0,NIL);
        return 0;
    }
   
    dummy       = MMpull(m)  ;
    /* Ici ajouter avant le strcpy un test sur la taille du texte envoye    */
    /* test de la taille du texte */
    if ( dummy == NIL ) strcpy ( TEXT , "" ) ;
    else
    {
        Tst = ( char * ) MMstart(m,(dummy >> 1) + +1) ; 
        if ( strlen ( Tst ) >= MAX_TEXT )
        {
            MMechostr ( 1 , "String too long\n" ) ;
            strcpy ( TEXT , "" ) ;
        } else strcpy ( TEXT ,  Tst ) ;
    }


    /* creation de la zone memoire de l'objet general */
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL )
    {
        MMechostr(MSKDEBUG,"_create_edit_text : Error in alloc MAGMA Memory\n" ) ;         
        return MERRMEM ;
    }    
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    /* on rempile l'addresse au cas ou il y aurait un GC par la suite */

    /* creation de la zone memoire pour les donnees relatives aux objets textes */
    l = ( sizeof ( struct ObjText ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL )
    {
        MMechostr(MSKDEBUG,"_create_edit_text : Error in alloc MAGMA Memory\n" ) ;
        return MERRMEM ;
    }


    Txt = ( PtrObjText ) MMstart(m, s2 ) ;
    s = MMpull (m ) ; /* recupere l'addresse de l'objet de base */
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;

    O->Type     = OBJ_TYPE_EDIT_TEXT << 1 ;   
    Txt -> Flags          = MMpull(m) >> 1 ;
    Txt -> TailleH        = MMpull(m) >> 1 ;
    Txt -> TailleW        = MMpull(m) >> 1 ;
    Txt -> PosY           = MMpull(m) >> 1 ;
    Txt -> PosX           = MMpull(m) >> 1 ;
    O -> Father           = MMpull(m) ;  
    O -> Buffer           = ( s2 << 1 ) + 1 ;
    O -> Tab              = NIL ;

    /* recuperation du handler window du parent, si parent il y a */
    if ( O -> Father == NIL ) Parent = NULL ;
    else
    {
        OP = ( PtrObjVoid ) MMstart(m, (O->Father>>1) ) ;
        if ( OP->Type != OBJ_TYPE_WINDOW << 1 )
        {
            MMechostr ( 1,"CreateEditText : Parent must be a window\n" ) ;
            MMpull(m);
			return MMpush(m,NIL) ;
        }
        PW = ( PtrObjWindow ) MMstart(m, (OP->Buffer >> 1 ) ) ;
        if ( PW->Flags & WN_DIALOG ) dialog = 1 ;
        Parent = PW->WHandler ;
    }

    HW = NewObjEditText ( Txt , TEXT , Parent , dialog ) ;    
    if ( ! HW )

    {
        MMechostr(MSKDEBUG,"_create_edit_text : Error in creating the WIN Obj - Check the values\n" ) ;
        MMpull(m);
        return MMpush(m,NIL) ;
    }
    Txt->WHandler = HW ;

    
    if ( TextProc == NULL ) TextProc = ( WNDPROC ) GetWindowLong ( HW , GWL_WNDPROC ) ;
    /*if (Txt->Flags & ET_TRANSPARENT )  SetWindowLong ( HW , GWL_WNDPROC , ( long )TextProc2 ) ;*/
    /*else*/ SetWindowLong ( HW , GWL_WNDPROC , ( long ) TextProc3 ) ;
    
    if ( DefaultFont != NULL ) 
      SendMessage ( HW , WM_SETFONT , ( WPARAM ) DefaultFont , ( LPARAM ) TRUE ) ;      

    if ( Txt->Flags & ET_HIDDEN )
    {
        ShowWindow ( HW , SW_HIDE ) ; 
        MMechostr ( 1 , "Fenetre texte Hidden\n" ) ;
    }


    else ShowWindow(HW,SW_SHOW);
    UpdateWindow(HW);  
     MMpush(m,s) ;
    res = OBJcreate(m,OBJTYPTEXT,(int)HW,OBJTYPWINDOW,(int)Parent) ;


    /********************************** DEBUG 2D *********************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr( 1 , "DBG _create_edit_text\n" ) ;
    #endif
    /*****************************************************************************/
    return res ;       
}

/*****************************************************************************/
/*                                                                           */
/* fonction int GRGetText ( mmachine m )                                     */
/*                                                                           */
/*  Cette fonction C correspond a la fonction magma S _get_text ( Obj ) ;    */
/*  laquelle renvoi le texte contenu dans un objet texte                     */
/*                                                                           */
/*****************************************************************************/


int GRGetText ( mmachine m )
{
    PtrObjVoid O ;
    PtrObjText Txt ;
    int Type , res , s ;
    char TEXT [MAX_TEXT ] ;    

    /**************************DEBUG 2D****************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _get_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**************************************************************************/

    s = MMpull(m) ;
    if ( s == NIL )
    {
        MMechostr ( 1 , "Object is NIL\n" ) ;
        return MMpush(m,NIL) ;
    }
    O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;
    Type = O->Type >> 1 ;

    if ( Type == OBJ_TYPE_TEXT )
    {
        strcpy ( TEXT , (char *)MMstart(m,(O->Tab>>1) +1)) ;
        res = Mpushstrbloc(m,TEXT) ;
        /******************** DEBUG 2D ******************************************/
        #ifdef TRACE2D
            FDebug2D ( m ) ;
            MMechostr ( 1 , "_get_text done\n" ) ;
        #endif
        /************************************************************************/
        return res ;
    }
    
    
    if (( Type != OBJ_TYPE_EDIT_LINE ) && ( Type != OBJ_TYPE_EDIT_TEXT ) && ( Type != OBJ_TYPE_RICH_TEXT ))
    {
        MMechostr ( 1 , "_get_text : Obj isn't a TEXT , EDIT_LINE or EDIT_TEXT Object\n" ) ;
        return MMpush(m,NIL) ;
    }

    Txt = ( PtrObjText ) MMstart(m, ( O->Buffer >> 1 ) )  ;
    GetText ( Txt->WHandler , TEXT ) ;

    
    res = Mpushstrbloc ( m , TEXT ) ;

    /*****************************DEBUG 2D**************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _get_text = %s\n" , TEXT ) ;
    #endif
    /***************************************************************************/
    return res ;
}    

/*****************************************************************************/
/*                                                                           */
/*  fonction int GRGetLineCount ( mmachine m )                               */
/*                                                                           */
/*  correspond a la fonction magma int _get_linecount ( Obj ) ;              */
/*  qui renvoi le nombre de ligne d'un objet texte                           */
/*                                                                           */
/*****************************************************************************/

int GRGetLineCount ( mmachine m )
{
        PtrObjVoid O ;
        PtrObjText Txt ;
        int Type , res , s ;

        /*******************DEBUG 2D*******************************************/
        #ifdef TRACE2D
            MMechostr ( 1 , "DBG _get_linecount\n" ) ;
            FDebug2D ( m ) ;
        #endif
        /**********************************************************************/
        s = MMpull(m) ;
        if ( s == NIL )
        {
            MMechostr ( 1 , "_get_linecount : Object is NIL\n" ) ;
            return MMpush(m,(-1)<<1) ;
        }

        O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;
        Type = O->Type >> 1 ;

        if (( Type != OBJ_TYPE_TEXT ) && ( Type != OBJ_TYPE_EDIT_TEXT ))                                        
        {
            MMechostr ( 1 , "_get_linecount ; Object is't a TEXT or EDIT_TEXT Object\n" ) ;
            return MMpush(m,(-1)<<1) ;
        }

        Txt = ( PtrObjText ) MMstart(m, ( O->Buffer >> 1 ) )  ;
        res = MMpush(m,GetLineCount ( Txt->WHandler ) << 1) ;      

        /**************************DEBUG 2D*************************************/
        #ifdef TRACE2D
            FDebug2D ( m ) ;
            MMechostr (1 , "DBG _get_linecount done\n" ) ;
        #endif
        /************************************************************************/
        return res ;       
}


/*****************************************************************************/
/*                                                                           */
/* function int GRAddText ( mmachine m ) ;                                   */
/*                                                                           */
/* cette fonction correspodn a la fonction magma Obj _add_text ( Obj , S )   */
/*                                                                           */
/*****************************************************************************/

int GRAddText ( mmachine m )
{
    PtrObjVoid O ;
    PtrObjText T ;
    int Type ;
    int s , st , res ;
    char * St ;
    char BUF [ 33000 ] ;
    HWND HW ;

    /****************** DEBUG 2D *********************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _add_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /*************************************************************************/

    s = MMpull ( m ) ;
    if ( s == NIL ) return 0 ;
    St = ( char * ) MMstart(m, (s>>1)+ 1) ;
    s = MMpull(m) ; 

    if( s == NIL )
    {
        MMechostr ( 1 , "_add_text : Object is NIL\n" ) ;
        return MMpush(m,NIL) ;
    }
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;    

    Type = O->Type >> 1 ;
    T = ( PtrObjText ) MMstart(m, ( O->Buffer>>1 ) ) ;
    HW = T->WHandler ;
    
    if ( Type == OBJ_TYPE_TEXT )
    {
           
        strcpy ( BUF , ( char * )MMstart(m,(O->Tab>>1) +1)) ;
        if ( strlen ( BUF ) + 1 + strlen ( St )  < MAX_TEXT - 2 )
            strcat ( BUF , St ) ;
        else MMechostr ( 1 , "_add_text : String too long\n" ) ;

        MMpush(m,s);
        if ( Mpushstrbloc(m,BUF))
        {
            MMechostr ( 1 , "_add_text : Mpushstrblox failed sur %s\n" , BUF ) ;
            return MERRMEM ;
        }              
        st = MMpull(m);
        s = MMpull(m) ;
        O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;
        O->Tab = st ;               
        SetText ( HW  , BUF ) ;        
    } else if ( Type == OBJ_TYPE_EDIT_TEXT )
    {
        GetText ( HW , BUF ) ;
        strcat ( BUF,St);
        SetText (HW,BUF);

    }
      
    else MMechostr ( 1 , "Can't add text on an item of type %d" , Type ) ;    
    res = MMpush(m,s) ;

    /*********************** DEBUG 2D ******************************************/
    #ifdef TRACE2D
        FDebug2D(m) ;
        MMechostr ( 1 , "DBG _add_text done\n" ) ;
    #endif
    /***************************************************************************/

    return res ;
}    

/********************************************************************************/
/*                                                                              */
/*  int GRDelTextLine ( mmachine m )                                            */
/*                                                                              */
/* correspond a la fonction magma Obj _del_text_line ( Obj , I ) ;              */
/*                                                                              */
/********************************************************************************/

int GRDelTextLine ( mmachine m )
{
    int s , l , ps , pd , la , st , res ;
    PtrObjVoid O ;
    PtrObjText T ;
    HWND HW ;
    char BUF [33000] ;
    char BUF2 [ 33000 ] ;

     /************************** DEBUG 2D *****************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _del_text_line\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /******************************************************************************/


    l = MMpull(m) >> 1 ;
    s = MMpull(m) ;

    if ( l < 0 )
    {
        MMechostr ( 1 , "DelTextLine : line number must be >=0 \n" ) ;
        return MMpush(m,s) ;
    }

    if ( s == NIL )
    {
        MMechostr ( 1 , "DelTextLine : Text Object is NIL\n" ) ;
        return MMpush(m,NIL) ;
    }

    O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;
    if (( O->Type == OBJ_TYPE_TEXT << 1 ) || ( O->Type == OBJ_TYPE_EDIT_TEXT << 1 ))
    {
        T = ( PtrObjText ) MMstart(m, (O->Buffer>>1) ) ;        
        if ( O->Type == OBJ_TYPE_EDIT_TEXT << 1 ) GetText ( T->WHandler , BUF ) ;
        else strcpy ( BUF , ( char * ) MMstart(m, (O->Tab>>1) +1) ) ;
        HW = T->WHandler ;
        
        BUF2 [ 0 ] = 0 ;
        la = 0 ;
        ps = 0 ;
        pd = 0 ;
        while ( BUF [ ps ] )
        {
            
            if ( l != la ) BUF2 [ pd ++ ] = BUF [ ps ] ;
            if ( BUF [ ps ] == '\n' ) la ++ ;
            ps ++ ;                                   
        }
        BUF2 [ pd ] = 0 ;

        if ( O->Type == OBJ_TYPE_TEXT << 1 )
        {
            if ( MMpush(m,s) ) return MERRMEM ;
            if ( Mpushstrbloc ( m , BUF2 ) ) return MERRMEM ;
            st = MMpull(m) ;
            s = MMpull(m) ;
            O = ( PtrObjVoid ) MMstart(m, ( s >> 1 ) ) ;
            O->Tab = st ;
        }
       SetText ( HW , BUF2 ) ;
    }
    else MMechostr ( 1 , "DelTextLine : Parameter object must be a static text or an edit text\n" ) ;
     
    res = MMpush(m,s) ;

    /*********************************** DEBUG 2D ************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _del_text_line done\n" ) ;
    #endif
    /*********************************************************************************/
    return res ;
}




/**********************************************************************************************/
/*                                                                                            */
/*  int GRScrollText ( mmachine m )                                                           */
/*                                                                                            */
/*   correspond a la fonction magma Obj _scroll_text ( Obj , I , I )                          */
/*                                                                                            */
/**********************************************************************************************/


int GRScrollText ( mmachine m )
{
    int x , y , s , res ;
    PtrObjVoid  O;
    PtrObjText T ;
    POINT P ;
   

    /***************************** DEBUG 2D ********************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _scroll_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /************************************************************************/

    y = MMpull(m) >> 1 ;
    x = MMpull(m) >> 1 ;
    s = MMpull(m) ;

    if ( s == NIL ) return MMpush(m,NIL) ;

    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    if (( O->Type == OBJ_TYPE_TEXT << 1 ) || ( O->Type == OBJ_TYPE_EDIT_TEXT << 1 ))
    {
        T = ( PtrObjText ) MMstart(m,(O->Buffer>>1)) ;
        SendMessage ( T->WHandler , EM_LINESCROLL , x , y ) ;
    }
    else if    (O->Type == OBJ_TYPE_RICH_TEXT << 1 )
    {
        T = ( PtrObjText ) MMstart(m, (O->Buffer>>1) ) ;
        
        // Version qui fonctionne dans Cryopolis
        res = SendMessage ( T->WHandler , EM_LINEINDEX , y , 0 ) ;
        SendMessage ( T->WHandler , EM_POSFROMCHAR , (WPARAM ) &P, res ) ;
        SendMessage ( T->WHandler , EM_SETSEL , res + x , res + x ) ;
        SendMessage ( T->WHandler ,  EM_SCROLLCARET , 0 , 0 ) ;
        
        /* Version pour Francisco pour le Debugger */
        //SendMessage ( T->WHandler , EM_LINESCROLL , x , y - SendMessage ( T->WHandler , EM_GETFIRSTVISIBLELINE , 0 , 0 )) ;
        
    }

    else MMechostr ( 1 , "ScrollText : Object must be a text edit or a static text\n" ) ;
    res = MMpush(m,s) ;

    /******************* DEBUG 2D **********************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr( 1 , "_scroll_text_ done\n" ) ;
    #endif
    /****************************************************************/
    return res ;
}

/*********************************************************************/
/*                                                                   */
/* int GRPaintObjText ( mmachine m ) ;                               */
/*                                                                   */
/* correspond a la fonction magma ObjText _paint_obj_text (ObjText)  */
/* laquelle repaint un objet texte                                   */
/*                                                                   */
/*********************************************************************/

int GRPaintObjText ( mmachine m )
{
    int s ;
    PtrObjVoid O ;
    PtrObjText T ;    

    /******************************* DEBUG 2D ************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _paint_obj_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /******************************************************************/

    s = MMpull(m) ;
    if ( s == NIL ) return MMpush(m,NIL ) ;

    O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;
    T = ( PtrObjText ) MMstart(m, (O->Buffer>>1)) ;
    InvalidateRect ( T->WHandler , NULL , TRUE ) ;
    SendMessage ( T->WHandler , WM_PAINT , 0 , 0 ) ;
    

    s = MMpush(m,s) ;

    /************************ DEBUG 2D ***********************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _paint_obj_text done\n" ) ;
    #endif
    /*********************************************************************/

    return s ;
}

/******************************************************************************/
/*                                                                            */
/* int GRReflexTextEvent ( mmachine m ) ;                                     */
/*                                                                            */
/* correspond a la fonction magma ObjText  _reflex_text_event (ObjText,Fun,u0)*/
/* laquelle definit le callback pour un evenement texte                       */
/*                                                                            */
/******************************************************************************/

int GRReflexTextEvent ( mmachine m )
{   
    return OBJaddreflex(m,OBJTYPTEXT,RFLTEXT_EVENT);
}

int GRReflexTextMove ( mmachine m )
{    
    return OBJaddreflex(m,OBJTYPTEXT,RFLTEXT_MOVE);
}

int GRReflexTextSize ( mmachine m ) 
{
    return OBJaddreflex(m,OBJTYPTEXT,RFLTEXT_SIZE);
}

int GRReflexLineOk ( mmachine m )
{   
    return OBJaddreflex(m,OBJTYPTEXT,RFLTEXT_LINEOK);
}


int GRReflexTextDropFile ( mmachine m )
{
    return OBJaddreflex(m,OBJTYPTEXT,RFLTEXT_DROPFILE);
}
/**************************************************************************/
/*                                                                        */
/* int GRDestroyObjText ( mmachine m ) ;                                  */
/*                                                                        */
/* correspond a la fonction magma I _destroy_obj_text ( ObjText )         */
/* laquelle detruit un objet texte                                        */
/*                                                                        */
/**************************************************************************/

int GRDestroyObjText ( mmachine m ) 
{
    int s ; 
    PtrObjVoid O ;
    HWND h ;

    /********************* DEBUG 2D ****************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _destroy_obj_text\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /***********************************************************/

    s = MMget(m,0) ;
    if ( s != NIL )
    {
        O = (PtrObjVoid ) MMstart(m,(s>>1) ) ;
        h = (( PtrObjText) (MMstart(m, ( O->Buffer >> 1) ) )) -> WHandler ;
        OBJdelTH (m,OBJTYPTEXT,(int)h);
    }
    MMset(m,0,0) ;

    /********************** DEBUG 2D ***************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _destroy_obj_text done\n" ) ;
    #endif
    /**********************************************************/

    return 0 ;
}
    

/********************************************************************************/
/*                                                                              */
/*      int GRGetFirstVisibleLine ( mmachine m ) ;                              */
/*                                                                              */
/*      correspond a la fonction magma _GETfirstLine ObjText -> I               */
/*      qui renvoi le numer ode la premiere ligne visible d'un objet texte      */
/*                                                                              */
/********************************************************************************/

int GRGetFirstLine ( mmachine m )
{
    int s , l ;
    PtrObjVoid O ;
    PtrObjText T ;


    /************************************** DEBUG 2D ***************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _GETfirstLine!\n" ) ;
        FDebug2D (m  ) ; 
    #endif
    /*******************************************************************************/

    s = MMpull ( m ) ;
    if ( s != NIL )
    {
        O = ( PtrObjVoid ) MMstart(m,(s>>1)) ;
        T = ( PtrObjText ) MMstart(m,(O->Buffer>>1)) ;
        l = SendMessage ( T->WHandler , EM_GETFIRSTVISIBLELINE , 0 , 0 ) ;
    }
    else
    {
        l = NIL  ;
        MMechostr ( 1 , "Objet Texte is NIL\n" ) ;
    }


    /***************************** DEBUG 2D *****************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _GETfirstLine done\n" ) ;
    #endif
    /***********************************************************************************/

    return MMpush(m,l<<1) ;
}

/*****************************************************************************************/
/*                                                                                       */
/*  int GRSetTextSize ( mmachine m ) ;                                                   */
/*                                                                                       */
/*  correspond a la fonction magma ObjText _SETtextSize ( ObjText , I )  laquelle        */
/*  fixe une taille en caractere au contenu de l'objet texte                             */
/*                                                                                       */
/*****************************************************************************************/

int GRSetTextSize ( mmachine m ) 
{
    int s , si ;
    PtrObjVoid  O ;
    PtrObjText T ;


    /*********************DEBUG 2D ******************************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _SETtextSize\n" ) ;
        FDebug2D (m  );
    #endif
    /*************************************************************************************/

    si = MMpull ( m ) >> 1 ;
    s = MMpull ( m ) ;

    if ( s != NIL && si > 0 && si < 32367 )  
    {
 
        O = ( PtrObjVoid ) MMstart(m,(s>>1)) ;
        T = ( PtrObjText ) MMstart(m,(O->Buffer>>1)) ;
        SendMessage ( T->WHandler,EM_LIMITTEXT , si , 0 ) ;       
        UpdateWindow ( T->WHandler ) ;       
    }

    s = MMpush(m,s ) ;

    /********************** DEBUG 2D ****************************************************/
    #ifdef TRACE2D
        FDebug2D ( m );
        MMechostr ( 1 , "DBG _SETtextSize done\n" ) ;
    #endif
    /***********************************************************************************/

        return s ;
}

/****************************************************************************************/
/*                                                                                      */
/*  int GRSetFirstLine ( mmachine m ) ;                                                 */
/*                                                                                      */
/*  correspond a la fonction ObjText _SETfirstLine ( ObjText , I ) ;                    */
/*  laquelle positionne la premiere ligne visible d'un objet texte multiligne           */
/*                                                                                      */
/****************************************************************************************/

int GRSetFirstLine ( mmachine m ) 
{
    int s, l , l2 , lm ;
    PtrObjVoid O ;
    PtrObjText T ;

    l = MMpull(m)>>1;
    s=MMpull(m);
    if (s!=NIL)
    {
        O=(PtrObjVoid) MMstart(m,(s>>1));
        T=(PtrObjText) MMstart(m,(O->Buffer>>1));
        l2 = SendMessage(T->WHandler,EM_GETFIRSTVISIBLELINE,0,0);
        lm = SendMessage (T->WHandler,EM_GETLINECOUNT,0,0);
        if(l<0 || l>=lm)
        {
            MMechostr(MSKDEBUG,"Line index outside the text in _SETfirstLine\n");
        }
        else
        {
            l2=l-l2;
            if(l2>0)
            while(l2) 
            {
                SendMessage(T->WHandler,EM_SCROLL,SB_LINEDOWN,0);
                l2--;
            } else while (l2<0)
            {
                SendMessage(T->WHandler,EM_SCROLL,SB_LINEUP,0);
                l2++;
            }
        }        
    }
    return MMpush(m,s) ;
}