/*
 * dselect - Debian package maintenance user interface
 * methlist.cc - list of access methods and options
 *
 * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
 * Copyright © 2001 Wichert Akkerman <wakkerma@debian.org>
 *
 * This 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.
 *
 * This is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <config.h>
#include <compat.h>

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#include <dpkg/i18n.h>
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>

#include "dselect.h"
#include "bindings.h"
#include "method.h"
#include "helpmsgs.h"

static keybindings methodlistbindings(methodlist_kinterps,methodlist_korgbindings);

const char *methodlist::itemname(int index) {
  return table[index]->name;
}

void methodlist::kd_abort() { }

void methodlist::kd_quit() {
  debug(dbg_general, "methodlist[%p]::kd_quit() setting coption=%p",
        this, table[cursorline]);
  coption= table[cursorline];
}

void methodlist::setheights() {
  debug(dbg_general, "methodlist[%p]::setheights()", this);
  baselist::setheights();
  list_height++;
}

void methodlist::setwidths() {
  debug(dbg_general, "methodlist[%p]::setwidths()", this);

  status_width= 1;
  gap_width= 1;
  name_width= 14;
  name_column= status_width + gap_width;
  description_column= name_column + name_width + gap_width;

  total_width= TOTAL_LIST_WIDTH;
  if (total_width < COLS)
    total_width= COLS;
  description_width= total_width - description_column;
}

void methodlist::redrawtitle() {
  if (title_height) {
    mywerase(titlewin);
    mvwaddnstr(titlewin,0,0,_("dselect - list of access methods"),xmax);
    wnoutrefresh(titlewin);
  }
}

void methodlist::redrawthisstate() {
  if (!thisstate_height) return;
  mywerase(thisstatepad);
  wprintw(thisstatepad,
          _("Access method `%s'."),
          table[cursorline]->name);
  pnoutrefresh(thisstatepad, 0,0, thisstate_row,0,
               thisstate_row, min(total_width - 1, xmax - 1));
}

void methodlist::redraw1itemsel(int index, int selected) {
  int i;
  const char *p;

  wattrset(listpad, selected ? listsel_attr : list_attr);
  mvwaddch(listpad,index,0,
           table[index] == coption ? '*' : ' ');
  wattrset(listpad, selected ? listsel_attr : list_attr);
  mvwprintw(listpad,index,name_column-1, " %-*.*s ",
            name_width, name_width, table[index]->name);

  i= description_width;
  p= table[index]->summary ? table[index]->summary : "";
  while (i>0 && *p && *p != '\n') {
    waddch(listpad,*p);
    i--; p++;
  }
  while (i>0) {
    waddch(listpad,' ');
    i--;
  }
}

void methodlist::redrawcolheads() {
  if (colheads_height) {
    wattrset(colheadspad,colheads_attr);
    mywerase(colheadspad);
    mvwaddstr(colheadspad,0,0, "  ");
    mvwaddnstr(colheadspad,0,name_column, _("Abbrev."), name_width);
    mvwaddnstr(colheadspad,0,description_column, _("Description"), description_width);
  }
  refreshcolheads();
}

methodlist::methodlist() : baselist(&methodlistbindings) {
  int newcursor= -1;

  debug(dbg_general, "methodlist[%p]::methodlist()", this);

  table= new struct dselect_option*[noptions];

  struct dselect_option *opt, **ip;
  for (opt=options, ip=table, nitems=0; opt; opt=opt->next, nitems++) {
    if (opt == coption) { assert(newcursor==-1); newcursor= nitems; }
    *ip++= opt;
  }
  assert(nitems==noptions);

  if (newcursor==-1) newcursor= 0;
  setcursor(newcursor);

  debug(dbg_general, "methodlist[%p]::methodlist done; noptions=%d",
        this, noptions);
}

methodlist::~methodlist() {
  debug(dbg_general, "methodlist[%p]::~methodlist()", this);
  delete[] table;
}

quitaction methodlist::display() {
  int response;
  const keybindings::interpretation *interp;

  debug(dbg_general, "methodlist[%p]::display()", this);

  setupsigwinch();
  startdisplay();

  debug(dbg_general, "methodlist[%p]::display() entering loop", this);
  for (;;) {
    if (whatinfo_height) wcursyncup(whatinfowin);
    if (doupdate() == ERR) ohshite(_("doupdate failed"));
    signallist= this;
    if (sigprocmask(SIG_UNBLOCK,&sigwinchset,0)) ohshite(_("failed to unblock SIGWINCH"));
    do
    response= getch();
    while (response == ERR && errno == EINTR);
    if (sigprocmask(SIG_BLOCK,&sigwinchset,0)) ohshite(_("failed to re-block SIGWINCH"));
    if (response == ERR) ohshite(_("getch failed"));
    interp= (*bindings)(response);
    debug(dbg_general, "methodlist[%p]::display() response=%d interp=%s",
          this, response, interp ? interp->action : "[none]");
    if (!interp) { beep(); continue; }
    (this->*(interp->mfn))();
    if (interp->qa != qa_noquit) break;
  }
  pop_cleanup(ehflag_normaltidy); // unset the SIGWINCH handler
  enddisplay();

  debug(dbg_general, "methodlist[%p]::display() done", this);

  return interp->qa;
}

void methodlist::itd_description() {
  whatinfovb(_("Explanation"));

  wattrset(infopad,info_headattr);
  waddstr(infopad, table[cursorline]->name);
  waddstr(infopad," - ");
  waddstr(infopad, table[cursorline]->summary);
  wattrset(infopad,info_attr);

  const char *m= table[cursorline]->description;
  if (!m || !*m) m= _("No explanation available.");
  waddstr(infopad,"\n\n");
  wordwrapinfo(0,m);
}

void methodlist::redrawinfo() {
  if (!info_height) return;
  whatinfovb.reset();
  werase(infopad); wmove(infopad,0,0);

  debug(dbg_general, "methodlist[%p]::redrawinfo()", this);

  itd_description();

  whatinfovb.terminate();
  int y,x;
  getyx(infopad, y,x);
  if (x) y++;
  infolines= y;

  refreshinfo();
}

const struct helpmenuentry *methodlist::helpmenulist() {
  static const struct helpmenuentry list[]= {
    { 'i', &hlp_methintro            },
    { 'k', &hlp_methkeys             },
    {  0                             }
  };
  return list;
};
