"Fossies" - the Fresh Open Source Software archive

Member "xvnews-2.3.4/xv_search.c" of archive xvnews-2.3.4.tar.gz:


/*
 * This file is provided for unrestricted use
 * provided that this legend is included on all tape media
 * and as a part of the software program in whole or part.  Users
 * may copy or modify this file without charge, but are not authorized to
 * license or distribute it to anyone else except as part of a product
 * or program developed by the user.
 *
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

#include <X11/Xos.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <xview/xview.h>
#include <xview/font.h>
#include <xview/canvas.h>
#include <xview/panel.h>
#define _OTHER_TEXTSW_FUNCTIONS /* For additional prototypes... */
#include <xview/termsw.h>
#include <xview/text.h>
#include <xview/notice.h>

#include "xvnews_ui.h"
#include "xvnews.h"
#include "codes.h"

extern struct globals	*Global;

STATIC_FUNCTION( int body_search, (int, char *, char *));
STATIC_FUNCTION( int get_sub_prev, (xvnews_xvnews_window_objects *,
				    char *, char *));
STATIC_FUNCTION( int nnrp_get_sub_prev, (xvnews_xvnews_window_objects *,
					 char *, char *));

extern int subject_search(ip, next)
xvnews_xvnews_window_objects    *ip;
int	next;
{
	int	row, num = 0, art;
	char	old[SUBJECT_LENGTH + 1];
	char	*str;

	assert(ip);
	assert(next == 0 || next == 1);

	row = xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
	str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);

	while (isdigit(*str) || *str == ' ') {
                ++str;
                ++num;
        }
 
        memset(old, '\0', SUBJECT_LENGTH);
        strncpy(old, str, SUBJECT_LENGTH - num);

	next ? row++:row--;
	while (row < xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL)) {
		str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);
		sscanf(str, "%d", &art);
		str += num;
		if ((!strncmp(old, str, SUBJECT_LENGTH - num) ||
			(!strncasecmp(str, "re:", 3) &
			!strncmp(old, &str[4], SUBJECT_LENGTH - num - 4)) ||
			(!strncasecmp(old, "re:", 3) &
			!strncmp(&old[4], str, strlen(old) - 4)) ||
			(!strncasecmp(str, "re:", 3) & !strncasecmp(old, "re:", 3) &
			!strncmp(&old[4], &str[4], strlen(old) - 4))) &&
			!isRead(str)) {

			xv_set(ip->articles_list,
				PANEL_LIST_SELECT, row, TRUE, NULL);
			retrieve_article(ip, art);
			return 1;
		}
	next ? row++:row--;
	}
	if (next) {
	  art = Global->article;
	  Global->article = next_unread_art(ip);
	  if (art == Global->article) {
	    if (Global->mode == ARTICLE_MODE) {
	      update_newsrc(ip, 0);
	    }
	    groups_set(ip);
	  }
	  else {
	    retrieve_article(ip, Global->article);
	    xvnews_err(ip, "No subject matches found, went to next unread article\n");
	  }
	  return -1;
	}
	xvnews_err(ip, "Searching archives for previous subject...\n");
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	if (toupper(old[0]) == 'R' && toupper(old[1]) == 'E') {
		if (Global->nnrp)
			art = nnrp_get_sub_prev(ip, "subject", &old[3]);
		else
			art = get_sub_prev(ip, "subject", &old[3]);
	} else {
		if (Global->nnrp)
			art = nnrp_get_sub_prev(ip, "subject", old);
		else
			art = get_sub_prev(ip, "subject", old);
	}
	if (art == -1) {
		xvnews_err(ip, "No matches found!\n");
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
		return -1;
	}
	xv_set(ip->articles_list, PANEL_LIST_SELECT, art, TRUE, NULL);
	retrieve_article(ip, xv_get(ip->articles_list, PANEL_LIST_CLIENT_DATA,
		art, NULL));
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
	return 1;
}

static int get_sub_prev(ip, comm, str)
xvnews_xvnews_window_objects    *ip;
char	*comm;
char	*str;
{
	int 	last = -1, art, num = 0, status;
	char	*old;
	char	string[49], message[MAX_MESSAGE_LEN];

	if (!notice_prompt(ip->controls1, NULL, NOTICE_MESSAGE_STRINGS, 
			"No match was found in unread articles.",
			"Search previously read articles?",
		 	NULL,
		NOTICE_BUTTON_YES, "Search",
		NOTICE_BUTTON_NO, "Abort",
		NULL))
			return -1;
	old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING,
		xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL),
			 NULL);
	sscanf(old, "%d", &art);
	put_server("XHDR %s 0-%d\n", comm, --art);
	memset(string, '\0', 49);
	num = strlen(str) - 1;
	while (str[num--] == ' ');
	strncpy(string, str, num+2);
	status = get_server(message, sizeof(message));
	if (status != OK_HEAD) {
		reconnect_server();
		put_server("XHDR %s 0-%d\n", comm, --art);
		status = get_server(message, sizeof(message));
		if (status != OK_HEAD) 
			return -1;
	}
	while (*message != '.') {
		get_server(message, sizeof(message));
		if (strstr(message, string) != NULL) {
			sscanf(message, "%d", &last);
		}
	}
	if (last != -1)
		return get_prev(ip, last);

	return -1;
}

