[comp.sources.amiga] v90i164: NewsView 2.32 - amiga usenet news reader, Part03/06

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (05/07/90)

Submitted-by: Richard Frost <rfrost@spam.ua.OZ.AU>
Posting-number: Volume 90, Issue 164
Archive-name: applications/nv-2.32/part03

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 6)."
# Contents:  Display.c NewsViewer/NV.pw.uu Select.c
# Wrapped by tadguy@xanth on Sun May  6 18:08:55 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Display.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Display.c'\"
else
echo shar: Extracting \"'Display.c'\" \(18075 characters\)
sed "s/^X//" >'Display.c' <<'END_OF_FILE'
X/* ======================================================================= */
X/*                                                                         */
X/* PROGRAM:                         News View                              */
X/*                                                                         */
X/* VERSION:      2.32                                                      */
X/*                                                                         */
X/*                                                                         */
X/* FILENAME:     Display.c                                                 */
X/*                                                                         */
X/* DESCRIPTION:  This module is a collection of routines that deal with    */
X/*               updating the display.                                     */
X/*									   */
X/* AUTHOR:       Copyright 1990   Richard Frost                                    */
X/*                                                                         */
X/* DATE:         22nd April 1990                                           */
X/*                                                                         */
X/* ======================================================================= */
X
X
X#include "Defs.h"
X#include "Globals.h"
X#include "ShutDown.h"
X#include "DefViewer.h"
X#include "WindData.h"
X#include "Gadgets.h"
X#include "Select.h"
X
X
X#define WINDOW_TITLE "News View:  Version 2.32  By Richard Frost and Robert Wozniak"
X#define SCREEN_TITLE "News View:  Yet another product from 4.00 AM Hacks Inc."
X
X
X/* Remove the line below to enable jump scrolling which involves
X   the clearing of the entire screen when a new screen of text is
X   displayed rather than clearing a line at a time and redrawing
X   text on top of it.
X*/
X
X#define NO_JUMP
X
XSHORT  Reg_LEFT,
X       Reg_TOP,
X       Reg_RIGHT,
X       Reg_BOTTOM,
X 
X       Text_LEFT,
X
X       Wind_Rows,
X       Wind_Cols,
X       Wind_FirstItem,    /* # of first Item in window */
X   
X       ArrowOffset=0,	  /* Y offset in pixels from the top of a character pos
X			     where to start to draw the selector */
X
X       ItemsDisplayed=0,
X       MaxFirstItem=0;    /* This is the Wind_FirstItem of the LAST allowable
X			    window. It is the maximum value that Wind_FirstItem
X			    can have.
X  			   */
X
XUBYTE  SubjColour=1,
X       SizeColour=0,
X       BgndColour=2;	
X
XUWORD  Text_Xsize,
X       Text_Ysize,
X       Text_Baseline;
X
Xstruct RastPort *Rp;
X
Xextern struct Window *OpenWindow();
Xextern BOOL          GetScreenData();
X
X
X       /* Useful macros: 1) ROW(n) obtains y pixel coord of bottom of row n,
X			 2) COL(n) obtains x pixel coord of right of col n
X        */
X
X#define TEXT_OFFSET 1
X
X#define ROW(n) (Reg_TOP   + TEXT_OFFSET + (n)*Text_Ysize)
X#define COL(n) (Text_LEFT + (n)*Text_Xsize)
X
X
X
X/* ======================================================================= */
X/*                                  DrawArrow                              */
X/* ======================================================================= */
X/* Draw the arrow next to the current news item.                           */
X
XPUBLIC VOID DrawArrow()
X{
X  DrawBorder(Rp,&Arrow,Reg_LEFT+2,Reg_TOP+(CurrentItem-Wind_FirstItem)*Text_Ysize+ArrowOffset);
X}
X
X
XPUBLIC VOID EraseArrow()
X{
X  DrawBorder(Rp,&BlankArrow,Reg_LEFT+2,Reg_TOP+(CurrentItem-Wind_FirstItem)*Text_Ysize+ArrowOffset);
X}
X
X
X/* ======================================================================= */
X/*                                 SetGlobalVars                           */
X/* ======================================================================= */
X
X/* Initialize all global variables, these are values that rarely change */
X
XPUBLIC VOID SetGlobalVars()
X{
X  Rp = NV_Window->RPort;
X
X  Text_Xsize    = Rp->Font->tf_XSize;
X  Text_Ysize    = Rp->Font->tf_YSize;
X  Text_Baseline = Rp->Font->tf_Baseline;
X
X
X       /* These values below are always relative to the upper left corner
X          of the window, and will not change with change in window size */
X
X  Text_LEFT = NV_Window->BorderLeft+Text_Xsize+4;
X  Reg_LEFT  = NV_Window->BorderLeft-2;
X  Reg_TOP   = NV_Window->BorderTop-1;
X
X  Wind_FirstItem = 0;
X 
X  ArrowOffset = (Text_Ysize-7)/2;
X
X  if (ArrowOffset <0)
X     ArrowOffset = -ArrowOffset;
X}
X
X
X/* ======================================================================== */
X/*                                SetWindowVars                             */
X/* ======================================================================== */
X
XPUBLIC VOID SetWindowVars()
X{
X  register SHORT wid1,wid2,hgt;
X  static   SHORT prev_windrows=10000;  /* The previous number of rows 
X					 of text in the window */ 
X
X  wid1 = NV_Window->Width  - NV_Window->BorderRight  - Reg_LEFT;
X  wid2 = NV_Window->Width  - NV_Window->BorderRight  - Text_LEFT;
X
X  hgt = NV_Window->Height -  NV_Window->BorderBottom - NV_Window->BorderTop;
X  
X  Reg_RIGHT  = Reg_LEFT + wid1 - 1;  /* Calculate the max X coord of the region */
X  Reg_BOTTOM = Reg_TOP  + hgt;  /* Calculate the max Y coord of region */
X
X  Wind_Cols = wid2 / Text_Xsize;
X  Wind_Rows = (hgt-TEXT_OFFSET)  / Text_Ysize;
X
X  /* Here we will ADJUST the variable "Wind_FirstItem" so that when a user
X     resizes the window from SMALL to LARGE, the larger window will have the
X     extra text row-space FILLED WITH TEXT (ie. there will be NO GAPS).
X
X     OR, "Wind_FirstItem" will be set to zero as the window must be large enough
X     to see ALL the available news items!!
X
X     The static variable "prev_windrows" stores the previous window size 
X     (# rows of text).
X
X     The algorithm is: 
X
X  	If (Wind_Rows > prev_windrows)
X	  {
X	    addedrows = Wind_Rows-prev_windrows
X	    Wind_FirstItem -= addedrows     scroll the text down
X	    if (Wind_FirstItem < 0)        not enough text to scroll
X	       Wind_FirstItem == 0
X	  }
X
X	prev_windrows = Wind_Rows
X
X  */		
X
X  if (Wind_Rows > prev_windrows)      /* Window is BIGGER than BEFORE! */
X    {
X      Wind_FirstItem -= (Wind_Rows-prev_windrows);
X      if (Wind_FirstItem < 0)  Wind_FirstItem = 0;
X    }
X
X  prev_windrows = Wind_Rows;
X
X  if (NumItems > Wind_Rows)
X    MaxFirstItem  = NumItems - Wind_Rows;
X  else
X    MaxFirstItem  = 0;
X   
X  SetDrMd(Rp,JAM2);
X
X}
X
X
X/* ======================================================================== */
X/*                                 MakeWindow                               */
X/* ======================================================================== */
XPUBLIC VOID MakeWindow()
X{
X
X  register SHORT deltaX,deltaY,
X		 deltaWid,deltaHgt;
X
X  register struct Window *w;
X
X  struct Screen WBscrn;
X  BOOL   gotdata;
X
X  
X  /* Find out the Screen Width & Height of the Workbench screen! */
X  /* EVERYONE SHOULD OPEN WINDOWS LIKE THIS!!!!!!!!!!!!!!!!!!!!  */
X
X  if (gotdata=GetScreenData(&WBscrn,sizeof(struct Screen),WBENCHSCREEN,NULL))
X    {
X      NewWindowStructure1.TopEdge  = WBscrn.TopEdge + WBscrn.BarHeight+2;
X      NewWindowStructure1.LeftEdge = WBscrn.LeftEdge;
X      NewWindowStructure1.Width    = WBscrn.Width;
X      NewWindowStructure1.Height   = WBscrn.Height  - WBscrn.BarHeight-2;
X    }
X  
X  if ( (NV_Window = OpenWindow(&NewWindowStructure1)) == NULL)
X    ShutDown("Could not open the window!",FALSE);
X
X  /* Set up the Menus! */
X
X  SetMenuStrip(NV_Window,&MenuList1);
X  
X  if (gotdata == FALSE)		 /* Resize to full size! */
X    {
X      w = NV_Window;
X  
X      deltaX   = w->WScreen->LeftEdge - w->LeftEdge;
X      deltaY   = w->WScreen->TopEdge  - w->TopEdge + 12; 
X      deltaHgt = w->WScreen->Height   - w->Height  - 12;
X      deltaWid = w->WScreen->Width    - w->Width;
X 
X      MoveWindow(w,deltaX,deltaY);
X      SizeWindow(w,deltaWid,deltaHgt);
X   }
X
X  /* THE DEFINES FOR THESE 2 STRING ARGUMENTS BELOW ARE AT THE TOP 
X     OF THIS SOURCE FILE
X   */
X
X  SetWindowTitles(NV_Window,WINDOW_TITLE,SCREEN_TITLE);
X
X}
X
X/* ======================================================================== */
X/*                                 ClearWindow                              */
X/* ======================================================================== */
X
XPUBLIC VOID ClearWindow()     /* Completely erase ALL characters in the current window */ 
X{
X  SetAPen(Rp,BgndColour);
X  RectFill(Rp,Reg_LEFT,Reg_TOP,Reg_RIGHT,Reg_BOTTOM);
X}
X
X/* ======================================================================== */
X/*                                 ClearRow                                 */
X/* ======================================================================== */
X
XPUBLIC VOID ClearRow(row)     /* Erase ALL characters in a row */
XSHORT row;
X{
X  register SHORT tmp = Reg_TOP+TEXT_OFFSET+row*Text_Ysize;
X
X  SetAPen(Rp,BgndColour);
X  RectFill(Rp,Reg_LEFT,tmp,Reg_RIGHT,tmp+Text_Ysize-1);
X}
X
X
X/* ======================================================================== */
X/*                               ClearFirstRow                              */
X/* ======================================================================== */
X
XPUBLIC VOID ClearFirstRow()     /* Erase ALL characters in the 1st row */
X{
X  register SHORT tmp = Reg_TOP+TEXT_OFFSET;
X
X  SetAPen(Rp,BgndColour);
X  RectFill(Rp,Reg_LEFT,tmp,Reg_RIGHT,tmp+Text_Ysize-1);
X}
X
X/* ======================================================================== */
X/*                               ClearLastRow                               */
X/* ======================================================================== */
X
XPUBLIC VOID ClearLastRow()     /* Erase ALL characters in the LAST row */
X{
X  register SHORT tmp = Reg_TOP+TEXT_OFFSET+Wind_Rows*Text_Ysize-1;
X
X  SetAPen(Rp,BgndColour);
X  RectFill(Rp,Reg_LEFT,tmp,Reg_RIGHT,tmp+Text_Ysize-1);
X}
X
X/* ======================================================================== */
X/*                                  DrawItem                                */
X/* ======================================================================== */
X
X/* This routine will display data corresponding to a news item pointed to by
X   "iptr". The types of data displayed is controlled by the global variables
X   "ShowNames" and "ShowSizes". The Subject string is always displayed but 
X   is rendered in a colour dependent on whether the item has been read or not,
X   this is determined using by the "Status" feild of the ITEM structure.
X*/
X
XPUBLIC DrawItem(iptr)
XITEM *iptr;
X{
X  char Buffer[8];
X  register USHORT len,
X	          colsleft;             /* Number of window cols left
X			                   in which to display text */
X#define LOTS_OF_SPACES  "                                                                                             "
X
X
X  SetBPen(Rp,BgndColour);                        /* Black Bgnd */
X  colsleft = Wind_Cols;
X
X  /* I KNOW Intuition clips Text() calls for you but
X     I WANT TO KNOW WHEN IT DOES SO for speedier window redraws ! */
X
X  if (ShowSizes)
X    {
X      SetAPen(Rp,SizeColour);		/* Blue Fgnd */
X
X/*    sprintf(Buffer,"%5d ",iptr->FileBytes);
X      len = strlen(Buffer);
X*/
X
X      len = iptr->fsize_len;
X
X      if (len < colsleft)		/* See if we had to clip text */
X	{
X	  Text(Rp,iptr->Filesize,len);
X	  colsleft -= len;		/* less space now to print in */
X	}
X      else
X	{
X	  Text(Rp,iptr->Filesize,colsleft);   /* We did, thus JUMP OUT here! */
X	  return;			      /* NO MORE text can be displayed */
X	}
X	
X    }
X
X
X  SetAPen(Rp,SubjColour);		/* White Fgnd */
X
X  if (ShowNames)		/* Print the filename of the newsitem?? */
X    {		
X/*    sprintf(Buffer,"%4s: ",iptr->Filename);
X      len = strlen(Buffer);
X*/
X      len = iptr->fname_len;
X
X      if (len < colsleft)
X	{
X	  Text(Rp,iptr->PrintedFilename,len);
X	  colsleft -= len;
X	}
X      else
X	{
X	  Text(Rp,iptr->PrintedFilename,colsleft);
X	  return;
X	}
X    }
X
X 			/* Print the SUBJECT TITLE ALWAYS!  */
X  	          /* Change pen colour to ORANGE if item is READ */
X
X		  /* NOTE: CHANGE THIS LATER ON, make a choice of this
X		     colour intelligent! (ie != Bgnd col or Subj Col!!
X		  */
X
X		
X  if (iptr->Status == READ)
X    SetAPen(Rp,(UBYTE) 3);        /* Orange Fgnd */
X
X/* len = strlen(iptr->Subject); */
X			
X  len = iptr->fsubj_len;
X
X  if (len < colsleft)
X    {
X      Text(Rp,iptr->Subject,len);
X      colsleft -= len;
X    }
X  else
X    {
X      Text(Rp,iptr->Subject,colsleft);        /* not enough space for whole string */
X      return;				      /* BAIL OUT!! */
X    }
X 
X#ifdef NO_JUMP    
X  /* Fill rest of the space in with spaces, NO MORE FLASHY FLASHY redraws! */
X  Text(Rp,LOTS_OF_SPACES,colsleft);
X#endif
X
X}
X 
X
X/* ======================================================================== */
X/*                                RedrawWindow                              */
X/* ======================================================================== */
X
X/* Redraw each menu item & clip if neccesary */
X
XPUBLIC VOID RedrawWindow()
X{
X
X  register SHORT i,ypos,
X                 last_item;      /* The number of the LAST item displayed */
X		
X  /* ---------------------------------*/
X  /* VARIABLE INPUT:  Wind_FirstItem  */
X  /* ---------------------------------*/
X
X  /* This routine attempts to draw from item "Wind_FirstItem", which is the
X     number of the news item corresponding to the FIRST DISPLAYED ITEM at the 
X     top of the window, to the last item that is DISPLAYABLE.
X
X     An item cannot be displayed if:
X
X         The item does not exist. This is when "Wind_FirstItem+Wind_Rows-1" is an 
X         index value to the array "ItemList" (size NumItems) being larger than the
X         array's size.
X         NOTE: "NumItems-1" is the index of the LAST item in the array "ItemList".
X   */
X
X
X                  
X  /* See if we can draw Wind_rows rows of text */
X
X  last_item  = Wind_FirstItem + Wind_Rows-1;
X
X  if (last_item > NumItems-1)     /* If there is not enough text left to do so ..*/
X    last_item = NumItems-1;       /* then stop with the last item in "ItemList"  */
X	
X
X  /* Ypos of the FIRST DISPLAYED item */
X  ypos = Reg_TOP + TEXT_OFFSET + Text_Baseline; 
X  
X  ItemsDisplayed=0;
X
X#ifndef NO_JUMP
X  ClearWindow();
X#endif
X
X  for(i= Wind_FirstItem; i <= last_item ;i++)
X    {
X       Move(Rp,Text_LEFT,ypos);          /* Start text up against LEFT side of window */
X
X       DrawItem(ItemList[i]);
X
X       ItemsDisplayed++;
X       ypos += Text_Ysize;               /* Advance to next row */
X    }
X
X}
X
X/* ======================================================================== */
X/*                                 SyncDisplay                              */
X/* ======================================================================== */
X/* Call CentreOnItem() only if the current item is not visible.		    */
X
XPUBLIC VOID SyncDisplay()
X{
X  register SHORT last_item;
X
X
X	/* calculate the last item displayed & see if Current item
X	   is still visble. */
X
X  last_item  = Wind_FirstItem + Wind_Rows-1; 
X  if (last_item > NumItems-1)    
X    last_item = NumItems-1;      
X 
X  if (CurrentItem >= Wind_FirstItem && CurrentItem <= last_item)
X    { 	
X      RedrawWindow();	/* Current item is still visible ! */
X    }
X  else
X    {
X      CentreOnItem(CurrentItem);
X    }
X}
X
X
X/* ======================================================================== */
X/*                                  RedrawRow                               */
X/* ======================================================================== */
X
X/* Redraw a given row (0=firstrow) and show its State accordingly as 
X   either READ or UNREAD */
X
X/* WARNING: NO CLIPPING is applied to this routine so make sure that there IS
X            an item on row "row"!!!!!
X*/
X
XPUBLIC VOID RedrawRow(row)
XSHORT row;
X{
X   SetAPen(Rp,SubjColour);
X   SetBPen(Rp,BgndColour);
X   SetDrMd(Rp,JAM2);
X
X   /* get into position! */
X   Move(Rp,Text_LEFT,TEXT_OFFSET+Reg_TOP+Text_Baseline+row*Text_Ysize); 
X   DrawItem(ItemList[Wind_FirstItem+row]);
X}  
X
X
X/* ======================================================================== */
X/*                                  ScrollDown                              */
X/* ======================================================================== */
X/* Scroll the window DOWN 1 row */
X
XPUBLIC VOID ScrollDown(setpos)
XSHORT setpos;
X{
X  VOID SetKnobPos();
X  register SHORT last_item;
X
X  if (Wind_FirstItem < MaxFirstItem)
X    {
X      Wind_FirstItem++;
X      /* SCROLL THE BITMAP UP BY ONE TEXT ROW */
X      /* This leaves a gap in the LAST row that must be filled IF possible */
X	
X      ScrollRaster(Rp,0,Text_Ysize,Text_LEFT,Reg_TOP+TEXT_OFFSET,Reg_RIGHT,ROW(Wind_Rows)-1);
X
X      last_item  = Wind_FirstItem + Wind_Rows-1;
X
X      if (last_item <= NumItems-1)     /* If there is an item in the last row */
X        RedrawRow(Wind_Rows-1);        /* then draw it.*/
X      else
X	ItemsDisplayed--;              /* else 1 less item was displayed */
X
X      if (setpos == UPDATESLIDER)
X	SetKnobPos();
X
X    }
X 
X}
X
X/* ======================================================================== */
X/*                                  ScrollUp                                */
X/* ======================================================================== */
X/* Scroll the window UP 1 row */
X
XPUBLIC VOID ScrollUp(setpos)
XSHORT setpos;
X{
X  VOID SetKnobPos();
X  register SHORT last_item;   /* The item # for item that occurs on the LAST row */
X
X  if (Wind_FirstItem > 0)
X    {
X      Wind_FirstItem--;
X
X      /* Scroll the BITMAP DOWN 1 ROW */
X      ScrollRaster(Rp,0,-Text_Ysize,Text_LEFT,Reg_TOP+TEXT_OFFSET,Reg_RIGHT,ROW(Wind_Rows)-1);
X
X      RedrawRow(0);        /* FIll the gap left in the first row with text */
X			   /* WE CAN ALWAYS DO THIS */
X      last_item  = Wind_FirstItem + Wind_Rows-1;
X
X      if (last_item > NumItems-1)      /* If no item exists on last row */
X	ItemsDisplayed++;              /* then 1 more has been displayed */
X
X      if (setpos == UPDATESLIDER)
X	SetKnobPos();
X
X    }
X}
X
X
X/* ======================================================================== */
X/*                                  UnreadAll                               */
X/* ======================================================================== */
X/* Unread ALL items!! */
X
XPUBLIC VOID UnreadAll()
X{
X   register SHORT i;
X
X   for (i=0 ; i < NumItems; i++)
X      ItemList[i]->Status = UNREAD;
X
X   RedrawWindow();
X}  
END_OF_FILE
if test 18075 -ne `wc -c <'Display.c'`; then
    echo shar: \"'Display.c'\" unpacked with wrong size!
