# xtext.tcl --
#
#
# Ce fichier contiendra :
# - toutes les proc de bas niveau destiner à gérer
#   le widget xtext (dont undo, selection rectangulaire, routine de
#   base pour la balance et la colorisation ...
#   REPORTEES DANS LE FICHIER "xtext_proc.tcl"
# - les binding liés fondementalement au widget
#
# Les binding de plus haut niveau sont reportées dans le fichier gérant
# les binding liés à l'application (i.e. quitter, sauvegarder, ...)
#
# De meme, des procédure de balance ou de coloration de plus haut
# niveau seront implantées dans un fichier réservé à l'application.
#
#
#
# Ce fichier basé sur text.tcl de tk et (profondément) modifié
# pour adaption à l'éditeur stead par Jean-Luc Commeau et
# Maurice Diamantini
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998 by Scriptics Corporation.
# Copyright (c) 2000 by ENSTA.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
## 
## Pour obtenir les ligne "##" de ce fichier, il faut evaluer :
## 
##  stead -command "ins \[exec grep  {^## } $F\]; xtext_markClean $T"
## 
# xtext -- create the xtext widget, its data and initialize it
# xtextInitBindings --

package provide xtext 2.0

#-------------------------------------------------------------------------
# Nota : tkPriv est remplacé par xtext pour xtext
# Elements of tkPriv that are used in this file:
#
#
# afterId -    If non-null, it means that auto-scanning is underway
#      and it gives the "after" id for the next auto-scan
#      command to be executed.
# char -    Character position on the line;  kept in order
#      to allow moving up or down past short lines while
#      still remembering the desired position.
# mouseMoved -    Non-zero means the mouse has moved a significant
#      amount since the button went down (so, for example,
#      start dragging out a selection).
# prevPos -    Used when moving up or down lines via the keyboard.
#      Keeps track of the previous insert position, so
#      we can distinguish a series of ups and downs, all
#      in a row, from a new up or down.
# selectMode -    The style of selection currently underway:
#      char, word, or line.
# x, y -    Last known mouse coordinates for scanning
#      and auto-scanning.
#-------------------------------------------------------------------------



## xtext -- create the xtext widget, its data and initialize it
#
# le tableau xtext
#   contiendra tout ce qui est commun à tous les widget xtext
# le tableau $w (i.e ".main.t")
#   contiendra ce qui est spécifique à chaque widget
#   (état courant, ...)
#   En particulier $w intégrera l'ancien xtext...)
#
# la variable globales "stead" devra progressivement disparaitre de ce
# fichier (ou plutot de ce répertoire :-)
#
proc xtext {w args  } {

    global xtext
    global stead
    # Initialisation à faire une seul fois : bindings et tableau xtext
    # pour les variables communes à **tous** les widgets xtext
    # 
    if {![info exists xtext(initialised)]} {
        xtextInit
    }

    # construction du widget :
    eval text $w $args
    
    # Initialisation spécifique à **ce** widget particulier
    xtextInitWidget $w

    # 
    # La valeur par défaut des bindtags (en interactif) est :
    # 
    #    pack [text .t]
    #    bindtags .t
    #       => .t Text . all
    #    winfo class .t
    #       => Text
    #    winfo class .
    #       => Wish8.3
    # 
    # Ce widget XText est déstiné en remplacer totalement le widget Text
    # Mais je souhaite que par défaut, ce widget soit également sensible 
    # à la classe de l'application (par exemple "Stead")
    # 
    # Ceci marchait, mais était insensible à la classe de l'appli :
    #    bindtags $w [list $w XText . all]     ;# (Ceci marchait !)
    # 
    bindtags $w [list $w  [winfo class .] XText . all]

    return $w
}

# xtextInit --
#
# Initialise les bindings pour la classe XText et le tableau xtext lors
# de la première utilisation d'un widget xtext
#
proc xtextInit {} {
    global xtext

    # initialisation des variables une seule fois pour l'ensemble de tous les
    # widget xtext à venir

    # Les 7 variables suivantes viennent de tkPriv (donc était communes à
    # plusieurs widgets)
    #
    set xtext(afterId)    {}
    set xtext(char)       0
    set xtext(mouseMoved) 0
    set xtext(prevPos)    {}
    set xtext(selectMode) char    ;# char|word|line|rect
    set xtext(x)          0
    set xtext(y)          0
    
    # Mémo de la précédente sélection
    set xtext(buf,oldSel,data) ""
    # Mémo de l'info "isRect" associée à la précédente sélection
    set xtext(buf,oldSel,isRect) 0

    # Mémo du presse-papier
    set xtext(buf,clip,data) ""
    # Mémo de l'info "isRect" associée au presse-papier
    set xtext(buf,clip,isRect) 0

    # Ca je ne sais pas ?
    set xtext(pressX)     0
    
    # Les caracteres à balancer dynamiquement lors de la saisie.
    # 
    # A FAIRE :
    #   Prévoir une "parSpec" pour spécification de parenthese.
    #   Créer alors la variable xtext($w,parSpecs) (qui dépendra du mode)
    #   
    #   Cette liste sera utiliser à la fois pour le surlignage dynamique 
    #   (en cours de saisie) et pour la balance (sur Meta-b)
    # 
    #   Cette derniere liste sera une liste de specification de paire
    #   avec un type :
    #     char : caractère unique à vérifier dynamiquement lors de la 
    #            saisie (c'est le cas le parenthèse du style [{( )}]
    #     exact : chaine 
    #     regexp : à
    #     full : gérant les patternes d'exception (par exemple
    #           pour tenir compte des caracteres commentés !)
    #   
    set xtext(balance_list) [list           \
        [list  parenright    \(   \)   ]    \
        [list  bracketright  \[   \]   ]    \
        [list  braceright    \{   \}   ]    \
    ]
    
    # liste des buffers autorisés (presse-papier, ancienne sélection...)
    # l'utilisateur pour créer ses propre buffer (plusieurs presse-papiers...)
    set xtext(buffers) [list clip oldSel]
    
    xtextInitBindings

    # Cette variable sera supprimée quand on connaitra une variable de nom
    # fiable de xtext()  (i.e qui ne soit pas positionnée par stead elle même !)
    #
    set xtext(initialised) 1

} ;# endproc xtextInit