extern int author_search(ip, next)
xvnews_xvnews_window_objects    *ip;
int     next;
{
	int     row, art;
        char    old[AUTHOR_LENGTH + 1];
        char    *str;

        row = xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
        str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);

	str += SUBJECT_LENGTH + 1;

	memset(old, '\0', AUTHOR_LENGTH + 1);
	strncpy(old, str, AUTHOR_LENGTH);

	next ? row++:row--;
	while (row < xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL)) {
		str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row,
NULL);
		sscanf(str, "%d", &art);
		str += SUBJECT_LENGTH + 1;
		if (strncmp(old, str, AUTHOR_LENGTH - 1) == 0) {
			xv_set(ip->articles_list,
                                 PANEL_LIST_SELECT, row, TRUE, NULL);
                        retrieve_article(ip, art);
                        return 1;
                }
	next ? row++:row--;
        }
	if (next) {
		Global->article = next_unread_art(ip);
		retrieve_article(ip, Global->article);
        	xvnews_err(ip, "No author matches found, went to next unread article\n");
		return -1;
	}
	xvnews_err(ip, "Searching archives for previous author...\n");
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	if (Global->nnrp)
		art = nnrp_get_sub_prev(ip, "from", old);
	else
		art = get_sub_prev(ip, "from", old);
	if (art == -1) {
		xvnews_err(ip, "No matches found!\n");
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
		return -1;
	}
	xv_set(ip->articles_list, PANEL_LIST_SELECT, 0, TRUE, NULL);
	retrieve_article(ip, xv_get(ip->articles_list, PANEL_LIST_CLIENT_DATA,
		NULL));
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
	return 1;
}

extern int exp_search(srp, next)
xvnews_search_popup_objects	*srp;
int next;
{
	xvnews_xvnews_window_objects *ip = (xvnews_xvnews_window_objects *) xv_get(xv_get(srp->search_popup, XV_OWNER, NULL), XV_KEY_DATA, INSTANCE, NULL);
	int	first, last, match = -1, row, status;
	char	*exp, *str, *old, *err = NULL, *artlast, *c;
	char	command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN];
	
	exp = (char *)xv_get(srp->search_text, PANEL_VALUE, NULL);
	str = (char *)xv_get(srp->header_text, PANEL_VALUE, NULL);

	old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING,
		xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL), NULL);
	sscanf(old, "%d", &first);

	if (next) {
		artlast = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, 
			xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL) - 1,
				 NULL);
		sscanf(artlast, "%d", &last);
		sprintf(command, "XHDR %s %d-%d", str, first + 1, last);
	} else
		sprintf(command, "XHDR %s 0-%d", str, first - 1);
	err = xvnews_comp(exp);
	if (err != NULL) {
		xv_set(srp->search_popup, FRAME_LEFT_FOOTER, err, NULL);
		xvnews_err(ip, "Expression error: %s!\n", err);
		return -1;
	}
	xv_set(srp->search_popup, FRAME_LEFT_FOOTER, "Searching...\n", NULL);
	xvnews_err(ip, "Searching...\n");
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	xv_set(srp->search_popup, FRAME_BUSY, TRUE, NULL);
	if (!strcmp(str, "article text") || !strcmp(str,"entire header")) 
		match = body_search(next, old, str);
	else {
		put_server("%s", command);
		status = get_server(message,sizeof(message));
		if (status != OK_HEAD) {
			reconnect_server();
			put_server("%s", command);
			status = get_server(message,sizeof(message));
			if (status != OK_HEAD) 
				return -1;
		}
		while(*message != '.') {
			get_server(message,sizeof(message));
			c = message;
			while(isdigit(*c++));
			if (xvnews_exec(c)) {
				if (next && match == -1) 
					sscanf(message, "%d", &match);
				if (!next)
					sscanf(message, "%d", &match);
			}
		}
	}
	if (match == -1) {
		xvnews_err(ip, "No matches found for \"%s\"!\n", exp);
		xv_set(srp->search_popup, FRAME_LEFT_FOOTER, "No matches.\n",
			 NULL);
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
		xv_set(srp->search_popup, FRAME_BUSY, FALSE, NULL);
		return -1;
	}
	row = get_prev(ip, match);
	xv_set(ip->articles_list, PANEL_LIST_SELECT, row, TRUE, NULL);
	retrieve_article(ip, match);
	if (!strcmp(str, "article text")) {
		Textsw_index text_first = 0, text_last = TEXTSW_INFINITY;

		if (textsw_find_exp(ip->article_window, exp,
				    &text_first, &text_last) != -1) {
		  textsw_normalize_view(ip->article_window, text_first - 5);
		  textsw_set_selection(ip->article_window,
				       text_first, text_last, 1);
		}
	}
	xv_set(srp->search_popup, FRAME_BUSY, FALSE, NULL);
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
	xv_set(srp->search_popup, FRAME_LEFT_FOOTER, "\n", NULL);
	return 1;
}

