/*
**++
**  FACILITY:
**      NEWSREGISTER
**
**  ABSTRACT:
**      Manage the per-user newsrc context file for read/unread items,
**      kill filters and marks.
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright © 1988,1989
**
**  MODIFICATION HISTORY:
**      V5.5     7-Oct-1988     GIH
**          Change profile name to NEWSRC
**      V5.6    11-Nov-1988     GIH
**      V5.7    17-Nov-1988     GIH
**        - Add CLASS support routines
**        - Correct problem with long lines in register file
**        - Add check_groups function to scan for newsgroups with unseen items
**        - Add force_dir to feedback from check_groups to reg_context when
**          invoked with NEWS/UNSEEN
**        - Add PROFILE entry to NEWSRC file, and support into this module
**      V5.8     5-Apr-1989     GIH
**        - Add support for PROFILE /NEWREGISTER qualifier
**        - Delete old news_groups.register file in sys$login
**        - keep the newsrc file to version 1 using a rename after write
**        - If newsrc is empty then don't panic!
**        - Add fastscan - a rapid check for unread items using a  fast, but
**          not conclusive method.
**      V5.9     4-May-1989     GIH
**        - Update newsgroup display header Reg: field on the fly
**	V6.1b9	17-Sep-1994     Mark Martinec   mark.martinec@ijs.si
**	  - code cleanup to preserve the read-only nature of string literals
**	    (strategically placed 'const' attribute to string parameters)
**	V6.1b11 14-Apr-1997  Mark Martinec   mark.martinec@ijs.si
**	  - change %s to %.<n>s in sprintf to guard against overwriting buffer
**--
**/

#ifdef vaxc
#module NEWSREGISTER "V6.2"
#endif

#define _NEWSREGISTER_C
#define module_name "NEWSREGISTER"

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

extern
time_t sys_reg_time;

static
int reg_confirm = 0;

/*
 *  screen_dereg
 *  screen_reg
 *
 *  Deregister / Register from a newsgroup
 */

void screen_dereg(g)
  int g;
{
  int indx = ga[g]->grp_display_indx;

  if (indx != 0) {
    if (ga[g]->grp_unread)
      smg$change_rendition(&grp_vd,&indx,c$ac(4),c$ac(1),c$ac(5),c$ac(0),0);
    smg$change_rendition(&grp_vd,&indx,c$ac(12),c$ac(1),c$ac(GRPNAMELEN),c$ac(0),0);
    }
  if ((g == curr_g) && (news_context > 1) && smg_active) newsgroup_header();
}

void screen_reg(g)
  int g;
{
  int indx = ga[g]->grp_display_indx;

  if (indx != 0) {
    if (ga[g]->grp_unread)
      smg$change_rendition(&grp_vd,&indx,c$ac(4),c$ac(1),c$ac(5),c$ac(SMG$M_BOLD),0);
    smg$change_rendition(&grp_vd,&indx,c$ac(12),c$ac(1),c$ac(GRPNAMELEN),c$ac(SMG$M_BOLD),0);
    }
  if ((g == curr_g) && (news_context > 1) && smg_active) newsgroup_header();
}

/*
 *  do_reg_all
 *
 *  register user in all newsgroups
 */

int do_reg_all(p,cretime,type)
  int p, cretime, type;
{
  int status;
  int g, reg_groups = 0;

#if FAST_LOAD
  if (fast_loading) {
    set_level(1);  /* ensure the directory is shown */
    if (! all_loaded ) {
      if (!nntp_client) {
        sysprv();
        sys_close(&itmfab);
        sys_close(&grpfab);
        nosysprv();               /* note this code is taken from the */
        close_hist_file();        /* closefiles function in the       */
        };                        /* NEWSFILES module.                */
      close_mail_file();  
      close_nntp_file();
      write_reg_file();
      all_loaded = 1;
      first_retr_call = 0;
      openfiles(nntp_client ? 4 : -1);
      }
    }                                       
#endif
  for (g = 1; g <= ga_size; ++g) {
    switch (type) {
      case 0 : if (ga[g]->grp_credate < cretime) continue; break;
      case 1 : if (ga[g]->grp_credate >= cretime) continue; break;
      case 2 : if (!(ga[g]->grp_flags & NEWS_M_LOCAL)) continue; break;
      case 3 : if (ga[g]->grp_flags & NEWS_M_LOCAL) continue; break;
      }

    if (!ga[g]->grp_reg) {
      if (reg_confirm) {
        sprintf(err_oline,"Register %.200s? [y]:",ga[g]->grp_name);
        status = get_input(&usr_inp_dsc,c$dscl(&err_oline_d),&usr_inp_l);
        if (status == SMG$_EOF) longjmp(env,2);
        if ((status & 1) && ((!usr_inp_l) || (tolower(*usr_inp) == 'y'))) status = 1;
        else status = 0;
        }
      else status = 1;
      if (status) {
        no_more_news = 0;
        ++reg_groups;
        ga[g]->grp_reg = p;
        if (smg_active) screen_reg(g);
        else {
          sprintf(err_oline,"\tRegister: Newsgroup %.200s",ga[g]->grp_name);
          err_line(err_oline);
          }
        }
      }
    }
  sprintf(err_oline,"\tRegister: %d Newsgroups registered",reg_groups);
  err_line(err_oline);
  if (reg_groups &&
      ((cur_dir_type == DIR_NEW) || (cur_dir_type == DIR_REGISTER)))
    do_dir(cur_dir_type + 1, 1);
  return(0);
}

