
# fonctionnalites de recherche/remplacement regulier ou non dans
# le widget texte entier, la selection,...
package provide stead 2.0


# A faire : 
#   stead:find ?option? ?--? ?string?  EN COURS 
#   
#   xtext_find $w [-next | -prev | -all]  <pat> <idx1> <idx2>
#   xtext_find $w -prev -startword <idx1> <idx2>
# 
#   xtext_findNext $w ?option? 
#      Return indice ou {}
#           -endword
#           -startword
#           -endwordbreak
#           -startwordbreak
#           -startpara
#           -endpara
#           -word -index <index> (défaut insert)
#           -regexpGlobal | -regexpLine | -exact
#           -nocase
#           -direction <backwards | forwards>
#           -count <varName>
#           -tags <tagList>
#           
#   xtext_findAll $w ?option?
#      Return liste paire d'indices ou {}
#           -tags <tagList>
# 
# 
# A FAIRE :
# ---------
#   Déporter le coeur de ces procédure dans xtext.
#   xtext_find devra gérer l'état de la recherche remplacement ainsi 
#   que les varaibles :
#       - xtext(find,-case)
#       - xtext(find,-mode)  <exact | regexpLine | regexpGlobal)
#       - ...
#   Les procédures de stead ne seront la que pour
#     - saisie graphiquement ces options (stead:findBox), 
#     - afficher les messages d'information, demande de confirmation, ...
# 
# 
 ## stead:findAssureInit -- initialisation de qq variable
 ## stead:findBox ?options? t - search-and-replace panel for text widget t
 ## stead:enterSelToSearchFor - mémo selection dans variable de recherche
 ## stead:enterSelToReplaceWith - mémo selection dans variable de remplacement
 ## stead:searchForward - cherche dans le sens normal
 ## stead:searchBackward - cherche dans le sens inverse
 ## stead:searchSelForward - cherche la selection en avant
 ## stead:searchSelBackward - cherche la selection en arriere
 ## stead:replace - remplace la selection par la chaine de remplacement
 ## stead:replaceSelected_private -- A REMPLACE PAR UN APPEL A xtext_insert
 ## stead:replaceThenSearchAgain - remplace la selection par la
 ##         chaine de remplacement et recherche de nouveau
 ## stead:replaceInSel - remplace dans la selection par la
 ## stead:replaceAll - remplace dans tous le fichier par la
 ## stead:find -- 
 ## xtk_labeledEntry - entry avel label et variable associée




## stead:findAssureInit -- initialisation de qq variable
#
# création md 03/10/2001
#
proc stead:findAssureInit {} {
    upvar #0 steadFindState state
    
    # Il se peut que certaines variables soit affectées avant une recherche
    #  (par exemple : on entre la chaine de recherche avant de lancer la boite)
    if { ![info exists state(searchFor)] }   { set state(searchFor)      "" }
    if { ![info exists state(replaceWith)] } { set state(replaceWith)    "" }
    if { ![info exists state(backwards)] }   { set state(backwards)       0 }
    if { ![info exists state(nocase)] }      { set state(nocase)          1 }
    if { ![info exists state(mode)] }        { set state(mode)        exact }
    if { ![info exists state(subst)] }       { set state(subst)           0 }
}