extern void kill_subject(ip, flg)
xvnews_xvnews_window_objects	*ip;
int flg;
{
  char	*str;
  char	old[SUBJECT_LENGTH + 1], undelete[SUBJECT_LENGTH + AUTHOR_LENGTH + 2];
  int 	num = 0, new = 0, artnum = 0;
  int	nrows = xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL);
  int	row = xv_get(ip->articles_list,PANEL_LIST_FIRST_SELECTED, NULL);
  xvnews_undelete_popup_objects *up = (xvnews_undelete_popup_objects *)
    xv_get(ip->xvnews_window, XV_KEY_DATA, UNDELETE_POPUP, NULL);

  str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);
	
  memset(old, '\0', SUBJECT_LENGTH);

  if (!flg) {
    /* Read past the article number */
    while (isdigit(*str)) {
      ++str;
      ++num;
    }
    
    /* Read past the spaces between the article number
       and the subject */
    while (*str == ' ') {
      ++str;
      ++num;
    }	
	
    if (strncasecmp(str, "re:", 3))
      strncpy(old, str, SUBJECT_LENGTH - num);
    else {
      str += 4;
      strncpy(old, str, SUBJECT_LENGTH - (num + 4));
    }
  } else {
    str += SUBJECT_LENGTH + 1;
    strncpy(old, str, AUTHOR_LENGTH - 1);
  }

  str = old + strlen(old) - 1;
  while (*str == ' ') {
    --str;
  }
  ++str;
  *str = '\0';
		
  num = 0;
  xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
  xv_set(ip->articles_list, XV_SHOW, FALSE, NULL);
  xv_set(up->undelete_list, XV_SHOW, FALSE, NULL);
  while(--nrows >= 0) {
    str = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, nrows, NULL);
    if (strstr(str, old) != NULL) {
      sscanf(str, "%d", &artnum);
      strncpy(undelete, str, SUBJECT_LENGTH + AUTHOR_LENGTH);
      undelete[SUBJECT_LENGTH + AUTHOR_LENGTH] = '\0';
      xv_set(up->undelete_list,
	     PANEL_LIST_INSERT, new,
	     PANEL_LIST_STRING, new, undelete,
	     NULL);
      if ((char *)xv_get(up->undelete_list, PANEL_LIST_STRING, new, NULL)
	  == NULL)
	xv_set(up->undelete_list, PANEL_LIST_DELETE, new, NULL);
      else
	new++;
      ++num;
      add_articles(Global->group, artnum, artnum);
      if (!isRead(str)) {
	Global->unread--;
      }
      xv_set(ip->articles_list,PANEL_LIST_DELETE, nrows,NULL);
    }
  }
  Global->unread++;
  xv_set(up->undelete_list, XV_SHOW, TRUE, NULL);
	
  if (num) {
    xv_set(up->controls3, WIN_FONT, Global->listfont, NULL);
    xv_set(up->undelete_list, PANEL_LIST_FONTS, Global->listfont, NULL, NULL);
  }
  if (!xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL)) {
    if (Global->mode == ARTICLE_MODE)
      update_newsrc(ip, 1);
    groups_set(ip);
    xvnews_err(ip, "All articles killed\n");
    return;
  }
  xv_set(ip->articles_list, XV_SHOW, TRUE, NULL);
  xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
  Global->article = next_unread_art(ip);
  retrieve_article(ip, Global->article);
  xvnews_err(ip, "%d %s killed matching \"%s\"\n", num,
	     num > 1 ? "articles":"article", old);
}

