package provide stead 2.0


## stead:see -- macro de positionnement sur une ligne 
# 
# syntaxe :  see ?options? where
# 
# Par défaut, le parametre where peut etre :
#   un nombre ou une marque,
#   une chaine de caractere à recherche,
#   vide, ce qui lance une fenetre de dialogue.
# 
# retourne l'index correspond à la position du texte, ou "" si introuvable
# 
# TODO :
#   - deux procédures auxiliaires : seeString et seeIndex spécialisées
#     dans le mode correspondant 
#   - options 
#       -string = -s : recherche d'un chaine
#       -index = -i : recherche d'une marque ou d'une numéro de ligne
#       -auto (default) : devine au mieux quoi chercher !
#       
#       A COMPLÉTER !
# 
# Diverses procédure de recherche (find, get)
#       xtext_getRange {...} qui retourne les index correspondant au text
#               trouvé
#       xtext_tagAdd {...} qui applique un ou des tag au texte trouvé
#       xtext_tagGet retourne le texte correspondant au tag 
#               option : -join <string> pour joindre les intervales
#                       (par défaut : "\n" ou " " ???   A COMPLÉTER !)
#           
#   
proc stead:see { args } {

    global stead
    upvar 0 stead(text) w
    
    # # Ceci est à mettre au point !
    # 
    # la ligne : b  { -type flag  -alias backwards }
    # Ne fonction pas encore (mais f ...  fonctionne !)
    # 
    # f  { -type flag  -eval {set opt(-direction) forwards}  }
    # b  { -type flag  -alias backwards }
    # dir -
    # direction {
    #     -type   flagenum
    #     -values { forwards  backwards }
    # }
    Parsarg_fullSpec -mode strict opt {
        from        1.0
        to          end
        
        set -
        setinsert   {
            -type flag 
            -label "si vrai, on positionne l'insert" 
        }
        strict      flag  
        nocase      flag  
        
        modepat {
            -type   flagenum
            -values {exact glob regexp}
        }
        
        dir -
        direction {
            -type   flagenum
            -values { {forwards f}  {backwards b} }
        }
    
        mode {
            -type   flagenum
            -values {auto string index}
        }
    }
    # Conserver cette spec tant que la précédente n'est pas totalement 
    # testée ! 
    # En faire un exemple de test à intégrer à Parsarg_fullSpec
    # # # Parsarg_fullSpec opt {
    # # #     from        1.0
    # # #     to          end
    # # #     
    # # #     setinsert   {
    # # #         -type flag 
    # # #         -label "si vrai, on positionne l'insert" 
    # # #     }
    # # #     strict      flag  
    # # #     nocase      flag  
    # # #     
    # # #     modepat { -default "exact" -regexp {^exact|glob|regexp$} }
    # # #     exact  { -type flag  -variable opt(-modepat)  -value exact }
    # # #     glob   { -type flag  -variable opt(-modepat)  -value glob }
    # # #     regexp { -type flag  -variable opt(-modepat)  -value regexp }
    # # # 
    # # #     dir         -
    # # #     direction  {-default "forwards"  -regexp {^forwards|backwards$} }
    # # #     
    # # #     fw      -
    # # #     forwards   {-type flag  -variable opt(-direction) -value forwards}
    # # #     bw      -
    # # #     backwards  {-type flag  -variable opt(-direction) -value backwards}
    # # #     
    # # #     mode   { -default "auto" -regexp {^auto|string|index$} }
    # # #     auto   { -type flag  -variable opt(-mode)  -value auto } 
    # # #     string { -type flag  -variable opt(-mode)  -value string } 
    # # #     index  { -type flag  -variable opt(-mode)  -value index }     
    # # # 
    # # # }
    # # ERREUR !! opt(-mode) vaut 0 au leir de "auto"
    # # # set opt(-mode) auto
    # report "Dans stead:see"
    # report -v opt(-mode)
    
    # On prévoit le cas ou on a passé un numéro de ligne au lieu d'un index
    set opt(-from) [xtext_guessIndex $w $opt(-from) 1.0]
    set opt(-to)   [xtext_guessIndex $w $opt(-to)   end]
    
    # Extraction du parametre à rechercher
    set where [lindex $args 0]
    
    # cas où l'on n'a pas précisé le parametre à rechercher
    if {(![string length $where])} {
        if {$opt(-strict)} {
            error "missing parameter to search for" 
        } 
        if {[catch {selection get} sel]} {
            # pas de sélection : on ouvre un dialogue
            set where [te:prompt \
                    -text "Go to where (line index or exact pattern)?"]
            if { ![string length $where] } {
                return ""
            }
        } else {
            # La sélection va servir pour construire l'objet recherché
            set where $sel
        }
    }
    
    # Le parametre "where" est connu, mais que représente-t-il : un
    # index ou une chaine de recherche ??
    
    #Le mode de recherche "index" n'a pratiquemnt pas d'options. Le présence 
    # d'une des options suivantes imposent implicitement le mode de recherche 
    # d'une chaine
    if { $opt(-from) || $opt(-to) || ($opt(-direction)=="backwards") || 
            [regexp {^glob|regexp$} $opt(-modpat)] ||  $opt(-nocase) } {
        set arg(-mode) string
    }
    
    if {$opt(-mode) == "auto"} {
        set guessedIdx [xtext_guessIndex $w $where ""]
        if { ![string length $guessedIdx] } {
            # pas d'index trouvé : 
            # on laisse "where" et on affirme le mode string
            set opt(-mode) string
        } else {
            set where $guessedIdx
            set opt(-mode) index
        }
        
    }
    # report -v  opt(-mode) where
    # 
    # Le mode ainsi que le parametre "where" sont définis
    # 
    
    if {$opt(-mode) == "string"} {

        # On vérifie que les limites de la zone de recherche sont dans 
        # le bon sens
        if {$opt(-direction) == "backwards"} {
            set startIdx [xtext_getLastIndex  $w  $opt(-from) $opt(-to)]
            set endIdx   [xtext_getFirstIndex $w  $opt(-from) $opt(-to)]
        } else {
            set startIdx [xtext_getFirstIndex $w  $opt(-from) $opt(-to)]
            set endIdx   [xtext_getLastIndex  $w  $opt(-from) $opt(-to)]
        }
    
        # Longueur de la chaine trouvée
        set count 0
        set searchCmd [list $w search           \
                            -$opt(-modepat)     \
                            -$opt(-direction)   \
                            -count count        \
                            --                  \
                            $where              \
                            $startIdx           \
                            $endIdx             \
        ]
        set idx [eval $searchCmd]
        
        if { ![string length $idx] } {
            stead:log "Chaine non trouvée : \"$where\""
            return ""
        }
            
        ################################################################
        # visualisation du résultat du mode "string"
        set idx1 [$w index $idx]
        set idx2 [$w index "$idx + ${count}c"]
        if {$opt(-setinsert)} {
            # Déselection automatique par défaut et gestion curseur :
            xtext_select $w $idx1 $idx2
            xtext_setCursor $w insert
        } else {
            # On rend visible sans changer l'insert ni la sélection
            $w tag remove found 1.0 end
            $w tag add found $idx1 $idx2
            $w see $idx1
        }
    } else {
        ################################################################
        # visualisation du résultat du mode "index"
        set idx1 [$w index $where]
        set idx2 $idx1
        if {$opt(-setinsert)} {
            xtext_setCursor $w $idx1
        } else {
            $w see $idx1
        }
    }
    xtext_applyShortHighlight $w "$idx1 linestart" "$idx2 lineend"
    return $idx1
}