## stead:findBox ?options? t - search-and-replace panel for text widget t
#
# option is:
#   -replace (default 1)
# if $replace, the replace box and buttons will be drawn, otherwise
#   it'll only be a search panel
# 
# A FAIRE : VIRER LE PARAMETRE w : car cette boite est multi documents
# 
# NE PLUS UTILSER L'OPTION -replace 0 (fonctionnalité supprimée)
# 
proc stead:findBox { w args} {

    global stead
    
    # Remarque : attention il y a besoin d'accéder au nom réel de cette 
    # variable globale pour la gestion des élènement (création des 
    # binding, ...)
    upvar #0 steadFindState state

    stead:findAssureInit
    
    Parsarg_fullSpec opt {
        replace 1
    }
    
    if {[winfo exists .find]} {
        wm withdraw .find
        wm deiconify .find                  ;# just try to make it visible
        focus .find.t.search.e              ;# and focus on the search field
        xentry_selectAll .find.t.search.e 
        return 0
    }
    
    # La Classe servira pour configurer les fontes...
    toplevel .find -class Stead
    
    frame .find.t

    # Attention le nom réel de la variablke est steadFindState() et non pas
    # state() qui n'est qu'un alias local 
    # Par ailleurs, -exportselection 0 est déja traité par XEntry
    # 
    xtk_labeledEntry .find.t.search \
          -label "Search for:" \
          -variable steadFindState(searchFor) \
          -exportselection 0
          
    xtk_labeledEntry .find.t.replace \
          -label "Replace with:" \
          -variable steadFindState(replaceWith) \
          -exportselection 0
    
    
    # A FAIRE
    # 
    # Modifier la classe Stead pour quelles ne dépende plus de widget %W
    # (en utilisant "stead(activeDoc)")
    # 
    bindtags .find              {.find Find all}
    bindtags .find.t.search.e   {.find.t.search.e  Find FindEntry XEntry All}
    bindtags .find.t.replace.e  {.find.t.replace.e Find FindEntry XEntry All}

    frame .find.t.options
    label .find.t.options.filler -text {} -width 16 -anchor e
    
    # Bouton de direction  "backwards"
    checkbutton .find.t.options.backwards \
          -relief flat \
          -anchor w \
          -text "Backwards" \
          -variable steadFindState(backwards) \
          -command {
                if {$steadFindState(mode) == "regexp"} {
                    set steadFindState(backwards) 0
                }
           }
           
    # Bouton "Ignore majuscule"  "nocase"
    checkbutton .find.t.options.nocase \
          -relief flat \
          -anchor w \
          -text "Ignore Case" \
          -variable steadFindState(nocase)
          
    # Les 3 Boutons radio de mode de recherche (exact|regexpLine|regexpGlobal)
    radiobutton .find.t.options.mode_exact \
          -relief flat \
          -anchor w \
          -text "Exact" \
          -value "exact" \
          -variable steadFindState(mode)
          
    radiobutton .find.t.options.mode_regexpLine \
          -relief flat \
          -anchor w \
          -text "Regexp (By Line)" \
          -value "regexpLine" \
          -variable steadFindState(mode)
          
    radiobutton .find.t.options.mode_regexpGlobal \
          -relief flat \
          -anchor w \
          -text "Regexp (global)" \
          -value "regexpGlobal" \
          -variable steadFindState(mode)


    # Description d'un bouton : 
    #  set  buttons(nom)  { nom label command }
    
    set buttons(cancel) {cancel Cancel {destroy .find}}

    set buttons(search) {
        search Search { 
            stead:find $::stead(text) 
        } 
    }
    
    set buttons(searchAndClose) {
        searchAndClose "Search and close" { 
            xtk_invokeButton .find.b1.search
            xtk_invokeButton .find.b1.cancel
        }
    }
    
    set buttons(replace) {
       replace Replace  {
           stead:replace $::stead(text)
       }
    }

    set buttons(replace_search_again) {
        replace_search_again "Replace and Search Again"  {
             stead:replaceThenSearchAgain $::stead(text)
        }
    }
    set buttons(replace_all) {
        replace_all "Replace All"  {
             stead:replaceAll $::stead(text)
        }
    }
    set buttons(replace_in_sel) {
        replace_in_sel "Replace in Selection"  {
           stead:replaceInSel $::stead(text)
        }
    }

    te:buttonbar .find.b1 \
            -default searchAndClose \
            -buttons [list \
                $buttons(searchAndClose) \
                $buttons(search) \
                $buttons(replace) \
                $buttons(cancel) \
    ]
    te:buttonbar .find.b2 \
            -buttons [list \
                $buttons(replace_search_again) \
                $buttons(replace_all) \
                $buttons(replace_in_sel) \
    ]

    checkbutton .find.b2.subst \
          -relief flat \
          -anchor w \
          -text "Post Tcl Substitution" \
          -variable steadFindState(subst)
      
    pack append .find.b2 \
            .find.b2.subst   {left expand fillx}




    pack append .find.t.options \
            .find.t.options.filler      {left fill} \
            .find.t.options.backwards   {left fill} \
            .find.t.options.nocase      {left fill} \
            .find.t.options.filler      {left fill}
            
    pack append .find.t.options \
            .find.t.options.mode_exact        {left fill} \
            .find.t.options.mode_regexpLine   {left fill} \
            .find.t.options.mode_regexpGlobal {left fill}

    pack append .find.t \
          [xtk_filler .find.t]   {top} \
          .find.t.search         {top expand fillx}

    
    pack append .find.t [xtk_filler .find.t] {top} \
                        .find.t.replace {top expand fillx}
                            
    pack append .find.t  .find.t.options {top expand fill}
    pack append .find .find.t {top fill padx 10 pady 5} \
                        [xtk_rule .find] {top fillx} \
                        .find.b2 {bottom fillx} \
                        .find.b1 {bottom fillx}

    # 
    # Les bindings de la boite de recherche
    # 
    
    # Commutation du focus entre les deux champs par <Tab>
    #
    bind .find.t.replace.e <Tab>       {
        focus .find.t.search.e 
        xentry_selectAll .find.t.search.e 
    } 
    bind .find.t.replace.e <Shift-Tab>       {
        focus .find.t.search.e 
        xentry_selectAll .find.t.search.e 
    } 

    bind .find.t.search.e <Tab>        {
        focus .find.t.replace.e 
        xentry_selectAll .find.t.replace.e 
    } 
    bind .find.t.search.e <Shift-Tab>        {
        focus .find.t.replace.e 
        xentry_selectAll .find.t.replace.e 
    } 


    # Supprimer cette redondance (plus tard, par une procédure de 
    # stead (et non pas de xtext !!) )
    # 
    bind Find <$stead(Meta)-e>  {stead:enterSelToSearchFor $stead(text)}
    bind Find <$stead(Meta)-E>  {stead:enterSelToReplaceWith $stead(text)}

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

    bind Find <$stead(Meta)-u>  {stead:replace $stead(text)}
    bind Find <$stead(Meta)-U>  {stead:replaceThenSearchAgain $stead(text)}

    foreach seq {<Return> <KP_Enter>} {
        bind Find $seq {
            # # # xtk_invokeButton .find.b1.search
            # # # destroy .find
            xtk_invokeButton .find.b1.searchAndClose
            destroy .find
        }
    }
    
    foreach seq $stead(cancelBindSequence) {
        bind Find $seq {
            xtk_invokeButton .find.b1.cancel
            destroy .find
        }
    }
    
    # Positionnement final 
    # 
    wm title .find "[file tail $stead(file)]: Find Panel"
    xtk_placeWindow .find

    focus .find.t.search.e
    xentry_selectAll .find.t.search.e 
}


