#module NEWSSEARCH "V5.6"

/*
**++
**  FACILITY:
**
**      NEWSSEARCH
**
**  ABSTRACT:
**
**      Implement the search command - Display item(s) containing a specified
**      target string.
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V5.6    11-Nov-1988     GIH
**          Correct bug in newsgroup selection
**
**--
**/

#include "newsinclude.h"
#include "newsdefine.h"
#include "newsextern.h"

static int context = 0,
           case_sensitive = 0,
           dheader = 0,
           dtpu = 0,
           display_call = 1,
           num_groups = 0,
           sea_groups = 0,
           stop_search = 0;

static char target[132],
            inam[257],
            fnam[257],
            s_groups[10][200];

static $DESCRIPTOR(itm_dsc,inam);
static $DESCRIPTOR(fnam_dsc,fnam);

/*
 *  util_wdir
 *
 *  Convert a newsgroup name to a VMS directory string, preserving '*' chars
 */

static char wdir_result[SUBJLEN + SUBJLEN];

static util_wdir(input)
    char *input;
{
    char *p = wdir_result,
         *in = input;

    while (*in) {
        if (isalnum(*in) || (*in == '-') || (*in == '.') || (*in == '*')) *p++ = *in++;
        else {
            *p++ = '_';
            if (*in == '_') *p++ = '_';
            else if (*in < '0') *p++ = (*in - '!') + 'A';
            else if (*in < 'A') *p++ = (*in - ':') + '0';
            else if (*in < 'a') *p++ = (*in - '[') + 'P';
            else *p++ = (*in - '{') + 'V';
            in++;
            }
        }
    *p = '\0';
    return(wdir_result);
}

/*
 * make_wild
 *
 * convert a wildcard newsgroup spec into a wildcard file spec
 */

static char make_result[256];

static char *make_wild(s)
    char *s;
{
    int i = strlen(s);
    if (!strcmp(s,"*")) return(strcpy(make_result,"*..."));
    else if (s[i - 1] == '*') {
        if (s[i  - 2] == '.') {
            s[i - 2] = '\0';
            strcpy(make_result,util_wdir(s));
            strcat(make_result,"...");
            }
        else {
            s[i-1] = '\0';
            strcpy(make_result,util_wdir(s));
            strcat(make_result,"*...");
            }
        }
    else strcpy(make_result,util_wdir(s));
    return(make_result);
}

/*
 *  search_break
 *
 *  AST routine - keyboard interrupt
 */

search_break(pid,param,null_r0,null_r1,null_pc,null_psl)
    unsigned int pid,param,null_r0,null_r1,null_pc,null_psl ;
{
    stop_search = 1;
}

/*
 *  get_break_str
 *
 *  Read interrupt string and abort or continue search
 */

get_break_str()
{
    unsigned short trm;

    stop_search = 0;
    if (screen_active) {
        smg$erase_display(&trailer_vd,c$rfi(1),c$rfi(6),c$rfi(2),c$rfi(80));
        smg$set_cursor_abs(&trailer_vd,c$rfi(1),c$rfi(1));
        smg$end_pasteboard_update(&pid);
        }
    smg$read_keystroke(&kid,&trm,0,0,0,0,0);
    status = smg$read_composed_line(&kid,&keytab,&command,c$dsc("NEWS> [RETURN to continue search] "),&response_length,screen_active ? &trailer_vd : 0);
    if (screen_active) smg$begin_pasteboard_update(&pid);
    if (status == SMG$_EOF) status = RMS$_EOF;
    if (status == RMS$_EOF) {
        smg$disable_unsolicited_input(&pid);
        edit_m_off();
        return(1);
        }
    else response[response_length] = '\0';
    if (response_length) {
        smg$disable_unsolicited_input(&pid);
        edit_m_off();
        return(1);
        }
    if (!screen_active) printf("\tContinuing Search...\n");
    else {
        smg$end_pasteboard_update(&pid);
        smg$put_chars(&trailer_vd,c$dsc("Continuing Search..."),c$rfi(2),c$rfi(1),c$rfi(1),c$rfi(SMG$M_REVERSE),0,0);
        smg$begin_pasteboard_update(&pid);
        }
    return(0);
}

/*
 *  exe_search
 *
 *  Locate next file containing target string and call display routine to
 *  file
 */