fi
# end of 'Display.c'
fi
if test -f 'NewsViewer/NV.pw.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'NewsViewer/NV.pw.uu'\"
else
echo shar: Extracting \"'NewsViewer/NV.pw.uu'\" \(10239 characters\)
sed "s/^X//" >'NewsViewer/NV.pw.uu' <<'END_OF_FILE'
Xbegin 666 NV.pw
XM4&]W97)7:6YD;W=S('8R+C4@+"`@:6UP;W)T960@8GD@455!4E1%6"!C<F%C1
XM:RUT96-H;F]L;V=I97,@,3DX."`@("`@("`@("`@```#]`````D@`0#_````6
XM`0`````!``````YD9C$Z3E9'861S,BYH```````````!``(0+P`$$WH`9``ZA
XM_____P`C=.`````````````````````````````*`/A*`````````0```0``!
XM`#T">P!?``4`!?____\````^3F5W<R!6:65W.B`@5F5R<VEO;B`R+C-A("!"K
XM>2!2:6-H87)D($9R;W-T(&%N9"!2;V)E<G0@5V]Z;FEA:P``(R#8``+_]``VN
XM``P`#@"#``$`^&I@`/AR2````````````````````"!R,/____\#```%`",@;
XMO````````````#<````W``T````-````````````-@`,``(``<2X`P``````(
XM````P/________P`________\`#_SY___\_P`/QGG___S_``_/.?SSWS\`#_%
XM^9QGD,/P`/_MG\9CS_``_^>>$[3)\`#_YZ?C&/'P`/_'Q@8QP_``_X\/____O
XM\`"`````````````````````````````#``\/W___[_\`#N>?___/_P`/XY\)
XM/O(/_``_AGN<;S_\`#^2>#^?/_P`/YAY[TLW_``_G%P<YX_\`#^^/_____P`:
XM/'_______`!________\````````-@`,``(``>[``P``````````P/______:
XM__P`````````#``"@(```$`,``Q"BJJJ2JP`!"$511E17``*T(PBD(*L``4IP
XM%41!15P`"L**$I2(K``%)2:@B%%<``K#0@(@@JP`!H4%55557``?_______\P
XM````````````________\`#]?W___[_P`/N_?___O_``_][^OO:O\`#_KWO=L
XM;W_P`/_6^K^_O_``_[U][VMW\`#_WMU?=Z_P`/^^O_____``_7______\`#@T
XM``````````````@`"`"#`/AI2`#X:P@`^'!``/AX4`#X=+@`^(5P````"4YE<
XM>'1)=&5M``````$``````0`````*3F5X=%])=&5M``````$``````0``(R(0K
XM`#C_]``V``P`#@"#``$`(9,H`"&4$````````````````````"&7:/____\#_
XM```%`",A%````````````#<````W``T````-````````````-@`,``(``>^(A
XM`P``````````P/________P`________\`#__Y_____P`/Q@S_____``^.?,P
XMY\\Y\`#_YYT$9SSP`/__#C_!D/``_^`\?A*C\`#_Y_S[X\?P`/_G\/P'#_``2
XM_X?_____\```````````````````````````````#``\`'_____\`#N?/___)
XM__P`/Y\S'#SW_``_GV+[F./\`#^`\?@^;_P`/Y_S^>]?_``_G_/\'S_\`#^?S
XM______P`/W_______`#________\````````-@`,``(``?!0`P``````````L
XMP/________P`````````#``"JH`````,``0@155555P`",*(HHHHK``%)94$3
XM10A<``K5"BJ`D*P`!2`45!"A7``*PJBJHD*L``4E4%0%!5P`"H*JJJJJK``?S
XM_______\````````````________\`#]57_____P`/O?O_____``_[]W77WWK
XM\`#_WVK[NO?P`/^J]?U_;_``_]_[^^]?\`#_O_?]7[_P`/_?______``_W__F
XM____\`#@``````````````@`"`"#`"!98`#XBQ``(%I8`"!;L``@<8``('Z0(
XM````"5!R979)=&5M``````$``````0`````*4')E=E])=&5M``````$`````-
XM`0``(R1P`'C_]`!```P`#@"#``$`(9F0`"+!*````````````````````"+!Y
XM>/____\#```%`",B3````````````$$```!!``T````-`````/_V````6``,"
XM``(``A2@`P`````````!(/______________`/_/_________\_\`/_/__Y_M
XM__^?_\_\`/_/\8,___X?_\_\`/_/XY\_/,YYS\_\`/_/_YXQG69YS\_\`/_/Z
XM__Q_#F99S\_\`/_/_[#X3$<ZS\_\`/_/_YGOCXXLS\_\`/_/_XR0'!APS\_\<
XM`/_/_A,?_/__C\_\```````````````````````````````````P````````"
XM`#`#`#_S\`'___Q___/_`#_S[GS___G___/_`#_S_GSP\SGG/_/_`#_S_GWN^
XM8IG'/_/_`#_S_@/@\9GF/_/_`#_S_D_GL[CE/_/_`#_S_F?P<'GS/_/_`#_S4
XM_G-_\___/_/_`#_S_?S_\__X?_/_`/______________```"````0``,``(`<
XM`A7(`P``````````P/__________``````````,`JJ```!```P40(5550557'
XM"BB2HHBC!*L%46$)4D:85PJJ@U"D(12K!5$$A$10J%<*J(JHJ*+$JP50B0%!`
XM!0A7"J$@JHJJJ*L?_________P``````````__________S_55___^___/[OU
XMW___O__\__?O7W?>^_S_[][VK;UW_/_U?J];WNO\_^[_>[NO5_S_]W]75]\[H
XM_/_O=_^___?\_]_?_W__U_S@``````````````@`"`"#`"&=H``A2+@`(9%@B
XM`"+#H``ADM@`(K*(````"DYE>'1297!L>0`````!``````$`````"TYE>'1?L
XM4F5P;'D``````0`````!```C)/``QO_T`#L`#``.`(,``0`BT#@`(O]`````B
XM````````````````(R3(_____P,```4`(R2L````````````/````#P`#0``+
XM``T````````````[``P``@`"&Q@#``````````#`_________^#_________@
XM@/__\Y___S^`_XP#'___/X#_G/^<Y^?/@/_\_YT&$P^`__\_GCW#/X#_S#_,Y
XM?#,C@/_,_XS_X\.`__C_&/X'#X#_\?______@```````````````````````:
XM````````8#^`#G___O_@/W/____\_^`_\_YS'!@_X#_S_&+Y[/_@/\#^<?X\$
XM_^`_L_XS^\S?X#_S_G/\'C_@/_?______^`_#_______X/_________@````W
XM```[``P``@`"&^`#``````````#`_________^``````````8`!54(```(!@'
XM!8@!%556%6`*A*L(HJ5*X`585I4$$@5@"I4K&BE!*N`%2!2$5"(A8`J$JPBJ7
XMHT+@!5A5$%0%!6`*H*JJJJJJX!_________@``````````#_________@/^J\
XMKW___W^`_W?____]_X#_^_[W75J_@/_W_6K[[?^`_^K^]?Z^_X#_M_][^]W?!
XM@/_[_O?]7K^`__?______X#_7_______@.``````````````"``(`(,`(L9XF
XM`"++Z``BT.@`(O]@`"+3(``BV7`````*1FER<W1)=&5M``````$``````0``3
XM```+1FER<W1?271E;0`````!``````$``",IX`$!__0`-@`,``X`@P`!`",/J
XMB``C)4@````````````````````C)6C_____`P``!0`C)2P````````````WW
XM````-P`-````#0```````````#8`#``"``(<J`,``````````,#________\4
XM`/________``__/____/\`#_P____\_P`/_/__/Y\_``_\_^,X3#\`#_S_YSG
XM<,_P`/_/_KD,R?``_X_G$?CQ\`#_\\8S@</P`/\/C_____``````````````!
XM``````````````````P`/X____^__``_/____S_\`#\__@\&#_P`/S_]SGL_G
XM_``_/_F/CS_\`#\_^4;S-_P`/W_<[P>/_``^#[_____\`#_P?_____P`____S
XM_____````````#8`#``"``(=<`,``````````,#________\``````````P`1
XM`%````!`#``%@555545<``I*JJ*I4JP`!855((2!7``*2JI24$JL``6%5*D(.
XMB5P`"@JA$*C0K``%4401`4%<``H*BJJJJJP`'________````````````/__S
XM______``_Z____^_\`#_?____[_P`/^__U]6K_``_W_^WWM_\`#_O_VOK[_P.
XM`/]_^U;W=_``___>[U>O\`#^K[_____P`/_U?_____``X``````````````(/
XM``@`@P`C)9``(N=0`",B:``C):@`(R7``",ET`````E,87-T271E;0`````!F
XM``````$`````"DQA<W1?271E;0`````!``````$``",OB`$W__0`H``,``\`/
XM@P`!`",J.``````````````````````````C*EC_____`P``!0`C*AP`````;
XM``````"A````H0`-````#0```````````*``#``"``(>.`,``````````>#_%
XM___________________________/_______________________Q_\___\__U
XM_S__/G/___________'_S_X8#___/_\_(________S__\?_/_GG_//?/^9XSA
XM\\_G\\Y_/__Q_\__^?&>0P_YS',9S_,9T'\___'_S__Y_QF//__,\_%DX_'C?
XM_S__\?_/__GX3M,G_^CYA.M'A,?_/\/Q_\__^G^,8\?_\?'X\8_XS_\\/_'_-
XMS__\>!C'#__SXX'C'X&/_P/_\?_/_^#______^/_________/__Q````````]
XM``````````````````$````````````````````````````P````````````Q
XM```````````./_/^`#___O_\_<________\___X_\_WG___\__CX________P
XM_\/__C_S_^?P^\@_]GW/#S_?#S'_^#_^/_/_Y^YQO/__.X[F/X[F+___@_X_L
XM\__GX/Y\__\[S@^;W@\?___X?C_S_^?GO2S?_Y?&>]2^>S_____^/_/_Y?!S"
XMGC__S\\'SG\'/_____X_\__#_______/_____________C_S____________K
XM___________^__________________________X````(``L`@``C)>``(RL@*
XM`",K,``C*T``(RM0`",K8`````$``````0`````!``````$``````0`````!>
XM```C,.C_ZO_I`!4`"P`>`!,``0`C*W``(R_@````````````````````(S!0Q
XM_____P,```4`(R_$````````````%@```!8`#`````P````````````5``L`^
XM`@``&,`#``````````!8___P`/__X`#_\^``__/@`/_^(`#__&``__C@`/_QD
XMX`#_X^``_^?@`.````````@`#__X``^?^``/G_@`"/_X``Q_^``./_@`#Q_X/
XM``^?^``/W_@`'__X````````%0`+``(``<6``P``````````6,``"`#"JK@`1
XMQ5%8`,*BN`#%5!@`PJ@X`,506`#"H+@`Q4%8`,*BN`#/__@`/__P`#__X``_O
XMO^``/]_@`#K_X``]?^``/K_@`#]?X``_O^``/]_@`#`````````(`!@`$P`C/
XM,'@`(S"0`",PH``C,+``(S#(`",PV`````M$;W=N0G5T=&]N``````$`````G
XM`0`````,1$]73E]"55143TX``````0`````!```C6YC_ZO_>`!4`"P`>`!,`O
XM`0`C,4``(SE0````````````````````(T=0_____P,```4`(S$D````````W
XM````%@```!8`#`````P````````````5``L``@`"("`#``````````!8___PQ
XM`/_GX`#_X^``__'@`/_XX`#__&``__X@`/_SX`#_\^``___@`.````````@`1
XM#]_X``^?^``/'_@`#C_X``Q_^``(__@`#Y_X``^?^``/__@`'__X````````A
XM%0`+``(``C`H`P``````````6,``"`#%15@`PJ*X`,516`#"J+@`Q518`,*J*
XM.`#%45@`PJ*X`,556`#/__@`/__P`#__X``_W^``/[_@`#]_X``^_^``/?_@Y
XM`#^_X``_W^``/__@`#`````````(`!@`$P`C1W@`(S%@`"-1<``C48``(UMX!
XM`"-;B`````E5<$)U='1O;@`````!``````$`````"E507T)55%1/3@`````!]
XM``````$``"-JF/_J``H`%O_3`%``$P`#`"-;\``````````````````C7!``D
XM```C7##_____`P``!0`C6]0````````````7````%P`S````,P``````````9
XM``X`+@`````````````````````!!?__``#_____````"@!0`!L`(VHH`"-JS
XM0``C:E``(VI@`"-J>``C:H@````+5F5R=%-L:61E<@`````!``````$`````U
XM#%9%4E1?4TQ)1$52``````$``````0```````=G_]?YF``H`*`*#``0`(VK$O
XM`````````````````"-T&````"-T2/____\#```%`"-JU````````````.(`5
XM``#B``L````+```````````````41&5F875L=``@("`@("`@("`@(``````*[
XM`"@"@P`C='``(W2(`"-TF``C=*@`(W3``"-TT`````I3=')I;F='860`````,
XM`0`````!``````M3=')I;F=?1V%D``````$``````0``(W4``P```````%``<
XM"@`C=1``(W78````"%!R;VIE8W0``"-UN``C=<@`40`C=3``````$```````:
XM``````4``@,`!``!``$```!0``H```````````````51=6ET``````$``"-UK
XM^`,``%````!0``H`(W80`".+H`````E3971T:6YG<P``(W98`"-V>````"-V1
XM,``C=H@0```C=[@`````!0`"`P`$``$``0```*``"@``````````````%$-LP
XM:6-K(%-E;&5C="`@("`@(+L``````0``(W;0`"-VX#0Q`"-VJ``C=O`````"&
XM!0(#`0`6``$`D?_[`',`"@``````````````!U-I;F=L90`````!```C=Q``^
XM(W<@/#(`(W>0``````````$%`@,!`!8``0"1``4`<P`*```````````````'/
XM1&]U8FQE``````$``"-X```C>"`````C=]@`(W@P,```(WXX``````4``@,`"
XM!``!``$`#P"@``H``````````````!13=6)J96-T("`@($-O;&]U<B"[````R
XM``$``"-X>``C?/`D```C>%``(WT`````#@4!````%``!`)'_\0!.``H`````4
XM``````````@@("`@("`@``````$``"-]2``C?5@L```C?2``(WUH````#04!0
XM`0$`%``!`)'_^P!.``H```````````````@@("`@("`@``````$``"-]L``C6
XM?<`D```C?8@`(WW0````"P4!`@(`%``!`)$`!0!.``H```````````````@@Y
XM("`@("`@``````$``"-^&``C?B@D```C??``````````!P4!`P,`%``!`)$`P
XM#P!.``H```````````````@@("`@("`@``````$``"-^@``C?J`````C?E@`K
XM(WZP$```(X!0``````4``@,`!``!``$`&0"@``H``````````````!1)=&5M*
XM(%-I>F4@($-O;&]U<B"[``````$``"-^^``C?P@L```C?M``(W\8````#@4!Y
XM````%``!`)'_\0!.``H```````````````@@("`@("`@``````$``"-_8``C\
XM?W`D```C?S@`(W^`````#04!`0$`%``!`)'_^P!.``H```````````````@@$
XM("`@("`@``````$``"-_R``C?]@D```C?Z``(W_H````"P4!`@(`%``!`)$`0
XM!0!.``H```````````````@@("`@("`@``````$``".`,``C@$`D```C@`@`+
XM````````!P4!`P,`%``!`)$`#P!.``H```````````````@@("`@("`@````(
XM``$``".`F``C@+@````C@'``(X#($```(X)H``````4``@,`!``!``$`(P"@%
XM``H``````````````!1"86-K9W)O=6YD($-O;&]U<B"[``````$``".!$``CE
XM@2`D```C@.@`(X$P````!@4!````%``!`)'_\0!.``H```````````````@@&
XM("`@("`@``````$``".!>``C@8@D```C@5``(X&8````#04!`0$`%``!`)'_7
XM^P!.``H```````````````@@("`@("`@``````$``".!X``C@?`L```C@;@`<
XM(X(`````"P4!`@(`%``!`)$`!0!.``H```````````````@@("`@("`@````E
XM``$``"."2``C@E@D```C@B``````````!P4!`P,`%``!`)$`#P!.``H`````T
XM``````````@@("`@("`@``````$``"."L``CBK`````C@H@`(XK`$```````%
XM``````4``@,`!``!``$`,@"@``H``````````````!1396%R8V@@:7,@8V%SI
XM92`N+B"[``````$``".+"``CBR`T10`CBN``(XLP`````@4"`P$`%@`!`)'_9
XM^P"6``H```````````````I396YS:71I=F4``````0``(XMX`".+D#Q)`".+W
XM4``````````!!0(#`0`6``$`D0`%`)8`"@``````````````#$EN<V5N<VET"
XM:79E``````$``".+P`,``*D```!7````(XO8`"/1``````M.97=S($ET96USZ
XM```C'#``(ODH````(XOX`"//2!```"/0&`````$%`@,!``0``0`!````KP`*X
XM```````````````64VAO=R!.97=S($ET96T@+BX@(""[``````$``"//D``C@
XMSZ`03@`CSV@`(\^P`````04"`P$`!``!`(G_^P!:``H```````````````9.5
XM86UE<P`````!```CS_@`(]`($%,`(\_0``````````(%`@,!``0``0")``4`1
XM6@`*```````````````&4VEZ97,``````0``(O\H`",<"!!&`"/0.``````0:
XM```CT(@`````!0(#`0`$``$``0`*`*\`"@``````````````#E-T<FEN9R!3'
XM96%R8V@``````0``(OJH`"+Y.!!5`"/0J``````0````````````!0(#`0`$Z
XM``$``0`>`*\`"@``````````````$55N<F5A9"!!3$P@271E;7,``````0``E
XM(]$@`P`!$0```&<````CT3@`(]&H````#4AI<W1O<GD@1FEL90``(]&``"/1?
XMF!```"/16``````0````````````!0(#`0`$``$``0```'H`"@``````````9
XM````#U5P9&%T92!(:7-T;W)Y``````$``"/1R`,``8D````O````(]'8````)
XM``````9!8F]U=```(](@`"/2.````"/1^``````0````````````!0(#`0`$.
XK``$``0```(P`"@``````````````$$%B;W5T($YE=W,@5FEE=P`````!```$@
X``
Xend
Xsize 7288
END_OF_FILE
if test 10239 -ne `wc -c <'NewsViewer/NV.pw.uu'`; then
    echo shar: \"'NewsViewer/NV.pw.uu'\" unpacked with wrong size!
fi
# end of 'NewsViewer/NV.pw.uu'
fi
if test -f 'Select.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Select.c'\"
else
echo shar: Extracting \"'Select.c'\" \(15072 characters\)
sed "s/^X//" >'Select.c' <<'END_OF_FILE'
X/* ======================================================================= */
X/*                                                                         */
X/* PROGRAM:                         News View                              */
X/*                                                                         */
X/* VERSION:      2.3a                                                      */
X/*                                                                         */
X/*                                                                         */
X/* FILENAME:     Select.c                                                  */
X/*                                                                         */
X/* DESCRIPTION:  This module is a collection of routines that handle       */
X/*               the selection of items in the window uisng the mouse.     */
X/*                                                                         */
X/* AUTHOR:       Copyright 1990   Richard Frost                                    */
X/*                                                                         */
X/* DATE:         22nd April 1990                                           */
X/*                                                                         */
X/* ======================================================================= */
X#include "Defs.h"	
X#include "Globals.h"
X#include "Winddata.h"
X#include "Request.h"
X#include "Display.h"
X
X	/* Variables to keep track of what the current item is */
X
XSHORT CurrentRow   = 0,   /* # of Current Row the arrow is on */
X      PreviousRow  = 0,
X      CurrentItem  = 0,
X      PreviousItem = 0;   
X
X			/* REPLY VARIABLES */
X#define WORD_LEN 30
XSHORT NumKeywords=0;
XUBYTE keyword[3][WORD_LEN+1];  /* 3 keywords thanks! */
X
X
X/* ======================================================================= */
X/*                                  GoReadItem                             */
X/* ======================================================================= */
X
X/* Execute the TEXT READER and give it the filename */
X
XPUBLIC VOID GoReadItem(item)
XSHORT item;
X{
X  VOID   RedrawRow();
X
X   if (StringGadSInfo.Buffer[0] != '\0')
X     {
X       if (strcmp(StringGadSInfo.Buffer,"Default") == 0)
X	 {
X            if (ViewNewsItem(ItemList[item]->Filename,ItemList[item]->Subject) == TRUE)
X	      {
X   	        ItemList[item]->Status = READ;
X		RedrawRow(item-Wind_FirstItem);
X	      }
X	    else
X	        ErrorMsg("Couldn't use the Default Viewer on that item!");
X	 }
X       else
X	 if (ExternalReadItem(item,StringGadSInfo.Buffer) == FALSE)
X	   {
X	     ErrorMsg("Couldn't use YOUR text viewer, so I'll try mine!");
X             if (ViewNewsItem(ItemList[item]->Filename,ItemList[item]->Subject) == TRUE)
X	       {
X   	         ItemList[item]->Status = READ;
X		 RedrawRow(item-Wind_FirstItem);
X	       }
X	     else
X	       ErrorMsg("Couldn't use my Default Viewer either!");
X	   }
X	 else
X	   {  
X             ItemList[item]->Status = READ;
X             RedrawRow(item-Wind_FirstItem);
X	   }
X     }
X}
X
X
X/* ======================================================================= */
X/*                                  SelectMouse                            */
X/* ======================================================================= */
X
XPUBLIC VOID SelectMouse(CurrentRow,CurrentSecs,CurrentMicros)
XSHORT CurrentRow;
XLONG  CurrentSecs,CurrentMicros;
X{
X  static LONG  StartSecs,
X               StartMicros;
X  static SHORT StartRow,
X               ClickNum=1;
X
X  SHORT ChosenItem;
X
X  BOOL   DoubleClick();
X  VOID   SetCurrentItem();
X
X
X  if (ClickSelect == 1)               /* If a selection is ONE mouse click ... */
X    {
X      ClickNum   = 1;
X      ChosenItem = Wind_FirstItem+CurrentRow;
X      EraseArrow();
X      SetCurrentItem(ChosenItem);
X      DrawArrow();
X      GoReadItem(ChosenItem);
X    }
X  else
X    {
X      if (ClickNum == 1)                       /* first click */
X        {
X          ClickNum++;                         /* Keep track of clicks */
X          StartSecs   = CurrentSecs;          /* Store "DoubleClick" params */
X          StartMicros = CurrentMicros;
X          StartRow    = CurrentRow;
X        }
X      else
X        {
X          if (CurrentRow == StartRow)
X	    {
X	       /* Okay, we hit on the SAME row as before, lets
X 	         check if the double click was OK!
X	       */
X
X 	       if (DoubleClick(StartSecs,StartMicros,CurrentSecs,CurrentMicros))
X                 {
X                    ChosenItem = Wind_FirstItem+CurrentRow;
X		    EraseArrow();
X		    SetCurrentItem(ChosenItem);
X		    DrawArrow();
X                    GoReadItem(ChosenItem);
X	         }
X	       else
X	         ClickNum = 1; 	/* double click no good, start again! */
X            }
X          else
X	    {
X 	       /* User moved rows on the second click!!, arrgh!
X		   Make this NEW row as the FIRST row clicked on.
X	        */     
X
X               StartSecs =   CurrentSecs;     /* Store "DoubleClick" params */
X               StartMicros = CurrentMicros;
X               StartRow =    CurrentRow;
X               ClickNum = 2;                  /* Reset click counter */
X	    }
X        }
X    }
X}
X
X
X/* ======================================================================== */
X/*                                 TouchedItem                              */
X/* ======================================================================== */
XPUBLIC BOOL TouchedItem(selrow)
XSHORT *selrow;
X{
X   *selrow = (NV_Window->MouseY - Reg_TOP)/Text_Ysize;
X
X   /* Test to see if an item is
X        1: within window row limits 
X        2: the one the mouse pointer touched
X    */
X
X   if (*selrow < Wind_Rows)
X     {
X       if ((Wind_FirstItem + *selrow) < NumItems)   
X         return TRUE;
X     }
X
X   return FALSE;	
X}
X
X
X/* ======================================================================== */
X/*                                SetCurrentItem                            */
X/* ======================================================================== */
X/* Make item x the current item, this routine will save the previous 
X   current item so PrevItem will work. This is also used when the
X   MOUSE selects an item.
X*/
X
XPUBLIC VOID SetCurrentItem(x)
XSHORT x;
X{
X   PreviousItem = CurrentItem;
X   CurrentItem  = x;
X
X   PreviousRow  = CurrentRow;
X   CurrentRow   = x-Wind_FirstItem;
X}
X
X
X/* ======================================================================== */
X/*                                   GetPrevItem                            */
X/* ======================================================================== */
X/* Return the item that was JUST READ */
X
XPUBLIC SHORT GetPrevItem()
X{
X  return PreviousItem;
X}
X
X
X/* ======================================================================== */
X/*                                   GetNextItem                            */
X/* ======================================================================== */
X/* Return the next item to read THAT IS UNREAD <= make this an option? */
X
XPUBLIC SHORT GetNextItem()
X{
X  /* Search for the next ITEM with status UNREAD */
X  register SHORT i,cnt;
X
X  i = CurrentItem;
X  cnt = 0;
X
X  while (cnt <= NumItems)
X    {
X      if (ItemList[i]->Status == UNREAD)
X        return i;
X
X      cnt++;
X      i++;
X      i %= NumItems;    /* Allow Wrap around! */
X
X    }
X
X  DisplayBeep(NULL);	/* NO MORE ITEMS TO READ !!!! */
X  return i;
X}
X
X
X
X/* ======================================================================== */
X/*									    */
X/*                                Reply Functions                           */
X/*									    */
X/* ======================================================================== */
X
X/* This routine will search for the next WORD in the string STR
X   and will return a pointer to where the search ended so that
X   NextWord() could be called again with the return pointer
X   as the new STR argument to find the next word.
X
X   NextWord() returns 0 when NO word is found.
X 
X   The found word is stored in the char array "WORD".
X
X   NOTE: Ensure the WORD array is defined as  WORD[WORD_LEN+1] AT LEAST!
X
X   NOTE: NEXT WORD WILL REJECT the WORD "re:" "RE:" etc.
X*/
X
X
X/* ======================================================================== */
X/*                                   NextWord                               */
X/* ======================================================================== */
X
XPRIVATE UBYTE *NextWord(str,word)   /* Retreive the NEXT word (skip white space) */
XUBYTE *str;
XUBYTE *word;
X{
X
X  register UBYTE  *ch = str;
X  register UBYTE  *cp = word;
X  register SHORT   len = 0;
X  register UBYTE   R,E;
X  register SHORT   WordNotFound=1;
X
X
X  while (WordNotFound)
X    {
X      WordNotFound = 0;
X
X      /* SKIP COLONS skip whitespace: TABS & SPACES */
X      while (*ch && (*ch == ' ' || *ch == '\t')) 
X        ch++;
X
X      /* Copy the word over !  STOP AT SPACES, TABS AND 
X         ":" <= used to trap Re:'s as 'Re:hhshsh' becomes 'Re' and 'hshsh'
X      */
X
X      while (*ch && *ch != ' ' && *ch != '\t')  
X        { 
X          if (*ch == ':')			/* check for a RE: */
X            {
X	      if (len >=2 )		        /* enough room to back up ?*/
X	        {
X	          R = tolower(*(ch-2));     /* get 2 chars before the colon */
X                  E = tolower(*(ch-1));
X
X	          if (R == 'r' && E =='e')  /* are they a RE? */
X		    {
X		      len = 0;		    /* if so, reset the found word */
X		      cp  = word;
X		      ch++;	            /* Advance over the colon char */
X		      WordNotFound = 1;	    /* We want another word! */
X		      continue;		    /* BACK to the while loop! */
X		    }
X	    	}
X	    }
X
X          if (len < WORD_LEN)
X            {
X              *cp++ = *ch++;
X              len++;
X            }
X          else
X            {
X	      ch++;
X#ifdef LOUD
X	      printf("\nNo keyword space left!\n");
X#endif
X	    }
X        }
X    };
X
X  if (len == 0)         /* Did NOT copy a word into the buffer! */
X    return 0;           /* return ABORT code! */
X  else
X    {
X      *cp = '\0';   /* NULL terminate the copied word */ 
X      return ch;    /* return where we got up to */
X    }
X
X}
X
X
X/* =================================================================== */
X/* This routine will set the Array of 3 strings to the keywords found
X   in the current line and will return the NUMBER of keywords found.
X*/
X
XPRIVATE SHORT GetSearchStrings(line)
XUBYTE *line;
X{
X  UBYTE *NextWord();
X
X  register UBYTE  *pos=line,*kywd;
X  register SHORT numfound=0;
X
X  while (*pos && numfound < 3)
X    { 
X      kywd = keyword[numfound];  /* get start addr of keyword str */
X
X      if (pos = NextWord(pos,kywd))
X        numfound++; /* If Got a word .. */
X      else break;	
X    }
X
X  return numfound;
X}
X
X/* =================================================================== */
X/* Do the first chars of the string STR contain the key? */
X 
XPRIVATE BOOL SubStr(k,str)
XUBYTE *k,*str;
X{
X   register UBYTE *ch=str;
X   register UBYTE *key=k;
X
X   while (*key && *ch)	  /* Step both arrays for each successful match */
X     if (tolower(*key) == tolower(*ch))
X      {
X#ifdef VLOUD
X	printf("KEY = [%c] STR = [%c]\n",tolower(*key),tolower(*ch));
X#endif
X        key++; ch++;
X      }
X     else
X        break;		  /* Failed match!, stop stepping */
X
X   if (*key)   /* All of key matched? */
X     return FALSE;
X   else        /* Yes, we are pointing to the NULL of the keyword! */
X     return TRUE;
X}
X
X/* =================================================================== */
X/* Is the STRING STR a reply with respect to the 3 keyword search 
X   strings? 
X
X   A return of TRUE occurs ONLY when the 3 search keywords are
X   matched IN ORDER with no bad matches in between.
X
X   If a BAD match occurs then the search continues with the search
X   keyword reset to the FIRST search keyword.
X 
X*/
X
XUBYTE word[WORD_LEN+1];
X
XPRIVATE BOOL IsReply(str)
XUBYTE *str;
X{
X  UBYTE *NextWord();
X
X  register UBYTE  *pos=str,*kywd;
X  register SHORT kwdmatches=0;
X
X#ifdef LOUD
X  printf("\nANALYSING LINE[%s]\n",str);
X#endif
X
X  while (*pos   &&   kwdmatches != NumKeywords)
X    { 
X      if (pos = NextWord(pos,word))         /* If Got a word .. */
X	{
X
X#ifdef LOUD
X	  printf("Got the word [%s]\n",word);
X#endif
X	  if (SubStr(keyword[kwdmatches],word))   /* a match ?! */
X	    {
X
X#ifdef LOUD
X 	      printf("Matched keyword [%s]!\n",keyword[kwdmatches]);
X#endif
X	      kwdmatches++;
X	    }
X	  else
X	    kwdmatches = 0;  /* No, reset to FIRST search token */
X	}
X      else break;
X    }
X
X  if (kwdmatches == NumKeywords)
X    return TRUE;
X  else
X    return FALSE;
X}
X
X
X/* ======================================================================== */
X/*                                   GetNextReply                           */
X/* ======================================================================== */
X/* Return the next item to read that is a reply to the current Item. 	    */
X
XPUBLIC SHORT GetNextReply()
X{
X  /* Search for the next ITEM that has the same inital 3 keywords of the
X     "Subject:" field of the CURRENT ITEM.
X   */
X
X  BOOL  IsReply();
X  SHORT GetSearchStrings();
X
X  register SHORT i,    /* Current item to be searched */	
X		 cnt;  /* Number of items searched thru */
X
X#ifdef LOUD
X  int j;
X#endif
X
X
X
X  i = CurrentItem;
X  cnt = 0;
X
X  if (NumItems > 1)	/* Cant have a reply if 1 item only!! */
X    {
X
X#ifdef LOUD  
X      printf("Current Item = %d\n",i);
X      printf("NumItems = %d\n",NumItems);
X#endif
X
X      /* Get all the keywords to search! */
X      NumKeywords = GetSearchStrings(ItemList[i++]->Subject);
X
X#ifdef LOUD  
X      for(j=0; j < NumKeywords; j++)
X        printf("Search Keyword %d is [%s]\n",j,keyword[j]);
X#endif
X
X
X      while (cnt < NumItems-1)
X        {
X	  i %= NumItems;	/* Allow Wrap around! */
X
X          if (IsReply(ItemList[i]->Subject))
X          return i;
X          i++;
X          cnt++;
X        }
X    }
X
X  DisplayBeep(NULL);	/* NO MORE ITEMS TO READ !!!! */
X  return i;
X}
X
X/* ======================================================================== */
X/*                                 CentreOnItem                             */
X/* ======================================================================== */
X/* Centre the screen about item x ... used in NEXT & PREV calculations.*/
X
XPUBLIC VOID CentreOnItem(x)
XSHORT x;
X{
X  register SHORT CentreRow=0;
X
X  if (x < Wind_FirstItem) 	/* We want to jump UP to item x */ 
X    {
X	if (Wind_Rows % 2) CentreRow = Wind_Rows/2;
X	else CentreRow = Wind_Rows/2 - 1;
X
X	if (x >= CentreRow)
X	  {
X	     Wind_FirstItem = x - CentreRow;
X	  }
X	else
X	  {
X	     Wind_FirstItem = 0;
X	  }	     
X
X        SetCurrentItem(x);
X        RedrawWindow();
X	SetKnobPos();
X    }
X  else				/* We want to jump DOWN to item x */	
X    if (x > (Wind_FirstItem+Wind_Rows -1))
X      {
X	 if (Wind_Rows % 2) CentreRow = Wind_Rows/2;
X         else CentreRow = Wind_Rows/2 - 1;
X
X         if (x < (NumItems - CentreRow))    /* <= Equiv. to (x <= (NI-CR-1) ) */
X           {
X	      Wind_FirstItem = x - CentreRow;
X	   }
X	 else
X	   {
X	      Wind_FirstItem = MaxFirstItem;
X	   }	     
X
X         SetCurrentItem(x);
X	 RedrawWindow();
X	 SetKnobPos();
X      }
X  else	/* The item is displayed in the window!, so lets move to it */
X    {
X       SetCurrentItem(x);
X    }
X}
END_OF_FILE
if test 15072 -ne `wc -c <'Select.c'`; then
    echo shar: \"'Select.c'\" unpacked with wrong size!
fi
# end of 'Select.c'
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.