## stead:enterSelToSearchFor - mémo selection dans variable de recherche
#
proc stead:enterSelToSearchFor {w} {

    upvar #0 steadFindState state
    
    set sel [xtext_getSel $w]
    if { [string length $sel] }  {
        set state(searchFor) $sel
    } else {
        stead:log -error "No selection to enter in search entry"
    }
}
## stead:enterSelToReplaceWith - mémo selection dans variable de remplacement
#
proc stead:enterSelToReplaceWith {w} {

    upvar #0 steadFindState state

    set sel [xtext_getSel $w]
    if { [string length $sel] } {
        set state(replaceWith) $sel
    } else {
        stead:log -error "No selection to enter in replace entry"
    }
}

## stead:searchForward - cherche dans le sens normal
#
proc stead:searchForward {w} {
    upvar #0 steadFindState state
    stead:findAssureInit
    set state(backwards) 0
    stead:find $w -restart 1 
}

## stead:searchBackward - cherche dans le sens inverse
#
proc stead:searchBackward {w} {
    upvar #0 steadFindState state
    stead:findAssureInit
    set state(backwards) 1
    stead:find $w -restart 1 
}

## stead:searchSelForward - cherche la selection en avant
#
proc stead:searchSelForward {w} {

    upvar #0 steadFindState state
    stead:findAssureInit

    set state(backwards) 0
    set sel [xtext_getSel $w]

    if { ![string length $sel] } {
        stead:findBox $w
    } else {
        if {[stead:find $w -- $sel] == 0} {
            stead:log -error "Selection not found forwards : \"$sel\"."
        }
    }
}

