#!/bin/bash
# *******************************************************************
# **  @file browse-packages.cui.sh - curses based backage browser
# **
# **  Creation:     2016-06-18 dv
# **  Last update:  $Id: browse-packages.cui.sh 43349 2016-09-15 11:42:42Z hbfl $
# **
# **  Copyright (c) 2016-2017 the eisfair team, team(at)eisfair(dot)org
# **
# **  This program is free software; you can redistribute it and/or modify
# **  it under the terms of the GNU General Public License as published by
# **  the Free Software Foundation; either version 2 of the License, or
# **  (at your option) any later version.
# *******************************************************************

. /var/install/include/cuilib
. /var/install/include/eismanlib


IDC_PACKAGE_LIST='1000'
IDC_HELPTEXT='1010'
IDC_TIMER='1020'

IDC_LOAD_PROGRESS='2000'

TEXT_WINDOW_HANDLE=""


DEF_STATUS_PREFIX="Commands:"
DEF_STATUS_TEXT="${DEF_STATUS_PREFIX} F1=Help F3=View Details F7=Install F8=Uninstall F10=Exit"


# *******************************************************************
# **  helper routines
# *******************************************************************

# *******************************************************************
# **  get first result for a given field returned from eisman query
# **  @param  $1  field name
# **  @param  $2  package name
# **  @param  $3  version of the package
# **  @param  $4  query options
# **  @return n/a
# *******************************************************************

query_first()
{
    local field="${1}"
    local name="${2}"
    local version="${3}"
    local options="${4}"

    local result=$(eisman query ${options} --unstable --fields="$field" "${name}" "${version}")

    local IFS_BAK=$IFS
    IFS="
"

    for line in $result
    do
        if [ "${line:0:3}" = "---" ]
        then
            IFS=${IFS_BAK}
            return
        else
            echo "${line:$FIELDHEADER} "
        fi
    done

    IFS=${IFS_BAK}
}


# *******************************************************************
# **  wait message popup
# *******************************************************************

# *******************************************************************
# **  wait_create_hook (creates child windows for wait popup message)
# **  @param  $p2  window handle
# **  @return n/a
# *******************************************************************

wait_create_hook()
{
    local win="${p2}"

    if cui_label_new "${win}" "" \
        0 0 26 1                 \
        0                        \
        "${CWS_NONE}" "${CWS_BORDER}"
    then
        local ctrl="${p2}"
        cui_window_settext "${ctrl}" "Searching, please wait..."
        cui_window_create  "${ctrl}"
    fi

    cui_return 1
}


# *******************************************************************
# **  load data / show progress
# *******************************************************************

# *******************************************************************
# **  progress_create_hook (for creation of child windows)
# **  @param  $p2  window handle
# **  @return n/a
# *******************************************************************

progress_create_hook()
{
    local win="${p2}"

    if cui_progress_new "${win}" "" \
        0 0 32 1                    \
        "${IDC_LOAD_PROGRESS}"      \
        "${CWS_NONE}" "${CWS_BORDER}"
    then
        local ctrl="${p2}"

        cui_progress_setrange "${ctrl}" 100
        cui_progress_setpos   "${ctrl}" 0
        cui_window_create     "${ctrl}"
    fi
    cui_return 1
}


# *******************************************************************
# **  update progress bar
# **  @param  $1  dialog handle
# **  @param  $2  position
# **  @return n/a
# *******************************************************************

progress_update()
{
    local win="${1}"
    local pos="${2}"

    if cui_window_getctrl "${win}" "${IDC_LOAD_PROGRESS}"
    then
        local ctrl="${p2}"
        if cui_valid_handle "${ctrl}"
        then
            cui_progress_setpos "${ctrl}" "${pos}"
        fi
    fi

    cui_update
}


# *******************************************************************
# **  read all installed packages and convert them into a
# **  single string
# **  @param  $1  fields to query
# **  @return n/a
# *******************************************************************

query_installed_packages()
{
    local ipackages=$(mktemp -p /tmp "ipackages_"XXXXXXXX)
    local fields=${1}
    local header=$((${FIELDHEADER} + 1))
    local one
    local two

    unset $created_inst_vars
    created_inst_vars=""

    (eisman query --installed --unstable --fields="${fields}" |
         cut -c "${header}-") > "${ipackages}"

    while read -r
    do
        local line=$REPLY
        if [ -n "${line}" ]
        then
            if [ "${line:0:3}" =  "---" ]
            then
                if [ -n "${one}" ] && [ -n "${two}" ]
                then
                    two="${two//./_}"
                    two="${two//-/_}"
                    two="${two//+/_}"
                    eval inst_"${two}"="${one}"
                    created_inst_vars="$created_inst_vars inst_$two"
                fi
                one=""
                two=""
            else
                two="${one}"
                one="${line}"
            fi
        fi
    done < "${ipackages}"
    rm -f "${ipackages}"
}


# *******************************************************************
# **  read data from file and transfer it into the listview
# **  @param  $1 --> mainwin window handle
# **  @return n/a
# *******************************************************************

