/*  GNU Moe - My Own Editor
    Copyright (C) 2005, 2006, 2007, 2008, 2009 Antonio Diaz Diaz.

    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 3 of the License, or
    (at your option) any later version.

    This program 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 <cstdio>
#include <string>
#include <vector>

#include "buffer.h"
#include "menu.h"
#include "screen.h"


namespace Menu {

const char *help_line[] = {
  " Help Screen: Keyboard Commands               PAGE_DN next",
  " @bF1@b Help           @bF5@b Prev window     @bF9@b Copy block     ^C  Close window",
  " @bF2@b Save file      @bF6@b Next window    @bF10@b Options menu   ^X  Save and close",
  " @bF3@b Load file      @bF7@b Undo           @bF11@b Buffers menu   ^QX Save all and exit",
  " @bF4@b Zoom window    @bF8@b Redo           @bF12@b Last visited   ^QC Exit without saving",
  " ",
  " @bGO TO@b                     @bSEARCH@b                   @bMISC@b",
  " ^[U Beg of file           ^F  Find                 Ins Insert/Overwrite",
  " ^[V End of file           ^G  Find next            Tab Filename completion",
  " ^[L Line                  ^W  Find word            ^B  Reformat paragraph",
  " ^[C Column                ^QU update (C)           ^P  Control char",
  " ^[B Beg of block                                   ^Y  Delete line",
  " ^[K End of block          @bBOOKMARKS@b                ^OC Center line",
  " ^[F Match pair ->         ^[ 0-9 Goto              ^ON Change buffer name",
  " ^[G Match pair <-         ^K 0-9 Set               ^OR Repaint screen",
  " ^[D Center cursor                                  ^OS Split window",
  "                           @bINFO@b                     ^Q@bF2@b Save named buffers",
  " @bSCROLL@b                    ^H  Show help",
  " ^[W Up                    ^SC Show character code",
  " ^[Z Down                  ^SG Show global status",
  " ^[A Left                  ^SI Show character info",
  " ^[S Right                 ^SV Show version",
  " ",
  " ^[X means Alt-X or Esc-X    ^X means Control-X",
  "",
  " Help Screen: Block Commands     PAGE_DN next/PAGE_UP prev",
  " ",
  " @bBLOCK@b                     @bENCODE@b                 @bMISC@b",
  " ^SPACE Mark begin/end     ^O1 To Base64          ^OD Remove duplicate lines ->",
  " ^KB Begin                 ^O3 To Rot-13          ^OE Remove duplicate lines <-",
  " ^KK End                   ^O4 To Rot-47",
  " ^KC Copy",
  " ^KM Move                  @bDECODE@b",
  " ^KY Delete                ^O2 Base64",
  " ^KR Read                  ^O6 Quoted-Printable",
  " ^KW Write                 ^O8 UTF-8",
  " ^KI Indent",
  " ^KU Unindent",
  " ^OL To lowercase",
  " ^OU To uppercase",
  "",
  " Help Screen: Search             PAGE_DN next/PAGE_UP prev",
  " ",
  " Escape sequences for special characters:",
  "   \\a  BEL (alert)       \\n  LF (newline)           \\\\   '\\' (backslash)",
  "   \\b  BS  (backspace)   \\r  CR (carriage return)   \\ooo  octal code 'ooo'",
  "   \\e  ESC (escape)      \\t  HT (tab)               \\xhh  hexadecimal code 'hh'",
  "   \\f  FF  (form feed)   \\v  VT (vertical tab)",
  " ",
  " Special search sequences:",
  "   \\?      matches any single char       \\^  \\$  matches beginning/end of line",
  "   \\*      matches 0 or more chars       \\<  \\>  matches beginning/end of word",
  "   \\[..]   matches one in a set          \\c      matches balanced C expression",
  "   \\[^..]  matches one not in a set      \\+<ch>  matches 0 or more of <ch>",
  "   \\s      matches 0 or more whitespace characters",
  "   \\S      matches the longest possible non-empty sequence of whitespace",
  "   \\w      matches any word-constituent character",
  "   \\W      matches any character that is not a word-constituent",
  " ",
  " Notes",
  "     Ranges of characters may be specified in sets with 'A-Z'",
  "     '-' may be specified in sets by placing it first or last",
  "     ']' may be specified in sets by placing it first",
  "     \\+\\[..] matches 0 or more chars of those in set",
  "     \\+\\w    matches 0 or more word-constituent characters",
  "",
  " Help Screen: Replace            PAGE_DN next/PAGE_UP prev",
  " ",
  " Special replace sequences:",
  "     \\&      replaced with text which matched search string",
  "     \\l  \\u  same as \\& but matched text is lowercased / uppercased",
  "     \\0 - 9  replaced with text which matched the Nth special search sequence",
  "",
  " Help Screen: Character Set                   PAGE_UP prev",
  " 32  \x20     56  \x38     80  \x50    104  \x68    160  \xA0    184  \xB8    208  \xD0    232  \xE8",
  " 33  \x21     57  \x39     81  \x51    105  \x69    161  \xA1    185  \xB9    209  \xD1    233  \xE9",
  " 34  \x22     58  \x3A     82  \x52    106  \x6A    162  \xA2    186  \xBA    210  \xD2    234  \xEA",
  " 35  \x23     59  \x3B     83  \x53    107  \x6B    163  \xA3    187  \xBB    211  \xD3    235  \xEB",
  " 36  \x24     60  \x3C     84  \x54    108  \x6C    164  \xA4    188  \xBC    212  \xD4    236  \xEC",
  " 37  \x25     61  \x3D     85  \x55    109  \x6D    165  \xA5    189  \xBD    213  \xD5    237  \xED",
  " 38  \x26     62  \x3E     86  \x56    110  \x6E    166  \xA6    190  \xBE    214  \xD6    238  \xEE",
  " 39  \x27     63  \x3F     87  \x57    111  \x6F    167  \xA7    191  \xBF    215  \xD7    239  \xEF",
  " 40  \x28     64  \x40     88  \x58    112  \x70    168  \xA8    192  \xC0    216  \xD8    240  \xF0",
  " 41  \x29     65  \x41     89  \x59    113  \x71    169  \xA9    193  \xC1    217  \xD9    241  \xF1",
  " 42  \x2A     66  \x42     90  \x5A    114  \x72    170  \xAA    194  \xC2    218  \xDA    242  \xF2",
  " 43  \x2B     67  \x43     91  \x5B    115  \x73    171  \xAB    195  \xC3    219  \xDB    243  \xF3",
  " 44  \x2C     68  \x44     92  \x5C    116  \x74    172  \xAC    196  \xC4    220  \xDC    244  \xF4",
  " 45  \x2D     69  \x45     93  \x5D    117  \x75    173  \xAD    197  \xC5    221  \xDD    245  \xF5",
  " 46  \x2E     70  \x46     94  \x5E    118  \x76    174  \xAE    198  \xC6    222  \xDE    246  \xF6",
  " 47  \x2F     71  \x47     95  \x5F    119  \x77    175  \xAF    199  \xC7    223  \xDF    247  \xF7",
  " 48  \x30     72  \x48     96  \x60    120  \x78    176  \xB0    200  \xC8    224  \xE0    248  \xF8",
  " 49  \x31     73  \x49     97  \x61    121  \x79    177  \xB1    201  \xC9    225  \xE1    249  \xF9",
  " 50  \x32     74  \x4A     98  \x62    122  \x7A    178  \xB2    202  \xCA    226  \xE2    250  \xFA",
  " 51  \x33     75  \x4B     99  \x63    123  \x7B    179  \xB3    203  \xCB    227  \xE3    251  \xFB",
  " 52  \x34     76  \x4C    100  \x64    124  \x7C    180  \xB4    204  \xCC    228  \xE4    252  \xFC",
  " 53  \x35     77  \x4D    101  \x65    125  \x7D    181  \xB5    205  \xCD    229  \xE5    253  \xFD",
  " 54  \x36     78  \x4E    102  \x66    126  \x7E    182  \xB6    206  \xCE    230  \xE6    254  \xFE",
  " 55  \x37     79  \x4F    103  \x67              183  \xB7    207  \xCF    231  \xE7    255  \xFF",
  0 };


class Help_index
  {
  std::vector< int > data;
public:
  Help_index()
    {
    data.push_back( 0 );
    for( int i = 0; ; ++i )
      {
      const char *p = help_line[i];
      if( !p || *p == 0 ) { data.push_back( i + 1 ); if( !p ) break; }
      }
    }
  int operator[]( int i ) const throw() { return data[i]; }
  int size() const throw() { return data.size(); }
  } help_index;


void show_help( int delta ) throw()
  {
  static int current = 0;

  if( delta > 0 && current + 2 < help_index.size() ) ++current;
  else if( delta < 0 && current > 0 ) --current;
  else if( delta != 0 ) return;

  int line = 0;
  int i = help_index[current];
  char buf[Screen::width()+1];

  snprintf( buf, sizeof buf, "%s  %5s  F1 exit help",
            help_line[i], Screen::clock_string().c_str() );
  Screen::out_line( buf, line, false, 'i' ); ++line; ++i;

  while( line < Screen::height() &&
         i < help_index[current+1] - 1 && help_line[i] )
    { Screen::out_line( help_line[i], line ); ++line; ++i; }

  while( line < Screen::height() ) { Screen::out_line( "", line ); ++line; }
  }

} // end namespace Menu


void Menu::help_menu( const int abort_key1, const int abort_key2 )
  {
  int delta = 0;
  bool done = false;

  Screen::save_lines_and_cursor( 0, Screen::height() );
  while( !done )
    {
    show_help( delta );
    Screen::move_to( Point( 0, Screen::width() - 1 ) );
    while( true )
      {
      int key = Screen::wait_kbhit( 1 );	// show clock on line 0 only
      if( key == 3 || key == abort_key1 || key == abort_key2 )	// ^C
        { done = true; break; }
      key = Screen::convert_key( key );
      if( key == Screen::key_npage ) { delta = +1; break; }
      if( key == Screen::key_ppage ) { delta = -1; break; }
      }
    }
  Screen::restore_lines_and_cursor();
  Screen::show_status_lines();
  }