## stead:searchSelBackward - cherche la selection en arriere
#
proc stead:searchSelBackward {w} {

    upvar #0 steadFindState state
    stead:findAssureInit

    set state(backwards) 1
    set sel [xtext_getSel $w]

    if { ![string length $sel] } {
        stead:findBox $w
    } else {
        if {[stead:find $w -- $sel] == 0} {
            stead:log -error "Selection not found backwards : \"$sel\"."
        }
    }
}

## stead:replace - remplace la selection par la chaine de remplacement
# 
# Surcouche (nécessaire) à "stead:replaceSelected_private"
# 
# TODO : faire appel à xtext_replaceInSel ou à string_replace !!!
# 
proc stead:replace {w} {

    upvar #0 steadFindState state
    stead:findAssureInit

    # Le test de state(searchFor) n'est pas forcément nécessaire ?
    if { ![xtext_hasSel $w] || ![string length $state(searchFor)] } {
        stead:log -error "Replace : There is nothing to replace "
        stead:findBox $w
        return 0
    } else {
    
        # essai diam 31/10/01
        # 
        # # set sel [xtext_getSel $w]
        # # stead:replaceSelected_private $w $state(replaceWith)
        # # xtext_updateFocusIn $w
        set cmd [list  xtext_replaceInSel $w -mode $state(mode)]
        if {$state(nocase)} {
            lappend cmd -nocase
        }
        lappend cmd -count ::steadFindState(count)
        if {$state(subst)} {
            lappend cmd -subst
        }
        lappend cmd -- $state(searchFor) $state(replaceWith)
        
        eval $cmd
        
        # NE MARCHE PAS CAR "count" est affectée par string_replace, mais
        # non retransmise par xtext_replaceInSel ni par xtext_applyToSel !
        #  
        stead:log "Nbre de remplacement effectué : $state(count)"
        
        return 1
    }
}

## stead:replaceSelected_private -- A REMPLACE PAR UN APPEL A xtext_insert
# 
# A FAIRE : 
# 
#   - vérifier que ceci fonctionne :
#           ([A-Z])_([A-Z]) --> \2_\1
#           
#   - prévoir flag -postsubst  pour faire utilser dans replace : 
#           \n \0x41 $F [incr i]
# 
#   - Fiare nouvelle proc :
#        xtext_replace $w -regexp 
#     
proc stead:replaceSelected_private { w string {checkpoint 1}} {

    upvar #0 steadFindState state
    stead:findAssureInit

    if {![xtext_hasSel $w]} {
        return 0
    }

    # si on est en recherche régulière on remplace avec regsub
    if { $state(mode) == "regexpLine" || $state(mode) == "regexpGlobal" } {
        set sel [xtext_getSel $w]
        regsub $state(searchFor) $sel $string string
    } 
    xtext_insert $w -push $checkpoint $string
    return 1
}


## stead:replaceThenSearchAgain - remplace la selection par la
##         chaine de remplacement et recherche de nouveau
#
proc stead:replaceThenSearchAgain {w} {

    upvar #0 steadFindState state
    stead:findAssureInit

    set ok [stead:replace $w]
    if {$ok} {
        stead:find $w
    } else {
        stead:log -error "Replace then Search again: nothing to replace."
    }
}