browser_readdata()
{
    local win="${1}"
    local idx=0

    local name
    local status
    local version
    local url
    local short
    local date

    local sel='0'
    local progress='0'
    local linecount='0'
    local linetotal

    query_installed_packages "name|version"

    if cui_window_new "${win}" \
        0 0 34 3               \
        $((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))
    then
        local dlg="${p2}"
        if cui_valid_handle "${dlg}"
        then
            cui_window_setcolors "${dlg}" "DIALOG"
            cui_window_settext   "${dlg}" "Loading data"
            cui_window_sethook   "${dlg}" "${HOOK_CREATE}"  progress_create_hook
            cui_window_create    "${dlg}"
            cui_update


            # read user inforamtion
            if cui_window_getctrl "${win}" "${IDC_PACKAGE_LIST}"
            then
                local ctrl="${p2}"

                if cui_valid_handle "$ctrl"
                then
                    cui_listview_getsel   "$ctrl" && sel="$p2"
                    cui_listview_clear    "$ctrl"

                    # get total number of lines in index
                    linetotal=$(wc -l < ${browsefile})

                    # read browse data line by line
                    while read -r
                    do
                        local line=$REPLY
                        local field="${line:0:${FIELDHEADER}}"
                        local data="${line:${FIELDHEADER}}"

                        if [ "${field}" = "-----------" ]
                        then
                            if [ -n "${name}" ]
                            then
                                if cui_listview_add "${ctrl}"
                                then
                                    local index="$p2"

                                    local istatus="-"
                                    local varname

                                    varname="${name//./_}"
                                    varname="${varname//-/_}"
                                    varname="${varname//+/_}"
                                    eval local iversion='$'inst_"${varname}"
                                    if [ -n "${iversion}" ]
                                    then
                                        local result=$(diff_version "${version}" "${iversion}")
                                        case "${result}" in
                                        "installed")
                                            istatus="inst."
                                            ;;
                                        "old")
                                            istatus="old"
                                            ;;
                                        "new")
                                            istatus="new"
                                            cui_listview_hilight "${ctrl}" "${index}" "0" "1"
                                            ;;
                                        *)
                                            ;;
                                        esac
                                    fi

                                    cui_listview_setrowtext "${ctrl}" \
                                        "${index}"                    \
                                        "${istatus}|${name}|${version}|${status}|${date}|${short}|${url}"
                                fi
                            fi

                            name=""
                            status=""
                            version=""
                            url=""
                            short=""
                            date=""

                            if [ ${idx} -ge 50 ]
                            then
                                linecount=$((${linecount} + ${idx}))
                                progress=$((${linecount} * 100 / ${linetotal}))
                                progress_update "${dlg}" "${progress}"
                                idx=0
                            fi
                        else
                            case "${field}" in
                            name*)
                                name="${data}"
                                ;;
                            status*)
                                status="${data}"
                                ;;
                            version*)
                                version="${data}"
                                ;;
                            url*)
                                url="${data}"
                                ;;
                            short*)
                                short="${data}"
                                ;;
                            date*)
                                date="${data}"
                                ;;
                            esac
                        fi

                        # update progress
                        idx=$((${idx} + 1))

                    done < ${browsefile}
                fi
            fi
            progress_update "${dlg}" "100"
            usleep 100000
            cui_window_destroy  "${dlg}"
        fi
    fi
}


# *******************************************************************
# **  update status field in list view
# **  @param  $1 --> list view window handle
# **  @return n/a
# *******************************************************************

update_line_status()
{
    local ctrl="${1}"
    local package
    local version

    if cui_listview_getsel "${ctrl}"
    then
        local sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi

        # get package version
        if cui_listview_gettext "${ctrl}" "${sel}" "2"
        then
            version="${p2}"
        fi

        local result=$(eisman check "${package}" "${version}")
        case "${result}" in
        "installed")
            cui_listview_settext "${ctrl}" "${sel}" 0 "inst."
            ;;
        "old")
            cui_listview_settext "${ctrl}" "${sel}" 0 "old"
            ;;
        "new")
            cui_listview_settext "${ctrl}" "${sel}" 0 "new"
            ;;
        *)
            cui_listview_settext "${ctrl}" "${sel}" 0 "-"
            ;;
        esac
    fi
}


# *******************************************************************
# **  menu handler functions
# *******************************************************************

# *******************************************************************
# **  postkey callback for popup windows
# **  @param $p2 : window handle
# **  @param $p3 : control window handle
# **  @param $p4 : key code
# **  @return cui_return 1 -> message handled; 0 -> message ignored
# *******************************************************************

popup_postkey_hook()
{
    local win="${p2}"
    local ctrl="${p3}"
    local key="${p4}"

    case "${key}" in
    "${KEY_F10}")
        cui_window_close "${ctrl}" "${IDCANCEL}"
        cui_return 1
        ;;
    "${KEY_ENTER}")
        cui_window_close "${p3}" "${IDOK}"
        cui_return 1
        ;;
    "27")
        cui_window_close "${p3}" "${IDCANCEL}"
        cui_return 1
        ;;
    *)
        cui_return 0
        ;;
    esac
}