/*
 *  add_reg
 *
 *  Register a group to a user
 */

void add_reg(g,p)
  int g, p;
{
  int status;

  if (!ga[g]->grp_reg) {
    if (reg_confirm) {
      sprintf(err_oline,"Register %.200s? [y]:",ga[g]->grp_name);
      status = get_input(&usr_inp_dsc,c$dscl(&err_oline_d),&usr_inp_l);
      if (status == RMS$_EOF) longjmp(env,2);
      if ((status & 1) && ((!usr_inp_l) || (tolower(*usr_inp) == 'y'))) status = 1;
      else status = 0;
      }
    else status = 1;
    if (status) {
      no_more_news = 0;
      ga[g]->grp_reg = p;
      if (smg_active) screen_reg(g);
      else {
        sprintf(err_oline,"\tRegister: Newsgroup %.200s",ga[g]->grp_name);
        err_line(err_oline);
        }
      if ((cur_dir_type == DIR_NEW) || (cur_dir_type == DIR_REGISTER))
        do_dir(cur_dir_type + 1, 1);
      }
    }
  else ga[g]->grp_reg = p;
}

/*
 *  do_dereg_all
 *
 *  register user in all newsgroups
 */

int do_dereg_all()
{
  int g;

  for (g = 1; g <= ga_size; ++g) {
    if (ga[g]->grp_reg) {
      ga[g]->grp_reg = 0;
      if (smg_active) screen_dereg(g);
      else {
        sprintf(err_oline,"\tDeregister - Remove newsgroup %.200s",ga[g]->grp_name);
        err_line(err_oline);
        }
      }
    }
  if ((cur_dir_type == DIR_NEW) || (cur_dir_type == DIR_REGISTER))
    do_dir(cur_dir_type + 1, 1);
  return(0);
}

/*
 *  rem_reg
 *
 *  Deregister a group to a user
 */

void rem_reg(g)
  int g;
{
  int old_lev = news_context,
      og = curr_g;

  set_level(1);
  if (   (curr_g == g)
      && ((cur_dir_type == DIR_NEW) || (cur_dir_type == DIR_REGISTER))
      && (cur_down_grp(1,0) != 1))
    cur_up_grp(1,0);
  if (og == curr_g) set_level(old_lev);
  if (ga[g]->grp_reg) {
    ga[g]->grp_reg = 0;
    if (smg_active) screen_dereg(g);
    else {
      sprintf(err_oline,"\tDeregister - Remove newsgroup %.200s",ga[g]->grp_name);
      err_line(err_oline);
      }
    if ((cur_dir_type == DIR_NEW) || (cur_dir_type == DIR_REGISTER))
      do_dir(cur_dir_type + 1, 1);
    }
}

/*
 *  do_deregister
 *
 *  Remove a group from the user list - 1 if successful - 0 on failure
 */

static int dddr()
{
  int i = 0, g;
  char ngroup[GRPNAMELEN];
  $DESCRIPTOR(ngroup_dsc,ngroup);
  unsigned short ngroup_len;

  if (cli$present(c$dsc("ALL")) == CLI$_PRESENT) return(do_dereg_all(),0);
  if (cli$get_value(c$dsc("NEWSGROUP"),&ngroup_dsc,&ngroup_len) == CLI$_ABSENT)
    return((curr_g) ? (rem_reg(curr_g),0) : 0);
  ngroup[ngroup_len] = '\0';
  util_cvrt(ngroup,ngroup);
  for (g = 1; g <= ga_size; ++g) {
    if (wild_match(ga[g]->grp_name,ngroup)) {
      ++i;
      rem_reg(g);
      }
    }
  if (!i) {
    sprintf(err_oline,"\tError: Register - no such Newsgroup: %.200s",ngroup);
    err_line(err_oline);
    return(0);
    }
  return(0);
}

