/* hostconf.c */

#include "ml.h"

/* Here we have stuff for maintaining a generic network "service"
 * database. IMAP access strings are precomputed, and are stored
 * in the preferences file as URLs for easier parsing. 
 */



NetServices Services[] = {
  { "file",  SERVICE_LOCAL,      },
  { "news" , SERVICE_NEWS,       },
  { "nntp" , SERVICE_NNTP        },
  { "pop3" , SERVICE_POP         },
  { "imap" , SERVICE_IMAP        },
  { "imsp" , SERVICE_IMSP        },
  { NULL   , SERVICE_NONE        },
};



Menu net_file_menu[] = {
  { NULL, "add", NUL_TERM,
      net_add, NULL, 0, NULL, NULL, BTN_SELECTION },
  { NULL, "modify", NUL_TERM,
      net_modify, NULL, 0, NULL, NULL, BTN_NOSELECTION },
  { NULL, "remove", NUL_TERM,
      net_remove, NULL, 0, NULL, NULL, BTN_NOSELECTION },
  { NULL, "close_window", NUL_TERM,
      net_close_window, NULL, 0, NULL, NULL, BTN_ON },
};

Menu net_main_menu[] = {
  { NULL, "file_menu", NUL_TERM,
      NULL, net_file_menu, XtNumber(net_file_menu), NULL, NULL, BTN_ON },
  { NULL, "reset", NUL_TERM,
      net_reset, NULL, 0, NULL, NULL, BTN_ON }, 
  { NULL, "HELP", NUL_TERM,
      net_help, NULL, 0, NULL, NULL, BTN_ON },

};



#ifdef __STDC__
void net_check_buttons(Network_Config *netconf)
#else
void net_check_buttons(netconf)
     Network_Config *netconf;
#endif
{
  if(netconf && netconf->is_realized)
    update_buttons(netconf->buttonlist,
		   netconf->buttonstate);
  return;
}




#ifdef __STDC__
Server_Config *new_server_config(void)
#else
Server_Config *new_server_config()
#endif
{
  Server_Config *server_config 
    = (Server_Config *) fs_get(sizeof(Server_Config));

  server_config->name         = NULL;
  server_config->type         = SERVICE_LOCAL;
  server_config->url          = NULL;
  server_config->imap         = NULL;
  server_config->hostname     = NULL;
  server_config->port         = 0;
  server_config->username     = NULL;
  server_config->password     = NULL;
  server_config->mailbox      = NULL;
  server_config->in_use       = FALSE;
  server_config->subscribed   = NULL;
  server_config->unsubscribed = NULL;
  server_config->next         = NULL;
  server_config->prev         = NULL;

  return(server_config);
}

#ifdef __STDC__
void free_server_config(Server_Config *server_config, Boolean recurse)
#else
void free_server_config(server_config,recurse)
     Server_Config *server_config;
     Boolean recurse;
#endif
{
  if(server_config == NULL)
    return;
  if(recurse)
    free_server_config(server_config->next, recurse);
  if(server_config->name)
    fs_give((void **) &server_config->name);
  if(server_config->url)
    fs_give((void **) &server_config->url);
  if(server_config->imap)
    fs_give((void **) &server_config->imap);
  if(server_config->hostname != NULL)
    fs_give((void **) &server_config->hostname);
  if(server_config->username != NULL)
    fs_give((void **) &server_config->username);
  if(server_config->password != NULL)
    fs_give((void **) &server_config->password);
  if(server_config->mailbox != NULL)
    fs_give((void **) &server_config->mailbox);
  if(server_config->subscribed)
    free_mailbox_list(server_config->subscribed);
  if(server_config->unsubscribed)
    free_mailbox_list(server_config->unsubscribed);
  fs_give((void **) &server_config);
  return;
}



#ifdef __STDC__
void create_host_window(Widget w, char *str)
#else
void create_host_window(w, str)
     Widget w;
     char *str;