static exe_search()
{
    char grp[132],
         ibuf[512],
         *s,
         *p;
    int g,
        m,
        version,
        i,
        n_found,
        tl = strlen(target),
        fnum = 0;

    FILE *fpi;

    while (lib$find_file(&itm_dsc,&fnam_dsc,&context,0,0,0,0) & 1) {
        fnam[256] = '\0';
        if (s = strchr(fnam,' ')) *s = '\0';

        if ((stop_search) && (get_break_str())) longjmp(env,2);

        if (screen_active) {
            if (!(++fnum % 10)) {
                sprintf(err_oline,"Searching... %d items",fnum);
                err_line(err_oline);
                smg$end_pasteboard_update(&pid);
                smg$begin_pasteboard_update(&pid);
                }
            }

        if ((stop_search) && (get_break_str())) longjmp(env,2);

        n_found = 1;
        if (fpi = fopen(fnam,"r")) {
            while (fgets(ibuf,512,fpi)) {
                if (!case_sensitive) s_to_lower(ibuf);
                s = ibuf;
                while (n_found && (s = strchr(s,*target)))
                    if (n_found = strncmp(s,target,tl)) ++s;
                if (!n_found) break;
                if ((stop_search) && (get_break_str())) {
                    fclose(fpi);
                    longjmp(env,2);
                    }
                }
            fclose(fpi);
            }
        if (n_found) continue;

        if (s = strchr(fnam,'[')) s++;
        if (p = strchr(fnam,']')) *p = ' ';
        if (sscanf(s,"%s %d.ITM;%d",grp,&m,&version) != 3) continue;
        if (p) *p = ']';

        strcpy(grp,util_undir(grp));
        util_cvrt(grp,grp);

        if (g = ga_exact_name(grp)) {
            do_select("%",g,2);
            for (i = 1; i <= ga[curr_g]->grp_count; ++i) {
                if (ga[curr_g]->grp_ia[i].itm_num == m) break;
                }
            if (i > ga[curr_g]->grp_count) continue;
            clear_err_line();
            cur_set_itm(curr_g,i);
            smg$disable_unsolicited_input(&pid);
            edit_m_off();
            if (display_call) {
                item_update(curr_g,curr_i);
                do_display(dheader,dtpu,0);
                }
            return(1);
            }
        }
    lib$find_file_end(&context);
    context = 0;
    smg$disable_unsolicited_input(&pid);
    edit_m_off();
    return(0);
}

/*
 *  do_search
 *
 *  search command - arg/param extraction
 */

do_search()
{
    int ldheader = 0,
        ldtpu = 0,
        found = 0,
        i;
    char ngroup[SUBJLEN],
         s[80];
    short ngroup_len = 0,
          s_len;
    $DESCRIPTOR(ngroup_dsc,ngroup);
    $DESCRIPTOR(s_dsc,s);

    if (cli$present(c$dsc("HEADER")) & 1) ldheader = 1;
    if (cli$present(c$dsc("TPU")) & 1) ldtpu = 1;
    if (cli$present(c$dsc("EDIT")) & 1) ldtpu = 1;
    if ((i = cli$present(c$dsc("DISPLAY"))) == CLI$_NEGATED) {
        i = 1;
        display_call = 0;
        }
    else if (i & 1) {
        i = 1;
        display_call = 1;
        }
    else i = 0;


    if (!context) {
        dheader = ldheader;
        dtpu = ldtpu;
        num_groups = 0;
        }

    if (cli$present(c$dsc("NEWSGROUPS")) & 1) {
        if (context) {
            lib$find_file_end(&context);
            context = 0;
            dheader = ldheader;
            dtpu = ldtpu;
            num_groups = 0;
            }
        if (cli$get_value(c$dsc("NEWSGROUPS"),&ngroup_dsc,&ngroup_len) & 1) {
            sea_groups = num_groups = 0;

            do {
                ngroup[ngroup_len] = '\0';
                util_cvrt(ngroup,ngroup);
                sprintf(s_groups[num_groups],Grp_template,make_wild(ngroup));
                strcat(s_groups[num_groups++],"*.ITM");
                } while ((cli$get_value(c$dsc("NEWSGROUP"),&ngroup_dsc,&ngroup_len) & 1) && (num_groups < 10));
            }
        else num_groups = 0;
        }

    if (cli$get_value(c$dsc("TARGET"),&s_dsc,&s_len) & 1) {
        if (context) {
            lib$find_file_end(&context);
            context = 0;
            dheader = ldheader;
            dtpu = ldtpu;
            num_groups = 0;
            }
        s[s_len] = '\0';
        }
    else if ((!context) || (cli$present(c$dsc("TARGET")) & 1)) {
        status = get_input_dflt(&s_dsc,c$dsc("Search String: "),&s_len,c$dsc(target),0);
        if (status == RMS$_EOF) return(0);
        s[s_len] = '\0';
        if (!i) display_call = 1;
        }

    if (!context) {
        int case_s = 0;
        char *p = s;

        if (!s_len) {
            err_line("\tNo search string specified\n");
            return(0);
            }
        while (*p) {
            if (isupper(*p)) {
                if (!case_s) case_s = 1;
                else if (case_s != 1) break;
                }
            else if (islower(*p)) {
                if (!case_s) case_s = 2;
                else if (case_s != 2) break;
                }
            ++p;
            }
        if (!(case_sensitive = (*p))) s_to_lower(s);
        strcpy(target,s);
        if (num_groups) sea_groups = 0;
        else if (curr_g) {
            sea_groups = 0;
            num_groups = 1;
            strcpy(ngroup,ga[curr_g]->grp_name);
            sprintf(s_groups[0],Grp_template,make_wild(ngroup));
            strcat(s_groups[0],"*.ITM");
            }
        else num_groups = 0;
        if (!i) display_call = 1;
        }

    while (!found) {
        if (!context) {
            if (sea_groups < num_groups) {
                strcpy(inam,s_groups[sea_groups++]);
                itm_dsc.dsc$w_length = strlen(inam);
                }
            else {
                if (!num_groups) err_line("\tNo newsgroup specified\n");
                else err_line("\tSearch string not located\n");
                return(0);
                }
            }
        stop_search = 0;
        smg$enable_unsolicited_input(&pid,search_break,0);
        found = exe_search();
        }
    return(0);
}