## stead:replaceInSel - remplace dans la selection par la
# chaine de remplacement
#
proc stead:replaceInSel {w} {

    upvar #0 steadFindState state
    stead:findAssureInit


    # nombre de remplacement
    set rep_num 0

    # selection
    set sel [xtext_getSel $w]

    # si la chaine de remplacement est vide, on demande confirmation
    # pour effacer la chaine de recherche.

    if { ! [string length state(replaceWith)] } {

        set reply [stead:messageBox                                      \
                -type okcancel                                           \
                -default ok                                              \
                -message "Delete $state(searchFor) \nin all selection ?" \
                -title  "Replace in Selection"                           \
        ]
        if {$reply == "cancel"} {
            return
        }
    }

    if { ! [xtext_hasSel $w] } {

        # sinon, si pas de sélection : message d'alerte
        stead:log -error "Replace in selection : There is no selection"
        return 
        
    } elseif {"x$state(searchFor)" == "x"} {
        # sinon, si pas de chaine de recherche, on affiche la boite find
        stead:log -error "Replace in selection : Please enter search string"
        stead:findBox $w
        return
      
    }
    
    set cmd [list  xtext_replaceInSel $w  \
                    -$state(mode) \
                    -count ::steadFindState(count) ]
    
    if {$state(nocase)} {
        lappend cmd "-nocase"
    }
    if {$state(subst)} {
        lappend cmd "-subst"
    }
    
    lappend cmd "--" $state(searchFor) $state(replaceWith)

    eval $cmd
    
    stead:log  "nbre de remplacement effectués : $state(count) "
    
    return

}

## stead:replaceAll - remplace dans tous le fichier par la chaine de
##                    remplacement
#
proc stead:replaceAll {w} {

    upvar #0 steadFindState state
    stead:findAssureInit

    if { ![string length $state(replaceWith)] } {
        set reply [stead:messageBox                                 \
                -type okcancel                                      \
                -default ok                                         \
                -message "Delete $state(searchFor) \nin all text?"  \
                -title  "Replace in Selection"                      \
        ]
        if {$reply == "cancel"} {
            return
        }
    }

    if { ![string length $state(searchFor)] } {
        stead:log -warning "Replace All : Please enter Search String"
        return
    }

    set cmd [list  xtext_replaceAll $w  \
                    -$state(mode)       \
                    -count ::steadFindState(count) ]
    
    if {$state(nocase)} {
        lappend cmd "-nocase"
    }
    
    if {$state(subst)} {
        lappend cmd "-subst"
    }
    
    # ATTENTION : pas de "--" dans xtext_replaceAll !
    lappend cmd "--" $state(searchFor) $state(replaceWith)
    
    eval $cmd
    
    stead:log  "nbre de remplacement effectués : $state(count) "

    return

}