## xtext_applyShortHighlight  surligne quelque instant un intervale
# 
# Syntaxe :
#   xtext_applyShortHighlight $w ?options? startIndex endIndex
# 
# Options :
# 
#   -ft
#   -flashtime : temps de surlignement
#   -tags : liste des tags à appiquer (par défaut : {hightlight} )
# 
# TODO :
# Prévoir option flashtime (0 pour permanant). La valeur par défaut de cette
# option sera initialisée par une préférences
# 
proc xtext_applyShortHighlight {w args } {
    
    global EDITPREFS
  
    set opt(-flashtime) $EDITPREFS(flashtime)
    
    Parsarg_fullSpec  opt {
        ft          -
        flashtime   = 
        
        tags        {highlight}
    }
    set startIndex [lindex $args 0]
    set endIndex   [lindex $args 1]
    
    foreach tag $opt(-tags) {
        catch {$w tag remove $tag 1.0 end}
        $w tag add $tag $startIndex $endIndex
        # Eviter le "see" car perturbant si on tape des parenthèses !
        # $w see $startIndex
        after $opt(-flashtime) $w tag remove $tag 1.0 end
    }

}


## xtext_applyTag  TODO généraliation de $w ?-type short? <theTag> args
# 
# w : widget text
# -mode short | clignote | on
# <theTag> 
# args : définit de plusieurs manières le(s) intervales à traiter.
# 

# ./