STATIC int body_search(next, old, str)
int	next;
char	*old, *str;
{
	char article[MAX_ARTICLE_LEN], search[16];
	int	art, artorig, match = -1, last, response;
	struct	newsrc_node	*curr = NULL;

	sscanf(old, "%d", &artorig);

	curr = Global->group;
	
	if (next) {
		art = artorig + 1;
		last = curr->last_article + 1;
	} else {
		last = curr->last_article - curr->articles - 1;
		art = artorig - 1;
	}

	if (!strcmp(str, "article text"))
		strcpy(search, "BODY");
	else
		strcpy(search, "HEAD");

	while(match == -1) {
		put_server("%s %d", search, art);
		response = get_server(article, sizeof(article));
		if (response > 229)  {
			if (response == ERR_FAULT)
				reconnect_server();
			if ((next && art >= last) || (!next && art <= last))
				break;
			next ? art++:art--;
			continue;
		}
		for (;;) {
			get_server(article, sizeof(article));
			if (article[0] == '.' && article[1] == '\0')
                        	break;
			if (xvnews_exec(article))
				match = art;
		}
		next ? art++:art--;
		if (art == last)
			break;
	}
	return match;
}

extern int next_unread_art(ip)
xvnews_xvnews_window_objects	*ip;
{
	int	nrows = xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL);
	int	row = 0, art;
	char	*old;

	for (row = 0; row < nrows; row++) {
		old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row,
			NULL);
		sscanf(old, "%d", &art);
		if (art == Global->article)
			break;
	}
	/* If the article is not found at all, reset row */
	if (row == nrows) {
	  row = 0;
	}
	old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, 
		xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL), NULL);
	sscanf(old, "%d", &art);
	for (; row < nrows; row++) {
		old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row,
			NULL);
		if ((int)strlen(old) < SUBJECT_LENGTH + AUTHOR_LENGTH + 5) {
		  sscanf(old, "%d", &art);
		  xv_set(ip->articles_list, PANEL_LIST_SELECT, row, TRUE,
			   NULL);
		  return art;
		}
	}
	xv_set(ip->articles_list, PANEL_LIST_SELECT,
	       xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL), 
	       TRUE, NULL);
	return art;
}

extern int undeleteKill(ip, prp, str, num)
xvnews_xvnews_window_objects	*ip;
xvnews_props_objects *prp;
char	*str;
int num;
{
	int	art, i = 0, rows = xv_get(ip->articles_list,PANEL_LIST_NROWS,NULL);
	char	*old;

	if (!xv_get(prp->sort, PANEL_TOGGLE_VALUE, 0)) {
		for (; i<rows; i++) {
			old = (char *)xv_get(ip->articles_list,PANEL_LIST_STRING,i);
			sscanf(old, "%d", &art);
			if (art == num)
				return i;
			if (num < art) 
				break;
		}
	}
	xv_set(ip->articles_list, PANEL_LIST_INSERT, i,
			PANEL_LIST_STRING, i, str,
			PANEL_LIST_FONT, i, Global->listfont,
			NULL);
	Global->unread++;

	return i;
}


STATIC int nnrp_get_sub_prev(ip, comm, str)
xvnews_xvnews_window_objects    *ip;
char	*comm;
char	*str;
{
	int 	last = -1, art, num = 0, status;
	char	*old, *c;
	char	string[50], message[MAX_MESSAGE_LEN];

	old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, 
		xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL)
			, NULL);
	sscanf(old, "%d", &art);
	memset(string, '\0', 49);
	num = strlen(str) - 1;
	while (str[num] == ' ' || str[num] == '*')
		num--;
	while (*str == '*' || *str == ' ') {
		str++;
		num--;
	}
	strncpy(string, str, num+1);
	c = string;
	while (*c++ != '\0')
		if (*c == ' ')
			*c = '?';
	put_server("XPAT %s 0-%d *%s*\n", comm, --art, string);
	status = get_server(message, sizeof(message));
	if (status != OK_HEAD) {
		reconnect_server();
		put_server("XPAT %s 0-%d *%s*\n", comm, --art, string);
		status = get_server(message, sizeof(message));
		if (status != OK_HEAD) 
			return -1;
	}
	while (*message != '.') {
		get_server(message, sizeof(message));
		if (message[0] != '.')
			sscanf(message, "%d", &last);
	}
	if (last != -1)
		return get_prev(ip, last);

	return -1;
}

extern int isRead(str)
char *str;
{
	if (!strncmp(&str[strlen(str) - 6], "[read]", 6) ||
		  !strncmp(&str[strlen(str) - 6], "[save]", 6) ||
		    !strncmp(&str[strlen(str) - 7], "[print]", 7) ||
		       !strncmp(&str[strlen(str) - 6], "[filt]", 6))
		return 1;
	
	return 0;
}