#endif
{
  Arg args[ARGLISTSIZE];
  int n = 0;
  XtTranslations translations;
  Network_Config *netconf;

  if(session->netconf != NULL) {
    if(session->netconf->is_realized == TRUE)
      de_iconify(session->netconf->shell);
    else {
      XtPopup(session->netconf->shell,XtGrabNone);
      session->netconf->is_realized = TRUE;
    }
    return;
  }

  netconf = (Network_Config *) fs_get(sizeof(Network_Config));
  netconf->is_realized = FALSE;
  session->netconf = netconf;

  netconf->servicetype = SERVICE_IMAP;
  netconf->sel_port = 143;
  netconf->buttonlist = NULL;
  netconf->buttonstate = BTN_ON | BTN_NOSELECTION;
  netconf->current = NULL;
  XtSetArg (args[n], XmNdeleteResponse, XmDO_NOTHING); n++;   
  netconf->shell = XtCreatePopupShell("netconf",topLevelShellWidgetClass,
				      session->shell, args,n);
  n = 0;
  AddDestroyCallback (netconf->shell);
  setup_editres(netconf->shell);

  if(ml_icon != (Pixmap) None)
    XtVaSetValues(netconf->shell,
		  XmNiconPixmap,ml_icon,
		  NULL);

  netconf->form = XmCreateForm(netconf->shell, "form", args, n );     n = 0;

  XtSetArg(args[n], XmNtopAttachment,   XmATTACH_FORM);               n ++;
  XtSetArg(args[n], XmNleftAttachment,  XmATTACH_FORM);               n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);               n ++;
  netconf->menubar = XmCreateMenuBar(netconf->form, "menubar", args, n);
  n = 0;
  XtManageChild(netconf->menubar);


  make_buttons(&netconf->buttonlist, NULL, netconf->menubar, 
	       net_main_menu, 
	       XtNumber(net_main_menu),
	       netconf->buttonstate, 
	       (XtPointer) netconf, ROOTMENULEVEL);



  netconf->nick =
    create_text_field(netconf->form, netconf->menubar, 
		      "nick", NULL, 0, NULL, NULL);

  netconf->name =
    create_text_field(netconf->form, netconf->nick,
		      "name", NULL, 0, NULL, NULL);

  netconf->user =
    create_text_field(netconf->form, netconf->name, 
		      "user", NULL, 0, NULL, NULL);

