/*{{{  #includes*/
#ifdef CONFIG_H
#   include "config.h"
#endif

#include <sys/types.h>
#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <local/bool.h>

#define PROMPT_C
#define I_DISPLAY_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_INIT_C
#define I_KEYBOARD_C
#define I_KEYTAB_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_SCREEN_C

#include "origami.h"
/*}}}  */

private bool status = TRUE;

/*{{{  message               put a message under statusline*/
public void message(unsigned char *s, bool  brackets)
{
  goclreol(1,MESSAGE_LINE);
  gotoxy(1,MESSAGE_LINE);
  if (brackets && !no_title) oputc('[');
  prt_bin_text(0,LINELEN,FALSE,s);
  if (brackets && !no_title) oputc(']');
  oflush;
  status = TRUE;
  if ((strlen((char*)s)+(brackets?2:0))>W_dx) dirty=TRUE;
}
/*}}}  */
/*{{{  vmessage              maybe put a message under statusline*/
public void vmessage(unsigned char *s)
{
  if (verbose) message(s,TRUE);
}
/*}}}  */
/*{{{  err_message           put a message under statusline*/
public void err_message(unsigned char *s,unsigned char *p, bool  brackets)
{
  goclreol(1,MESSAGE_LINE);
  gotoxy(1, MESSAGE_LINE);
  if (brackets && !no_title) oputc('[');
  pline(s);
  oputc(' ');
  prt_bin_text(0,LINELEN,FALSE,p);
  oputc(' ');
  pline(strerror(errno));
  if (brackets && !no_title) oputc(']');
  oflush;
  status = TRUE;
  if ((strlen((char*)s)+strlen((char*)p)+4)>W_dx) dirty=TRUE;
}
/*}}}  */
/*{{{  no_message            remove message*/
public void no_message(void)
{
  if (status) {
    status = FALSE;
    goclreol(1,MESSAGE_LINE);
  }
}
/*}}}  */
/*{{{  readprompt            read a string with prompt*/
public unsigned char *readprompt(unsigned char *Result,
                                 unsigned char *prompt, int max)
{
  /*{{{  variables*/
  bool dirty_prompt=TRUE;
  unsigned char *s;
  TOKEN ch;
  unsigned char STR1[LINELEN+1];
  int lg,lp;
  /*}}}  */

  /*{{{  prepare prompt's ang length-counters'*/
  strcpy((char *)STR1,(char *)prompt);
  strcat((char *)STR1,question);
  s=STR1+(lg=lp=strlen((char *)STR1));
  /*}}}  */
  do
   /*{{{  handle one keystroke*/
   {
     /*{{{  maybe show current input and prompt*/
     if (dirty_prompt)
      { dirty_prompt=FALSE;
        goclreol(1,MESSAGE_LINE);
        gotoxy(1, MESSAGE_LINE-(lg/W_dx));
        if (prt_bin_text(0,LINELEN,FALSE,STR1)>W_dx) dirty=TRUE;
      }
     /*}}}  */
     ch = hide_key();
     if (ch < O_NOP)
      { *(s++)=(char) ch;*s='\0';prt_bin_text(0,1,FALSE,s-1);lg++; }
     else if (ch == O_DELETE)
      { if (lg!=lp) { *(--s) = '\0';dirty_prompt=TRUE;lg--; } }
     else if (ch==O_RETURN)
        break;
     else if (aborted)
      { *Result='\0';break; }
   }
   /*}}}  */
  while ((lg-lp)<max);
  strcpy((char*)Result,(char*)STR1+lp);
  return(Result);
}
/*}}}  */
/*{{{  yes                   ask for boolean*/
public bool yes(unsigned char *q)
{
  unsigned char temp[8];

  do {
    readprompt(temp,q,6);
    if (*temp != '\0') {
      temp[0] = toupper(temp[0]);
      if (temp[0]==YES) return(TRUE);
      if (temp[0]==NO) return(FALSE);
    }
  } while (!aborted);
  return(FALSE);
}
/*}}}  */
/*{{{  menu_item             display a menu string and get item number*/
public int menu_item(unsigned char *prompt, int start, bool direct)
{ title_op(UPDTITLE);
  for (;;)
   /*{{{  display and get input*/
   { int i;
     int max;
     TOKEN cmd;
     unsigned char *s=prompt;

     /*{{{  print the menu*/
     if (start<0) start=0;
     /*{{{  print menu line*/
     message(empty_text,FALSE);
     i=0;
     while (*s)
      { if (*s==' ')
         /*{{{  skip spaces*/
         { do
            { oputc(' '); }
           while (*++s==' ');
         }
         /*}}}  */
        else if (i==start)
         /*{{{  write current mark*/
         { if (so && se) standout(); else oputc('*');
           while (*s && *s!=' ') oputc(*s++);
           if (so && se) standend(); else oputc('*');
           i++;
         }
         /*}}}  */
        else
         /*{{{  write other mark*/
         { while (*s && *s!=' ') oputc(*s++);
           i++;
         }
         /*}}}  */
      }
     oputs(" ? ");
     max=i;
     /*}}}  */
     if (start>=max) { start=max-1;continue; }
     i=start;
     /*}}}  */
     if (direct)
      /*{{{  read the key direct from keyboard*/
      { disable_abort();
        enable_echo(FALSE);
        /* if aborted is true before get_key is called, then ... :-( */
        cmd=get_key();
        enable_echo(TRUE);
        enable_abort();
      }
      /*}}}  */
     else
      /*{{{  hide_key*/
        cmd=hide_key();
      /*}}}  */
     if (cmd==O_LEFT)
      { if (i) start= --i; }
     else if (cmd==O_RIGHT)
      { if (i<max-1) start= ++i; }
     else if (cmd<O_NOP)
      /*{{{  look in list for corresponding entry*/
      { unsigned char ch=toupper((unsigned char)cmd);

        s=prompt;
        i=0;
        while (*s)
         { if (*s==' ')
              while (*(++s)==' ');
           else if (ch==toupper(*s))
            { return(i); }
           else
            { while (*(++s) && *s!=' ');
              i++;
            }
         }
        break;
      }
      /*}}}  */
     else
        break;
   }
   /*}}}  */
  return(start);
}
/*}}}  */
/*{{{  help                  display help or binding*/
public int bind_mark[KBD_COUNT][2];

