/*
**++
**  FACILITY:
**      NEWSSELECT
**
**  ABSTRACT:
**      This module selects a newsgroup as the "current" newsgroup. The side
**      effect of selection is that the newsgroup is added to the current
**      newsgroup disectory display screen if necessary.
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright © 1988,1989,1990
**
**  MODIFICATION HISTORY:
**      V5.5     7-Oct-1988     GIH
**          Remove "adding" informational message
**      V5.6    11-Nov-1988     GIH
**          Correctly position current item arrow on screen following select
**      V5.8    20-Jan-1989     GIH
**        - Allow the OPEN and SELECT commands (without qualifiers only)
**          to select the current item for reading at the right context level
**      V6.1b7  15-May-1993  Charles Bailey  bailey@genetics.upenn.edu
**        - Optimize item number lookup
**	V6.1b11 14-Apr-1997	Mark Martinec   mark.martinec@ijs.si
**	  - replace call to strcpy with safer strnncpy
**--
**/

#ifdef vaxc
#module NEWSSELECT "V6.2"
#endif

#define _NEWSSELECT_C
#define module_name "NEWSSELECT"

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

#define CLASSES 1

/*
 *  selnew
 *
 *  Pick out the next newsgroup with unread news with the max priority
 */

int selnew(lev)
  int lev;
{
  int g, mg = 0, mp = 0;

  if (no_more_news) {
    err_line("Select - No new items in registered groups");
    set_level(lev);
    return(0);
    }

  if (   curr_g
      && ga[curr_g]->grp_reg
      && ga[curr_g]->grp_unread

#if CLASSES
      && ga[curr_g]->grp_display_indx
#endif
      ) {

    if (news_context != 1) return(do_select("%",curr_g,lev),1);
    else {
      mg = curr_g;
      mp = ga[curr_g]->grp_reg;
      }
    }

  for (;;) {
    no_more_news = 1;
    for (g = curr_g + 1; g <= ga_size; ++g) {
      if (ga[g]->grp_reg && ga[g]->grp_unread && !(ga[g]->grp_flags & NEWS_M_NEWSKIP)) {
        no_more_news = 0;
        if (   (ga[g]->grp_reg > mp)
#if CLASSES
            && ga[g]->grp_display_indx
#endif      
            ) {
          mp = ga[g]->grp_reg;
          mg = g;
          }
        }
      }

    for (g = 1; g <= curr_g; ++g) {
      if (ga[g]->grp_reg && ga[g]->grp_unread && !(ga[g]->grp_flags & NEWS_M_NEWSKIP)) {
        no_more_news = 0;
        if (  (ga[g]->grp_reg > mp)
#if CLASSES
            && ga[g]->grp_display_indx
#endif      
            ) {
          mp = ga[g]->grp_reg;
          mg = g;
          }
        }
      }


    if (mg) {
      int i;

      do_select("%",mg,lev);
      if (lev < 2) return(1);
      if (   curr_g
          && curr_i
          && (ga[curr_g]->grp_ia[curr_i].itm_flags & NEWS_M_UNREAD)
          && !(ga[curr_g]->grp_ia[curr_i].itm_flags & NEWS_M_NOACCESS))
	return(1);
      for (i = 1; i <= ga[curr_g]->grp_count; ++i)
        if (   (ga[curr_g]->grp_ia[i].itm_flags & NEWS_M_UNREAD)
            && !(ga[curr_g]->grp_ia[i].itm_flags & NEWS_M_NOACCESS)) break;
      if (i <= ga[curr_g]->grp_count) {
        cur_set_itm(curr_g,i);
        return(1);
        }
      ga[curr_g]->grp_flags |= NEWS_M_NEWSKIP;
      mp = mg = 0;
      }
    else break;
    }
  if (!ga_size) err_line("Select - NEWS has no Newsgroups");
  else err_line("Select - No new items");
  return(0);
}

int selmark(lev)
  int lev;
{
  int i;
  unsigned int g,
               m,
               gm;
  char tg[80],
       *tag = 0;
  unsigned short tag_len;
  $DESCRIPTOR(tag_dsc,tg);

  if (cli$get_value(c$dsc("MARKER"),&tag_dsc,&tag_len) & 1) {
    tg[tag_len] = '\0';
    tag = tg;
    }
  if (!curr_g) g = m = 0;
  else g = ga[curr_g]->grp_num;
  if ((g) && ((curr_i <= 0) || (news_context < 2))) m = 0;
  else if (g) m = ga[curr_g]->grp_ia[curr_i].itm_num;

  for (;;) {
    if (!mark_find(g,m,tag,&g,&m))
      return(err_line("Info: Read/Mark - No more items with this tag"),0);

    if (!(gm = ga_locate(g))) continue;
    if (!ga[gm]->grp_count) continue;
    if (!ga[gm]->grp_ia) map_items(gm);
    if (!find_itm_by_num(gm,m,&i)) continue;
    break;
    }
  do_select("%",gm,lev);
  if (lev > 1) cur_set_itm(curr_g,i);
  return(1);
}

