/*      _ ____       _           _   
**     (_) ___|  ___| | ___  ___| |_ 
**    / /\___ \ / _ \ |/ _ \/ __| __|
**   / /  ___) |  __/ |  __/ (__| |_ 
**  (_(  |____/ \___|_|\___|\___|\__|
**
**  iSelect -- Interactive Selection Tool
**
**  iSelect is a Curses-based tool for interactive line selection 
**  in an ASCII file via a full-screen terminal session.
**  
**  ======================================================================
**
**  Copyright (c) 1997-2007 Ralf S. Engelschall.
**
**  This program is free software; it may be redistributed and/or
**  modified only under the terms of the GNU General Public License, 
**  which may be found in the iSelect source distribution.  
**  Look at the file COPYING for details. 
**
**  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 the GNU General Public License for more details.
**
**  ======================================================================
**
**  iselect_main.c -- main program
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include "iselect_global.h"
#include "iselect_getopt.h"
#include "iselect_browse.h"
#include "iselect_keys.h"

#define _ISELECT_VERSION_C_AS_HEADER_
#include "iselect_version.c"
#undef  _ISELECT_VERSION_C_AS_HEADER_

void give_version(char *name);
void give_usage(char *name);

void give_version(char *name)
{
    fprintf(stderr, "%s\n", iselect_version.v_tex);
    fprintf(stdout, "Copyright (c) 1997-2000 Ralf S. Engelschall <rse@engelschall.com>\n");
    fprintf(stdout, "\n");
    fprintf(stdout, "This program is distributed in the hope that it will be useful,\n");
    fprintf(stdout, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
    fprintf(stdout, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
    fprintf(stdout, "GNU General Public License for more details.\n");
    fprintf(stdout, "\n");
}

void give_usage(char *name)
{
    fprintf(stderr, "Usage: %s [options] [line1 line2 ...]\n", name);
    fprintf(stderr, "\n");
    fprintf(stderr, " Input Options:\n");
    fprintf(stderr, "  -d, --delimiter=STR,STR selection tag delimiters\n");
    fprintf(stderr, "  -c, --strip-comments    strip sharp-comments in input buffer\n");
    fprintf(stderr, "  -f, --force-browse      browse even if input has 0 or only 1 line\n");
    fprintf(stderr, "  -a, --all-select        force all lines to be selectable\n");
    fprintf(stderr, "  -e, --exit-no-select    exit immediately if no lines are selectable\n");
    fprintf(stderr, "\n");
    fprintf(stderr, " Display Options:\n");
    fprintf(stderr, "  -p, --position=NUM      initial line position of cursor\n");
    fprintf(stderr, "  -k, --key=KEY[:OKEY]    enable an additional input key\n");
    fprintf(stderr, "  -m, --multi-line        allow multiple lines to be selected\n");
    fprintf(stderr, "  -n, --name=STR          program name shown flush-left on status bar\n");
    fprintf(stderr, "  -t, --title=STR         title string shown centered on status bar\n");
    fprintf(stderr, "\n");
    fprintf(stderr, " Output Options:\n");
    fprintf(stderr, "  -S, --strip-result      strip whitespaces in result string\n");
    fprintf(stderr, "  -P, --position-result   prefix result string with `N:' (N=line number)\n");
    fprintf(stderr, "  -K, --key-result        prefix result string with `K:' (K=select key)\n");
    fprintf(stderr, "  -Q, --quit-result=STR   result string on quit (default='')\n");
    fprintf(stderr, "\n");
    fprintf(stderr, " Giving Feedback:\n");
    fprintf(stderr, "  -V, --version           display version string\n");
    fprintf(stderr, "  -h, --help              display this page\n");
    fprintf(stderr, "\n");
}

struct option options[] = {
    { "strip-comments",  FALSE, NULL, 'c'  },
    { "force-browse",    FALSE, NULL, 'f'  },
    { "all-select",      FALSE, NULL, 'a'  },
    { "exit-no-select",  FALSE, NULL, 'e'  },
    { "position",        TRUE,  NULL, 'p'  },
    { "key",             TRUE,  NULL, 'k'  },
    { "multi-line",      FALSE, NULL, 'm'  },
    { "name",            TRUE,  NULL, 'n'  },
    { "title",           TRUE,  NULL, 't'  },
    { "strip-result",    FALSE, NULL, 'S'  },
    { "position-result", FALSE, NULL, 'P'  },
    { "key-result",      FALSE, NULL, 'K'  },
    { "quit-result",     TRUE,  NULL, 'Q'  },
    { "version",         FALSE, NULL, 'V'  },
    { "help",            FALSE, NULL, 'h'  },
    { NULL,              FALSE, NULL, '\0' },
};

char caBuf[MAXBUF];

int main(int argc, char **argv)
{
    int fpStdout;
    int fpStdin;
    char *cp;
    char c;
    int pos = -1;
    char *progname;
    int nBuf, p;
    char ca[1024];
    char *title = "";
    char *name = "iSelect";
    int stripco = FALSE;
    int stripws = FALSE;
    int resultline = FALSE;
    int keyresultline = FALSE;
    int browsealways = FALSE;
    int allselectable = FALSE;
    int multiselect = FALSE;
    int exitnoselect = FALSE;
    int i;
    char *keystr;
    char *abortstr = NULL;
	char *tagbegin = "<";
	char *tagend   = ">";

    /*
     *  argument handling
     */

    /*  canonicalize program name */
    if ((cp = strrchr(argv[0], '/')) != NULL)
        progname = cp+1;
    else
        progname = argv[0];
    argv[0] = progname;

    /*  parse the option arguments */
    opterr = 0;
    while ((c = getopt_long(argc, argv, "d:cfaep:k:mn:t:SPKQ:Vh", options, NULL)) != (char)(-1)) {
        if (optarg == NULL) 
            optarg = "(null)";
        switch (c) {
            case 'd':
				tagbegin = strdup(optarg);
				if ((cp = strchr(tagbegin, ',')) == NULL) {
                    fprintf(stderr, "iSelect: bad argument to option '%c'\n", optopt);
                    fprintf(stderr, "Try `%s --help' for more information.\n", progname);
                    exit(EX_USAGE);
				}
				*cp++ = NUL;
				tagend = cp;
                break;
            case 'c':
                stripco = TRUE;
                break;
            case 'f':
                browsealways = TRUE;
                break;
            case 'a':
                allselectable = TRUE;
                break;
            case 'e':
                exitnoselect = TRUE;
                break;
            case 'p':
                pos = atoi(optarg); 
                break;
            case 'k':
                configure_custom_key(optarg); 
                break;
            case 'm':
                multiselect = TRUE;
                break;
            case 'n':
                name = strdup(optarg); 
                break;
            case 't':
                title = strdup(optarg); 
                break;
            case 'S':
                stripws = TRUE;
                break;
            case 'P':
                resultline = TRUE;
                break;
            case 'K':
                keyresultline = TRUE;
                break;
            case 'Q':
                abortstr = strdup(optarg); 
                break;
            case 'V':
                give_version(progname);
                exit(EX_OK);
            case 'h':
                give_usage(progname);
                exit(EX_OK);
            case '?':
                fprintf(stderr, "iSelect: invalid option: '%c'\n", optopt);
                fprintf(stderr, "Try `%s --help' for more information.\n", progname);
                exit(EX_USAGE);
            case ':':
                fprintf(stderr, "iSelect: missing argument to option '%c'\n", optopt);
                fprintf(stderr, "Try `%s --help' for more information.\n", progname);
                exit(EX_USAGE);
        }
    }

    /*
     *  read input
     */

    if (optind < argc) {
        /* browsing text is given as arguments */
        nBuf = 0;
        for (; optind < argc; ++optind) {
            cp = (argv[optind] == NULL ? "" : argv[optind]);
            sprintf(caBuf+nBuf, "%s\n", cp);
            nBuf += strlen(cp)+1;
        }
        caBuf[nBuf++] = NUL;
    }
    else if (optind == argc && !feof(stdin)) {
        /* browsing text is given on stdin */
        nBuf = 0;
        while ((c = fgetc(stdin)) != (char)(EOF)) {
            caBuf[nBuf++] = c;
        }
        caBuf[nBuf++] = NUL;

        /* save stdin filehandle and reconnect it to tty */
        fpStdin = dup(0);
        close(0);
        open("/dev/tty", O_RDONLY);
    }
    else {
        give_usage(progname);
        exit(EX_USAGE);
    }

    /*
     *  preserve stdout filehandle for result string, i.e.
     *  use the terminal directly for output
     */
    fpStdout = dup(1);
    close(1);
    open("/dev/tty", O_RDWR);

    pos = (pos < 1 ? 1 : pos);

    p = iSelect(caBuf, pos-1, title, name,
                tagbegin, tagend, stripco, stripws, 
                browsealways, allselectable, multiselect, exitnoselect, &keystr);

    /*
     *  give back the result string to the user via 
     *  the stdout file handle
     */
    if (p != -1) {
        for (i = 0; i < nLines; i++) {
            if (spaLines[i]->fSelected) {
                if (resultline) {
                    sprintf(ca, "%d:", i+1);
                    write(fpStdout, ca, strlen(ca));
                }
                if (keyresultline) {
                    sprintf(ca, "%s:", keystr);
                    write(fpStdout, ca, strlen(ca));
                }
                write(fpStdout, spaLines[i]->cpResult, strlen(spaLines[i]->cpResult));
                sprintf(ca, "\n");
                write(fpStdout, ca, strlen(ca));
            }
        }
    }
    else {
        if (abortstr != NULL)
            write(fpStdout, abortstr, strlen(abortstr));
    }
    exit(0);
}


/*EOF*/