# stead:find -- recherche et sélectionne une chaine  EN COURS 
#    
# Recherche et sélectionne  dans le document courant la chaine 
# en fonction des options de recherche prédéfinies, ecrasables
# par celles passées en parametre.
# (fait seulement appel à stead:findBox si pas de chaine à rechercher)
# 
# Syntaxe :
# 
#    stead:find ?option? ?--? ?string?
# 
# retourne :
#   1 si trouvé
#   0 sinon
#  
# options :
#   -b
#   -backwards
#   -f
#   -forwards
#   
#   -d
#   -dir
#   -direction <backwards|forwards>
#   
#   -nocase  (flag)
#   
#   -mode <exact | regexpLine | regexpGlobal>
#   
#   -restart (flag) : si pas trouvé, recommence la recherche à l'autre
#           extrémité.
#    
#   
## stead:find -- 
# 
# 
proc stead:find { w args } {
    global stead
    upvar #0 steadFindState state
    
    stead:findAssureInit
    
    if {$state(backwards)} {
        set  opt(-direction) "backwards"
    } else {
        set  opt(-direction) "forwards"
    }
    set opt(-nocase)     $state(nocase)
    set opt(-mode)       $state(mode)
    # set opt(-fromidx)    -1 ;# EN DEVELOPPEMENT
    
    Parsarg_fullSpec opt {
        d -
        dir -
        direction {
            -type flagenum
            -values {forwards backwards}
            -default =
        }
        f {
            -type flag
            -variable opt(-direction)
            -default =
            -value forwards
        }
        b {
            -type flag
            -variable opt(-direction)
            -default =
            -value backwards
        }
        
        m -
        mode {
            -type flagenum
            -values {exact regexpLine regexpGlobal}
            -default =
        }
        fromidx {
            -type string
            -variable opt(-fromidx)
            -default -1
        }
        
        nocase {
            -type flag
            -variable opt(-nocase)
            -default =
            -value 1
            -label "Si flag présent : insensible à la casse."
        }
        
        restart {
            -type boolean
            -default 1
            -value 0
            -label "Si valeur vraie : propose de reboucler si pas trouvé."
        }
    }
    # Autre solution pour une option -nocase **avec** valeur
    #     nocase {
    #         -type boolean
    #         -variable opt(-nocase)
    #         -default =
    #         -value 0
    #         -label "Si valeur vrai : insensible à la casse."
    #     }
    #     nocase {
    #         -type flag
    #         -variable opt(-nocase)
    #         -default =
    #         -value 1
    #         -label "Si flag présent : insensible à la casse."
    #     }
        
        
    set pat [lindex $args 0]
    if {![string length $pat]} {
        set pat $state(searchFor)
    } 
    if {![string length $pat]} {
        stead:findBox $stead(text)
        return 0
    } 
    
    # Début de la recherche : l'insert en général, mais dépend de la sélection 
    # et de la direction de recherche
    # # if {![xtext_hasSel $w]} {
    # #     set startIdx [$w index insert]
    # # } else {
    # #     # Il y a une sélection
    # #     if {$opt(-direction) == "backwards"} {
    # #         set startIdx [xtext_moveCursor $w -backwards 1 -nomove]
    # #     } else {
    # #         set startIdx [xtext_moveCursor $w -forwards 1  -nomove]
    # #     }
    # # }
    # # # Fin de la recherche : dépend de la direction de recherche 
    # # if {$opt(-direction) == "backwards"} {
    # #     set stopIdx 1.0
    # # } else {
    # #     set stopIdx end
    # # }
    if {$opt(-fromidx) != -1} {
        set startIdx $opt(-fromidx)
    } elseif {![xtext_hasSel $w]} {
        set startIdx [$w index insert]
    } else {
        # Il y a une sélection
        if {$opt(-direction) == "backwards"} {
            set startIdx [xtext_moveCursor $w -backwards 1 -nomove]
        } else {
            set startIdx [xtext_moveCursor $w -forwards 1  -nomove]
        }
    }
    # Fin de la recherche : dépend de la direction de recherche 
    if {$opt(-direction) == "backwards"} {
        set stopIdx 1.0
    } else {
        set stopIdx end
    }
    
    
    if {$opt(-mode) == "regexpGlobal"} {
    
        # On doit extraire le texte depuis l'insert jusqu'à la fin car
        # "$w search" ne traite pas ce cas là.
        # De plus, l'option "-backwards 1" n'est pas supportée dans 
        # ce mode.
        set text [$w get $startIdx end]        
        
        if {$opt(-nocase)} {
            set cmd [list regexp -indices -nocase -- $pat $text foundRange]
        } else {
            set cmd [list regexp -indices         -- $pat $text foundRange]
        }
        
        if {[eval $cmd]} {
            set found 1
            set firstIdx [$w index "insert + [lindex $foundRange 0] c"]
            set lastIdx  [$w index "insert + [lindex $foundRange 1] c + 1 c"]
            # report -v cmd pat foundRange  firstIdx lastIdx
        } else {
            set found 0
        }
        
    } else {
            
        # $opt(-mode) vaut soit "exact" soit "regexpLine"
        # Le widget text doit recevoir "-regexp" au lieu de "regexpLine"
        if { $opt(-mode) == "regexpLine"} {
            set mode "regexp"
        } else {
            set mode "exact"
        }
        
        
        if {$opt(-nocase)} {
            set cmd [list $w search -nocase ]
        } else {
            set cmd [list $w search         ]
        }
        lappend cmd -$mode \
                    -$opt(-direction) \
                    -count count \
                    -- \
                    $pat \
                    $startIdx \
                    $stopIdx
        
        set firstIdx [eval $cmd]
                        
        if {[string length $firstIdx]} {
            set found 1
            set lastIdx [$w index "$firstIdx + $count c"]
        } else {
            set found 0
        }
    }
    # stead steae steaf steac steaD  (pour essai de stead:find)
    ####################################################################
    if {$found} {
        xtext_select $w $firstIdx $lastIdx
        $w see insert
        xtext_updateFocusIn $w
        return [$w index sel.first]
    } else {
        # Pas trouvé. Suivant option : on recommance la recherche depuis
        # l'autre extémité
        if {$opt(-restart)} {
            if {$opt(-direction) == "backwards"} {
                set restartIdx end
                set msg   "\"$pat\" not found backwards !\n \
                           Restarting from end of file?"   \
            } else {
                set restartIdx 1.0
                set msg   "\"$pat\" not found forwards !\n \
                           Restarting from start of file?"   \
            }

            set reply [stead:messageBox                     \
                    -type okcancel                          \
                    -default ok                             \
                    -message $msg                           \
                    -title  "Find"                          \
            ]                                          
            if {$reply == "ok"} {
                # CECI MARCHERA QUAND l'option -case ne sera plus un flag !
                # xtext_setCursor $w $restartIdx
                # set cmd [list stead:find $w                       \
                #                   -fromidx  $restartIdx           \
                #                   -restart 0                      \
                #                   -direction $opt(-direction)     \
                #                   -mode $opt(-mode)               \
                #                   -nocase $opt(-nocase)           \
                #                   --  $pat                        \
                # ]
                set cmd [list stead:find $w                       \
                                  -fromidx  $restartIdx           \
                                  -restart 0                      \
                                  -direction $opt(-direction)     \
                                  -mode $opt(-mode)               \
                ]
                if {$opt(-nocase)} {
                    lappend cmd -nocase
                }
                lappend cmd --  $pat 
                
                
                
                return [eval $cmd]        
            }            

        } else {
            return 0
        }
    }
    
}