public bool help(bool show_help)
{
  /*{{{  local variables*/
  FILE *fp;
  bool help_as_rc=FALSE;
  bool displayed=FALSE;
  char line[rc_help_lg+1];
  int li;
  /*{{{  mark strings for rc-help*/
  char numb1[20];
  int nl1;
  char numb2[20];
  int nl2;
  char ab[20];
  int al;
#  ifdef MOUSY
     char mouse[20];
     int ml;
#  endif
  static char mark[2]="|";
  /*}}}  */
  TOKEN ch=' ';
  /*}}}  */

  /*{{{  open the file*/
  for (;;)
   { if (show_help)
      { if (fp=fopen(open_sysfile("help"),READ)) break;
        help_as_rc=TRUE;
      }
     fp=fopen(open_sysfile(M_RCSTR),READ);
     break;
   }
  if (!fp)
   { err_message(get_msg(show_help?M_HF:M_RF),empty_text,TRUE);return(FALSE); }
  /*}}}  */
  if (!show_help)
   /*{{{  set leading marks for bindinglist*/
   {
     /*{{{  keyboard mark1*/
     strcpy(numb1,i_to_a(bind_mark[curr_kbd][0]));
     strcat(numb1,mark);
     nl1=strlen(numb1);
     /*}}}  */
     /*{{{  keyboard mark2*/
     strcpy(numb2,i_to_a(bind_mark[curr_kbd][1]));
     strcat(numb2,mark);
     nl2=strlen(numb2);
     /*}}}  */
     /*{{{  abort*/
     strcpy(ab,i_to_a(abort_kbd));
     strcat(ab,mark);
     al=strlen(ab);
     /*}}}  */
#     ifdef MOUSY
      /*{{{  mouse*/
        if (use_mouse==no_mouse)
         { mouse[0]='\0';ml=0; }
        else
         { strcpy(mouse,i_to_a(mouse_kbd));strcat(mouse,mark);ml=strlen(ab); }
      /*}}}  */
#     endif
   }
   /*}}}  */
  else
   /*{{{  clear or set marks for help*/
   {
     /*{{{  abort,mouse,kbd_2 cleared*/
     ab[0]=numb2[0]='\0';
     al=nl2=0;
#     ifdef MOUSY
       mouse[0]='\0';ml=0;
#     endif
     /*}}}  */
     if (help_as_rc)
      /*{{{  kbd_1 to ref_kbd*/
      { strcpy(numb1,i_to_a(ref_kbd));
        strcat(numb1,mark);
        nl1=strlen(numb1);
        show_help=FALSE;
      }
      /*}}}  */
     else
      /*{{{  kbd_1 cleared*/
      { numb1[0]='\0';nl1=0; }
      /*}}}  */
   }
   /*}}}  */
  /*{{{  maybe seek in rc-file*/
  if (!show_help && (-1==fseek(fp,(off_t)helpofs,SEEK_SET)))
   { fclose(fp);return(FALSE); }
  /*}}}  */
  /*{{{  init position on screen*/
  li=1;
  /*}}}  */
  /*{{{  display all lines*/
  while (fgets(line,rc_help_lg,fp))
   { int xl=0;
#     ifdef MOUSY
        bool mouse_but=FALSE;
#     endif

     if
      /*{{{  help || current || mouse || std*/
      (   show_help
       || (                !strncmp(line,numb1,xl=nl1)
           || ((xl=nl2) && !strncmp(line,numb2,nl2))
           || ((xl=al)  && !strncmp(line,ab,al))
#          ifdef MOUSY
           || ((xl=ml)  && (mouse_but= !strncmp(line,mouse,ml)))
#          endif
          )
      )
      /*}}}  */
      /*{{{  put line*/
      { displayed=TRUE;
        if (line[xl]) line[strlen(line)-1]='\0';
#        ifdef MOUSY
           if (mouse_but)
            /*{{{  decode the mouse buttonnumber to a name*/
            { char *s=line+xl;
              char c;

              while (*s) s++;
              c=(*(--s)-first_mouse_char);
              if (mouse_b_count[use_mouse]>c && c>=0)
                 strcpy(s,mouse_b_names[use_mouse][c]);
              else
               { strcpy(s,"internal code ");strcat(s,i_to_a(c)); }
            }
            /*}}}  */
#        endif
        go_prt_clreol(1,li++,0,LEN-1,TRUE,(unsigned char*) line+xl);
      }
      /*}}}  */
     if (li>SCREEN_LEN)
      /*{{{  prompt for key*/
      { li=1;
        do
         { message(get_msg(M_ANY_Q),TRUE);ch=hide_key(); }
        while (ch==O_PROMPT || ch==O_NOP);
      }
      /*}}}  */
     if (aborted || (tolower(ch)=='q')) break;
   }
  /*}}}  */
  if (ch!='q' && li>1)
   /*{{{  clear rest and prompt*/
   { while (li<=SCREEN_LEN) goclreol(1,li++);
     do message(get_msg(M_ANY),TRUE); while (hide_key()==O_PROMPT);
   }
   /*}}}  */
  /*{{{  check closing the helpfile*/
  if (fclose(fp)<0)
     err_message(get_msg(M_CLOSE_FAILED),get_msg(show_help?M_HF:M_RF),TRUE);
  /*}}}  */
  /*{{{  maybe there was no ref in the rc-file, so complain then*/
  if (help_as_rc && !displayed)
   { err_message(get_msg(M_HF),empty_text,TRUE);return(FALSE); }
  /*}}}  */
  no_message();
  return TRUE;
}
/*}}}  */