# xtextInitWidget --
#
# Initialise les variable propres à chaque widget
#
proc xtextInitWidget {w} {
    global xtext

    # Initialisation des variables propres à cette instance de widget :
    #
    # Les variables propres à ce widget sont de la forme
    #   xtext($w,XXX)
    # mais pourront avoir leur propre nom du style
    #   upvar #0 $w data
    # 
    # la vaiable xtext sera alors réservée au données commune à tout widget
    # xtext. Pour les données liées à un widget particulier, on utilisera
    # data (par un upvar)
    # 

    # point d'insertion courant pour mise à jour de la case d'affiche 
    # de position
    set xtext($w,insertPos) 1.0

    # point d'insertion précédent pour les procédures xtext_insert et 
    # xtext_delete  (utiliser pour savoir si pushState nécessaire)
    set xtext($w,lastInsertPos) 1.0
    set xtext($w,lastDeletePos) 1.0
    set xtext($w,prevLineNum) 0   ;# RESERVE PAS ENCORE UTILISE

    # état modifier du widget text :
    #   - mis à 1 à chaque modification
    #   - remis à 0 par l'application lors d'une sauvegarde
    # Peut être utiliser par un procédure de trace pour modifier l'icone ou
    # le nom de l'application : "mon_fichier.cc" -> "!mon_fichier.cc"
    set xtext($w,modified)  0


    # Quelques globales liées à l'exécution multiple d'une meme action
    # 
    # Nombre de fois que la commande suivante doit etre exécutée :
    #
    set xtext($w,autoRepeatCount) 1
    #
    # Boolean vrai si on est en train de saisir le nombre de répetitions
    #  
    set xtext($w,autoRepeatActif) 0

    # Chaine de caracteres débutant les "Méta-commentaires"
    # Ceux-ci représente les commentaires les plus importants
    # d'un fichier (par exemple la description succinte de
    # procédures tcl)
    # 
    # A FAIRE : 
    #   Créer et faire appel à :
    #       xtext_getMetaComment w {w {metaPrefix ""}}
    #   qui retourne le texte correspondant.
    # 
    # set xtext($w,metaPrefix) "## "
    set xtext($w,metaPrefix) "## "
    
    xtext_style $w init
    
    # Vrai des que la position Y du widget text à changé, et tant que
    # ce changement n'a pas été exploiter (par un rafraichissement des
    # couleurs) 
    set xtext(screenChangeSent) 0
    

    # A RENOMMER avec refonte du undo et des state (pushState...)
    # 
    global UNDOPTR  ;# current index into undo ring
    set UNDOPTR 0

}