## xtk_labeledEntry - entry avel label et variable associée
#
# Options :
#   -label       (default "Value:")
#   -variable    (default value - not really optional)
#   -labelwidth  (default 16)
#   -entrywidth  (default 40)
#   -labelconfig (default "")
#   -entryconfig (default "")
#
# labelconfig and entryconfig are lists of additional configuration
#   options to control the appearance of the label and the entry
# BOGUSNESS:  you need to know that the entry is $newframe.e
#   in order to bind to it!
#
# Historique :
#   version initiale de Jay Sekoka (jstools)
#   diam@ensta.fr 02/10/96 : rajout option -exportselection
#
proc xtk_labeledEntry {newframe args} {
    Parsarg_fullSpec opt   {
        label             Value:
        variable          value
        exportselection   1
        labelwidth        16
        entrywidth        60
        labelconfig       ""
        entryconfig       ""
    }
    # Correction bug le 29/01/05
    # puts "\$opt(-variable)=$opt(-variable)"
    #    => $opt(-variable)=steadFindState(searchFor)
    #    
    # Résultat sous wish8.5 (suite à menu Find...") => 
    #     bad variable name "steadFindState(searchFor)": 
    #     upvar won't create a scalar variable that looks like an array element
    # 
    # Solution : 
    # commenter la ligne suite, car de toute façon, cette variable est passée
    # à "entry ... -textvariable ..." est concidérée comme globale.
    # 
    # 
    # global $opt(-variable)   ;# idem avec global [set opt(-variable)]

    frame $newframe
    set l $newframe.l
    set e $newframe.e
    label $l -text $opt(-label) -width $opt(-labelwidth) -anchor e
    entry $e -relief sunken \
             -width $opt(-entrywidth) \
             -textvariable $opt(-variable) \
             -exportselection $opt(-exportselection)

    if {$opt(-labelconfig) != ""} {
        eval $l configure $opt(-labelconfig)
    }
    if {$opt(-entryconfig) != ""} {
        eval $e configure $opt(-entryconfig)
    }
    pack $l -in $newframe -side left -fill both
    pack $e -in $newframe -side left -fill both

    return $newframe
}
#./

