# $Id$

namespace eval bookmark {
    hook::add postload_hook [namespace current]::init
    hook::add open_chat_post_hook [namespace current]::on_open_chat
    hook::add close_chat_post_hook [namespace current]::on_close_chat
    hook::add chat_win_popup_menu_hook [namespace current]::popup_menu
    hook::add draw_message_hook [namespace current]::add_bookmark 80
}

proc bookmark::init {} {
    global usetabbar

    if {$usetabbar} {
	bind . <Shift-F3> [list [namespace current]::next_bookmark .]
	catch {bind . <XF86_Switch_VT_3> [list [namespace current]::next_bookmark .]}
	bind . <F3>       [list [namespace current]::prev_bookmark .]
    }
}

proc bookmark::on_open_chat {chatid type} {
    global usetabbar

    if {!$usetabbar} {
	set cw [chat::chat_win $chatid]
	set top [winfo toplevel $cw]
	bind $top <Shift-F3> [list [namespace current]::next_bookmark [double% $cw]]
	catch {bind $top <XF86_Switch_VT_3> [list [namespace current]::next_bookmark [double% $cw]]}
	bind $top <F3>       [list [namespace current]::prev_bookmark [double% $cw]]
    }
}

proc bookmark::on_close_chat {chatid} {
    variable bookmark

    set cw [chat::chat_win $chatid]
    catch { array unset bookmark $cw,* }
}

proc bookmark::popup_menu {m W X Y x y} {
    set groupchat 0
    foreach chatid [chat::opened] {
	if {[chat::chat_win $chatid] == $W} {
	    set groupchat [expr {[chat::is_groupchat $chatid]}]
	    break
	}
    }
    if {!$groupchat} return

    $m add command -label [::msgcat::mc "Prev highlighted"] -accelerator F3 \
        -command [list [namespace current]::prev_bookmark $W]
    $m add command -label [::msgcat::mc "Next highlighted"] -accelerator Shift-F3 \
        -command [list [namespace current]::next_bookmark $W]
}


proc bookmark::get_chatwin {} {
    global usetabbar

    if {!$usetabbar} {
	return ""
    }

    set cw ""
    foreach chatid [chat::opened] {
	if {[.nb raise] == [ifacetk::nbpage [chat::winid $chatid]]} {
	    set cw [chat::chat_win $chatid]
	    break
	}
    }
    return $cw
}

proc bookmark::add_bookmark {chatid from type body x} {
    variable bookmark

    if {$type != "groupchat"} return

    set cw [chat::chat_win $chatid]

    set xlib [chat::get_xlib $chatid]
    set jid [chat::get_jid $chatid]
    set myjid [chat::our_jid $chatid]
    set mynick [chat::get_nick $xlib $myjid $type]
    if {[string equal $jid $from] || [string equal $myjid $from] || \
	    ![check_message $mynick $body]} {
	return
    }
    
    if {![info exists bookmark($cw,id)]} {
	set bookmark($cw,id) 0
    }
    set b [incr bookmark($cw,id)]
    $cw mark set hbookmark$b "end - 1 char"
    $cw mark gravity hbookmark$b left
}

proc bookmark::next_bookmark {cw} {
    variable bookmark

    if {$cw == "."} {
	set cw [get_chatwin]
	if {$cw == ""} return
    }

    set groupchat 0
    foreach chatid [chat::opened] {
	if {[chat::chat_win $chatid] == $cw} {
	    set groupchat [expr {[chat::is_groupchat $chatid]}]
	    break
	}
    }
    if {!$groupchat} return

    if {![info exists bookmark($cw,last)] || \
	    [catch {$cw index $bookmark($cw,last)}]} {
	set bookmark($cw,last) 0.0
    }
    set idx [$cw index $bookmark($cw,last)]
    if {$bookmark($cw,last) == "end" || \
	    (([lindex [$cw yview] 0] == 0 || [lindex [$cw yview] 1] == 1) && \
		([$cw dlineinfo $idx] == {} || \
		[lsearch -exact [$cw tag names $idx] sel] < 0))} {
        set bookmark($cw,last) 0.0
    }
    if {$bookmark($cw,last) == "0.0"} {
	set first_round 0
    } else {
	set first_round 1
    }
    while {($bookmark($cw,last) != {}) || $first_round} {
	if {$bookmark($cw,last) == {}} {
	    set bookmark($cw,last) 0.0
	    set first_round 0
	}
        set bookmark($cw,last) [$cw mark next $bookmark($cw,last)]
        if {[string match "hbookmark*" $bookmark($cw,last)]} {
            break
        }
    }
    if {$bookmark($cw,last) == {}} {
	set bookmark($cw,last) 0.0
    } else {
	$cw tag remove sel 0.0 end
	$cw tag add sel \
	    "$bookmark($cw,last) linestart" \
	    "$bookmark($cw,last) lineend"
	$cw see $bookmark($cw,last)
    }
    return $bookmark($cw,last)
}

proc bookmark::prev_bookmark {cw} {
    variable bookmark

    if {$cw == "."} {
	set cw [get_chatwin]
	if {$cw == ""} return
    }

    set groupchat 0
    foreach chatid [chat::opened] {
	if {[chat::chat_win $chatid] == $cw} {
	    set groupchat [expr {[chat::is_groupchat $chatid]}]
	    break
	}
    }
    if {!$groupchat} return

    if {![info exists bookmark($cw,last)] || \
	    [catch {$cw index $bookmark($cw,last)}]} {
	set bookmark($cw,last) end
    }
    set idx [$cw index $bookmark($cw,last)]
    if {$bookmark($cw,last) == "0.0" || \
	    ([lindex [$cw yview] 1] == 1 && \
		([$cw dlineinfo $idx] == {} || \
		[lsearch -exact [$cw tag names $idx] sel] < 0))} {
        set bookmark($cw,last) end
    }
    if {$bookmark($cw,last) == "end"} {
	set first_round 0
    } else {
	set first_round 1
    }
    while {($bookmark($cw,last) != {}) || $first_round} {
	if {$bookmark($cw,last) == {}} {
	    set bookmark($cw,last) end
	    set first_round 0
	}
        set bookmark($cw,last) [$cw mark previous $bookmark($cw,last)]
        if {[string match "hbookmark*" $bookmark($cw,last)]} {
            break
        }
    }
    if {($bookmark($cw,last) == {})} {
	set bookmark($cw,last) end
    } else {
	$cw tag remove sel 0.0 end
	$cw tag add sel \
	    "$bookmark($cw,last) linestart" \
	    "$bookmark($cw,last) lineend"
	$cw see $bookmark($cw,last)
    }
    return $bookmark($cw,last)
}