/*  netconf->pass =
 *   create_text_field(netconf->form, netconf->user, 
 *		      "pass", NULL, 0, NULL, NULL);
 */

  netconf->mbox =
    create_text_field(netconf->form, netconf->user, 
		      "mbox", NULL, 0, NULL, NULL);


  XtSetArg(args[n], XmNadjustMargin, FALSE);      n ++;
  XtSetArg(args[n], XmNmarginWidth, 0);           n ++;
  XtSetArg(args[n], XmNborderWidth, 0);           n ++;

  XtSetArg(args[n], XmNnumColumns, 3);                     n ++;
  XtSetArg(args[n], XmNtopAttachment,   XmATTACH_WIDGET);    n ++;
  XtSetArg(args[n], XmNtopWidget, netconf->mbox);          n ++;
  XtSetArg(args[n], XmNleftAttachment,  XmATTACH_FORM);    n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);      n ++;
  XtSetArg(args[n], XmNradioBehavior,   TRUE);               n ++;
  XtSetArg(args[n], XmNradioAlwaysOne,  TRUE);               n ++;
  XtSetArg(args[n], XmNorientation,     XmVERTICAL);         n ++;
  XtSetArg(args[n], XmNpacking, XmPACK_COLUMN);              n ++;
  netconf->rowcol = XtCreateWidget("rowcol",
				   xmRowColumnWidgetClass,
				   netconf->form, args, n );
  n = 0;
  XtManageChild(netconf->rowcol);
  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;
  netconf->button1 = XmCreateToggleButton(netconf->rowcol, "local_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button1);

  XtAddCallback(netconf->button1, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "local");

  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;
  netconf->button2 = XmCreateToggleButton(netconf->rowcol, "localn_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button2);

  XtAddCallback(netconf->button2, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "localn");

  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;
  netconf->button3 = XmCreateToggleButton(netconf->rowcol, "nntp_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button3);

  XtAddCallback(netconf->button3, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "nntp");

  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;
  netconf->button4 = XmCreateToggleButton(netconf->rowcol, "pop_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button4);

  XtAddCallback(netconf->button4, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "pop");

  XtSetArg(args[n], XmNset, TRUE);                        n ++;
  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;

  netconf->button5 = XmCreateToggleButton(netconf->rowcol, "imap_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button5);

  XtAddCallback(netconf->button5, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "imap");

  XtSetArg(args[n], XmNborderWidth, 0);           n ++;
  XtSetArg(args[n], XmNtraversalOn, FALSE);       n ++;
  netconf->button6 = XmCreateToggleButton(netconf->rowcol, "special_toggle",
					  args, n); n = 0;
  XtManageChild(netconf->button6);

  XtAddCallback(netconf->button6, XmNvalueChangedCallback, 
		(XtCallbackProc) netconf_select, "special");



  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);   n ++;
  XtSetArg(args[n], XmNtopWidget, netconf->rowcol); n ++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++;

  XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n ++;
  XtSetArg(args[n], XmNlistSizePolicy,XmCONSTANT);        n ++;
  XtSetArg(args[n], XmNselectionPolicy,XmSINGLE_SELECT);  n ++;
  netconf->list = XmCreateScrolledList(netconf->form,"list",args,n); 
  n = 0;

  XtAddCallback(netconf->list, XmNsingleSelectionCallback, 
		(XtCallbackProc) net_select, netconf);
  XtAddCallback(netconf->list, XmNdefaultActionCallback, 
		(XtCallbackProc) net_default, netconf);

  translations = XtParseTranslationTable(GLOBAL_netconf_pop_translations);
  XtOverrideTranslations(netconf->list, translations);

  XtAddCallback(netconf->shell, XmNpopdownCallback, 
		(XtCallbackProc) net_popdown, netconf);

  XtAddCallback(netconf->shell, XmNdestroyCallback, 
		(XtCallbackProc) net_destroy, netconf);


  XtSetValues(XtParent(netconf->list), args, n); n = 0;
  XtManageChild(netconf->list);

  stuff_host_list(netconf, FALSE);


  XtManageChild(netconf->form);
  XtManageChild(netconf->shell);
  XtPopup(netconf->shell,XtGrabNone); 

  net_check_buttons(netconf);

  if(str)
    XmTextSetString(netconf->nick,str);

  netconf->is_realized = TRUE;
  return;
}

#ifdef __STDC__
void net_add(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_add(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  char log[FILEBUFFLEN];
  char *tmp;
  Server_Config *now;
  Server_Config *prev;

  tmp = XmTextGetString(netconf->nick);
  if(*tmp == NUL_TERM)
    return;

  for(now = session->servers; now; now = now->next)
    if((now->name != NULL) && ((strcmp(now->name,tmp)) == STRMATCH)) {
      mm_log(MLGetLocalized(XtNmsgDuplicate,MsgDuplicate),WARN);
      fs_give((void **) &tmp);
      return;
    }

  now = new_server_config();
  now->name = tmp;

  tmp = XmTextGetString(netconf->name);

  if(*tmp != NUL_TERM) {
    if((ml_confirm(netconf->shell,MLGetLocalized(XtNmsgYouConnected,
						 MsgYouConnected),
		   CONFIRM_YES_NO)) == FALSE) {
      
      lcase(tmp);
      sprintf(log,MLGetLocalized(XtNmsgCannotQualify,
				 MsgCannotQualify), tmp);
      mm_log(log,WARN);
    }
    else
      now->hostname = get_qualified_host_name(tmp);
  }
  fs_give((void **) &tmp);
  XmTextSetString(netconf->name,
		  (now->hostname) ? now->hostname : EMPTYSTR);


  tmp = XmTextGetString(netconf->user);
  if(*tmp != NUL_TERM)
    now->username = cpystr(tmp);
  fs_give((void **) &tmp);

  tmp = XmTextGetString(netconf->mbox);
  if(*tmp != NUL_TERM)
    now->mailbox = cpystr(tmp);
  fs_give((void **) &tmp);

  now->type = netconf->servicetype;
  now->port = netconf->sel_port;

  now->url = server_config_to_url(now);
  now->imap = server_config_to_imap(now);


  if(session->servers == NULL)
    session->servers = now;
  else
    for(prev = session->servers; prev->next; prev = prev->next)
      ;
  if(prev)
    prev->next = now;
  now->prev = prev;

  stuff_host_list(netconf,TRUE);
  save_defaults();
  net_context_switch(netconf,NULL, now);
  return;

}



#ifdef __STDC__
void net_select(Widget w, Network_Config *netconf, XmListCallbackStruct *cb)
#else
void net_select(w, netconf, cb)
     Widget w;
     Network_Config *netconf;
     XmListCallbackStruct *cb;
#endif
{
  unsigned char *str;
  Server_Config *server;

  XmStringGetLtoR(cb->item, XmSTRING_DEFAULT_CHARSET, (char **) &str);
  for(server = session->servers; server; server = server->next) {
    if((ml_strcoll((unsigned char *) server->name,str)) == STRMATCH) {
      net_context_switch(netconf,netconf->current, server);
      netconf->buttonstate |= BTN_SELECTION;
      netconf->buttonstate &= ~BTN_NOSELECTION;
    }
  }
  fs_give((void **) &str);

  net_check_buttons(netconf);
  return;
}


#ifdef __STDC__
void net_context_switch(Network_Config *netconf,
			Server_Config *old,
			Server_Config *now)
#else
void net_context_switch(netconf,old,now)
     Network_Config *netconf;
     Server_Config *old;
     Server_Config *now;
#endif
{

  netconf->current = now;
  if(now) {
    XmTextSetString(netconf->nick,(now->name) ? now->name : EMPTYSTR);
    XmTextSetString(netconf->name,(now->hostname) ? now->hostname : EMPTYSTR);
    XmTextSetString(netconf->user,(now->username) ? now->username : EMPTYSTR);
    XmTextSetString(netconf->mbox,(now->mailbox) ? now->mailbox : EMPTYSTR);
    netconf->sel_port = now->port;
    netconf->servicetype = now->type;

    switch(now->type) {
    case SERVICE_LOCAL:
      XmToggleButtonSetState(netconf->button1, TRUE, TRUE);
      break;
    case SERVICE_NEWS:
      XmToggleButtonSetState(netconf->button2, TRUE, TRUE);
      break;
    case SERVICE_NNTP:
      XmToggleButtonSetState(netconf->button3, TRUE, TRUE);
      break;
    case SERVICE_POP:
      XmToggleButtonSetState(netconf->button4, TRUE, TRUE);
      break;
    case SERVICE_IMAP:
    case SERVICE_NONE:
    default:
      XmToggleButtonSetState(netconf->button5, TRUE, TRUE);
      /* Hack so the TCP prompt isn't popped up during a context switch */
      if(now->port != 143) {
	netconf->sel_port = now->port; /* re-do after toggle */
	XmToggleButtonSetState(netconf->button5, FALSE, FALSE);
	XmToggleButtonSetState(netconf->button6, TRUE, FALSE);
      }
      break;
      
    }

    netconf->buttonstate |= BTN_SELECTION;
    netconf->buttonstate &= BTN_NOSELECTION;
    net_check_buttons(netconf);
  }
  else 
    net_reset(netconf->shell, netconf, NULL);

  return;
}



#ifdef __STDC__
void net_default(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_default(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{

}

#ifdef __STDC__
void net_destroy(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_destroy(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  free_buttonlist(netconf->buttonlist);
  fs_give((void **) &session->netconf);
  session->netconf = NULL;
}


#ifdef __STDC__
void net_modify(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_modify(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  char *tmp;
  Server_Config *now;
  Server_Config *prev;

  if(netconf->current == NULL)
    return;

  tmp = XmTextGetString(netconf->nick);
  if(*tmp == NUL_TERM)
    return;

  now = netconf->current;
  if(now->name)
    fs_give((void **) &now->name);
  now->name = tmp;

  tmp = XmTextGetString(netconf->name);
  if(*tmp != NUL_TERM) {
    if(now->hostname != NULL)
      fs_give((void **) &now->hostname);
    now->hostname = get_qualified_host_name(tmp);
  }
  fs_give((void **) &tmp);
  XmTextSetString(netconf->name,now->hostname);


  tmp = XmTextGetString(netconf->user);
  if(*tmp != NUL_TERM) {
    if(now->username)
      fs_give((void **) &now->username);
    now->username = cpystr(tmp);
  }
  fs_give((void **) &tmp);

  tmp = XmTextGetString(netconf->mbox);
  if(*tmp != NUL_TERM) {
    if(now->mailbox)
      fs_give((void **) &now->mailbox);
    now->mailbox = cpystr(tmp);
  }
  fs_give((void **) &tmp);

  now->type = netconf->servicetype;
  now->port = netconf->sel_port;

  if(now->url)
    fs_give((void **) &now->url);
  now->url = server_config_to_url(now);

  if(now->imap)
    fs_give((void **) &now->imap);
  now->imap = server_config_to_imap(now);

  stuff_host_list(netconf,TRUE);
  save_defaults();
  net_context_switch(netconf,NULL, now);
  return;

}


#ifdef __STDC__
void net_remove(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_remove(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  if(netconf->current == NULL)
    return;
  if((preferences.confirmDestroy == TRUE)
     && ((ml_confirm(netconf->shell,
		     MLGetLocalized(XtNmsgDestroyConfig,
				    MsgDestroyConfig),
		     CONFIRM_OK_CANCEL)) == FALSE))
    return;

  if(netconf->current == session->servers)
    session->servers = netconf->current->next;
  if(netconf->current->next)
    netconf->current->next->prev = netconf->current->prev;
  if(netconf->current->prev)
    netconf->current->prev->next = netconf->current->next;

  free_server_config(netconf->current, FALSE);

  stuff_host_list(netconf,TRUE);
  save_defaults();
  net_reset(w,netconf,xp);
  return;
}

#ifdef __STDC__
void net_popdown(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_popdown(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  netconf->is_realized = FALSE;
  return;
}



#ifdef __STDC__
void net_close_window(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_close_window(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  XtPopdown(netconf->shell);
  netconf->is_realized = FALSE;
  return;
}

#ifdef __STDC__
void net_reset(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_reset(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  XmTextSetString(netconf->nick,EMPTYSTR);
  XmTextSetString(netconf->name,EMPTYSTR);
  XmTextSetString(netconf->user,EMPTYSTR);
  XmTextSetString(netconf->mbox,EMPTYSTR);
  XmToggleButtonSetState(netconf->button5, TRUE,TRUE);
  XmListDeselectAllItems(netconf->list);

  netconf->current = NULL;
  netconf->sel_port = 143;
  netconf->servicetype = SERVICE_IMAP;
  netconf->buttonstate |= BTN_NOSELECTION;
  netconf->buttonstate &= ~BTN_SELECTION;

  net_check_buttons(netconf);

}


#ifdef __STDC__
void net_help(Widget w, Network_Config *netconf, XtPointer xp)
#else
void net_help(w, netconf, xp)
     Widget w;
     Network_Config *netconf;
     XtPointer xp;
#endif
{
  help(netconf->shell,CONFIGHELPFILE);
  return;
}


#ifdef __STDC__
void stuff_host_list(Network_Config *netconf, Boolean update)
#else
void stuff_host_list(netconf, update)
     Network_Config *netconf;
     Boolean update;
#endif
{
  Server_Config *server;
  XmString xstr;
  if(update) {
    XmListDeselectAllItems(netconf->list);
    XmListDeleteAllItems(netconf->list);
  }

  for (server = session->servers; server; server = server->next) {
    xstr = XmStringCreateSimple((char *) server->name);
    XmListAddItemUnselected(netconf->list, xstr, 0);
    XmStringFree(xstr);
  }
  return;
}

#ifdef __STDC__
Server_Config *find_server_config(char *hostname, char *service)
#else
Server_Config *find_server_config(hostname, service)
     char *hostname;
     char *service;
#endif
{
  return(NULL);
#ifdef FLOG
  Server_Config *server_config = NULL;
  char local_hostname[MAXHOSTNAMELEN];
  Boolean found = FALSE;

  if(hostname)
    strncpy(local_hostname,hostname,MAXHOSTNAMELEN);
  else
    strcpy(local_hostname,EMPTYSTR);

  for(server_config = session->servers; server_config;
      server_config = server_config->next) {
    if(server_config->hostname == NULL) {
      if((*local_hostname == NUL_TERM) 
	 && (strcmp(service,server_config->service) == STRMATCH)) {
	found = TRUE;
	break;
      }
    }
    else {
      if(((strcasecmp(server_config->hostname,hostname)) == STRMATCH)
	 && ((strcmp(server_config->service,service)) == STRMATCH)) {
	found = TRUE;
	break;
      }
    }
  }
  return(server_config);
#endif
  

}

#ifdef __STDC__
Server_Config *find_server_by_host(char *hostname)
#else
Server_Config *find_server_by_host(hostname)
     char *hostname;
#endif
{
  Server_Config *server_config = NULL;

  if(hostname) {
    for(server_config = session->servers; server_config;
	server_config = server_config->next) {
      if((server_config->hostname != NULL)
	 && ((strcasecmp(server_config->hostname,hostname)) == STRMATCH))
	return(server_config);
    }
  }
  return(server_config);
}




#ifdef __STDC__
Server_Config *find_configuration(char *name)
#else
Server_Config *find_configuration(name)
     char *name;
#endif
{
  Server_Config *server_config = NULL;

  if((name != NULL) && (*name != NUL_TERM)) 
    for(server_config = session->servers; server_config;
	server_config = server_config->next)
      if((strcasecmp(name,server_config->name)) == STRMATCH)
	return(server_config);

  return(server_config);
}


#ifdef __STDC__
void netconf_select(Widget w, XtPointer call_data,
		    XmToggleButtonCallbackStruct *xp)
#else
void netconf_select(w,call_data,xp)
     Widget w;
     XtPointer call_data;
     XmToggleButtonCallbackStruct *xp;
#endif
{
  char *result = NULL;
  char buffer[128];
  if(xp->set == TRUE) {
    if((strcmp((char *)call_data,"local")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_LOCAL;
      session->netconf->sel_port = 0;
    }
    if((strcmp((char *)call_data,"localn")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_NEWS;
      session->netconf->sel_port = 0;
    }
    if((strcmp((char *)call_data,"nntp")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_NNTP;
      session->netconf->sel_port = 0;
    }
    if((strcmp((char *)call_data,"pop")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_POP;
      session->netconf->sel_port = 0;
    }
    if((strcmp((char *)call_data,"imap")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_IMAP;
      session->netconf->sel_port = 143;
    }
    if((strcmp((char *) call_data,"special")) == STRMATCH) {
      session->netconf->servicetype = SERVICE_IMAP;
      sprintf(buffer,"%d",session->netconf->sel_port);
      result = input_string(session->netconf->shell,
			    MLGetLocalized(XtNmsgTCPPort,MsgTCPPort),
			    buffer,
			    TCPPORTHELPFILE);
      if((result == NULL) || (*result == NUL_TERM)) {
	if(result)
	  fs_give((void **) &result);
	return;
      }
      session->netconf->sel_port = atoi(result);
      fs_give((void **) &result);
    }
  }
  return;
}


#ifdef __STDC__
char *fix_str(char *s)
#else
char *fix_str(s)
     char *s;
#endif
{
  char *src = s;
  char *buffer;
  char *dst;

  if((s == NULL) || (*s == NUL_TERM))
    return(cpystr(NIL_STR));
  if(((strchr(s,SPACECHAR)) == NULL) && ((strchr(s,DQUOTECHAR)) == NULL)) 
    return(cpystr(s));
  else {
    buffer = fs_get(strlen(s) + 128);
    dst = buffer;
    *dst++ = DQUOTECHAR;
    while(*src != NUL_TERM) {
      switch(*src) {
      case DQUOTECHAR:
	*dst++ = '\\';
      default:
	*dst++ = *src++;
	break;
      }
    }
    *dst++ = DQUOTECHAR;
    *dst = NUL_TERM;
  }
  return(buffer);
}

#ifdef __STDC__
char *get_next_fixed_str(char *s, char **end)
#else
char *get_next_fixed_str(s,end)
     char *s;
     char **end;
#endif
{
  char *ret = NULL;
  char *ptr;
  char *src;
  char *dst;

  if(s == NULL) {
    *end = NULL;
    return(NULL);
  }

  if(*s != DQUOTECHAR) {
    ptr = strchr(s,SPACECHAR);
    if(ptr != NULL) {
      *ptr = NUL_TERM;
      *end = ptr + 1;
    }
    else
      *end = NULL;
    return((((strcmp(s,NIL_STR))) == STRMATCH)
	   ? NULL : cpystr(s));
  }
  else {
    s ++;
    ret = fs_get(strlen(s));
    src = s;
    dst = ret;
    while(*src != NUL_TERM) {
      if(*src == '\\') {
	src ++;
	continue;
      }
      if(*src == DQUOTECHAR) {
	if(*(src - 1) == '\\') {
	  *dst ++ = *src ++;
	  continue;
	}
	else {
	  src ++;
	  break;
	}
      }
      *dst ++ = *src ++;
    }
    *dst = NUL_TERM;
    if(*src == SPACECHAR)
      *end = src + 1;
    else
      *end = NULL;
    return(ret);
  }
  /* NOTREACHED */
}


#ifdef __STDC__
char *server_config_to_url(Server_Config *server_config)
#else
char *server_config_to_url(server_config)
     Server_Config *server_config;
#endif
{
  char buffer[FILEBUFFLEN];
  char portbuffer[16];

  sprintf(buffer,"%s:",service_type_to_name(server_config->type));
  if((server_config->type == SERVICE_LOCAL) 
     || (server_config->type == SERVICE_NEWS))
    return(cpystr(buffer));

  if(server_config->hostname == NULL)
    server_config->hostname = cpystr("localhost");

  strcat(buffer,"//");
  strcat(buffer,server_config->hostname);

  if(server_config->port) {
    sprintf(portbuffer,":%d",server_config->port);
    strcat(buffer,portbuffer);
  }
  return(cpystr(buffer));
}


#ifdef __STDC__
char *server_config_to_imap(Server_Config *server_config)
#else
char *server_config_to_imap(server_config)
     Server_Config *server_config;
#endif
{
  char buffer[FILEBUFFLEN];
  char portbuffer[16];
  ServiceType type = server_config->type;

  if((type == SERVICE_LOCAL) 
     || (type == SERVICE_NEWS)
     || (type == SERVICE_NONE))
    return(NULL);

  if(server_config->hostname == NULL)
    server_config->hostname = cpystr("localhost");

  strcpy(buffer,"{");
  strcat(buffer,server_config->hostname);
  if(type == SERVICE_IMAP) {
    if(server_config->port != 0) {
      sprintf(portbuffer,":%d",server_config->port);
      strcat(buffer,portbuffer);
    }
  }
  if((type == SERVICE_NNTP) || (type == SERVICE_POP)) {
    strcat(buffer,"/");
    strcat(buffer,service_type_to_name(type));
  }
  strcat(buffer,"}");
  return(cpystr(buffer));
}

#ifdef __STDC__
void fill_server_config(Server_Config *server_config)
#else
void fill_server_config(server_config)
     Server_Config *server_config;
#endif
{
  char buffer[FILEBUFFLEN];
  char *ptr;

  if(server_config->url == NULL)
    return;

  strcpy(buffer,server_config->url);

  ptr = strchr(buffer,COLONCHAR);
  *ptr = NUL_TERM;
  ptr ++;
  server_config->type = service_name_to_type(buffer);
  while((*ptr != NUL_TERM) && (*ptr == '/'))
    ptr ++;
  strcpy(buffer,ptr);
  if((ptr = strchr(buffer,COLONCHAR)) != NULL) {
    *ptr = NUL_TERM;
    ptr ++;
    server_config->port = atoi(ptr);
  }
  else
    server_config->port = 0;
  server_config->hostname = cpystr(buffer);
  server_config->imap  = server_config_to_imap(server_config);
  return;
}



#ifdef __STDC__
Server_Config *fix_server_config(Server_Config *server_config)
#else
Server_Config *fix_server_config(server_config)
     Server_Config *server_config;
#endif
{
  Server_Config *tmp = new_server_config();
  tmp->type = server_config->type;
  tmp->name = fix_str(server_config->name);
  tmp->url = fix_str(server_config->url);
  tmp->imap = fix_str(server_config->imap);
  tmp->hostname = fix_str(server_config->hostname);
  tmp->port = server_config->port;
  tmp->username = fix_str(server_config->username);
  tmp->mailbox = fix_str(server_config->mailbox);
  return(tmp);
}

#ifdef __STDC__
int save_server_tables(FILE *fp)
#else
int save_server_tables(fp)
     FILE *fp;
#endif
{
  Server_Config *server_config;
  Server_Config *tmp;
  char buffer[FILEBUFFLEN];
  
  fprintf(fp,"\n%s\n",BEGIN_SERVERS_STR);
  for(server_config = session->servers; 
      server_config; server_config = server_config->next) {
    tmp = fix_server_config(server_config);
    fprintf(fp,"%s %s %s %s %s\n",
	    service_type_to_name(tmp->type), 
	    tmp->name, tmp->url, tmp->username, tmp->mailbox);
    free_server_config(tmp, FALSE);
  }
  fprintf(fp,"%s\n",END_SERVERS_STR);
  return(0);
}


#ifdef __STDC__
int load_server_tables(FILE *fp)
#else
int load_server_tables(fp)
     FILE *fp;
#endif
{
  char buffer[FILEBUFFLEN];
  char *ptr = NULL;
  char *end = NULL;
  int errors = 0;
  char *portstr;

  Server_Config *prev = NULL;
  Server_Config *server_config;

  while((fgets(buffer,sizeof(buffer),fp)) != NULL) {
    buffer[strlen(buffer)-1] = '\0';

    if((strcmp(buffer,END_SERVERS_STR)) == STRMATCH)
      return(0);

    if((ptr = strchr(buffer,SPACECHAR)) == NULL)
      continue;
    *ptr = NUL_TERM;
    ptr ++;
    server_config = new_server_config();

    server_config->type = service_name_to_type(buffer);

    server_config->name = get_next_fixed_str(ptr,&end);
    ptr = end;
    server_config->url = get_next_fixed_str(ptr,&end);
    ptr = end;
    server_config->username = get_next_fixed_str(ptr,&end);
    ptr = end;
    server_config->mailbox = get_next_fixed_str(ptr,&end);

    fill_server_config(server_config);

    prev = NULL;
    if(session->servers != NULL)
      for(prev = session->servers; prev->next; prev = prev->next)
	;

    if(prev == NULL) 
      session->servers = server_config;
    else {
      prev->next = server_config;
      server_config->prev = prev;
    }
  }
  return(0);
}


#ifdef __STDC__
char *service_type_to_name(ServiceType type)
#else
char *service_type_to_name(type)
     ServiceType type;
#endif
{
  int cnt;
  for(cnt = 0; Services[cnt].service != NULL; cnt ++ )
    if(Services[cnt].type == type)
      return(Services[cnt].service);
  return(NULL);
}

#ifdef __STDC__
ServiceType service_name_to_type(char *name)
#else
ServiceType service_name_to_type(name)
     char *name;
#endif
{
  int cnt;
  for(cnt = 0; Services[cnt].service != NULL; cnt ++ )
    if((strcmp(Services[cnt].service,name)) == STRMATCH)
      return(Services[cnt].type);
  return(SERVICE_NONE);
}




#ifdef __STDC__
void set_default_server_config(void)
#else
void set_default_server_config()
#endif
{
  Server_Config *server_config;
  if(session->servers == NULL) {
    server_config = new_server_config();
    server_config->name = cpystr(MLGetLocalized(XtNstrDefault,StrDefault));
    server_config->type = SERVICE_LOCAL;
    server_config->mailbox = cpystr(INBOX);
    fill_server_config(server_config);
    session->servers = server_config;
  }
  return;
}


#ifdef __STDC__
void netconf_pop(Widget w, XtPointer xp)
#else
void netconf_pop(w,xp)
     Widget w;
     XtPointer xp;
#endif
{
  net_close_window(w,session->netconf,NULL);
  return;
}


syntax highlighted by Code2HTML, v. 0.9.1