# *******************************************************************
# **  transfer package info into a popup text view
# **  @param $p2 : window handle
# **  @return nothing
# *******************************************************************

show_package_detail()
{
    local win="${1}"
    local ctrl="${2}"
    local package
    local version
    local istatus
    local urlbase
    local url
    local date
    local short
    local status


    if cui_listview_getsel "${ctrl}"
    then
        local sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get installed state
        if cui_listview_gettext "${ctrl}" "${sel}" "0"
        then
            istatus="${p2}"
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi

        # get package version
        if cui_listview_gettext "${ctrl}" "${sel}" "2"
        then
            version="${p2}"
        fi

        # get package status
        if cui_listview_gettext "${ctrl}" "${sel}" "3"
        then
            status="${p2}"
        fi

        # get package date description
        if cui_listview_gettext "${ctrl}" "${sel}" "4"
        then
            date="${p2}"
        fi

        # get package short description
        if cui_listview_gettext "${ctrl}" "${sel}" "5"
        then
            short="${p2}"
        fi

        # get package url
        if cui_listview_gettext "${ctrl}" "${sel}" "6"
        then
            url="${p2}"
        fi
    fi

    # convert package url to base url
    urlbase="$(get_base_url ${url})"

    if cui_textview_new "${win}" "Package details" \
        0 0 80 21                                  \
        0                                          \
        "$((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))" \
        "${CWS_NONE}"
    then
        local dlg="${p2}"
        local option

        if [ "${work_on_installed}" = "yes" ]
        then
            option="--installed"
        else
            option="--url=${urlbase}"
        fi

        local author=$(query_first 'author' "${package}" "${version}" "${option}")
        local section=$(query_first 'section' "${package}" "${version}" "${option}")
        local text=$(query_first 'text' "${package}" "${version}" "${option}")

        cui_textview_add        "${dlg}" "  Name:      ${package}"
        cui_textview_add        "${dlg}" "  Package:   ${short}"
        cui_textview_add        "${dlg}" "  Version:   ${version}"
        cui_textview_add        "${dlg}" "  Date:      ${date}"
        cui_textview_add        "${dlg}" "  Author:    ${author}"
        cui_textview_add        "${dlg}" "  Status:    ${status}"
        cui_textview_add        "${dlg}" "  Section:   ${section}"
        cui_textview_add        "${dlg}" "  URL:       ${url}"
        cui_textview_add        "${dlg}" ""

        local IFS_BAK=$IFS
        IFS="
"

        for line in $text
        do
            cui_textview_add    "${dlg}" "  ${line}"
        done

        IFS=${IFS_BAK}

        cui_textview_add        "${dlg}" ""
        cui_textview_add        "${dlg}" "  press [ENTER] to close"

        cui_textview_callback   "${dlg}" "${TEXTVIEW_POSTKEY}" "${win}" popup_postkey_hook
        cui_window_create       "${dlg}"

        # resize text popup when window size changes
        TEXT_WINDOW_HANDLE="${dlg}"
        mainwin_resize_text_popup

        # set specific status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_PREFIX} ENTER=Close F10=Exit"

        cui_window_modal        "${dlg}"
        cui_window_destroy      "${dlg}"

        # disable resizeing of text popup window
        TEXT_WINDOW_HANDLE=""

        # restore status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_TEXT}"
    fi
}


# *******************************************************************
# **  display package files
# **  @param $p2 : window handle
# **  @return nothing
# *******************************************************************

show_package_files()
{
    local win="${1}"
    local ctrl="${2}"
    local package
    local version

    if cui_listview_getsel "${ctrl}"
    then
        local sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi
    fi

    if cui_textview_new "${win}" "Package files" \
        0 0 80 21                                  \
        0                                          \
        "$((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))" \
        "${CWS_NONE}"
    then
        local dlg="${p2}"

        cui_textview_read       "${dlg}" "/etc/filelist.d/${package}-files.txt"

        cui_textview_add        "${dlg}" ""
        cui_textview_add        "${dlg}" "  press [ENTER] to close"

        cui_textview_callback   "${dlg}" "${TEXTVIEW_POSTKEY}" "${win}" popup_postkey_hook
        cui_window_create       "${dlg}"

        # resize text popup when window size changes
        TEXT_WINDOW_HANDLE="${dlg}"
        mainwin_resize_text_popup

        # set specific status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_PREFIX} ENTER=Close F10=Exit"

        cui_window_modal        "${dlg}"
        cui_window_destroy      "${dlg}"

        # disable resizeing of text popup window
        TEXT_WINDOW_HANDLE=""

        # restore status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_TEXT}"
    fi
}


# *******************************************************************
# **  transfer package info into a popup text view
# **  @param $p2 : window handle
# **  @return nothing
# *******************************************************************