/*
 *  do_select
 *
 *  Pick out a news group by calling select(). Set the read context to
 *  -1 to indicate that no items have been read so far from this group.
 */

int do_select(s,sg,lev)
  const char *s;
  int sg, lev;
{
  char ngroup[GRPNAMELEN];
  int g = 0,
      save_level = news_context;
  $DESCRIPTOR(ngroup_dsc,ngroup);
  unsigned short ngroup_len = 0;

  if (!s) {
    if (cli$present(c$dsc("NEW")) == CLI$_PRESENT) {
      if (!cur_down_grp(1,0)) do_top();
      return(selnew(lev));
      }
    if (cli$present(c$dsc("MARKER")) == CLI$_PRESENT)
      return(selmark(lev));
    if (cli$get_value(c$dsc("NEWSGROUP"),&ngroup_dsc,&ngroup_len) == CLI$_ABSENT) {
      if (curr_g && curr_i && (save_level > 1)) {
        markasread(curr_g,curr_i,1);
        rpush(curr_g,curr_i);
        do_display(0,0,0);
        return(0);
        }
      if ((smg_active) && (curr_g)) g = curr_g;
      else if (curr_g)
        get_input_dflt(&ngroup_dsc,c$dsc("Newsgroup: "),&ngroup_len,c$dsc(ga[curr_g]->grp_name),0);
      else get_input(&ngroup_dsc,c$dsc("Newsgroup: "),&ngroup_len);
      }
    }
  else if (*s != '%') {
    int ll;
    strnncpy(ngroup,sizeof(ngroup), s,-1, &ll); ngroup_len = ll;
    }
  else g = sg;

  set_level(1);
  if (ngroup_len) {
    ngroup[ngroup_len] = '\0';
    util_cvrt(ngroup,ngroup);
    if (!(g = ga_search_name(ngroup))) {
      strcpy(err_oline,"Error: Select - No such Newsgroup: ");
      err_oline_cat(ngroup);
      err_line(err_oline);
      set_level(save_level);
      return(0);
      }
    }
  else if (!g) g = curr_g;

  if (smg_active && g) {
    if (!ga[g]->grp_display_indx)
      if (ga[g]->grp_reg) do_dir(DIR_REGISTER+1,0);
      else do_dir(DIR_ALL + 1,0);
    if (!ga[g]->grp_display_indx) {
      reset_class();
      if (ga[g]->grp_reg) do_dir(DIR_REGISTER+1,0);
      else do_dir(DIR_ALL + 1,0);
      }
    }
  cur_set_grp(g);
  if ((curr_g) && (!smg_active)) {
    printf("\tSelect - Newsgroup %s (%d items, %d unread)\n",
            ga[curr_g]->grp_name,ga[curr_g]->grp_count,ga[curr_g]->grp_unread);
    if (ga[curr_g]->grp_topic && *(ga[curr_g]->grp_topic))
      printf("   Title:  -<%s>-\n",ga[curr_g]->grp_topic);
    if (ga[curr_g]->grp_notice && *(ga[curr_g]->grp_notice))
      printf("   Notice: [%s]\n",ga[curr_g]->grp_notice);
    }
  set_level(lev);
  return(1);
}

/*
 *  do_selgrp
 *
 *  select a newsgroup - CLI entry point
 */

static int dsgroup()
{
  if (cli$present(c$dsc("MAIL")) & 1) return(do_open_mail());
  if (do_select(0,0,2)) selgrp_action();
  return(0);
}

int do_selgrp()
{
  return(unwind_display(OUTER_LOOP,dsgroup));
}

static int dopn()
{
  char s[80];
  unsigned short s_l;
  $DESCRIPTOR(s_d,s);

  if (cli$get_value(c$dsc("NEWSGROUP"),&s_d,&s_l) & 1) {
    s[s_l] = '\0';
    lower_case(s);
    if (!strcmp(s,"mail")) return(do_open_mail());
    if (do_select(s,0,2)) selgrp_action();
    return(0);
    }
  if (cli$present(c$dsc("CLASSNAME")) & 1) return(do_set_class());
  return(do_selgrp());
}

int
do_openit()
{
  return(unwind_display(OUTER_LOOP,dopn));
}

static int
dcls()
{
  char s[80];
  unsigned short s_l;
  $DESCRIPTOR(s_d,s);

  if (cli$present(c$dsc("MAIL")) & 1) return(do_close_mail());
  if (cli$get_value(c$dsc("OBJECT"),&s_d,&s_l) & 1) {
    s[s_l] = '\0';
    lower_case(s);
    if (!strcmp(s,"mail")) return(do_close_mail());
    }
  return(screen_grp_display());
}

int
do_closeit()
{
  return(unwind_display(OUTER_LOOP,dcls));
}