## xtextInitBindings --
#
#
proc xtextInitBindings {args} {
    global stead
    global xtext
    global tcl_platform
    global tk_strictMotif


    # Commenté par diam car remplacé par appel hard à xtext_markDirty
    # bind XText <<ModifyText>> {xtext_markDirty %W}


    # Tiré de la classe Text de wish8.3 :
    #  
    # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
    # Otherwise, if a widget binding for one of these is defined, the
    # <KeyPress> class binding will also fire and insert the character,
    # which is wrong.  Ditto for <Escape>.
    # ATTENTION : {# nothing} (= { }) n'est PAS equivalent à {} !!!
    # 
    bind XText <Alt-KeyPress>        {# nothing}
    bind XText <Alt-Shift-KeyPress>  {# nothing}
    bind XText <Meta-KeyPress>       {# nothing}
    bind XText <Meta-Shift-KeyPress> {# nothing}
    bind XText <$stead(Control)-KeyPress>    {# nothing}
    bind XText <Escape>              {# nothing}
    bind XText <KP_Enter>            {# nothing}
    if {[string equal $tcl_platform(platform) "macintosh"]} {
        bind XText <Command-KeyPress> {# nothing}
        # bind XText <Option-KeyPress> {# nothing}
    }

    # Suppression des évènements virtuels prédéfinis :
    foreach ev [event info] {
        event delet $ev
    }

    # Fonctionalité "autorepeat" : permet par exemple d'exécuter
    # plusieurs fois la commande suivante 
    # 
    bind XText <$stead(Control)-u>    {xtext_autoRepeatTimes4Count %W}
    foreach the_digit {0 1 2 3 4 5 6 7 8 9} {
        
        bind XText <$stead(Control)-u><Key-$the_digit> \
                        {xtext_autoRepeatStartCount %W %A}
        bind XText <$stead(Control)-u><Key-KP_$the_digit> \
                        {xtext_autoRepeatStartCount %W %A}
                        
        bind XText <Escape><Key-$the_digit> \
                        {xtext_autoRepeatStartCount %W %A}
        bind XText <Escape><Key-KP_$the_digit> \
                        {xtext_autoRepeatStartCount %W %A}
                        
        bind XText <Key-$the_digit> \
                        {xtext_insertDigit %W %A}
        bind XText <Key-KP_$the_digit> \
                        {xtext_insertDigit %W %A}
    }

    bind XText <$stead(Meta)-b>    {xtext_selectBalance %W}

    # effacement
    bind XText <BackSpace>      {xtext_delete %W -backward 1}
    # bind XText <Key-Delete>     {xtext_delete %W -backward 1}
    bind XText <Key-Delete>     {xtext_delete %W -forward 1}
    bind XText <$stead(Control)-h>      {xtext_delete %W -backward 1}
    bind XText <$stead(Control)-d>      {xtext_delete %W -forward  1}
                                                
    bind XText <Escape><Delete> {xtext_deleteLeftWord %W}
    bind XText <Escape><Key-d>  {xtext_deleteRightWord %W}

    # insertion
    bind XText <Any-Key>        {
        if {[string length %A]} {
            xtext_insert %W -balance 1 -style 1 -string %A
        }
        # Surtout pas de "break" car les touches de controle passent par ici !
    }


    # Les caracteres spéciaux <Space> <Tab>
    #
    # Attention pour la tabulation : certain systemes envoe le symbole
    # "ISO_Left_Tab" au lieu de  "Tab".
    # On peut vérifier par :
    # 
    #    bind . <KeyPress> {puts %K}

    # 
    # A FAIRE : prevoir un moyen standard pour inserer un caractere literal
    #    en plus du <Shift-Tab> ci-dessous,
    #    il y aussi <$stead(Control)-q><sequence>
    #
    bind XText <Tab>  {
        stead:tabkey
        break
    }

    bind XText <space>  {
        stead:spacebar
        break
    }
    bind XText <Return>         {stead:returnkey;break}
    
    # Quelques insertion litérales
    # 
    bind XText <Shift-Return>   {xtext_insert %W -string "\n";break}
    bind XText <Shift-space>    {xtext_insert %W -string " " ;break}
    bind XText <Shift-Tab>      {xtext_insert %W -string "\t";break}
    bind XText <$stead(Control)-i>      {xtext_insert %W -string "\t";break}

    ## abbréviations dynamiques
    bind XText <$stead(Meta)-Tab> {
      if {$EDITPREFS(dabbrev)} {
        stead:cmd:dabbrev
      } else {
        xtext_insert %W -string "\t" 
      }
      break
    }
    # abbréviations dynamiques (pour les environement qui se réserves
    # le raccourci <Meta-tab> pour eux, (macosx) et pour éviter de modifier 
    # leur configuration par défaut, voici deux alternatives
    #  
    # pratique sur clavier AZERTY
    bind XText <$stead(Meta)-ampersand> {
      if {$EDITPREFS(dabbrev)} {
        stead:cmd:dabbrev
      } else {
        xtext_insert %W -string "\t" 
      }
      break
    }
    # pratique sur clavier QUERTY
    bind XText <$stead(Meta)-quoteright> {
      if {$EDITPREFS(dabbrev)} {
        stead:cmd:dabbrev
      } else {
        xtext_insert %W -string "\t"
      }
      break
    }

    # abbréviations statiques
    bind XText <$stead(Meta)-space> {
        if {$EDITPREFS(sabbrev)} {
            electricAlias-expand %W " " 1
        } else {
            xtext_insert %W -string " " 
            stead:autobreak_hook %W
        }
      break
    } 

    # cut, copy, paste
    # # TRANSERT FAIT DANS LE FICHIER DES MENU (build.tcl)
    # bind XText <$stead(Meta)-c>    {xtext_copy  %W}
    # bind XText <$stead(Meta)-x>    {xtext_cut   %W}
    # bind XText <$stead(Meta)-v>    {xtext_paste %W}
    # Non : à déplacer dans stead
    #     bind XText <$stead(Meta)-C>    {xtext_named_copy  %W}
    #     bind XText <$stead(Meta)-X>    {xtext_named_cut   %W}
    #     bind XText <$stead(Meta)-V>    {xtext_named_paste %W}
                               
    # sélection
    bind XText <$stead(Meta)-a>    {xtext_select %W  -all}

    bind XText <$stead(Meta)-d>    {
        if {$xtext(selectMode) == "line"} {
            # Cas fréquent où on duplique un groupe de ligne, qu'on doit
            # relelectionner pour les modifier aussitot.
            # Je préfère donc conserver ces lignes sélectionnées
            xtext_xpaste %W -tags sel            
        } else {
            xtext_xpaste %W sel
        }
    }
    
    # 
    # Recherche et Remplacement
    # 

    bind XText <$stead(Meta)-j>  {stead:see -setinsert}

    bind XText <$stead(Meta)-e>  {stead:enterSelToSearchFor %W}
    bind XText <$stead(Meta)-E>  {stead:enterSelToReplaceWith %W}

    bind XText <$stead(Meta)-r>  {stead:searchBackward %W}
    bind XText <$stead(Meta)-f>  {stead:findBox %W}
    bind XText <$stead(Meta)-g>  {stead:searchForward %W}
    
    bind XText <$stead(Meta)-R>  {stead:searchSelBackward %W}
    bind XText <$stead(Meta)-G>  {stead:searchSelForward %W}
    # RESERVE (en cours de reflexion)  $stead(Meta)-F>
    # - soit :
    #    bind XText <$stead(Meta)-F>  {stead:findBox -fullbox %W}E
    # - soit :
    #    utiliser <$stead(Meta)-F> comme préfixe pour piloter les
    #    nombreuses options de recherche

    bind XText <$stead(Meta)-u>  {stead:replace %W}
    bind XText <$stead(Meta)-U>  {stead:replaceThenSearchAgain %W}



    # 09/12/99 (diam) : Centralisation de la colorisation
    bind XText <$stead(Control)-c><$stead(Control)-a> {stead:styleRefresh -all}
    bind XText <$stead(Control)-c><$stead(Control)-c> {stead:styleRefresh}
    bind XText <$stead(Control)-c><$stead(Control)-r> {stead:styleCancel}
    bind XText <$stead(Control)-c><$stead(Control)-s> {xtext_style %W apply -screen}


    # annulation
    bind XText <$stead(Meta)-z> {xtext_undo %W}
    bind XText <$stead(Meta)-Z> {xtext_redo %W}

    # Indentation sur clavier QWERTY
    bind XText <$stead(Meta)-bracketright> {te:cmd:indent_right}
    bind XText <$stead(Meta)-bracketleft>  {te:cmd:indent_left}
    bind XText <$stead(Meta)-braceright>   {te:cmd:indent_one_space_right}
    bind XText <$stead(Meta)-braceleft>    {te:cmd:indent_one_space_left}

    # Indentation sur clavier AZERTY (Mac/linux) (27/11/98)
    bind XText <$stead(Meta)-parenright>         {te:cmd:indent_right}
    bind XText <$stead(Meta)-parenleft>          {te:cmd:indent_left}
    bind XText <$stead(Meta)-$stead(Control)-parenright> {te:cmd:indent_one_space_right}
    bind XText <$stead(Meta)-$stead(Control)-parenleft>  {te:cmd:indent_one_space_left}

    bind XText <$stead(Meta)-k>             {xtext_capitalise %W}

    # 13/08/02 MODIF des raccourcis de gestion de la mise en commentaire
    # pour pouvoir libérer Meta-minus et Meta-plus.
    # Principe : 
    #   - simple quote pour commenter (Meta ou controle suivant le cas)
    #   - double quote pour décommenter (Meta)
    # Ces raccourcis sont facilement accessibles, aussi bien sur les claviers
    # AZERTY que QWERTY
    # 
    # # bind XText <$stead(Meta)-minus>         {te:cmd:ins_pref  after}
    # # bind XText <$stead(Meta)-$stead(Control)-minus> {te:cmd:ins_pref  before}
    # # bind XText <$stead(Meta)-underscore>    {te:cmd:remove_prefix}
    # # bind XText <$stead(Control)-minus>              {te:cmd:set_prefix}
    # 
    bind XText <$stead(Meta)-quotedbl>      {te:cmd:remove_prefix}
    bind XText <$stead(Control)-quotedbl>      {te:cmd:remove_prefix}
    
    # catch {
    #     bind XText <$stead(Meta)-apostrophe>    {te:cmd:ins_pref  after}
    #     bind XText <$stead(Control)-apostrophe>         {te:cmd:ins_pref  before}
    #     bind XText <$stead(Meta)-$stead(Control)-apostrophe>   {te:cmd:set_prefix}
    # }
    # quoteright : anciennement apostrophe
    bind XText <$stead(Meta)-quoteright>    {te:cmd:ins_pref  after}
    bind XText <$stead(Control)-quoteright>         {te:cmd:ins_pref  before}
    bind XText <$stead(Meta)-$stead(Control)-quoteright>   {te:cmd:set_prefix}
    
    # Dupplication car suivant clavier la touche s'appelle quoteleft
    bind XText <$stead(Meta)-quoteleft>    {te:cmd:ins_pref  after}
    bind XText <$stead(Control)-quoteleft>         {te:cmd:ins_pref  before}
    bind XText <$stead(Meta)-$stead(Control)-quoteleft>   {te:cmd:set_prefix}
    
    
    # Wrapping de la sélection :
    # Modif diam 22/01/04
    # 
    # <$stead(Control)-slash> inactivé dans la class Text de wish8.0
    # bind XText <$stead(Control)-slash>            {xtext_wrapSel %W /* */}
    # bind XText <$stead(Control)-Shift-braceright> {xtext_wrapSel %W \\\{ \\\}}
    # bind XText <$stead(Control)-Shift-quotedbl>   {xtext_wrapSel %W \\" \\"}
    # bind XText <$stead(Control)-bracketright>     {xtext_wrapSel %W \\\[ \\\]}
    # bind XText <$stead(Control)-Shift-parenright> {xtext_wrapSel %W \( \)}
    # bind XText <$stead(Control)-Shift-greater>    {xtext_wrapSel %W < >}
    
    bind XText <$stead(Meta)-less>   {}
    bind XText <$stead(Meta)-greater>   {}
    bind XText <$stead(Meta)-less><slash>     [list xtext_wrapSel %W /  /]
    bind XText <$stead(Meta)-less><quotedbl>     [list xtext_wrapSel %W \" \"]
    bind XText <$stead(Meta)-less><quoteleft>     [list xtext_wrapSel %W `  `]
    bind XText <$stead(Meta)-less><quoteright>     [list xtext_wrapSel %W '  ']
    bind XText <$stead(Meta)-less><backslash>    [list xtext_wrapSel %W \\ \\]
    bind XText <$stead(Meta)-less><asterisk>     [list xtext_wrapSel %W  *  *]
    bind XText <$stead(Meta)-less><braceright>   [list xtext_wrapSel %W  \{  \}]
    bind XText <$stead(Meta)-less><b>            [list xtext_wrapSel %W  \{  \}]
    bind XText <$stead(Meta)-less><bracketright> [list xtext_wrapSel %W \[  \]]
    bind XText <$stead(Meta)-less><r>            [list xtext_wrapSel %W \[  \]]
    bind XText <$stead(Meta)-less><bar>          [list xtext_wrapSel %W  | |]
    bind XText <$stead(Meta)-less><l>            [list xtext_wrapSel %W  | |]
    bind XText <$stead(Meta)-less><parenright> [list xtext_wrapSel %W  (  )]
    bind XText <$stead(Meta)-less><greater> [list xtext_wrapSel %W  < > ]
    bind XText <$stead(Meta)-less><equal> [list xtext_wrapSel %W  = =  ]
    bind XText <$stead(Meta)-less><minus> [list xtext_wrapSel %W  - -  ]
    bind XText <$stead(Meta)-less><plus> [list xtext_wrapSel %W  + +  ]
    bind XText <$stead(Meta)-less><numbersign> [list xtext_wrapSel %W  # # ]
    
    bind XText <$stead(Meta)-less><c>    \
                                [list xtext_wrapSel %W "/* " " */"]
    bind XText <$stead(Meta)-greater><c>  \
                                [list xtext_wrapSel %W "/*\n" "\n*/"]
                                
    bind XText <$stead(Meta)-less><h>   \
                                [list xtext_wrapSel %W  "<!-- " " --> "]
    bind XText <$stead(Meta)-greater><h> \
                                [list xtext_wrapSel %W  "<!--\n" "\n-->\n"]
    

    # Marquage (dont conventions emacs) (*** A NETTOYER !!! ***)
    # 
    bind XText <$stead(Control)-m>         {te:tb:e:set-mark-command %W}
    bind XText <$stead(Control)-M>         {te:tb:e:go-to-mark %W}
    bind XText <$stead(Control)-at>        {te:tb:e:go-to-mark %W}
    # 
    bind XText <$stead(Control)-space>     {te:tb:e:set-mark-command %W}
    bind XText <$stead(Control)-u><$stead(Control)-space>  \
                                           {te:tb:e:go-to-mark %W}
    bind XText <$stead(Control)-x><$stead(Control)-x> \
                                           {te:tb:e:exchange-point-and-mark %W}
    


    # on affiche ou non le curseur suivant la presence de la selection
    #
    bind XText <Enter>  {
        if {"x[focus]" == "x%W"} {xtext_updateFocusIn %W}
    }
    bind XText <FocusIn> {xtext_updateFocusIn %W}

    # Définition des Macros
    # A PREVOIR

    # quelques bindings emacs
    # movement keys
    bind XText <Escape><less>  { xtext_setCursor %W 1.0 }
    bind XText <Escape><greater> { xtext_setCursor %W end }
    bind XText <Escape><b>  { event generate %W <$stead(Control)-Left> }
    bind XText <Escape><f>  { event generate %W <$stead(Control)-Right> }

    # scrolling keys
    bind XText <$stead(Control)-v>  { event generate %W <Next> }
    bind XText <Escape><v>  { event generate %W <Prior> }


    ####################################################################
    # DEBUT de sélection (dont rectangulaire)

    # A FAIRE (quand cela sera au point)
    # 
    # Le bouton 3 sera réservé :
    #  1 - au menus contextuels apres une demi-seconde sans bouger la souris
    #  2 - au menus contextuels sur un relacher sans bouger la souris
    #  2 - à la selection rectangulaire si on a bougé
    # Ce bouton 3 sera equivalent à <$stead(Control)-B1>
    # 
    
    bind XText <1> {
        xtext_selectionStart %W -char %x %y
        xtext_unSelect %W
    }
    bind XText <Double-1> {
        xtext_selectTo %W -word -- %x %y
        # catch {%W mark set insert sel.first}
        # catch {%W mark set anchor sel.first}
    }
    bind XText <Triple-1> {
        xtext_selectTo %W -line -- %x %y
        # catch {%W mark set insert sel.first}
        # catch {%W mark set anchor sel.first}
    }
    bind XText <B1-Motion> {
        set xtext(x) %x
        set xtext(y) %y
        xtext_selectTo %W -- %x %y
    }
    bind XText <Shift-1> {
        # xtext_resetAnchor empeche de sélectioner au moment du Shift-click 
        xtext_resetAnchor %W @%x,%y
        # Pour un clique simple, on conserve le mode de sélection précédent 
        # (line, word, char)
        xtext_selectTo %W -- %x %y
    }
    bind XText <Double-Shift-1>  {
        # set xtext(selectMode) word
        xtext_selectTo %W -word -- %x %y
        
        # prévoirparametre supplémentaire  modif de tk8.4 (PLUS TARD !)
        # xtext_selectTo %W -- %x %y 1
    }
    bind XText <Triple-Shift-1>  {
        # set xtext(selectMode) line
        xtext_selectTo %W -line -- %x %y
    }
    # QUESTION (diam 13/08/00) : comment créer un binding sur quadruple click ?
    # 
    # bind XText <Triple-1><1> {
    #     xtext_selectTo %W  -all
    # }
    
    bind XText <B1-Leave> {
        set xtext(x) %x
        set xtext(y) %y
        xtext_autoScan %W
    }
    bind XText <B1-Enter> {
        xtext_cancelRepeat
    }
    bind XText <ButtonRelease-1> {
        xtext_cancelRepeat
        xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    ####################################################################
    # Control-B1 est equivalent au troisième bouton
    # 
    # 
    bind XText <$stead(Control)-1> {
        # xtext_selectionStart %W -rect -- %x %y
        xtext_selectTo %W -rect -- %x %y
        xtext_unSelect %W
    }
    bind XText <$stead(Control)-B1-Motion> {
        set xtext(x) %x
        set xtext(y) %y
        xtext_selectTo %W -rect -- %x %y
    }
    bind XText <$stead(Control)-ButtonRelease-1> {
        xtext_cancelRepeat
    }
    bind XText <$stead(Control)-Shift-1> {
        xtext_resetAnchor %W @%x,%y
        xtext_selectTo %W -rect -- %x %y
    }

    ####################################################################
    # Bouton 2 Cpoie par impulsion ou déplacement à la MacPaint
    # 
    bind XText <2> {
        %W scan mark %x %y
        set xtext(x) %x
        set xtext(y) %y
        set xtext(mouseMoved) 0
    }
    bind XText <B2-Motion> {
        # On ne considère un déplacement que si >= "miniMotion" pixel
        set dx [expr {%x - $xtext(x)}]
        set dy [expr {%y - $xtext(y)}]
        set motion [expr {abs ($dx) + abs ($dy) } ]
        # report  "dx=$dx  dy=$dy  motion=$motion"
        if { $motion >= 3} {
            # A FAIRE : que si  ||dx + dy|| > miniMotion
            set xtext(mouseMoved) 1
        }
        # # if {(%x != $xtext(x)) || (%y != $xtext(y))} {
        # #     # A FAIRE : que si  ||dx + dy|| > miniMotion
        # #     set xtext(mouseMoved) 1
        # # }
        if {$xtext(mouseMoved)} {
            %W scan dragto %x %y
        }
        xtext_style %W apply  -screen  ;# BIDOUILLE EN T
    }

    # Gestion de la copie directe de la sélection sur le relachement de <2>
    bind XText <ButtonRelease-2> {
        if {!$xtext(mouseMoved)} {
            xtext_xpaste %W
        }
        xtext_style %W apply  -screen  ;# BIDOUILLE EN T
    }
    
    ####################################################################
    # Bouton 3 : création de la sélection rectangulaire
    # 
    bind XText <3> {
        xtext_selectionStart %W -rect %x %y
        xtext_unSelect %W
    }
    bind XText <B3-Motion> {
        set xtext(x) %x
        set xtext(y) %y
        xtext_selectTo %W -rect -- %x %y
    }
    bind XText <ButtonRelease-3> {
        xtext_cancelRepeat
        xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <B3-Leave> {
        set xtext(x) %x
        set xtext(y) %y
        xtext_autoScan %W
    }
    bind XText <B3-Enter> {
        xtext_cancelRepeat
    }
    
    bind XText <Shift-3> {
        xtext_resetAnchor %W @%x,%y
        set xtext(selectMode) rect
        xtext_selectTo %W -- %x %y
    }
    
    ####################################################################
    # 
    # Sélection par le clavier
    # 
    bind XText <Shift-Left> {
        xtext_keySelect %W [%W index {insert - 1c}]
    }
    bind XText <Shift-Right> {
        xtext_keySelect %W [%W index {insert + 1c}]
    }
    bind XText <Shift-Up> {
        xtext_keySelect %W [xtext_upDownLine %W -1]
    }
    bind XText <Shift-Down> {
        xtext_keySelect %W [xtext_upDownLine %W 1]
    }
    
    bind XText <Shift-$stead(Control)-Left> {
        xtext_keySelect %W [xtext_prevPos %W insert tcl_startOfPreviousWord]
    }
    bind XText <Shift-$stead(Control)-Right> {
        xtext_keySelect %W [xtext_nextWord %W insert]
    }
    bind XText <Shift-$stead(Control)-Up> {
        xtext_keySelect %W [xtext_prevPara %W insert]
    }
    bind XText <Shift-$stead(Control)-Down> {
        xtext_keySelect %W [xtext_nextPara %W insert]
    }
    
    bind XText <Shift-Prior> {
        xtext_keySelect %W [xtext_scrollPages %W -1]
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <Shift-Next> {
        xtext_keySelect %W [xtext_scrollPages %W 1]
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <Shift-Home> {
        xtext_keySelect %W {insert linestart}
    }
    bind XText <Shift-End> {
        xtext_keySelect %W {insert lineend}
    }
    bind XText <$stead(Control)-Shift-Home> {
        xtext_keySelect %W 1.0
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <$stead(Control)-Shift-End> {
        xtext_keySelect %W {end - 1 char}
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    
    # FIN de sélection (dont rectangulaire)
    ####################################################################


    # 
    # A FAIRE Control doit permettre de selectionner une zone est de faire
    # un xpaste au point d'insertion d'origine !
    # 
    # CECI NE FONCTIONNE PAS (c'est pas plus mal car pas "user-friendly")
    # 
    # bind XText <$stead(Control)-1> {
    #     %W mark set insert @%x,%y
    # }
    bind XText <Left>  {xtext_moveCursor %W -backwards 1}
    bind XText <Right> {xtext_moveCursor %W -forwards  1}
    bind XText <Up>    {xtext_moveCursor %W -up        1}
    bind XText <Down>  {xtext_moveCursor %W -down      1}
                                                      
    bind XText <$stead(Meta)-Up> {
        xtext_setCursor %W 1.0
    }
    bind XText <$stead(Meta)-Down> {
        xtext_setCursor %W end
    }
    bind XText <$stead(Meta)-Left> {
        event generate %W <Home>
    }
    bind XText <$stead(Meta)-Right> {
        event generate %W <End>
    }
    # 10/09/00 diam : pourquoi c'est pas symetrques ?
    #                 manque une proc xtext_prevWord ??
    bind XText <$stead(Control)-Left> {
        xtext_setCursor %W [xtext_prevPos %W insert tcl_startOfPreviousWord]
    }
    bind XText <$stead(Control)-Right> {
        xtext_setCursor %W [xtext_nextWord %W insert]
    }
    bind XText <$stead(Control)-Up> {
        event generate %W <Prior>
        # xtext_setCursor %W [xtext_prevPara %W insert]
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <$stead(Control)-Down> {
        event generate %W <Next>
        # xtext_setCursor %W [xtext_nextPara %W insert]
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <Prior> {
        xtext_setCursor %W [xtext_scrollPages %W -1]
    }
    bind XText <Next> {
        xtext_setCursor %W [xtext_scrollPages %W 1]
    }
    bind XText <$stead(Control)-Prior> {
        %W xview scroll -1 page
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <$stead(Control)-Next> {
        %W xview scroll 1 page
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }

    bind XText <Home> {
        xtext_setCursor %W {insert linestart}
    }
    bind XText <End> {
        xtext_setCursor %W {insert lineend}
    }
    bind XText <$stead(Control)-Home> {
        xtext_setCursor %W 1.0
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }
    bind XText <$stead(Control)-End> {
        xtext_setCursor %W {end - 1 char}
        # xtext_style %W apply -screen ;# BIDOUILLE EN TEST
    }

    # # #
    # # # 31/07/01 (diam) je ne voix pas l'intéret pour l'instant
    # # #
    # # bind XText <Select> {
    # #     %W mark set anchor insert
    # # }
    # # # bind XText <$stead(Control)-Shift-space> {
    # # #     set xtext(selectMode) char
    # # #     xtext_keyExtend %W insert
    # # # }
    # # bind XText <Shift-Select> {
    # #     set xtext(selectMode) char
    # #     xtext_keyExtend %W insert
    # # }
    bind XText <$stead(Control)-backslash> {
        %W tag remove sel 1.0 end
    }

    # 
    # Les copié-collés...
    # 

    bind XText <<Cut>> {
    report "bind XText <<Cut>>"
        xtext_cut %W
    }
    bind XText <<Copy>> {
    report "bind XText <<Copy>>"
        xtext_copy %W
    }
    bind XText <<Paste>> {
    report "bind XText <<Paste>>"
        xtext_paste %W
    }
    bind XText <<Clear>> {xtext_delete %W sel}

    bind XText <<PasteSelection>> {
        if {!$xtext(mouseMoved)} {
            xtext_xpaste %W
        }
    }
    bind XText <Insert> {
        if {!$xtext(mouseMoved)} {
            xtext_xpaste %W
        }
    }


    # Additional emacs-like bindings:

    bind XText <$stead(Control)-a> {
        xtext_setCursor %W {insert linestart}
    }
    bind XText <$stead(Control)-b> {
        event generate %W <Left>
    }

    bind XText <$stead(Control)-e> { event generate %W <End> }

    bind XText <$stead(Control)-f> { event generate %W <Right> }


    bind XText <$stead(Control)-k> {xtext_killEndLine %W}


    bind XText <$stead(Control)-w> {xtext_cut   %W}
    bind XText <$stead(Control)-y> {xtext_paste %W}




    bind XText <$stead(Control)-n> {
        xtext_setCursor %W [xtext_upDownLine %W 1]
    }

    bind XText <$stead(Control)-o> {
        xtext_insert %W  -string \n
        %W mark set insert insert-1c
    }
    bind XText <$stead(Control)-p> {
        xtext_setCursor %W [xtext_upDownLine %W -1]
    }

    bind XText <$stead(Control)-t> { xtext_transpose %W }


    # if {$tcl_platform(platform) != "windows"} {
    # bind XText <$stead(Control)-v> {
    #     if {!$tk_strictMotif} {
    #     xtext_scrollPages %W 1
    #     }
    # }
    # }

    # bind XText <$stead(Meta)-b> {
    #     if {!$tk_strictMotif} {
    #     xtext_setCursor %W [xtext_prevPos %W insert tcl_startOfPreviousWord]
    #     }
    # }
    # bind XText <$stead(Meta)-d> {
    #     if {!$tk_strictMotif} {
    #     %W delete insert [xtext_nextWord %W insert]
    #     }
    # }
    # bind XText <$stead(Meta)-f> {
    #     if {!$tk_strictMotif} {
    #     xtext_setCursor %W [xtext_nextWord %W insert]
    #     }
    # }
    # bind XText <$stead(Meta)-less> {
    #     xtext_setCursor %W 1.0
    # }
    # bind XText <$stead(Meta)-greater> {
    #     if {!$tk_strictMotif} {
    #         xtext_setCursor %W end-1c
    #     }
    # }

    # Les binging suivant doivent etre impémentées par l'intermédiaire de
    # proc undoables
    #
    # bind XText <$stead(Meta)-BackSpace> {
    #     %W delete [xtext_prevPos %W insert tcl_startOfPreviousWord] insert
    #         # event generate %W <<ModifyText>>
    #         xtext_markDirty %W
    # }
    # bind XText <$stead(Meta)-Delete> {
    #     if {!$tk_strictMotif} {
    #     %W delete [xtext_prevPos %W insert tcl_startOfPreviousWord] insert
    #         # event generate %W <<ModifyText>>
    #         xtext_markDirty %W
    #     }
    # }
    bind XText <$stead(Meta)-BackSpace> {
        xtext_delete %W [xtext_prevPos %W insert tcl_startOfPreviousWord] insert
    }
    bind XText <$stead(Meta)-Delete> {
        xtext_delete %W [xtext_prevPos %W insert tcl_startOfPreviousWord] insert
    }
    # A faire <$stead(Control)-Delete>, <$stead(Meta)-$stead(Control)-Delete>
    # pour effacer le mot suivant, le debut de ligne..

    # Macintosh only bindings:

    # if text black & highlight black -> text white, other text the same
    if {$tcl_platform(platform) == "macintosh"} {
        bind XText <FocusIn> {
            %W tag configure sel -borderwidth 0
            %W configure \
                    -selectbackground systemHighlight \
                    -selectforeground systemHighlightText
        }
        bind XText <FocusOut> {
            %W tag configure sel -borderwidth 1
            %W configure -selectbackground white -selectforeground black
        }
        bind XText <Option-Left> {
            xtext_setCursor %W [xtext_prevPos %W insert tcl_startOfPreviousWord]
        }
        bind XText <Option-Right> {
            xtext_setCursor %W [xtext_nextWord %W insert]
        }
        bind XText <Option-Up> {
            xtext_setCursor %W [xtext_prevPara %W insert]
        }
        bind XText <Option-Down> {
            xtext_setCursor %W [xtext_nextPara %W insert]
        }
        bind XText <Shift-Option-Left> {
            xtext_keySelect %W [xtext_prevPos %W insert tcl_startOfPreviousWord]
        }
        bind XText <Shift-Option-Right> {
            xtext_keySelect %W [xtext_nextWord %W insert]
        }
        bind XText <Shift-Option-Up> {
            xtext_keySelect %W [xtext_prevPara %W insert]
        }
        bind XText <Shift-Option-Down> {
            xtext_keySelect %W [xtext_nextPara %W insert]
        }

    } ;# End of Mac only bindings


    # The MouseWheel will typically only fire on Windows.  However,
    # someone could use the "event generate" command to produce one
    # on other platforms.
    #
    # la tag <MouseWheel> ne semble pas fonctionner sous unix
    # (à garder pour windoze)
    bind XText <MouseWheel> {
        %W yview scroll [expr - (%D / 120) * 4] units
        # xtext_style %W apply  -screen  ;# BIDOUILLE EN T
    }
    bind XText <Button-4> {
        %W yview scroll -5 units
    }
    bind XText <Button-5> {
        %W yview scroll  5 units
    }

    # Quelque filtres sur la sélection
    bind XText <$stead(Meta)-semicolon>    {te:sys_fmt  ; break} 
    bind XText <$stead(Meta)-dollar>    {xtext_insert %W -- \u20AC} 
    
    # # # # Modif de la configuration du widget (fontes...)
    # # # # 
    # # # # Augmenter la taille de la fonte de deux points
    # # # bind XText <$stead(Control)-KP_Add>        { xtext_fontEnlarges %W +1 } 
    # # # bind XText <$stead(Control)-plus>          { xtext_fontEnlarges %W +1 } 
    # # # 
    # # # # Diminuer la taille de la fonte de deux points
    # # # bind XText <$stead(Control)-KP_Subtract>   { xtext_fontEnlarges %W -1 } 
    # # # bind XText <$stead(Control)-minus>         { xtext_fontEnlarges %W -1 } 
    # # # 
    # # # # Inverser le poinds de la fonte (bold/normal)
    # # # bind XText <$stead(Control)-asterisk>       {xtext_fontToggleWeight %W  } 
    # # # bind XText <$stead(Control)-KP_Multiply>       {xtext_fontToggleWeight %W  } 
    # Modif de la configuration du widget (fontes...)
    # 
    # Augmenter la taille de la fonte de un point 
    # plus et equal sont plus ou moins pratique suivant AZERTY ou QUERTY
    bind XText <$stead(Meta)-KP_Add>        { xtext_fontEnlarges %W +1 } 
    bind XText <$stead(Meta)-plus>          { xtext_fontEnlarges %W +1 } 
    bind XText <$stead(Meta)-equal>         { xtext_fontEnlarges %W +1 } 
    
    # Diminuer la taille de la fonte de un point
    bind XText <$stead(Meta)-KP_Subtract>   { xtext_fontEnlarges %W -1 } 
    bind XText <$stead(Meta)-minus>         { xtext_fontEnlarges %W -1 } 
    
    # Inverser le poids de la fonte (bold/normal)
    bind XText <$stead(Meta)-asterisk>      {xtext_fontToggleWeight %W  } 
    bind XText <$stead(Meta)-KP_Multiply>   {xtext_fontToggleWeight %W  } 
}
## xtext_applyFindBindings -- créer les binding de recherche sur le widget/tag
# 
# 
# # # proc xtext_applySearchBindings {w widgetOrTag } {
# # #     
# # #     bind $widgetOrTag <$stead(Meta)-e>  {stead:enterSelToSearchFor %W}
# # #     bind $widgetOrTag <$stead(Meta)-E>  {stead:enterSelToReplaceWith %W}
# # # 
# # #     bind $widgetOrTag <$stead(Meta)-r>  {stead:searchBackward %W}
# # #     bind $widgetOrTag <$stead(Meta)-f>  {stead:findBox %W}
# # #     bind $widgetOrTag <$stead(Meta)-g>  {stead:searchForward %W}
# # #     
# # #     bind $widgetOrTag <$stead(Meta)-R>  {stead:searchSelBackward %W}
# # #     bind $widgetOrTag <$stead(Meta)-G>  {stead:searchSelForward %W}
# # #     # RESERVE (en cours de reflexion)  $stead(Meta)-F>
# # #     # - soit :
# # #     #    bind $widgetOrTag <$stead(Meta)-F>  {stead:findBox -fullbox %W}E
# # #     # - soit :
# # #     #    utiliser <$stead(Meta)-F> comme préfixe pour piloter les
# # #     #    nombreuses options de recherche
# # # 
# # #     bind $widgetOrTag <$stead(Meta)-u>  {stead:replace %W}
# # # }

# ./