show_pending_requirements()
{
    local win="${1}"
    local ctrl="${2}"
    local package
    local version
    local text

    if cui_listview_getsel "${ctrl}"
    then
        local sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi
    fi

    text=$(eisman usage "${package}")

    if cui_textview_new "${win}" "Pending requirements" \
        0 0 80 21                                  \
        0                                          \
        "$((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))" \
        "${CWS_NONE}"
    then
        local dlg="${p2}"

        if [ -n "${text}" ]
        then
            cui_textview_add        "${dlg}" "  List of pending requirements:"
            cui_textview_add        "${dlg}" ""

            local IFS_BAK=$IFS
            IFS="
"

            for line in $text
            do
                cui_textview_add    "${dlg}" "  ${line}"
            done

            IFS=${IFS_BAK}
        else
            cui_textview_add        "${dlg}" "  No pending requirements found!"
        fi

        cui_textview_add        "${dlg}" ""
        cui_textview_add        "${dlg}" "  press [ENTER] to close"

        cui_textview_callback   "${dlg}" "${TEXTVIEW_POSTKEY}" "${win}" popup_postkey_hook
        cui_window_create       "${dlg}"

        # resize text popup when window size changes
        TEXT_WINDOW_HANDLE="${dlg}"
        mainwin_resize_text_popup

        # set specific status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_PREFIX} ENTER=Close F10=Exit"

        cui_window_modal        "${dlg}"
        cui_window_destroy      "${dlg}"

        # disable resizeing of text popup window
        TEXT_WINDOW_HANDLE=""

        # restore status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_TEXT}"
    fi
}


# *******************************************************************
# **  transfer package info into a popup text view
# **  @param $p2 : window handle
# **  @return nothing
# *******************************************************************

install_package()
{
    local win="${1}"
    local ctrl="${2}"
    local package
    local version
    local status
    local urlbase
    local line
    local sel
    local options

    if cui_listview_getsel "${ctrl}"
    then
        sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi

        # get package version
        if cui_listview_gettext "${ctrl}" "${sel}" "2"
        then
            version="${p2}"
        fi

        # get package state
        if cui_listview_gettext "${ctrl}" "${sel}" "3"
        then
            status="${p2}"
        fi

        # get package url
        if cui_listview_gettext "${ctrl}" "${sel}" "6"
        then
            urlbase="${p2}"
        fi
    fi

    # convert package url to base url
    urlbase="$(get_base_url ${urlbase})"

    # setup options
    if [ "${work_on_installed}" = "no" ]
    then
        options="${options} --url="${urlbase}""
    fi

    if [ "${status}" != "stable" ]
    then
        options="${options} --unstable"
    fi

    # construction of wait popup window
    if cui_window_new "${win}" \
        0 0 29 3               \
        $((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))
    then
        local popup="${p2}"
        if cui_valid_handle "${popup}"
        then
            local
            cui_window_setcolors "${popup}" "DIALOG"
            cui_window_sethook   "${popup}" "${HOOK_CREATE}"  wait_create_hook
            cui_window_create    "${popup}"
            cui_update

            # execute eisman package manager to find requirement list
            text=$(eisman install --info --no-wait-anim ${options} "${package}"="${version}" 2>&1)

            cui_window_destroy    "${popup}"
        fi
    fi

    # create text view control to display result data
    if cui_textview_new "${win}" "Install package" \
        0 0 80 21                                  \
        0                                          \
        "$((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))" \
        "${CWS_NONE}"
    then
        local dlg="${p2}"

        # execute install --info command
        local IFS_BAK=$IFS
        IFS="
"
        # transfer result to text view
        for line in $text
        do
            # in case of an error, show a message box
            # and leave the loop
            if [ "${line:0:6}" = "error:" ]
            then
                cui_message "${win}" "${line}" "eisman error" "${MB_ERROR}"

                IFS=${IFS_BAK}

                cui_window_destroy "${dlg}"
                return
            fi
            cui_textview_add  "${dlg}" "  ${line}"
        done

        IFS=${IFS_BAK}

        # add user controls
        cui_textview_add       "${dlg}" ""
        cui_textview_add       "${dlg}" "  press [ENTER] to install"
        cui_textview_add       "${dlg}" "  press [ESC]   to cancel"

        # add key callbacks
        cui_textview_callback  "${dlg}" "${TEXTVIEW_POSTKEY}" "${win}" popup_postkey_hook
        cui_window_create      "${dlg}"

        # resize text popup when window size changes
        TEXT_WINDOW_HANDLE="${dlg}"
        mainwin_resize_text_popup

        # set specific status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_PREFIX} ENTER=Install ESC=Cancel F10=Exit"

        # execute as modal dialog
        if cui_window_modal    "${dlg}"
        then
            # disable resizeing of text popup window
            TEXT_WINDOW_HANDLE=""

            if [ "${p2}" = "${IDOK}" ]
            then
                # when ENTER has been pressed, leave curses and call eisman
                cui_window_destroy "${dlg}"
                cui_leave_curses

                cui_shell_execute "eisman install --auto  ${options} \"${package}\"=\"${version}\"; \
                    /var/install/bin/anykey"

                # when command is done, restore curses
                cui_resume_curses

                # reload the whole package list, since the install state
                # of other packages may have changed to
                browser_readdata    "${win}"
                cui_listview_setsel "${ctrl}" "${sel}"
            else
                cui_window_destroy "${dlg}"
            fi
        else
            # disable resizeing of text popup window
            TEXT_WINDOW_HANDLE=""
            cui_window_destroy "${dlg}"
        fi
    fi

    # restore status text
    cui_window_setlstatustext "${win}" "${DEF_STATUS_TEXT}"
}