int do_deregister()
{
  return(unwind_display(OUTER_LOOP,dddr));
}

/*
 *  do_register
 *
 *  register newsgroup(s)
 */

static int drgr()
{
  int status;
  int g, since_time, reg_prio = 1, i = 0;
  char ngroup[GRPNAMELEN], sincestr[132];
  unsigned short ngroup_len, since_len;
  $DESCRIPTOR(since_dsc,sincestr);
  $DESCRIPTOR(ngroup_dsc,ngroup);

  if (cli$get_value(c$dsc("PRIORITY"),&ngroup_dsc,&ngroup_len) & 1) {
    ngroup[ngroup_len] = '\0';
    if (sscanf(ngroup,"%d",&reg_prio) != 1) reg_prio = 1;
    }
  if (reg_prio > 255) reg_prio = 255;
  if (reg_prio < 1) reg_prio = 1;
  reg_confirm = cli$present(c$dsc("CONFIRM")) & 1;
  if (cli$present(c$dsc("NEW"))  & 1) {
    do_reg_all(reg_prio,sys_reg_time,0);
    time(&sys_reg_time);
    return(0);
    }
  if (cli$present(c$dsc("ALL"))  & 1) {
    do_reg_all(reg_prio,0,0);
    time(&sys_reg_time);
    return(0);
    }
  if (cli$present(c$dsc("LOCAL")) & 1) {
    do_reg_all(reg_prio,0,2);
    if (cli$present(c$dsc("RECORD")) & 1) time(&sys_reg_time);
    return(0);
    }
  if (cli$present(c$dsc("NETGROUPS")) & 1) {
    do_reg_all(reg_prio,0,3);
    if (cli$present(c$dsc("RECORD")) & 1) time(&sys_reg_time);
    return(0);
    }
  if (cli$present(c$dsc("SINCE")) & 1)
    if (cli$get_value(c$dsc("SINCE"),&since_dsc,&since_len) & 1) {
      sincestr[since_len] = '\0';
      since_time = cvt_date_val(sincestr);
      do_reg_all(reg_prio,since_time,0);
      if (cli$present(c$dsc("RECORD")) & 1) time(&sys_reg_time);
      return(0);
    }
  if (cli$present(c$dsc("BEFORE")) & 1)
    if (cli$get_value(c$dsc("BEFORE"),&since_dsc,&since_len) & 1) {
      sincestr[since_len] = '\0';
      since_time = cvt_date_val(sincestr);
      do_reg_all(reg_prio,since_time,1);
      if (cli$present(c$dsc("RECORD")) & 1) time(&sys_reg_time);
      return(0);
      }
  if (cli$present(c$dsc("RECORD")) & 1) {
    time(&sys_reg_time);
    return(0);
    }

  if (cli$get_value(c$dsc("NEWSGROUP"),&ngroup_dsc,&ngroup_len) == CLI$_ABSENT)
    return((curr_g) ? (add_reg(curr_g,reg_prio),0) : 0);

#if FAST_LOAD
  if (fast_loading) {
    set_level(1);  /* ensure the directory is shown */
    if (! all_loaded ) {
      if (!nntp_client) {
        sysprv();
        sys_close(&itmfab);
        sys_close(&grpfab);
        nosysprv();               /* note this code is taken from the */
        close_hist_file();        /* closefiles function in the       */
        };                        /* NEWSFILES module.                */
      close_mail_file();  
      close_nntp_file();
      write_reg_file();
      all_loaded = 1;
      first_retr_call = 0;
      openfiles(nntp_client ? 4 : -1);
      }
    }                                       
#endif

  ngroup[ngroup_len] = '\0';
  util_cvrt(ngroup,ngroup);
  for (g = 1; g <= ga_size; ++g) {
    if (wild_match(ga[g]->grp_name,ngroup)) {
      ++i;
      add_reg(g,reg_prio);
      }
    }
  if (!i) {
    sprintf(err_oline,"\tError: Register - no such Newsgroup: %.200s",ngroup);
    err_line(err_oline);
    }
  return(0);
}

int do_register()
{
  return(unwind_display(OUTER_LOOP,drgr));
}