# *******************************************************************
# **  transfer package info into a popup text view
# **  @param $p2 : window handle
# **  @return nothing
# *******************************************************************

uninstall_package()
{
    local win="${1}"
    local ctrl="${2}"
    local recursive="${3}"
    local package
    local line
    local sel
    local install_state

    if cui_listview_getsel "${ctrl}"
    then
        sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            return
        fi

        # get package install state
        if cui_listview_gettext "${ctrl}" "${sel}" "0"
        then
            install_state="${p2}"
        fi

        # get package name
        if cui_listview_gettext "${ctrl}" "${sel}" "1"
        then
            package="${p2}"
        fi
    fi

    # construction of wait popup window
    if cui_window_new "${win}" \
        0 0 29 3               \
        $((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))
    then
        local popup="${p2}"
        if cui_valid_handle "${popup}"
        then
            local
            cui_window_setcolors "${popup}" "DIALOG"
            cui_window_sethook   "${popup}" "${HOOK_CREATE}"  wait_create_hook
            cui_window_create    "${popup}"
            cui_update

            # execute eisman package manager to find requirement list
            text=$(eisman uninstall --info --no-wait-anim "${recursive}" "${package}" 2>&1)

            cui_window_destroy    "${popup}"
        fi
    fi

    # create text view control
    if cui_textview_new "${win}" "Uninstall package" \
        0 0 80 21                                  \
        0                                          \
        "$((${CWS_POPUP} + ${CWS_BORDER} + ${CWS_CENTERED}))" \
        "${CWS_NONE}"
    then
        local dlg="${p2}"

        # execute install --info command
        local IFS_BAK=$IFS
        IFS="
"

        # transfer result to text view
        for line in $text
        do
            # in case of an error, show a message box
            # and leave the loop
            if [ "${line:0:6}" = "error:" ]
            then
                cui_message "${win}" "${line}" "eisman error" "${MB_ERROR}"

                IFS=${IFS_BAK}

                cui_window_destroy "${dlg}"
                return
            fi
            cui_textview_add  "${dlg}" "  ${line}"
        done

        IFS=${IFS_BAK}

        # add user controls
        cui_textview_add       "${dlg}" ""
        cui_textview_add       "${dlg}" "  press [ENTER] to uninstall"
        cui_textview_add       "${dlg}" "  press [ESC]   to cancel"

        # add key callbacks
        cui_textview_callback  "${dlg}" "${TEXTVIEW_POSTKEY}" "${win}" popup_postkey_hook
        cui_window_create      "${dlg}"

        # resize text popup when window size changes
        TEXT_WINDOW_HANDLE="${dlg}"
        mainwin_resize_text_popup

        # set specific status text
        cui_window_setlstatustext "${win}" "${DEF_STATUS_PREFIX} ENTER=Uninstall ESC=Cancel F10=Exit"

        # execute as modal dialog
        if cui_window_modal    "${dlg}"
        then
            # disable resizeing of text popup window
            TEXT_WINDOW_HANDLE=""

            if [ "${p2}" = "${IDOK}" ]
            then
                # when ENTER has been pressed, leave curses and call eisman
                cui_window_destroy "${dlg}"
                cui_leave_curses

                cui_shell_execute "eisman uninstall \"${recursive}\" --auto  \"${package}\"; /var/install/bin/anykey"

                # when command is done, restore curses
                cui_resume_curses

                # reload the whole package list, since the install state
                # of other packages may have changed to
                browser_readdata    "${win}"
                cui_listview_setsel "${ctrl}" "${sel}"
            else
                cui_window_destroy "${dlg}"
            fi
        else
            # disable resizeing of text popup window
            TEXT_WINDOW_HANDLE=""

            cui_window_destroy "${dlg}"
        fi
    fi

    # restore status text
    cui_window_setlstatustext "${win}" "${DEF_STATUS_TEXT}"
}


# *******************************************************************
# **  select menu hooks
# *******************************************************************

# *******************************************************************
# **  module_menu_clicked_hook
# **  @param $p2 : window handle
# **  @param $p3 : control window handle
# **  @return cui_return 1 -> message handled
# *******************************************************************

menu_clicked_hook()
{
    cui_window_close "${p3}" "${IDOK}"
    cui_return 1
}


# *******************************************************************
# **  module_menu_escape_hook
# **  @param $p2 : window handle
# **  @param $p3 : control window handle
# **  @return cui_return 1 -> message handled
# *******************************************************************

menu_escape_hook()
{
   cui_window_close "${p3}" "${IDCANCEL}"
   cui_return 1
}


# *******************************************************************
# **  module_menu_postkey_hook
# **  @param $p2 : window handle
# **  @param $p3 : control window handle
# **  @param $p4 : key code
# **  @return cui_return 1 -> message handled, 0 -> message ignored
# *******************************************************************

menu_postkey_hook()
{
   local ctrl="${p3}"

   if [ "${p4}" = "${KEY_F10}" ]
   then
       cui_window_close "${ctrl}" "${IDCANCEL}"
       cui_window_quit 0
       cui_return 1
   else
       cui_return 0
   fi
}


# *******************************************************************
# **  listview callbacks
# *******************************************************************

# *******************************************************************
# **  handle listview clicking events
# **  @param  $p1  window handle of parent window
# **  @param  $p2  control id
# **  @return cui_return 1 -> message handled
# *******************************************************************

listview_clicked_hook()
{
    local win="${p2}"
    local ctrl="${p3}"
    local item
    local dlg
    local installed_state=""
    local height=10

    if cui_listview_getsel "${ctrl}"
    then
        local sel="${p2}"

        # if no record is selected, exit
        if [ "${sel}" -lt 0 ]
        then
            cui_return 1
            return
        fi

        # check if selected package is installed
        if cui_listview_gettext "${ctrl}" "${sel}" "0"
        then
            if [ "${p2}" != "-" ]
            then
                installed_state="${p2}"
                height=14
            fi
        fi
    fi

    if cui_menu_new "${win}" "Options"        \
        0 0 34 ${height} 1                           \
        "$((${CWS_CENTERED} + ${CWS_POPUP}))" \
        "${CWS_NONE}"
    then
        local menu="${p2}"

        if cui_valid_handle "${menu}"
        then
            cui_menu_additem      "${menu}" "View Details"              1

            case "${installed_state}" in
            "new")
                cui_menu_additem      "${menu}" "Upgrade"               2
                ;;
            "inst.")
                cui_menu_additem      "${menu}" "(Re)Install"           2
                ;;
            "old")
                cui_menu_additem      "${menu}" "Downgrade"             2
                ;;
            *)
                cui_menu_additem      "${menu}" "Install"               2
                ;;
            esac

            if [ -n "${installed_state}" ]
            then
                cui_menu_additem  "${menu}" "Uninstall"                 3
                cui_menu_additem  "${menu}" "Uninstall (recursive)"     4
                cui_menu_additem  "${menu}" "Show pending requirements" 5
                cui_menu_additem  "${menu}" "Show package files"        6
            fi

            cui_menu_addseparator "${menu}"
            cui_menu_additem      "${menu}" "Exit application"          8
            cui_menu_addseparator "${menu}"
            cui_menu_additem      "${menu}" "Close menu"                0
            cui_menu_selitem      "${menu}" 1

            cui_menu_callback     "${menu}" "${MENU_CLICKED}" "${win}" "menu_clicked_hook"
            cui_menu_callback     "${menu}" "${MENU_ESCAPE}"  "${win}" "menu_escape_hook"
            cui_menu_callback     "${menu}" "${MENU_POSTKEY}" "${win}" "menu_postkey_hook"

            cui_window_create     "${menu}"

            if cui_window_modal   "${menu}"
            then
                local result="${p2}"

                if [ "${result}" = "${IDOK}" ]
                then
                    cui_menu_getselitem "${menu}"

                    item="${p2}"

                    case "${item}" in
                    1)
                        cui_window_destroy  "${menu}"
                        show_package_detail "${win}" "${ctrl}"
                        ;;
                    2)
                        cui_window_destroy  "${menu}"
                        install_package     "${win}" "${ctrl}"
                        ;;
                    3)
                        cui_window_destroy  "${menu}"
                        uninstall_package   "${win}" "${ctrl}" ""
                        ;;
                    4)
                        cui_window_destroy  "${menu}"
                        uninstall_package   "${win}" "${ctrl}" "--recursive"
                        ;;
                    5)
                        cui_window_destroy  "${menu}"
                        show_pending_requirements "${win}" "${ctrl}"
                        ;;
                    6)
                        cui_window_destroy  "${menu}"
                        show_package_files  "${win}" "${ctrl}"
                        ;;
                    8)
                        cui_window_destroy  "${menu}"
                        cui_window_quit 0
                        ;;
                    *)
                        cui_window_destroy  "${menu}"
                        ;;
                    esac
                else
                   cui_window_destroy  "${menu}"
                fi
            fi
        fi
    fi

    cui_return 1
}


# *******************************************************************
# ** users_list_postkey_hook (catch ENTER key)
# **   $p2 --> window handle of main window
# **   $p3 --> window handle of list control
# **   $p4 --> key
# *******************************************************************

listview_postkey_hook()
{
    local win="${p2}"
    local ctrl="${p3}"
    local key="${p4}"

    if [ "${key}" == "${KEY_ENTER}" ]
    then
        listview_clicked_hook "${win}" "${ctrl}"
    else
        cui_return 0
    fi
}


# *******************************************************************
# **  main window
# *******************************************************************

# *******************************************************************
# **  mainwin_render_layout (reorder windows)
# **  @param  $1 --> mainwin window handle
# **  @return n/a
# *******************************************************************

mainwin_render_layout()
{
    local win="${1}"
    local ctrl
    local focus

    cui_getclientrect "${win}"
    local w="${p4}"
    local h="${p5}"
    local p="${h}"

    local list

    if [ "${help_visible}" = "yes" ]
    then
        p="$(($h - $h / 3 + $h / 10))"
    fi

    # move menu window
    if cui_window_getctrl "${win}" "${IDC_PACKAGE_LIST}"
    then
        list="${p2}"
        if cui_valid_handle "${list}"
        then
            cui_window_move "${list}" "0" "0" "${w}" "${p}"
        fi
    fi

    # move help window (hide if necessary)
    if cui_window_getctrl "${win}" "${IDC_HELPTEXT}"
    then
        ctrl="${p2}"
        if cui_valid_handle "${ctrl}"
        then
            if [ "${help_visible}" = "yes" ]
            then
                cui_window_hide "${ctrl}" "0"
                cui_window_move "${ctrl}" "0" "${p}" "${w}" "$(($h -$p))"
            else
                if cui_window_getfocus
                then
                    focus="${p2}"
                    if [ "${focus}" = "${ctrl}" ]
                    then
                       cui_window_setfocus "${list}"
                    fi
                fi
                cui_window_hide "${ctrl}" "1"
                cui_window_move "${ctrl}" "0" "${p}" "${w}" "1"
            fi
        fi
    fi

    if cui_valid_handle "${TEXT_WINDOW_HANDLE}"
    then
        mainwin_resize_text_popup
    fi
}


# *******************************************************************
# **  when terminal size changes and a text popup window has been
# **  opened, this routine resizes the text popup so that it
# **  always has the best dimensions for the current terminal size
# **  @param  n/a
# **  @return n/a
# *******************************************************************

mainwin_resize_text_popup()
{
    if cui_getdesktop
    then
        local desktop="${p2}"

        cui_getclientrect "${desktop}"
        local w="${p4}"
        local h="${p5}"
        local x=2
        local y=2

        if [ "${w}" -gt 4 ]
        then
            w=$((${w} - 4))
        else
            if [ "${w}" -gt 80 ]
            then
                w=0
            fi
        fi

        if [ "${h}" -gt 4 ]
        then
            h=$((${h} - 4))
        else
            if [ "${h}" -gt 20 ]
            then
                h=0
            fi
        fi

        cui_window_move "${TEXT_WINDOW_HANDLE}" "${x}" "${y}" "${w}" "${h}"
    fi
}


# *******************************************************************
# **  mainwin_size_hook (handle resize events for mainwin)
# **  @param  $p2 window handle
# **  @return cui_return 1 -> message handled
# *******************************************************************

mainwin_size_hook()
{
    mainwin_render_layout "${p2}"
    cui_return 1
}


# *******************************************************************
# **  mainwin_key_hook (handle key events for mainwin)
# **  @param  $p2  window handle
# **  @param  $p3  key code
# **  @return cui_return 1 if key has been handled, 0 otherwise
# *******************************************************************

mainwin_key_hook()
{
    local win="${p2}"
    local key="${p3}"
    local ctrl

    if cui_window_getctrl "${win}" "${IDC_PACKAGE_LIST}"
    then
        ctrl="${p2}"
        if cui_valid_handle "${ctrl}"
        then
            case $key in
            "${KEY_F1}")
                if [ "${help_visible}" = "yes" ]
                then
                    help_visible="no"
                else
                    help_visible="yes"
                fi
                mainwin_render_layout $win
                cui_return 1
                return
                ;;
            "${KEY_F3}")
                show_package_detail  "${win}" "${ctrl}"
                cui_return 1
                return
                ;;
            "${KEY_F7}")
                install_package  "${win}" "${ctrl}"
                cui_return 1
                return
                ;;
            "${KEY_F8}")
                uninstall_package  "${win}" "${ctrl}"
                cui_return 1
                return
                ;;
            "${KEY_F10}")
                cui_window_quit 0
                cui_return 1
                return
                ;;
            esac
        fi
    fi

    cui_return 0
}


# *******************************************************************
# **  mainwin_init_hook (load data)
# **  @param  $p2 window handle
# **  @return cui_return 1 -> message handled
# *******************************************************************

mainwin_init_hook()
{
    local win="$p2"
    cui_settimer "$win" "$IDC_TIMER" 50
    cui_return 1
}


# *******************************************************************
# **  mainwin_timer_hook (handle timer events)
# **  @param  $p2  window handle
# **  @return cui_return 1 = message handled
# *******************************************************************

mainwin_timer_hook()
{
    local win="${p2}"
    cui_killtimer "${win}" "${IDC_TIMER}"
    browser_readdata "${win}"
    cui_return 1
}


# *******************************************************************
# **  mainwin_create_hook (for creation of child windows)
# **  @param  $p2  window handle
# **  @return n/a
# *******************************************************************

mainwin_create_hook()
{
    local win="$p2"
    local ctrl

    if cui_listview_new "${win}" "" \
        0 0 30 10 7                 \
        "${IDC_PACKAGE_LIST}"       \
        "${CWS_NONE}" "${CWS_NONE}"
    then
        ctrl="${p2}"
        if cui_valid_handle "${ctrl}"
        then
            cui_window_setcolors    "${ctrl}" "WINDOW"
            cui_listview_setcoltext "${ctrl}" 0 "IS   "
            cui_listview_setcoltext "${ctrl}" 1 "Name"
            cui_listview_setcoltext "${ctrl}" 2 "Version"
            cui_listview_setcoltext "${ctrl}" 3 "Status"
            cui_listview_setcoltext "${ctrl}" 4 "Date"
            cui_listview_setcoltext "${ctrl}" 5 "Short"
            cui_listview_setcoltext "${ctrl}" 6 "URL"
            cui_listview_callback   "${ctrl}" "${LISTBOX_CLICKED}"  "${win}" listview_clicked_hook
            cui_listview_callback   "${ctrl}" "${LISTVIEW_POSTKEY}" "${win}" listview_postkey_hook

            cui_listview_settitlealignment  "${ctrl}" 0 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 1 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 2 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 3 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 4 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 5 "${ALIGN_LEFT}"
            cui_listview_settitlealignment  "${ctrl}" 6 "${ALIGN_LEFT}"

            cui_window_create "${ctrl}"
        fi
    fi

    if cui_textview_new "$win" "Help" \
        0 0 10 10                     \
        "${IDC_HELPTEXT}"             \
        "${CWS_NONE}" "${CWS_NONE}"
    then
        ctrl="${p2}"
        if cui_valid_handle "${ctrl}"
        then
            cui_window_setcolors  "${ctrl}" "HELP"
            cui_textview_add      "${ctrl}" \
                "This is the eisfair package browser for the CUI environment. You can"
            cui_textview_add      "${ctrl}" \
                "choose to either install(F7) uninstall(F8) or inspect(F3) a package "
            cui_textview_add      "${ctrl}" \
                "previously selected in the list of packages. You can also simply press "
            cui_textview_add      "${ctrl}" \
                "the ENTER-Key to bring up a popup menu that shows all possible operations "
            cui_textview_add      "${ctrl}" \
                "that are available for the currently selected package."
            cui_window_create     "${ctrl}"
        fi
    fi

    cui_return 1
}



# *******************************************************************
# **  initial shellrun callback
# *******************************************************************

# *******************************************************************
# **  show help on arguments and possible options
# **  @param  $p2 desktop window handle
# **  @return n/a
# *******************************************************************

init()
{
    local win="${p2}"

    if cui_window_new "${win}" \
        0 0 0 0                \
        $((${CWS_POPUP} + ${CWS_CAPTION} + ${CWS_STATUSBAR} + ${CWS_MAXIMIZED}))
    then
        mainwin="${p2}"
        if cui_valid_handle "${mainwin}"
        then
            cui_window_setcolors      "${mainwin}" "DESKTOP"
            cui_window_settext        "${mainwin}" "package browser - ${message}"
            cui_window_setlstatustext "${mainwin}" "${DEF_STATUS_TEXT}"
            cui_window_setrstatustext "${mainwin}" "V1.0.0"
            cui_window_sethook        "${mainwin}" "${HOOK_CREATE}"  mainwin_create_hook
            cui_window_sethook        "${mainwin}" "${HOOK_INIT}"    mainwin_init_hook
            cui_window_sethook        "${mainwin}" "${HOOK_KEY}"     mainwin_key_hook
            cui_window_sethook        "${mainwin}" "${HOOK_SIZE}"    mainwin_size_hook
            cui_window_sethook        "${mainwin}" "${HOOK_TIMER}"   mainwin_timer_hook
            cui_window_create         "${mainwin}"
        fi
    fi
    cui_return 0
}

# *******************************************************************
# ** main program
# *******************************************************************
main()
{
    message='Select one of the available packages'
    work_on_installed='yes'

    if [ "$1" = "CUISHELL" ]
    then
        # skip cui arguments
        shift
        shift

        # read option switches
        while [ "${1:0:2}" = "--" ]
        do
            case ${1} in
            --help)
                show_help
                exit 0
                ;;
            --message)
                shift
                message="${1}"
                shift
                ;;
            --message=*)
                message="${1:10}"
                shift
                ;;
            --install)
                work_on_installed="no"
                shift
                ;;
            --uninstall)
                work_on_installed="yes"
                shift
                ;;
            *)
                echo "error: invalid option switch \"$1\"!" >&2
                exit 1
                ;;
            esac
        done

        # get parameters
        if [ "$#" -eq 1 ]
        then
            browsefile="$1"
        else
            echo 'error: invalid number of arguments!' >&2
            exit 1
        fi
    fi

    cui_init
    cui_run

    exit 0
}

main "${@}"

# *******************************************************************
# **  end of cui program
# *******************************************************************
