$! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 6-JAN-1991 11:23:41.46 By user MURPHY $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 25 PARTS, TO KEEP EACH PART $! BELOW 99 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. ALT-MAILER-2.;1 $! 2. ALT-MAILER.;1 $! 3. ANU-NEWS.PATCHES;1 $! 4. AVL.C;1 $! 5. AVL.H;1 $! 6. BIGICON.XBM;1 $! 7. BUTTONS.C;1 $! 8. BUTTONS.H;1 $! 9. CALVIN.ICON;1 $! 10. CHANGES.;1 $! 11. CLIENTLIB.C;1 $! 12. CODES.H;1 $! 13. COMPOSE.C;1 $! 14. COMPOSE.H;1 $! 15. CONFIG.H;1 $! 16. COPYRIGHT.;1 $! 17. COPYRIGHT.H;1 $! 18. CURSOR.C;1 $! 19. CURSOR.H;1 $! 20. DIALOGS.C;1 $! 21. DIALOGS.H;1 $! 22. DXRN.XBM;1 $! 23. ERROR_HNDS.C;1 $! 24. ERROR_HNDS.H;1 $! 25. FIXERS.;1 $! 26. HOBBES1.ICON;1 $! 27. HOBBES2.ICON;1 $! 28. IMAKEFILE.;1 $! 29. INTERNALS.C;1 $! 30. INTERNALS.H;1 $! 31. LIST.C;1 $! 32. LIST.H;1 $! 33. MAKE-DXRN.COM;1 $! 34. MAKE-MXRN.COM;1 $! 35. MAKEFILE.;1 $! 36. MAKEFILE.DECNET;1 $! 37. MAKEFILE.MOTIF;1 $! 38. MENUS.C;1 $! 39. MESG.C;1 $! 40. MESG.H;1 $! 41. MODES.H;1 $! 42. MXRN.XBM;1 $! 43. NEWS.H;1 $! 44. NEWSRC.L;1 $! 45. NEWSRC.Y;1 $! 46. NEWSRCFILE.C;1 $! 47. NEWSRCFILE.H;1 $! 48. NEWSRC_PARSE.C;1 $! 49. NEWSRC_PARSE.H;1 $! 50. ORIGMAKEFILE.;1 $! 51. PANE.C;1 $! 52. PANE.H;1 $! 53. PANEP.H;1 $! 54. PRINTER.;1 $! 55. README.;1 $! 56. RESOURCES.C;1 $! 57. RESOURCES.H;1 $! 58. REVERSE-VIDEO.;1 $! 59. SAVE.C;1 $! 60. SAVE.H;1 $! 61. SERVER.C;1 $! 62. SERVER.H;1 $! 63. SLIST.C;1 $! 64. SLIST.H;1 $! 65. SLISTP.H;1 $! 66. SMALLICON.XBM;1 $! 67. T.H;1 $! 68. T6.C;1 $! 69. T7.C;1 $! 70. TODO.;1 $! 71. UTILS.C;1 $! 72. UTILS.H;1 $! 73. XMISC.C;1 $! 74. XMISC.H;1 $! 75. XRN.C;1 $! 76. XRN.DOC;1 $! 77. XRN.H;1 $! 78. XRN.ICON;1 $! 79. XTHELPER.C;1 $! 80. XTHELPER.H;1 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' XReturn-Path: evans@decvax.dec.com XReceived: from eros.Berkeley.EDU by shambhala.Berkeley.EDU (5.61/1.28) X`09id AA19881; Tue, 2 Jan 90 06:22:28 -0800 XReceived: by eros.berkeley.edu (5.57/1.28) X`09id AA17513; Tue, 2 Jan 90 06:22:31 PST XReceived: by decvax.dec.com (5.57/v2.4) X`09id AA00453; Fri, 29 Dec 89 11:49:27 -0500 XReceived: by flume.zk3.dec.com (5.57/dv.5.yp) X`09id AA16031; Fri, 29 Dec 89 11:52:27 EST XReceived: by testmax.local (5.57/Ultrix3.0-C) X`09id AA09559; Fri, 29 Dec 89 11:49:13 EST XMessage-Id: <8912291649.AA09559@testmax.local> XTo: xrn@eros.berkeley.edu XSubject: GRIPE about XRN 6.4 (for X11R3) XDate: Fri, 29 Dec 89 11:49:09 EST XFrom: evans@decvax.dec.com X XEnclosed you will find a shell script that I wrote to be used in conjunction Xwith xrn. It addresses the same problem that the #ifdef NO_SENDMAIL does, bu Vt Xin a more generic manner (in my opinion anyway). It allows xrn to be compile Vd Xwithout defining NO_SENDMAIL, and then each user can change the mailer using Xthe xrn.Mailer resource. I find it is quite useful for people that use xmh, Xmhmail, or the DECwindows dxmail programs, but where the system wide mailer Xneeds to default to /usr/lib/sendmail. X XThis script is as of now in the Public Domain, and therefore you can do as y Vou Xwish with it. X X- Marc Evans X========================================================================== XMarc Evans - WB1GRH - evans@decvax.DEC.COM `7C Synergytics (603)893-8481 X Unix/X-window Software Contractor `7C 3 Koper Ln, Pelham, NH 03076 X========================================================================== X----------8<----------8<----------CUT HERE----------8<----------8<---------- X#!/bin/sh X# X# This shell script is designed to read mail from either standard input or X# from 1 or more files supplied as arguments, and send the contents to the X# program mh/send (/usr/new/mh/send on ULTRIX). If no arguments are specifie Vd X# then standard input is read. Otherwise, the arguments are assumed to be X# valid pathnames of files to be individually sent. X# X# This script is primarily useful in conjunction with programs which send X# mail via standard output, and the user typically use the mhmail facilities X# for sending mail (this includes DECwindows /usr/bin/dxmail program). An X# example program would be xrn, which is an X windows based netnews reader. X# Xset -x Xmhmail=$`7BMAILER-/usr/new/mh/send`7D Xmdir="" Xargv="$*" Xif `5B $# = 0 `5D ; then argv="-" ; fi X# Xc="`60grep '`5EPath:' $HOME/.mh_profile `7C sed 's/`5EPath:`5B `09`5D*//'`60 V" Xif `5B "$c" != "" `5D ; then X dirs="$HOME/$c $c $HOME/Mail /usr/tmp" Xelse X dirs="$HOME/Mail /usr/tmp" Xfi Xfor i in $dirs ; do X if `5B -d $i -a -w $i `5D ; then X`09mdir=$i X`09break X fi Xdone X# Xif `5B ! -d "$mdir" -a -w "$mdir" `5D ; then X echo "Can't determine directory in which to create draft message. Aborti Vng" X exit 1 Xfi Xif `5B ! -f "`60echo $mhmail `7C sed 's/`5B `09`5D.*//'`60" `5D ; then X echo "Program '$mhmail' is not available. Aborting" X exit 1 Xfi X# Xumask 077 Xfor i in $argv ; do X cat $i >$mdir/draft.$$ && $mhmail $mdir/draft.$$ Xdone $ CALL UNPACK ALT-MAILER-2.;1 1377839137 $ create 'f' XReturn-Path: tengi@Princeton.EDU XReceived: from Princeton.EDU by shambhala.Berkeley.EDU (5.61/1.28) X`09id AA18073; Fri, 10 Nov 89 08:45:47 -0800 XReceived: from idunno.Princeton.EDU by Princeton.EDU (5.58+++/2.25/mailrelay V) X`09id AA17524; Fri, 10 Nov 89 11:42:07 EST XReceived: from localhost by idunno.Princeton.EDU (5.61/1.92) X`09id AA01989; Fri, 10 Nov 89 11:43:41 -0500 XMessage-Id: <8911101643.AA01989@idunno.Princeton.EDU> XTo: Rick L. Spickelmier XCc: tengi@Princeton.EDU XSubject: Re: XRN and mail aliases`20 XIn-Reply-To: Your message of Wed, 27 Sep 89 09:44:37 -0700. X <8909271644.AA06010@shambhala.Berkeley.EDU>`20 XDate: Fri, 10 Nov 89 11:43:39 -0500 XFrom: tengi@Princeton.EDU X XRick, X I tried your solution to my aliases problem (as I use mh here) and Xit worked just fine. Since I have my mh profile set up to use my Xaliases file automatically, I didn't need to pass the shell script an Xargument. Bottom line is this in my X resources: X Xxrn.mailer: /u/tengi/bin/xrn-mh-mailer X Xand this in /u/tengi/bin/xrn-mh-mailer: X X#! /bin/csh Xcat > /tmp/mail.$`7BUSER`7D.$$ Xsend /tmp/mail.$`7BUSER`7D.$$ Xexit 0 X X XNaturally, you need to be sure that /tmp/#* files geventually get Xremoved (we do it nightly with cron) since send renames file to #file Xon completion. Thanks for the idea. It works great here! X X`09`09`09`09`09`09/Chris X X $ CALL UNPACK ALT-MAILER.;1 1901793229 $ create 'f' XI've gotten dxrn working on VMS (5.3) using ANU News v6.0 release 3 beta as V the XNNTP server. At the end of this message are the patches needed to do this. T Vhe Xversion of dxrn I used was the last one I saw you announce to comp.os.vms an Vd/or Xvmsnet.sources.d. What I had to do was: X X Define GENERATE_EXTRA_FIELDS. X X Added a new definition to config.h for the name of an environment X variable containing the timezone (TIMEZONE_ENV). It might not patch X cleanly, because I didn't save the original config.h (before I'd X customized it locally) so the patch is against a previous customized X version. That did, however, keep it from generating changes for my X local configuration. X X Change compose.c to check whether gmtime returns NULL. If so, use X localtime and append the timezone string contained in the environment X variable (i.e. logical name) named by TIMEZONE_ENV. An appropriate X value for a DECUS UUCP site is UUCP_TIME_ZONE. Believe it or not, ANU X News just puts in the local time and labels it GMT! This change is not X ifdef'd for VMS, because ANSI C allows gmtime to return NULL. The X return value of gmtime is checked at run time. X X Change compose.c to put in the message-id and date in the CANCEL X control message. Also not ifdef'd to VMS, since it was obviously an X oversight. X XThere are several comments/observations I'd like to make: X X First and foremost, I love it! I use it exclusively for reading news X now. Even with the network overhead of using a server, it is a much X better news reader than ANU News. I run dxrn and the server on the same X machine. I only run a server at all to be able to use dxrn. Thanks! X X Due to a bug in the ANU News NNTP server, most posts or follow-ups X fail. The server aborts. Being the news manager here, I just feed X dead.letter into ANU News. This is NOT a dxrn problem, it is an ANU X News problem. Nevertheless, it should probably be mentioned to anyone X wanting to use dxrn with ANU News. I may try to fix ANU News, but that X is no small undertaking. X X Contrary to the documentation, setting the geometry in the resource X file DOES work. However, if you save the customization using the menu X in dxrn, it gets the geometry wrong. I do believe that the window size X in the geometry string is a little wrong. I'm on a VS3100 (1024x832), X yet to get it to work properly, I have to give it numbers as though my X screen were 860 in the y direction. My dxrn window is the left half of X the screen, from the bottom of the icon box to the bottom of the X string, and I use the geometry string 511x769+512+91, even though it X should by 511x741+512+91. X X Several customization items (maybe most) are NOT saved when you try to X save your settings from the customization menu. They simply aren't X changed in the resource file. These include at least all the directory X settings. As a result of these 2 items, we just edit the resource file X here and NEVER save our settings with the customize menu. I'm glad the X documentation gives a lot of info in this respect. X X Contrary to the documentation, there appear to be NO default key X bindings. I found the rn.bindings file, and built my own set based on X them, but there are none by default that I could determine. Some of my X bindings haven't worked (particularly, none in all or add modes), but I X haven't yet completely determined that this is not my fault. X X When you move the cursor to the double line between sub-windows in the X dxrn or composeTop windows, you get the double triangle cursor, but it X won't let you drag the boundary and thus resize your subwindows. X X I learned a LOT about editting resource files! In particular, I X couldn't stand the fonts it used, they made the window much too big. I X ended up using DECterm fonts. Are those the only Narrow fixed-width X fonts available? X XHah! Just found another one. I used the Gripe command so I wouldn't have to V look Xup your email address. It doesn't use the replyPath string to generate the Xaddress on the To: line. Thus, it didn't put my uu%%"%s" stuff in, and the m Vail Xfailed. Also, would it be possible to document the action routines for the Xbuttons on composeTop so that key bindings could be in? I'm sure I could dig V it Xout of the code, but I'm inherently lazy. X X*** compose.c_orig X--- compose.c X************** X*** 2217,2223 X `20 X #ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X! char timeString`5B30`5D; X #endif X `20 X if (ComposeActive) `7B X--- 2217,2224 ----- X `20 X #ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X! char timeString`5B40`5D; X! struct tm *cur_time; X #endif X `20 X if (ComposeActive) `7B X************** X*** 2256,2263 X `20 X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X- #ifndef VMS X- /* gmtime() always returns null on VMS.. */ X (void) time(&clockTime); X (void) strcpy(timeString, asctime(gmtime(&clockTime))); X timeString`5B24`5D = '\0'; X--- 2257,2262 ----- X `20 X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X (void) time(&clockTime); X cur_time = gmtime(&clockTime); X if(cur_time)`7B X************** X*** 2259,2267 X #ifndef VMS X /* gmtime() always returns null on VMS.. */ X (void) time(&clockTime); X! (void) strcpy(timeString, asctime(gmtime(&clockTime))); X! timeString`5B24`5D = '\0'; X! (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X #endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X--- 2258,2275 ----- X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X (void) time(&clockTime); X! cur_time = gmtime(&clockTime); X! if(cur_time)`7B X! (void) strcpy(timeString, asctime(cur_time)); X! timeString`5B24`5D = ' '; X! (void) strcat(timeString, "GMT"); X! `7D else `7B X! cur_time = localtime(&clockTime); X! (void) strcpy(timeString, asctime(cur_time)); X! timeString`5B24`5D = ' '; X! (void) strcat(timeString, getenv(TIMEZONE_ENV)); X! `7D X! (void) sprintf(buffer, "Date: %s\n", timeString); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X************** X*** 2263,2269 X timeString`5B24`5D = '\0'; X (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X- #endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X #endif X--- 2271,2276 ----- X `7D X (void) sprintf(buffer, "Date: %s\n", timeString); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X #endif X************** X*** 2319,2325 X `20 X #ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X! char timeString`5B30`5D; X #endif X `20 X if (ComposeActive) `7B X--- 2326,2333 ----- X `20 X #ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X! char timeString`5B40`5D; X! struct tm *cur_time; X #endif X `20 X if (ComposeActive) `7B X************** X*** 2350,2356 X (void) strcat(TempString, "Distribution: world\n"); X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X- #ifndef VMS X (void) time(&clockTime); X (void) strcpy(timeString, asctime(gmtime(&clockTime))); X timeString`5B24`5D = '\0'; X--- 2358,2363 ----- X (void) strcat(TempString, "Distribution: world\n"); X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X (void) time(&clockTime); X cur_time = gmtime(&clockTime); X if(cur_time)`7B X************** X*** 2352,2360 X /* stuff to generate Message-ID and Date... */ X #ifndef VMS X (void) time(&clockTime); X! (void) strcpy(timeString, asctime(gmtime(&clockTime))); X! timeString`5B24`5D = '\0'; X! (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X #endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X--- 2359,2376 ----- X #ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X (void) time(&clockTime); X! cur_time = gmtime(&clockTime); X! if(cur_time)`7B X! (void) strcpy(timeString, asctime(cur_time)); X! timeString`5B24`5D = ' '; X! (void) strcat(timeString, "GMT"); X! `7D else `7B X! cur_time = localtime(&clockTime); X! (void) strcpy(timeString, asctime(cur_time)); X! timeString`5B24`5D = ' '; X! (void) strcat(timeString, getenv(TIMEZONE_ENV)); X! `7D X! (void) sprintf(buffer, "Date: %s\n", timeString); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X************** X*** 2356,2362 X timeString`5B24`5D = '\0'; X (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X- #endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X #endif X--- 2372,2377 ----- X `7D X (void) sprintf(buffer, "Date: %s\n", timeString); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X #endif X************** X*** 2407,2412 X char buffer`5B10000`5D; X char *bufptr; X `20 X if (ComposeActive) `7B X `09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X `09return; X--- 2422,2433 ----- X char buffer`5B10000`5D; X char *bufptr; X `20 X+ #ifdef GENERATE_EXTRA_FIELDS X+ time_t clockTime; X+ char timeString`5B40`5D; X+ struct tm *cur_time; X+ #endif X+`20 X if (ComposeActive) `7B X `09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X `09return; X************** X*** 2456,2461 X (void) strcat(TempString, "\n"); X (void) sprintf(buffer, "Control: cancel %s\n", Header.messageId); X (void) strcat(TempString, buffer); X `20 X switch (postArticle(TempString,XRN_NEWS)) `7B X `09case POST_FAILED: X--- 2477,2501 ----- X (void) strcat(TempString, "\n"); X (void) sprintf(buffer, "Control: cancel %s\n", Header.messageId); X (void) strcat(TempString, buffer); X+ #ifdef GENERATE_EXTRA_FIELDS X+ /* stuff to generate Message-ID and Date... */ X+ (void) time(&clockTime); X+ cur_time = gmtime(&clockTime); X+ if(cur_time)`7B X+ (void) strcpy(timeString, asctime(cur_time)); X+ timeString`5B24`5D = ' '; X+ (void) strcat(timeString, "GMT"); X+ `7D else `7B X+ cur_time = localtime(&clockTime); X+ (void) strcpy(timeString, asctime(cur_time)); X+ timeString`5B24`5D = ' '; X+ (void) strcat(timeString, getenv(TIMEZONE_ENV)); X+ `7D X+ (void) sprintf(buffer, "Date: %s\n", timeString); X+ (void) strcat(TempString, buffer); X+ (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X+ (void) strcat(TempString, buffer); X+ #endif X `20 X switch (postArticle(TempString,XRN_NEWS)) `7B X `09case POST_FAILED: X*** config.h_orig X--- config.h X************** X*** 201,206 X #define GENERATE_EXTRA_FIELDS X `20 X /* X * the active file of most currently used news systems has a problem: X * if the first article number equals the last article number for a X * newsgroup, this means that there are 0 OR 1 ARTICLES. X--- 201,216 ----- X #define GENERATE_EXTRA_FIELDS X `20 X /* X+ * environment variable containing timezone name X+ * X+ * Used only with GENERATE_EXTRA_FIELDS. Since gmtime is allowed to X+ * return NULL, we must be prepared to use localtime and provide a`20 X+ * timezone specification. This macro defines the name of the environmen Vt X+ * variable containing the time zone. X+ */ X+ #define TIMEZONE_ENV "UUCP_TIME_ZONE" X+`20 X+ /* X * the active file of most currently used news systems has a problem: X * if the first article number equals the last article number for a X * newsgroup, this means that there are 0 OR 1 ARTICLES. X X X-- XTerry Poot The McCall Pattern Company X(uucp: ...!rutgers!ksuvax1!mccall!tp) 615 McCall Road X(800)255-2762, in KS (913)776-4041 Manhattan, KS 66502, USA X X================== RFC 822 Headers ================== XReceived: from deimos.cis.ksu.edu by harris.cis.ksu.edu`20 X`09(5.58/SWH-2.03); id AA12207; Wed, 10 Oct 90 15:22:07 CDT XReturn-Path: XReceived: by deimos.cis.ksu.edu`20 X`09(5.58a-3B15/SWH-2.03); id AA12536; Wed, 10 Oct 90 15:41:10 EDT XDate: Wed, 10 Oct 90 19:41:04 EDT XMessage-Id: <9010101941.AA12536@deimos.cis.ksu.edu> XRick:`20 XApparently-To: murphy@ufp.dco.dec.com $ CALL UNPACK ANU-NEWS.PATCHES;1 106880872 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/avl.c,v 1.7 V 90/09/29 01:11:27 ricks Exp $"; X#endif X X/* X * avl package X * X * Copyright (c) 1988, 1989, 1990, The Regents of the University of Californ Via. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X#ifndef VMS X#include X#else X#include X#endif X#include "config.h" X#include "avl.h" X X#define ALLOC(type, number) (type *) XtMalloc((unsigned) sizeof(type) * num Vber) X#define NIL(type) (type *) 0 X#define FREE(item)`09 (void) XtFree(item) X X#define MAX(a,b) ((a) > (b) ? (a) : (b)) X X/* LINTLIBRARY */ X X X/*#define MAX(a,b) ((a) > (b) ? (a) : (b))*/ X#define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height) X#define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left)) X X#define compute_height(node) `7B`09`09`09`09\ X int x=HEIGHT(node->left), y=HEIGHT(node->right);`09\ X (node)->height = MAX(x,y) + 1;`09`09`09\ X`7D X X#define COMPARE(key, nodekey, compare)`09 `09`09\ X ((compare == avl_numcmp) ? `09`09`09`09\ X`09(int) key - (int) nodekey : `09`09`09\ X`09(*compare)(key, nodekey)) X Xstatic avl_node *new_node(); Xstatic avl_node *find_rightmost(); Xstatic void do_rebalance();`20 Xstatic void rotate_left(); Xstatic void rotate_right(); Xstatic int do_check_tree(); X X`0C Xavl_tree * Xavl_init_table(compar) Xint (*compar)(); X`7B X avl_tree *tree; X X tree = ALLOC(avl_tree, 1); X tree->root = NIL(avl_node); X tree->compar = compar; X tree->num_entries = 0; X return tree; X`7D X X Xavl_lookup(tree, key, value_p) Xavl_tree *tree; Xregister char *key; Xchar **value_p; X`7B X register avl_node *node; X register int (*compare)() = tree->compar, diff; X X node = tree->root; X while (node != NIL(avl_node)) `7B X`09diff = COMPARE(key, node->key, compare); X`09if (diff == 0) `7B X`09 /* got a match, give the user a 'value' only if non-null */ X`09 if (value_p != NIL(char *)) *value_p = node->value; X`09 return 1; X`09`7D X`09node = (diff < 0) ? node->left : node->right; X `7D X return 0; X`7D X X Xavl_insert(tree, key, value) Xavl_tree *tree; Xchar *key; Xchar *value; X`7B X register avl_node **node_p, *node; X register int stack_n = 0; X register int (*compare)() = tree->compar; X avl_node **stack_nodep`5B32`5D; X int diff, status; X X node_p = &tree->root; X X /* walk down the tree (saving the path); stop at insertion point */ X status = 0; X while ((node = *node_p) != NIL(avl_node)) `7B X`09stack_nodep`5Bstack_n++`5D = node_p; X`09diff = COMPARE(key, node->key, compare); X`09if (diff == 0) status = 1; X`09node_p = (diff < 0) ? &node->left : &node->right; X `7D X X /* insert the item and re-balance the tree */ X *node_p = new_node(key, value); X do_rebalance(stack_nodep, stack_n); X tree->num_entries++; X tree->modified = 1; X return status; X`7D X`0C Xavl_delete(tree, key_p, value_p) Xavl_tree *tree; Xchar **key_p; Xchar **value_p; X`7B X register avl_node **node_p, *node, *rightmost; X register int stack_n = 0; X char *key = *key_p; X int (*compare)() = tree->compar, diff; X avl_node **stack_nodep`5B32`5D; X `20 X node_p = &tree->root; X X /* Walk down the tree saving the path; return if not found */ X while ((node = *node_p) != NIL(avl_node)) `7B X`09diff = COMPARE(key, node->key, compare); X`09if (diff == 0) goto delete_item; X`09stack_nodep`5Bstack_n++`5D = node_p; X`09node_p = (diff < 0) ? &node->left : &node->right; X `7D X return 0;`09`09/* not found */ X X /* prepare to delete node and replace it with rightmost of left tree */ Xdelete_item: X *key_p = node->key; X if (value_p != 0) *value_p = node->value; X if (node->left == NIL(avl_node)) `7B X`09*node_p = node->right; X `7D else `7B X`09rightmost = find_rightmost(&node->left); X`09rightmost->left = node->left; X`09rightmost->right = node->right; X`09rightmost->height = -2; `09/* mark bogus height for do_rebal */ X`09*node_p = rightmost; X`09stack_nodep`5Bstack_n++`5D = node_p; X `7D X FREE(node); X X /* work our way back up, re-balancing the tree */ X do_rebalance(stack_nodep, stack_n); X tree->num_entries--; X tree->modified = 1; X return 1; X`7D X`0C Xstatic void`20 Xavl_record_gen_forward(node, gen) Xavl_node *node; Xavl_generator *gen; X`7B X if (node != NIL(avl_node)) `7B X`09avl_record_gen_forward(node->left, gen); X`09gen->nodelist`5Bgen->count++`5D = node; X`09avl_record_gen_forward(node->right, gen); X `7D X`7D X X Xstatic void`20 Xavl_record_gen_backward(node, gen) Xavl_node *node; Xavl_generator *gen; X`7B X if (node != NIL(avl_node)) `7B X`09avl_record_gen_backward(node->right, gen); X`09gen->nodelist`5Bgen->count++`5D = node; X`09avl_record_gen_backward(node->left, gen); X `7D X`7D X X Xavl_generator * Xavl_init_gen(tree, dir) Xavl_tree *tree; Xint dir; X`7B X avl_generator *gen; X X /* what a hack */ X gen = ALLOC(avl_generator, 1); X gen->tree = tree; X gen->nodelist = ALLOC(avl_node *, avl_count(tree)); X gen->count = 0; X if (dir == AVL_FORWARD) `7B X`09avl_record_gen_forward(tree->root, gen); X `7D else `7B X`09avl_record_gen_backward(tree->root, gen); X `7D X gen->count = 0; X X /* catch any attempt to modify the tree while we generate */ X tree->modified = 0; X return gen; X`7D X X Xavl_gen(gen, key_p, value_p) Xavl_generator *gen; Xchar **key_p; Xchar **value_p; X`7B X avl_node *node; X X if (gen->count == gen->tree->num_entries) `7B X`09return 0; X `7D else `7B X`09node = gen->nodelist`5Bgen->count++`5D; X`09if (key_p != NIL(char *)) *key_p = node->key; X`09if (value_p != NIL(char *)) *value_p = node->value; X`09return 1; X `7D X`7D X X Xvoid Xavl_free_gen(gen) Xavl_generator *gen; X`7B X FREE(gen->nodelist); X FREE(gen); X`7D X`0C Xstatic avl_node * Xfind_rightmost(node_p) Xregister avl_node **node_p; X`7B X register avl_node *node; X register int stack_n = 0; X avl_node **stack_nodep`5B32`5D; X X node = *node_p; X while (node->right != NIL(avl_node)) `7B X`09stack_nodep`5Bstack_n++`5D = node_p; X`09node_p = &node->right; X`09node = *node_p; X `7D X *node_p = node->left; X X do_rebalance(stack_nodep, stack_n); X return node; X`7D X X Xstatic void Xdo_rebalance(stack_nodep, stack_n) Xregister avl_node ***stack_nodep; Xregister int stack_n; X`7B X register avl_node **node_p, *node; X register int hl, hr; X int height; X X /* work our way back up, re-balancing the tree */ X while (--stack_n >= 0) `7B X`09node_p = stack_nodep`5Bstack_n`5D; X`09node = *node_p; X`09hl = HEIGHT(node->left);`09`09/* watch for NIL */ X`09hr = HEIGHT(node->right);`09`09/* watch for NIL */ X`09if ((hr - hl) < -1) `7B X`09 rotate_right(node_p); X`09`7D else if ((hr - hl) > 1) `7B X`09 rotate_left(node_p); X`09`7D else `7B X`09 height = MAX(hl, hr) + 1; X`09 if (height == node->height) break; X`09 node->height = height; X`09`7D X `7D X`7D X`0C Xstatic void Xrotate_left(node_p) Xregister avl_node **node_p; X`7B X register avl_node *old_root = *node_p, *new_root, *new_right; X X if (BALANCE(old_root->right) >= 0) `7B X`09*node_p = new_root = old_root->right; X`09old_root->right = new_root->left; X`09new_root->left = old_root; X `7D else `7B X`09new_right = old_root->right; X`09*node_p = new_root = new_right->left; X`09old_root->right = new_root->left; X`09new_right->left = new_root->right; X`09new_root->right = new_right; X`09new_root->left = old_root; X`09compute_height(new_right); X `7D X compute_height(old_root); X compute_height(new_root); X`7D X X Xstatic void Xrotate_right(node_p) Xavl_node **node_p; X`7B X register avl_node *old_root = *node_p, *new_root, *new_left; X X if (BALANCE(old_root->left) <= 0) `7B X`09*node_p = new_root = old_root->left; X`09old_root->left = new_root->right; X`09new_root->right = old_root; X `7D else `7B X`09new_left = old_root->left; X`09*node_p = new_root = new_left->right; X`09old_root->left = new_root->right; X`09new_left->right = new_root->left; X`09new_root->left = new_left; X`09new_root->right = old_root; X`09compute_height(new_left); X `7D X compute_height(old_root); X compute_height(new_root); X`7D X`0C Xstatic void`20 Xavl_walk_forward(node, func) Xavl_node *node; Xvoid (*func)(); X`7B X if (node != NIL(avl_node)) `7B X`09avl_walk_forward(node->left, func); X`09(*func)(node->key, node->value); X`09avl_walk_forward(node->right, func); X `7D X`7D X X Xstatic void`20 Xavl_walk_backward(node, func) Xavl_node *node; Xvoid (*func)(); X`7B X if (node != NIL(avl_node)) `7B X`09avl_walk_backward(node->right, func); X`09(*func)(node->key, node->value); X`09avl_walk_backward(node->left, func); X `7D X`7D X X Xvoid`20 Xavl_foreach(tree, func, direction) Xavl_tree *tree; Xvoid (*func)(); Xint direction; X`7B X if (direction == AVL_FORWARD) `7B X`09avl_walk_forward(tree->root, func); X `7D else `7B X`09avl_walk_backward(tree->root, func); X `7D X`7D X X Xstatic void Xfree_entry(node, key_free, value_free) Xavl_node *node; Xvoid (*key_free)(); Xvoid (*value_free)(); X`7B X if (node != NIL(avl_node)) `7B X`09free_entry(node->left, key_free, value_free); X`09free_entry(node->right, key_free, value_free); X`09if (key_free != 0) (*key_free)(node->key); X`09if (value_free != 0) (*value_free)(node->value); X`09FREE(node); X `7D X`7D X `20 X Xvoid`20 Xavl_free_table(tree, key_free, value_free) Xavl_tree *tree; Xvoid (*key_free)(); Xvoid (*value_free)(); X`7B X free_entry(tree->root, key_free, value_free); X FREE(tree); X`7D X X Xint`20 Xavl_count(tree) Xavl_tree *tree; X`7B X return tree->num_entries; X`7D X`0C Xstatic avl_node * Xnew_node(key, value) Xchar *key; Xchar *value; X`7B X register avl_node *new; X X new = ALLOC(avl_node, 1); X new->key = key; X new->value = value; X new->height = 0; X new->left = new->right = NIL(avl_node); X return new; X`7D X X Xint`20 Xavl_numcmp(x, y) Xchar *x, *y;`20 X`7B X return (int) x - (int) y; X`7D X`0C Xint Xavl_check_tree(tree) Xavl_tree *tree; X`7B X int error = 0; X (void) do_check_tree(tree->root, tree->compar, &error); X return error; X`7D X X Xstatic int Xdo_check_tree(node, compar, error) Xavl_node *node; Xint (*compar)(); Xint *error; X`7B X int l_height, r_height, comp_height, bal; X `20 X if (node == NIL(avl_node)) `7B X`09return -1; X `7D X X r_height = do_check_tree(node->right, compar, error); X l_height = do_check_tree(node->left, compar, error); X X comp_height = MAX(l_height, r_height) + 1; X bal = r_height - l_height; X `20 X if (comp_height != node->height) `7B X`09(void) printf("Bad height for 0x%08x: computed=%d stored=%d\n", X`09 node, comp_height, node->height); X`09++*error; X `7D X X if (bal > 1 `7C`7C bal < -1) `7B X`09(void) printf("Out of balance at node 0x%08x, balance = %d\n",`20 X`09 node, bal); X`09++*error; X `7D X X if (node->left != NIL(avl_node) &&`20 X`09`09 (*compar)(node->left->key, node->key) > 0) `7B X`09(void) printf("Bad ordering between 0x%08x and 0x%08x",`20 X`09 node, node->left); X`09++*error; X `7D X `20 X if (node->right != NIL(avl_node) &&`20 X`09`09 (*compar)(node->key, node->right->key) > 0) `7B X`09(void) printf("Bad ordering between 0x%08x and 0x%08x",`20 X`09 node, node->right); X`09++*error; X `7D X X return comp_height; X`7D $ CALL UNPACK AVL.C;1 1344203270 $ create 'f' X#ifndef AVL_H X#define AVL_H X X/* X * $Header: /users/ricks/xrn/src/RCS/avl.h,v 1.5 90/09/29 02:27:08 ricks Exp V $ X */ X X/* X * avl package X * X * Copyright (c) 1988, 1989, 1990, The Regents of the University of Californ Via. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X Xtypedef struct avl_node_struct avl_node; Xstruct avl_node_struct `7B X avl_node *left, *right; X char *key; X char *value; X int height; X`7D; X X Xtypedef struct avl_tree_struct avl_tree; Xstruct avl_tree_struct `7B X avl_node *root; X int (*compar)(); X int num_entries; X int modified; X`7D; X X Xtypedef struct avl_generator_struct avl_generator; Xstruct avl_generator_struct `7B X avl_tree *tree; X avl_node **nodelist; X int count; X`7D; X X X#define AVL_FORWARD `090 X#define AVL_BACKWARD `091 X X Xextern avl_tree *avl_init_table(); Xextern int avl_delete(), avl_insert(), avl_lookup(); Xextern int avl_count(), avl_numcmp(), avl_gen(); Xextern void avl_foreach(), avl_free_table(), avl_free_gen(); Xextern avl_generator *avl_init_gen(); X X#define avl_is_member(tree, key)`09avl_lookup(tree, key, (char **) 0) X X#define avl_foreach_item(table, gen, dir, key_p, value_p) `09\ X for(gen = avl_init_gen(table, dir); `09`09`09\ X`09 avl_gen(gen, key_p, value_p) `7C`7C (avl_free_gen(gen),0);) X X#endif X $ CALL UNPACK AVL.H;1 57362812 $ create 'f' X#define bigicon_width 32 X#define bigicon_height 32 Xstatic char bigicon_bits`5B`5D = `7B X 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xa0, X 0xfd, 0xff, 0xff, 0xcf, 0x05, 0x00, 0x00, 0xa8, 0x85, 0xb9, 0x52, 0xc8, X 0x85, 0xaa, 0x22, 0xa8, 0x85, 0xa9, 0x26, 0xc8, 0x05, 0x00, 0x00, 0xa8, X 0x05, 0xb5, 0x32, 0xc8, 0x05, 0x97, 0x12, 0xa8, 0x05, 0xb5, 0x1b, 0xc8, X 0x05, 0x00, 0x00, 0xa8, 0xf5, 0xff, 0xff, 0xcb, 0x05, 0x00, 0x00, 0xa8, X 0x05, 0x00, 0x00, 0xc8, 0xc5, 0xf8, 0x97, 0xa9, 0x35, 0x0b, 0xf4, 0xca, X 0x05, 0x08, 0x04, 0xa8, 0x45, 0x98, 0xb4, 0xcb, 0xb5, 0x0b, 0x04, 0xa8, X 0x05, 0x88, 0xc4, 0xcb, 0xb5, 0x7b, 0x74, 0xaa, 0xc5, 0x08, 0x04, 0xc8, X 0x05, 0xf8, 0xb7, 0xab, 0xf5, 0x03, 0x60, 0xc8, 0x85, 0xb8, 0x07, 0xa8, X 0x05, 0x00, 0x00, 0xc8, 0xfd, 0xff, 0xff, 0xaf, 0x01, 0x00, 0x00, 0xc0, X 0xab, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff`7D; $ CALL UNPACK BIGICON.XBM;1 1467174404 $ create 'f' X`20 X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/buttons.c,v V 1.21 90/09/29 01:11:36 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * buttons.c: create and handle the buttons X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#else X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#include X#else X#ifndef VMS X#include X#else X#include X#endif X#endif /* MOTIF */ X#include "compose.h" X#include "cursor.h" X#include "mesg.h" X#include "dialogs.h" X#include "modes.h" X#include "resources.h" X#include "internals.h" X#include "save.h" X#include "xmisc.h" X#include "error_hnds.h" X#include "xthelper.h" X#include "xrn.h" X#include "news.h" X#include "buttons.h" X#include "slist.h" X X#ifdef MOTIF Xextern void PaneSetMinMax(); X#else X#define XmNlabelString DwtNlabel X#define XmNactivateCallback DwtNactivateCallback X#define XmNborderWidth DwtNborderWidth X#endif X#define GROUP_NAME_SIZE 128 Xextern void resetPopupSize(); Xextern void close_server(); X X#ifdef VMS X#include X#endif X Xstatic Widget *AddButtons = NIL(Widget); Xstatic Widget *NgButtons = NIL(Widget); Xstatic Widget *AllButtons = NIL(Widget); Xstatic Widget *ArtButtons = NIL(Widget); Xstatic Widget *ArtSpecButtons = NIL(Widget); Xexternalref Widget ngMenus`5B5`5D; Xexternalref Widget artMenus`5B7`5D; Xexternalref Widget allMenus`5B5`5D; Xexternalref Widget addMenus`5B3`5D; Xexternalref Widget *AddPopupButtons; Xexternalref Widget *NgPopupButtons; Xexternalref Widget *AllPopupButtons; Xexternalref Widget *ArtPopupButtons; X Xstatic char **AddGroupsStrings = (char**) 0; /* new newsgroups list ... V */ Xstatic char **NewsGroups = (char**) 0; /* newsgroups list that is displ Vayed */ Xstatic char **AllGroupsStrings = (char**) 0; /* list of all groups so the us Ver */ X`09`09`09`09 /* can subscribe/unsubscribe to them */ Xstatic char **SubjectStrings = (char**) 0; /* list of article numbers and su Vbjects */ X Xstatic int GroupPosition = 0; `09/* cursor position in newsgroup window */ Xstatic int AddGroupPosition = 0;/* cursor position in newsgroup window */ Xstatic int GroupItems = 0;`09/* Number of groups */ Xstatic int AddGroupItems = 0;`09/* Number of new groups */ Xstatic int ArtPosition = 0;`09/* cursor position in article subject window V */ Xstatic int SubjectItems = 0;`09/* Number of subjects */ Xstatic int AllPosition = 0;`09/* position in all groups window */ Xstatic int AllGroupItems = 0;`09/* Number of items in All Groups strings */ X Xstatic char LastGroup`5BGROUP_NAME_SIZE`5D;`09/* last newsgroup accessed; us Ved to */ X`09`09`09`09/* determine whether or not to move the */ X`09`09`09`09/* cursor in the newsgroup window */ Xstatic int CurrentArticle;`09/* the number of the article currently */ X`09`09`09`09/* displayed, used for marking an article */ X`09`09`09`09/* as saved */ X Xstatic long PrevArticle;`09/* the number of the article displayed */ X`09`09`09`09/* before the current one */ X Xstatic int ArtStatus = 0;`09/* keeps track of what kind of article to */ X`09`09`09`09/* search for: next, previous, or next */ X`09`09`09`09/* unread */ Xstatic int AllStatus = 0;`09/* keeps track of which order to put the */ X`09`09`09`09/* groups in in all groups mode */ Xstatic char *LastRegexp;`09/* last regular expression searched for */ Xstatic int LastSearch;`09`09/* the direction of the last regular */ X`09`09`09`09/* expression search */ X Xstatic char *selList = NULL;`09/* Keeps the selected entry array */ Xstatic int selSize = 0;`09`09/* current size of the array */ Xstatic int selCount = 0;`09/* selection count */ X Xstatic int Action;`09`09/* action to take when a confirmation box */ X`09`09`09`09/* is clicked in */ X Xstatic int SelectionItem = -1;`09/* List item selected */ Xstatic int SelectionCount= 0;`09/* Number of items selected */ X Xstatic int NewsgroupDisplayMode = 0;`09/* 0 for unread groups, 1 for all sub V */ X#define XRN_JUMP 0 X#define XRN_GOTO 1 Xstatic int NewsgroupEntryMode = XRN_GOTO; X Xstatic int ArtEntry = 1; Xstatic int currentTop = 0;`09/* Current list top entry */ X X X/* article mode "modes" ... determines what to do: jump out of article */ X/* mode, change the subject string, or do nothing */ X#define art_DONE 0 X#define art_CHANGE 1 X#define art_NOCHANGE 2 X X/* keeps track of which type of article to search for: Next, Unread, or */ X/* previous */ X#define art_NEXT 0 X#define art_UNREAD 1 X#define art_PREV 2 X#define art_CURRENT 3 X Xint Mode = NO_MODE; `09`09/* current mode * V/ Xstatic int PreviousMode = NO_MODE;`09/* previous mode, what buttons to */ X`09`09`09`09`09/* remove */ X X#define XRN_NO 0 X#define XRN_YES 1 X X/* the user is in a command - eat type ahead */ Xint inCommand = 0; X Xstatic struct _translations `7B X Widget widget; X XtTranslations tables`5BMAX_MODE`5D; X char *unparsed`5BMAX_MODE`5D; X`7D Translations`5B6`5D; X Xstatic void listSelect(); Xstatic void DoubleClick(); Xstatic void subjSetPos(); Xstatic void resetSubjectWidget(); Xstatic void catchUpNG(); Xstatic void unsubscribeNG(); Xstatic void catchUpART(); Xstatic void catchUpPartART(); Xstatic void unsubscribeART(); Xstatic void switchToAllMode(); Xstatic void fedUpART(); X X/* handle autorescan timeouts */ X Xstatic XtIntervalId TimeOut = 0; X Xvoid addTimeOut() X`7B X void autoRescan(); X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X X if (app_resources.rescanTime <= 0) `7B X`09return; X `7D X X /* do not allow recursive timeouts */ X if (TimeOut) `7B X`09return; X `7D X /* handle race conditions??? */ X TimeOut = 1; X X TimeOut = XtAddTimeOut(app_resources.rescanTime * 1000, autoRescan, 0); X return; X`7D X Xvoid removeTimeOut() X`7B X XtIntervalId temp; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X X /* handle race conditions??? */ X temp = TimeOut; X TimeOut = 0; X X /* do not allow recursive timeouts */ X if (temp) `7B X`09XtRemoveTimeOut(temp); X `7D X return; X`7D X X X/* X * definition of the buttons X */ X X#if defined(__STDC__) && !defined(UNIXCPP) X#define BUTTON(nm)`09`09`09`09\ Xvoid nm##Function();`09`09`09`09\ Xstatic void nm##Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09XBell(XtDisplay(TopLevel), 0);`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X removeTimeOut();`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm##Function(widget, event, string, count);`09\ X unbusyCursor();`09`09`09`09\ X addTimeOut();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ X/*ARGSUSED*/ \ Xstatic void nm##Button(widget, client_data, call_data) \ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Action(widget, NULL, 0, 0);`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xexternaldef (nm##callbacks) XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Button, NULL`7D,`09`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname,`09`09(XtArgVal) #nm`7D,`09\ X `7BXmNlabelString,`09(XtArgVal) NULL`7D,`09\ X `7BXmNactivateCallback, (XtArgVal) nm##Callbacks`7D,\ X `7BXmNborderWidth,`09(XtArgVal) 1`7D,`09`09\ X`7D; X#else X#define BUTTON(nm)`09`09`09`09\ Xvoid nm/**/Function();`09`09`09`09\ Xstatic void nm/**/Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09XBell(XtDisplay(TopLevel), 0);`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X removeTimeOut();`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm/**/Function(widget, event, string, count); \ X unbusyCursor();`09`09`09`09\ X addTimeOut();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ X/*ARGSUSED*/`09`09`09`09`09\ Xstatic void nm/**/Button(widget, client_data, call_data)`09\ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Action(widget, NULL, 0, 0);`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xexternaldef (nm/**/callbacks) XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Button, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname,`09`09(XtArgVal) "nm"`7D,`09\ X `7BXmNlabelString,`09(XtArgVal) NULL`7D,`09\ X `7BXmNactivateCallback, (XtArgVal) nm/**/Callbacks`7D,\ X `7BXmNborderWidth,`09(XtArgVal) 1`7D,`09`09\ X`7D; X#endif X X#if defined(__STDC__) && !defined(UNIXCPP) X#define intBUTTON(nm)`09`09`09`09\ Xvoid nm##Function();`09`09`09`09\ X/*ARGSUSED*/`09`09`09`09`09\ Xstatic void nm##Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Function(widget, event, string, count);`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xexternaldef (nm##callbacks) XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname,`09`09(XtArgVal) #nm`7D,`09\ X `7BXmNlabelString,`09(XtArgVal) NULL`7D,`09\ X `7BXmNactivateCallback, (XtArgVal) nm##Callbacks`7D,\ X `7BXmNborderWidth,`09(XtArgVal) 1`7D,`09`09\ X`7D; X#else X#define intBUTTON(nm)`09`09`09`09\ Xvoid nm/**/Function();`09`09`09`09\ X/*ARGSUSED*/`09`09`09`09`09\ Xstatic void nm/**/Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Function(widget, event, string, count); \ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xexternaldef (nm/**/callbacks) XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname,`09`09(XtArgVal) "nm"`7D,`09\ X `7BXmNlabelString, (XtArgVal) NULL`7D,`09`09\ X `7BXmNactivateCallback, (XtArgVal) nm/**/Callbacks`7D,\ X `7BXmNborderWidth,`09(XtArgVal) 1`7D,`09`09\ X`7D; X#endif X X/* X * The newsgroup and article command buttons X * X * To add a button: X * X * - add the appropriate static Arg`5B`5D for describing the button X * label and handler (define the return value of the handler) X * - add the variable and size to the apropriate *ButtonList X * - add it to the actions table and the keyactions table X * X */ X XBUTTON(addQuit) XBUTTON(addFirst) XBUTTON(addLast) XBUTTON(addAfter) XBUTTON(addUnsub) X XBUTTON(ngExit) XBUTTON(ngQuit) XBUTTON(ngRead) XBUTTON(ngOpen) XBUTTON(ngNext) XBUTTON(ngPrev) XBUTTON(ngCatchUp) XBUTTON(ngSubscribe) XBUTTON(ngUnsub) XBUTTON(ngGoto) XBUTTON(ngToggleGroups) XBUTTON(ngAllGroups) XBUTTON(ngRescan) XBUTTON(ngPrevGroup) XBUTTON(ngSelect) XBUTTON(ngMove) XBUTTON(ngCheckPoint) XBUTTON(ngPost) XBUTTON(ngGripe) X XBUTTON(allQuit) XBUTTON(allSub) XBUTTON(allFirst) XBUTTON(allLast) XBUTTON(allAfter) XBUTTON(allUnsub) XBUTTON(allGoto) XBUTTON(allSelect) XBUTTON(allMove) XBUTTON(allToggle) XBUTTON(allScroll) XBUTTON(allScrollBack) XBUTTON(allSearch) XBUTTON(allContinue) XintBUTTON(allCancelSearch) X XBUTTON(artQuit) XBUTTON(artNext) XBUTTON(artNextUnread) XBUTTON(artPrev) XBUTTON(artLast) XBUTTON(artNextGroup) XBUTTON(artGotoArticle) XBUTTON(artCatchUp) XBUTTON(artFedUp) XBUTTON(artMarkRead) XBUTTON(artMarkUnread) XBUTTON(artUnsub) XBUTTON(artScroll) XBUTTON(artScrollBack) XBUTTON(artScrollEnd) XBUTTON(artScrollBeginning) XBUTTON(artSubNext) XBUTTON(artSubPrev) XBUTTON(artKillSession) XBUTTON(artKillLocal) XBUTTON(artKillGlobal) XBUTTON(artKillAuthor) XBUTTON(artSubSearch) XBUTTON(artContinue) XintBUTTON(artCancelSearch) XBUTTON(artSorted) XBUTTON(artPost) XBUTTON(artExit) XBUTTON(artCheckPoint) XBUTTON(artGripe) XBUTTON(artListOld) X XBUTTON(artSave) XBUTTON(artReply) XBUTTON(artForward) XBUTTON(artFollowup) XBUTTON(artCancel) XBUTTON(artRot13) XBUTTON(artHeader) XBUTTON(artPrint) X Xstatic void doTheRightThing();`20 Xvoid abortSet(); Xstatic XtActionsRec TopActions`5B`5D = `7B X `7B"doTheRightThing",`09doTheRightThing`7D, X`7D; X Xstatic XtActionsRec AddActions`5B`5D = `7B X `7B"addQuit",`09`09addQuitAction`7D, X `7B"addFirst",`09addFirstAction`7D, X `7B"addLast",`09`09addLastAction`7D, X `7B"addAfter",`09addAfterAction`7D, X `7B"addUnsub",`09addUnsubAction`7D, X`7D; X Xstatic XtActionsRec NgActions`5B`5D = `7B X `7B"ngQuit",`09`09ngQuitAction`7D, X `7B"ngRead",`09`09ngReadAction`7D, X `7B"ngOpen",`09`09ngOpenAction`7D, X `7B"ngNext",`09`09ngNextAction`7D, X `7B"ngPrev",`09`09ngPrevAction`7D, X `7B"ngCatchUp",`09ngCatchUpAction`7D, X `7B"ngSubscribe",`09ngSubscribeAction`7D, X `7B"ngUnsub",`09`09ngUnsubAction`7D, X `7B"ngGoto",`09`09ngGotoAction`7D, X `7B"ngRescan",`09ngRescanAction`7D, X `7B"ngAllGroups",`09ngAllGroupsAction`7D, X `7B"ngToggleGroups",`09ngToggleGroupsAction`7D, X `7B"ngPrevGroup",`09ngPrevGroupAction`7D, X `7B"ngSelect",`09ngSelectAction`7D, X `7B"ngMove",`09`09ngMoveAction`7D, X `7B"ngExit",`09`09ngExitAction`7D, X `7B"ngGripe",`09`09ngGripeAction`7D, X `7B"ngPost",`09`09ngPostAction`7D, X `7B"ngCheckPoint",`09ngCheckPointAction`7D, X`7D; `20 Xstatic XtActionsRec ArtActions`5B`5D = `7B X `7B"artQuit",`09`09artQuitAction`7D, X `7B"artNextUnread",`09artNextUnreadAction`7D, X `7B"artScroll",`09artScrollAction`7D, X `7B"artScrollBack",`09artScrollBackAction`7D, X `7B"artScrollEnd",`09artScrollEndAction`7D, X `7B"artScrollBeginning",artScrollBeginningAction`7D, X `7B"artNext",`09`09artNextAction`7D, X `7B"artPrev",`09`09artPrevAction`7D, X `7B"artLast",`09`09artLastAction`7D, X `7B"artNextGroup",`09artNextGroupAction`7D, X `7B"artCatchUp",`09artCatchUpAction`7D, X `7B"artFedUp",`09artFedUpAction`7D, X `7B"artGotoArticle",`09artGotoArticleAction`7D, X `7B"artMarkRead",`09artMarkReadAction`7D, X `7B"artMarkUnread",`09artMarkUnreadAction`7D, X `7B"artUnsub",`09artUnsubAction`7D, X `7B"artSubNext",`09artSubNextAction`7D, X `7B"artSubPrev",`09artSubPrevAction`7D, X `7B"artKillSession",`09artKillSessionAction`7D, X `7B"artKillLocal",`09artKillLocalAction`7D, X `7B"artKillGlobal",`09artKillGlobalAction`7D, X `7B"artKillAuthor",`09artKillAuthorAction`7D, X `7B"artSubSearch",`09artSubSearchAction`7D, X `7B"artContinue",`09artContinueAction`7D, X `7B"artCancelSearch",`09artCancelSearchAction`7D, X `7B"artSorted",`09artSortedAction`7D, X `7B"artPost",`09`09artPostAction`7D, X `7B"artExit",`09`09artExitAction`7D, X `7B"artSave",`09`09artSaveAction`7D, X `7B"artReply",`09artReplyAction`7D, X `7B"artForward",`09artForwardAction`7D, X `7B"artFollowup",`09artFollowupAction`7D, X `7B"artCancel",`09artCancelAction`7D, X `7B"artRot13",`09artRot13Action`7D, X `7B"artHeader",`09artHeaderAction`7D, X `7B"artPrint",`09artPrintAction`7D, X `7B"artGripe",`09artGripeAction`7D, X `7B"artListOld",`09artListOldAction`7D, X`7D; X Xstatic XtActionsRec AllActions`5B`5D = `7B X `7B"allQuit",`09`09allQuitAction`7D, X `7B"allSub",`09`09allSubAction`7D, X `7B"allFirst",`09allFirstAction`7D, X `7B"allLast",`09`09allLastAction`7D, X `7B"allAfter",`09allAfterAction`7D, X `7B"allUnsub",`09allUnsubAction`7D, X `7B"allGoto",`09`09allGotoAction`7D, X `7B"allSelect",`09allSelectAction`7D, X `7B"allMove",`09`09allMoveAction`7D, X `7B"allToggle",`09allToggleAction`7D, X `7B"allScroll",`09allScrollAction`7D, X `7B"allScrollBack",`09allScrollBackAction`7D, X `7B"allSearch",`09allSearchAction`7D, X `7B"allContinue",`09allContinueAction`7D, X `7B"allCancelSearch", allCancelSearchAction`7D, X`7D; X Xtypedef struct buttonList `7B X char *label; X Arg *buttonArgs; X unsigned int size; X char *message; X`7D ButtonList; X Xexternaldef(addbuttonlist) ButtonList AddButtonList`5B`5D = `7B X `7B"Quit", addQuitArgs, XtNumber(addQuitArgs), X "Quit add mode, unsubscribe all remaining groups"`7D, X `7B"Add First", addFirstArgs, XtNumber(addFirstArgs), X "Add the selected group(s) to the beginning of the .newsrc file"`7D, X `7B"Add Last", addLastArgs, XtNumber(addLastArgs), X "Add the selected group(s) to the end of the .newsrc file"`7D, X `7B"Add After Group", addAfterArgs, XtNumber(addAfterArgs), X "Add the selected group(s) after a particular group in the .newsrc file"` V7D, X `7B"Add Unsubscribed", addUnsubArgs, XtNumber(addUnsubArgs), X "Add the selected group(s) as unsubscribed"`7D, X`7D; X Xstatic int AddButtonListCount = XtNumber(AddButtonList); Xexternaldef(addpopupcount) int AddPopupCount = XtNumber(AddButtonList); X Xexternaldef(ngbuttonlist) ButtonList NgButtonList`5B`5D = `7B X `7B"Quit", ngQuitArgs, XtNumber(ngQuitArgs), X "Quit XRN"`7D, X `7B"Read Group", ngReadArgs, XtNumber(ngReadArgs), X "Read the articles in the current group"`7D, X `7B"Open Group", ngOpenArgs, XtNumber(ngOpenArgs), X "Open the current group"`7D, X `7B"Next", ngNextArgs, XtNumber(ngNextArgs), X "Move the cursor to the next group"`7D, X `7B"Prev", ngPrevArgs, XtNumber(ngPrevArgs), X "Move the cursor to the previous group"`7D, X `7B"Catch Up", ngCatchUpArgs, XtNumber(ngCatchUpArgs), X "Mark all articles in the current group as read"`7D, X `7B"Subscribe", ngSubscribeArgs, XtNumber(ngSubscribeArgs), X "Subscribe to a group"`7D, X `7B"Unsubscribe", ngUnsubArgs, XtNumber(ngUnsubArgs), X "Unsubscribe to the current group"`7D, X `7B"Go To Newsgroup", ngGotoArgs, XtNumber(ngGotoArgs), X "Go to a newsgroup"`7D, X `7B"All Groups", ngAllGroupsArgs, XtNumber(ngAllGroupsArgs), X "View all available groups, with option to subscribe"`7D, X `7B"Toggle Groups", ngToggleGroupsArgs, XtNumber(ngToggleGroupsArgs), X "Show groups with no new articles (toggle)"`7D, X `7B"Rescan", ngRescanArgs, XtNumber(ngRescanArgs), X "Query the news server for new articles and groups"`7D, X `7B"Prev Group", ngPrevGroupArgs, XtNumber(ngPrevGroupArgs), X "Return to the group just visited"`7D, X `7B"Select Groups", ngSelectArgs, XtNumber(ngSelectArgs), X "Mark current selection for subsequent move operations"`7D, X `7B"Move", ngMoveArgs, XtNumber(ngMoveArgs), X "Move previously selected groups in front of the current selection"`7D, X `7B"Exit", ngExitArgs, XtNumber(ngExitArgs), X "Quit XRN, leaving the .newsrc file unchanged since the last rescan"`7D, X `7B"Checkpoint", ngCheckPointArgs, XtNumber(ngCheckPointArgs), X "Update the .newsrc file"`7D, X `7B"Gripe", ngGripeArgs, XtNumber(ngGripeArgs), X "Mail a gripe to the XRN maintainers"`7D, X `7B"Post", ngPostArgs, XtNumber(ngPostArgs), X "Post an article to a newsgroup"`7D, X`7D; X Xstatic int NgButtonListCount = XtNumber(NgButtonList); Xexternaldef(ngpopupcount) int NgPopupCount = XtNumber(NgButtonList); X Xexternaldef(allbuttonlist) ButtonList AllButtonList`5B`5D = `7B X `7B"Quit", allQuitArgs, XtNumber(allQuitArgs), X "Return to newsgroup mode, saving changes"`7D, X `7B"Subscribe", allSubArgs, XtNumber(allSubArgs), X "Subscribe to current group, leaveing .newsrc position unchanged"`7D, X `7B"Subscribe First", allFirstArgs, XtNumber(allFirstArgs), X "Subscribe to the selected group(s); put at the beginning of the .newsrc V file"`7D, X `7B"Subscribe Last", allLastArgs, XtNumber(allLastArgs), X "Subscribe to the selected group(s); put at the end of the .newsrc file"` V7D, X `7B"Subscribe After Group", allAfterArgs, XtNumber(allAfterArgs), X "Subscribe to the selected group(s); put after a specified group in the . Vnewsrc file"`7D, X `7B"Unsubscribe", allUnsubArgs, XtNumber(allUnsubArgs), X "Unsubscribe to the selected group(s)"`7D, X `7B"Go To Group", allGotoArgs, XtNumber(allGotoArgs), X "Go to the current newsgroup"`7D, X `7B"Select Groups", allSelectArgs, XtNumber(allSelectArgs), X "Mark current selection for subsequent move operations"`7D, X `7B"Move", allMoveArgs, XtNumber(allMoveArgs), X "Move previously selected groups to the current position"`7D, X `7B"Toggle Order", allToggleArgs, XtNumber(allToggleArgs), X "Change order of groups: alphabetical/.newsrc order"`7D, X `7B"Scroll Forward", allScrollArgs, XtNumber(allScrollArgs), X "Scroll the ALL groups screen forward"`7D, X `7B"Scroll Backward", allScrollBackArgs, XtNumber(allScrollBackArgs), X "Scroll the ALL groups screen backward"`7D, X `7B"Search", allSearchArgs, XtNumber(allSearchArgs), X "Search for a newsgroup"`7D, X `7B"Continue", allContinueArgs, XtNumber(allContinueArgs), X "Continue newsgroup search"`7D, X `7B"Cancel Search", allCancelSearchArgs, XtNumber(allCancelSearchArgs), X "Cancel newsgroup search"`7D, X`7D; X Xstatic int AllButtonListCount = XtNumber(AllButtonList); Xexternaldef(allpopupcount) int AllPopupCount = XtNumber(AllButtonList); X Xexternaldef(artbuttonlist) ButtonList ArtButtonList`5B`5D = `7B X `7B"Quit", artQuitArgs, XtNumber(artQuitArgs), X "Return to newsgroup mode"`7D, X `7B"Next Unread", artNextUnreadArgs, XtNumber(artNextUnreadArgs), X "Read the next unread article"`7D, X `7B"Next", artNextArgs, XtNumber(artNextArgs), X "Read the next article"`7D, X `7B"Scroll Forward", artScrollArgs, XtNumber(artScrollArgs), X "Scroll current article forward"`7D, X `7B"Scroll Backward", artScrollBackArgs, XtNumber(artScrollBackArgs), X "Scroll current article backward"`7D, X `7B"Scroll to End", artScrollEndArgs, XtNumber(artScrollEndArgs), X "Scroll to end of current article"`7D, X `7B"Scroll to Beginning", artScrollBeginningArgs, XtNumber(artScrollBegi VnningArgs), X "Scroll to beginning of current article"`7D, X `7B"Prev", artPrevArgs, XtNumber(artPrevArgs), X "Read the previous article"`7D, X `7B"Last", artLastArgs, XtNumber(artLastArgs), X "Go back to the last article displayed"`7D, X `7B"Next Newsgroup", artNextGroupArgs, XtNumber(artNextGroupArgs), X "Go to the next newsgroup, skipping newsgroup mode"`7D, X `7B"Catch Up",artCatchUpArgs, XtNumber(artCatchUpArgs), X "Mark all articles (up to the selected article) in the current group as r Vead"`7D, X `7B"Fed Up", artFedUpArgs, XtNumber(artFedUpArgs), X "Mark all articles in the current group as read and go to next newsgroup V "`7D, X `7B"Go To Article", artGotoArticleArgs, XtNumber(artGotoArticleArgs), X "Go to the specified article number in the current group"`7D, X `7B"Mark Read", artMarkReadArgs, XtNumber(artMarkReadArgs), X "Mark selected article(s) as read"`7D, X `7B"Mark Unread", artMarkUnreadArgs, XtNumber(artMarkUnreadArgs), X "Mark selected article(s) as unread"`7D, X `7B"Unsubscribe", artUnsubArgs, XtNumber(artUnsubArgs), X "Unsubscribe to the current group"`7D, X `7B"Subject Next", artSubNextArgs, XtNumber(artSubNextArgs), X "Search for the next article with the selected subject"`7D, X `7B"Subject Prev", artSubPrevArgs, XtNumber(artSubPrevArgs), X "Search for the previous article with the selected subject"`7D, X `7B"Session Kill", artKillSessionArgs, XtNumber(artKillSessionArgs), X "Mark all articles with this subject as read, this session only"`7D, X `7B"Local Kill", artKillLocalArgs, XtNumber(artKillLocalArgs), X "Mark all articles with this subject as read in this group for this and a Vll future sessions"`7D, X `7B"Global Kill", artKillGlobalArgs, XtNumber(artKillGlobalArgs), X "Mark all articles with this subject as read for all groups for this and V all future sessions"`7D, X `7B"Author Kill", artKillAuthorArgs, XtNumber(artKillAuthorArgs), X "Mark all articles with this author as read, this session only"`7D, X `7B"Subject Search", artSubSearchArgs, XtNumber(artSubSearchArgs), X "Search the subject lines for a regular expression"`7D, X `7B"Continue", artContinueArgs, XtNumber(artContinueArgs), X "Continue the regular expression subject search"`7D, X `7B"Cancel Search", artCancelSearchArgs, XtNumber(artCancelSearchArgs), X "Cancel subject search"`7D, X `7B"Toggle Order", artSortedArgs, XtNumber(artSortedArgs), X "Toggle subject order (sorted/unsorted)"`7D, X `7B"Post", artPostArgs, XtNumber(artPostArgs), X "Post an article to this newsgroup"`7D, X `7B"Exit", artExitArgs, XtNumber(artExitArgs), X "Return to newsgroup mode, marking all articles as unread"`7D, X `7B"Checkpoint", artCheckPointArgs, XtNumber(artCheckPointArgs), X "Update the .newsrc file"`7D, X `7B"Gripe", artGripeArgs, XtNumber(artGripeArgs), X "Mail a gripe to the XRN maintainers"`7D, X `7B"List Old", artListOldArgs, XtNumber(artListOldArgs), X "List all articles in the current group (may be slow)"`7D, X`7D; X Xstatic int ArtButtonListCount = XtNumber(ArtButtonList); Xexternaldef(artpopupcount) int ArtPopupCount = XtNumber(ArtButtonList); X Xexternaldef(artspecbuttonlist) ButtonList ArtSpecButtonList`5B`5D = `7B X `7B"Save", artSaveArgs, XtNumber(artSaveArgs), X "Save the current article in a file"`7D, X `7B"Reply", artReplyArgs, XtNumber(artReplyArgs), X "Mail a reply to the author of the current article"`7D, X `7B"Forward", artForwardArgs, XtNumber(artForwardArgs), X "Forward an article to a user(s)"`7D, X `7B"Followup", artFollowupArgs, XtNumber(artFollowupArgs), X "Post a followup to the current article"`7D, X `7B"Cancel", artCancelArgs, XtNumber(artCancelArgs), X "Cancel the current article"`7D, X `7B"Rot-13", artRot13Args, XtNumber(artRot13Args), X "Decrypt an encrypted joke"`7D, X `7B"Toggle Header", artHeaderArgs, XtNumber(artHeaderArgs), X "Display the complete/stripped header"`7D, X `7B"Print", artPrintArgs, XtNumber(artPrintArgs), X "Print the article"`7D, X`7D; X Xexternaldef(artspecbuttonlistcount) int ArtSpecButtonListCount = XtNumber(Ar VtSpecButtonList); Xexternaldef(artspecpopupcount) int ArtSpecPopupCount = XtNumber(ArtButtonLis Vt); X Xstatic char TopNonButtonInfo`5BLABEL_SIZE`5D; Xstatic char BottomNonButtonInfo`5BLABEL_SIZE`5D; X X X/*ARGSUSED*/ Xvoid XtopInfoHandler(widget, client_data, event) XWidget widget; Xcaddr_t client_data; XXEvent *event; X/* X * handle the Enter and Leave events for the buttons X * X * upon entering a button, get it's info string and put in the Question labe Vl X * upon leaving a button, restore the old info string X * X */ X`7B X Arg infoLineArg`5B1`5D; X#ifdef MOTIF X XmString infoString; X XmString defInfoString; X#else X DwtCompString infoString; X DwtCompString defInfoString; X#endif X X if (event->type == LeaveNotify) `7B X#ifdef MOTIF X`09defInfoString = XmStringLtoRCreate(TopNonButtonInfo, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09XtSetArg(infoLineArg`5B0`5D, XmNlabelString, defInfoString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XmStringFree(defInfoString); X#else X`09defInfoString = DwtLatin1String(TopNonButtonInfo); X`09XtSetArg(infoLineArg`5B0`5D, DwtNlabel, defInfoString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XtFree(defInfoString); X#endif X `7D else if (event->type == EnterNotify) `7B X#ifdef MOTIF X`09infoString = XmStringLtoRCreate(client_data, X`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X`09XtSetArg(infoLineArg`5B0`5D, XmNlabelString, infoString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XmStringFree(infoString); X#else X`09infoString = DwtLatin1String(client_data); X`09XtSetArg(infoLineArg`5B0`5D, DwtNlabel, infoString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XtFree(infoString); X#endif X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XbottomInfoHandler(widget, client_data, event) XWidget widget; Xcaddr_t client_data; XXEvent *event; X/* X * handle the Enter and Leave events for the buttons X * X * upon entering a button, get it's info string and put in the Question labe Vl X * upon leaving a button, restore the old info string X * X */ X`7B X Arg infoLineArg`5B1`5D; X#ifdef MOTIF X XmString infoString; X XmString defInfoString; X#else X DwtCompString infoString; X DwtCompString defInfoString; X#endif X X if (event->type == LeaveNotify) `7B X#ifdef MOTIF X`09defInfoString = XmStringLtoRCreate(BottomNonButtonInfo, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09XtSetArg(infoLineArg`5B0`5D, XmNlabelString, defInfoString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XmStringFree(defInfoString); X#else X`09defInfoString = DwtLatin1String(BottomNonButtonInfo); X`09XtSetArg(infoLineArg`5B0`5D, DwtNlabel, defInfoString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XtFree(defInfoString); X#endif X `7D else if (event->type == EnterNotify) `7B X#ifdef MOTIF X`09infoString = XmStringLtoRCreate(client_data, X`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X`09XtSetArg(infoLineArg`5B0`5D, XmNlabelString, infoString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XmStringFree(infoString); X#else X`09infoString = DwtLatin1String(client_data); X`09XtSetArg(infoLineArg`5B0`5D, DwtNlabel, infoString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XtFree(infoString); X#endif X `7D X return; X`7D X X Xstatic void XresetSelection() X/* X * Reset selection once it's used.. X */ X`7B X selCount = 0; X SelectionItem = -1; X SListSelectAll(TopList, 0); `20 X return; X`7D X X Xstatic void XsetTopInfoLineHandler(widget, message) XWidget widget; Xchar *message; X`7B X XtAddEventHandler(widget, X`09`09 (EventMask) (EnterWindowMask`7CLeaveWindowMask), X`09`09 False, X`09`09 topInfoHandler, X`09`09 (caddr_t) message); X return; X`7D X X Xstatic void XsetBottomInfoLineHandler(widget, message) XWidget widget; Xchar *message; X`7B X XtAddEventHandler(widget, X`09`09 (EventMask) (EnterWindowMask`7CLeaveWindowMask), X`09`09 False, X`09`09 bottomInfoHandler, X`09`09 (caddr_t) message); X return; X`7D X X Xstatic void XsetTopInfoLine(message) `20 Xchar *message; X`7B X Arg infoLineArg`5B1`5D; X#ifdef MOTIF X XmString labelString; X#else X DwtCompString labelString; X#endif X X (void) strcpy(TopNonButtonInfo, (char *) message); X#ifdef MOTIF X labelString = XmStringLtoRCreate(message, XmSTRING_DEFAULT_CHARSET); X XtSetArg(infoLineArg`5B0`5D, XmNlabelString, labelString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X XmStringFree(labelString); X#else X labelString = DwtLatin1String(message); X XtSetArg(infoLineArg`5B0`5D, DwtNlabel, labelString); X XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X XtFree(labelString); X#endif X return; X`7D X X Xstatic void XsetBottomInfoLine(message) `20 Xchar *message; X`7B X Arg infoLineArg`5B1`5D; X#ifdef MOTIF X XmString labelString; X#else X DwtCompString labelString; X#endif X X (void) strcpy(BottomNonButtonInfo, (char *) message); X#ifdef MOTIF X labelString = XmStringLtoRCreate(message, XmSTRING_DEFAULT_CHARSET); X XtSetArg(infoLineArg`5B0`5D, XmNlabelString, labelString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X XmStringFree(labelString); X#else X labelString = DwtLatin1String(message); X XtSetArg(infoLineArg`5B0`5D, DwtNlabel, labelString); X XtSetValues(BottomInfoLine, infoLineArg, XtNumber(infoLineArg)); X XtFree(labelString); X#endif X return; X`7D X X#define TOP`090 X#define BOTTOM`091 X Xstatic void XdoButtons(resource, box, buttons, buttonList, size, infoLine) Xchar *resource; XWidget box; XWidget *buttons; XButtonList *buttonList; Xint *size; Xint infoLine; X`7B X char *ptr, *token, *savePtr; X int j, i = 0; X X if (resource) `7B X`09savePtr = ptr = XtNewString(resource); X X`09while ((token = strtok(ptr, ", \t\n")) != NIL(char)) `7B X`09 /* find name */ X`09 for (j = 0; j < *size; j++) `7B X`09`09if (STREQ(token, (char *) buttonList`5Bj`5D.buttonArgs`5B0`5D.value)) V `7B X#ifdef MOTIF X`09`09 if (buttonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09 buttonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)XmStringLtoRCreate(buttonList`5Bj`5D.label, X`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09`09 `7D X`09`09 buttons`5Bi`5D = XmCreatePushButton(box, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs, X`09`09`09`09`09 buttonList`5Bj`5D.size); X#else X`09`09 if (buttonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09 buttonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)DwtLatin1String(buttonList`5Bj`5D.label); X`09`09 `7D X`09`09 buttons`5Bi`5D = DwtPushButtonCreate(box, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs, X`09`09`09`09`09 buttonList`5Bj`5D.size); X#endif X`09`09 if (infoLine == TOP) `7B X`09`09`09setTopInfoLineHandler(buttons`5Bi`5D, buttonList`5Bj`5D.message); X`09`09 `7D else `7B X`09`09`09setBottomInfoLineHandler(buttons`5Bi`5D, buttonList`5Bj`5D.message) V; X`09`09 `7D X`09`09 i++; X`09`09 break; X`09`09`7D X`09 `7D X`09 if (j == *size) `7B X`09`09mesgPane(XRN_SERIOUS, "XRN error: bad button name: %s", token); X`09 `7D X`09 ptr = NIL(char); X`09`7D X`09*size = i; X`09XtFree(savePtr);`09 X `7D else `7B X`09for (i = 0; i < *size; i++) `7B X`09 `20 X#ifdef MOTIF X`09 if (buttonList`5Bi`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09buttonList`5Bi`5D.buttonArgs`5B1`5D.value = X`09`09 (XtArgVal)XmStringLtoRCreate(buttonList`5Bi`5D.label, X`09`09 XmSTRING_DEFAULT_CHARSET); X`09 `7D X`09 buttons`5Bi`5D = XmCreatePushButton(box, X`09`09`09`09buttonList`5Bi`5D.buttonArgs`5B0`5D.value, X`09`09`09`09buttonList`5Bi`5D.buttonArgs, X`09`09`09`09buttonList`5Bi`5D.size); X#else X`09 if (buttonList`5Bi`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09buttonList`5Bi`5D.buttonArgs`5B1`5D.value = X`09 `09 (XtArgVal)DwtLatin1String(buttonList`5Bi`5D.label); X`09 `7D X`09 buttons`5Bi`5D = DwtPushButtonCreate(box, X`09`09`09`09buttonList`5Bi`5D.buttonArgs`5B0`5D.value, X`09`09`09`09buttonList`5Bi`5D.buttonArgs, X`09`09`09`09buttonList`5Bi`5D.size); X#endif X`09 if (infoLine == TOP) `7B X`09`09setTopInfoLineHandler(buttons`5Bi`5D, buttonList`5Bi`5D.message); X`09 `7D else `7B X`09`09setBottomInfoLineHandler(buttons`5Bi`5D, buttonList`5Bi`5D.message); X`09 `7D X`09`7D X `7D X return; X`7D X X Xvoid XcreateButtons(mode) Xint mode; X`7B X#define SETTRANSLATIONS(w, index, mode, bind) \ X Translations`5Bindex`5D.widget = w; \ X Translations`5Bindex`5D.unparsed`5Bmode`5D = bind; X X int i; X X if (mode == -1) `7B X`09SETTRANSLATIONS(TopButtonBox, 0, ADD_MODE, app_resources.addBindings); X`09SETTRANSLATIONS(BottomButtonBox, 1, ADD_MODE, app_resources.addBindings); X`09SETTRANSLATIONS(TopInfoLine, 2, ADD_MODE, app_resources.addBindings); X`09SETTRANSLATIONS(BottomInfoLine, 3, ADD_MODE, app_resources.addBindings); X`09SETTRANSLATIONS(TopList, 4, ADD_MODE, app_resources.addBindings); X`09SETTRANSLATIONS(ArticleText, 5, ADD_MODE, app_resources.addBindings); X X`09SETTRANSLATIONS(TopButtonBox, 0, ALL_MODE, app_resources.allBindings); X`09SETTRANSLATIONS(BottomButtonBox, 1, ALL_MODE, app_resources.allBindings); X`09SETTRANSLATIONS(TopInfoLine, 2, ALL_MODE, app_resources.allBindings); X`09SETTRANSLATIONS(BottomInfoLine, 3, ALL_MODE, app_resources.allBindings); X`09SETTRANSLATIONS(TopList, 4, ALL_MODE, app_resources.allBindings); X`09SETTRANSLATIONS(ArticleText, 5, ALL_MODE, app_resources.allBindings); X X`09SETTRANSLATIONS(TopButtonBox, 0, NEWSGROUP_MODE, app_resources.ngBindings V); X`09SETTRANSLATIONS(BottomButtonBox, 1, NEWSGROUP_MODE, app_resources.ngBindi Vngs); X`09SETTRANSLATIONS(TopInfoLine, 2, NEWSGROUP_MODE, app_resources.ngBindings) V; X`09SETTRANSLATIONS(BottomInfoLine, 3, NEWSGROUP_MODE, app_resources.ngBindin Vgs); X`09SETTRANSLATIONS(TopList, 4, NEWSGROUP_MODE, app_resources.ngBindings); X`09SETTRANSLATIONS(ArticleText, 5, NEWSGROUP_MODE, app_resources.ngBindings) V; X X`09SETTRANSLATIONS(TopButtonBox, 0, ARTICLE_MODE, app_resources.artBindings) V; X`09SETTRANSLATIONS(BottomButtonBox, 1, ARTICLE_MODE, app_resources.artBindin Vgs); X`09SETTRANSLATIONS(TopInfoLine, 2, ARTICLE_MODE, app_resources.artBindings); X`09SETTRANSLATIONS(BottomInfoLine, 3, ARTICLE_MODE, app_resources.artBinding Vs); X`09SETTRANSLATIONS(TopList, 4, ARTICLE_MODE, app_resources.artBindings); X`09SETTRANSLATIONS(ArticleText, 5, ARTICLE_MODE, app_resources.artBindings); X X`09XtAddActions(TopActions, XtNumber(TopActions)); X X`09AddButtons = ARRAYALLOC(Widget, XtNumber(AddButtonList)); X`09XtAddActions(AddActions, XtNumber(AddActions)); X X`09doButtons(app_resources.addButtonList, TopButtonBox, AddButtons, X`09`09AddButtonList, &AddButtonListCount, TOP); X X`09NgButtons = ARRAYALLOC(Widget, XtNumber(NgButtonList)); X`09XtAddActions(NgActions, XtNumber(NgActions)); X `20 X`09doButtons(app_resources.ngButtonList, TopButtonBox, NgButtons, X`09`09NgButtonList, &NgButtonListCount, TOP); X X`09AllButtons = ARRAYALLOC(Widget, XtNumber(AllButtonList)); X`09XtAddActions(AllActions, XtNumber(AllActions)); X `20 X`09doButtons(app_resources.allButtonList, TopButtonBox, AllButtons, X`09`09AllButtonList, &AllButtonListCount, TOP); X `20 X`09ArtButtons = ARRAYALLOC(Widget, XtNumber(ArtButtonList)); X`09XtAddActions(ArtActions, XtNumber(ArtActions)); X `20 X`09doButtons(app_resources.artButtonList, TopButtonBox, ArtButtons, X`09`09ArtButtonList, &ArtButtonListCount, TOP); X `20 X`09ArtSpecButtons = ARRAYALLOC(Widget, XtNumber(ArtSpecButtonList)); X `20 X`09doButtons(app_resources.artSpecButtonList, BottomButtonBox, X`09`09ArtSpecButtons, ArtSpecButtonList, &ArtSpecButtonListCount, BOTTOM); X X`09XtAddCallback(TopList, SListNselectCallback, listSelect,0); X`09XtAddCallback(TopList, SListNdoubleClickCallback, DoubleClick,0); X `7D X if (mode == ADD_MODE) `7B X`09XtUnmanageChildren(AddButtons, AddButtonListCount); X`09for (i=0; i < AddButtonListCount; i++) `7B X`09 XtDestroyWidget(AddButtons`5Bi`5D); X`09`7D X`09AddButtonListCount = XtNumber(AddButtonList); X`09doButtons(app_resources.addButtonList, TopButtonBox, AddButtons, X`09`09AddButtonList, &AddButtonListCount, TOP); X`09if (Mode == ADD_MODE) `7B X`09 XtManageChildren(AddButtons, AddButtonListCount); X`09`7D X `7D X if (mode == ALL_MODE) `7B X`09XtUnmanageChildren(AllButtons, AllButtonListCount); X`09for (i=0; i < AllButtonListCount; i++) `7B X`09 XtDestroyWidget(AllButtons`5Bi`5D); X`09`7D X`09AllButtonListCount = XtNumber(AllButtonList); X`09doButtons(app_resources.allButtonList, TopButtonBox, AllButtons, X`09`09AllButtonList, &AllButtonListCount, TOP); X`09if (Mode == ALL_MODE) `7B X`09 XtManageChildren(AllButtons, AllButtonListCount); X`09`7D X `7D X if (mode == ARTICLE_MODE) `7B X`09XtUnmanageChildren(ArtButtons, ArtButtonListCount); X`09for (i=0; i < ArtButtonListCount; i++) `7B X`09 XtDestroyWidget(ArtButtons`5Bi`5D); X`09`7D X`09ArtButtonListCount = XtNumber(ArtButtonList); X`09doButtons(app_resources.artButtonList, TopButtonBox, ArtButtons, X`09`09ArtButtonList, &ArtButtonListCount, TOP); X`09if (Mode == ARTICLE_MODE) `7B X`09 XtManageChildren(ArtButtons, ArtButtonListCount); X`09`7D X `7D X if (mode == NEWSGROUP_MODE) `7B X`09XtUnmanageChildren(NgButtons, NgButtonListCount); X`09for (i=0; i < NgButtonListCount; i++) `7B X`09 XtDestroyWidget(NgButtons`5Bi`5D); X`09`7D X`09NgButtonListCount = XtNumber(NgButtonList); X`09doButtons(app_resources.ngButtonList, TopButtonBox, NgButtons, X`09`09NgButtonList, &NgButtonListCount, TOP); X`09if (Mode == NEWSGROUP_MODE) `7B X`09 XtManageChildren(NgButtons, NgButtonListCount); X`09`7D X `7D X return; X`7D X Xstatic void XsetTranslations(mode) Xint mode; X`7B X Arg args`5B1`5D; X static int init`5BMAX_MODE`5D = `7B0,0,0,0`7D; X int i; X X if (!init`5Bmode`5D) `7B X`09/* X`09 * first time: X`09 * parse table X`09 * override X`09 * get table back and store X`09 */ X`09for (i = 0; i < sizeof(Translations) / sizeof(struct _translations); i++) V `7B X`09 XtTranslations table; X X`09 if (Translations`5Bi`5D.unparsed`5Bmode`5D == NIL(char)) `7B X`09`09table = 0; X`09 `7D else `7B X`09 table = XtParseTranslationTable(Translations`5Bi`5D.unparsed`5Bmo Vde`5D); X`09 `7D X#ifndef MOTIF X`09 XtSetArg(args`5B0`5D, XtNtranslations, 0); X`09 XtGetValues(Translations`5Bi`5D.widget, args, XtNumber(args)); X`09 if ((XtTranslations) args`5B0`5D.value == (XtTranslations) 0) `7B X`09`09if (table) `7B X`09`09 XtSetArg(args`5B0`5D, XtNtranslations, table); X`09`09 XtSetValues(Translations`5Bi`5D.widget, args, XtNumber(args)); X`09`09`7D X`09 `7D X#endif /* MOTIF */ X`09 if (table) `7B X`09 XtOverrideTranslations(Translations`5Bi`5D.widget, table); X`09 `7D X`09 XtSetArg(args`5B0`5D, XtNtranslations, 0); X`09 XtGetValues(Translations`5Bi`5D.widget, args, XtNumber(args)); X`09 Translations`5Bi`5D.tables`5Bmode`5D = (XtTranslations) args`5B0`5D.v Value; X`09`7D X`09init`5Bmode`5D = 1; X `7D else `7B X`09/* X`09 * second and future times: X`09 * install translations X`09 */ X`09for (i = 0; i < sizeof(Translations) / sizeof(struct _translations); i++) V `7B X`09 if (Translations`5Bi`5D.tables`5Bmode`5D != (XtTranslations) NULL) `7 VB X#ifndef MOTIF X`09 XtSetArg(args`5B0`5D, XtNtranslations, Translations`5Bi`5D.tables V`5Bmode`5D); X`09 XtSetValues(Translations`5Bi`5D.widget, args, XtNumber(args)); X#else X`09`09XtOverrideTranslations(Translations`5Bi`5D.widget, Translations`5Bi`5D V.tables`5Bmode`5D); X#endif X`09 `7D X`09`7D X `7D X return; X`7D X Xstatic void XswapMode() X/* X * change the buttons displayed in the TopButtonBox (switch modes) X */ X`7B X Arg resizeArg`5B1`5D; X Arg testArgs`5B1`5D; X int y; X Dimension min, max; X static int buttonHeight = 0; X int windowWidth; X X if (PreviousMode == Mode) `7B X`09return; X `7D X if (buttonHeight == 0) `7B X`09if (ArtSpecButtonListCount > 0) `7B X#ifdef MOTIF X`09 XtSetArg(resizeArg`5B0`5D, XmNheight, &buttonHeight); X#else X`09 XtSetArg(resizeArg`5B0`5D, DwtNheight, &buttonHeight); X#endif X`09 XtGetValues(ArtSpecButtons`5B0`5D, resizeArg, 1); X`09 buttonHeight += 2;`09/* allow for margins */ X`09`7D else `7B X`09 if (ArtButtonListCount > 0) `7B X#ifdef MOTIF X`09`09XtSetArg(resizeArg`5B0`5D, XmNheight, &buttonHeight); X#else X`09`09XtSetArg(resizeArg`5B0`5D, DwtNheight, &buttonHeight); X#endif X`09`09XtGetValues(ArtButtons`5B0`5D, resizeArg, 1); X`09`09buttonHeight += 2;`09/* allow for margins */ X`09 `7D else `7B X`09`09buttonHeight = 10; X`09 `7D X`09`7D X#ifdef MOTIF X`09PaneSetMinMax(BottomButtonBox, buttonHeight + 6, buttonHeight + 6); X#else X`09DwtPaneSetMinMax(BottomButtonBox, buttonHeight + 6, buttonHeight + 6); X#endif X `7D X `20 X y = 0; X /* X * NONE -> ADD X * manage add in top box X * manage art in bottom box X * desensitize bottom box X * install add actions in top box X */ X if ((PreviousMode == NO_MODE) && (Mode == ADD_MODE)) `7B X`09XtManageChildren(AddButtons, AddButtonListCount); X`09XtManageChildren(AddPopupButtons, AddPopupCount); X`09XtManageChildren(ArtSpecButtons, ArtSpecButtonListCount); X`09XtSetSensitive(BottomButtonBox, False); X`09setTranslations(ADD_MODE); X`09if (AddButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(AddButtons`5BAddButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtManageChildren(addMenus, XtNumber(addMenus)); X X /* `20 X * NONE -> NG X * manage ng in top box X * manage art in bottom box X * desensitize bottom box X * install ng actions in top box X */ X `7D else if ((PreviousMode == NO_MODE) && (Mode == NEWSGROUP_MODE)) `7B X`09XtManageChildren(NgButtons, NgButtonListCount); X`09XtManageChildren(NgPopupButtons, NgPopupCount); X`09XtManageChildren(ArtSpecButtons, ArtSpecButtonListCount); X`09XtSetSensitive(BottomButtonBox, False); X`09setTranslations(NEWSGROUP_MODE); X`09if (NgButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(NgButtons`5BNgButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(ngMenus, XtNumber(ngMenus)); X /* X * ADD -> NG X * unmanage add in top box X * manage ng in top box X * install ng actions in top box X */ X `7D else if ((PreviousMode == ADD_MODE) && (Mode == NEWSGROUP_MODE)) `7B X`09XtUnmanageChildren(AddButtons, AddButtonListCount); X`09XtUnmanageChildren(AddPopupButtons, AddPopupCount); X`09resetPopupSize(); X`09XtManageChildren(NgButtons, NgButtonListCount); X`09XtManageChildren(NgPopupButtons, NgPopupCount); X`09setTranslations(NEWSGROUP_MODE); X`09if (NgButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(NgButtons`5BNgButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(ngMenus, XtNumber(ngMenus)); X /* X * NG -> ART X * unmanage ng in top box X * manage art in top box X * sensitize bottom box X * install art actions in top box X * install art actions in bottom box X */ X `7D else if ((PreviousMode == NEWSGROUP_MODE) && (Mode == ARTICLE_MODE)) V `7B X`09XtUnmanageChildren(NgButtons, NgButtonListCount); X`09XtUnmanageChildren(NgPopupButtons, NgPopupCount); X`09resetPopupSize(); X`09XtManageChildren(ArtButtons, ArtButtonListCount); X`09XtManageChildren(ArtPopupButtons, ArtPopupCount); X`09XtSetSensitive(BottomButtonBox, True); X`09setTranslations(ARTICLE_MODE); X`09if (ArtButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(ArtButtons`5BArtButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtManageChildren(artMenus, XtNumber(artMenus)); X /* X * NG -> ADD X * unmanage ng in top box X * manage add in top box X * install add actions in top box X */ X `7D else if ((PreviousMode == NEWSGROUP_MODE) && (Mode == ADD_MODE)) `7B X`09XtUnmanageChildren(NgButtons, NgButtonListCount); X`09XtUnmanageChildren(NgPopupButtons, NgPopupCount); X`09resetPopupSize(); X`09XtManageChildren(AddButtons, AddButtonListCount); X`09XtManageChildren(AddPopupButtons, AddPopupCount); X`09setTranslations(ADD_MODE); X`09if (AddButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(AddButtons`5BAddButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtManageChildren(addMenus, XtNumber(addMenus)); X /* X * NG -> ALL X * desensitize top box X * unmanage art in bottom box X * manage all in bottom box X * sensitize bottom box X * install all actions in bottom box X */ X `7D else if ((PreviousMode == NEWSGROUP_MODE) && (Mode == ALL_MODE)) `7B X`09XtSetSensitive(BottomButtonBox, False); X`09XtUnmanageChildren(NgButtons, NgButtonListCount); X`09XtUnmanageChildren(NgPopupButtons, NgPopupCount); X`09resetPopupSize(); X`09XtManageChildren(AllButtons, AllButtonListCount); X`09XtManageChildren(AllPopupButtons, AllPopupCount); X`09XtSetSensitive(TopButtonBox, True); X`09setTranslations(ALL_MODE); X`09if (AllButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(AllButtons`5BAllButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(allMenus, XtNumber(allMenus)); X /* `20 X * ART -> NG X * desensitize bottom box X * unmanage art in top box X * manage ng in top box X * install ng actions in top box X */ X `7D else if ((PreviousMode == ARTICLE_MODE) && (Mode == NEWSGROUP_MODE)) V `7B X`09XtSetSensitive(BottomButtonBox, False); X`09XtUnmanageChildren(ArtButtons, ArtButtonListCount); X`09XtUnmanageChildren(ArtPopupButtons, ArtPopupCount); X`09resetPopupSize(); X`09XtManageChildren(NgButtons, NgButtonListCount); X`09XtManageChildren(NgPopupButtons, NgPopupCount); X`09setTranslations(NEWSGROUP_MODE); X`09if (NgButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(NgButtons`5BNgButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtManageChildren(ngMenus, XtNumber(ngMenus)); X /* X * ALL -> NG X * sensitize top box X * unmanage all in bottom box X * manage art in bottom box X * desensitize bottom box X */ X `7D else if ((PreviousMode == ALL_MODE) && (Mode == NEWSGROUP_MODE)) `7B X`09XtSetSensitive(TopButtonBox, True); X`09XtUnmanageChildren(AllButtons, AllButtonListCount); X`09XtUnmanageChildren(AllPopupButtons, AllPopupCount); X`09resetPopupSize(); X`09XtManageChildren(NgButtons, NgButtonListCount); X`09XtManageChildren(NgPopupButtons, NgPopupCount); X`09XtSetSensitive(BottomButtonBox, False); X`09setTranslations(NEWSGROUP_MODE); X`09if (NgButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(NgButtons`5BNgButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(ngMenus, XtNumber(ngMenus)); X /* X * ART -> ALL (going back to previous ALL_MODE) X * unmanage art in bottom box X * unmanage art in top box X * manage all in bottom box X * manage ng in top box X * desensitize top box X * install all actions in bottom box X */ X `7D else if ((PreviousMode == ARTICLE_MODE) && (Mode == ALL_MODE)) `7B X`09XtSetSensitive(BottomButtonBox, False); X`09XtUnmanageChildren(ArtButtons, ArtButtonListCount); X`09XtUnmanageChildren(ArtPopupButtons, ArtPopupCount); X`09resetPopupSize(); X`09XtManageChildren(AllButtons, AllButtonListCount); X`09XtManageChildren(AllPopupButtons, AllPopupCount); X`09XtSetSensitive(TopButtonBox, True); X`09setTranslations(ALL_MODE); X`09if (AllButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(AllButtons`5BAllButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtUnmanageChildren(artMenus, XtNumber(artMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(allMenus, XtNumber(allMenus)); X /*`09 X * ALL -> ART X * unmanage ng in top box X * sensitize top box X * manage art in top box X * unmanage all in bottom box X * manage art in bottom box X * install art actions in bottom box X */ X `7D else if ((PreviousMode == ALL_MODE) && (Mode == ARTICLE_MODE)) `7B X`09XtSetSensitive(TopButtonBox, True); X`09XtUnmanageChildren(AllButtons, AllButtonListCount); X`09XtUnmanageChildren(AllPopupButtons, AllPopupCount); X`09resetPopupSize(); X`09XtUnmanageChildren(NgButtons, NgButtonListCount); X`09XtUnmanageChildren(NgPopupButtons, NgPopupCount); X`09XtManageChildren(ArtButtons, ArtButtonListCount); X`09XtManageChildren(ArtPopupButtons, ArtPopupCount); X`09XtManageChildren(ArtSpecButtons, ArtSpecButtonListCount); X`09XtSetSensitive(BottomButtonBox, True); X`09setTranslations(ARTICLE_MODE); X`09if (ArtButtonListCount > 0) `7B X`09 XtSetArg(testArgs`5B0`5D, XtNy, &y); X`09 XtGetValues(ArtButtons`5BArtButtonListCount-1`5D, testArgs, X`09`09`09XtNumber(testArgs)); X`09 min = max = y + buttonHeight + 6; X`09`7D else `7B X`09 min = 1; max = 1; X`09`7D X`09XtUnmanageChildren(ngMenus, XtNumber(ngMenus)); X`09XtUnmanageChildren(allMenus, XtNumber(allMenus)); X`09XtUnmanageChildren(addMenus, XtNumber(addMenus)); X`09XtManageChildren(artMenus, XtNumber(artMenus)); X X `7D else `7B X`09(void) sprintf(error_buffer, "unsupported transition: %d to %d\n", X`09`09`09 PreviousMode, Mode); X`09ehErrorExitXRN(error_buffer); X `7D X `20 X#ifdef MOTIF X if (min == 1 && max == 1) `7B X`09PaneSetMinMax(TopButtonBox, min, max); X `7D else `7B X`09if (max != 0 && min != 0) `7B X`09 min -= 6; X`09 max -= 6; X`09 PaneSetMinMax(TopButtonBox, min ,max); X`09`7D X `7D X#ifdef MOTIF_V1_0 X XtSetArg(resizeArg`5B0`5D, XmNrefigureMode, False); X XtSetValues(XtParent(TopButtonBox), resizeArg, 1); X XtSetArg(resizeArg`5B0`5D, XmNrefigureMode, True); X XtSetValues(XtParent(TopButtonBox), resizeArg, 1); X#endif X#else X if (max != 0 && min != 0) `7B X`09DwtPaneSetMinMax(TopButtonBox, min ,max); X `7D X#endif X return; X`7D X X Xstatic int XRNAbort = 0; X Xint XabortP() X`7B X xthHandleAllPendingEvents(); X return XRNAbort; X`7D X Xvoid XabortSet() X`7B X XRNAbort = 1; X return; X`7D X Xvoid XabortClear() X`7B X XRNAbort = 0; X return; X`7D X X#ifdef MOTIF XBoolean XmTextPosToXY(); Xstatic Boolean ScrollDownOnePage(w) XWidget w; X`7B X XmTextWidget widget = (XmTextWidget) w; X int n; X int x, y; X X if (XmTextPosToXY(w, XmTextGetLastPosition(w), &x, &y)) X`09return TRUE; X X#ifdef MOTIF_V1_0 X XmTextDisableRedisplay(widget, FALSE); X n = XmTextNumLines(widget); X#else X _XmTextDisableRedisplay(widget, FALSE); X n = _XmTextNumLines(widget); X#endif X if (n > 1) n--; X XmTextScroll(widget, n); X#ifdef MOTIF_V1_0 X XmTextEnableRedisplay(widget); X#else X _XmTextEnableRedisplay(widget); X#endif X return FALSE; X`7D Xstatic Boolean ScrollUpOnePage(w) XWidget w; X`7B X XmTextWidget widget = (XmTextWidget) w; X int n; X int x, y; X X if (XmTextPosToXY(w, 0, &x, &y)) X`09return TRUE; X X#ifdef MOTIF_V1_0 X XmTextDisableRedisplay(widget, FALSE); X n = XmTextNumLines(widget); X#else X _XmTextDisableRedisplay(widget, FALSE); X n = _XmTextNumLines(widget); X#endif X if (n > 1) n--; X XmTextScroll(widget, -n); X#ifdef MOTIF_V1_0 X XmTextEnableRedisplay(widget); X#else X _XmTextEnableRedisplay(widget); X#endif X return FALSE; X`7D X#else Xextern Boolean DwtTextPosToXY(); Xstatic Boolean ScrollDownOnePage(w) XWidget w; X`7B X int n = 0; X int x, y; X Arg rowArg`5B1`5D; X `20 X if (DwtTextPosToXY(w, DwtSTextGetLastPosition(w), &x, &y)) X`09return TRUE; X X XtSetArg(rowArg`5B0`5D, DwtNrows, (XtArgVal) &n); X XtGetValues(w, rowArg, 1); X if (n > 1) n--; X DwtTextDisableRedisplay(w, FALSE); X (void) DwtTextScroll(w, n); X DwtTextEnableRedisplay(w); X return FALSE; X`7D Xstatic Boolean ScrollUpOnePage(w) XWidget w; X`7B X int n = 0; X int x, y; X Arg rowArg`5B1`5D; X `20 X if (DwtTextPosToXY(w, 0, &x, &y)) X`09return TRUE; X X XtSetArg(rowArg`5B0`5D, DwtNrows, (XtArgVal) &n); X XtGetValues(w, rowArg, 1); X if (n > 1) n--; X DwtTextDisableRedisplay(w, FALSE); X (void) DwtTextScroll(w, -n); X DwtTextEnableRedisplay(w); X return FALSE; X`7D X#endif /* MOTIF */ X X/*ARGSUSED*/ Xstatic void XdoTheRightThing(widget, event, string, count) XWidget widget; XXEvent *event; XString *string; XCardinal count; X`7B X void ngReadFunction(), ngOpenFunction(), artScrollFunction(); X void artNextFunction(), artNextUnreadFunction(), artSubNextFunction(); X void allScrollFunction(); X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X switch (Mode) `7B X`09case ALL_MODE: X`09allScrollFunction((Widget) 0); X`09break; X X`09case NEWSGROUP_MODE: X`09if (string && (count == 1) && strcmp(string`5B0`5D, "jump") == 0) `7B X`09 NewsgroupEntryMode = XRN_JUMP; X`09`7D X`09if (app_resources.autoRead) `7B X`09 ngReadFunction((Widget) 0); X`09`7D else `7B X`09 ngOpenFunction((Widget) 0); X`09`7D X`09break; X X`09case ARTICLE_MODE: X`09if (event && X`09 (event->type == ButtonPress `7C`7C event->type == ButtonRelease)) `7B X`09 artNextFunction((Widget) 0); X`09 break; X`09`7D X`09artScrollFunction((Widget) 0); X`09break; X `7D X unbusyCursor(); X inCommand = 0; X return; X`7D X X Xvoid XupdateSubjectWidget(start, end) X/* X * Redraw the items between start and end in the subject list; X * Adjust the window so the cursor is between min and max lines. X */ Xint`09start; Xint`09end; X`7B X int i; X `20 X if (start < 0) start = 0; X if (end > SubjectItems) end = SubjectItems; X for (i=start; i 0) ArtPosition--; X`09 *artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 gotoArticle(*artNum); X`09 subjSetPos(TopList, ArtPosition); X`09`7D X`09return art_CHANGE; X `7D X X if (status == art_NEXT) `7B X`09ArtPosition++; X`09if (ArtPosition >= SubjectItems `7C`7C`20 X`09`09SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09 ArtPosition = SubjectItems - 1; X`09 return art_DONE; X`09`7D X`09*artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09gotoArticle(*artNum); X`09subjSetPos(TopList, ArtPosition); X`09while (getArticleText(filename, question) != XRN_OKAY) `7B X`09 resetSubjectWidget(UNREAD, False); X`09 if (ArtPosition > 0) ArtPosition--; X`09 if (SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09`09return art_DONE; X`09 `7D X`09 *artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 gotoArticle(*artNum);`20 X`09 subjSetPos(TopList, ArtPosition); X`09`7D X`09return art_CHANGE; X `7D X if (status == art_CURRENT) `7B X`09if (ArtPosition < 0 `7C`7C ArtPosition > SubjectItems) `7B X`09 ArtPosition = 0; X`09 return art_DONE; X`09`7D X`09*artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09gotoArticle(*artNum); X`09subjSetPos(TopList, ArtPosition); X`09while (getArticleText(filename, question) != XRN_OKAY) `7B X`09 resetSubjectWidget(UNREAD, False); X`09 if (ArtPosition > 0) ArtPosition--; X`09 if (SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09`09if (ArtPosition == 0) `7B X`09`09 return art_DONE; X`09`09`7D X`09`09ArtPosition = 0; X`09 `7D X`09 *artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 gotoArticle(*artNum);`20 X`09 subjSetPos(TopList, ArtPosition); X`09`7D X`09return art_CHANGE; X `7D X if (status == art_UNREAD) `7B X`09if (ArtPosition < 0) ArtPosition = 0; X`09if (ArtPosition >= SubjectItems `7C`7C`20 X`09`09SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09 if (ArtPosition == 0) `7B X`09`09return art_DONE; X`09 `7D X`09 ArtPosition = 0; X`09`7D X`09beginning = ArtPosition; X`09if (SubjectStrings`5BArtPosition`5D`5B0`5D != ' ') `7B X`09 ArtPosition++; X`09 if (ArtPosition >= SubjectItems) `7B X`09`09return art_DONE; X`09 `7D X`09 while ((SubjectStrings`5BArtPosition`5D`5B0`5D != ' ') && X`09`09 (ArtPosition != beginning)) `7B X`09`09ArtPosition++; X`09 if (ArtPosition >= SubjectItems) `7B X`09`09 return art_DONE; X`09`09`7D X`09 `7D X`09 if (ArtPosition == beginning) `7B X`09`09return art_DONE; X`09 `7D X`09`7D X`09/* we are at an unread article */ X`09*artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09gotoArticle(*artNum); X`09subjSetPos(TopList, ArtPosition); X`09while (getArticleText(filename, question) != XRN_OKAY) `7B X`09 resetSubjectWidget(UNREAD, False); X`09 if (ArtPosition > 0) ArtPosition--; X`09 if (ArtPosition >= SubjectItems `7C`7C X`09`09 SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09`09if (ArtPosition == 0) `7B X`09`09 return art_DONE; X`09`09`7D X`09`09ArtPosition = 0; X`09 `7D X`09 while ((SubjectStrings`5BArtPosition`5D`5B0`5D != ' ') && X`09`09 (ArtPosition != beginning)) `7B X`09`09ArtPosition++; X`09`09if (ArtPosition >= SubjectItems) `7B X`09`09 return art_DONE; X`09`09`7D X`09 `7D X`09 if (ArtPosition == beginning) `7B X`09`09return art_DONE; X`09 `7D X`09 *artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 gotoArticle(*artNum);`20 X`09 subjSetPos(TopList, ArtPosition); X`09`7D X`09return art_CHANGE; X `7D X return art_CHANGE; X`7D X X X#define CHANGE 0`09`09/* subject window has changed */ X#define NOCHANGE 1`09`09/* subject window has not changed */ X#define DONE 2`09`09`09/* no new article was found */ X`09`09`09`09/* EXIT is already defined, it implies */ X`09`09`09`09/* there are no articles left at all */ X Xstatic int XisPrevSubject(subject, filename, question, artNum) Xchar *subject; Xchar **filename, **question; Xlong *artNum; X/* X * X */ X`7B X char *newsubject; X char *newLine; X char *newSubjectString; X int save; X X save = ArtPosition; X startSearch(); X abortClear(); X `20 X for (;;) `7B X`09if (abortP()) `7B X`09 failedSearch(); X`09 ArtPosition = save; X`09 return ABORT; X`09`7D X`09if (ArtPosition >= SubjectItems `7C`7C X`09 SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09 ArtPosition = SubjectItems - 1; X`09`7D X`09if (ArtPosition > 0) `7B X`09 ArtPosition--; X`09 *artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 newsubject = getSubject(*artNum); X`09 gotoArticle(*artNum); X`09 if (utSubjectCompare(newsubject, subject) == 0) `7B X`09`09gotoArticle(*artNum); X`09`09subjSetPos(TopList, ArtPosition); X`09`09if (getArticleText(filename, question) != XRN_OKAY) `7B X`09`09 resetSubjectWidget(UNREAD, False); X`09`09 if (ArtPosition > 0) ArtPosition--; X`09`09 continue; X`09`09`7D X`09`09if (SubjectStrings`5BArtPosition`5D`5B0`5D == 'u') `7B X`09`09 markArticleAsUnread(*artNum); X`09`09`7D X`09`09return NOCHANGE; X`09 `7D X`09 continue; X`09`7D else `7B X`09 if ((newLine = getPrevSubject()) == NIL(char)) `7B X`09`09failedSearch(); X`09`09ArtPosition = save; X`09`09return DONE; X`09 `7D X`09 newLine`5B0`5D = '+'; X`09 *artNum = atol(&newLine`5B2`5D); X`09 newsubject = getSubject(*artNum); X`09 if (utSubjectCompare(newsubject, subject) == 0) `7B X`09`09/* found a match, go with it*/ X`09`09gotoArticle(*artNum); X`09`09subjSetPos(TopList, ArtPosition); X`09`09(void) getArticleText(filename, question); X`09`09return CHANGE; X`09 `7D X`09 continue; X`09`7D X `7D X`7D X X Xstatic int XisNextSubject(subject, filename, question, artNum) Xchar *subject; Xchar **filename, **question; Xlong *artNum; X/* X * X */ X`7B X char *newsubject; X int save = ArtPosition; X X abortClear(); X `20 X if (ArtPosition != 0 `7C`7C (SubjectItems > 0 && SubjectStrings`5B0`5D`5 VB0`5D == '+')) `7B X`09ArtPosition++; X `7D X for (;;) `7B X X`09if (abortP()) `7B X`09 failedSearch(); X`09 ArtPosition = save; X`09 return ABORT; X`09`7D X`09if (ArtPosition >= SubjectItems) `7B X`09 ArtPosition = save; X`09 return DONE; X`09`7D X`09*artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09newsubject = getSubject(*artNum); X`09if (utSubjectCompare(newsubject, subject) == 0) `7B X`09 gotoArticle(*artNum); X`09 subjSetPos(TopList, ArtPosition); X`09 if (getArticleText(filename, question) != XRN_OKAY) `7B X`09`09resetSubjectWidget(UNREAD, False); X`09`09if (ArtPosition > 0) ArtPosition--; X`09 `7D X`09 return NOCHANGE; X`09`7D else `7B X`09 ArtPosition++; X`09`7D X `7D X`7D X X Xstatic int XgetPrevious(artNum) Xint *artNum; X/* X *`20 X */ X`7B X char *newLine; X if ((newLine = getPrevSubject()) != NIL(char)) `7B X`09resetSubjectWidget(ALL, False); X`09ArtPosition = 0; X`09*artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09return TRUE; X `7D X return FALSE; X`7D X Xstatic void XredrawAllWidget(position) Xint position; X/* X * Redraw the all groups window, assuming it has changed X */ X`7B X int i; X if (Mode != ALL_MODE) `7B X`09return; X `7D X X AllGroupsStrings = getStatusString(AllStatus); X X for (AllGroupItems = 0; AllGroupsStrings`5BAllGroupItems`5D != NIL(char) V; X`09 AllGroupItems++); X X SListLoad(TopList, AllGroupsStrings, AllGroupItems); X currentTop = 0; X resetSelection(); X subjSetPos(TopList, position); X return; X`7D X X Xstatic void XredrawNewsgroupListWidget() X/* X * Rebuild the newsgroup list window. X * Find out what groups have articles to read and build up the string. X * Create a string source and display it. X */ X`7B X char name`5BGROUP_NAME_SIZE`5D; X int i; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X X if (NewsGroups != NIL(char *)) `7B X`09for (i = 0; NewsGroups`5Bi`5D != NIL(char); i++)`20 X`09 FREE(NewsGroups`5Bi`5D); X`09FREE(NewsGroups); X`09NewsGroups = (char**)0; X `7D X X NewsGroups = unreadGroups(NewsgroupDisplayMode); X X /* update the info line */ X X if (NewsGroups == (char**)0 `7C`7C utStrlen(NewsGroups`5B0`5D) == 0) `7B X`09setTopInfoLine("No more unread articles in the subscribed to newsgroups") V; X if (XtIsRealized(TopLevel)) X`09 XSetIconName(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09`09 app_resources.iconName); X `7D else `7B X if (XtIsRealized(TopLevel)) `7B X`09 XSetIconName(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09`09 app_resources.unreadIconName); X`09`7D X `7D X `20 X GroupItems = 0; X for (i=0;NewsGroups`5Bi`5D != '\0';i++) `7B X`09GroupItems++; X `7D X if (GroupItems > 0) `7B X`09if (GroupPosition >= GroupItems) GroupPosition = 0; X`09if (NewsGroups`5BGroupPosition`5D == '\0') `7B X`09 GroupPosition = 0; X`09`7D X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09if (STREQ(name, LastGroup)) `7B X`09 GroupPosition++; X`09 if (GroupPosition >= GroupItems) X`09`09GroupPosition = 0; X`09`7D X `7D else `7B X`09setTopInfoLine("No more unread articles in the subscribed to newsgroups") V; X `7D X `20 X SListLoad(TopList, NewsGroups, GroupItems); X currentTop = 0; X subjSetPos(TopList, GroupPosition); X SelectionItem = -1; X SelectionCount = 0; X selCount = 0; X return; X`7D X Xstatic void XupdateNewsgroupMode() X/* X * update the info line and update the newsgroup text window X */ X`7B X if (PreviousMode != NEWSGROUP_MODE) `7B X`09setTopInfoLine("Questions apply to current selection or cursor position") V; X `7D X redrawNewsgroupListWidget(); X subjSetPos(TopList, GroupPosition); X SelectionItem = -1; X SelectionCount = 0; X selCount = 0; X return; X`7D X X Xstatic void XswitchToNewsgroupMode() X/* X * install the newsgroup mode buttons (and the delete the previous mode butt Vons) X * and then go to newsgroup mode X */ X`7B X PreviousMode = Mode; X Mode = NEWSGROUP_MODE; X LastRegexp = NIL(char); X X resetSelection(); X X /* switch buttons */ X swapMode(); X `20 X /* update the newsgroup mode windows */ X updateNewsgroupMode(); X `20 X return; X`7D X X Xstatic int XswitchToArticleMode(readFlag) XBoolean readFlag; X/* X * install the article mode buttons (and delete the previous mode buttons), X * build the subject line screen, and call art mode function 'next unread' X */ X`7B X int i; X int`09 oldMode; X /* change the list window */ X X SubjectStrings = getSubjects(UNREAD); X X ArtPosition = 0; X if ((SubjectStrings == (char**)0) `7C`7C (*SubjectStrings`5B0`5D == '\0' V)) `7B X/* X * No articles. report bogus group and X * redetermine mode X */ X`09bogusNewsgroup(); X`09SubjectItems = 0; X`09determineMode(); X`09return BAD_GROUP; X `7D X X oldMode = PreviousMode; X PreviousMode = Mode; X Mode = ARTICLE_MODE; X X /* switch buttons */ X swapMode(); X X X /* X * "What's the purpose of this?" you're saying. "It looks wrong." X * Well, try taking out any mention of oldMode in this function, X * then recompile and do the following: X * 1. Enter article mode X * 2. Clock "Next Newsgroup". X * 3. Click "Quit". X * You will be returned to all mode instead of article mode. X * Therefore, we've got to keep track in this function of whether X * we're switching from article mode to article mode, and if so, X * set PreviousMode truly in order for swapMode to work, but once X * that's done, we can put it back to what it was before). X */ X if (PreviousMode == ARTICLE_MODE) `7B X`09PreviousMode = oldMode; X `7D X /* get and display the article */ X ArtPosition = 0; X for (SubjectItems = 0; X`09 SubjectStrings`5BSubjectItems`5D != NIL(char) &&`20 X`09 SubjectStrings`5BSubjectItems`5D`5B0`5D != '\0'; X`09 SubjectItems++); X SListLoad(TopList, SubjectStrings, SubjectItems); X currentTop = 0; X updateSubjectWidget(0, 0); X ArtEntry = 1; X if (readFlag) `7B X`09artNextUnreadFunction((Widget) 0); X `7D X return GOOD_GROUP; X`7D X Xstatic void XresetSubjectWidget(artstatus, emptyOK) X/* X * rebuild the subject list widget X */ X int artstatus; X Boolean emptyOK; X`7B X int `09i; X /* change the list window */ X X if (SubjectStrings != NIL(char *)) `7B X`09for (i = 0; i < SubjectItems; i++) `7B X`09 if (SubjectStrings`5Bi`5D != NULL) X`09 FREE(SubjectStrings`5Bi`5D); X`09`7D X`09FREE(SubjectStrings); X `7D X X SubjectStrings = getSubjects(artstatus); X X if ((SubjectStrings == (char**)0) `7C`7C (*SubjectStrings`5B0`5D == '\0' V)) `7B X`09if (!emptyOK) X`09 bogusNewsgroup(); X`09SubjectItems = 0; X`09return; X `7D X X for (SubjectItems = 0; X`09 SubjectStrings`5BSubjectItems`5D != NIL(char) &&`20 X`09 SubjectStrings`5BSubjectItems`5D`5B0`5D != '\0'; X`09 SubjectItems++); X SListLoad(TopList, SubjectStrings, SubjectItems); X currentTop = 0; X X if (ArtPosition >= SubjectItems) X`09ArtPosition = SubjectItems - 1; X return; X`7D X Xstatic void XupdateAllWidget(left, right) Xint left, right; X/* X * X */ X`7B X while (left <= right) `7B X`09SListUpdateLine(TopList, left); X`09left++; X `7D X return; X`7D X Xstatic void XredrawArticleWidget(filename, question) Xchar *filename, *question; X/* X * If the article to be displayed has changed, update the article X * window and redraw the mode line X */ X`7B X Arg args`5B2`5D; X X#ifdef MOTIF X XmTextSetString(ArticleText, filename); X XmTextSetEditable(ArticleText, FALSE); X#else X DwtSTextSetString(ArticleText, filename); X DwtSTextSetEditable(ArticleText, FALSE); X#endif X`09 X setBottomInfoLine(question); X#ifdef XRN_PREFETCH X /* force the screen to update before prefetching */ X if (app_resources.typeAhead == False) `7B X`09xthHandleAllPendingEvents(); X `7D X`09 X prefetchNextArticle(); X`09 X#endif /* XRN_PREFETCH */ X return; X`7D X X Xstatic void XexitArticleMode() X/* X * release the storage associated with article mode, unlink the article file Vs, X * and go to newsgroup mode X */ X`7B X int i; X PrevArticle = CurrentArticle = 0; X `20 X /* clear the article window */ X X#ifdef MOTIF X XmTextSetString(ArticleText, NULL); X XmTextSetEditable(ArticleText, FALSE); X#else X DwtSTextSetString(ArticleText, ""); X DwtSTextSetEditable(ArticleText, FALSE); X#endif X setBottomInfoLine(""); X if (SubjectStrings != (char**)0) `7B X`09for (i=0;SubjectStrings`5Bi`5D != NIL(char);i++) `7B X`09 FREE(SubjectStrings`5Bi`5D); X`09`7D X`09FREE(SubjectStrings); X`09SubjectStrings = (char**)0 ; X `7D X `20 X releaseNewsgroupResources(); X if (app_resources.updateNewsrc == TRUE) `7B X`09while (!updatenewsrc()) X`09 (void) ehErrorRetryXRN("Can not update the newsrc file", True); X `7D X X if (PreviousMode == NEWSGROUP_MODE) `7B X`09switchToNewsgroupMode(); X `7D else `7B X`09static void switchToAllMode(); X`09switchToAllMode(); X `7D X `20 X return; X`7D X `20 Xstatic void XexitAddMode() X/* X * release storage associated with add mode and go to newsgroup mode X */ X`7B X int i; X if (AddGroupItems > 0 && AddGroupsStrings != (char**) 0) `7B X`09for (i = 0; i < AddGroupItems; i++) `7B X`09 FREE(AddGroupsStrings`5Bi`5D); X`09`7D X`09FREE(AddGroupsStrings); X`09AddGroupsStrings = (char**) 0; X `7D X X switchToNewsgroupMode(); X `20 X return; X`7D X X Xstatic void XredrawAddListWidget(insertPoint) Xint insertPoint; X/* X * update the add mode text window to correspond to the new set of groups X */ X`7B X int i; `20 X X if (AddGroupItems > 0 && AddGroupsStrings != (char**) 0) `7B X`09for (i = 0; i < AddGroupItems; i++) `7B X`09 FREE(AddGroupsStrings`5Bi`5D); X`09`7D X`09FREE(AddGroupsStrings); X`09AddGroupsStrings = (char**) 0; X `7D X AddGroupItems = 0; X AddGroupsStrings = newGroups(); X if (AddGroupsStrings == (char**)0) X`09return; X X for (AddGroupItems=0; X`09AddGroupsStrings`5BAddGroupItems`5D != '\0'; X`09AddGroupItems++); X X SListLoad(TopList, AddGroupsStrings, AddGroupItems); X currentTop = 0; X resetSelection(); X subjSetPos(TopList,insertPoint); X AddGroupPosition = insertPoint; X return; X`7D X X Xvoid XfoundArticle(file, ques, artNum) Xchar *file, *ques; Xlong artNum; X/* X * Display new article, mark as read. X */ X`7B X int curArt; X X PrevArticle = CurrentArticle; X curArt = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X if (curArt != artNum) `7B`09/* not current pos; have to find it */ X`09for (ArtPosition = 0; ArtPosition < SubjectItems; ArtPosition++) `7B X`09 curArt = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09 if (curArt == artNum) break; X`09`7D X`09if (curArt != artNum) `7B`09/* not in current screen, go get 'em all */ X`09 resetSubjectWidget(ALL, False); X`09 for (ArtPosition = 0; ArtPosition < SubjectItems; ArtPosition++) `7B X`09`09curArt = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09`09if (curArt == artNum) break; X`09 `7D X`09`7D X `7D X if (curArt != artNum) ArtPosition = 0; X if (SubjectStrings`5BArtPosition`5D`5B0`5D == 'u') `7B X`09markArticleAsUnread(artNum); X`09CurrentArticle = artNum; X `7D else `7B X`09CurrentArticle = markStringRead(SubjectStrings`5BArtPosition`5D); X `7D X resetSelection(); X updateSubjectWidget(ArtPosition, ArtPosition); X subjSetPos(TopList, ArtPosition); X redrawArticleWidget(file, ques); X `20 X return; X`7D X Xstatic Widget ExitConfirmBox = (Widget) 0; Xstatic Widget CatchUpConfirmBox = (Widget) 0; Xstatic Widget PartCatchUpConfirmBox = (Widget) 0; Xstatic Widget UnSubConfirmBox = (Widget) 0; Xstatic Widget FedUpConfirmBox = (Widget) 0; Xstatic Widget EndActionBox = (Widget) 0; X X/*ARGSUSED*/ Xstatic void XgeneralHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X switch(Action) `7B X`09case NG_EXIT: X`09if ((int) client_data == XRN_YES) `7B X`09 ehNoUpdateExitXRN(); X`09`7D X`09PopDownDialog(ExitConfirmBox); X`09break; X X`09case NG_QUIT: X`09if ((int) client_data == XRN_YES) `7B X`09 ehCleanExitXRN(); X`09`7D X`09PopDownDialog(ExitConfirmBox); X `09break; X X`09case NG_CATCHUP: X`09if ((int) client_data == XRN_YES) `7B X`09 catchUpNG(); X`09`7D X`09PopDownDialog(CatchUpConfirmBox); X `09break; X`09 `20 X`09case NG_UNSUBSCRIBE: X`09if ((int) client_data == XRN_YES) `7B X`09 unsubscribeNG(); X`09`7D X`09PopDownDialog(UnSubConfirmBox); X`09break; X`09 `20 X`09case ART_CATCHUP: X`09if ((int) client_data == XRN_YES) `7B X`09 catchUpART(); X`09`7D`09 `20 X`09PopDownDialog(CatchUpConfirmBox); X`09break; X`09 `20 X`09case ART_PART_CATCHUP: X`09if ((int) client_data == XRN_YES) `7B X`09 catchUpPartART(); X`09`7D`09 `20 X`09PopDownDialog(PartCatchUpConfirmBox); X`09break; X`09 `20 X`09case ART_UNSUBSCRIBE: X`09if ((int) client_data == XRN_YES) `7B X`09 unsubscribeART(); X`09`7D`09 `20 X`09PopDownDialog(UnSubConfirmBox); X`09break; X X`09case ART_FEDUP: X`09if ((int) client_data == XRN_YES) `7B X`09 fedUpART(); X`09`7D`09 `20 X`09PopDownDialog(FedUpConfirmBox); X`09FedUpConfirmBox = 0; X`09break; X `7D X unbusyCursor(); X inCommand = 0; X return; X`7D X X/*ARGSUSED*/ Xvoid XngQuitFunction(widget) XWidget widget; X/* X * called when the user wants to quit xrn X * X * full update the newsrc file X * exit X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X if (app_resources.confirmMode & NG_QUIT) `7B X`09Action = NG_QUIT; X`09if (ExitConfirmBox == (Widget) 0) `7B X`09 ExitConfirmBox = CreateDialog(TopLevel, "Are you sure?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(ExitConfirmBox); X`09return; X `7D X ehCleanExitXRN(); X`7D X X X/*ARGSUSED*/ Xvoid XngReadFunction(widget) XWidget widget; X/* X * called when the user wants to read a new newsgroup X * X * get the selected group, set the internal pointers, and go to article mode X * X */ X`7B X char name`5BGROUP_NAME_SIZE`5D; X#ifdef MOTIF X XmString`09*selectedItems; X#else X DwtCompString`09*selectedItems; X#endif X int`09`09i; X int`09`09numSelectedItems; X Arg`09`09listArg`5B2`5D; X int `09status; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X SListSelectAll(TopList, 0); X if (SelectionItem < 0) `7B X`09SelectionItem = SListGetHighlight(TopList); X`09SelectionCount = 1; X `7D X if (SelectionItem >= GroupItems) `7B X`09resetSelection(); X`09return; X `7D X GroupPosition = SelectionItem; X resetSelection(); X if (GroupPosition >= 0) `7B X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09if (NewsgroupEntryMode == XRN_GOTO) `7B X`09 status = gotoNewsgroupForRead(name); X`09`7D else `7B X`09 status = jumpToNewsgroup(name); X`09 NewsgroupEntryMode = XRN_GOTO; X`09`7D X`09if (status == GOOD_GROUP) `7B X`09 if (getNewsgroup() == XRN_NOMORE) `7B X`09`09mesgPane(XRN_SERIOUS, "Can not get the group, it may have been deleted V"); X`09`09return; X`09 `7D X`09 (void) strcpy(LastGroup, name); X`09 (void) switchToArticleMode(True); X`09`7D X `7D else `7B X`09GroupPosition = 0; X `7D X subjSetPos(TopList, 0); X return; X`7D X X/*ARGSUSED*/ Xvoid XngOpenFunction(widget) XWidget widget; X/* X * called when the user wants to open a new newsgroup X * X * get the selected group, set the internal pointers, and go to article mode X * X */ X`7B X char name`5BGROUP_NAME_SIZE`5D; X#ifdef MOTIF X XmString`09*selectedItems; X#else X DwtCompString`09*selectedItems; X#endif X int`09`09i; X int`09`09numSelectedItems; X Arg`09`09listArg`5B2`5D; X int `09status; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X SListSelectAll(TopList, 0); X if (SelectionItem < 0) `7B X`09SelectionItem = SListGetHighlight(TopList); X`09SelectionCount = 1; X `7D X if (SelectionItem >= GroupItems) `7B X`09resetSelection(); X`09return; X `7D X GroupPosition = SelectionItem; X resetSelection(); X if (GroupPosition >= 0) `7B X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09if (NewsgroupEntryMode == XRN_GOTO) `7B X`09 status = gotoNewsgroupForRead(name); X`09`7D else `7B X`09 status = jumpToNewsgroup(name); X`09 NewsgroupEntryMode = XRN_GOTO; X`09`7D X`09if (status == GOOD_GROUP) `7B X`09 if (getNewsgroup() == XRN_NOMORE) `7B X`09`09mesgPane(XRN_SERIOUS, "Can not get the group, it may have been deleted V"); X`09`09return; X`09 `7D X`09 (void) strcpy(LastGroup, name); X`09 (void) switchToArticleMode(False); X`09`7D X `7D else `7B X`09GroupPosition = 0; X `7D X subjSetPos(TopList, 0); X return; X`7D X X/*ARGSUSED*/ Xvoid XngNextFunction(widget) XWidget widget; X/* X * called when the user does not want to read a newsgroup X * X * if selected group, set internal group X * call updateNewsgroupMode X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X GroupPosition++; X if (GroupPosition >= GroupItems) `7B X`09GroupPosition = 0; X `7D X subjSetPos(TopList, GroupPosition); X return; X`7D X X X/*ARGSUSED*/ Xvoid XngPrevFunction(widget) XWidget widget; X/* X * called when the user wants to move the cursor up in X * the newsgroup window X * X * if selected group, set internal group X * call updateNewsgroupMode X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X `20 X GroupPosition--; X if (GroupPosition < 0) `7B X`09GroupPosition = GroupItems - 1; X `7D X subjSetPos(TopList, GroupPosition); X return; X`7D X X Xstatic void XcatchUpNG() X/* X * used when the user has elected to catch X * up newsgroups in newsgroup mode X */ X`7B X char name`5BGROUP_NAME_SIZE`5D; X int first; X int savePosition = GroupPosition; X int i; X `20 X if (SelectionItem < 0) `7B X`09first = SListGetHighlight(TopList); X`09resetSelection(); X`09if (first < 0) return; X`09if (first >= GroupItems) `7B X`09 first = GroupItems - 1; X`09`7D X`09GroupPosition = first; X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09if (gotoNewsgroup(name) == GOOD_GROUP) `7B X`09 catchUp(); X`09`7D X`09updateNewsgroupMode(); X`09return; X `7D else `7B X`09for (i = 0; i < GroupItems; i++) `7B X`09 if (SListIsSelected(TopList, i)) `7B X`09`09currentGroup(Mode, NewsGroups`5Bi`5D, name); X`09`09if (gotoNewsgroup(name) == GOOD_GROUP) `7B X`09`09 catchUp(); X`09`09`7D X`09 `7D X`09`7D X`09resetSelection(); X `7D X GroupPosition = savePosition; X if (GroupPosition >= GroupItems) `7B X`09GroupPosition = GroupItems - 1; X `7D X updateNewsgroupMode(); X return; X`7D X X Xstatic void XunsubscribeNG() X/* X * Unsubscribe user from selected group(s) X */ X`7B X char name`5BGROUP_NAME_SIZE`5D; X int first, i; X int savePosition = GroupPosition; X `20 X if (SelectionItem < 0) `7B X`09first = SListGetHighlight(TopList); X`09resetSelection(); X`09if (first < 0) return; X`09if (first >= GroupItems) X`09 first = GroupItems - 1; X`09GroupPosition = first; X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09if (gotoNewsgroup(name) == GOOD_GROUP) `7B X`09 unsubscribe(); X`09`7D X`09updateNewsgroupMode(); X`09return; X `7D else `7B X`09for (i=0;i= GroupItems) `7B X`09GroupPosition = GroupItems - 1; X `7D X resetSelection(); `20 X updateNewsgroupMode(); X return; X`7D X X Xstatic void XcatchUpART() X/* X * Catch up group, and exit article mode X */ X`7B X catchUp(); X exitArticleMode(); X return; `20 X`7D X X Xstatic void XcatchUpPartART() X/* X * Mark all articles between 0 and ArtPosition as read. X * Get the next unread article and display it, quit X * if there are no more unread articles. X */ X`7B X char *filename, *question; X long artNum; X `20 X if (SelectionItem > 0) X`09ArtPosition = SelectionItem + 1; X if (ArtPosition >= SubjectItems) `7B X`09ArtPosition = SubjectItems - 1; X `7D X markArticles(SubjectStrings, 0, ArtPosition, '+'); X updateSubjectWidget(ArtPosition,ArtPosition); X if (getNearbyArticle(art_UNREAD, &filename, &question, &artNum) ==`20 X`09art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X foundArticle(filename, question, artNum); X `20 X return; X`7D X X Xstatic void XfedUpART() X`7B X char name`5BGROUP_NAME_SIZE`5D; X int i; X X PrevArticle = CurrentArticle = 0; X X catchUp(); X artNextGroupFunction((Widget) 0); X return; X`7D X Xstatic void XunsubscribeART() X/* X * Unsubscribe user from the current group; X * exit article mode X */ X`7B X unsubscribe(); X exitArticleMode(); X `20 X return; X`7D X X/*ARGSUSED*/ Xvoid XngCatchUpFunction(widget) XWidget widget; X/* X * called to catch up on all unread articles in this newsgroup X * use a confirmation box if the user has requested it X * if selected group, set internal group X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X `20 X if (app_resources.confirmMode & NG_CATCHUP) `7B X`09Action = NG_CATCHUP; X`09if (CatchUpConfirmBox == (Widget) 0) `7B X`09 CatchUpConfirmBox = CreateDialog(TopLevel, "OK to catch up?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(CatchUpConfirmBox); X X`09return; X `7D X catchUpNG(); X X return; X`7D X X X/*ARGSUSED*/ Xvoid XngUnsubFunction(widget) XWidget widget; X/* X * called to unsubscribe to a newsgroup X * X * if selected group, set internal group X * do internals X * call updateNewsgroupMode X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; `20 X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X X if (app_resources.confirmMode & NG_UNSUBSCRIBE) `7B X`09Action = NG_UNSUBSCRIBE; X`09if (UnSubConfirmBox == (Widget) 0) `7B X`09 UnSubConfirmBox = CreateDialog(TopLevel, "OK to unsubscribe?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(UnSubConfirmBox); X`09return; X `7D X unsubscribeNG(); X X return; X`7D X X X#define XRNsub_ABORT 0 X#define XRNsub_LASTGROUP 1 X#define XRNsub_FIRST 2 X#define XRNsub_LAST 3 X#define XRNsub_CURRENT 4 X Xstatic Widget SubscribeBox = (Widget) 0; X X/*ARGSUSED*/ Xstatic void XsubscribeHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X int status = SUBSCRIBE; X char name`5BGROUP_NAME_SIZE`5D; X int left, right; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X switch ((int) client_data) `7B X`09case XRNsub_LASTGROUP: X`09if (LastGroup`5B0`5D != '\0') `7B X`09 if (gotoNewsgroup(LastGroup) != GOOD_GROUP) `7B X`09`09mesgPane(XRN_SERIOUS, "Bad Group"); X`09`09PopDownDialog(SubscribeBox); X`09`09unbusyCursor(); X`09`09inCommand = 0; X`09`09return; X`09 `7D X`09 subscribe(); X`09 updateNewsgroupMode(); X`09`7D X`09break; X X`09case XRNsub_FIRST: X`09if (addToNewsrcBeginning(GetDialogValue(SubscribeBox), X`09`09`09`09 status) == GOOD_GROUP) `7B X`09 GroupPosition = 0; X`09 updateNewsgroupMode(); X`09`7D X`09break; X X`09case XRNsub_LAST: X`09if (addToNewsrcEnd(GetDialogValue(SubscribeBox), X`09`09`09 status) == GOOD_GROUP) `7B X`09 updateNewsgroupMode(); X `09 subjSetPos(TopList, GroupPosition); X`09`7D X`09break; X X`09case XRNsub_CURRENT: X`09if (GroupPosition < 0) GroupPosition = 0; X`09if (GroupPosition >= GroupItems) GroupPosition = GroupItems - 1; X`09if (NewsGroups`5BGroupPosition`5D == '\0') `7B X`09 if (addToNewsrcEnd(GetDialogValue(SubscribeBox), X`09`09`09 status) == GOOD_GROUP) `7B X`09`09updateNewsgroupMode(); X `09 `09subjSetPos(TopList, GroupPosition); X`09 `7D X`09`7D else `7B X X`09 /* don't need to check for the null group here, it would have */ X`09 /* been already handled above */ X`09 if (GroupPosition == 0) `7B X`09 if (addToNewsrcBeginning(GetDialogValue( X`09`09 SubscribeBox),status) == GOOD_GROUP) `7B X`09`09 updateNewsgroupMode(); X`09`09`7D X`09 `7D else `7B X`09`09GroupPosition--; X`09`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X`09 if (addToNewsrcAfterGroup(GetDialogValue( X`09`09 SubscribeBox), name, status) == GOOD_GROUP) `7B X`09`09 updateNewsgroupMode(); X`09`09`7D X`09 `7D X `09`7D X`09break; X `7D X PopDownDialog(SubscribeBox); X subjSetPos(TopList,GroupPosition); X unbusyCursor(); X inCommand = 0; X return; X`7D X X X/*ARGSUSED*/ Xvoid XngSubscribeFunction(widget) XWidget widget; X/* X * Subscribe to a group currently unsubscribed to X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"cursor position", subscribeHandler, (caddr_t) XRNsub_CURRENT`7D, X`09`7B"abort", subscribeHandler, (caddr_t) XRNsub_ABORT`7D, X`09`7B"last group", subscribeHandler, (caddr_t) XRNsub_LASTGROUP`7D, X`09`7B"first", subscribeHandler, (caddr_t) XRNsub_FIRST`7D, X`09`7B"last", subscribeHandler, (caddr_t) XRNsub_LAST`7D, X `7D; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X `20 X if (SubscribeBox == (Widget) 0) `7B X`09SubscribeBox = CreateDialog(TopLevel, "Group to subscribe to:", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(SubscribeBox); X X return; X`7D X X X#define XRNgoto_ABORT 0 X#define XRNgoto_GOTO 1 X Xstatic Widget GotoNewsgroupBox = (Widget) 0; X X/*ARGSUSED*/ Xstatic void XgotoHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X char *name; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X resetSelection(); X if ((int) client_data == XRNgoto_GOTO) `7B X`09name = GetDialogValue(GotoNewsgroupBox); X`09if (name`5B0`5D == '\0') `7B X`09 mesgPane(XRN_INFO, "No newsgroup entered"); X`09`7D else if (jumpToNewsgroup(name) == GOOD_GROUP) `7B X`09 (void) strcpy(LastGroup, name); X`09 (void) switchToArticleMode(app_resources.autoRead); X`09`7D X `7D X PopDownDialog(GotoNewsgroupBox); X unbusyCursor(); X inCommand = 0; X return; X`7D X X X/*ARGSUSED*/ Xvoid XngGotoFunction(widget) XWidget widget; X/* X * Jump to a newsgroup not displayed in newsgroup mode (either because X * it's not subscribed to, or because all the articles have been read) X * X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"go to newsgroup", gotoHandler, (caddr_t) XRNgoto_GOTO`7D, X`09`7B"abort", gotoHandler, (caddr_t) XRNgoto_ABORT`7D, X `7D; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X resetSelection(); X if (GotoNewsgroupBox == (Widget) 0) `7B X`09GotoNewsgroupBox = CreateDialog(TopLevel, "Group to go to:", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(GotoNewsgroupBox); X return; X`7D X X X Xstatic void XswitchToAllMode() X`7B `20 X PreviousMode = Mode; X Mode = ALL_MODE; X X /* switch buttons */ X swapMode(); X `20 X setTopInfoLine("View all available groups, with option to subscribe"); X redrawAllWidget(0); X X return; X`7D X X X X/*ARGSUSED*/ Xstatic void XngToggleGroupsFunction(widget) XWidget widget; X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X NewsgroupDisplayMode = (NewsgroupDisplayMode == 0) ? 1 : 0; X redrawNewsgroupListWidget(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XngAllGroupsFunction(widget) XWidget widget; X/* X * Enter "all" mode. Display all available groups to allow user to X * subscribe/unsubscribe to them. X */ X`7B X Arg args`5B3`5D; X `20 X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X resetSelection(); X switchToAllMode(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XngRescanFunction(widget) XWidget widget; X/* X * query the server to see if there are any new articles and groups X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X resetSelection(); X rescanServer(); X determineMode(); X `20 X return; X`7D X/*ARGSUSED*/ Xvoid autoRescan(data, id) Xcaddr_t data; XXtIntervalId *id; X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09TimeOut = 0; X`09return; X `7D X if (TimeOut != *id) `7B X`09(void) fprintf(stderr, "bad time out, id is %d, expected %d\n", *id, Time VOut); X`09TimeOut = 0; X`09return; X `7D X TimeOut = 0; X if (!inCommand) `7B X`09inCommand = 1; X`09busyCursor(); X`09infoNow("automatic rescan in progresss..."); X`09ngRescanFunction((Widget) 0); X`09infoNow("automatic rescan completed"); X`09close_server(); X`09unbusyCursor(); X`09inCommand = 0; X `7D X addTimeOut(); X X return; X`7D X X X/*ARGSUSED*/ Xvoid XngPrevGroupFunction(widget) XWidget widget; X/* X * put the user in the last newsgroup accessed X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X resetSelection(); X if (LastGroup`5B0`5D != '\0') `7B X`09if (jumpToNewsgroup(LastGroup) == GOOD_GROUP) `7B X`09 (void) switchToArticleMode(app_resources.autoRead); X`09`7D X `7D X X return; X`7D X X X/*ARGSUSED*/ Xvoid XngSelectFunction(widget) XWidget widget; X/*`20 X * save the user's selection of groups to be moved with the move X * command X */ X`7B X int i, count; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X if (selSize < GroupItems) `7B X`09if (selList != NULL) FREE(selList); X`09selList = XtMalloc(GroupItems+1); X`09selSize = GroupItems; X `7D X count = 0; X for (i=0; i= GroupItems) moveTo = GroupItems - 1; X if (moveTo > 0) `7B X`09currentGroup(Mode, NewsGroups`5BmoveTo-1`5D, oldGroup); X `7D X for (moveFrom = 0; moveFrom < GroupItems; moveFrom++) `7B X`09if (selList`5BmoveFrom`5D != 0) `7B X`09 currentGroup(Mode, NewsGroups`5BmoveFrom`5D, newGroup); X`09 if (moveTo <= 0) `7B X`09`09moveTo = 0; X`09`09(void) addToNewsrcBeginning(newGroup, status); X`09`09(void) strcpy(oldGroup, newGroup); X`09 `7D else `7B X`09`09(void) addToNewsrcAfterGroup(newGroup, oldGroup, status); X`09`09(void) strcpy(oldGroup, newGroup); X`09 `7D X`09`7D X `7D X resetSelection(); X selCount = 0; X redrawNewsgroupListWidget(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XngExitFunction(widget) XWidget widget; X/* X * Quit xrn, leaving the newsrc in the state it was in at X * the last invokation of rescan. X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; X X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X if (app_resources.confirmMode & NG_EXIT) `7B X`09Action = NG_EXIT; X`09if (ExitConfirmBox == (Widget) 0) `7B X`09 ExitConfirmBox = CreateDialog(TopLevel, "Are you sure?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(ExitConfirmBox); X`09return; X `7D X X ehNoUpdateExitXRN(); X`7D X X X/*ARGSUSED*/ Xvoid XngCheckPointFunction(widget) XWidget widget; X/* X * update the .newsrc file X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X X while (!updatenewsrc()) X`09(void) ehErrorRetryXRN("Can not update the newsrc file", True); X X return; X`7D X X X/*ARGSUSED*/ Xvoid XngGripeFunction(widget) XWidget widget; X/* X * Allow user to gripe X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X gripe(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XngPostFunction(widget) XWidget widget; X/* X * allow user to post an article X */ X`7B X if (Mode != NEWSGROUP_MODE) `7B X`09return; X `7D X post(); X `20 X return; X`7D X X X/*ARGSUSED*/ Xvoid XartQuitFunction(widget) XWidget widget; X/* X * called when the user wants to quit the current newsgroup and go to X * the next one X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X exitArticleMode(); X `20 X return; X`7D X X/*ARGSUSED*/ Xvoid XartNextFunction(widget) XWidget widget; X/* X * called when the user wants to read the next article X */ X`7B X char *filename;`09`09/* name of the article file */ X char *question;`09`09/* question to put in the question box */ X long artNum; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (getNearbyArticle(ArtStatus, &filename, &question, X`09`09`09 &artNum) == art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X /* update the text window */ X foundArticle(filename, question, artNum); X X ArtStatus = art_NEXT; X ArtEntry = 0; X return; X`7D X X/*ARGSUSED*/ Xvoid XartScrollFunction(widget) XWidget widget; X/* X * called when the user wants to scroll the current article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (!app_resources.pageArticles) `7B X`09if (ScrollDownOnePage(ArticleText)) `7B X`09 if (app_resources.subjectRead == False) `7B X`09`09artNextUnreadFunction((Widget) 0); X`09 `7D else `7B X`09`09artSubNextFunction((Widget) 0); X`09 `7D X`09`7D X `7D else `7B X`09ScrollDownOnePage(ArticleText); X`09return; X `7D X return; X`7D X X/*ARGSUSED*/ Xvoid XartScrollBackFunction(widget) XWidget widget; X/* X * called when the user wants to scroll the current article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X (void) ScrollUpOnePage(ArticleText); X return; X`7D X X/*ARGSUSED*/ Xstatic void XartScrollEndFunction(widget) XWidget widget; X/* X * called when the user wants to scroll the current article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X#ifdef MOTIF X XmTextShowPosition(ArticleText, XmTextGetLastPosition(ArticleText)); X XmTextScroll(ArticleText, -1); X#else X DwtTextShowPosition(ArticleText, DwtSTextGetLastPosition(ArticleText)); X DwtTextScroll(ArticleText, -1); X#endif X return; X`7D X X X/*ARGSUSED*/ Xstatic void XartScrollBeginningFunction(widget) XWidget widget; X/* X * called when the user wants to scroll the current article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X#ifdef MOTIF X XmTextShowPosition(ArticleText, 0); X#else X DwtTextShowPosition(ArticleText, 0); X#endif X return; X`7D X Xvoid XartNextUnreadFunction(widget) XWidget widget; X/* X * called when the user wants to go to the next unread news X * article in the current newsgroup X *`20 X */ X`7B X char *filename;`09`09/* name of the article file */ X char *question;`09`09/* question to put in the question box */ X long artNum; X X void artNextFunction(); X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X ArtStatus = art_UNREAD; X artNextFunction(widget); X return; X`7D X X/*ARGSUSED*/ Xvoid XartPrevFunction(widget) XWidget widget; X/* X * called when the user wants to read the previous article X */ X`7B X int left, right; X long artNum; X char *filename, *question; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X ArtStatus = art_PREV; X if (ArtPosition <= 0) `7B X`09ArtPosition = 0; X`09if (getPrevious(&artNum)) `7B X`09 gotoArticle(artNum); X`09 (void) getArticleText(&filename, &question); X`09 foundArticle(filename, question, artNum); X`09 ArtStatus = art_NEXT; X`09 return; X`09`7D X`09setTopInfoLine("No previous article available"); X`09return; X `7D X ArtStatus = art_PREV; X if (getNearbyArticle(ArtStatus, &filename, &question, X`09`09`09 &artNum) == art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X foundArticle(filename, question, artNum); X ArtStatus = art_NEXT; X `20 X return; X`7D X X/*ARGSUSED*/ Xvoid XartReadFunction(widget) XWidget widget; X/* X * called when the user wants to read the current article X */ X`7B X char *filename;`09`09/* name of the article file */ X char *question;`09`09/* question to put in the question box */ X long artNum; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X ArtStatus = art_CURRENT; X if (getNearbyArticle(ArtStatus, &filename, &question, X`09`09`09 &artNum) == art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X /* update the text window */ X foundArticle(filename, question, artNum); X X ArtStatus = art_NEXT; X return; X`7D X X X/*ARGSUSED*/ Xvoid XartNextGroupFunction(widget) XWidget widget; X`7B X void artQuitFunction(); X char name`5BGROUP_NAME_SIZE`5D; X int append = 0; X int oldGP; X int i; X X PrevArticle = CurrentArticle = 0; X X#ifdef MOTIF X XmTextSetString(ArticleText, NULL); X XmTextSetEditable(ArticleText, FALSE); X#else X DwtSTextSetString(ArticleText, ""); X DwtSTextSetEditable(ArticleText, FALSE); X#endif X setBottomInfoLine(""); X X while (1) `7B X`09/* X`09 * XXX if the newsgroup is fully read, then when the new newsgroup X`09 * string is regenerated (upon entry to newsgroup mode), the string X`09 * for this group will not be there and thus the Group Position will X`09 * be too far forward (by one group) X`09 */ X X`09if (NewsGroups != NIL(char *)) `7B X`09 for (i = 0; NewsGroups`5Bi`5D != NIL(char); i++)`20 X`09`09FREE(NewsGroups`5Bi`5D); X`09 FREE(NewsGroups); X`09 NewsGroups = (char**)0; X`09`7D X X NewsGroups = unreadGroups(NewsgroupDisplayMode); X`09GroupItems = 0; X`09for (i=0;NewsGroups`5Bi`5D != '\0';i++) `7B X`09 GroupItems++; X`09`7D X`09if (GroupPosition >= GroupItems) `7B X`09 GroupPosition = 0; X`09 artQuitFunction(widget); X`09 return; X`09`7D X`09currentGroup(Mode, NewsGroups`5BGroupPosition`5D, name); X if (STREQ(name, LastGroup)) `7B X`09 /* last group not fully read */ X`09 GroupPosition++; X`09 if (GroupPosition >= GroupItems) `7B X`09`09artQuitFunction(widget); X`09 return; X`09 `7D X`09 currentGroup(NEWSGROUP_MODE, NewsGroups`5BGroupPosition`5D, name); X`09`7D X X`09if ((name == NIL(char)) `7C`7C (*name == '\0')) `7B X`09 artQuitFunction(widget); X`09 return; X`09`7D X X`09if (gotoNewsgroup(name) != GOOD_GROUP) `7B X`09 mesgPane(XRN_SERIOUS `7C append, X`09`09"Bad group `60%s', skipping to next group", name); X`09 append = XRN_APPEND; X`09 GroupPosition++; X`09 continue; X`09`7D X X`09if (getNewsgroup() == XRN_NOMORE) `7B X`09 mesgPane(XRN_INFO `7C append, X`09`09 "No unread articles in `60%s', skipping to next group", X`09`09 name); X`09 append = XRN_APPEND; X`09 GroupPosition++; X`09 continue; X`09`7D X X`09if (switchToArticleMode(app_resources.autoRead) == GOOD_GROUP) `7B X`09 setNewsgroup(LastGroup); X`09 releaseNewsgroupResources(); X`09 setNewsgroup(name); X`09 (void) strcpy(LastGroup, name); X`09 if (app_resources.updateNewsrc == TRUE) `7B X`09`09while (!updatenewsrc()) X`09`09 ehErrorRetryXRN("Cannot update the newsrc file", True); X`09 `7D X`09 return; X`09`7D X`09 /* X`09 * Normally, I'd put a call to mesgPane in here to tell the X`09 * user that the switchToArticleMode failed, but it isn't X`09 * necessary because switchToArticleMode calls bogusNewsgroup X`09 * if it fails, and bogusNewsgroup calls mesgPane with an X`09 * appropriate message. X`09 */ X `7D X`7D X X X/*ARGSUSED*/ Xvoid XartFedUpFunction(widget) XWidget widget; X`7B X static struct DialogArg args`5B`5D = `7B X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7D; X X if (app_resources.confirmMode & ART_FEDUP) `7B X`09Action = ART_FEDUP; X`09if (FedUpConfirmBox == (Widget) 0) `7B X`09 FedUpConfirmBox = CreateDialog(TopLevel, "Are you sure?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(FedUpConfirmBox); X`09return; X `7D X X fedUpART(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartCatchUpFunction(widget) XWidget widget; X/* X * called when the user wants to mark all articles in the current group as r Vead X */ X`7B X int left, right; X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SelectionItem < 0) `7B X`09if (app_resources.confirmMode & ART_CATCHUP) `7B X`09 Action = ART_CATCHUP; X`09 if (CatchUpConfirmBox == (Widget) 0) `7B X`09`09CatchUpConfirmBox = CreateDialog(TopLevel, "OK to catch up?", X`09`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09 `7D X`09 PopUpDialog(CatchUpConfirmBox); X`09 return; X`09`7D X catchUpART(); X return; X `7D X ArtPosition++; X if (ArtPosition >= SubjectItems) X`09ArtPosition = SubjectItems - 1; X if (app_resources.confirmMode & ART_CATCHUP) `7B X`09Action = ART_PART_CATCHUP; X`09if (PartCatchUpConfirmBox == (Widget) 0) `7B X`09`09PartCatchUpConfirmBox = CreateDialog(TopLevel, X`09`09`09`09`09`09 "OK to catch up to current position?", X`09`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(PartCatchUpConfirmBox); X `7D else `7B X`09catchUpPartART(); X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XartUnsubFunction(widget) XWidget widget; X/* X * called when the user wants to unsubscribe to the current group X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"yes", generalHandler, (caddr_t) XRN_YES`7D, X `7B"no", generalHandler, (caddr_t) XRN_NO`7D, X `7D; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (app_resources.confirmMode & ART_UNSUBSCRIBE) `7B X`09Action = ART_UNSUBSCRIBE; X`09if (UnSubConfirmBox == (Widget) 0) `7B X`09 UnSubConfirmBox = CreateDialog(TopLevel, "OK to unsubscribe?", X`09`09`09`09`09 DIALOG_NOTEXT, args, XtNumber(args)); X`09`7D X`09PopUpDialog(UnSubConfirmBox); X`09return; X `7D X unsubscribeART(); X return; X`7D X X Xvoid XmarkFunction(marker) Xchar marker; X/* X * Get selection region, mark articles, redisplay subject window. X */ X`7B X int i; X int count = 0; X X for (i = 0; i < SubjectItems; i++) `7B X`09if (SListIsSelected(TopList,i)) `7B X`09 markArticles(SubjectStrings, i, i+1, marker); X`09 SListUpdateLine(TopList, i); X`09 count++; X`09`7D X `7D X X resetSelection(); X X if (count == 0) `7B X`09count = 1; X`09markArticles(SubjectStrings, ArtPosition, ArtPosition+1, marker); X`09SListUpdateLine(TopList, ArtPosition); X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XartMarkReadFunction(widget) XWidget widget; X/* X * Mark selected article(s) as read X */ X`7B X char marker = '+'; X int save; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X save = ArtPosition; X markFunction(marker); X ArtPosition = save; X subjSetPos(TopList, ArtPosition); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartMarkUnreadFunction(widget) XWidget widget; X/* X * Mark selected article(s) as unread X */ X`7B X char marker = 'u'; X int save; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X save = ArtPosition; X markFunction(marker); X ArtPosition = save; X subjSetPos(TopList, ArtPosition); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartPostFunction(widget) XWidget widget; X/* X * allow user to post to the newsgroup currently being read X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X post(); X `20 X return; X`7D X X#define EA_Next 1 X#define EA_Followup 2 X#define EA_Quit 3 X/*ARGSUSED*/ Xstatic void XendActionHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X PopDownDialog(EndActionBox); X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X switch((int) client_data) `7B X`09case EA_Next: X`09 artNextUnreadFunction((Widget) 0); X`09 break; X`09case EA_Followup: X`09 artFollowupFunction((Widget) 0); X`09 break; X`09case EA_Quit: X`09 artQuitFunction((Widget) 0); X`09 break; X `7D X unbusyCursor(); X inCommand = 0; X return; X`7D X/*ARGSUSED*/ Xvoid XartSubNextFunction(widget) XWidget widget; X/* X * X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"next unread", endActionHandler, (caddr_t) EA_Next`7D, X`09`7B"followup", endActionHandler, (caddr_t) EA_Followup`7D, X`09`7B"quit",`09endActionHandler, (caddr_t) EA_Quit`7D, X `7D; X X int left, right; X char *filename, *question; X char *subject; X long artNum; X int status; X `20 X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SelectionItem >= 0) `7B X`09ArtPosition = SelectionItem; X`09resetSelection(); X`09if (ArtPosition >= SubjectItems) X`09 ArtPosition = SubjectItems - 1; X`09if (SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09 return; X`09`7D X `7D X artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X subject = XtNewString(getSubject(artNum)); X (void) sprintf(error_buffer, "Subject search: %s", subject); X info(error_buffer); X status = isNextSubject(subject, &filename, &question, &artNum); X switch (status) `7B X`09 case ABORT: X `09 FREE(subject); X`09 infoNow("search has been aborted"); X`09 return; X`09 case NOCHANGE: X`09 (void) sprintf(error_buffer, "Subject search: %s", subject); X`09 info(error_buffer); X `09 FREE(subject); X`09 foundArticle(filename, question, artNum); X`09 return; X`09 case DONE: X `09 FREE(subject); X`09 if (app_resources.confirmMode & ART_ENDACTION) `7B X`09`09if (EndActionBox == (Widget) 0) `7B X`09`09`09EndActionBox = CreateDialog(TopLevel, X`09`09`09"End of subject. Next action?", X`09`09`09DIALOG_NOTEXT, args, XtNumber(args)); X`09`09`7D X`09`09PopUpDialog(EndActionBox); X`09`09return; X`09 `7D else `7B X`09`09ArtPosition = 0; X`09`09infoNow("Subject has been exhausted, returning to first unread article V"); X`09`09if (getNearbyArticle(art_UNREAD,&filename, X`09`09`09`09&question,&artNum) == art_DONE) `7B X`09`09 exitArticleMode(); X`09`09 return; X`09`09`7D X`09`09foundArticle(filename, question, artNum); X`09`09return; X`09 `7D X`09 case EXIT: X `09 FREE(subject); X`09 exitArticleMode(); X`09 return; X`09`7D X if (getNearbyArticle(art_NEXT, &filename, &question, &artNum) == art_DON VE) `7B X`09exitArticleMode(); X`09return; X `7D X foundArticle(filename, question, artNum); X `20 X return; X`7D X`09 X X/*ARGSUSED*/ Xvoid XartSubPrevFunction(widget) XWidget widget; X/* X * X */ X`7B X char *subject; X long artNum; X char *filename, *question; X int status; X char buffer`5B256`5D; X Arg args`5B3`5D; X int i; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SelectionItem < 0 )`7B X`09if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X`09/* nothing selected, we should be on a valid article */ X`09if (SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09 resetSelection(); X`09 return; X`09`7D X`09artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09subject = XtNewString(getSubject(artNum)); X`09(void) sprintf(error_buffer, "Subject search: %s", subject); X`09info(error_buffer); X`09status = isPrevSubject(subject, &filename, &question, &artNum); X`09FREE(subject); X`09switch(status) `7B X`09 case ABORT: X`09 infoNow("search has been aborted"); X`09 return; X`09 case NOCHANGE: X`09 foundArticle(filename, question, artNum); X`09 return; X`09 case CHANGE: X`09 ArtPosition = 0; X`09 resetSubjectWidget(ALL, False); X`09 foundArticle(filename, question, artNum); X`09 return; X`09 case DONE: X`09 infoNow("Subject has been exhausted"); X`09 return; X`09 case EXIT: X`09 exitArticleMode(); X`09 return; X`09`7D X `7D X ArtPosition = SelectionItem; X resetSelection(); X if (ArtPosition < 0) ArtPosition = 0; X if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X gotoArticle(artNum); X subjSetPos(TopList, ArtPosition); X if (getArticleText(&filename, &question) != XRN_OKAY) `7B X`09if (getNearbyArticle(art_NEXT, &filename, &question, &artNum) == art_DONE V) `7B X`09 exitArticleMode(); X`09 return; X`09`7D X`09infoNow(error_buffer); X`09foundArticle(filename, question, artNum); X`09return; X `7D X infoNow(error_buffer); X foundArticle(filename, question, artNum); X `20 X return; X`7D X X Xchar *SubjectKilled; X X/*ARGSUSED*/ Xvoid XartKillSessionFunction(widget) XWidget widget; X/* X * Allow user to mark all articles with the current subject as read X * X * XXX get subject, kill using data structures, rebuild SubjectString X */ X`7B X int left, right; X char *subject; X char *cursubject; X char *filename, *question; X long artNum; X Arg args`5B3`5D; X#ifdef MOTIF X XmString subjString; X#else X DwtCompString subjString; X#endif X int i; X `20 X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SelectionItem > 0 && SelectionItem < SubjectItems) `7B X`09ArtPosition = SelectionItem; X `7D X resetSelection(); X if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X subject = XtNewString(getSubject(artNum)); X SubjectKilled = XtNewString(subject); X ArtPosition = 0; X while (ArtPosition < SubjectItems) `7B X`09artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09cursubject = getSubject(artNum); X`09/* only kill those that have not been marked as unread */ X`09if ((STREQ(subject, cursubject)) && X`09 (SubjectStrings`5BArtPosition`5D`5B0`5D != 'u')) `7B X`09 markArticleAsRead(artNum); X`09`7D X`09ArtPosition++; X `7D X /* set the cursor back to the beginning of the subject screen */ X clearArtCache(); X ArtPosition = 0; X infoNow("Subject had been killed, returning to first unread article"); X FREE(subject); X resetSubjectWidget(UNREAD, True); X if (SubjectItems == 0 `7C`7C X`09getNearbyArticle(art_UNREAD, &filename, &question, &artNum) X`09== art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X foundArticle(filename, question, artNum); X `20 X return; X`7D X X X/*ARGSUSED*/ Xvoid XartKillAuthorFunction(widget) XWidget widget; X/* X * Allow user to mark all articles with the current author as read X * X * XXX get author, kill using data structures, rebuild SubjectString X * XXX merge this with artKillSession X */ X`7B X char *author; X char *curauthor; X char *filename, *question; X long artNum; X Arg args`5B3`5D; X `20 X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SelectionItem >= 0 && SelectionItem < SubjectItems) `7B X`09ArtPosition = SelectionItem; X `7D X if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X resetSelection(); X artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X author = XtNewString(getAuthor(artNum)); X ArtPosition = 0; X while (SubjectStrings`5BArtPosition`5D`5B0`5D != '\0') `7B X`09artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X`09curauthor = getAuthor(artNum); X`09/* only kill those that have not been marked as unread */ X`09if ((STREQ(author, curauthor)) && X`09 (SubjectStrings`5BArtPosition`5D`5B0`5D != 'u')) `7B X`09 markArticleAsRead(artNum); X`09`7D X`09ArtPosition++; X `7D X /* set the cursor back to the beginning of the subject screen */ X clearArtCache(); X FREE(author); X ArtPosition = 0; X infoNow("Author had been killed, returning to first unread article"); X resetSubjectWidget(UNREAD, True); X if (SubjectItems == 0 `7C`7C`20 X`09getNearbyArticle(art_UNREAD, &filename, &question, &artNum) X`09== art_DONE) `7B X`09exitArticleMode(); X`09return; X `7D X foundArticle(filename, question, artNum); X `20 X return; X`7D X X X/*ARGSUSED*/ Xvoid XartKillLocalFunction(widget) XWidget widget; X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X artKillSessionFunction(widget); X killItem(SubjectKilled, KILL_LOCAL); X FREE(SubjectKilled); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartKillGlobalFunction(widget) XWidget widget; X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X artKillSessionFunction(widget); X killItem(SubjectKilled, KILL_GLOBAL); X FREE(SubjectKilled); X return; X`7D X X X/*ARGSUSED*/ Xstatic void XartListOldFunction(widget) XWidget widget; X`7B X char *filename, *question; X int SavePosition; X int status; X long artNum; X Arg sargs`5B5`5D; X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X X busyCursor(); X resetSelection(); `20 X SavePosition = ArtPosition; X X artNum = newsgroup->first; X while (artNum<=newsgroup->last && IS_UNAVAIL(articles`5BINDEX(artNum)`5D V)) X `7BartNum++;`7D X `20 X status = moveToArticle(artNum, &filename, &question); X X switch (status) `7B X X case NOMATCH: X`09mesgPane(XRN_SERIOUS, X`09 "First article (number %d) not available", artNum); X X case ERROR: X`09ArtPosition = SavePosition; X`09break; X X case MATCH: X`09resetSubjectWidget(ALL, False); X`09ArtPosition = 0; X`09foundArticle(filename, question, artNum); X`09break; X `7D X unbusyCursor(); X return; X`7D X X X/*ARGSUSED*/ Xstatic void XartCheckPointFunction(widget) XWidget widget; X/* X * update the .newsrc file X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X X while (!updatenewsrc()) X`09ehErrorRetryXRN("Cannot update the newsrc file", True); X X return; X`7D X X X#define XRNgotoArticle_ABORT`090 X#define XRNgotoArticle_DOIT`091 X Xstatic Widget GotoArticleBox = (Widget) 0; X X X/*ARGSUSED*/ Xstatic void`20 XgotoArticleHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X char *numberstr; X char *filename, *question; X int SavePosition; X int status; X int direction; X long artNum; X Arg args`5B3`5D; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X SListSelectAll(TopList, 0); X if ((int) client_data == XRNgotoArticle_ABORT) `7B X`09PopDownDialog(GotoArticleBox); X`09unbusyCursor(); X`09inCommand = 0; X`09return; X `7D X SavePosition = ArtPosition; X numberstr = GetDialogValue(GotoArticleBox); X if (numberstr == NIL(char)) `7B X`09mesgPane(XRN_INFO, "Bad article number"); X`09PopDownDialog(GotoArticleBox); X`09unbusyCursor(); X`09inCommand = 0; X`09return; X `7D X X artNum = atol(numberstr); X if (artNum == 0) `7B X`09mesgPane(XRN_SERIOUS, "Bad article number"); X`09PopDownDialog(GotoArticleBox); X`09unbusyCursor(); X`09inCommand = 0; X`09return; X `7D X `20 X status = moveToArticle(artNum, &filename, &question); X X switch (status) `7B X X case NOMATCH: X`09mesgPane(XRN_SERIOUS, "Article number %d not available", artNum); X`09break; X X case ERROR: X`09ArtPosition = SavePosition; X`09break; X X case MATCH: X`09foundArticle(filename, question, artNum); X`09break; X `7D X X PopDownDialog(GotoArticleBox); X unbusyCursor(); X inCommand = 0; X return; X`7D X/*ARGSUSED*/ Xvoid XartGotoArticleFunction(widget) XWidget widget; X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"doit", gotoArticleHandler, (caddr_t) XRNgotoArticle_DOIT`7D, X`09`7B"abort", gotoArticleHandler, (caddr_t) XRNgotoArticle_ABORT`7D, X `7D; X `20 X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (GotoArticleBox == (Widget) 0) `7B X`09GotoArticleBox = CreateDialog(TopLevel, "Article Number:", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(GotoArticleBox); X return; X`7D X X#define XRNsubSearch_ABORT 0 X#define XRNsubSearch_FORWARD 1 X#define XRNsubSearch_BACK 2 X Xstatic Widget SubSearchBox = (Widget) 0; X X#define CLEANUP \ X`09if (SubSearchBox) PopDownDialog(SubSearchBox); \ X`09inCommand = 0; \ X`09unbusyCursor(); X X X/*ARGSUSED*/ Xstatic void`20 XsubSearchHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X char *regexpr; X char *filename, *question; X int SavePosition; X int status; X int direction; X long artNum; X Arg args`5B3`5D; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X X busyCursor(); X resetSelection(); X if ((int) client_data == XRNsubSearch_ABORT) `7B X`09CLEANUP; X`09return; X `7D X if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X SavePosition = ArtPosition; X regexpr = GetDialogValue(SubSearchBox); X if (*regexpr == 0) `7B X`09if (LastRegexp == NIL(char)) `7B X`09 mesgPane(XRN_INFO, "No previous regular expression"); X`09 CLEANUP; X`09 return;`09 `20 X`09`7D X`09regexpr = LastRegexp; X `7D else `7B X`09if (LastRegexp != NIL(char)) `7B X`09 FREE(LastRegexp); X`09`7D X`09LastRegexp = XtNewString(regexpr); X `7D X `20 X /* XXX */ X if (SubSearchBox) PopDownDialog(SubSearchBox); X X direction = ((int) client_data == XRNsubSearch_FORWARD) ? FORWARD : BACK V; X LastSearch = direction; X status = subjectSearch(direction, SubjectStrings,`20 X`09`09`09 &ArtPosition, ArtPosition, LastRegexp, X`09`09`09 &filename, &question, &artNum); X switch (status) `7B X case ABORT: X`09infoNow("search aborted"); X`09ArtPosition = SavePosition; X`09subjSetPos(TopList, ArtPosition); X`09break; X case NOMATCH: X`09(void) sprintf(error_buffer, "Search for expression %s: no match was foun Vd", X`09`09 LastRegexp); X`09infoNow(error_buffer); X case ERROR: X`09ArtPosition = SavePosition; X`09subjSetPos(TopList, ArtPosition); X`09break; X case MATCH: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); X`09foundArticle(filename, question, artNum); X`09break; X case WINDOWCHANGE: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); X`09ArtPosition = 0; X`09resetSubjectWidget(ALL, False); X`09foundArticle(filename, question, artNum); X`09break; X case EXIT: X`09exitArticleMode(); X`09break; X `7D X CLEANUP; X return; X`7D X X X/*ARGSUSED*/ Xvoid XartSubSearchFunction(widget) XWidget widget; X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"forward", subSearchHandler, (caddr_t) XRNsubSearch_FORWARD`7D, X`09`7B"back", subSearchHandler, (caddr_t) XRNsubSearch_BACK`7D, X`09`7B"abort", subSearchHandler, (caddr_t) XRNsubSearch_ABORT`7D, X `7D; X `20 X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (SubSearchBox == (Widget) 0) `7B X`09SubSearchBox = CreateDialog(TopLevel, "Regular Expression?", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(SubSearchBox); X return; X`7D X X/*ARGSUSED*/ Xvoid XartCancelSearchFunction(widget) XWidget widget; X`7B X abortSet(); X`7D X X/*ARGSUSED*/ Xvoid XartContinueFunction(widget) XWidget widget; X/* X * Continue a previously started regular expression X * search of the subject lines. Search for same X * regular expression, in same direction. X */ X`7B X char *filename, *question; X int SavePosition; X int status; X long artNum; X Arg args`5B3`5D; X X if (LastRegexp == NULL) `7B X`09mesgPane(XRN_INFO, "No previous regular expression"); X`09return; X `7D X (void) sprintf(error_buffer, "Searching for expression %s", LastRegexp); X info(error_buffer); X resetSelection(); X SavePosition = ArtPosition; X status = subjectSearch(LastSearch, SubjectStrings, X`09`09`09 &ArtPosition, ArtPosition, LastRegexp, X`09`09`09 &filename, &question, &artNum); X switch (status) `7B X case ABORT: X`09infoNow("search aborted"); X`09ArtPosition = SavePosition; X`09subjSetPos(TopList, ArtPosition); X`09return; X case NOMATCH: X`09(void) sprintf(error_buffer, "Search for expression %s: no match was foun Vd", LastRegexp); X`09infoNow(error_buffer); X case ERROR: X`09ArtPosition = SavePosition; X`09subjSetPos(TopList, ArtPosition); X`09return; X case MATCH: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); `20 X`09foundArticle(filename, question, artNum); X`09return; X case WINDOWCHANGE: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); X`09ArtPosition = 0; X`09resetSubjectWidget(ALL, False); X`09foundArticle(filename, question, artNum); X`09return; X case EXIT: X`09exitArticleMode(); X`09return; X `7D X`7D X X/*ARGSUSED*/ Xvoid XartSortedFunction(widget) XWidget widget; X/* X * toggle order of sorting in subject widget and reload X */ X`7B X int artNum, newArtNum; X int i; X X if (ArtPosition < 0) ArtPosition = 0; X if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X if (SubjectStrings`5BArtPosition`5D`5B0`5D == '\0') `7B X`09ArtPosition = 0; X`09app_resources.sortedSubjects = !app_resources.sortedSubjects; X`09resetSubjectWidget(ALL, False); X`09return; X `7D X artNum = atol(&SubjectStrings`5BArtPosition`5D`5B2`5D); X app_resources.sortedSubjects = !app_resources.sortedSubjects; X resetSubjectWidget(ALL, False); X if (SubjectItems <= 0) return; X for (i=0; i < SubjectItems; i++) `7B X`09newArtNum = atol(&SubjectStrings`5Bi`5D`5B2`5D); X`09if (newArtNum == artNum) `7B X`09 ArtPosition = i; X`09 subjSetPos(TopList, ArtPosition); X`09 return; X`09`7D X `7D X ArtPosition = 0; X subjSetPos(TopList, ArtPosition); X`7D X`09 X/*ARGSUSED*/ Xvoid XartLastFunction(widget) XWidget widget; X/* X * Display the article accessed before the current one X */ X`7B X char *filename, *question; X long artNum = 0; X int status; X int SavePosition; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (PrevArticle <= 0) `7B X`09mesgPane(XRN_INFO, "No previous article"); X`09return; X `7D X X SavePosition = ArtPosition; X artNum = PrevArticle; X X status = moveToArticle(artNum, &filename, &question); X switch (status) `7B X X case NOMATCH: X`09mesgPane(XRN_SERIOUS, "Article number %d not available", artNum); X`09break; X X case ERROR: X`09ArtPosition = SavePosition; X`09break; X X case MATCH: X`09foundArticle(filename, question, artNum); X`09break; X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XartExitFunction(widget) XWidget widget; X/* X * Exit from the current newsgroup, marking all articles as X * unread X */ X`7B X int beg, end; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X beg = 0; X end = SubjectItems; X markArticles(SubjectStrings, beg, end, ' '); X exitArticleMode(); X `20 X return; X`7D X X X/*ARGSUSED*/ Xvoid XaddQuitFunction(widget) XWidget widget; X/* X * unsubscribe to the remaining groups and exit add mode X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X int left; X int status = UNSUBSCRIBE; X X if (Mode != ADD_MODE) `7B X`09return; X `7D X left = 0; X X /* X * go through the remaining groups, add them X * to the end of the newsrc and unsubscribe them X */ X while (left < AddGroupItems) `7B X`09(void) strcpy(newGroup, AddGroupsStrings`5Bleft`5D); X`09(void) addToNewsrcEnd(newGroup, status); X`09left++; X `7D X X exitAddMode(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XaddFirstFunction(widget) XWidget widget; X/* X * Find selected group(s) and add them to the .newsrc in the first position. X * Move the cursor to the next group. X * Update the AddGroupsStrings, going into newsgroup mode if it X * is NULL. Update the text window, update the insertion point. X * X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X char oldGroup`5BGROUP_NAME_SIZE`5D; X int status = SUBSCRIBE; X int first = 1; X int i; X X if (Mode != ADD_MODE) `7B X`09return; X `7D X if (SelectionItem == -1) `7B X`09currentGroup(Mode, AddGroupsStrings`5BAddGroupPosition`5D, newGroup); X`09(void) addToNewsrcBeginning(newGroup, status); X `7D else `7B X`09for (i = 0; i < AddGroupItems; i++) `7B X`09 if (SListIsSelected(TopList, i)) `7B X`09`09if (first) `7B X`09`09 currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09 (void) addToNewsrcBeginning(newGroup, status); X`09`09 (void) strcpy(oldGroup, newGroup); X`09`09 first = 0; X`09`09`7D else `7B X`09`09 currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09 (void) addToNewsrcAfterGroup(newGroup, oldGroup, status); X`09`09 (void) strcpy(oldGroup, newGroup); X`09`09`7D X`09 `7D X`09`7D X `7D X resetSelection(); X X /* update the text window */ X redrawAddListWidget(0); X if (AddGroupItems <= 0) `7B X`09exitAddMode(); X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XaddLastFunction(widget) XWidget widget; X/* X * add the currently selected group(s) to the end of the .newsrc file X * and subscribe to them. X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X int status = SUBSCRIBE; X int i; X X if (Mode != ADD_MODE) `7B X`09return; X `7D X if (SelectionItem == -1) `7B X`09currentGroup(Mode, AddGroupsStrings`5BAddGroupPosition`5D, newGroup); X`09(void) addToNewsrcEnd(newGroup, status); X `7D else `7B X`09for (i = 0; i < AddGroupItems; i++) `7B X`09 if (SListIsSelected(TopList, i)) `7B X`09`09currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09(void) addToNewsrcEnd(newGroup, status); X`09 `7D X`09`7D X `7D X resetSelection(); X redrawAddListWidget(0); X if (AddGroupItems <= 0) `7B X`09exitAddMode(); X `7D X `20 X return; X`7D X X X/* entering the name of a newsgroup to add after */ X X#define XRNadd_ADD 1 X#define XRNadd_ABORT 0 X Xstatic Widget AddBox = (Widget) 0; X X/*ARGSUSED*/ Xstatic void XaddHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X/* X * get the newsgroup to add a new newsgroup after in the .newsrc file X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X char oldGroup`5BGROUP_NAME_SIZE`5D; X int status = SUBSCRIBE; X int first = 1; X int i; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X X if (SelectionItem == -1) `7B X`09currentGroup(Mode, AddGroupsStrings`5BAddGroupPosition`5D, newGroup); X`09(void) addToNewsrcAfterGroup(newGroup,GetDialogValue(AddBox),status); X`09resetSelection(); X`09redrawAddListWidget(0); X`09if (AddGroupItems <= 0) `7B X`09 exitAddMode(); X`09`7D X`09PopDownDialog(AddBox); X`09unbusyCursor(); X`09inCommand = 0; X`09return; X `7D X for (i = 0; i < AddGroupItems; i++) `7B X`09if (SListIsSelected(TopList, i)) `7B X`09 if (first) `7B X`09`09currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09if (!addToNewsrcAfterGroup(newGroup, X`09`09`09`09 GetDialogValue(AddBox), X`09`09`09`09 status) == GOOD_GROUP) `7B X`09`09 return; X`09`09`7D else `7B X`09`09 first = 0; X`09`09`7D X`09 `7D else `7B X`09`09currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09(void) addToNewsrcAfterGroup(newGroup, oldGroup, status); X`09 `7D X`09 (void) strcpy(oldGroup, newGroup); X`09`7D X `7D X resetSelection(); X redrawAddListWidget(0); X if (AddGroupItems <= 0) `7B X`09exitAddMode(); X `7D X PopDownDialog(AddBox); X unbusyCursor(); X inCommand = 0; X return; X`7D X X X/*ARGSUSED*/ Xvoid XaddAfterFunction(widget) XWidget widget; X/* X * subscribe to a new newsgroup, adding after a particular group in the X * .newsrc file X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"add", addHandler, (caddr_t) XRNadd_ADD`7D, X`09`7B"abort", addHandler, (caddr_t) XRNadd_ABORT`7D, X `7D; X X if (Mode != ADD_MODE) `7B X`09return; X `7D X if (AddBox == (Widget) 0) `7B X`09AddBox = CreateDialog(TopLevel, "After which newsgroup?", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(AddBox); X return; X`7D X X X/*ARGSUSED*/ Xvoid XaddUnsubFunction(widget) XWidget widget; X/* X * add a group to the end of the .newsrc file as unsubscribed X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X int status = UNSUBSCRIBE; X int i; X X if (Mode != ADD_MODE) `7B X`09return; X `7D X if (SelectionItem == -1) `7B X`09currentGroup(Mode, AddGroupsStrings`5BAddGroupPosition`5D, newGroup); X`09(void) addToNewsrcEnd(newGroup, status); X `7D else `7B`09 X`09for (i = 0; i < AddGroupItems; i++) `7B X`09 if (SListIsSelected(TopList, i)) `7B X`09`09currentGroup(Mode, AddGroupsStrings`5Bi`5D, newGroup); X`09`09(void) addToNewsrcEnd(newGroup, status); X`09 `7D X`09`7D X `7D X resetSelection(); X redrawAddListWidget(0); X if (AddGroupItems <= 0)`7B X`09exitAddMode(); X `7D X return; X`7D X X X#define XRNsave_ABORT 0 X#define XRNsave_SAVE 1 X Xstatic Widget SaveBox = (Widget) 0; /* box for typing in the name of a file V */ X X/*ARGSUSED*/ Xstatic void XsaveHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X/* X * handler for the save box X */ X`7B X int i, start, end; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X busyCursor(); X PopDownDialog(SaveBox); X if ((int) client_data != XRNsave_ABORT) `7B X`09if (SelectionItem != -1) `7B X`09 for (i = 0; i < SubjectItems; i++) `7B X`09`09if (SListIsSelected(TopList, i)) `7B X`09`09 start = atol(&SubjectStrings`5Bi`5D`5B2`5D); X`09`09 end = start; X`09`09 (void) saveRangeOfArticles(GetDialogValue(SaveBox), start, end); X`09`09`7D X`09 `7D`20 X`09 markFunction('S'); X`09`7D else `7B X`09 if (saveCurrentArticle(GetDialogValue(SaveBox))) `7B X`09 SubjectStrings`5BArtPosition`5D`5B1`5D = 'S'; X`09`09SListUpdateLine(TopList, ArtPosition); X`09 `7D X`09`7D X `7D X subjSetPos(TopList, ArtPosition); X unbusyCursor(); X inCommand = 0; X return; X`7D `20 X X/*ARGSUSED*/ Xvoid XartSaveFunction(widget, ev, params, num_params) XWidget widget; XXEvent *ev; XString *params; XCardinal *num_params; X/* X * query the user about saving an article X * X * brings up a dialog box X * X * returns: void X * X */ X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"save", saveHandler, (caddr_t) XRNsave_SAVE`7D, X`09`7B"abort", saveHandler, (caddr_t) XRNsave_ABORT`7D, X `7D; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (num_params && *num_params == 1) `7B X`09int i, start, end; X`09char *SaveString; X X`09SaveString = params`5B0`5D; X `09busyCursor(); X X`09if (SelectionItem != -1) `7B X`09 for (i = 0; i < SubjectItems; i++) `7B X`09`09if (SListIsSelected(TopList, i)) `7B X`09`09 start = atol(&SubjectStrings`5Bi`5D`5B2`5D); X`09`09 end = start; X`09`09 (void) saveRangeOfArticles(SaveString, start, end); X`09`09`7D X`09 `7D`20 X`09 markFunction('S'); X`09`7D else `7B X`09 if (saveCurrentArticle(SaveString)) `7B X`09 SubjectStrings`5BArtPosition`5D`5B1`5D = 'S'; X`09`09SListUpdateLine(TopList, ArtPosition); X`09 `7D X`09`7D X`09return; X `7D X if (SaveBox == (Widget) 0) `7B X`09SaveBox = CreateDialog(TopLevel, "File Name?", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(SaveBox); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartPrintFunction(widget) XWidget widget; X`7B X#ifdef VMS X int status; X short msglen; X char buffer`5B1024`5D; X struct dsc$descriptor_s buf_desc = `7B sizeof(buffer)-1, X`09DSC$K_DTYPE_T, DSC$K_CLASS_S, buffer `7D; X X (void) sprintf(buffer, "%sARTICLE-%u.LIS", app_resources.tmpDir, X`09CurrentArticle); X if (saveCurrentArticle(buffer)) X `7B X`09(void) sprintf(buffer, "%s %sARTICLE-%u.LIS", X`09 app_resources.printCommand, app_resources.tmpDir, X`09 CurrentArticle); X`09status = system(buffer); X`09if (status & 1) `7B X`09 info("Article sucessfully queued"); X`09`7D else `7B X`09 status = SYS$GETMSG(status, &msglen, &buf_desc, 0, 0); X`09 buffer`5Bmsglen`5D = '\0'; X`09 mesgPane(XRN_SERIOUS, buffer); X`09`7D X `7D X X`7D X#else /* not VMS */ X char command`5B1024`5D; X X (void) sprintf(command, "`7C %s", app_resources.printCommand); X (void) saveCurrentArticle(command); X return; X`7D X#endif /* VMS */ X X/*ARGSUSED*/ Xvoid XartReplyFunction(widget) XWidget widget; X/* X * Allow user to post a reply to the currently posted article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X reply(); X return; X`7D X X X X/*ARGSUSED*/ Xvoid XartForwardFunction(widget) XWidget widget; X/* X * Allow user to forward an article to a user(s) X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X forward(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartGripeFunction(widget) XWidget widget; X/* X * Allow user to gripe X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X gripe(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartFollowupFunction(widget) XWidget widget; X/* X * Allow user to post a followup to the currently displayed article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X followup(); X return; X`7D X X/*ARGSUSED*/ Xvoid XartCancelFunction(widget) XWidget widget; X/* X * Allow user to post a followup to the currently displayed article X */ X`7B X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X cancelArticle(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XartRot13Function(widget) XWidget widget; X/* X * decrypt a joke X */ X`7B X char *filename, *question; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (toggleRotation(&filename, &question) == XRN_OKAY) `7B X`09redrawArticleWidget(filename, question); X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XartHeaderFunction(widget) XWidget widget; X`7B X char *filename, *question; X X if (Mode != ARTICLE_MODE) `7B X`09return; X `7D X if (toggleHeaders(&filename, &question) == XRN_OKAY) `7B X`09redrawArticleWidget(filename, question); X `7D X return; X`7D X X X#define SUB_STRING "subscribed " X#define UNSUB_STRING "unsubscribed" X X/*ARGSUSED*/ Xvoid XallQuitFunction(widget) XWidget widget; X/* X * Quit all groups mode. X */ X`7B X int i; X if (Mode != ALL_MODE) `7B X`09return; X `7D X /* destroy strings */ X `20 X if (AllGroupItems > 0) `7B X`09for (i=0; i= AllGroupItems) X`09AllPosition = AllGroupItems - 1; X subjSetPos(TopList, AllPosition); X return; X`7D X/*ARGSUSED*/ Xvoid XallScrollBackFunction(widget) XWidget widget; X/* X * called when the user wants to scroll the all groups window X */ X`7B X if (Mode != ALL_MODE) `7B X`09return; X `7D X AllPosition -= 9; X if (AllPosition < 0) X`09AllPosition = 0; X subjSetPos(TopList, AllPosition); X return; X`7D X X/*ARGSUSED*/ Xvoid XallGotoFunction(widget) XWidget widget; X/* X * Go to the current newsgroup. The current X * group is either the first group of a selection, X * or, if there is no selection, the group the cursor X * is currently on (if any). X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X int gbeg, gend; X int i; X X if (Mode != ALL_MODE) `7B X`09return; X `7D X X /* get the current group name */ X X if (SelectionItem < 0) `7B X`09SelectionItem = AllPosition; X`09SelectionCount = 1; X `7D X gbeg = SelectionItem; X gend = SelectionItem + SelectionCount; X if (gbeg >= AllGroupItems) gbeg = AllGroupItems - 1; X if (gend > AllGroupItems) gend = AllGroupItems; X resetSelection(); X if (gbeg < 0 `7C`7C gend < 0) return; X currentGroup(Mode, AllGroupsStrings`5Bgbeg`5D, newGroup); X X /* jump to the newsgroup */ X X if (jumpToNewsgroup(newGroup) == GOOD_GROUP) `7B X`09(void) strcpy(LastGroup, newGroup); X`09 X`09/* free string */ X X`09if (AllGroupItems > 0) `7B X`09 for (i=0; i < AllGroupItems; i++) `7B X`09`09FREE(AllGroupsStrings`5Bi`5D); X`09 `7D X`09 if (AllGroupsStrings != (char**)0) `7B X`09`09FREE(AllGroupsStrings); X`09`09AllGroupsStrings = (char**) 0; X`09 `7D X`09`7D X`09(void) switchToArticleMode(app_resources.autoRead); X`09return; X `7D X return; X`7D X X X/*ARGSUSED*/ Xvoid XallSelectFunction(widget) XWidget widget; X/* X * Make note of the groups that were selected X * to be moved. X */ X`7B X int i, count; X X if (Mode != ALL_MODE) `7B X`09return; X `7D X if (selSize < AllGroupItems) `7B X`09if (selList != NULL) FREE(selList); X`09selList = XtMalloc(AllGroupItems+1); X`09selSize = AllGroupItems; X `7D X count = 0; X for (i=0; i < AllGroupItems;i++) `7B X`09if (SListIsSelected(TopList, i)) `7B X`09 selList`5Bi`5D = 1; X`09 count++; X`09`7D else `7B X`09 selList`5Bi`5D = 0; X`09`7D X `7D X if (count == 0) `7B X`09count++; X`09selList`5BSListGetHighlight(TopList)`5D = 1; X `7D X resetSelection(); X selCount = count; X return; X`7D X X X/*ARGSUSED*/ Xvoid XallMoveFunction(widget) XWidget widget; X/* X * Move the previously selected groups to the position before the X * current selection X */ X`7B X char newGroup`5BGROUP_NAME_SIZE`5D; X char oldGroup`5BGROUP_NAME_SIZE`5D; X int status = SUBSCRIBE; X int moveTo; X int moveFrom; X int first = 1; X X if (Mode != ALL_MODE) `7B X`09return; X `7D X if (selCount == 0) `7B X`09mesgPane(XRN_INFO, "No groups were selected"); X`09return;`09 X `7D X if (SelectionItem < 0) `7B X`09mesgPane(XRN_INFO, "You must select a group to move before"); X`09return; X `7D X moveTo = SelectionItem; X if (moveTo >= AllGroupItems) moveTo = AllGroupItems - 1; X for (moveFrom = 0; moveFrom < AllGroupItems; moveFrom++) `7B X`09if (selList`5BmoveFrom`5D != 0) `7B X`09 currentMode(AllGroupsStrings`5BmoveFrom`5D, newGroup, &status); X`09 if (moveTo <= 0) `7B X`09 moveTo = 0; X`09 `09(void) addToNewsrcBeginning(newGroup, status); X`09 `09(void) strcpy(oldGroup, newGroup); X`09 `7D else `7B X`09`09if (first) `7B X`09`09 currentGroup(Mode, AllGroupsStrings`5BmoveTo-1`5D, oldGroup); X`09`09 (void) addToNewsrcAfterGroup(newGroup, oldGroup, status); X`09`09 first = 0; X`09`09`7D else `7B X`09`09 currentMode(AllGroupsStrings`5BmoveFrom`5D, newGroup, &status); X`09`09 (void) addToNewsrcAfterGroup(newGroup, oldGroup, status); X`09`09`7D X`09`09(void) strcpy(oldGroup, newGroup); X`09 `7D X`09`7D X `7D X selCount = 0; X resetSelection(); X redrawAllWidget(moveTo); X subjSetPos(TopList, moveTo); X return; X`7D X X X/*ARGSUSED*/ Xvoid XallToggleFunction(widget) XWidget widget; X/*`20 X * Change the order the groups appear on the screen. X */ X`7B X int i; X `20 X if (Mode != ALL_MODE) `7B X`09return; X `7D X X AllStatus = (AllStatus == 0) ? 1 : 0; X X /* make the new string and source */ X X AllGroupsStrings = getStatusString(AllStatus); X X for (AllGroupItems = 0; AllGroupsStrings`5BAllGroupItems`5D != NIL(char) V; X`09 AllGroupItems++); X X SListLoad(TopList, AllGroupsStrings, AllGroupItems); X currentTop = 0; X resetSelection(); X subjSetPos(TopList, 0); X X return; X`7D X X#define XRNallSearch_ABORT 0 X#define XRNallSearch_FORWARD 1 X#define XRNallSearch_BACK 2 X Xstatic Widget AllSearchBox = (Widget) 0; X X#undef CLEANUP X#define CLEANUP \ X`09if (AllSearchBox) PopDownDialog(AllSearchBox); \ X`09inCommand = 0; \ X`09unbusyCursor(); X X Xstatic int XgroupSearch(dir) Xint dir; X`7B X#ifdef SYSV_REGEX X extern char *regcmp(); X extern char *regex(); X#else X char *re_comp();`09`09/* regular expression routine */ X#endif X static char *reRet;`09`09/* returned by re_comp/regcmp */ X char newgroup`5B128`5D;`09`09/* group name of current line */ X X abortClear(); X X if (LastRegexp != NIL(char)) `7B X#ifdef SYSV_REGEX X`09if ((reRet = regcmp(LastRegexp, NULL)) == NULL) `7B X#else X`09if ((reRet = re_comp(LastRegexp)) != NULL) `7B X#endif X`09 /* bad regular expression */ X#ifdef SYSV_REGEX X`09 mesgPane(XRN_SERIOUS, "error in regular expression"); X#else X`09 mesgPane(XRN_SERIOUS, reRet); X#endif X`09 failedSearch(); X`09 return ERROR; X`09`7D X `7D X X if (dir == FORWARD) `7B X`09for (;;) `7B X`09 if (abortP()) `7B X`09`09return ABORT; X`09 `7D X`09 if (AllGroupsStrings`5BAllPosition`5D == NIL(char) `7C`7C X`09`09AllGroupsStrings`5BAllPosition`5D`5B0`5D == '\0') `7B X`09`09if (AllPosition == 0) `7B X X`09`09 /* the string is null, no more articles are left */ X X`09`09 return EXIT; X`09`09`7D X`09`09return NOMATCH; X`09 `7D X`09 AllPosition = AllPosition + 1; X`09 if (AllGroupsStrings`5BAllPosition`5D == NIL(char) `7C`7C X`09`09AllGroupsStrings`5BAllPosition`5D`5B0`5D == '\0') `7B X X`09`09/* reached end of string */ X X`09`09return NOMATCH; X`09 `7D X`09 currentGroup(Mode, AllGroupsStrings`5BAllPosition`5D, newgroup); X X#ifdef SYSV_REGEX X`09 if (regex(reRet, newgroup) != NULL) `7B X#else X`09 if (re_exec(newgroup)) `7B X#endif X`09`09/* found a match to the regular expression */ X X`09`09return MATCH; X`09 `7D X`09`7D X `7D else `7B X`09startSearch(); X`09for (;;) `7B X`09 if (abortP()) `7B X X`09`09/* reset pointers back to where we began, since the */ X`09`09/* search was aborted */ X X`09`09failedSearch(); X`09`09return ABORT; X`09 `7D X`09 if ((AllPosition == 0) && X`09`09(AllGroupsStrings`5BAllPosition`5D == NIL(char) `7C`7C X`09`09 AllGroupsStrings`5BAllPosition`5D`5B0`5D == '\0')) `7B X X`09`09/* no more articles remain, return to Newgroup mode */ X X`09`09return EXIT; X`09 `7D X`09 if (AllPosition != 0) `7B X X`09`09/* we are still within the subject list */ X X`09`09AllPosition = AllPosition - 1; X`09`09currentGroup(Mode, AllGroupsStrings`5BAllPosition`5D, newgroup); X X#ifdef SYSV_REGEX X`09`09if (regex(reRet, newgroup) != NULL) `7B X#else X`09`09if (re_exec(newgroup)) `7B X#endif X`09`09 /* an article matching the regular expression was found */ X X`09`09 return MATCH; X`09`09`7D X`09 `7D else `7B X`09`09failedSearch(); X`09`09return NOMATCH; X`09 `7D X`09`7D X `7D X`7D X/*ARGSUSED*/ Xstatic void`20 XallSearchHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X char *regexpr; X char *filename, *question; X int SavePosition; X int status; X int direction; X long artNum; X Arg args`5B3`5D; X X if (inCommand) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09return; X `7D X inCommand = 1; X X busyCursor(); X resetSelection(); X if ((int) client_data == XRNallSearch_ABORT) `7B X`09CLEANUP; X`09return; X `7D X if (AllPosition >= AllGroupItems) AllPosition = AllGroupItems - 1; X SavePosition = AllPosition; X regexpr = GetDialogValue(AllSearchBox); X if (*regexpr == 0) `7B X`09if (LastRegexp == NIL(char)) `7B X`09 mesgPane(XRN_INFO, "No previous regular expression"); X`09 CLEANUP; X`09 return;`09 `20 X`09`7D X`09regexpr = LastRegexp; X `7D else `7B X`09if (LastRegexp != NIL(char)) `7B X`09 FREE(LastRegexp); X`09`7D X`09LastRegexp = XtNewString(regexpr); X `7D X `20 X /* XXX */ X if (AllSearchBox) PopDownDialog(AllSearchBox); X X direction = ((int) client_data == XRNallSearch_FORWARD) ? FORWARD : BACK V; X LastSearch = direction; X status = groupSearch(direction); X switch (status) `7B X case ABORT: X`09infoNow("search aborted"); X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09break; X case NOMATCH: X`09(void) sprintf(error_buffer, "Search for expression %s: no match was foun Vd", X`09`09 LastRegexp); X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09infoNow(error_buffer); X case ERROR: X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09break; X case MATCH: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); X`09subjSetPos(TopList, AllPosition); X`09break; X case EXIT: X`09break; X `7D X CLEANUP; X return; X`7D X X X/*ARGSUSED*/ Xvoid XallSearchFunction(widget) XWidget widget; X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"forward", allSearchHandler, (caddr_t) XRNallSearch_FORWARD`7D, X`09`7B"back", allSearchHandler, (caddr_t) XRNallSearch_BACK`7D, X`09`7B"abort", allSearchHandler, (caddr_t) XRNallSearch_ABORT`7D, X `7D; X `20 X if (Mode != ALL_MODE) `7B X`09return; X `7D X if (AllSearchBox == (Widget) 0) `7B X`09AllSearchBox = CreateDialog(TopLevel, "Regular Expression?", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(AllSearchBox); X return; X`7D X X/*ARGSUSED*/ Xvoid XallCancelSearchFunction(widget) XWidget widget; X`7B X abortSet(); X`7D X X/*ARGSUSED*/ Xvoid XallContinueFunction(widget) XWidget widget; X/* X * Continue a previously started regular expression X * search of the subject lines. Search for same X * regular expression, in same direction. X */ X`7B X char *filename, *question; X int SavePosition; X int status; X long artNum; X Arg args`5B3`5D; X X if (LastRegexp == NULL) `7B X`09mesgPane(XRN_INFO, "No previous regular expression"); X`09return; X `7D X (void) sprintf(error_buffer, "Searching for expression %s", LastRegexp); X info(error_buffer); X resetSelection(); X SavePosition = AllPosition; X status = groupSearch(LastSearch); X X switch (status) `7B X case ABORT: X`09infoNow("search aborted"); X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09return; X case NOMATCH: X`09(void) sprintf(error_buffer, "Search for expression %s: no match was foun Vd", LastRegexp); X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09infoNow(error_buffer); X case ERROR: X`09AllPosition = SavePosition; X`09subjSetPos(TopList, AllPosition); X`09return; X case MATCH: X`09(void) sprintf(error_buffer, "Search for expression %s", LastRegexp); X`09infoNow(error_buffer); `20 X`09subjSetPos(TopList, AllPosition); X`09return; X case EXIT: X`09return; X `7D X`7D X X/* X * public routines X */ X Xvoid XdetermineMode() X/* X * determine the initial mode and set up Text, TopButtonBox, and Question X */ X`7B X /* set mode, handle text and question */ X PreviousMode = Mode; X `20 X /* X * article specific buttons, only create them if this is the first X * call to 'determineMode' X */ X if (PreviousMode == NO_MODE) `7B X`09createButtons(-1); X`09XtManageChildren(ArtSpecButtons, XtNumber(ArtSpecButtonList)); X `7D X if ((AddGroupsStrings = newGroups()) != (char**)0) `7B X`09Mode = ADD_MODE; X`09swapMode(); X`09setTopInfoLine("Select groups to `60add', `60quit' unsubscribes remaining V groups"); X`09GroupPosition = 0; X`09redrawAddListWidget(0); X `7D else `7B X`09Mode = NEWSGROUP_MODE; X`09GroupPosition = 0; X`09swapMode(); X`09redrawNewsgroupListWidget(); X`09/* update the question */ X`09if (GroupItems == 0) `7B X`09 setTopInfoLine("No more unread articles in the subscribed to newsgrou Vps"); X`09`7D else `7B X`09 setTopInfoLine("Operations apply to current selection or cursor posit Vion"); X`09`7D X `7D X setBottomInfoLine(""); X `20 X return; X`7D Xstatic void listSelect(w, closure, call_data) X Widget`09`09 w; X caddr_t`09`09 closure; X SListCallbackStruct *call_data; X`7B X SListCallbackStruct *cb = call_data; X X SelectionItem = cb->item_number; X SelectionCount = cb->item_count; X return; X`7D Xstatic void DoubleClick(w, closure, call_data) X Widget`09`09 w; X caddr_t`09`09 closure; X SListCallbackStruct *call_data; X`7B X SListCallbackStruct *cb = call_data; X X SelectionItem = cb->item_number; X X if (Mode == NEWSGROUP_MODE) `7B X`09if (app_resources.autoRead) `7B X`09 ngReadAction((Widget) 0, NULL, NULL, 0); X`09`7D else `7B X`09 ngOpenAction((Widget) 0, NULL, NULL, 0); X`09`7D X`09return; X `7D X if (Mode == ALL_MODE) `7B X`09allGotoAction((Widget) 0, NULL, NULL, 0); X`09return; X `7D X if (Mode == ARTICLE_MODE) `7B X`09if (inCommand) `7B X`09 XBell(XtDisplay(TopLevel), 0); X`09 return; X`09`7D X`09inCommand = 1; X`09busyCursor(); X`09ArtPosition = SelectionItem; X`09if (ArtPosition >= SubjectItems) ArtPosition = SubjectItems - 1; X`09artReadFunction((Widget) 0); X`09unbusyCursor(); X`09inCommand = 0; X`09return; X `7D X return; X`7D Xstatic void subjSetPos(w, position) X Widget w; X int position; X`7B X int delta; X X SListSelectAll(w, 0); X switch (Mode) `7B X`09case NEWSGROUP_MODE: X`09 GroupPosition = position; X`09 SListHighlight(w, position); X`09 break; X`09case ARTICLE_MODE: X`09 ArtPosition = position; X`09 SListHighlight(w, position); X`09 break; X`09case ADD_MODE: X`09 GroupPosition = position; X`09 SListHighlight(w, position); X`09 break; X`09case ALL_MODE: X`09 AllPosition = position; X`09 SListHighlight(w, position); X`09 break; X`09default: X`09 return; X `7D X X if (position < app_resources.maxLines) `7B X`09SListSetTop(w, 0); X`09currentTop = 0; X `7D else `7B X`09delta = position - currentTop;`09/* lines above position desired */ X`09if (delta < app_resources.minLines `7C`7C delta > app_resources.maxLines) V `7B X`09 currentTop = position - app_resources.minLines; X`09 SListSetTop(w, currentTop); X`09`7D X `7D`20 X`7D $ CALL UNPACK BUTTONS.C;1 124259623 $ create 'f' X#ifndef BUTTONS_H X#define BUTTONS_H X X/* X * $Header: /users/ricks/xrn/src/RCS/buttons.h,v 1.6 90/09/29 02:27:16 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * buttons.h: create and handle the buttons X * X */ X Xextern void determineMode(); Xextern void addTimeOut(); Xextern void abortSet(); X X#endif /* BUTTONS_H */ $ CALL UNPACK BUTTONS.H;1 2050587960 $ create 'f' X#define calvin_width 90 X#define calvin_height 90 X Xstatic char calvin_bits`5B`5D = `7B X 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x11, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x21, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x41, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x7e, 0x00, 0x81, 0x10, 0x29, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x8c, 0x0f, 0x01, 0x09, 0x2a, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x18, 0x38, 0x01, 0x0a, 0x2a, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x70, 0x60, 0x01, 0x04, 0x44, 0x81, 0x01, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xc0, 0xc1, 0x01, 0x0c, 0x44, 0x61, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x80, 0x1b, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0xe0, 0x06, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x20, 0xc0, 0x03, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xfc, 0x87, 0x1f, 0x00, 0x10, 0x01, 0x30, 0x00, 0x00, 0x00, X 0x00, 0xfe, 0x03, 0x0c, 0x00, 0x00, 0x10, 0x93, 0x20, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x13, 0x27, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x35, 0x1a, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x89, 0x2c, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x88, 0x20, 0x02, 0x00, 0x00, 0x00, X 0x00, 0xfe, 0x02, 0x00, 0x00, 0x70, 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0xc0, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0x23, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x00, 0x00, 0xbf, 0x23, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0xf0, 0xe7, 0xc7, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x18, 0xfc, 0x00, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x04, 0xee, 0x1f, 0x78, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xf4, 0xfe, 0x0f, 0x88, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x8e, 0x8f, 0x0f, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xf9, 0x8f, 0x0f, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xbf, 0x8d, 0x0f, 0x1c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x9f, 0xfd, 0x07, 0xe2, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x9f, 0xff, 0x03, 0x02, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xfe, 0xf1, 0x01, 0x02, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xfe, 0x00, 0x18, 0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xbc, 0x00, 0x10, 0x39, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x88, 0x00, 0x10, 0xc1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x88, 0x31, 0x10, 0x03, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x08, 0x0e, 0x88, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x08, 0x00, 0x84, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x08, 0x00, 0x83, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x08, 0xf8, 0xc0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x7e, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, X 0xc0, 0xc1, 0x10, 0x00, 0x38, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x20, 0x00, 0x71, 0xc0, 0x07, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x20, 0x13, 0x81, 0x3f, 0x38, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, X 0xe0, 0x08, 0x02, 0x07, 0xc0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x40, 0x44, 0x82, 0x38, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x20, 0x44, 0x44, 0xc1, 0x03, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x20, 0x46, 0xa4, 0x00, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x20, 0xa6, 0xa8, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0xc0, 0x99, 0xb0, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xc0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xc1, 0xff, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x51, 0x00, 0xfc, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x4a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x24, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xe0, 0xff, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0xf0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0x80, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0xe0, 0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0x80, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xe0, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x20, 0x00, 0xc0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x40, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x40, 0xfc, 0x3f, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x40, 0xfc, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xf0, 0xff, 0xbf, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x30, 0xf8, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xd0, 0x47, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xff, 0xff, 0x71, 0xf1, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, X 0x00, 0x80, 0xff, 0x7f, 0x1f, 0xce, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 X `7D; $ CALL UNPACK CALVIN.ICON;1 89862844 $ create 'f' X X/* X * $Header: /users/ricks/xrn/src/RCS/CHANGES,v 1.10 90/09/29 02:31:31 ricks V Exp Locker: ricks $ X */ X XXRN release 6.14: X X- next newsgroup / fed up cursor positioning bug fixed! X X- articles marked as unread will not be marked read by catch up and fed up X X- checkpoint button added to article mode (artCheckPoint) X X- line count can now be displayed in the subject index window X (use -displayLineCount) X Chris P. Ross X X- search regex groups in newsrc order X Per Hedeland X X- new tempnam.c function, posting bug fixed X Jonathan I. Kamens X X- author full name is controlled by a resource now, not a config parameter X (+/-authorFullName) X Mike Yang X X- configuration now based on SYSV defined, not BSD defined X Casey Leedom`09`09 X X- default print command passes 8-bit characters (for French sites) X Marcin Skubiszewski`09`09 X X- toggle groups changed to List Old and the output is in a new format X When a group contains only old news, the corresponding line is X `09" news in misc.misc ..." X instead of the old (and wrong) X `09"Unread news in misc.misc ..." X similarly, when a group is totally empty (which is unfrequent), the X line reads X `09" in misc.misc ..." X Marcin Skubiszewski`09`09 X X- new button in article mode: list old (artListOld) X lists all articles available in the group X Marcin Skubiszewski`09`09 X X- new format for "Unread news" lines in newsgroup mode X `09"Unread news in misc.misc 3 articles + 350 old" X where "+ 350 old" means that misc.misc contains 350 old messages. X This count is not always right, but it is right for the newsgroups X which never expire X`09Marcin Skubiszewski X X- new resources: saveString and resetSave. X saveString sets the default string to go in the Save dialog (the X default is the empty string, as before), and resetSave affects X whether or not the SaveString variable gets reset for each newsgroup. X David Elliott X X- fix so word wrapping works correctly X Jim Graham`09`09`09 X X- various bug fixes X Marc Evans`09`09`09 X Mike Yang X Per Hedeland X Casey Leedom`09`09 X Marcin Skubiszewski`09`09 X Greg McNutt`09`09`09 X X- man page updated (and flags/options now in alphabetical order) X X`0C XXRN release 6.13: X X- signature file is not automatically included if compiled with the`20 X INEWS_READ_SIG option (see config.h) X David Elliot`09`09`09 X- display local time instead of GMT (only works for SYSV machines right now, X how do you do it for a non-SYSV machine?) X (see USE_LOCALTIME and +/-displayLocalTime) X Mike Yang`09`09`09 X- the default distribution can now be set X (see DISTRIBUTION and -distribution) X- C-News does not (by default) reset the low number of the newsgroups X in the news active file, however many sites have programs to do this. X If you do, define FIXED_C_NEWS_ACTIVE_FILE) X- the goto newsgroup dialog now takes substrings and regular expressions X- new button in newsgroup mode: 'toggle groups', display all groups that X are currently subscribed to. X- SVR4 fixes X David Elliot`09`09`09 X- better editorCommand failure return information X David Elliot`09`09`09 X- bug fixes X - toggle header, rot13, typeahead X Per Hedeland`09`09 X- scroll bar stuff X Dan R. Greening`09`09 X- scrolling X Jim Graham`09`09`09 X- man page has been updated somewhat (still probably a bit out of date) X- new defines for machines that don't have TEMPNAM and STRSTR X`09(see config.h) X X`0C XXRN release 6.12: X X- a little faster (better use of X toolkit functions) X- word wrapping of postings and mail fixed X- uses less memory X jhsu@wsl.dec.com (define STUPIDMMU in config.h) X- fix for C-news low article number problem: X`09C-new does not update the low article number in the active file... X`09murphy@ufp.dco.dec.com X- Motif support X`09- add -DMOTIF to the compiler flags in the Imakefile X`09- link with -lXm rather than -lXaw and -lXmu X`09mikey%eukanuba.wpd@sgi.com X- icon title change for unread news X`09mikey%eukanuba.wpd@sgi.com X- addition of ansi-c prototypes`20 X`09mikey%eukanuba.wpd@sgi.com X- better author parsing (for author full name) X`09Odd Einar Aurbakken X- author full name in subject window (define AUTHOR_FULLNAME in config.h) X`09(also can be controlled by a resource, mikey%eukanuba.wpd@sgi.com) X- direct use of inews when posting (also: haozhou@acsu.buffalo.edu (hao zhou V)) X`09Odd Einar Aurbakken X- verboseKill option X`09Odd Einar Aurbakken X- artLast, artNext now show proper unread count X X X`0C XXRN release 6.11: X X- editorCommand program is now a separate process X- groups of articles can now be saved as a group X`09- select a group of articles, hit 'save', X`09 if a '%d' is in the string typed into the dialog box, X`09 it will be replaced with the article number. X- organization can now be set from the environment X`09(per@erix.ericsson.se) X- xrn -help no longer removes the lock file X- accelerators can now be specified in your resources file X`09(jik@pit-manager.mit.edu) X- much better error handling and recovery X`09(jik@pit-manager.mit.edu) X- fixed freeing of a non-malloced structure X`09(mikey@eukanuba.wpd.sgi.com) X- added blank lines in compositions X`09(mikey@eukanuba.wpd.sgi.com) X- lots of cleanup X`09(jik@pit-manager.mit.edu) X- fixed core dump problem X`09(jik@pit-manager.mit.edu) X- moved information dialog defaults to application defaults file X`09(jik@pit-manager.mit.edu) X- 'Message-ID' and 'Date' now added to postings and followups X`09(drw900@anusf.anu.edu.au) X - in my opinion, this is really the responsibility of the NNTP X server and news readers/posters have no business generating`20 X these fields... but there are a few NNTP servers that don't X do it (or don't spawn an inews that does it) X GENERATE_EXTRA_FIELDS in config.h turns on the generation of`20 X these 2 fields X- got rid of 'Cc: user' on forwards X- new resource (xrn.cc), allows the user to specify if a 'Cc' should X `09be added to a reply. X- newsgroup names can now have '$' in them X`09(dgreen@cs.ucla.edu + others) X- "--" now separates signatures and messages when posting X X X`0C XXRN release 6.10: X X- usage message can be requested when another xrn is running X`09(lock file is not checked until later on) X- title and iconName can be specified via X resources X`09(per@erix.ericsson.se) X- tmpDir is now tilde expanded X- artFedUp now allowed to have a confirm box X- changes to XRn.ad X`09(jik@pit-manager.mit.edu) X- better error handling in article saving code (and faster saving) X`09(jik@pit-manager.mit.edu) X- better handling of form feeds in articles X`09(per@erix.ericson.se) X- added 'Cc: user' to mail messages X- fixed bug that caused a core dump during automatic rescan X`09(per@ericom.ericsson.se) X- made prefetch_max a resource X`09(evans@decvax.dec.com) X- xrn.includePrefix for setting the include article text prefix X`09(defaults to "`7C> ") X- popups fixed X`09(jik@pit-manager.mit.edu) X- handles newsgroups of type 'x' X`09(jik@pit-manager.mit.edu) X- newsgroup names can now contain '&' X- better handling of multiple messages in the information dialog X- version number of XRN now stored in XRn.ad, so on startup XRN X can determine if the XRn.ad file is in sync with XRN X- xrn.cancelCount for specifying how many articles to scan before X`09popping up the 'cancel search' button X- added another way to specify the senders actual address (RETURN_HOST, X`09see config.h) (phil@BRL.MIL) X- better core dump handling, now a resource (xrn.dumpCore) X`09(jik@pit-manager.mit.edu) X- probably more that we forgot about... X X X`0C XXRN release (6.9): X X- support for gould machines (Hugues.Leroy@irisa.fr) X- fixed XRn.ad: X`09missing colon: jqj@rt-jqj.stanford.edu (JQ Johnson) X`09reordering bindings: he@idt.unit.no (Haavard Eidnes) X- commented out the following from Xresources.sample: X`09xrn.organization: UC Berkeley IC CAD Group X`09xrn.replyTo: ricks@berkeley.edu X users were copying the entire file verbatim and I was getting X replies to articles posted by others... X- better `60info line' messages for some of the buttons X- bug fixes to compose (many authors) X- ANSI-C updates for mesg.`7Bh,c`7D: Ken Raeburn X- bug fixes ito XFILESEARCHPATH code X X XXRN release (6.8): X X- bug fixes X - signature file now in the right place (various authors) X- XRN now detects if the application defaults file has not been installed X- posting group fix X- artFedUp X- documentation on widget hierarchy X- cancel button for stopping searches X X XXRN release (6.7): X X- bug fixes X - now return to the right now after next newsgroup X (Jonathan I. Kamens ) X - button box size at start is correct X (Jonathan I. Kamens ) X - topLines now works X- faster newsrc file backup X (Jonathan I. Kamens ) X- mail messages are now wordwrapped in the same manner that articles are X (Jonathan I. Kamens ) X- updated XRn.ad file X - default button labels, fixed key bindings, grips removed X (us, Salvador Pinto Abreu , X and Jonathan I. Kamens ) X- scroll and doTheRightThing work again (just like they did in the R3 versio Vn) X - a backwards scroll function also exists, default bound to 'b' X- SHORT_ICONNAME X - define this to keep your icon title small X (Mike Yang ) X- user-settable command button labels X - see XRn.ad X (Salvador Pinto Abreu ) X- select newsgroup / article X - click with the middle button in the index window (top text window) X on a newsgroup entry to enter the group, on a subject entry to read`20 X an article (just like the old double clicking) X (Salvador Pinto Abreu ) X- better Imakefile`20 X - handles the use of installed libraries better X (Mark Hastings ) X - handles saber X (Jonathan I. Kamens ) X- XFILESEARCHPATH added, see config.h X (Jonathan I. Kamens ) X X- the name of the article text widget was changed from X "text" to "articleText" X X XXRN release (6.6): X X- xmkmf X- IBM RT AOS patches X (Keith Moore ) X- titlebar removed and the title and iconName resources are set to X what the titlebar originally contained (you can define TITLEBAR in X config.h to get it back) X- pane bug fix: X`09Thanks! aw@rruxi.bae.bellcore.com (Andrew Wason) X XXRN release (6.5): X XNOTES: X X- R3 support has not been tested X- editorCommand has not been tested X- VMS support has not been tested X X- X11R4 support (define R3 to get R3 support, see config.h) X - use 'xrn*ShapeStyle: Oval' to get rounded buttons X- subscribes to groups that are entered via "goto group" X- ALT-MAILER-2 (Marc Evans ) X- NO_SENDMAIL removed, now use ALT-MAILER-2 X- PRINTER (???) X- if you goto a group from all mode, exiting the group will return you to X all mode X- mail messages are now folded in the same manner that article submissions X are folded X- bug fixes: X - using wrong text widget in some 'all mode' functions X`09(Mark J. Kilgard <@rice.edu:mjk@uncle-bens.rice.edu>) X - mesgPane is no longer editable X - freeing some already freed (or never allocated) memory X- if the lock file is on the same host and the xrn process is no longer X running, the lock file will be updated and xrn will be allowed to run X- save file name is not saved across newgroups X X XXRN release (6.4): X X- documented xrn.info: on/off (xrn +/-info) X- new define, FIXED_ACTIVE_FILE. Define this if your news system X defines its active file format such that if the first article number X and the last article number are the same, there are no articles X available (see config.h). This will speed up 'rescan' and startup. X- support for Swedish characters in group names X- new option: +/-typeAhead, +typeAhead allows typeahead, -typeAhead X disallows typeahead. X- bug fixes X - temp files were being left around if a posting was aborted X - fixed bugs from interacting buttons X - fixed timeOut problems X - fixed type-ahead, DO_NOT_EAT_TYPE_AHEAD gotten rid of X X XXRN release (6.3): X X- bug fixes X- eats type-ahead (I think... - #define DO_NOT_EAT_TYPE_AHEAD in config.h X`09if you don't like this feature) X- alternate mailer - calls 'send' rather than 'sendmail',`20 X allowing 'mh' aliases to be used (see the file ALT-MAILER) X`09(thanks to Chris Tengi ) X- auto rescan (see the description of -rescanTime in the man page) X`09(see RESCAN_TIME in config.h) X- informational messages to the Information window can be turned off X`09(see +/-info, xrn.info: on/off) X- better internal specification of buttons X- busy cursor works for key bindings and double clicking X- new defines: RESOLVER, NO_SENDMAIL, (see the file config.h) X`09(thanks to Greg Wohletz ) X- new hobbes bitmaps (to keep Calvin company) X`09(thanks to me and mead!devil!dem@decwrl.dec.com (Dave Myers)) X- cancel authorization check X`09(thanks to Andy Linton) X X XXRN release (6.2.1): X X- include config.h in cursor.c and utils.c X- removed sys/file.h from source files (included via X11/Xos.h) X- change #if SYSV_REGX to #ifdef SYSV_REGX in cursor.c X- fixed app defaults installation X- fixed width and height in app defaults X- composition window name change to "Composition" X- include file box would segv, fixed X- moved getinfofromfile to internals.c so other X implementations of clientlib can be used X- added v`7Bf,s`7Dprintf for those that don't have it in libc.a X- added strtok for those that don't have it in libc.a X- documented the new confirm boxes X- goto article screwed up for out of range article number, fixed X- indef's added so file/org/domain defines can be done in the X Imakefile X- char -> int in compose.c X- added button for scrolling X X XXRN release (6.2): X Xbug fixes X- print for VMS fixes (misinstalled patch) X `5Bthanks to Kevin Herbert `5D X- popup dialogs work better with sticky focus window managers X `5Bthanks to mikey@wsl.dec.com (Mike Yang)`5D X- added ':' to the end of the Article %ld in %s line in saved articles X (allows various mail programs to work on saved articles) X- installing add mode translations could occasionally core dump X- next newsgroup should work better now (no core dumps or infinite loops) X- fixed a few infinite loops X- the articles that have been read are no longer lost when you unsubscribe X to a group X Xkey bindings are no longer lost after using pop up dialogs. X Xinformation box geometry can now be specified: X`09xrn.Information.geometry:`20 X Xarticles can now be sorted by subjects. See xrn.sortedSubjects. X sorting is case insensitive and based on the first 24 characters X X"include file" now does tilde expansion X Xposting failures put you back in the composition window X Xdefault action for confirm dialog boxes is now 'yes'. X Xsupport for the macII running A/UX 1.1 (System V Rel 2 with BSD networking) X `5Bthanks to glenn@mathcs.emory.edu (Glenn T. Barry)`5D X Xsupport for HPUX X `5Bthanks to jp@hplb.hpl.hp.com (Julian Perry)`5D X Xeven better kill file support X- regular expressions are supported in the kill pattern X (still missing: all the various possible commands that can be used) X- better kill file entries generated X XNN 'Re`5E#:' is understood and dealt with. X Xconfirm boxes are now available on a per-button basis. XSee xrn.confirm in the man page. X Xsubject next now uses a case insensitive/24 character comparision X Xrn bindings are in the app-defaults file and are now the default bindings X Xinternals X- better 'mesgPane' interface X `5Bthanks to mtoy%there.esd.sgi.com@sgi.sgi.com (Michael Toy)`5D X X XXRN release (6.1): X Xbug fixes X - insertion point for compose windows now in the right place X - tabs and new lines can now be in *ButtonList: X resources X - occasionally xrn would die due to not being able to open X the newsrc temp file - this has been fixed X - garbage text in error label during subject next gotten rid of X - group names can now be longer than 32 characters X`09'hp-factory.software-eng.excalibur' can now be read X - busy cursor appears all of the times when XRN is busy X - top window redraws correctly - going from all/ng mode to X article mode, if the group was empty, you would pop back out X to all/ng mode, but without any text in the top window X - control C now aborts a subject search X - exiting out of All mode had some problems X (thanks to Rich Simoni ) X Xpopup mesg window X - no more output to stderr X - much of the error/warning output that went to the top info/help X label now goes to the mesg window X Xdefines to deal with various toolkit/window manger problems X - see config.h X Xconfirm box on XRN quit/exit X Xkey bindings now work in all widgets, not just the button box X XVMS support (thanks to Kevin Herbert ) X Xxrn checks to see if another xrn is running - the .rnlock file X used by rn is not used. XRN stores the host that XRN is running X on in addition to the process id. X Xkey bindings are now exported: X - four new resources/command line options: X`09addBindings, artBindings, allBindings, ngBindings X - see the man page for more information X XSet of RN-like keybindings for XRN X (thanks to Jeff Wallace ) X XNew configuration parameter: SUBJECTS (config.h) X - the number of subject lines to prefetch when doing a backwards X subject search. The default is 10 X Xturning off kill file support: X - for those of you that don't use kill files, the searching`20 X for kill files can be turned off. The kill buttons remain X if you want to add something to a kill file, but they will X not be processed. See the +/-killFiles option. X XngLastGroup changed to ngPrevGroup X - last group confused some people who thought it meant go to X the last group displayed in the newsgroup index. X Xnew button in article specific pane: print X - print an article, uses the 'printCommand' resource/command line option X (defaults to 'enscript') X Xnew button in composition pane: include file X - includes a file in a posting - like Meta-I in the text X widget, but: (1) does not screw up your keyboard bindings, X and (2) has an accelerator. X Xincluding an article now only includes the text (strips the header). X - this can be changed via the 'includeHeader' option. X (thanks to Paul Raveling ) X Xthe .newsrc file can now be automatically updated when leaving article X mode - see the `60updateNewsrc' option. X Xslightly better KILL file support X - killing based on author name supported X - more formats of kill file entries supported X Xarticles can be saved into newsgroup `60folders', like 'xmh'. see the X saveMode option (thanks to Paul Raveling ) X XMore ways to specify the domain, hidden host, new hidden path, ... X (thanks to Frederick M. Avolio (avolio@decuac.dec.com) X - see config.h X XUSC ISI app-defaults file for XRN included (isi.app-defaults) X (thanks to Paul Raveling ) X X'abort' option in the death notifier dialog now dumps core in Xthe real stack rather than the signal stack (thanks to KJ Pires X- before looking for just X . X X- includeSep X X A new Xdefault has been added to get rid of the "> " characters X put in front of included messages. Xdefault: X`09 X`09 includeSep: on/off X X Command Line: X X`09 +/-includeSep X X- header lines are no longer broken X X The last release included code to break long lines in news postings X to reasonable values. Unfortunately it would also break header X lines (which is not allowed). This version does not break the lines. X X- updated man page X X The man page has been updated to reflect the current state of XRN. X X- double click X X `5Bnote: this feature has not been added to the man page - it still X has some problems`5D X X Double clicking on a newgroup entry will send you to the group. X Double clicking on an article entry will display the article. X X X X`09`09Rick Spickelmier (ricks@ic..berkeley.edu) X`09`09Ellen Sentovich (ellen@ic..berkeley.edu) X $ CALL UNPACK CHANGES.;1 1733126932 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/clientlib.c, Vv 1.12 90/09/29 01:12:27 ricks Exp $"; X#endif X X/* X * nntp client interface X * X * Copyright (c) 1988, 1989, 1990, The Regents of the University of Californ Via. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X#ifndef VMS X#include X#else X#define index strchr X/* X * Define UCX if you want UCX TCP/IP transport for VMS. X * Define CMU_TCP for CMU TCP/IP transport. (Code supplied by Mike Iglesias, X`09`09`09`09 iglesias@draco.acs.uci.edu) X * Define FUSION for Fusion TCP/IP. (Code Supplied by Ken Robinson, X`09`09`09`09 robinson@cp0201.bellcore.com) X * Define WOLLONGONG for WIN/TCP. X */ X X#if defined(UCX) `7C`7C defined(CMU_TCP) `7C`7C defined(FUSION) `7C`7C defin Ved (WOLLONGONG) X#define VMS_TCPIP X#else X#define VMS_DECNET X#endif`20 X X#include X X#define NNTP_PORT_NUMBER 119 X#define index strchr X X#ifdef CMU_TCP X#include X#include X#include X#define TCP$OPEN IO$_CREATE X#define TCP$READ IO$_READVBLK X#define TCP$SEND IO$_WRITEVBLK X#define TCP$CLISE IO$_DELETE X#endif /* CMU_TCP */ X X#if defined(VMS_UCX) `7C`7C defined(WOLLONGONG) X#include X#include X#include X#endif /* VMS_UCX or WOLLONGONG */ X X#ifdef FUSION X#include X#include X#include X#include X#endif /* FUSION */ X X#ifdef VMS_DECNET X#include X#include X#define NNTPobject "::\"0=NNTP\"" X#endif /* VMS_DECNET */ X X#endif /* VMS */ X#include X X#ifndef VMS X#include X#include X#include X#endif /* VMS */ X X#ifdef DECNET X#include X#include X#endif X X#include "codes.h" X#include "config.h" X#include "utils.h" X Xvoid close_server(); X#ifdef BSD_BFUNCS X#define memset(_Str_, _Chr_, _Len_) bzero(_Str_, _Len_) X#define memcpy(_To_, _From_, _Len_) bcopy(_From_, _To_, _Len_) X#endif X Xstatic FILE`09*ser_rd_fp = NULL; Xstatic FILE`09*ser_wr_fp = NULL; Xstatic Boolean`09ServerOpen = False; Xstatic int`09sockt_rd, sockt_wr; X X#ifdef CMU_TCP Xstatic unsigned short cmu_chan; X$DESCRIPTOR (cmu_ip, "IP0"); Xint status; Xstruct iosb_str `7B X short stat; /* status */ X short count; /* Byte count */ X int`09 info;`09 /* additional info */ X`7D; Xstruct iosb_str iosb; X#endif /* CMU_TCP */ X/* X * getserverbyfile`09Get the name of a server from a named file. X *`09`09`09Handle white space and comments. X *`09`09`09Use NNTPSERVER environment variable if set. X * X *`09Parameters:`09"file" is the name of the file to read. X * X *`09Returns:`09Pointer to static data area containing the X *`09`09`09first non-ws/comment line in the file. X *`09`09`09NULL on error (or lack of entry in file). X * X *`09Side effects:`09None. X */ X Xchar * Xgetserverbyfile(file) Xchar`09*file; X`7B X char *cp; X extern char *getenv(), *getinfofromfile(); X static char`09buf`5B256`5D; X X if (cp = getenv("NNTPSERVER")) `7B X`09(void) strcpy(buf, cp); X `7D else `7B X`09cp = getinfofromfile(file); X`09if (cp == NULL) `7B X`09 return(NULL); X`09`7D else `7B X`09 (void) strcpy(buf, cp); X`09`7D X `7D X return (buf); X`7D X X/* X * server_init Get a connection to the remote news server. X * X *`09Parameters:`09"machine" is the machine to connect to. X * X *`09Returns:`09-1 on error X *`09`09`09server's initial response code on success. X * X *`09Side effects:`09Connects to server. X *`09`09`09"ser_rd_fp" and "ser_wr_fp" are fp's X *`09`09`09for reading and writing to server. X */ X Xserver_init(machine) Xchar`09*machine; X`7B X`09char`09line`5B256`5D; X#ifdef VMS_DECNET X`09static char *in_buffer = NULL, *out_buffer = NULL; X X`09close_server();`09`09`09`09/* make sure it's closed */ X`09(void) close(sockt_rd); X`09(void) close(sockt_wr); X`09sockt_rd = get_dnet_socket(machine); X#else /* not VMS_DECNET */ X X#ifdef DECNET X`09char`09*cp; X X`09cp = index(machine, ':'); X X`09if (cp && cp`5B1`5D == ':') `7B X`09`09*cp = '\0'; X`09`09sockt_rd = get_dnet_socket(machine); X`09`09*cp = ':'; X`09`7D else X`09`09sockt_rd = get_tcp_socket(machine); X#else /* DECNET */ X#ifndef CMU_TCP X`09sockt_rd = get_tcp_socket(machine); X#else X`09sockt_rd = get_cmutcp_socket(machine); X#endif /* CMU_TCP */ X#endif /* DECNET */ X#endif /* VMS_DECNET */ X X`09if (sockt_rd < 0) X`09`09return (-1); X X`09/* X`09 * Now we'll make file pointers (i.e., buffered I/O) out of X`09 * the socket file descriptor. Note that we can't just X`09 * open a fp for reading and writing -- we have to open X`09 * up two separate fp's, one for reading, one for writing. X`09 */ X X#ifndef VMS_TCPIP X#ifndef VMS_DECNET X`09if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) `7B X`09`09perror("server_init: fdopen #1"); X`09`09return (-1); X`09`7D X X`09sockt_wr = dup(sockt_rd); X`09if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) `7B X`09`09perror("server_init: fdopen #2"); X`09`09ser_rd_fp = NULL;`09`09/* from above */ X`09`09return (-1); X`09`7D X#else /* VMS_DECNET */ X`09if (in_buffer == NULL) `7B X`09 if ((in_buffer = XtMalloc(8192)) == NULL) `7B X`09 perror("in buffer malloc failed."); X`09 return (-1); X`09 `7D X`09`7D X`09if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) `7B X`09`09perror("server_init: fdopen #1"); X`09`09return (-1); X`09`7D X`09if (setvbuf(ser_rd_fp, in_buffer, _IOLBF, 8192)) `7B X`09 perror("setvbuf"); X`09 return (-1); X`09`7D X`09if (out_buffer == NULL) `7B X`09 if ((out_buffer = XtMalloc(8192)) == NULL) `7B X`09 perror("out buffer malloc failed."); X`09 return (-1); X`09 `7D X`09`7D X`09if ((ser_wr_fp = fdopen(sockt_rd, "w")) == NULL) `7B X`09`09perror("server_init: fdopen #2"); X`09`09ser_rd_fp = NULL;`09`09/* from above */ X`09`09return (-1); X`09`7D X`09if (setvbuf(ser_wr_fp, out_buffer, _IOLBF, 8192)) `7B X`09 perror("setvbuf"); X`09 return (-1); X`09`7D X#endif /* VMS_DECNET */ X#endif /* VMS_TCPIP */ X X`09ServerOpen = True; X`09/* Now get the server's signon message */ X X`09(void) get_server(line, sizeof(line)); X`09return (atoi(line)); X`7D X X#ifndef VMS_DECNET X#ifndef CMU_TCP X/* X * get_tcp_socket -- get us a socket connected to the news server. X * X *`09Parameters:`09"machine" is the machine the server is running on. X * X *`09Returns:`09Socket connected to the news server if X *`09`09`09all is ok, else -1 on error. X * X *`09Side effects:`09Connects to server. X * X *`09Errors:`09`09Printed via perror. X */ X Xget_tcp_socket(machine) Xchar`09*machine; X`7B X`09int`09s; X#ifdef h_addr X`09int x = 0; X`09register char **cp; X#endif /* h_addr */ X X#ifdef FUSION X#define gethostbyname ghbyname X#endif X`09struct`09sockaddr_in sin; X`09struct`09servent *getservbyname(), *sp; X`09struct`09hostent *gethostbyname(), *hp; X X`09if ((hp = gethostbyname(machine)) == NULL) `7B X`09`09(void) fprintf(stderr, "%s: Unknown host.\n", machine); X`09`09return (-1); X`09`7D X X#ifndef VMS X`09if ((sp = getservbyname("nntp", "tcp")) == NULL) `7B X`09`09(void) fprintf(stderr, "nntp/tcp: Unknown service.\n"); X`09`09return (-1); X`09`7D X#endif X X`09(void) memset((char *) &sin, 0, sizeof(sin)); X`09sin.sin_family = hp->h_addrtype; X#ifndef VMS X`09sin.sin_port = sp->s_port; X#else X`09sin.sin_port = htons(NNTP_PORT_NUMBER); X#endif X X`09/* X`09 * The following is kinda gross. The name server under 4.3 X`09 * returns a list of addresses, each of which should be tried X`09 * in turn if the previous one fails. However, 4.2 hostent X`09 * structure doesn't have this list of addresses. X`09 * Under 4.3, h_addr is a #define to h_addr_list`5B0`5D. X`09 * We use this to figure out whether to include the NS specific X`09 * code... X`09 */ X X#if defined(h_addr) X`09/* get a socket and initiate connection -- use multiple addresses */ X X`09for (cp = hp->h_addr_list; cp && *cp; cp++) `7B X`09`09s = socket(hp->h_addrtype, SOCK_STREAM, 0); X`09`09if (s < 0) `7B X`09`09`09(void) perror("socket"); X`09`09`09return (-1); X`09`09`7D X`09`09(void) memcpy((char *) &sin.sin_addr, *cp, hp->h_length); X`09`09 X`09`09if (x < 0) `7B X`09`09 (void) fprintf(stderr, "trying %s\n", inet_ntoa(sin.sin_addr)); X`09`09`7D X`09`09x = connect(s, (struct sockaddr *)&sin, sizeof (sin)); X`09`09if (x == 0) X`09`09`09break; X (void) fprintf(stderr, "connection to %s: ", inet_ntoa(sin.s Vin_addr)); X`09`09(void) perror(""); X`09`09(void) close(s); X`09`7D X`09if (x < 0) `7B X`09`09(void) fprintf(stderr, "giving up...\n"); X`09`09return (-1); X`09`7D X#else`09/* no name server */ X X`09if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) `7B /* Get the socket */ X`09`09(void) perror("socket"); X`09`09return (-1); X`09`7D X X`09/* And then connect */ X X`09(void) memcpy((char *) &sin.sin_addr, hp->h_addr, hp->h_length); X`09if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) `7B X`09`09(void) perror("connect"); X`09`09(void) close(s); X`09`09return (-1); X`09`7D X X#endif X`09ServerOpen = True; X`09return (s); X`7D X X#else /* CMU_TCP */ X/* X * get_cmutcp_socket -- get us a CMU TCP/IP socket connected to the news ser Vver X * X *`09Paremeters:`09"machine" is the machine the server is running on. X * X *`09Returns:`09Socket connected to the news server if X *`09`09`09all is ok, else -1 on error. X * X *`09Side effects:`09Connects to server. X * X *`09Errors:`09`09Printed vua perror. X */ Xget_cmutcp_socket (machine) Xchar *machine; X`7B X int stat; X X /* first, open a channel to the IP0 device */ X if (((stat = SYS$ASSIGN(&cmu_ip, &cmu_chan, 0, 0)) & 1) != 1) X`09return (-1); X X /* now connect to the server */ X X stat = SYS$QIOW (0, cmu_chan, TCP$OPEN, &iosb, 0, 0, machine, X`09`09 NNTP_PORT_NUMBER, 0, 1, 0, 0); X if ((stat & 1) != 1) return (-1); X if (iosb.stat == SS$_ABORT) return (-1); X return (1); X`7D X#endif /* CMU_TCP */ X#endif /* VMS_DECNET */ X X#if defined(DECNET) `7C`7C defined(VMS_DECNET) X/* X * get_dnet_socket -- get us a socket connected to the news server. X * X *`09Parameters:`09"machine" is the machine the server is running on. X * X *`09Returns:`09Socket connected to the news server if X *`09`09`09all is ok, else -1 on error. X * X *`09Side effects:`09Connects to server. X * X *`09Errors:`09`09Printed via nerror. X */ X Xget_dnet_socket(machine) Xchar`09*machine; X`7B X#ifdef VMS X`09char *connect; X`09int`09s,colon; X X`09colon = ((char *) colon=index(machine, ':')) ? ((char *)colon)-machine : X`09`09strlen(machine); X X`09connect = ARRAYALLOC(char, ((int) colon+sizeof NNTPobject+1)); X`09(void) strncpy(connect, machine, colon); X`09(void) strcpy(&connect`5Bcolon`5D, NNTPobject); X`09 X`09if ((s = open(connect, O_RDWR, 0)) == -1) `7B X`09 perror("open"); X`09 FREE(connect); X`09 return (-1); X`09`7D X X`09FREE(connect); X X#else /* Not VMS */ X X`09int`09s, area, node; X`09struct`09sockaddr_dn sdn; X`09struct`09nodeent *getnodebyname(), *np; X X`09(void) memset((char *) &sdn, 0, sizeof(sdn)); X X`09switch (s = sscanf( machine, "%d%*`5B.`5D%d", &area, &node )) `7B X`09`09case 1:`20 X`09`09`09node = area; X`09`09`09area = 0; X`09`09case 2:`20 X`09`09`09node += area*1024; X`09`09`09sdn.sdn_add.a_len = 2; X`09`09`09sdn.sdn_family = AF_DECnet; X`09`09`09sdn.sdn_add.a_addr`5B0`5D = node % 256; X`09`09`09sdn.sdn_add.a_addr`5B1`5D = node / 256; X`09`09`09break; X`09`09default: X`09`09`09if ((np = getnodebyname(machine)) == NULL) `7B X`09`09`09 (void) fprintf(stderr,`20 X`09`09`09`09 "%s: Unknown host.\n", machine); X`09`09`09 return (-1); X`09`09`09`7D else `7B X`09`09`09 (void) memcpy((char *) sdn.sdn_add.a_addr,`20 X`09`09`09`09`09 np->n_addr,`20 X`09`09`09`09`09 np->n_length); X`09`09`09 sdn.sdn_add.a_len = np->n_length; X`09`09`09 sdn.sdn_family = np->n_addrtype; X`09`09`09`7D X`09`09`09break; X`09`7D X`09sdn.sdn_objnum = 0; X`09sdn.sdn_flags = 0; X`09sdn.sdn_objnamel = strlen("NNTP"); X`09(void) memcpy(&sdn.sdn_objname`5B0`5D, "NNTP", sdn.sdn_objnamel); X X`09if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) `7B X`09`09nerror("socket"); X`09`09return (-1); X`09`7D X X`09/* And then connect */ X X`09if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) `7B X`09`09nerror("connect"); X`09`09close(s); X`09`09return (-1); X`09`7D X#endif /* VMS */ X X`09ServerOpen = True; X`09return (s); X`7D X#endif /* DECNET or VMS */ X X/* X * handle_server_response X * X *`09Print some informative messages based on the server's initial X *`09response code. This is here so inews, rn, etc. can share X *`09the code. X * X *`09Parameters:`09"response" is the response code which the X *`09`09`09server sent us, presumably from "server_init", X *`09`09`09above. X *`09`09`09"server" is the news server we got the X *`09`09`09response code from. X * X *`09Returns:`09-1 if the error is fatal (and we should exit). X *`09`09`090 otherwise. X * X *`09Side effects:`09None. X */ X Xhandle_server_response(response, server) Xint`09response; Xchar`09*server; X`7B X switch (response) `7B X`09case OK_NOPOST:`09`09/* fall through */ X `09`09printf( X`09"NOTE: This machine does not have permission to post articles.\n"); X`09`09printf( X`09" Please don't waste your time trying.\n\n"); X X`09case OK_CANPOST: X`09`09return (0); X X`09case ERR_ACCESS: X`09`09printf( X "This machine does not have permission to use the %s news server.\n", X`09`09server); X`09`09return (-1); X X`09default: X`09`09printf("Unexpected response code from %s news server: %d\n", X`09`09`09server, response); X`09`09return (-1); X `7D X`09/*NOTREACHED*/ X`7D X X X/* X * put_server -- send a line of text to the server, terminating it X * with CR and LF, as per ARPA standard. X * X *`09Parameters:`09"string" is the string to be sent to the X *`09`09`09server. X * X *`09Returns:`09Nothing. X * X *`09Side effects:`09Talks to the server. X * X *`09Note:`09`09This routine flushes the buffer each time X *`09`09`09it is called. For large transmissions X *`09`09`09(i.e., posting news) don't use it. Instead, X *`09`09`09do the fprintf's yourself, and then a final X *`09`09`09fflush. X */ X Xvoid Xput_server(string) Xchar *string; X`7B X#ifdef CMU_TCP X static char crlf`5B`5D = "\r\n"; X#endif /* CMU_TCP */ X`09if (!ServerOpen) X`09`09start_server(NIL(char)); X#ifdef DEBUG X`09(void) fprintf(stderr, ">>> %s\n", string); X#endif X#ifndef VMS_TCPIP X`09(void) fprintf(ser_wr_fp, "%s\r\n", string); X`09(void) fflush(ser_wr_fp); X#else X#ifndef CMU_TCP X`09(void) send(sockt_rd, string, strlen(string),0);`09 X`09(void) send(sockt_rd, "\r\n", 2, 0); X#else X`09status = SYS$QIOW (0, cmu_chan, TCP$SEND, &iosb, 0, 0, X`09`09`09 string, strlen(string), 0, 0, 0, 0); X`09status = SYS$QIOW (0, cmu_chan, TCP$SEND, &iosb, 0, 0, X`09`09`09 crlf, 2, 0, 0, 0, 0); X#endif /* CMU_TCP */ X#endif X`7D X X X/* X * get_server -- get a line of text from the server. Strips X * CR's and LF's. X * X *`09Parameters:`09"string" has the buffer space for the X *`09`09`09line received. X *`09`09`09"size" is the size of the buffer. X * X *`09Returns:`09-1 on error, 0 otherwise. X * X *`09Side effects:`09Talks to server, changes contents of "string". X */ X Xget_server(string, size) Xchar`09*string; Xint`09size; X`7B X`09register char *cp; X#ifdef VMS_TCPIP X`09static char netBuf`5B1025`5D; X`09static int inBuf = 0; X`09static char *bufPtr; X`09static int level = 0; X`09int ret; X#endif X X`09if (!ServerOpen) X`09`09start_server(NIL(char)); X X#ifndef VMS_TCPIP X`09if (fgets(string, size, ser_rd_fp) == NULL) X`09`09return (-1); X`09if ((cp = index(string, '\r')) != NULL) X`09`09*cp = '\0'; X`09else if ((cp = index(string, '\n')) != NULL) X`09`09*cp = '\0'; X#else X`09if (level == 0) X`09 *string = '\0'; X`09if (inBuf <= 0) `7B X#ifndef CMU_TCP X`09 if ((inBuf = recv(sockt_rd, netBuf, sizeof(netBuf)-1,0)) == -1)`20 X`09`09return (-1); X#else X`09 status = SYS$QIOW (0, cmu_chan, TCP$READ, &iosb, 0, 0, X`09`09`09 &netBuf, sizeof(netBuf)-1, 0, 0, 0, 0); X`09 if ((status & 1) ! = 1) return (-1); X`09 if (iosb.stat == SS$_ABORT) return (-1); X`09 inBuf = iosb.count; X#endif`09/* CMU_TCP */ X`09 X`09 netBuf`5BinBuf`5D = '\0'; X`09 bufPtr = netBuf; X`09 if (*bufPtr == '\n') X`09`09bufPtr++; X`09`7D X`09if ((cp = index(bufPtr, '\r')) != NULL) `7B X`09 *cp = '\0'; X`09 strcat(string, bufPtr); X`09 bufPtr = ++cp; X`09 if (*bufPtr == '\n') X`09`09bufPtr++; X`09`7D else `7B X`09 if ((cp = index(bufPtr, '\n')) != NULL) `7B X`09`09*cp = '\0'; X`09`09strcat(string, bufPtr); X`09`09bufPtr = ++cp; X`09`09if (*bufPtr == '\n') X`09`09 bufPtr++; X`09 `7D else `7B X`09`09level = 1; X`09`09inBuf = 0; X`09`09strcat(string, bufPtr); X`09`09ret = get_server(string, size); X`09`09level = 0; X`09`09return ret; X`09 `7D X`09`7D X#endif X X#ifdef DEBUG X`09(void) fprintf(stderr, "<<< %s\n", string); X#endif X X`09return (0); X`7D X X X/* X * close_server -- close the connection to the server, after sending X *`09`09the "quit" command. X * X *`09Parameters:`09None. X * X *`09Returns:`09Nothing. X * X *`09Side effects:`09Closes the connection with the server. X *`09`09`09You can't use "put_server" or "get_server" X *`09`09`09after this routine is called. X */ X Xvoid Xclose_server() X`7B X`09char`09ser_line`5B256`5D; X X`09if (!ServerOpen `7C`7C ser_wr_fp == NULL `7C`7C ser_rd_fp == NULL) X`09`09return; X X`09put_server("QUIT"); X`09(void) get_server(ser_line, sizeof(ser_line)); X X#ifndef VMS_TCPIP X`09(void) fclose(ser_wr_fp); X`09(void) fclose(ser_rd_fp); X#else X#ifndef CMU_TCP X`09(void) close(sockt_rd); X#else X`09status = SYS$QIOW (0, cmu_chan, TCP$CLOSE, 0, 0, 0, 2, 0, 0, 0, 0, 0); X#endif /* CMU_TCP */ X#endif /* VMS_TCPIP */ X`09ServerOpen = False; X`7D $ CALL UNPACK CLIENTLIB.C;1 205743787 $ create 'f' X#ifndef CODES_H X#define CODES_H X X/* X * $Header: /users/ricks/xrn/src/RCS/codes.h,v 1.5 90/09/29 02:27:20 ricks E Vxp $ X */ X X/* X * Response Codes for the NNTP Server X * X * Copyright (c) 1988, 1989, 1990, The Regents of the University of Californ Via. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * Response codes for NNTP server X * X * @(#)response_codes.h`091.6`09(Berkeley) 2/6/86 X * X * First digit: X * X *`091xx`09Informative message X *`092xx`09Command ok X *`093xx`09Command ok so far, continue X *`094xx`09Command was correct, but couldn't be performed X *`09`09for some specified reason. X *`095xx`09Command unimplemented, incorrect, or a X *`09`09program error has occured. X * X * Second digit: X * X *`09x0x`09Connection, setup, miscellaneous X *`09x1x`09Newsgroup selection X *`09x2x`09Article selection X *`09x3x`09Distribution X *`09x4x`09Posting X */ X X#define`09CHAR_INF`09'1' X#define`09CHAR_OK`09`09'2' X#define`09CHAR_CONT`09'3' X#define`09CHAR_ERR`09'4' X#define`09CHAR_FATAL`09'5' X X#define`09INF_HELP`09100`09/* Help text on way */ X#define`09INF_DEBUG`09199`09/* Debug output */ X X#define`09OK_CANPOST`09200`09/* Hello; you can post */ X#define`09OK_NOPOST`09201`09/* Hello; you can't post */ X#define`09OK_SLAVE`09202`09/* Slave status noted */ X#define`09OK_GOODBYE`09205`09/* Closing connection */ X#define`09OK_GROUP`09211`09/* Group selected */ X#define`09OK_GROUPS`09215`09/* Newsgroups follow */ X#define`09OK_ARTICLE`09220`09/* Article (head & body) follows */ X#define`09OK_HEAD`09`09221`09/* Head follows */ X#define`09OK_BODY`09`09222`09/* Body follows */ X#define`09OK_NOTEXT`09223`09/* No text sent -- stat, next, last */ X#define`09OK_NEWNEWS`09230`09/* New articles by message-id follow */ X#define`09OK_NEWGROUPS`09231`09/* New newsgroups follow */ X#define`09OK_XFERED`09235`09/* Article transferred successfully */ X#define`09OK_POSTED`09240`09/* Article posted successfully */ X X#define CONT_XFER`09335`09/* Continue to send article */ X#define`09CONT_POST`09340`09/* Continue to post article */ X X#define`09ERR_GOODBYE`09400`09/* Have to hang up for some reason */ X#define`09ERR_NOGROUP`09411`09/* No such newsgroup */ X#define`09ERR_NCING`09412`09/* Not currently in newsgroup */ X#define`09ERR_NOCRNT`09420`09/* No current article selected */ X#define`09ERR_NONEXT`09421`09/* No next article in this group */ X#define`09ERR_NOPREV`09422`09/* No previous article in this group */ X#define`09ERR_NOARTIG`09423`09/* No such article in this group */ X#define ERR_NOART`09430`09/* No such article at all */ X#define ERR_GOTIT`09435`09/* Already got that article, don't send */ X#define ERR_XFERFAIL`09436`09/* Transfer failed */ X#define`09ERR_XFERRJCT`09437`09/* Article rejected, don't resend */ X#define`09ERR_NOPOST`09440`09/* Posting not allowed */ X#define`09ERR_POSTFAIL`09441`09/* Posting failed */ X X#define`09ERR_COMMAND`09500`09/* Command not recognized */ X#define`09ERR_CMDSYN`09501`09/* Command syntax error */ X#define`09ERR_ACCESS`09502`09/* Access to server denied */ X#define ERR_FAULT`09503`09/* Program fault, command not performed */ X X#endif $ CALL UNPACK CODES.H;1 556738086 $ create 'f' X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /net/opus/mnt/ricks/src/X/xrn/RCS/com Vpose.c,v 1.22 90/09/29 01:12:30 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * compose.c: routines for composing messages and articles X */ X X#include "copyright.h" Xextern char *getinfofromfile(/* char *filename */); X#ifndef VMS X#include X#else X#include X#endif X#include X#include X#include "utils.h" X#include "config.h" X#ifndef VMS X#include X#include X#include X#ifdef RESOLVER X#include X#include X#include X#endif X#else X#include X#define index strchr X#endif X#include X#if defined(aiws) `7C`7C defined(DGUX) Xstruct passwd *getpwuid(); Xstruct passwd *getpwnam(); X#endif X#ifndef VMS X#include X#include X#include X#else X#include X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#else X#ifndef DwtNmenuExtendLastRow X#define DwtNmenuExtendLastRow "menuExtendLastRow" X#endif X#ifndef VMS X#include X#include "Pane.h" X#else X#include X#include "Pane.h" X#endif X#endif X#include "avl.h" X#include "xthelper.h" X#include "resources.h" X#include "dialogs.h" X#include "server.h" X#include "mesg.h" X#include "news.h" X#include "internals.h" X#include "xrn.h" X#include "xmisc.h" X#include "error_hnds.h" X X/* entire pane */ XWidget ComposeTopLevel = (Widget) 0; Xstatic Boolean ComposeActive = False; X/* text window */ XWidget ComposeText = (Widget) 0; X/* buttons */ Xstatic Widget AbortButton; Xstatic Widget SendButton; Xstatic Widget SaveButton; Xstatic Widget IncludeFileButton; Xstatic Widget IncludeArticleButton; Xstatic int InsertionPoint = 0; XWidget HeaderText = (Widget) 0; X#ifdef MOTIF Xstatic Widget headerFrame = (Widget) 0; Xstatic Widget textFrame = (Widget) 0; X#endif X Xstatic char *CompositionString = NIL(char); Xstatic char *HeaderString = NIL(char); Xstatic char *TempString = NIL(char); Xstatic int CompositionSize = 0; X X#define BUFFER_SIZE 1024 X X#define POST 0 X#define FOLLOWUP 1 X#define REPLY 2 X#define FORWARD 3 X#define GRIPE 4 Xstatic int PostingMode = POST; X Xstruct header `7B X art_num article; X char *artText; X char *newsgroups; X char *subject; X char *messageId; X char *followupTo; X char *references; X char *from; X char *replyTo; X char *distribution; X char *keywords; X X char *user; X char *fullname; X char *host; X char *path; X char *organization; X X char *date; /* added to header structure....... */ X`7D; X X X/* X * storage for the header information needed for building, checking, X * and repairing the header. Once this is created, the user can go X * to another article or another group and still use the composition X * window X */ X Xstatic struct header Header = `7B0, NIL(char), NIL(char), NIL(char), NIL(cha Vr), NIL(char), X NIL(char), NIL(char), NIL(char), NIL(char), N VIL(char), X NIL(char),NIL(char),NIL(char)`7D; X X X#define HOST_NAME_SIZE 1024 X X Xstatic void LowerCase(); X Xstatic void XsizeCompose(newSize) Xint newSize; X`7B X newSize += 10000; X if (newSize > CompositionSize) `7B X`09if (CompositionString == NIL(char)) `7B X`09 CompositionString = XtMalloc(newSize); X`09 HeaderString = XtMalloc(newSize); X`09 TempString= XtMalloc(newSize); X`09`7D else `7B X`09 CompositionString = XtRealloc(CompositionString, newSize); X`09 HeaderString = XtRealloc(HeaderString, newSize); X`09 TempString= XtRealloc(TempString, newSize); X`09`7D X`09 `20 X `7D X`7D Xstatic void XgetHeader(article) Xart_num article; X/* X * get the header and other important information for an article X * X * if called with article equal to zero, will only set up the non-article X * specific entries X * X */ X`7B X struct passwd *pwd; X char host`5BHOST_NAME_SIZE`5D, *ptr; X char path`5BHOST_NAME_SIZE`5D; X char buffer`5B10000`5D; X X#ifndef VMS X#ifdef RESOLVER X struct hostent *hent; X#endif X#endif X char *getenv(); X `20 X if (article > 0) `7B X`09Header.article = article; X#ifdef XRN_PREFETCH X`09/* X`09 * handle the case where this is a request at the last X`09 * article and the next newsgroup has been prefetched. X`09 * X`09 * must go back to the current newsgroup so the header information X`09 * can be retrieved from the server X`09 */ X`09if (!invalidatePrefetchedGroup(Newsrc`5BCurrentGroupNumber`5D)) `7B X`09 mesgPane(XRN_SERIOUS, "The newsgroup has been deleted out from undern Veath us"); X`09`7D else `7B X#endif /* XRN_PREFETCH */ X`09 xhdr(article, "newsgroups", &Header.newsgroups); X`09 xhdr(article, "subject", &Header.subject); X`09 xhdr(article, "message-id", &Header.messageId); X`09 xhdr(article, "followup-to", &Header.followupTo); X`09 xhdr(article, "references", &Header.references); X`09 xhdr(article, "from", &Header.from); X`09 xhdr(article, "reply-to", &Header.replyTo); X`09 xhdr(article, "distribution", &Header.distribution); X`09 xhdr(article, "keywords", &Header.keywords); X X#ifdef XRN_PREFETCH X`09`7D X#endif /* XRN_PREFETCH */ X X `7D else `7B X`09/* information for 'post' */ X`09if (CurrentGroupNumber != NO_GROUP) `7B X`09 Header.newsgroups = XtNewString(Newsrc`5BCurrentGroupNumber`5D->name) V; X`09`7D else `7B X`09 Header.newsgroups = XtNewString(""); X`09`7D X`09Header.artText = NULL; X `7D X X /* X * since I'm lazy down below, I'm going to replace NIL pointers with "" X */ X if (Header.newsgroups == NIL(char)) `7B X`09Header.newsgroups = XtNewString(""); X `7D X if (Header.subject == NIL(char)) `7B X`09Header.subject = XtNewString(""); X `7D X if (Header.messageId == NIL(char)) `7B X`09Header.messageId = XtNewString(""); X `7D X if (Header.followupTo == NIL(char)) `7B X`09Header.followupTo = XtNewString(""); X `7D X if (Header.references == NIL(char)) `7B X`09Header.references = XtNewString(""); X `7D X if (Header.from == NIL(char)) `7B X`09Header.from = XtNewString(""); X `7D X if (Header.replyTo == NIL(char)) `7B X`09Header.replyTo = XtNewString(""); X `7D X if (Header.distribution == NIL(char)) `7B X`09Header.distribution = XtNewString(""); X `7D X if (Header.keywords == NIL(char)) `7B X`09Header.keywords = XtNewString(""); X `7D X X host`5B0`5D = 0; X#ifdef`09UUCPNAME X `7B X FILE * uup; X `20 X if ((uup = fopen(UUCPNAME, "r")) != NULL) `7B X `09`09char *p; X `09`09char xbuf`5BBUFSIZ`5D; X `20 X `09`09while (fgets(xbuf, sizeof(xbuf), uup) != NULL) `7B X `09`09 if (*xbuf <= ' ' `7C`7C *xbuf == '#') X `09`09`09continue; X `09`09 break; X `09`09`7D X `09`09if (p = index(xbuf, '\n')) X `09`09 *p = '\0'; X `09`09(void) strncpy(host, xbuf, sizeof(host) - 1); X `09`09(void) fclose(uup); X `7D X `7D X#endif X if (app_resources.hostName != NIL(char))`7B X`09LowerCase(app_resources.hostName, host); X `7D X if (host`5B0`5D == 0) `7B X if ((ptr = getenv("HIDDENHOST")) != NIL(char)) `7B X`09 (void) strncpy(host, ptr, sizeof(host)-1); X `7D else if ((ptr = getinfofromfile(HIDDEN_FILE)) != NULL) `7B X`09 (void) strncpy(host, ptr, sizeof(host) - 1); X`09`7D else `7B X#ifdef RETURN_HOST X`09 (void) strcpy(host, RETURN_HOST); X#else /* Not RETURN_HOST */ X#ifndef VMS X`09 (void) gethostname(host, sizeof(host)); X#ifdef RESOLVER X`09 hent = gethostbyname(host); X`09 if (hent != NULL) `7B X`09`09(void) strcpy(host,hent->h_name); X`09 `7D X#endif X#else X`09 if ((ptr = getenv("SYS$CLUSTER_NODE")) == NIL(char)) `7B X`09 `09ptr = getenv("SYS$NODE"); X`09 `7D X`09 (void) strcpy(host, ptr); X`09 ptr = index(host, ':'); X`09 if (ptr != NIL(char)) `7B X`09`09*ptr = '\0'; X`09 `7D X`09 (void) strcat(host, DOMAIN_NAME); X`09 LowerCase(host, host); X#endif X#endif /* Not RETURN_HOST */ X`09`7D X `7D X `20 X if ((ptr = getenv("HIDDENPATH")) != NIL(char)) `7B X`09(void) strncpy(path, ptr, sizeof(path)-1); X `7D else if ((ptr = getinfofromfile(PATH_FILE)) != NULL) `7B X`09(void) strncpy(path, ptr, sizeof(path)-1); X `7D else `7B X`09(void) strncpy(path, host, sizeof(path)-1); X `7D X X /* If the host name is not a full domain name, put in the domain */ X if (index (host, '.') == NIL(char)) `7B X char *domain; X `20 X if ((domain = getenv ("DOMAIN")) != NIL (char)) `7B X`09 (void) strcat(host, domain); X`09`7D else if ((domain = getinfofromfile(DOMAIN_FILE)) != NULL) `7B X`09 (void) strcat(host, domain); X `7D else `7B X`09 (void) strcat (host, DOMAIN_NAME); X`09`7D X `7D X X Header.host = XtNewString(host); X Header.path = XtNewString(path); X if (app_resources.organization != NIL(char)) `7B X`09Header.organization = XtNewString(app_resources.organization); X `7D else if ((ptr = getenv ("ORGANIZATION")) != NIL(char)) `7B X`09Header.organization = XtNewString(ptr); X `7D else if ((ptr = getinfofromfile(ORG_FILE)) != NULL) `7B X`09Header.organization = XtNewString(ptr); X `7D else `7B X`09Header.organization = XtNewString(ORG_NAME); X `7D X#ifndef VMS X pwd = getpwuid(getuid()); X Header.user = XtNewString(pwd->pw_name); X Header.fullname = XtNewString(pwd->pw_gecos); X#else X Header.user = XtNewString(getenv("USER")); X LowerCase(Header.user, Header.user); X if (app_resources.personalName != NULL) `7B X`09Header.fullname = XtNewString(app_resources.personalName); X `7D else `7B X`09if ((Header.fullname = getenv("FULLNAME")) == NIL (char)) X`09 Header.fullname = XtNewString(""); X `7D X#endif X ptr = index(Header.fullname, ','); X if (ptr != NIL(char)) `7B X`09*ptr = '\0'; X `7D X `20 X /* & expansion */ X ptr = index(Header.fullname, '&'); X if (ptr != NIL(char)) `7B X`09char *p = buffer + (ptr - Header.fullname); X X`09buffer`5B0`5D = '\0'; X`09*ptr = '\0'; X`09(void) strcpy(buffer, Header.fullname); X`09(void) strcat(buffer, Header.user); X`09if (isascii(*p)) `7B X`09 *p = toupper(*p); X`09`7D X`09ptr++; X`09(void) strcat(buffer, ptr); X`09FREE(Header.fullname); X`09Header.fullname = XtNewString(buffer); X `7D X `20 X return; X`7D X X Xstatic int XfieldExists(string, fieldName) Xchar *string; Xchar *fieldName; X/* X * see if a field exists in the header that begins with `60fieldName' X * X * returns 0 for no, non-zero for yes X */ X`7B X char *ptr; X X `20 X for (ptr = string; (ptr != NIL(char)) && (*ptr != '\0'); ptr++) `7B X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\0')) `7B X`09 /* end of message */ X`09 return(0); X`09`7D X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\n')) `7B X`09 /* end of header */ X`09 return(0); X`09`7D X X`09/* X`09 * see if the field name is in the string and at the beginning X`09 * of the line and that the field name ends with a ':' X`09 */ X`09if (((ptr == string) `7C`7C (*(ptr-1) == '\n')) && X`09 STREQN(fieldName, ptr, utStrlen(fieldName)) && X`09 (ptr`5ButStrlen(fieldName)`5D == ':')) `7B X`09 return(1); X`09`7D X `7D X return(0); X`7D X X Xstatic void XaddField(string, field) Xchar *string; Xchar *field; X/* X * add a header field to a message. X * this is a destructive operation. X */ X`7B X char buffer`5B10000`5D; X X (void) strcpy(buffer, string); X string`5B0`5D = '\0'; X (void) strcat(string, field); X (void) strcat(string, buffer); X X return; X`7D `20 X X Xstatic void XstripField(string, fieldName) Xchar *string; Xchar *fieldName; X/* X * remove all fields from a header that begin with `60fieldName'. X * this is a destructive operation. X */ X`7B X char *ptr, *nl; X X X for (ptr = string; (ptr != NIL(char)) && (*ptr != '\0'); ptr = index(ptr V, '\n')) `7B X`09if (ptr != string) `7B X`09 /* character after the newline */ X`09 ptr++; X`09`7D X`09 X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\0')) `7B X`09 /* end of message */ X`09 return; X`09`7D X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\n')) `7B X`09 /* end of header */ X`09 return; X`09`7D X X`09/* X`09 * make sure a ':' is at the end of the field name X`09 */ X`09if (STREQN(fieldName, ptr, utStrlen(fieldName)) && (ptr`5ButStrlen(fieldN Vame)`5D == ':')) `7B X`09 nl = index(ptr, '\n'); X`09 (void) strcpy(ptr, ++nl); X`09 if (*ptr == '\n') `7B X`09`09return; X`09 `7D X`09 ptr--; X`09`7D X `7D X return; X`7D X X#if defined(VMS) `7C`7C defined(NO_SENDMAIL) Xstatic void XreturnField(string, fieldName, removed) Xchar *string; Xchar *fieldName; Xchar *removed; X/* X * remove fields from a header that begin with `60fieldName' X * and return the removed characters in `60removed'. X * this is a destructive operation. X */ X`7B X char *ptr, *nl, *copyPtr; X X *removed = '\0'; X for (ptr = string; (ptr != NIL(char)) && (*ptr != '\0'); ptr = index(++ Vptr, '\n')) `7B X`09if (ptr != string) `7B X`09 /* character after the newline */ X`09 ptr++; X`09`7D X`09 X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\0')) `7B X`09 /* end of message */ X`09 return; X`09`7D X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\n')) `7B X`09 /* end of header */ X`09 return; X`09`7D X X`09/* X`09 * make sure a ':' is at the end of the field name X`09 */ X`09if (STREQN(fieldName, ptr, utStrlen(fieldName)) && (ptr`5ButStrlen(fieldN Vame)`5D == ':')) `7B X`09 nl = index(ptr, '\n'); X`09 copyPtr = ptr + utStrlen(fieldName) + 1; X`09 while (*copyPtr == ' ')`09`09/* strip leading spaces */ X`09`09copyPtr++; X`09 for (; copyPtr < nl; copyPtr++) X`09 *removed++ = *copyPtr; X`09 *removed = '\0'; X`09 (void) strcpy(ptr, ++nl); X`09 return; X`09`7D X `7D X return; X`7D X#endif /* VMS */ X Xstatic void XPopdownCompositionTopLevel() X`7B X XtSetSensitive(SendButton, False); X XtSetSensitive(SaveButton, False); X XtSetSensitive(IncludeFileButton, False); X XtSetSensitive(IncludeArticleButton, False); X if (ComposeTopLevel != (Widget) 0) `7B X`09XtUnmapWidget(ComposeTopLevel); X `7D X ComposeActive = False; X return; X`7D X Xstatic void XfreeHeader() X`7B X if (PostingMode != GRIPE) `7B X`09FREE(Header.newsgroups); X`09FREE(Header.subject); X`09FREE(Header.messageId); X`09FREE(Header.followupTo); X`09FREE(Header.references); X`09FREE(Header.from); X`09FREE(Header.replyTo); X`09FREE(Header.distribution); X`09FREE(Header.keywords); X`09FREE(Header.user); X`09FREE(Header.fullname); X`09FREE(Header.host); X`09FREE(Header.path); X`09FREE(Header.organization); X `7D X return; X`7D X X Xstatic void XbuildSubject(message) Xchar *message; X/* X * add a subject field to the header of a message. X * deal with supressing multiple '`5BrR`5D`5BeE`5D: ' strings X */ X`7B X if (STREQN(Header.subject, "Re: ", 4) `7C`7C X`09STREQN(Header.subject, "RE: ", 4) `7C`7C X`09STREQN(Header.subject, "re: ", 4)) `7B X`09(void) strcat(message, "Subject: "); X `7D else `7B X`09(void) strcat(message, "Subject: Re: "); X `7D X (void) strcat(message, Header.subject); X (void) strcat(message, "\n"); X X return; X`7D X X X/*ARGSUSED*/ Xstatic void XabortFunction(widget) XWidget widget; X`7B X PopdownCompositionTopLevel(); X freeHeader(); X mesgPane(XRN_INFO, "Article/Message aborted"); X return; X`7D X Xstatic void XsaveMessage(fname) Xchar *fname; X`7B X FILE *fp; X char *file = utTildeExpand(fname); X X if (file == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot save the article/message"); X`09return; X `7D X `20 X#ifndef VMS X if ((fp = fopen(file, "a")) != NULL) `7B X#else X if ((fp = fopen(file, "w")) != NULL) `7B X#endif X`09(void) sprintf(error_buffer, "Saving in %s", file); X`09infoNow(error_buffer); X`09 X`09(void) fwrite(HeaderString,sizeof(char), utStrlen(HeaderString), fp); X`09(void) putc('\n', fp); X`09(void) fwrite(CompositionString, sizeof(char), utStrlen(CompositionString V), fp); X`09(void) putc('\n', fp); X`09(void) putc('\n', fp); X`09(void) fclose(fp); X `7D else `7B X`09mesgPane(XRN_SERIOUS, "Can not save the article/message"); X `7D X return; X`7D X X/*ARGSUSED*/ Xstatic void XsaveFunction(widget) XWidget widget; X`7B X FILE *fp; X char *textString; X `20 X#ifdef MOTIF X textString = XmTextGetString(ComposeText); X#else X textString = DwtSTextGetString(ComposeText); X#endif X sizeCompose(utStrlen(textString)); X strcpy(CompositionString, textString); X XtFree(textString); X#ifdef MOTIF X textString = XmTextGetString(HeaderText); X#else X textString = DwtSTextGetString(HeaderText); X#endif X strcpy(HeaderString, textString); X XtFree(textString); X saveMessage(app_resources.savePostings); X`7D X Xstatic void XsaveDeadLetter(textString) Xchar`09*textString; X`7B X FILE *fp; X X#ifndef VMS X if ((fp = fopen(utTildeExpand(app_resources.deadLetters), "a")) != NULL) V `7B X#else X if ((fp = fopen(utTildeExpand(app_resources.deadLetters), "w")) != NULL) V `7B X#endif X`09(void) fwrite(textString ,sizeof(char), utStrlen(textString), fp); X`09(void) putc('\n', fp); X`09(void) putc('\n', fp); X`09(void) fclose(fp); X `7D else `7B X`09mesgPane(XRN_SERIOUS, "Can not save the dead article/message"); X `7D X return; X`7D X X X/*ARGSUSED*/ Xstatic void XstripBlankFields(string) Xchar *string; X/* X * go through the string and look for fields that have not X * been filled in and remove them X */ X`7B X char *ptr, *nl, *end; X X ptr = string + utStrlen(string) - 1; X/* X * make sure it ends with a newline X */ X if (*ptr != '\n') `7B X`09ptr++; X`09*ptr++ = '\n'; X`09*ptr++ = '\0'; X `7D X for (ptr = string; (ptr != NIL(char)) && (*ptr != '\0'); ptr = index(ptr V, '\n')) `7B X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\0')) `7B X`09 ptr`5B1`5D = '\n';`09`09/* put in the missing newline */ X`09 ptr`5B2`5D = '\0'; X`09 /* end of message */ X`09 return; X`09`7D X`09if ((ptr`5B0`5D == '\n') && (ptr`5B1`5D == '\n')) `7B X`09 /* end of header */ X`09 return; X`09`7D X X`09if (ptr != string) `7B X`09 /* character after the newline */ X`09 ptr++; X`09`7D X`09 X`09/* get the line */ X`09if ((nl = index(ptr, '\n')) == NIL(char)) `7B X`09 /* weird */ X`09 return; X`09`7D X X`09/* ignore trailing spaces */ X`09end = nl; X`09end--; X`09for ( ; *end == ' '; end--) ; X`09 X`09if ((*end == ':') && (end == index(ptr, ':'))) `7B X`09 /* blank field */ X`09 (void) strcpy(ptr, ++nl); X`09 if (*ptr == '\n') `7B X`09`09return; X`09 `7D X`09 ptr--; X`09`7D X `7D X return; X`7D `20 X X#ifdef VMS X#include X#include X#include Xstatic Widget`09mailErrorDialog = NULL; Xstatic char`09VMSmessage`5B255`5D; Xstatic char`09TXTmessage`5B255`5D; Xstatic char`09*VMSmessPtr; Xstatic int`09VMSmessSize; Xstatic int XgrabMessage(descr) Xstruct`09dsc$descriptor_s *descr; X`7B X char *p; X short s; X s = (short)descr->dsc$w_length; X p = (char *)descr->dsc$a_pointer; X strncpy(VMSmessPtr, p, s); `20 X VMSmessSize += s; X VMSmessage`5BVMSmessSize`5D = '\n'; X VMSmessSize++; X VMSmessage`5BVMSmessSize`5D = '\0'; X VMSmessPtr += VMSmessSize; X return 0; X`7D Xstatic int XhandleMailSignal(sig, mech) Xint sig`5B`5D; Xint mech`5B`5D; X`7B X sig`5B0`5D = sig`5B0`5D - 2; X VMSmessPtr = VMSmessage; X VMSmessSize = 0; X sys$putmsg(sig, grabMessage, 0, 0); X sig`5B0`5D = sig`5B0`5D + 2; X return SS$_CONTINUE; X`7D Xstatic void XpopDownMail(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X PopDownDialog(mailErrorDialog); X return; X`7D Xstatic void XmailError() X`7B X static struct DialogArg args`5B`5D = `7B X`09`7B"Click to continue", popDownMail, (caddr_t) -1`7D, X `7D; X X (void) strcpy(TXTmessage,"Error sending mail:"); X (void) strcat(TXTmessage,VMSmessage); X mailErrorDialog = CreateDialog(TopLevel, TXTmessage, DIALOG_NOTEXT, X`09`09`09`09 args, XtNumber(args)); X PopUpDialog(mailErrorDialog); X return; X`7D X#endif /* VMS */ X X/*ARGSUSED*/ Xstatic void XsendFunction(widget) XWidget widget; X`7B X char buffer`5B10000`5D; X char *textString; X FILE *fp; X int mode; X int postStatus; X X if (app_resources.editorCommand == NIL(char)) `7B X#ifdef MOTIF X`09textString = XmTextGetString(ComposeText); X#else X`09textString = DwtSTextGetString(ComposeText); X#endif X`09sizeCompose(utStrlen(textString)); X`09strcpy(CompositionString, textString); X`09XtFree(textString); X#ifdef MOTIF X`09textString = XmTextGetString(HeaderText); X#else X`09textString = DwtSTextGetString(HeaderText); X#endif X`09strcpy(HeaderString, textString); X`09XtFree(textString); X`09stripBlankFields(HeaderString); X `7D else `7B X`09strcpy(HeaderString, CompositionString); X`09CompositionString`5B0`5D = '\0'; X`09stripBlankFields(HeaderString); X `7D X `20 X if ((PostingMode == POST) `7C`7C (PostingMode == FOLLOWUP)) `7B X`09mode = XRN_NEWS; X`09if (app_resources.editorCommand == NIL(char)) `7B X`09 if (!fieldExists(HeaderString, "Subject")) `7B X`09`09if (PostingMode == POST) `7B X`09`09 XBell(XtDisplay(TopLevel), 50); X`09`09 (void) sprintf(buffer, "Subject: ********\n"); X`09`09 mesgPane(XRN_SERIOUS, X`09`09`09 "The Subject field is missing in your message!"); X`09`09 addField(HeaderString, buffer); X#ifdef MOTIF X`09`09 XmTextSetString(HeaderText, HeaderString); X#ifdef MOTIF_V1_0 X`09`09 XmTextSetInsertionPosition(HeaderText, (XmTextPosition) 0); X#else X`09`09 XmTextSetCursorPosition(HeaderText, (XmTextPosition) 0); X#endif X#else X`09`09 DwtSTextSetString(HeaderText, HeaderString); X`09`09 DwtTextSetInsertionPosition(HeaderText, 0); X#endif X`09`09 return; X`09`09`7D X`09`09buffer`5B0`5D = '\0'; X`09`09buildSubject(buffer); X`09`09addField(HeaderString, buffer); X`09 `7D X`09`7D X`09if (PostingMode == FOLLOWUP) `7B X`09 if (!fieldExists(HeaderString, "References")) `7B X`09`09(void) sprintf(buffer, "References: %s\n", Header.messageId); X`09`09addField(HeaderString, buffer); X`09 `7D X`09`7D X X`09if (!fieldExists(HeaderString, "From")) `7B X`09 (void) sprintf(buffer, "From: %s@%s (%s)\n", X`09`09`09 Header.user, Header.host, Header.fullname); X`09 addField(HeaderString, buffer); X`09`7D X X`09if (!fieldExists(HeaderString, "Newsgroups")) `7B X`09 (void) sprintf(buffer, "Newsgroups: %s\n", Header.newsgroups); X`09 addField(HeaderString, buffer); X`09`7D X X`09if (!fieldExists(HeaderString, "Path")) `7B X`09 (void) sprintf(buffer, "Path: %s!%s\n", Header.host, Header.user); X`09 addField(HeaderString, buffer); X`09`7D X X/*`09stripField("Message-ID:"); .............we need this !!! */ X`09stripField(HeaderString, "Relay-Version"); X`09stripField(HeaderString, "Posting-Version"); X X`09(void) strcat (HeaderString, CompositionString); X `7D else `7B X`09(void) strcat (HeaderString, CompositionString); X`09mode = XRN_MAIL; X `7D X X switch (postArticle(HeaderString,mode)) `7B X`09case POST_TRYAGAIN: X`09 return; X X`09case POST_FAILED: X`09 XBell(XtDisplay(TopLevel), 50); X`09 mesgPane(XRN_SERIOUS, "Could not post, saving to %s", X`09`09app_resources.deadLetters); X`09 saveDeadLetter(HeaderString); X`09 break; X X`09case POST_NOTALLOWED: X`09mesgPane(XRN_SERIOUS, "Posting not allowed from this machine, saving in % Vs", X`09`09 app_resources.deadLetters); X`09break; X`09 `20 X`09case POST_OKAY: X`09mesgPane(XRN_INFO, "Article/Message Sent"); X`09break; X `7D X`09 X if (app_resources.editorCommand == NIL(char)) `7B X`09PopdownCompositionTopLevel(); X `7D X freeHeader(); X X return; X`7D X#ifdef VMS Xint XMailArticle(article) Xchar *article; X`7B X struct _itemList `7B X`09short item_size; X`09short item_code; X`09char* item_ptr; X`09int item_rtn_size; X`09int end_list; X `7D itemList; X`09`20 X struct _ccList `7B X`09short item1_size; X`09short item1_code; X`09char* item1_ptr; X`09int item1_rtn_size; X`09short item2_size; X`09short item2_code; X`09char* item2_ptr; X`09int item2_rtn_size; X`09int end_list; X `7D ccList; X`09`20 X FILE *fp; X char toString`5BBUFFER_SIZE`5D; X char ccString`5BBUFFER_SIZE`5D; X char subjString`5BBUFFER_SIZE`5D; X char listFileName`5B512`5D; X char listName`5B512`5D; X int listNameSize; X int`09context, status; X char *textPtr, *nl; X char *toElement, *tokPtr; X char *p; X char *ccElement; X int mailCC = MAIL$_CC; X char **wrappedLines; X char **lines; X long zero = 0; X X VAXC$ESTABLISH(handleMailSignal); X returnField(HeaderString, "To", toString); X X if (strlen(toString) == 0) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09mesgPane(XRN_SERIOUS, "You must enter a non-Null TO field"); X`09return POST_TRYAGAIN; X`09`7D X X returnField(HeaderString, "Subject", subjString); X if (strlen(subjString) == 0) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09mesgPane(XRN_SERIOUS, "You must enter a non-Null subject"); X`09return POST_TRYAGAIN; X `7D X returnField(HeaderString,"Cc", ccString); X context = 0; X status = MAIL$SEND_BEGIN(&context, &zero, &zero); X if ((status&1) != 1) `7B X`09mailError(); X`09return POST_TRYAGAIN; X `7D X if (index(toString,'"') == NULL) `7B X`09for (p = toString; *p != '\0'; p++) `7B X`09 *p = toupper(*p); X`09`7D X `7D X if (index(ccString,'"') == NULL) `7B X`09for (p = ccString; *p != '\0'; p++) `7B X`09 *p = toupper(*p); X`09`7D X `7D X itemList.item_code = MAIL$_SEND_TO_LINE; X itemList.item_ptr = toString; X itemList.item_size = strlen(toString); X itemList.item_rtn_size = 0; X itemList.end_list = 0; X status = MAIL$SEND_ADD_ATTRIBUTE(&context, &itemList, &zero); X if ((status&1) != 1) `7B X`09mailError(); X`09return POST_TRYAGAIN; X `7D X itemList.item_code = MAIL$_SEND_CC_LINE; X itemList.item_ptr = ccString; X itemList.item_size = strlen(ccString); X itemList.item_rtn_size = 0; X itemList.end_list = 0; X status = MAIL$SEND_ADD_ATTRIBUTE(&context, &itemList, &zero); X if ((status&1) != 1) `7B X`09mailError(); X`09return POST_TRYAGAIN; X `7D X tokPtr = toString; X while ((toElement = strtok(tokPtr, ",")) != NULL) `7B X`09itemList.item_code = MAIL$_SEND_USERNAME; X`09if ((itemList.item_ptr = getenv(toElement)) == NULL) `7B X`09 itemList.item_ptr = toElement; X`09`7D X`09itemList.item_size = strlen(itemList.item_ptr); X`09for (p = itemList.item_ptr; *p == ' '; p++); X`09if (*p == '@') `7B X`09 p++; X`09 if ((fp = fopen(p, "r","dna=.dis")) == NULL) `7B X`09`09sprintf(VMSmessage, "Error opening distribution file %s",p); X`09`09mailError(); X`09`09return POST_TRYAGAIN; X`09 `7D else `7B X`09`09while (fgets(listName, 128, fp) != NULL) `7B X`09`09 listNameSize = strlen(listName); X`09`09 listNameSize--;`09`09`09/* strip the newline */ X`09`09 listName`5BlistNameSize`5D = '\0'; X`09`09 itemList.item_code = MAIL$_SEND_USERNAME; X`09`09 if (itemList.item_ptr = getenv(listName) == NULL) `7B X`09`09`09itemList.item_ptr = listName; X`09`09 `7D X`09`09 for (p = itemList.item_ptr; *p != '\0'; p++) `7B X`09`09`09if (*p == '!') X`09`09`09 *p = '\0'; X`09`09`09if (*p == '\t') X`09`09`09 *p = ' '; X`09`09 `7D X`09`09 p = itemList.item_ptr; X`09`09 if ((itemList.item_ptr = getenv(p)) == NULL) `7B X`09`09`09itemList.item_ptr = p; X`09`09 `7D X`09`09 itemList.item_size = strlen(itemList.item_ptr); X`09`09 itemList.item_rtn_size = 0; X`09`09 itemList.end_list = 0; X`09`09 status = MAIL$SEND_ADD_ADDRESS(&context, &itemList, &zero); X`09`09 if ((status&1) != 1) `7B X`09`09`09fclose(fp); X`09`09`09mailError(); X`09`09`09return POST_TRYAGAIN; X`09`09 `7D X`09`09`7D X`09`09fclose(fp); X`09 `7D X`09`7D else `7B X`09 itemList.item_rtn_size = 0; X`09 itemList.end_list = 0; X`09 status = MAIL$SEND_ADD_ADDRESS(&context, &itemList, &zero); X`09 if ((status&1) != 1) `7B X`09`09mailError(); X`09`09return POST_TRYAGAIN; X`09 `7D X`09`7D X`09tokPtr = NULL; X `7D X tokPtr = ccString; X while ((toElement = strtok(tokPtr, ",")) != NULL) `7B X`09ccList.item1_code = MAIL$_SEND_USERNAME; X`09if ((ccList.item1_ptr = getenv(toElement)) == NULL) `7B X`09 ccList.item1_ptr = toElement; X`09`7D X`09ccList.item1_size = strlen(ccList.item1_ptr); X`09for (p = ccList.item1_ptr; *p == ' '; p++); X`09if (*p == '@') `7B X`09 p++; X`09 if ((fp = fopen(p, "r","dna=.dis")) == NULL) `7B X`09`09sprintf(VMSmessage, "Error opening distribution file %s",p); X`09`09mailError(); X`09`09return POST_TRYAGAIN; X`09 `7D else `7B X`09`09while (fgets(listName, 128, fp) != NULL) `7B X`09`09 listNameSize = strlen(listName); X`09`09 listNameSize--;`09`09`09/* strip the newline */ X`09`09 listName`5BlistNameSize`5D = '\0'; X`09`09 ccList.item1_code = MAIL$_SEND_USERNAME; X`09`09 if (ccList.item1_ptr = getenv(listName) == NULL) `7B X`09`09`09ccList.item1_ptr = listName; X`09`09 `7D X`09`09 for (p = ccList.item1_ptr; *p != '\0'; p++) `7B X`09`09`09if (*p == '!') X`09`09`09 *p = '\0'; X`09`09`09if (*p == '\t') X`09`09`09 *p = ' '; X`09`09 `7D X`09`09 p = ccList.item1_ptr; X`09`09 if ((ccList.item1_ptr = getenv(p)) == NULL) `7B X`09`09`09ccList.item1_ptr = p; X`09`09 `7D X`09`09 ccList.item1_size = strlen(ccList.item1_ptr); X`09`09 ccList.item1_rtn_size = 0; X`09`09 ccList.item2_code = MAIL$_SEND_USERNAME_TYPE; X`09`09 ccList.item2_ptr = &mailCC; X`09`09 ccList.item2_size = sizeof(long); X`09`09 ccList.item2_rtn_size = 0; X`09`09 ccList.end_list = 0; X`09`09 status = MAIL$SEND_ADD_ADDRESS(&context, &itemList, &zero); X`09`09 if ((status&1) != 1) `7B X`09`09`09fclose(fp); X`09`09`09mailError(); X`09`09`09return POST_TRYAGAIN; X`09`09 `7D X`09`09`7D X`09`09fclose(fp); X`09 `7D X`09`7D else `7B X`09 ccList.item1_rtn_size = 0; X`09 ccList.item2_code = MAIL$_SEND_USERNAME_TYPE; X`09 ccList.item2_ptr = &mailCC; X`09 ccList.item2_size = sizeof(long); X`09 ccList.item2_rtn_size = 0; X`09 ccList.end_list = 0; X`09 status = MAIL$SEND_ADD_ADDRESS(&context, &itemList, &zero); X`09 if ((status&1) != 1) `7B X`09`09mailError(); X`09`09return POST_TRYAGAIN; X`09 `7D X`09`7D X`09tokPtr = NULL; X `7D X itemList.item_code = MAIL$_SEND_SUBJECT; X itemList.item_size = strlen(subjString); X itemList.item_ptr = subjString; X itemList.item_rtn_size = 0; X itemList.end_list = 0; X status = MAIL$SEND_ADD_ATTRIBUTE(&context, &itemList, &zero); X if ((status&1) != 1) `7B X`09mailError(); X`09return POST_TRYAGAIN; X `7D X/* X * Iterate over the composition string, extracting records X * delimited by newlines and sending each as a record X * X */ X textPtr = HeaderString; X if (*textPtr == '\n') X`09textPtr++; X lines = wrappedLines = wrapText(textPtr); X X while (*lines) `7B X`09itemList.item_code = MAIL$_SEND_RECORD; X`09itemList.item_size = strlen(*lines); X`09itemList.item_ptr = *lines; X`09itemList.item_rtn_size = 0; X`09itemList.end_list = 0; X`09status = MAIL$SEND_ADD_BODYPART(&context, &itemList, &zero); X`09if ((status&1) != 1) `7B X`09 mailError(); X`09 return POST_FAILED; X`09`7D X`09 X`09FREE(*lines); X`09lines++; X `7D X FREE(wrappedLines); X status = MAIL$SEND_MESSAGE(&context, &zero, &zero); X if ((status&1) != 1) `7B X`09mailError(); X`09return POST_FAILED; X `7D X return POST_OKAY; X`7D X#endif X Xstatic void XincludeArticleText() X`7B X char line`5B256`5D, *end; X char *art; X X sizeCompose(utStrlen(CompositionString) + utStrlen(Header.artText)); X end = CompositionString + InsertionPoint; X (void) strcpy(TempString, end); X *end = '\0'; X X if (PostingMode == POST `7C`7C Header.artText == NULL) `7B X`09XBell(XtDisplay(TopLevel), 0); X`09mesgPane(XRN_SERIOUS, "No article to include"); X`09return; X `7D X if (PostingMode == REPLY) `7B X (void) sprintf(line, "In article %s you write:\n", X`09`09Header.messageId ); X `7D else `7B X (void) sprintf(line, "In article %s, %s writes:\n", X`09`09 Header.messageId, Header.from); X `7D X X (void) strcat(CompositionString, line); X end = CompositionString + utStrlen(CompositionString); X *end = '\0'; X X /* copy the article */ X X if (app_resources.includeSep == TRUE && PostingMode != FORWARD) `7B X (void) strcat(end, app_resources.includePrefix); X`09end += utStrlen(app_resources.includePrefix); X `7D X for (art = Header.artText; *art != '\0'; art++) `7B X`09*end++ = *art; X `09*end = '\0'; X`09if (*art == '\n') X`09 if (app_resources.includeSep == TRUE && PostingMode != FORWARD) `7B X`09`09(void) strcat(end, app_resources.includePrefix); X`09`09end += utStrlen(app_resources.includePrefix); X`09 `7D X `7D X *end++ = '\n'; X *end = '\0'; X /* copy back the text after the insertion point */ X (void) strcat(end, TempString); X if (ComposeText != (Widget) 0) `7B X#ifdef MOTIF X`09XmTextSetString(ComposeText,CompositionString); X#else X`09DwtSTextSetString(ComposeText,CompositionString); X#endif X `7D X return; X`7D X X X/*ARGSUSED*/ Xstatic void XincludeArticleFunction(widget) XWidget widget; X`7B X char *art; X#ifndef MOTIF X Arg textPos`5B1`5D; X#endif X if (PostingMode == POST) `7B X`09return; X `7D X `20 X#ifdef MOTIF X art = XmTextGetString(ComposeText); X#else X art = DwtSTextGetString(ComposeText); X#endif X sizeCompose(utStrlen(art)); X strcpy(CompositionString, art); X XtFree(art); X#ifdef MOTIF X#ifdef MOTIF_V1_0 X InsertionPoint = XmTextGetInsertionPosition(ComposeText); X#else X InsertionPoint = XmTextGetCursorPosition(ComposeText); X#endif X#else X XtSetArg(textPos`5B0`5D, DwtNinsertionPosition, (XtArgVal) &InsertionPoi Vnt); X XtGetValues(ComposeText, textPos, XtNumber(textPos)); X#endif X includeArticleText(); X#ifdef MOTIF X XmTextSetString(ComposeText,CompositionString); X#ifdef MOTIF_V1_0 X XmTextSetInsertionPosition(ComposeText, (XmTextPosition) utStrlen(Compos VitionString)); X#else X XmTextSetCursorPosition(ComposeText, (XmTextPosition) utStrlen(Compositi VonString)); X#endif X#else X DwtSTextSetString(ComposeText,CompositionString); X XtSetArg(textPos`5B0`5D, DwtNinsertionPosition, X`09(XtArgVal) utStrlen(CompositionString)); X XtSetValues(ComposeText, textPos, XtNumber(textPos)); X#endif X X return; X`7D X X#define XRNinclude_ABORT 0 X#define XRNinclude_DOIT 1 X Xstatic Widget IncludeBox = (Widget) 0; /* box for typing in the name of a f Vile */ X X/*ARGSUSED*/ Xstatic void XincludeHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X/* X * handler for the include box X */ X`7B X#ifndef MOTIF X Arg textPos`5B1`5D; X#endif X char *end, *file, c; X FILE *filefp; X struct stat fileStat; X X PopDownDialog(IncludeBox); X X if ((int) client_data != XRNinclude_ABORT) `7B X`09end = CompositionString + InsertionPoint; X`09(void) strcpy(TempString, end); X`09*end = '\0'; X X`09/* copy the file */ X`09file = XtNewString(GetDialogValue(IncludeBox)); X`09if ((stat(file, &fileStat) != -1) &&`20 X`09 ((filefp = fopen(file, "r")) != NULL)) `7B X`09 sizeCompose(CompositionSize + utStrlen(TempString) +`20 X`09`09`09fileStat.st_size + 10000); X`09 end = CompositionString + InsertionPoint; X`09 while ((c = getc(filefp)) != EOF) `7B X`09`09*end = c; X`09`09end++; X`09 `7D X`09 *end = '\0'; X`09 (void) fclose(filefp); X`09`7D else `7B X`09 mesgPane(XRN_SERIOUS, "Can not open `60%s'", file); X`09`7D X`09XtFree(file); X`09/* new insertion point */ X`09InsertionPoint = end - CompositionString; X X`09/* copy back the text after the insertion point */ X`09(void) strcat(end, TempString); X X#ifdef MOTIF X`09XmTextSetString(ComposeText, CompositionString); X#ifdef MOTIF_V1_0 X`09XmTextSetInsertionPosition(ComposeText, InsertionPoint); X#else X`09XmTextSetCursorPosition(ComposeText, InsertionPoint); X#endif X#else X`09DwtSTextSetString(ComposeText, CompositionString); X`09XtSetArg(textPos`5B0`5D, DwtNinsertionPosition, X`09 (XtArgVal) utStrlen(CompositionString)); X`09XtSetValues(ComposeText, textPos, XtNumber(textPos)); X#endif X `7D X X return; X`7D `20 X X/*ARGSUSED*/ Xstatic void XincludeFileFunction(widget) XWidget widget; X`7B X#ifndef MOTIF X Arg textPos`5B1`5D; X#endif X int len; X char *art; X static struct DialogArg args`5B`5D = `7B X`09`7B"doit", includeHandler, (caddr_t) XRNinclude_DOIT`7D, X`09`7B"abort", includeHandler, (caddr_t) XRNinclude_ABORT`7D, X `7D; X X#ifdef MOTIF X art = XmTextGetString(ComposeText); X#else X art = DwtSTextGetString(ComposeText); X#endif X sizeCompose(utStrlen(art)); X strcpy(CompositionString, art); X XtFree(art); X#ifdef MOTIF X#ifdef MOTIF_V1_0 X InsertionPoint = XmTextGetInsertionPosition(ComposeText); X#else X InsertionPoint = XmTextGetCursorPosition(ComposeText); X#endif X#else X XtSetArg(textPos`5B0`5D, DwtNinsertionPosition, (XtArgVal) &InsertionPoi Vnt); X XtGetValues(ComposeText, textPos, XtNumber(textPos)); X#endif X `20 X if (IncludeBox == (Widget) 0) `7B X`09IncludeBox = CreateDialog(ComposeTopLevel, " File Name? ", X`09`09`09`09 DIALOG_TEXT, args, XtNumber(args)); X `7D X PopUpDialog(IncludeBox); X X return; X`7D X Xstatic struct stat originalBuf; Xstatic char FileName`5B512`5D; X Xstatic void XprocessMessage() X`7B X FILE *filefp; X struct stat buf; X char *ptr; X int mode; X X if ((filefp = fopen(FileName, "r")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, "Cannot open the temp file"); X`09return; X `7D X X if (fstat(fileno(filefp), &buf) == -1) `7B X`09mesgPane(XRN_SERIOUS, "Cannot stat the temp file"); X`09(void) fclose(filefp); X`09(void) unlink(FileName); X`09return; X `7D X X if (originalBuf.st_mtime == buf.st_mtime) `7B X`09mesgPane(XRN_INFO, "No change, aborting"); X`09(void) fclose(filefp); X`09(void) unlink(FileName); X`09return; X `7D X X if (buf.st_size == 0) `7B X`09mesgPane(XRN_INFO, "Zero size, aborting"); X`09(void) fclose(filefp); X`09(void) unlink(FileName); X`09return; X `7D X X sizeCompose(buf.st_size+1); X ptr = ARRAYALLOC(char, (buf.st_size + 1)); X (void) fread(ptr, sizeof(char), buf.st_size, filefp); X ptr`5Bbuf.st_size`5D = '\0'; X (void) fclose(filefp); X (void) unlink(FileName); X strcpy(HeaderString, ptr); X X /* pop up a confirm box */ X if (ConfirmationBox(TopLevel, "Send the message?") == XRN_CB_ABORT) `7B X`09if (ConfirmationBox(TopLevel, "re-edit the message?") == XRN_CB_ABORT) `7 VB X`09 mesgPane(XRN_SERIOUS, "Aborting the message, saving to %s", X`09`09 app_resources.deadLetters); X`09 saveDeadLetter(ptr); X`09 FREE(ptr); X`09`7D else `7B X`09 mesgPane(XRN_SERIOUS, "not implemented... saving to %s", X`09`09 app_resources.deadLetters); X`09 saveDeadLetter(ptr); X`09 FREE(ptr); X`09`7D X`09return; X `7D X`09 X /* send to the proper processor */ X if ((PostingMode == GRIPE) `7C`7C X`09(PostingMode == FORWARD) `7C`7C X`09(PostingMode == REPLY)) `7B X`09mode = XRN_MAIL; X `7D else `7B X`09mode = XRN_NEWS; X `7D X `20 X switch (postArticle(ptr, mode)) `7B X`09case POST_FAILED: X`09XBell(XtDisplay(TopLevel), 0); X`09mesgPane(XRN_SERIOUS, "Could not send, saving in %s", X`09`09 app_resources.deadLetters); X`09saveDeadLetter(ptr); X`09FREE(ptr); X`09return; X `20 X`09case POST_NOTALLOWED: X`09mesgPane(XRN_SERIOUS, "Posting not allowed from this machine, saving in % Vs", X`09`09 app_resources.deadLetters); X`09break; X`09 X`09case POST_OKAY: X`09mesgPane(XRN_INFO, "Article/Message Sent"); X`09break; X `7D X `20 X FREE(ptr); X return; X`7D X X Xstatic int forkpid;`20 X X#ifndef VMS Xstatic int Xcatch_sigchld(signo) Xint signo; X`7B X if (signo != SIGCHLD) `7B X`09/* whoops! */ X`09return 1; X `7D X (void) signal(SIGCHLD, SIG_DFL); X if (forkpid != wait(0)) `7B X`09/* whoops! */ X`09return 1; X `7D X processMessage(); X FileName`5B0`5D = '\0'; X return 1; X`7D X X#endif X X/* X * definition of the buttons X */ Xextern int inCommand; X X#undef lint X#ifdef MOTIF X#ifdef lint X#define BUTTON(nm,lbl) X#else X#ifdef __STDC__`09 X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic void nm##Function();`09`09`09\ Xstatic void nm##Core(widget)`09`09`09\ XWidget widget;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (!ComposeActive) `7B`09`09`09\ X`09PopdownCompositionTopLevel();`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm##Function(widget);`09`09`09\ X unbusyCursor();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm##Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm##Button(widget, client_data, call_data)`09\ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Button, NULL`7D,`09`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) #nm`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) #lbl`7D,`09`09\ X `7BXmNlabelString, (XtArgVal) NULL`7D,`09`09\ X `7BXmNactivateCallback, (XtArgVal) nm##Callbacks`7D`09\ X`7D; X#else X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic void nm/**/Function();`09`09`09\ Xstatic void nm/**/Core(widget)`09`09`09\ XWidget widget;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (!ComposeActive) `7B`09`09`09\ X`09PopdownCompositionTopLevel();`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm/**/Function(widget);`09`09`09\ X unbusyCursor();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm/**/Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm/**/Button(widget, client_data, call_data)`09\ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Button, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) "nm"`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) "lbl"`7D,`09`09\ X `7BXmNlabelString, (XtArgVal) NULL`7D,`09`09\ X `7BXmNactivateCallback, (XtArgVal) nm/**/Callbacks`7D`09\ X`7D; X X#endif X#endif X#else /* not MOTIF */ X#ifdef lint X#define BUTTON(nm,lbl) X#else X#ifdef __STDC__`09 X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic void nm##Function();`09`09`09\ Xstatic void nm##Core(widget)`09`09`09\ XWidget widget;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (!ComposeActive) `7B`09`09`09\ X`09PopdownCompositionTopLevel();`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm##Function(widget);`09`09`09\ X unbusyCursor();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm##Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm##Button(widget, client_data, call_data)`09\ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm##Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Button, NULL`7D,`09`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) #nm`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) #lbl`7D,`09`09\ X `7BDwtNlabel, (XtArgVal) NULL`7D,`09`09\ X `7BDwtNactivateCallback, (XtArgVal) nm##Callbacks`7D`09\ X`7D; X#else X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic void nm/**/Function();`09`09`09\ Xstatic void nm/**/Core(widget)`09`09`09\ XWidget widget;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X if (!ComposeActive) `7B`09`09`09\ X`09PopdownCompositionTopLevel();`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X if (inCommand) `7B`09`09`09`09\ X`09return;`09`09`09`09`09\ X `7D`09`09`09`09`09`09\ X inCommand = 1;`09`09`09`09\ X busyCursor();`09`09`09`09\ X nm/**/Function(widget);`09`09`09\ X unbusyCursor();`09`09`09`09\ X inCommand = 0;`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm/**/Action(widget, event, string, count) \ XWidget widget;`09`09`09`09`09\ XXEvent *event;`09`09`09`09`09\ XString *string;`09`09`09`09`09\ XCardinal count;`09`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic void nm/**/Button(widget, client_data, call_data)`09\ XWidget widget;`09`09`09`09`09\ Xcaddr_t client_data;`09`09`09`09\ Xcaddr_t call_data;`09`09`09`09\ X`7B`09`09`09`09`09`09\ X nm/**/Core(widget);`09`09`09`09\ X return;`09`09`09`09`09\ X`7D`09`09`09`09`09`09\ Xstatic XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Button, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) "nm"`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) "lbl"`7D,`09`09\ X `7BDwtNlabel, (XtArgVal) NULL`7D,`09`09\ X `7BDwtNactivateCallback, (XtArgVal) nm/**/Callbacks`7D`09\ X`7D; X X#endif X#endif X#endif /* MOTIF */ X XBUTTON(abort,abort); XBUTTON(send,send); XBUTTON(save,save); XBUTTON(includeArticle,include article); XBUTTON(includeFile,include file); X Xstatic XtActionsRec ComposeActions`5B`5D = `7B X `7B"composeAbort", abortAction`7D, X `7B"composeSend", sendAction`7D, X `7B"composeSave", saveAction`7D, X `7B"composeIncludeArticle", includeArticleAction`7D, X `7B"composeIncludeFile", includeFileAction`7D, X`7D; X Xstatic int XcomposePane(titleString, header) Xchar *titleString; Xchar *header; X/* X * brings up a new vertical pane, not moded, but maintains X * enough state so that the current group and/or current X * article can be changed X * X * only one compose pane at a time X * X * the pane consists of 4 parts: title bar, header window, X * scrollable text window, button box X * X * seven functions: X * post article X * followup article X * reply to author X * include the text of the article (followup and reply) X * include a file X * send a gripe X * forward a message X */ X`7B X int maxdesc; X Widget pane, buttonBox, label; X int i; X Arg fontArgs`5B1`5D; X Arg paneArgs`5B15`5D; X Arg MinMaxArgs`5B4`5D; X Arg labelArgs`5B2`5D; X int paneWidth; X#ifdef MOTIF X XmString labelString; X static Arg boxArgs`5B`5D = `7B X`09`7BXmNresizeHeight,`09(XtArgVal) True`7D, X`09`7BXmNresizeWidth,`09(XtArgVal) False`7D, X`09`7BXmNnumColumns,`09`09(XtArgVal) 1`7D, X`09`7BXmNadjustLast, `09(XtArgVal) False`7D, X`09`7BXmNorientation,`09(XtArgVal) XmHORIZONTAL`7D, X`09`7BXmNpacking,`09`09(XtArgVal) XmPACK_TIGHT`7D, X`09`7BXmNallowResize,`09(XtArgVal) True`7D, X`09`7BXmNskipAdjust, `09(XtArgVal) True`7D, X `7D; X static Arg headerArgs`5B`5D = `7B X`09`7BXmNcolumns,`09`09(XtArgVal) 80`7D, X`09`7BXmNrows,`09`09(XtArgVal) 10`7D, X`09`7BXmNwordWrap,`09`09(XtArgVal) FALSE`7D, X`09`7BXmNscrollVertical, `09(XtArgVal) TRUE`7D, X`09`7BXmNscrollHorizontal,`09(XtArgVal) TRUE`7D, X`09`7BXmNeditMode, `09`09(XtArgVal) XmMULTI_LINE_EDIT`7D, X`09`7BXmNskipAdjust, `09(XtArgVal) True`7D, X `7D; X static Arg textArgs`5B`5D = `7B X`09`7BXmNcolumns,`09`09(XtArgVal) 80`7D, X`09`7BXmNrows,`09`09(XtArgVal) 30`7D, X`09`7BXmNwordWrap, `09`09(XtArgVal) FALSE`7D, X`09`7BXmNscrollVertical, `09(XtArgVal) TRUE`7D, X`09`7BXmNscrollHorizontal,`09(XtArgVal) TRUE`7D, X`09`7BXmNeditMode, `09`09(XtArgVal) XmMULTI_LINE_EDIT`7D, X `7D; X X static Arg frameArgs`5B`5D = `7B X`09`7BXmNshadowType,`09`09(XtArgVal) XmSHADOW_OUT`7D, X `7D; X#else /* MOTIF */ X Arg textPos`5B1`5D; X DwtCompString labelString; X static Arg boxArgs`5B`5D = `7B X`09`7BDwtNresizeHeight,`09(XtArgVal) True`7D, X`09`7BDwtNresizeWidth,`09(XtArgVal) False`7D, X`09`7BDwtNorientation,`09(XtArgVal) DwtOrientationHorizontal`7D, X`09`7BDwtNmenuPacking,`09(XtArgVal) DwtMenuPackingTight`7D, X`09`7BDwtNmenuExtendLastRow, (XtArgVal) False`7D, X`09`7BDwtNborderWidth,`09(XtArgVal) 3`7D, X`09`7BDwtNentryBorder,`09(XtArgVal) 2`7D, X`09`7BDwtNspacing,`09`09(XtArgVal) 2`7D, X`09`7BDwtNchildOverlap,`09(XtArgVal) False`7D, X`09`7BDwtNmenuNumColumns,`09(XtArgVal) 1`7D, X`09`7BDwtNmin,`09`09(XtArgVal) 30`7D, X`09`7BDwtNmenuType,`09`09(XtArgVal) DwtWorkarea`7D, X `7D; X static Arg headerArgs`5B`5D = `7B X`09`7BDwtNcols,`09`09(XtArgVal) 80`7D, X`09`7BDwtNrows,`09`09(XtArgVal) 10`7D, X`09`7BDwtNwordWrap,`09`09(XtArgVal) TRUE`7D, X`09`7BDwtNscrollVertical,`09(XtArgVal) TRUE`7D, X `7D; X static Arg textArgs`5B`5D = `7B X`09`7BDwtNcols,`09`09(XtArgVal) 80`7D, X`09`7BDwtNrows,`09`09(XtArgVal) 30`7D, X`09`7BDwtNwordWrap, `09`09(XtArgVal) TRUE`7D, X`09`7BDwtNscrollVertical,`09(XtArgVal) TRUE`7D, X `7D; X X#endif /* MOTIF */ X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return(-1); X `7D X X if (app_resources.editorCommand != NIL(char)) `7B X`09char buffer`5B1024`5D; X`09FILE *filefp; X`09struct stat buf, oldbuf; X`09int sysStat; X X#ifndef VMS X`09(void) sprintf(FileName, "%s/xrnXXXXXXX.tmp", app_resources.tmpDir); X#else X`09(void) sprintf(FileName, "%sxrnXXXXXXX.tmp", app_resources.tmpDir); X#endif X`09(void) mktemp(FileName); X`09 X`09if ((filefp = fopen(FileName, "w")) == NULL) `7B X`09 mesgPane(XRN_SERIOUS, "Can not open the temp file"); X`09 return(-1); X`09`7D X X`09sizeCompose(utStrlen(header)); X`09(void) strcpy(CompositionString, HeaderString); X`09(void) strcat(CompositionString, header); X`09if ((PostingMode != FORWARD) && (PostingMode != POST) && X`09 (PostingMode != GRIPE)) `7B X`09 includeArticleText(); X`09`7D`09 `20 X `20 X`09(void) fwrite(CompositionString, sizeof(char), utStrlen(CompositionString V), filefp); X`09(void) fclose(filefp); X X`09if (stat(FileName, &oldbuf) == -1) `7B X`09 mesgPane(XRN_SERIOUS, "Can not stat the temp file"); X`09 return(-1); X`09`7D X`09 X`09/* X`09 * app_resources.editorCommand is a sprintf'able string with a %s where t Vhe X`09 * file name should be placed. The result should be a command that X`09 * handles all editing and windowing. X`09 * X`09 * Examples are: X`09 * X`09 * emacsclient %s X`09 * xterm -e vi %s X`09 * xterm -e microEmacs %s X`09 * X`09 */ X`09(void) sprintf(buffer, app_resources.editorCommand, FileName); X#ifndef VMS X`09if ((forkpid = fork()) == 0) `7B X`09 int i; X X#ifdef hpux X`09 maxdesc = _NFILE; X#else X#ifdef SVR4 X#include X`09 maxdesc = ulimit(UL_GDESLIM); X#else X`09 maxdesc = getdtablesize(); X#endif X#endif X`09 for (i = 3; i < maxdesc; i++) `7B X`09`09(void) close(i); X`09 `7D X`09 (void) execl("/bin/csh", "csh", "-f", "-c", buffer, 0); X`09 (void) fprintf(stderr, "execl of %s failed\n", buffer); X`09 (void) _exit(127); X`09`7D X`09if (forkpid < 0) `7B X`09 sprintf(error_buffer, "Can not execute editor (%s)", X`09 `09errmsg(errno)); X`09 infoNow(error_buffer); X`09 FileName`5B0`5D = '\0'; X`09`7D else `7B X`09`09signal(SIGCHLD, (SIG_PF0) catch_sigchld); X`09`7D X#else X`09sysStat = system(buffer); X`09if ((sysStat & 1) != 1) `7B X`09 mesgPane(XRN_SERIOUS, "Error return from system - %d, aborting", X`09`09sysStat); X`09 return(-1); X`09`7D X`09processMessage(); X#endif X`09return(0); X `7D X `20 X ComposeActive = True; X if (ComposeTopLevel != (Widget) 0) `7B X`09i = 0; X#ifdef MOTIF X`09XtSetArg(paneArgs`5Bi`5D, XmNtitle,`09`09(XtArgVal) titleString);i++; X#else X`09XtSetArg(paneArgs`5Bi`5D, DwtNtitle,`09(XtArgVal) titleString);i++; X#endif X`09XtSetValues(ComposeTopLevel, paneArgs, i); X `7D else `7B X`09i = 0; X#ifdef MOTIF X`09XtSetArg(paneArgs`5Bi`5D, XtNinput, `09(XtArgVal) True); i++; X`09XtSetArg(paneArgs`5Bi`5D, XmNiconName, `09(XtArgVal) "XRN Compose"); i++; X`09XtSetArg(paneArgs`5Bi`5D, XmNtransient,`09(XtArgVal) False); i++; X`09XtSetArg(paneArgs`5Bi`5D, XmNallowShellResize,(XtArgVal) True); i++; X`09XtSetArg(paneArgs`5Bi`5D, XmNallowResize,`09(XtArgVal) True);i++; X`09XtSetArg(paneArgs`5Bi`5D, XmNtitle,`09`09(XtArgVal) titleString);i++; X#else X`09XtSetArg(paneArgs`5Bi`5D, XtNinput, `09(XtArgVal) True); i++; X`09XtSetArg(paneArgs`5Bi`5D, XtNallowShellResize, (XtArgVal) True); i++; X`09XtSetArg(paneArgs`5Bi`5D, DwtNtitle,`09(XtArgVal) titleString);i++; X#endif X X`09ComposeTopLevel = XtAppCreateShell("ComposeTop", "composeTop", X`09`09`09`09`09 applicationShellWidgetClass, X`09`09`09`09`09 XtDisplay(TopLevel), X`09`09`09`09`09 paneArgs, i); X X#ifdef MOTIF X`09pane = XtCreateManagedWidget("pane", xmPanedWindowWidgetClass, X`09`09`09`09`09ComposeTopLevel, NULL, 0); X#else X`09i = 0; X`09XtSetArg(paneArgs`5Bi`5D, DwtNwidth,`09(XtArgVal) 680);i++; X`09XtSetArg(paneArgs`5Bi`5D, DwtNheight,`09(XtArgVal) 600);i++; X`09pane = XtCreateManagedWidget("pane", panewidgetclass, X`09`09`09`09`09ComposeTopLevel, paneArgs, i); X#endif X X /* XXX how to make a 80 column text window with scroll bar */ X headerArgs`5B0`5D.value = app_resources.breakLength; /* set rows */ X`09textArgs`5B0`5D.value = app_resources.breakLength; X#ifdef MOTIF X`09headerFrame = XtCreateManagedWidget("headerFrame", xmFrameWidgetClass, X`09`09`09`09`09pane, frameArgs,XtNumber(frameArgs)); X`09HeaderText = XmCreateScrolledText(headerFrame, "headerText", X`09`09`09`09`09headerArgs, XtNumber(headerArgs)); X#else X`09HeaderText = DwtSTextCreate(pane, "headerText", X`09`09`09`09`09headerArgs, XtNumber(headerArgs)); X#endif X`09XtManageChild(HeaderText); X#ifdef MOTIF X`09textFrame = XtCreateManagedWidget("textFrame", xmFrameWidgetClass, X`09`09`09`09`09pane, frameArgs,XtNumber(frameArgs)); X`09ComposeText = XmCreateScrolledText(textFrame, "composeText",`20 X`09`09`09`09`09textArgs, XtNumber(textArgs)); X#else X`09ComposeText = DwtSTextCreate(pane, "composeText",`20 X`09`09`09`09`09textArgs, XtNumber(textArgs)); X#endif X`09XtManageChild(ComposeText); X#ifdef MOTIF X`09buttonBox = XtCreateManagedWidget("box", xmRowColumnWidgetClass, X`09`09pane, boxArgs, XtNumber(boxArgs)); X#else X`09buttonBox = DwtMenuCreate(pane, "box", boxArgs, XtNumber(boxArgs)); X`09XtManageChild(buttonBox); X X`09paneWidth = 0; X`09XtSetArg(paneArgs`5B0`5D, DwtNwidth, &paneWidth); X`09XtGetValues(ComposeText, paneArgs, 1); X`09XtSetArg(paneArgs`5B0`5D, DwtNwidth, paneWidth); X`09XtSetValues(pane, paneArgs, 1); X#endif X X`09if (abortArgs`5B2`5D.value == NULL) `7B X#ifdef MOTIF X`09 abortArgs`5B2`5D.value = (XtArgVal)XmStringLtoRCreate(abortArgs`5B1`5 VD.value, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 abortArgs`5B2`5D.value = (XtArgVal)DwtLatin1String(abortArgs`5B1`5D.v Value); X#endif X`09`7D X#ifdef MOTIF X`09AbortButton = XtCreateManagedWidget("abort", xmPushButtonWidgetClass, X`09`09`09`09buttonBox, abortArgs, XtNumber(abortArgs)); X `20 X#else X`09AbortButton = XtCreateManagedWidget("abort", pushbuttonwidgetclass, X`09`09`09`09buttonBox, abortArgs, XtNumber(abortArgs)); X#endif X`09if (sendArgs`5B2`5D.value == NULL) `7B X#ifdef MOTIF X`09 sendArgs`5B2`5D.value = (XtArgVal)XmStringLtoRCreate(sendArgs`5B1`5D. Vvalue, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 sendArgs`5B2`5D.value = (XtArgVal)DwtLatin1String(sendArgs`5B1`5D.val Vue); X#endif X`09`7D X#ifdef MOTIF X`09SendButton = XtCreateManagedWidget("send", xmPushButtonWidgetClass, X`09`09`09`09buttonBox, sendArgs, XtNumber(sendArgs)); X#else X`09SendButton = XtCreateManagedWidget("send", pushbuttonwidgetclass, X`09`09`09`09buttonBox, sendArgs, XtNumber(sendArgs)); X#endif X `20 X`09if (saveArgs`5B2`5D.value == NULL) `7B X#ifdef MOTIF X`09 saveArgs`5B2`5D.value = (XtArgVal)XmStringLtoRCreate(saveArgs`5B1`5D. Vvalue, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 saveArgs`5B2`5D.value = (XtArgVal)DwtLatin1String(saveArgs`5B1`5D.val Vue); X#endif X`09`7D X#ifdef MOTIF X`09SaveButton = XtCreateManagedWidget("save", xmPushButtonWidgetClass, X`09`09`09buttonBox, saveArgs, XtNumber(saveArgs)); X#else X`09SaveButton = XtCreateManagedWidget("save", pushbuttonwidgetclass, X`09`09`09buttonBox, saveArgs, XtNumber(saveArgs)); X#endif X X`09if (includeFileArgs`5B2`5D.value == NULL) `7B X#ifdef MOTIF X`09 includeFileArgs`5B2`5D.value = (XtArgVal) XmStringLtoRCreate( X`09`09`09`09`09`09includeFileArgs`5B1`5D.value, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 includeFileArgs`5B2`5D.value = (XtArgVal)DwtLatin1String( X`09`09`09`09`09includeFileArgs`5B1`5D.value); X#endif X`09`7D X#ifdef MOTIF X`09IncludeFileButton = XtCreateManagedWidget("includeFile", X`09`09`09xmPushButtonWidgetClass, buttonBox, X`09`09`09includeFileArgs, XtNumber(includeFileArgs)); X#else X`09IncludeFileButton = XtCreateManagedWidget("includeFile", X`09`09`09pushbuttonwidgetclass, buttonBox, X`09`09`09includeFileArgs, XtNumber(includeFileArgs)); X#endif X X`09if (includeArticleArgs`5B2`5D.value == NULL) `7B X#ifdef MOTIF X`09 includeArticleArgs`5B2`5D.value = (XtArgVal)XmStringLtoRCreate( X`09`09`09`09`09`09includeArticleArgs`5B1`5D.value, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 includeArticleArgs`5B2`5D.value = (XtArgVal)DwtLatin1String( X`09`09`09`09`09includeArticleArgs`5B1`5D.value); X#endif X`09`7D X#ifdef MOTIF X`09IncludeArticleButton = XtCreateManagedWidget("includeArticle", X`09`09`09xmPushButtonWidgetClass, buttonBox, X`09`09`09includeArticleArgs, XtNumber(includeArticleArgs)); X#else X`09IncludeArticleButton = XtCreateManagedWidget("includeArticle", X`09`09`09pushbuttonwidgetclass, buttonBox, X`09`09`09includeArticleArgs, XtNumber(includeArticleArgs)); X#endif X`09xmIconCreate(ComposeTopLevel); X`09XtAddActions(ComposeActions, XtNumber(ComposeActions)); X `7D X X sizeCompose(utStrlen(header)); X (void) strcpy(CompositionString, header); X#ifdef MOTIF X XmTextSetString(HeaderText,HeaderString); X XmTextSetString(ComposeText,CompositionString); X#ifdef MOTIF_V1_0 X XmTextSetInsertionPosition(ComposeText, X`09(XmTextPosition) utStrlen(CompositionString)); X#else X XmTextSetCursorPosition(ComposeText, X`09(XmTextPosition) utStrlen(CompositionString)); X#endif X#else X DwtSTextSetString(HeaderText,HeaderString); X DwtSTextSetString(ComposeText,CompositionString); X XtSetArg(textPos`5B0`5D, DwtNinsertionPosition, X`09(XtArgVal) utStrlen(CompositionString)); X XtSetValues(ComposeText, textPos, XtNumber(textPos)); X#endif X X XtSetSensitive(SendButton, True); X XtSetSensitive(SaveButton, True); X XtSetSensitive(IncludeFileButton, True); X XtSetSensitive(IncludeArticleButton, (PostingMode != POST)); X XtRealizeWidget(ComposeTopLevel); X `20 X XtMapWidget(ComposeTopLevel); X X return; X`7D X X Xstatic char * XsignatureFile() X/* X * return a string containing the contents of the users signature file X * (in a static buffer) X * X * if the signature file is bigger than MAX_SIGNATURE_SIZE, return NIL(char) V. X */ X`7B X char *file; X struct stat buf; X FILE *infofp; X long count; X static char *sigInfo; X static initialized = 0; X X if (!initialized) `7B X X`09sigInfo = NIL(char); X`09 X`09if ((file = utTildeExpand(app_resources.signatureFile)) == NIL(char)) `7B X`09 return(NIL(char)); X`09`7D X`09if (stat(file, &buf) == -1) `7B X`09 return(NIL(char)); X`09`7D X`09if (buf.st_size > MAX_SIGNATURE_SIZE) `7B X`09 return(NIL(char)); X`09`7D X`09if ((infofp = fopen(file, "r")) == NULL) `7B X`09 return(NIL(char)); X`09`7D X`09sigInfo = ARRAYALLOC(char, (buf.st_size + 1 + 3)); /* 3 for "--\n" */ X`09(void) strcpy(sigInfo, "--\n"); X`09count = fread(&sigInfo`5B3`5D, sizeof(char), buf.st_size, infofp); X`09sigInfo`5Bcount + 3`5D = '\0'; X X`09(void) fclose(infofp); X`09initialized = 1; X `7D X `20 X return(sigInfo); X`7D X X X/* public functions 'reply', 'gripe', 'forward', 'followup', and 'post' */ X Xvoid Xreply() X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num current = newsgroup->current; X char title`5BLABEL_SIZE`5D; X char pathFormatString`5B100`5D; X char *message, *signature; X int OldPostingMode = PostingMode; X X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X getHeader(current); X Header.artText = newsgroup->articles`5BINDEX(current)`5D.filename; X X PostingMode = REPLY; X message = XtMalloc(MAX_SIGNATURE_SIZE + BUFFER_SIZE +`20 X`09`09`09utStrlen(Header.artText)); X sizeCompose(utStrlen(Header.artText) + MAX_SIGNATURE_SIZE + BUFFER_SIZE) V; X X (void) sprintf(title, "Reply to article %ld in %s", current, X`09`09newsgroup->name); X `20 X if (app_resources.replyPath != NIL(char)) `7B X`09if (app_resources.cc == True) `7B X`09 sprintf(pathFormatString, "To: %s\nCc: \n",app_resources.replyPath); X`09`7D else `7B X`09 sprintf(pathFormatString, "To: %s\n",app_resources.replyPath); X`09`7D X `7D else `7B X`09if (app_resources.cc == True) `7B X`09 strcpy(pathFormatString, "To: %s\nCc: \n"); X`09`7D else `7B X`09 strcpy(pathFormatString, "To: %s\n"); X`09`7D X `7D X (void) sprintf(message, pathFormatString, X`09`09 (*Header.replyTo != '\0') ? Header.replyTo : Header.from); X buildSubject(message); X (void) strcat(message, "\n"); X InsertionPoint = utStrlen(message); X (void) strcat(message, "\n"); X strcpy(HeaderString, message); X message`5B0`5D = '\0'; X if ((signature = signatureFile()) != NIL(char)) `7B X`09(void) strcpy(message, signature); X `7D X if (composePane(title, message)) X`09 PostingMode = OldPostingMode; X X FREE(message); X return; X`7D X X Xvoid Xgripe() X`7B X char title`5BLABEL_SIZE`5D; X char message`5BMAX_SIGNATURE_SIZE + 10000`5D, *signature; X int OldPostingMode = PostingMode; X `20 X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X sizeCompose(1000); X (void) strcpy(title, "Gripe"); X (void) sprintf(message, "To: %s\nSubject: GRIPE about XRN %s\n\n", X`09`09 GRIPES, XRN_VERSION); X InsertionPoint = utStrlen(message); X (void) strcat(message, "\n"); X (void) strcpy(HeaderString, message); X message`5B0`5D = '\0'; X if ((signature = signatureFile()) != NIL(char)) `7B X`09(void) strcat(message, signature); X `7D X X Header.artText = NULL; X PostingMode = GRIPE; X if (composePane(title, message)) X`09 PostingMode = OldPostingMode; X X return; X`7D X X Xvoid Xforward() X`7B X char title`5BLABEL_SIZE`5D; X char *signature; X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num current = newsgroup->current; X int OldPostingMode = PostingMode; X `20 X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X getHeader(current); X Header.artText = newsgroup->articles`5BINDEX(current)`5D.filename; X `20 X sizeCompose(MAX_SIGNATURE_SIZE + utStrlen(Header.artText) + 1000); X (void) sprintf(title, "Forward article %ld in %s to a User", current, X`09`09 newsgroup->name); X if (app_resources.cc == True) `7B X`09(void) sprintf(HeaderString, "To: \nCc: \nSubject: \n\n"); X `7D else `7B X`09(void) sprintf(HeaderString, "To: \nSubject: \n\n"); X `7D X InsertionPoint = 0; X if ((signature = signatureFile()) != NIL(char)) `7B X`09(void) strcpy(TempString, signature); X `7D else `7B X`09*TempString = '\0'; X `7D X X strcpy(CompositionString, TempString); X InsertionPoint = 0; X PostingMode = FORWARD; X includeArticleText(); X strcpy(TempString, CompositionString); X if (composePane(title, TempString)) X`09 PostingMode = OldPostingMode; X return; X`7D X X#ifdef GENERATE_EXTRA_FIELDS X/* X * generate a message id X */ Xstatic char genid`5B132`5D; X Xstatic char *gen_id() X`7B X char *timestr, *cp; X time_t cur_time; X X time(&cur_time); X timestr = ctime(&cur_time); X X (void) sprintf(genid, "<%.4s%.3s%.2s.%.2s%.2s%.2s@%s>", X`09`09 ×tr`5B20`5D, ×tr`5B4`5D, ×tr`5B8`5D, X`09`09 ×tr`5B11`5D, ×tr`5B14`5D, ×tr`5B17`5D, X`09`09 Header.host); X cp = &genid`5B8`5D; X X if (*cp == ' ') `7B X`09do `7B X`09 *cp = *(cp + 1);`20 X`09`7D while (*cp++); X `7D X X return(genid); X`7D X#endif X Xvoid Xfollowup() X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num current = newsgroup->current; X char buffer`5B10000`5D, title`5BLABEL_SIZE`5D; X char *signature, *ptr; X int OldPostingMode = PostingMode; X X#ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X char timeString`5B30`5D; X#endif X X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X if ((newsgroup->status & NG_UNPOSTABLE) == NG_UNPOSTABLE) `7B X`09mesgPane(XRN_SERIOUS, "Can not post articles to this group"); X`09return; X `7D X X getHeader(current); X Header.artText = newsgroup->articles`5BINDEX(current)`5D.filename; X sizeCompose(utStrlen(Header.artText) + MAX_SIGNATURE_SIZE + 1000); X `20 X PostingMode = FOLLOWUP; X (void) sprintf(title, "Followup to article %ld in %s", current, newsgrou Vp->name); X X#ifdef INEWS X (void) sprintf(TempString, "Path: %s\n", Header.user); X#else X (void) sprintf(TempString, "Path: %s!%s\n", Header.path, Header.user); X#endif X if (*Header.followupTo != '\0') `7B X`09Header.newsgroups = XtNewString(Header.followupTo); X `7D X (void) sprintf(buffer, "Newsgroups: %s\n", Header.newsgroups); X (void) strcpy(TempString, buffer); X (void) strcat(TempString, "Distribution: "); X if ((Header.distribution != NIL(char)) && (*Header.distribution != '\0') V) `7B X`09(void) strcat(TempString, Header.distribution); X `7D else if (app_resources.distribution) `7B X`09(void) strcat(TempString, app_resources.distribution); X `7D else `7B`09 X`09(void) strcat(TempString, DISTRIBUTION); X `7D X (void) strcat(TempString, "\n"); X (void) strcat(TempString, "Followup-To: \n"); X (void) sprintf(buffer, "References: %s %s\n", X`09Header.references, Header.messageId); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "From: %s@%s (%s)\n", X`09`09 Header.user, Header.host, Header.fullname); X (void) strcat(TempString, buffer); X X#ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X#ifndef VMS X/* gmtime() always returns null on VMS.. */ X (void) time(&clockTime); X (void) strcpy(timeString, asctime(gmtime(&clockTime))); X ptr = index(timeString, '\n'); X *ptr = '\0'; X (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X#endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X#endif X X (void) strcat(TempString, "Reply-To: "); X if (app_resources.replyTo != NIL(char)) `7B X`09(void) strcat(TempString, app_resources.replyTo); X `7D else `7B X`09(void) sprintf(buffer, "%s@%s (%s)", X`09`09 Header.user, Header.host, Header.fullname); X`09(void) strcat(TempString, buffer); X `7D X (void) strcat(TempString, "\n"); X X (void) strcat(TempString, "Organization: "); X if (app_resources.organization != NIL(char)) `7B X`09(void) strcat(TempString, app_resources.organization); X `7D else `7B X`09(void) strcat(TempString, ORG_NAME); X `7D X (void) strcat(TempString, "\n"); X X buildSubject(TempString); X `20 X (void) strcat(TempString, "Keywords: "); X if ((Header.keywords != NIL(char)) && (*Header.keywords != '\0')) `7B X`09(void) strcat(TempString, Header.keywords); X `7D X (void) strcat(TempString, "\n"); X X (void) strcpy(HeaderString, TempString); X X InsertionPoint = utStrlen(TempString); X `20 X if ((signature = signatureFile()) != NIL(char)) `7B X`09(void) strcpy(TempString, signature); X `7D else `7B X`09*TempString = '\0'; X `7D X X if (composePane(title, TempString)) X`09 PostingMode = OldPostingMode; X X return; X`7D X X Xvoid Xpost(ingroupp) Xint ingroupp; X`7B X struct newsgroup *newsgroup; X char title`5BLABEL_SIZE`5D, buffer`5B10000`5D; X char *signature; X int OldPostingMode = PostingMode; X X#ifdef GENERATE_EXTRA_FIELDS X time_t clockTime; X char *ptr, timeString`5B30`5D; X#endif X X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X if (CurrentGroupNumber != NO_GROUP) `7B X`09newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X`09if ((newsgroup->status & NG_UNPOSTABLE) == NG_UNPOSTABLE) `7B X`09 mesgPane(XRN_SERIOUS, "Can not post articles to this group"); X`09 return; X`09`7D X `7D X X sizeCompose(10000); X getHeader((art_num) 0); X X if (!ingroupp `7C`7C (CurrentGroupNumber == NO_GROUP)) `7B X`09FREE(Header.newsgroups); X`09Header.newsgroups = XtNewString(""); X`09(void) strcpy(title, "Post article (no current group)"); X `7D else `7B X`09(void) sprintf(title, "Post article to `60%s'", newsgroup->name); X `7D X X#ifdef INEWS X (void) sprintf(TempString, "Path: %s\n", Header.user); X#else X (void) sprintf(TempString, "Path: %s!%s\n", Header.path, Header.user); X#endif X (void) sprintf(buffer, "Newsgroups: %s\n", Header.newsgroups); X (void) strcat(TempString, buffer); X (void) strcat(TempString, "Distribution: "); X if (app_resources.distribution) `7B X`09(void) strcat(TempString, app_resources.distribution); X `7D else `7B`09 X`09(void) strcat(TempString, DISTRIBUTION); X `7D X (void) strcat(TempString, "\n"); X X#ifdef GENERATE_EXTRA_FIELDS X /* stuff to generate Message-ID and Date... */ X#ifndef VMS X (void) time(&clockTime); X (void) strcpy(timeString, asctime(gmtime(&clockTime))); X ptr = index(timeString, '\n'); X *ptr = '\0'; X (void) sprintf(buffer, "Date: %s GMT\n", timeString); X (void) strcat(TempString, buffer); X#endif X (void) sprintf(buffer, "Message-ID: %s\n", gen_id()); X (void) strcat(TempString, buffer); X#endif X X (void) strcat(TempString, "Followup-To: \n"); X (void) sprintf(buffer, "From: %s@%s (%s)\n", X`09`09 Header.user, Header.host, Header.fullname); X (void) strcat(TempString, buffer); X (void) strcat(TempString, "Reply-To: "); X if (app_resources.replyTo != NIL(char)) `7B X`09(void) strcat(TempString, app_resources.replyTo); X `7D else `7B X`09(void) sprintf(buffer, "%s@%s (%s)", Header.user, Header.host, Header.ful Vlname); X`09(void) strcat(TempString, buffer); X `7D X (void) strcat(TempString, "\n"); X X (void) strcat(TempString, "Organization: "); X if (app_resources.organization != NIL(char)) `7B X`09(void) strcat(TempString, app_resources.organization); X `7D else `7B X`09(void) strcat(TempString, ORG_NAME); X `7D X (void) strcat(TempString, "\n"); X (void) strcat(TempString, "Subject: \n"); X (void) strcat(TempString, "Keywords: \n"); X `20 X (void) strcpy(HeaderString, TempString); X X InsertionPoint = 0; X if ((signature = signatureFile()) != NIL(char)) `7B X`09(void) strcpy(TempString, signature); X `7D else `7B X`09*TempString = '\0'; X `7D X X PostingMode = POST; X if (composePane(title, TempString)) X`09 PostingMode = OldPostingMode; X X return; X`7D X X Xvoid XcancelArticle() X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num current = newsgroup->current; X char buffer`5B10000`5D; X char *bufptr; X X if (ComposeActive) `7B X`09mesgPane(XRN_SERIOUS, "Only one composition pane at a time"); X`09return; X `7D X if ((newsgroup->status & NG_UNPOSTABLE) == NG_UNPOSTABLE) `7B X`09mesgPane(XRN_SERIOUS, "Can not post articles to this group"); X`09return; X `7D X X getHeader(current); X X sizeCompose(10000); X /* verify that the user can cancel the article */ X bufptr = index(Header.from, '@'); X if (bufptr != NIL(char)) `7B X`09bufptr++; X`09(void) strcpy(buffer, bufptr); X`09if ((bufptr = index(buffer, ' ')) != NIL(char)) `7B X`09 *bufptr = '\0'; X`09`7D X`09if (strncmp(Header.host, buffer, utStrlen(Header.host)) X`09 `7C`7C (strncmp(Header.user, Header.from, utStrlen(Header.user))`20 X`09 && strcmp(Header.user, "root"))) `7B X`09 mesgPane(XRN_SERIOUS, "Not entitled to cancel the article"); X`09 return; X `7D X `7D X X#ifdef INEWS X (void) sprintf(TempString, "Path: %s\n", Header.user); X#else X (void) sprintf(TempString, "Path: %s!%s\n", Header.path, Header.user); X#endif X (void) sprintf(buffer, "From: %s@%s (%s)\n", Header.user, Header.host, H Veader.fullname); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "Subject: cancel %s\n", Header.messageId); X (void) strcat(TempString, buffer); X if (*Header.followupTo != '\0') `7B X`09Header.newsgroups = XtNewString(Header.followupTo); X `7D X (void) sprintf(buffer, "Newsgroups: %s\n", Header.newsgroups); X (void) strcat(TempString, buffer); X (void) sprintf(buffer, "References: %s %s\n", X`09`09 Header.references, Header.messageId); X (void) strcat(TempString, buffer); X X (void) strcat(TempString, "Distribution: "); X if ((Header.distribution != NIL(char)) && (*Header.distribution != '\0') V) `7B X`09(void) strcat(TempString, Header.distribution); X `7D else if (app_resources.distribution) `7B X`09(void) strcat(TempString, app_resources.distribution); X `7D else `7B X`09(void) strcat(TempString, DISTRIBUTION); X `7D X (void) strcat(TempString, "\n"); X (void) sprintf(buffer, "Control: cancel %s\n", Header.messageId); X (void) strcat(TempString, buffer); X X switch (postArticle(TempString,XRN_NEWS)) `7B X`09case POST_FAILED: X`09mesgPane(XRN_SERIOUS, "Could not cancel the article"); X`09break; X X`09case POST_NOTALLOWED: X`09mesgPane(XRN_SERIOUS, "Posting not allowed from this machine"); X`09break; X`09 `20 X`09case POST_OKAY: X`09mesgPane(XRN_INFO, "Canceled the article"); X`09break; X `7D X X return; X`7D X Xstatic void LowerCase(source, dest) Xregister char *source, *dest; X`7B X register char ch; X X for (; (ch = *source) != '\0'; source++, dest++) `7B X`09if ('A' <= ch && ch <= 'Z') X`09 *dest = ch - 'A' + 'a'; X`09else X`09 *dest = ch; X `7D X *dest = '\0'; X`7D $ CALL UNPACK COMPOSE.C;1 2047133904 $ create 'f' X#ifndef COMPOSE_H X#define COMPOSE_H X X/* X * $Header: /users/ricks/xrn/src/RCS/compose.h,v 1.7 90/09/29 02:27:24 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * compose.h: functions for composing and sending messages X */ X Xextern void post(); Xextern void followup(); Xextern void reply(); Xextern void cancelArticle(); Xextern void gripe(); Xextern void forward(); X X#endif /* COMPOSE_H */ $ CALL UNPACK COMPOSE.H;1 1082078351 $ create 'f' X#ifndef CONFIG_H X#define CONFIG_H X X/* X * $Header: /users/ricks/xrn/src/RCS/config.h,v 1.19 90/09/29 01:10:15 ricks V Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * config.h: configurable defaults X */ X X/* place to report bugs and request new features */ X#ifndef GRIPES X#define GRIPES "murphy@ufp.dco.dec.com" X#endif X X/* if you want xrn to provide a titlebar */ X/* #define TITLEBAR */ X X/* if you want a short icon name */ X#define SHORT_ICONNAME X X/* define to use the DEC cursor font */ X#define USE_DEC_CURSOR X X/* X * your internet domain name, examples are: X * X * .Berkeley.EDU X * .mit.EDU X * .CSS.GOV X * .CS.NET X * .BITNET X * .UUCP X * X * wouldn't it be nice if there were a call like 'gethostname' X * that would get the domain name... X * X * DOMAIN_NAME can be overriden with the DOMAIN environment variable`20 X * or the DOMAIN_FILE (see below) X * X * NOTE: use of the RESOLVER define should make DOMAIN_NAME obsolete`20 X * X */ X#ifndef DOMAIN_NAME X#define DOMAIN_NAME ".enet.dec.com" X#endif X X/* X * Define RETURN_HOST if you want a default return address host name. X * Useful if your site uses MX records or something to address all X * mail to a pseudo host (e.g. user@Berkeley.EDU) X */ X/*#define RETURN_HOST "Berkeley.EDU"*/ X X/* default distribution */ X#ifndef DISTRIBUTION X#define DISTRIBUTION "world" X#endif X X/* organization name */ X#ifndef ORG_NAME X#define ORG_NAME`09"Digital Equipment Corporation" X#endif X X/* uucp netnews name (if different from your internet host name) */ X/* #define UUCPNAME "/etc/uucpname" */ X X#ifndef VMS X/* X * name of the nntp server is in this file - can be overriden X * by command line option, X resource, or environment variable X */ X#ifndef SERVER_FILE X#define SERVER_FILE "/usr/local/lib/rn/server" X#endif X/* X * name of the host to use as the users host name in the From field X * in a composition is in thie file X */ X#ifndef HIDDEN_FILE X#define HIDDEN_FILE "/usr/local/lib/news/hiddenhost" X#endif X/* X * name of the host to use as the users hosts name in the Path field`20 X * in a composition is in the file X */ X#ifndef PATH_FILE X#define PATH_FILE "/usr/local/lib/news/pathhost" X#endif X/* X * name of the internet domain is in this file X */ X#ifndef DOMAIN_FILE X#define DOMAIN_FILE "/usr/local/lib/news/domain" X#endif X/* X * name of the organization is in this file X */ X#ifndef ORG_FILE X#define ORG_FILE "/usr/local/lib/news/organization" X#endif X#else X#define SERVER_FILE "SYS$LOGIN:NNTP.SERVER" X#define HIDDEN_FILE "SYS$LOGIN:HIDDEN.HOST" X#define PATH_FILE "SYS$LOGIN:PATH.HOST" X#define DOMAIN_FILE "SYS$LOGIN:DOMAIN.NAME" X#define ORG_FILE "SYS$LOGIN:ORG.NAME" X#endif X X/* X * maximum size of a signature file (in bytes), if file is bigger than this, X * it is not included X */ X#define MAX_SIGNATURE_SIZE 1000 X X/* X * Prefix for each line included from an article X */ X#define INCLUDEPREFIX`09"`7C> " X X X/* X * for of author names: email address (default) or fullname X */ X#define AUTHOR_FULLNAME X X/* prefetch articles and groups */ X/*#define XRN_PREFETCH */ X X/* X * if there are more the this many unread articles in the next X * group, do not prefetch it X */ X X#ifdef XRN_PREFETCH X#define XRN_PREFETCH_MAX "50" X#endif /* XRN_PREFETCH */ X X/* X * number of article headers to prefetch when searching subjects X * in the backwards direction X */ X#define SUBJECTS`0910 X X X/* X * use the name server to find out your official (with domain) host name X */ X#ifndef RESOLVER X#define RESOLVER X#endif X X/* X * For debugging only, define if you want core dumps, rather than X * a death notification box and an attempt at updating the .newsrc X * and cleaning up the temporary files X * X */ X/* #define DUMPCORE */ X X/* X * use MOTIF widgets X */ X/* #define MOTIF */ X X/* X * use less memory at the expense of some cpu time X * I have had some reports that this may not be working... X */ X/* #define STUPIDMMU */ X X/* X * for various bugs in the toolkit / widget set X */ X/* #define TRANSLATIONBUG */`09/* DEC (VMS) X windows release`09`09*/ X/* #define ERRORBUG */`09`09/* DEC (VMS) X windows release`09`09*/ X/* #define DECFOCUSPATCH */`09/* for certain DEC window managers`09*/ X X/* X * If XFILESEARCHPATH is defined, then its contents are treated as a string` V20 X * which is appended to the end of the XFILESEARCHPATH environment variable. X * The purpose of this is that if you are planning on installing xrn X * (and its app-defaults file) in a non-standard location, you can make`20 X * sure that it will find its app-defaults file by compiling the program`20 X * with the path to the file set in XFILESEARCHPATH (for example, when`20 X * I compile the program I #define XFILESEARCHPATH to be`20 X * "/usr/sipb/lib/%T/%N", since I install it in the Student Information`20 X * Processing Board (SIPB) filesystem. This patch addresses a general`20 X * flaw in X11R4's (and X11R3's) handling of application defaults file -- X * there is no way for the programmer to suggest to the toolkit X * where to look for the file without mucking with environment variables. X * X * (Jonathan I. Kamens ) X */ X/* #define XFILESEARCHPATH "path"*/ X X/* X * generate Message-ID and Date fields X * X * NNTP POST should handle this, but does not for some X * implementations X */ X/*#define GENERATE_EXTRA_FIELDS*/ X X/* X * the active file of most currently used news systems has a problem: X * if the first article number equals the last article number for a X * newsgroup, this means that there are 0 OR 1 ARTICLES. X * X * Cnews and and Bnews 2.11 (patch #19) have fixed this problem. X */ X/* #define FIXED_ACTIVE_FILE */ X X/* X * deal with stupid C-news problem of NOT updating the low number X * of the group entries in the active file - define this if you X * have fixed the problem X */ X/* #define FIXED_C_NEWS_ACTIVE_FILE */ X X/* X * Do you want to use inews for postings? X */ X/* #define INEWS "/usr/lib/news/inews" */ X X/* X * Does INEWS read the signature file? X */ X/* #define INEWS_READS_SIG */ X X/* X * if you don't want XRN to eat type ahead, define this X */ X/*#define DO_NOT_EAT_TYPE_AHEAD*/ X X/* SYSTEM V regex package */ X#if defined(macII) `7C`7C defined(aiws) `7C`7C defined(hpux) `7C`7C defined( VSYSV) X#define SYSV_REGEX X#ifndef SYSV X#define SYSV X#endif X#endif X X/* bsd b* functions */ X#if defined(sequent) `7C`7C !defined(SYSV) X#define BSD_BFUNCS X#endif X X/* v`7Bs,f`7Dprintf functions */ X#if defined(sequent) `7C`7C defined(ibm032) `7C`7C defined(hp300) `7C`7C def Vined(sony) `7C`7C !defined(SYSV) X#define NEED_VPRINTF X#endif X X X/* X * define this if your system C library doesn't have the tempnam X * function X */ X#if defined(convex) `7C`7C defined(sony) `7C`7C (!defined(sun) && !defined(u Vltrix) && !defined(SYSV) && !defined(VMS)) `7C`7C defined(ibm032) `7C`7C def Vined(sequent) X#define NEED_TEMPNAM X#endif X `20 X/* strtok function */ X#if defined(sequent) `7C`7C !defined(SYSV) X#define NEED_STRTOK X#endif X X/* strstr function */ X#if defined(MOTIF) X#define NEED_STRSTR X#endif X X/* X * display articles with local time rather than GMT - only works for SYSV X * right now X */ X#define USE_LOCALTIME X#if defined(USE_LOCALTIME) && (defined(SYSV) `7C`7C defined(sun)) X#define REALLY_USE_LOCALTIME X#endif X X/* X * non-display defaults X */ X#ifndef PRINTCOMMAND X#ifndef VMS X#define PRINTCOMMAND`09"enscript" X#else X#define PRINTCOMMAND "PRINT/DELETE" X#endif X#endif X X#ifndef SENDMAIL X#ifndef VMS X#define SENDMAIL "/usr/lib/sendmail -oi -t" X#else X#define SENDMAIL "MAIL " X#endif X#endif X X#define SAVEMODE "normal,headers,onedir" X#define SAVE_DIR_DEFAULT`09ONEDIR_SAVE X#ifndef VMS X#define SAVEDIR "`7E/News" X#define NEWSRCFILE "`7E/.newsrc" X#define SAVENEWSRCFILE "`7E/.oldnewsrc" X#define SIGNATUREFILE "`7E/.signature" X#else X#define SAVEDIR`09 "SYS$SCRATCH:" X#define NEWSRCFILE "SYS$LOGIN:NEWS.RC" X#define SAVENEWSRCFILE "SYS$LOGIN:OLDNEWS.RC" X#define SIGNATUREFILE "SYS$LOGIN:NEWS.SIGNATURE" X#endif X#define TOPLINES`09"10" X#define MINLINES`09"3" X#define MAXLINES`09"8" X#define CANCELCOUNT`09"20" X#define LINELENGTH`09"72" X#define BREAKLENGTH`09"80" X/* RESCAN_TIME is in seconds, default is 300 seconds (5 minutes) */ X#define RESCAN_TIME`09"300" X X#ifndef VMS X#define DEADLETTER "`7E/dead.letter" X#define SAVEPOSTINGS "`7E/Articles" X#define TEMPORARY_DIRECTORY "/tmp" X#else X#define DEADLETTER "SYS$SCRATCH:DEAD.LETTER" X#define SAVEPOSTINGS "SYS$SCRATCH:SAVED.POSTING" X#define TEMPORARY_DIRECTORY "SYS$SCRATCH:" X#endif X X#endif /* CONFIG_H */ $ CALL UNPACK CONFIG.H;1 1964613762 $ create 'f' X X/* X * $Header: /users/ricks/xrn/src/RCS/COPYRIGHT,v 1.5 90/09/29 02:31:12 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X $ CALL UNPACK COPYRIGHT.;1 1316441111 $ create 'f' X#ifndef COPYRIGHT_H X#define COPYRIGHT_H X X/* X * $Header: /users/ricks/xrn/src/RCS/copyright.h,v 1.8 90/09/29 02:27:28 ric Vks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X#if !defined(lint) && !defined(SABER) Xstatic char *copyright = "Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich V and Rick L. Spickelmier."; X#endif X X#endif /* COPYRIGHT_H */ $ CALL UNPACK COPYRIGHT.H;1 1748568838 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /net/opus/mnt/ricks/src/X/xrn/RCS/cur Vsor.c,v 1.13 90/09/29 01:12:38 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * cursor.c: routines for manipulating the cursor and/or text in a text X * window X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include "config.h" X#include "utils.h" X#include "mesg.h" X#include "internals.h" X#include "modes.h" X#include "xrn.h" X#include "cursor.h" X#include "error_hnds.h" X Xvoid XcurrentGroup(mode, tstring, groupName) Xint mode;`09`09`09/* xrn Mode */ Xchar *tstring;`09`09`09/* text string */ Xchar *groupName;`09`09/* string to return group name in */ X/* X * Return the name of the group on the current line. X * Assume there is a group there. X */ X`7B X if ((mode != ALL_MODE) && (mode != ADD_MODE)) `7B X`09if (sscanf(&tstring`5B0`5D, NEWS_GROUP_LINE, groupName) == 1) `7B X`09 return; X`09`7D else `7B X`09 *groupName = '\0'; X`09 return; X`09`7D X `7D else `7B X`09(void) sscanf(&tstring`5B0`5D, "%s", groupName); X `7D X return; X`7D X X Xvoid XcurrentMode(tstring, groupName, mode) Xchar *tstring; Xchar *groupName; Xint *mode; X/* X * Return the status of the group on the current line. X */ X`7B X char status`5B100`5D; X X (void) sscanf(&tstring`5B0`5D, "%s %s", groupName, status); X if (strcmp(status,"unsubscribed") == 0) `7B X`09*mode = UNSUBSCRIBE; X `7D else `7B X`09*mode = SUBSCRIBE; X `7D X return; X`7D X X Xint XmarkStringRead(tstring) Xchar *tstring;`09`09`09/* text string */ X/* X * Mark the article at the current ArticlePosition as read,if it is X * not already marked. Return the article number of the article X * that was marked. This subroutine only marks the text string; X * the article is marked internally as read by calling`20 X * markArticleAsRead(). X */ X`7B X int artNum;`09`09`09/* number of article to be marked */ X X if (tstring`5B0`5D == ' ') `7B X`09tstring`5B0`5D = '+'; X `7D X return atoi(&tstring`5B2`5D); X`7D X X Xvoid XmarkAllString(tstring, left, right, status) Xchar **tstring;`09`09`09/* text string */ Xint left, right;`09`09/* groups to be marked */ Xchar *status;`09`09`09/* "subscribed" or "unsubscribed" */ X`7B X/* X * Mark all groups in the region between the left and right bytes X * of the text array 'tstring' as subscribed or unsubscribed, X * depending on the contents of the string status. X */ X int`09temp, point;`09/* positions used to move through string */ X int i; X `20 X temp = left; X while (temp < right) `7B X`09point = utStrlen(tstring`5Btemp`5D); X`09for (i = 0; i < utStrlen(status); i++) `7B X`09 tstring`5Btemp`5D`5Bpoint-1`5D = status`5ButStrlen(status) - i - 1`5D V; X`09 point--; X`09`7D X`09temp++; X `7D X return; X`7D X X Xvoid XmarkArticles(tstring, first, last, marker) Xchar **tstring;`09`09`09/* text strings */ Xint first, last;`09`09/* boundaries of articles to be marked */ Xchar marker;`09`09`09/* either '+' or ' ' */ X/* X * Mark a group of articles between first and last as read or unread. X * Marks the articles in the text string, and marks them internally. X */ X`7B X long artNum;`09`09/* number of current article to be marked */ X X while (first < last) `7B X`09if (marker == 'S') `7B X`09 tstring`5Bfirst`5D`5B0`5D = '+'; X`09 tstring`5Bfirst`5D`5B1`5D = 'S'; X`09`7D else `7B X`09 tstring`5Bfirst`5D`5B0`5D = marker; X`09`7D X`09artNum = atol(&tstring`5Bfirst`5D`5B2`5D); X`09if (marker == '+' `7C`7C marker == 'S') `7B X`09 markArticleAsRead(artNum); X`09`7D else `7B X`09 markArticleAsUnread(artNum); X`09`7D X`09first++; X `7D X return; X`7D X Xint XsubjectSearch(dir, tstring, position, ttop, expr, file, ques, artNum) Xint dir;`09`09`09/* direction, either FORWARD or BACK */ Xchar **tstring;`09`09`09/* text string (may be changed here) */ Xint *position, ttop;`09`09/* cursor position, position of top of text */ Xchar *expr;`09`09`09/* regular expression to search for */ Xchar **file, **ques;`09`09/* filename and status line for new article */ Xlong *artNum;`09`09`09/* number of new article */ X`7B X#ifdef SYSV_REGEX X extern char *regcmp(); X extern char *regex(); X#else X char *re_comp();`09`09/* regular expression routine */ X#endif X static char *reRet;`09`09/* returned by re_comp/regcmp */ X char *newsubject;`09`09/* subject of current line */ X char *oldString, *newString; /* strings used to build up new text string V */ X char *newLine; X char *newSubjectString; X extern void abortClear(); X extern int abortP(); X X oldString = NIL(char); X X abortClear(); X X if (expr != NIL(char)) `7B X#ifdef SYSV_REGEX X`09if ((reRet = regcmp(expr, NULL)) == NULL) `7B X#else X`09if ((reRet = re_comp(expr)) != NULL) `7B X#endif X`09 /* bad regular expression */ X#ifdef SYSV_REGEX X`09 mesgPane(XRN_SERIOUS, "error in regular expression"); X#else X`09 mesgPane(XRN_SERIOUS, reRet); X#endif X`09 failedSearch(); X`09 return ERROR; X`09`7D X `7D X X if (dir == FORWARD) `7B X`09for (;;) `7B X`09 if (abortP()) `7B X`09`09return ABORT; X`09 `7D X`09 if (tstring`5B*position`5D == NIL(char) `7C`7C X`09`09tstring`5B*position`5D`5B0`5D == '\0') `7B X`09`09if (*position == 0) `7B X X`09`09 /* the string is null, no more articles are left */ X X`09`09 return EXIT; X`09`09`7D X`09`09return NOMATCH; X`09 `7D X`09 *position = *position + 1; X`09 if (tstring`5B*position`5D == NIL(char) `7C`7C X`09`09tstring`5B*position`5D`5B0`5D == '\0') `7B X X`09`09/* reached end of string */ X X`09`09return NOMATCH; X`09 `7D X`09 *artNum = atol(&tstring`5B*position`5D`5B2`5D); X`09 newsubject = getSubject(*artNum); X X#ifdef SYSV_REGEX X`09 if (regex(reRet, newsubject) != NULL) `7B X#else X`09 if (re_exec(newsubject)) `7B X#endif X`09`09/* found a match to the regular expression */ X X`09`09gotoArticle(*artNum); X`09`09if (getArticleText(file, ques) != XRN_OKAY) `7B X X`09`09 /* the matching article was invalid */ X X`09`09 continue; X`09`09`7D X`09`09return MATCH; X`09 `7D X`09`7D X `7D else `7B X`09startSearch(); X`09for (;;) `7B X`09 if (abortP()) `7B X X`09`09/* reset pointers back to where we began, since the */ X`09`09/* search was aborted */ X X`09`09failedSearch(); X`09`09return ABORT; X`09 `7D X`09 if ((*position == 0) && X`09`09(tstring`5B*position`5D == NIL(char) `7C`7C X`09`09 tstring`5B*position`5D`5B0`5D == '\0')) `7B X X`09`09/* no more articles remain, return to Newgroup mode */ X X`09`09return EXIT; X`09 `7D X`09 if (*position != 0) `7B X X`09`09/* we are still within the subject list */ X X`09`09*position = *position - 1; X`09`09*artNum = atol(&tstring`5B*position`5D`5B2`5D); X`09`09newsubject = getSubject(*artNum); X X#ifdef SYSV_REGEX X`09`09if (regex(reRet, newsubject) != NULL) `7B X#else X`09`09if (re_exec(newsubject)) `7B X#endif X`09`09 /* an article matching the regular expression was found */ X X`09`09 gotoArticle(*artNum); X`09`09 if (getArticleText(file, ques) != XRN_OKAY) `7B X X`09`09`09/* article is invalid, remove it from the text string*/ X X`09`09`09continue; X`09`09 `7D X`09`09 return MATCH; X`09`09`7D X`09 `7D else `7B X X`09`09/* must query the news server for articles not shown */ X`09`09/* on the current subject screen */ X X`09`09if ((newLine = getPrevSubject()) == NIL(char)) `7B X`09`09 `20 X`09`09 /* all articles have been exhausted, reset variables */ X`09`09 /* to what they were before the search was started */ X X`09`09 failedSearch(); X`09`09 return NOMATCH; X`09`09`7D X`09`09newLine`5B0`5D = '+'; X`09`09*artNum = atol(&newLine`5B2`5D); X`09`09newsubject = getSubject(*artNum); X#ifdef SYSV_REGEX X`09`09if (regex(reRet, newsubject) != NULL) `7B X#else X`09`09if (re_exec(newsubject)) `7B X#endif X`09`09 /* the new article (subjectline) obtained here */ X`09`09 /* does not need to be checked for validity, since */ X`09`09 /* getPrevSubject() only returns valid articles */ X X`09`09 gotoArticle(*artNum); X`09`09 (void) getArticleText(file, ques); X`09`09 return WINDOWCHANGE; X`09`09`7D X`09`09continue; X`09 `7D X`09`7D X `7D X`7D X X Xint XmoveToArticle(artNum, file, ques) Xlong artNum;`09`09`09/* number of new article */ Xchar **file, **ques;`09`09/* text and status line for new article */ X`7B X fillUpArray(artNum); X X if (checkArticle(artNum) != XRN_OKAY) `7B X`09return NOMATCH; X `7D X X gotoArticle(artNum); X if (getArticleText(file, ques) != XRN_OKAY) `7B X`09return ERROR; X `7D X X return MATCH; X`7D $ CALL UNPACK CURSOR.C;1 574218330 $ create 'f' X#ifndef CURSOR_H X#define CURSOR_H X X/* X * $Header: /users/ricks/xrn/src/RCS/cursor.h,v 1.6 90/09/29 02:27:31 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * cursor.h: functions for manipulating the cursor and/or text in a X * text window X */ X X#define BACK 0 X#define FORWARD 1 X X#define NEWS_GROUP_LINE "%*15c%s" X Xextern void currentGroup(); Xextern void currentMode(); Xextern int markStringRead(); Xextern void markAllString(); Xextern void markArticles(); Xextern void findArticle(); Xextern int subjectSearch(); Xextern int moveToArticle(); X X#endif /* CURSOR_H */ $ CALL UNPACK CURSOR.H;1 259679488 $ create 'f' X X#if !defined(lint) &&!defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /net/opus/mnt/ricks/src/X/xrn/RCS/dia Vlogs.c,v 1.18 90/09/29 01:12:41 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * dialogs.c: create simple moded dialog boxes X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#else X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#else X#ifndef VMS X#include X#else X#include X#endif /* VMS */ X#endif /* MOTIF */ X#ifndef VMS X#include X#else X#include X#endif X#include "xthelper.h" X#include "xmisc.h" X#include "xrn.h" X#include "dialogs.h" X X#ifdef MOTIF XWidget XCreateDialog(parent, title, textField, args, count) XWidget parent; /* parent window */ Xchar *title; /* title of the dialog box */ Xchar *textField;`09 /* default text field */ Xstruct DialogArg *args; /* description of the buttons */ Xunsigned int count; /* number of buttons */ X/* X * create a simple moded dialog box X */ X`7B X Widget popup; X Arg dargs`5B10`5D; X Arg bargs`5B10`5D; X Widget button; X int i, j; X Dimension x, y, width; X XmString labelString; X static XtCallbackRec callbacks`5B`5D = `7B X`09 `7BCBbusyCursor, NULL`7D, X`09 `7BNULL, NULL`7D, X`09 `7BCBunbusyCursor, NULL`7D, X`09 `7BNULL, NULL`7D, X `7D; X X /* override does not get titlebar, transient does */ X `20 X i = 0; X XtSetArg(dargs`5Bi`5D, XtNinput, True); i++; X XtSetArg(dargs`5Bi`5D, XtNallowShellResize, True); i++; X XtSetArg(dargs`5Bi`5D, XmNtextColumns, 40); i++; X labelString = XmStringLtoRCreate(title, XmSTRING_DEFAULT_CHARSET); X X /* create the dialog box */ X if (textField != DIALOG_NOTEXT) `7B X XtSetArg(dargs`5Bi`5D, XmNselectionLabelString, labelString); i++; X`09XtSetArg(dargs`5Bi`5D, XmNresizePolicy, XmRESIZE_GROW);i++; X`09XtSetArg(dargs`5Bi`5D, XmNwidth, 200);i++; X`09popup = (Widget) XmCreatePromptDialog(parent,title,dargs,i); X`09XtSetArg(dargs`5B0`5D, XmNcolumns, 25); X `09XtSetValues(XmSelectionBoxGetChild(popup, XmDIALOG_TEXT), dargs, 1); X`09 X /* Create the buttons */ X /* Button 1: */ X`09 X`09callbacks`5B1`5D.callback = args`5B0`5D.handler; X`09callbacks`5B1`5D.closure = args`5B0`5D.data; X X labelString = XmStringLtoRCreate(args`5B0`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09button = (Widget) XmSelectionBoxGetChild(popup,XmDIALOG_OK_BUTTON); X`09j = 0; X`09XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09XtSetValues(button, bargs, j); X`09XmStringFree(labelString); X X /* Button 2: */ X`09 X`09if (count < 2) `7B X`09 XtUnmanageChild(XmSelectionBoxGetChild(popup, X`09`09`09`09XmDIALOG_CANCEL_BUTTON)); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B1`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B1`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B1`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmSelectionBoxGetChild(popup, X`09`09`09`09`09`09`09XmDIALOG_CANCEL_BUTTON); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09 XtSetValues(button, bargs, j); X`09 XmStringFree(labelString); X`09`7D X /* Button 3: */ X`09 X`09if (count < 3) `7B X`09 XtUnmanageChild(XmSelectionBoxGetChild(popup, X`09`09`09`09XmDIALOG_HELP_BUTTON)); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B2`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B2`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B2`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmSelectionBoxGetChild(popup, X`09`09`09`09`09`09`09XmDIALOG_HELP_BUTTON); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09 XtSetValues(button, bargs, j); X`09 XmStringFree(labelString); X`09`7D X X /* Button 4: */ X`09 X`09if (count > 3) `7B X`09 callbacks`5B1`5D.callback = args`5B3`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B3`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B3`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmSelectionBoxGetChild(popup, X`09`09`09`09`09XmDIALOG_APPLY_BUTTON); X`09 XtManageChild(button); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09 XtSetValues(button, bargs, j); X`09 XmStringFree(labelString); X`09`7D X X /* Button 5: */ X X`09if (count > 4) `7B X`09 callbacks`5B1`5D.callback = args`5B4`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B4`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B4`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmSelectionBoxGetChild(popup, X`09`09`09`09`09XmDIALOG_APPLY_BUTTON); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNx, &x); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNy, &y); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNwidth, &width); j++; X`09 XtGetValues(button, bargs, j); X`09 x = x + width + 10; X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNx, x); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNy, y); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X`09 button = (Widget) XmCreatePushButton(popup,`20 X`09`09`09`09args`5B4`5D.buttonName, bargs, j); X`09 XtManageChild(button); X`09 XmStringFree(labelString); X`09`7D X X `7D else `7B`09/* No text field */ X X XtSetArg(dargs`5Bi`5D, XmNmessageString, labelString); i++; X`09popup = (Widget) XmCreateQuestionDialog(parent,title,dargs,i); X`09 X /* Create the buttons */ X /* Button 1: */ X`09 X`09callbacks`5B1`5D.callback = args`5B0`5D.handler; X`09callbacks`5B1`5D.closure = args`5B0`5D.data; X X labelString = XmStringLtoRCreate(args`5B0`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09button = (Widget) XmMessageBoxGetChild(popup,XmDIALOG_OK_BUTTON); X`09j = 0; X`09XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09XtSetValues(button, bargs, j); X`09XmStringFree(labelString); X X /* Button 2: */ X`09 X`09if (count < 2) `7B X`09 XtUnmanageChild(XmMessageBoxGetChild(popup, X`09`09`09`09XmDIALOG_CANCEL_BUTTON)); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B1`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B1`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B1`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmMessageBoxGetChild(popup, X`09`09`09`09`09XmDIALOG_CANCEL_BUTTON); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09 XtSetValues(button, bargs, j); X`09 XmStringFree(labelString); X`09`7D X /* Button 3: */ X`09 X`09if (count < 3) `7B X`09 XtUnmanageChild(XmMessageBoxGetChild(popup, X`09`09`09`09XmDIALOG_HELP_BUTTON)); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B2`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B2`5D.data; X X`09 labelString = XmStringLtoRCreate(args`5B2`5D.buttonName, X`09`09`09`09`09 XmSTRING_DEFAULT_CHARSET); X`09 button = (Widget) XmMessageBoxGetChild(popup,XmDIALOG_HELP_BUTTON); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, XmNlabelString, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, XmNactivateCallback, callbacks);j++; X X`09 XtSetValues(button, bargs, j); X`09 XmStringFree(labelString); X`09`7D X `7D X XtRealizeWidget(popup); X X return(popup); X`7D X#else /* not MOTIF */ XWidget XCreateDialog(parent, title, textField, args, count) XWidget parent; /* parent window */ Xchar *title; /* title of the dialog box */ Xchar *textField;`09 /* default text field */ Xstruct DialogArg *args; /* description of the buttons */ Xunsigned int count; /* number of buttons */ X/* X * create a simple moded dialog box X */ X`7B X DialogWidget popup; X Widget text; X Widget button4; X Widget button5; X Widget defaultButton; X Arg dargs`5B30`5D; X Arg bargs`5B10`5D; X int i, j; X Dimension x, y, width; X DwtCompString labelString; X static XtCallbackRec callbacks`5B`5D = `7B X`09 `7BbusyCursor, NULL`7D, X`09 `7BNULL, NULL`7D, X`09 `7BunbusyCursor, NULL`7D, X`09 `7BNULL, NULL`7D, X `7D; X X /* override does not get titlebar, transient does */ X `20 X i = 0; X XtSetArg(dargs`5Bi`5D, DwtNinput, True); i++; X XtSetArg(dargs`5Bi`5D, XtNallowShellResize, True); i++; X XtSetArg(dargs`5Bi`5D, DwtNchildOverlap, False); i++; X XtSetArg(dargs`5Bi`5D, DwtNunits, DwtFontUnits); i++; X labelString = DwtLatin1String(title); X X /* create the dialog box */ X if (textField != DIALOG_NOTEXT) `7B X XtSetArg(dargs`5Bi`5D, DwtNlabel, labelString); i++; X`09popup = (DialogWidget) DwtCautionBoxCreate((Widget)parent,(char *)title, X`09`09`09dargs, i); X /* create the SText */ X`20 X`09i = 0; X`09XtSetArg(dargs`5Bi`5D, DwtNeditable, TRUE); i++; X`09XtSetArg(dargs`5Bi`5D, DwtNx, 40);i++; X`09XtSetArg(dargs`5Bi`5D, DwtNy, 100);i++; X`09XtSetArg(dargs`5Bi`5D, DwtNrows, 1);i++; X`09XtSetArg(dargs`5Bi`5D, DwtNcols, 40);i++; X`09XtSetArg(dargs`5Bi`5D, DwtNresizeWidth, FALSE);i++; X X`09text = DwtSTextCreate(popup, "text", dargs, i); X`09XtManageChild(text); X`09 X`09i = 0; X`09XtSetArg(dargs`5Bi`5D, DwtNuserData, text); i++; X`09XtSetValues(popup, dargs, i); X X /* Create the buttons */ X /* Button 1: */ X`09 X`09callbacks`5B1`5D.callback = args`5B0`5D.handler; X`09callbacks`5B1`5D.closure = args`5B0`5D.data; X X labelString = DwtLatin1String(args`5B0`5D.buttonName); X`09j = 0; X`09XtSetArg(dargs`5Bj`5D, DwtNyesLabel, labelString); j++; X`09XtSetArg(dargs`5Bj`5D, DwtNyesCallback, callbacks);j++; X X`09XtSetValues(popup, dargs, j); X`09XtFree(labelString); X X /* Button 2: */ X`09 X`09if (count < 2) `7B X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtNoButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 XtUnmanageChild(defaultButton); X`09`7D else `7B X`09 X`09 callbacks`5B1`5D.callback = args`5B1`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B1`5D.data; X X`09 labelString = DwtLatin1String(args`5B1`5D.buttonName); X`09 j = 0; X`09 XtSetArg(dargs`5Bj`5D, DwtNnoLabel, labelString); j++; X`09 XtSetArg(dargs`5Bj`5D, DwtNnoCallback, callbacks);j++; X X`09 XtSetValues(popup, dargs, j); X`09 XtFree(labelString); X`09`7D X /* Button 3: */ X`09 X`09if (count < 3) `7B X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtCancelButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 XtUnmanageChild(defaultButton); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B2`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B2`5D.data; X X`09 labelString = DwtLatin1String(args`5B2`5D.buttonName); X`09 j = 0; X`09 XtSetArg(dargs`5Bj`5D, DwtNcancelLabel, labelString); j++; X`09 XtSetArg(dargs`5Bj`5D, DwtNcancelCallback, callbacks);j++; X X`09 XtSetValues(popup, dargs, j); X`09 XtFree(labelString); X`09`7D X X /* Button 4: */ X X`09if (count > 3) `7B X`09 callbacks`5B1`5D.callback = args`5B3`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B3`5D.data; X X`09 labelString = DwtLatin1String(args`5B3`5D.buttonName); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtCancelButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, &x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, &y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNwidth, &width); j++; X`09 XtGetValues(defaultButton, bargs, j); X`09 x = x + width + 10; X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNlabel, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNactivateCallback, callbacks);j++; X`09 button4 = DwtPushButtonGadgetCreate(popup,args`5B4`5D.buttonName, X`09`09bargs, j); X`09 XtManageChild(button4); X`09 XtFree(labelString); X`09`7D X X /* Button 5: */ X X`09if (count > 4) `7B X`09 callbacks`5B1`5D.callback = args`5B4`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B4`5D.data; X X`09 labelString = DwtLatin1String(args`5B4`5D.buttonName); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, &x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, &y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNwidth, &width); j++; X`09 XtGetValues(button4, bargs, j); X`09 x = x + width + 10; X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNlabel, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNactivateCallback, callbacks);j++; X`09 button5 = DwtPushButtonGadgetCreate(popup,args`5B4`5D.buttonName, X`09`09bargs, j); X`09 XtManageChild(button5); X`09 XtFree(labelString); X`09`7D X X `7D else `7B`09/* No text field */ X X XtSetArg(dargs`5Bi`5D, DwtNlabel, labelString); i++; X`09popup = (DialogWidget) DwtCautionBoxCreate(parent,title,dargs,i); X`09 X /* Create the buttons */ X /* Button 1: */ X`09 X`09callbacks`5B1`5D.callback = args`5B0`5D.handler; X`09callbacks`5B1`5D.closure = args`5B0`5D.data; X X labelString = DwtLatin1String(args`5B0`5D.buttonName); X`09j = 0; X`09XtSetArg(dargs`5Bj`5D, DwtNyesLabel, labelString); j++; X`09XtSetArg(dargs`5Bj`5D, DwtNyesCallback, callbacks);j++; X X`09XtSetValues(popup, dargs, j); X`09XtFree(labelString); X X /* Button 2: */ X`09 X`09if (count < 2) `7B X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtNoButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 XtUnmanageChild(defaultButton); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B1`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B1`5D.data; X X`09 labelString = DwtLatin1String(args`5B1`5D.buttonName); X`09 j = 0; X`09 XtSetArg(dargs`5Bj`5D, DwtNnoLabel, labelString); j++; X`09 XtSetArg(dargs`5Bj`5D, DwtNnoCallback, callbacks);j++; X X`09 XtSetValues(popup, dargs, j); X`09 XtFree(labelString); X`09`7D X /* Button 3: */ X`09 X`09if (count < 3) `7B X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtCancelButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 XtUnmanageChild(defaultButton); X`09`7D else `7B X`09 callbacks`5B1`5D.callback = args`5B2`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B2`5D.data; X X`09 labelString = DwtLatin1String(args`5B2`5D.buttonName); X`09 j = 0; X`09 XtSetArg(dargs`5Bj`5D, DwtNcancelLabel, labelString); j++; X`09 XtSetArg(dargs`5Bj`5D, DwtNcancelCallback, callbacks);j++; X X`09 XtSetValues(popup, dargs, j); X`09 XtFree(labelString); X`09`7D X X /* Button 4: */ X X`09if (count > 3) `7B X`09 callbacks`5B1`5D.callback = args`5B3`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B3`5D.data; X X`09 labelString = DwtLatin1String(args`5B3`5D.buttonName); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtCancelButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultButton, &defaultButton);j++; X`09 XtGetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNdefaultPushbutton, DwtYesButton);j++; X`09 XtSetValues(popup, bargs, j); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, &x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, &y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNwidth, &width); j++; X`09 XtGetValues(defaultButton, bargs, j); X`09 x = x + width + 10; X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNlabel, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNactivateCallback, callbacks);j++; X`09 button4 = DwtPushButtonGadgetCreate(popup,args`5B4`5D.buttonName, X`09`09bargs, j); X`09 XtManageChild(button4); X`09 XtFree(labelString); X`09`7D X X /* Button 5: */ X X`09if (count > 4) `7B X`09 callbacks`5B1`5D.callback = args`5B4`5D.handler; X`09 callbacks`5B1`5D.closure = args`5B4`5D.data; X X`09 labelString = DwtLatin1String(args`5B4`5D.buttonName); X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, &x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, &y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNwidth, &width); j++; X`09 XtGetValues(button4, bargs, j); X`09 x = x + width + 10; X`09 j = 0; X`09 XtSetArg(bargs`5Bj`5D, DwtNx, x); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNy, y); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNlabel, labelString); j++; X`09 XtSetArg(bargs`5Bj`5D, DwtNactivateCallback, callbacks);j++; X`09 button5 = DwtPushButtonGadgetCreate(popup,args`5B4`5D.buttonName, X`09`09bargs, j); X`09 XtManageChild(button5); X`09 XtFree(labelString); X`09`7D X `7D X XtRealizeWidget(popup); X X return((Widget)popup); X`7D X#endif /* MOTIF */ X X#ifdef DECFOCUSPATCH Xvoid XFocusPopUp(popup, data, event) XWidget popup; Xcaddr_t data; XXEvent *event; X`7B X if (event->type == MapNotify) `7B X`09XSetInputFocus(XtDisplay(popup), XtWindow(popup), X`09`09 RevertToPointerRoot, CurrentTime); X`09XtRemoveEventHandler(popup, XtAllEvents, True, FocusPopUp, 0); X `7D X return; X`7D X#endif X Xvoid XPopUpDialog(popup) XWidget popup; X`7B X xthCenterWidgetOverCursor(popup); X XtManageChild(popup); X XtPopup(XtParent(popup), XtGrabExclusive); X#ifdef DECFOCUSPATCH X XtAddEventHandler(popup, StructureNotifyMask, False, FocusPopUp, 0); X#endif X return; X`7D X X Xvoid XPopDownDialog(dialog) XWidget dialog; X/* X * pop down the dialog (do not destroy, it will be used again) X */ X`7B X XtUnmanageChild(dialog); X XtPopdown(XtParent(dialog)); X return; X`7D X X Xchar * XGetDialogValue(popup) XWidget popup; X`7B X#ifdef MOTIF X return XmTextGetString(XmSelectionBoxGetChild(popup, XmDIALOG_TEXT)); X#else X Arg`09args`5B4`5D; X Widget w; X X XtSetArg(args`5B0`5D, DwtNuserData, &w); X XtGetValues(popup, args, 1); X X return DwtSTextGetString(w); X#endif X`7D X X X/* X * simple confirmation box X */ X Xstatic int retVal; X X/* ARGSUSED */ Xstatic void XcbHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X retVal = (int) client_data; X return; X`7D X X Xstatic XtCallbackRec ConfirmOkCallback`5B`5D = `7B X`09`7BcbHandler, (caddr_t) XRN_CB_CONTINUE`7D, X`09`7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec ConfirmCancelCallback`5B`5D = `7B X`09`7BcbHandler, (caddr_t) XRN_CB_ABORT`7D, X`09`7BNULL, NULL`7D, X`7D; X#ifdef MOTIF Xint XConfirmationBox(parent, message) XWidget parent; Xchar *message; X/* X * pop up a confirmation box and return either 'XRN_CB_ABORT' or 'XRN_CB_CON VTINUE' X */ X`7B X XEvent ev; X XtInputMask mask; X Widget widget; X Arg`09 args`5B4`5D; X XmString`09labelString; X retVal = -1; X X labelString = XmStringLtoRCreate(message, XmSTRING_DEFAULT_CHARSET); X XtSetArg(args`5B0`5D, XmNmessageString, labelString); X XtSetArg(args`5B1`5D, XmNokCallback, ConfirmOkCallback); X XtSetArg(args`5B2`5D, XmNcancelCallback, ConfirmCancelCallback); X XtSetArg(args`5B3`5D, XmNdefaultButtonType, XmDIALOG_OK_BUTTON); X widget = (Widget) XmCreateQuestionDialog(parent,"confirmBox", X`09`09`09`09args, XtNumber(args)); X XtUnmanageChild(XmMessageBoxGetChild(widget,XmDIALOG_HELP_BUTTON)); X#else /* not MOTIF */ Xint XConfirmationBox(parent, message) XWidget parent; Xchar *message; X/* X * pop up a confirmation box and return either 'XRN_CB_ABORT' or 'XRN_CB_CON VTINUE' X */ X`7B X XEvent ev; X XtInputMask mask; X Widget widget; X Arg`09 args`5B6`5D; X DwtCompString labelString; X X retVal = -1; X X labelString = DwtLatin1String(message); X XtSetArg(args`5B0`5D, DwtNlabel, labelString); X XtSetArg(args`5B1`5D, DwtNyesCallback, ConfirmOkCallback); X XtSetArg(args`5B2`5D, DwtNnoCallback, ConfirmCancelCallback); X XtSetArg(args`5B3`5D, DwtNcancelCallback, ConfirmCancelCallback); X XtSetArg(args`5B4`5D, DwtNdefaultPushbutton, DwtYesButton); X XtSetArg(args`5B5`5D, DwtNstyle, DwtModeless); X widget = (Widget) DwtCautionBoxCreate(parent,"confirmBox", X`09`09`09args, XtNumber(args)); X#endif /* MOTIF */ X XtManageChild(widget); X XtFree(labelString); X PopUpDialog(widget); X X for(;;) `7B X`09XtNextEvent(&ev); X`09(void) XtDispatchEvent(&ev); X`09if (retVal != -1) `7B X`09 PopDownDialog(widget); X`09 XtDestroyWidget(widget); X`09 while ((mask = XtPending()) != 0) `7B X`09`09if (mask == XtIMTimer) `7B X`09`09 XtProcessEvent(XtIMAll); X`09`09`7D else `7B X`09`09 XtNextEvent(&ev); X`09`09 XtDispatchEvent(&ev); X`09`09`7D X`09 `7D X`09 return(retVal); X`09`7D X `7D X`7D $ CALL UNPACK DIALOGS.C;1 1414778733 $ create 'f' X#ifndef DIALOGS_H X#define DIALOGS_H X X/* X * $Header: /users/ricks/xrn/src/RCS/dialogs.h,v 1.6 90/09/29 02:27:37 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X#ifdef MOTIF X#include X#else X#ifndef VMS X#include X#else X#include X#endif X#endif X X/* X * dialogs.h: create simple moded dialog boxes X * X */ X X X/* description of a button */ Xstruct DialogArg `7B X char *buttonName; X void (*handler)(); X caddr_t data; X`7D; X X#define DIALOG_TEXT "" X#define DIALOG_NOTEXT (char *)0 X Xextern Widget CreateDialog(/* Widget parent, char *title, char *text, struct V DialogArgs *args, int count */); X Xextern void PopUpDialog(/* Widget dialog */); Xextern void PopDownDialog(/* Widget dialog */); X Xextern char *GetDialogValue(/* Widget dialog */); X Xextern int ConfirmationBox(/* Widget parent, char *message */); X X#define XRN_CB_ABORT 0 X#define XRN_CB_CONTINUE 1 X X#endif /* DIALOGS_H */ X $ CALL UNPACK DIALOGS.H;1 997305895 $ create 'f' X#define dxrn_width 32 X#define dxrn_height 40 Xstatic char dxrn_bits`5B`5D = `7B X 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xa0, 0x61, 0x44, 0x27, 0xc2, X 0xa1, 0x28, 0x69, 0xa2, 0x21, 0x11, 0xa9, 0xc2, 0x21, 0x11, 0x27, 0xa3, X 0xa1, 0x28, 0x29, 0xc2, 0x61, 0x44, 0x29, 0xa2, 0x01, 0x00, 0x00, 0xc0, X 0x01, 0x00, 0x00, 0xa0, 0xfd, 0xff, 0xff, 0xcf, 0x05, 0x00, 0x00, 0xa8, X 0x85, 0xb9, 0x52, 0xc8, 0x85, 0xaa, 0x22, 0xa8, 0x85, 0xa9, 0x26, 0xc8, X 0x05, 0x00, 0x00, 0xa8, 0x05, 0xb5, 0x32, 0xc8, 0x05, 0x97, 0x12, 0xa8, X 0x05, 0xb5, 0x1b, 0xc8, 0x05, 0x00, 0x00, 0xa8, 0xf5, 0xff, 0xff, 0xcb, X 0x05, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0xc8, 0xc5, 0xf8, 0x97, 0xa9, X 0x35, 0x0b, 0xf4, 0xca, 0x05, 0x08, 0x04, 0xa8, 0x45, 0x98, 0xb4, 0xcb, X 0xb5, 0x0b, 0x04, 0xa8, 0x05, 0x88, 0xc4, 0xcb, 0xb5, 0x7b, 0x74, 0xaa, X 0xc5, 0x08, 0x04, 0xc8, 0x05, 0xf8, 0xb7, 0xab, 0xf5, 0x03, 0x60, 0xc8, X 0x85, 0xb8, 0x07, 0xa8, 0x05, 0x00, 0x00, 0xc8, 0xfd, 0xff, 0xff, 0xaf, X 0x01, 0x00, 0x00, 0xc0, 0xab, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0xd5, X 0xff, 0xff, 0xff, 0xff`7D; $ CALL UNPACK DXRN.XBM;1 456075758 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/error_hnds.c V,v 1.12 90/09/29 01:12:43 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * error_handlers.c: routines for error/signal handling X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include "config.h" X#include "utils.h" X#include X#ifndef VMS X#include X#else X#include X#endif X#include X#include "dialogs.h" X#include "xmisc.h" X#include "xthelper.h" X#include "internals.h" X#include "xrn.h" X#include "mesg.h" X#include "error_hnds.h" X#include "resources.h" X X/* X * error handlers - major purpose is to close down 'rn' cleanly X */ X XBoolean allowErrors = False; X X/*ARGSUSED*/ Xstatic int XxrnXIOError(display) XDisplay *display; X`7B X XRNState &= `7EXRN_X_UP; X sprintf(error_buffer, "XIO Error: %s", errmsg(errno)); X ehErrorExitXRN(error_buffer); X`7D X X X/*ARGSUSED*/ Xstatic int XxrnXError(display, event) XDisplay *display; XXErrorEvent *event; X`7B X char buffer`5B1024`5D; X X#ifdef ERRORBUG X`09if (event->request_code == 4) `09`09/* destroy window errors */ X`09return;`09`09`09`09`09/* Bug workaround */ X#endif X X if (event->request_code == 42) return;`09/* Ignore 'set input focus' err Vs */ X if (allowErrors) return; X XGetErrorText(display, event->error_code, buffer, sizeof(buffer)); X (void) fprintf(stderr, "xrn: X Error: %s\n", buffer); X (void) fprintf(stderr, " serial number: %d\n", event->serial); X (void) fprintf(stderr, " error code: %d\n", (int) event->error_code) V; X (void) fprintf(stderr, " request code: %d\n", (int) event->request_c Vode); X (void) fprintf(stderr, " minor code: %d\n", (int) event->minor_code) V; X (void) fprintf(stderr, " resource id: %d\n", (int) event->resourceid) V; X XRNState &= `7EXRN_X_UP; X ehErrorExitXRN("X Error"); X`7D X X/*ARGSUSED*/ Xstatic int XxrnXtError(errorMessage) XString errorMessage; X`7B X#define XTERRORINTRO "X Toolkit Error: " X char buffer`5B80`5D; X if (allowErrors) return; X X strcpy(buffer, XTERRORINTRO); X strncat(buffer, errorMessage, sizeof(buffer) - sizeof(XTERRORINTRO)); X (void) fprintf(stderr, "xrn: %s\n", buffer); X XRNState &= `7EXRN_X_UP; X ehErrorExitXRN(buffer); X#undef XTERRORINTRO X`7D X Xvoid XehInstallErrorHandlers() X`7B X if (! app_resources.dumpCore) `7B X`09XtSetErrorHandler(xrnXtError); X`09XSetErrorHandler(xrnXError); X`09XSetIOErrorHandler(xrnXIOError); X `7D X return; X`7D X X Xstatic void Xsig_catcher(signo) Xint signo; X`7B X char buffer`5B80`5D; X `20 X /* allow HUP's and INT's to do a clean exit */ X if ((signo == SIGHUP) `7C`7C (signo == SIGINT)) `7B X`09ehCleanExitXRN(); X `7D X X (void) sprintf(buffer, "Caught signal (%d), cleaned up .newsrc and remov Ved temp files", signo); X X (void) signal(signo, SIG_DFL); X ehSignalExitXRN(buffer); X (void) kill(getpid(), signo); X`7D X X Xvoid XehInstallSignalHandlers() X`7B X int i; X X if (! app_resources.dumpCore) `7B X`09for (i = 1; i <= SIGTERM; i++) `7B X`09 switch(i) `7B X#ifdef SIGSTOP X`09 case SIGSTOP: X#endif X#ifdef SIGTSTP X`09 case SIGTSTP: X#endif X#ifdef SIGCONT X`09 case SIGCONT: X#endif X`09`09break; X X`09 case SIGPIPE: X`09`09(void) signal(i, SIG_IGN); X`09`09break; X X`09 default: X`09`09(void) signal(i, (SIG_PF0) sig_catcher); X`09`09break; X`09 `7D X`09`7D X `7D X return; X`7D X X Xstatic int retry; Xstatic int die = 0; X Xstatic void XmyAbort() X`7B X die = 1; X return; X`7D `20 X X Xstatic void XmyExit() X`7B X#ifdef VMS X exit(1); X#else X exit(-1); X#endif X`7D X X Xstatic void XRetry() X`7B X retry = 1; X return; X`7D X Xstatic void XdeathNotifier(message) Xchar *message; X`7B X XEvent ev; X X static struct DialogArg args`5B`5D = `7B X`09`7B"abort", myAbort, (caddr_t) -1`7D, X`09`7B"exit", myExit, (caddr_t) -1`7D, X `7D; X X die = 0; X `20 X if ((XRNState & XRN_X_UP) != XRN_X_UP) `7B X`09(void) fprintf(stderr, "xrn: %s\n", message); X`09return; X `7D X X /* XXX unmap icon */ X XtMapWidget(TopLevel); X PopUpDialog(CreateDialog(TopLevel, message, DIALOG_NOTEXT, args, XtNumbe Vr(args))); X X while (!die) `7B X`09XtNextEvent(&ev); X`09XtDispatchEvent(&ev); X `7D X X return; X`7D Xstatic int XretryNotifier(message) Xchar *message; X`7B X XEvent ev; X Widget dialog; X `20 X static struct DialogArg args`5B`5D = `7B X`09`7B"exit", myAbort, (caddr_t) -1`7D, X`09`7B"retry", Retry, (caddr_t) -1`7D, X `7D; X X die = retry = 0; X `20 X if ((XRNState & XRN_X_UP) != XRN_X_UP) `7B X`09(void) fprintf(stderr, "xrn: %s\n", message); X`09return 0; X `7D X X /* XXX unmap icon */ X XtMapWidget(TopLevel); X dialog = CreateDialog(TopLevel, message, DIALOG_NOTEXT, args, X`09`09`09 XtNumber(args)); X PopUpDialog(dialog); X X while (!retry && !die) `7B X`09XtNextEvent(&ev); X`09XtDispatchEvent(&ev); X `7D X X PopDownDialog(dialog); X `20 X return retry; X`7D X Xstatic Widget warnWidget = (Widget) NULL; Xstatic void unmapWarn() X`7B X PopDownDialog(warnWidget); X XtDestroyWidget(warnWidget); X warnWidget = (Widget) NULL; X`7D Xvoid Xwarning(message) Xchar *message; X`7B X XEvent ev; X X static struct DialogArg args`5B`5D = `7B X`09`7B"OK", unmapWarn, (caddr_t) -1`7D, X `7D; X X if ((XRNState & XRN_X_UP) != XRN_X_UP) `7B X`09(void) fprintf(stderr, "%s\n", message); X`09return; X `7D X X /* XXX unmap icon */ X XtMapWidget(TopLevel); X if (warnWidget != (Widget) NULL) X`09return; X PopUpDialog(warnWidget = X CreateDialog(TopLevel, message, DIALOG_NOTEXT, args, XtNumber(args)) V); X X return; X`7D X X X#define XRN_NORMAL_EXIT_BUT_NO_UPDATE 2 X#define XRN_NORMAL_EXIT 1 X#define XRN_ERROR_EXIT 0 X#define XRN_SIGNAL_EXIT -1 X `20 Xstatic void XexitXRN(status) Xint status; X`7B X static int beenHere = 0; X X /* X * immediate exit, exitXRN was called as a result of something in X * itself X */`20 X if (beenHere == 1) `7B X`09exit(-1); X `7D X `20 X beenHere = 1; X X if ((XRNState & XRN_NEWS_UP) == XRN_NEWS_UP) `7B X`09/* XXX is this really needed? does free files... */ X`09releaseNewsgroupResources(); X X#ifdef XRN_PREFETCH `20 X`09/* unlink the first article of the prefetched group */ X`09freePrefetchedGroupArticle(); X#endif /* XRN_PREFETCH */ X`09if (status != XRN_NORMAL_EXIT_BUT_NO_UPDATE) `7B X`09 if (!updatenewsrc()) `7B X`09`09fprintf(stderr, "xrn: .newsrc file update failed\n"); X`09 `7D X`09`7D X `7D X X /* clean up the lock */ X removeLock(); X X return; X`7D X X Xvoid XehNoUpdateExitXRN() X`7B X exitXRN(XRN_NORMAL_EXIT_BUT_NO_UPDATE); X exit(0); X`7D X X Xvoid XehCleanExitXRN() X`7B X exitXRN(XRN_NORMAL_EXIT); X exit(0); X`7D X X Xvoid XehErrorExitXRN(message) Xchar *message; X`7B X exitXRN(XRN_ERROR_EXIT); X deathNotifier(message); X exit(-1); X`7D X X Xint XehErrorRetryXRN(message, save) Xchar *message; XBoolean save; X`7B X int retryFlag; X `20 X retryFlag = retryNotifier(message); X X if (!retryFlag && save) `7B X`09exitXRN(XRN_ERROR_EXIT); X`09exit(-1); X `7D X `20 X return retryFlag; X`7D X `20 Xvoid XehSignalExitXRN(message) Xchar *message; X`7B X exitXRN(XRN_SIGNAL_EXIT); X deathNotifier(message); X return; X`7D `20 $ CALL UNPACK ERROR_HNDS.C;1 511356449 $ create 'f' X#ifndef ERROR_HANDLERS_H X#define ERROR_HANDLERS_H X X/* X * $Header: /users/ricks/xrn/src/RCS/error_hnds.h,v 1.8 90/09/29 01:10:27 ri Vcks Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * error_handlers.h: routines for error/signal handling X * X */ X Xextern void warning(/* char *message */); Xextern void ehErrorExitXRN(/* char *message */); Xextern void ehSignalExitXRN(/* char *message */); Xextern void ehCleanExitXRN(); Xextern void ehNoUpdateExitXRN(); X X/* install the X and Xtoolkit error handlers */ Xextern void ehInstallErrorHandlers(); X X/* install the signal handlers */ Xextern void ehInstallSignalHandlers(); X X#ifndef VMS Xextern int errno, sys_nerr; Xextern char *sys_errlist`5B`5D; X#else X#include X#include X#endif X X#define errmsg(a) ((a < sys_nerr) ? sys_errlist`5Ba`5D : "unknown error") X X#endif /* ERROR_HANDLERS_H */ $ CALL UNPACK ERROR_HNDS.H;1 1364072152 $ create 'f' X XWe would like to the thank the following people for sending us bug Xfixes, porting to new OS's, and new features (hopefully we haven't Xleft out too many people): X X Salvador Pinto Abreu`09 X Jeff Anton`09`09`09 X Frederick M. Avolio`09`09 X Glenn T. Barry`09`09 X John Brezak`09`09`09 X Mark Costlow`09`09 X Ian Darwin`09`09`09 X Phil Dykstra`09`09 X Greg Earle`09`09`09 X Haavard Eidnes`09`09 X David Elliott`09`09 X Marc Evans`09`09`09 X Jim Graham`09`09`09 X Dan R. Greening`09`09 X Dirk Grunwald`09`09 X Mark Hastings`09`09 X Per Hedeland`09`09 X Kevin Herbert`09`09 X P. Allen Jensen`09`09 X JQ Johnson`09`09`09 X Casey Leedom`09`09 X Andy Linton`09`09`09 X Steve Losen`09`09`09 X Sean Kamath`09`09`09 X Jonathan I. Kamens`09`09 X Phil Karlton`09`09 X Mark J. Kilgard`09`09<@rice.edu:mjk@uncle-bens.rice.edu> X Greg McNutt`09`09`09 X Matthew Merzbacher`09`09 X Keith Moore`09`09`09 X Rick Murphy`09`09`09 X Jacob M. Parnas`09`09 X Julian Perry`09`09 X Kurt Pires`09`09`09 X Ken Raeburn`09`09`09 X Paul Raveling`09`09 X Chris P. Ross`09`09 X Rich Simoni`09`09`09 X Andreas Stolcke`09`09 X Ken Stone`09`09`09 X Marcin Skubiszewski`09`09 X Matt Thomas`09`09`09 X Michael Toy`09`09`09 X Jeff Wallace`09`09 X Andrew Wason`09`09 X Bill Webb`09`09`09 X Terry Weissman`09`09 X Drew Whitehouse`09`09 X Greg Wohletz`09`09 X Mike Yang`09`09`09 X $ CALL UNPACK FIXERS.;1 1367289969 $ create 'f' X#define bob_width 60 X#define bob_height 60 Xstatic short bob_bits`5B`5D = `7B X 0xf000, 0x0000, 0x0000, 0x0000, X 0xbc00, 0x0003, 0xfc00, 0x0000, X 0x7e00, 0x0003, 0x8e00, 0x0001, X 0xff00, 0x9216, 0xe708, 0x0007, X 0xff00, 0x9947, 0xff84, 0x0007, X 0xcf00, 0x491f, 0xff72, 0x0007, X 0x1e00, 0x003f, 0xfe80, 0x0007, X 0x1e00, 0x0000, 0xfe00, 0x0001, X 0xfc00, 0x03e0, 0xf83e, 0x0000, X 0xf000, 0x0410, 0x1041, 0x0000, X 0xe000, 0x8808, 0x0880, 0x0000, X 0x7000, 0x0008, 0x3080, 0x0000, X 0x3000, 0x000c, 0x7180, 0x0000, X 0x3000, 0x0004, 0x6100, 0x0000, X 0x3000, 0x0004, 0x6100, 0x0000, X 0x3000, 0x8e04, 0x6103, 0x0000, X 0x3000, 0x8a04, 0x6102, 0x0000, X 0x7000, 0x8e04, 0x6103, 0x0000, X 0x7000, 0x0004, 0x6100, 0x0000, X 0x3000, 0x0004, 0x6100, 0x0000, X 0x3000, 0x0004, 0x7900, 0x0000, X 0xf000, 0x0009, 0xfc80, 0x0002, X 0xf200, 0x0013, 0xf040, 0x0001, X 0xf400, 0xf9e1, 0x003c, 0x0000, X 0x1900, 0xfe40, 0xe003, 0x0002, X 0x0200, 0xff20, 0x8007, 0x0001, X 0x1c00, 0xff00, 0x0007, 0x0004, X 0x0100, 0xff00, 0xe007, 0x0003, X 0x1e00, 0xff00, 0x0007, 0x0000, X 0x0000, 0xff00, 0x2007, 0x0004, X 0x1f00, 0xfe00, 0xc003, 0x0003, X 0x1000, 0xf800, 0x0000, 0x0000, X 0x0800, 0x0000, 0x6000, 0x0000, X 0x1000, 0x0000, 0xc000, 0x0000, X 0x0f00, 0x0000, 0x0000, 0x0003, X 0x2000, 0x9000, 0x3001, 0x0000, X 0x5000, 0xfe00, 0x7003, 0x0000, X 0xce00, 0x2800, 0xc400, 0x0000, X 0x2000, 0x0003, 0x9800, 0x0001, X 0x9800, 0x0004, 0x3200, 0x0000, X 0x4000, 0x009a, 0x4410, 0x0000, X 0x2000, 0xff99, 0x087f, 0x0000, X 0x8000, 0xfe18, 0x3047, 0x0000, X 0x0000, 0x0018, 0x0060, 0x0000, X 0x0000, 0x0078, 0x0070, 0x0000, X 0x0000, 0x00f8, 0x0f58, 0x0000, X 0x0000, 0x1ff8, 0x30c0, 0x0000, X 0x0000, 0x2004, 0x4030, 0x0000, X 0x0000, 0x2002, 0x4008, 0x0000, X 0x0000, 0x2001, 0xc004, 0x0003, X 0x0000, 0x2001, 0x2044, 0x000e, X 0x0000, 0xfe11, 0x204f, 0x0038, X 0xff00, 0x0211, 0x1070, 0x07c0, X 0x01e0, 0x0111, 0x0f80, 0x0c00, X 0x003c, 0x00fe, 0x0000, 0x0000, X 0x0007, 0x0000, 0x0000, 0x0000, X 0x0000, 0x0000, 0x0000, 0x0000, X 0x0000, 0x0000, 0x0000, 0x0000, X 0x0000, 0x0000, 0x0000, 0x0000, X 0x0000, 0x0000, 0x0000, 0x0000`7D; $ CALL UNPACK HOBBES1.ICON;1 1495284600 $ create 'f' X#define hobbes_width 90 X#define hobbes_height 90 X#define hobbes_x_hot -1 X#define hobbes_y_hot -1 Xstatic char hobbes_bits`5B`5D = `7B X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x07, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xc9, 0x63, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0x28, 0x46, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x40, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x40, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0xf8, 0x80, 0x1f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0xcc, 0x00, 0x20, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x84, 0x00, 0x20, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x04, 0x00, 0x3e, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x0c, 0x00, 0x3f, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0xf8, 0x00, 0x3f, 0x9f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x81, 0x03, 0xff, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x07, 0x02, 0xff, 0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x1c, 0x02, 0xfe, 0x63, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xfe, 0x04, 0x30, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xff, 0xfb, 0x99, 0xdf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x01, 0xfe, 0xc9, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xf1, 0x0f, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xff, 0x07, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0x0f, 0x03, 0x60, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xc0, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xe0, 0x16, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0x71, 0x36, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xfe, 0xe7, 0x01, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xf6, 0x23, 0x00, 0x6f, 0x0c, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x1c, 0x62, 0x02, 0x6e, 0x1c, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xc8, 0x63, 0x02, 0x26, 0x3e, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xe8, 0x33, 0x02, 0x36, 0xe6, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xf8, 0x1b, 0x03, 0x32, 0xc3, 0x03, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x01, 0xb6, 0x61, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xd6, 0x39, 0x0e, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xf4, 0x0c, 0x18, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xfc, 0xf6, 0x11, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x8c, 0x7f, 0x3f, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xd8, 0x03, 0x3c, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0xc0, 0x81, 0xcf, 0x07, 0x24, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0x00, 0x3e, 0x0c, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x1f, 0xf8, 0x07, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x7e, 0xe0, 0x01, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xfc, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xe0, 0x1b, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0xc0, 0x88, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x40, 0x8c, 0x1e, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x77, 0xfa, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc2, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe2, 0x1f, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x7f, 0x18, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x3f, 0x08, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x0e, 0x02, 0xc0, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x1f, 0xf3, 0x03, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x80, 0xb1, 0xe0, 0x01, 0xf0, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, X 0x00, 0xc0, 0xe0, 0xe3, 0x01, 0xf8, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x60, 0xce, 0xe7, 0x03, 0x08, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x20, 0x8e, 0xe7, 0xff, 0x0e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x20, 0x06, 0x67, 0xfc, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x20, 0x60, 0x67, 0xe0, 0x3b, 0xc0, 0x00, 0xfc, 0x00, 0x00, 0x00, X 0x00, 0xb0, 0x61, 0x7e, 0xfc, 0x71, 0x60, 0x00, 0x64, 0x03, 0x00, 0x00, X 0x00, 0x90, 0x61, 0xde, 0x0f, 0xe0, 0x71, 0x00, 0x62, 0x02, 0x00, 0x00, X 0x00, 0xb0, 0x01, 0x06, 0x1f, 0xc0, 0x9f, 0x00, 0x73, 0x04, 0x00, 0x00, X 0x00, 0x30, 0x08, 0x86, 0xff, 0x07, 0x8e, 0x01, 0x8f, 0x07, 0x00, 0x00, X 0x00, 0x20, 0x1c, 0x82, 0xf1, 0xff, 0xfe, 0x01, 0x8f, 0x07, 0x00, 0x00, X 0x00, 0x60, 0x1c, 0x82, 0x01, 0xfc, 0x43, 0x03, 0x89, 0x04, 0x00, 0x00, X 0x00, 0x40, 0x1c, 0x83, 0x07, 0xe0, 0x3f, 0x86, 0x89, 0x04, 0x00, 0x00, X 0x00, 0x80, 0x00, 0x01, 0x07, 0x38, 0x00, 0x84, 0xcf, 0x07, 0x00, 0x00, X 0x00, 0x00, 0x83, 0x01, 0xfc, 0x1f, 0x00, 0x84, 0xc7, 0x07, 0x00, 0x00, X 0x00, 0x00, 0xc6, 0x00, 0xf8, 0x1f, 0x00, 0x4e, 0xc4, 0x03, 0x00, 0x00, X 0x00, 0x00, 0x58, 0x00, 0xf8, 0x03, 0x00, 0x7e, 0xc4, 0x01, 0x00, 0x00, X 0x00, 0x00, 0x70, 0xf0, 0x3f, 0x20, 0x00, 0xdf, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x11, 0x80, 0xcd, 0x02, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x70, 0x78, 0x11, 0xc0, 0xf8, 0xfd, 0x00, 0x00, 0x00, X 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00`7D V; $ CALL UNPACK HOBBES2.ICON;1 912490110 $ create 'f' X# X# $Header: /users/ricks/xrn/src/RCS/Imakefile,v 1.10 90/09/29 01:14:01 ricks V Exp Locker: ricks $ X# X# xrn - an X-based NNTP news reader X# X# Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmier V. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation, and that the name of the University of California not X# be used in advertising or publicity pertaining to distribution of`20 X# the software without specific, written prior permission. The University X# of California makes no representations about the suitability of this X# software for any purpose. It is provided "as is" without express or X# implied warranty. X# X# THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X# FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X# X# Suggestions, comments, or improvements are welcome and should be X# addressed to: X# X# xrn@ic.berkeley.edu X# ..!ucbvax!ic!xrn X# X X#ifdef BandAidCompiler X#include BandAidCompiler X#endif X X#if defined(XmacIIServer) `7C`7C defined(hp9000s300) `7C`7C defined(hp9000s8 V00) `7C`7C defined(SGIArchitecture) XEXTRA_LOAD_FLAGS = -lPW X#endif X X#if defined(aiws) XDEFINES = -a -Nn3000 -Nd4000 X#else X#if defined(HCRevision) XDEFINES = -DUNIXCPP -DNOSTDHDRS X#else X#if defined(gould) XDEFINES = -DNOVOID -DLONGINT -UINTSPRINTF X#else XDEFINES = X#endif X#endif X#endif X XLOCAL_LIBRARIES = XawClientLibs XDEPLIBS = XawClientDepLibs XPROGRAMS = xrn X X SRCS = avl.c buttons.c clientlib.c compose.c cursor.c dialogs.c \ X`09`09 mesg.c error_hnds.c newsrcfile.c resources.c \ X`09`09 internals.c save.c server.c utils.c xmisc.c xrn.c \ X`09`09 xthelper.c vprintf.c tempnam.c strstr.c strtok.c y.tab.c cancel.c X OBJS = avl.o buttons.o clientlib.o compose.o cursor.o dialogs.o \ X`09`09 mesg.o error_hnds.o newsrcfile.o resources.o \ X`09`09 internals.o save.o server.o utils.o xmisc.o xrn.o \ X`09`09 xthelper.o vprintf.o tempnam.o strstr.o strtok.o y.tab.o cancel.o X XAllTarget(xrn) X Xdepend:: y.tab.c lex.yy.c X XComplexProgramTarget(xrn) X Xlex.yy.c: newsrc.l X`09lex newsrc.l X Xy.tab.c: newsrc.y X`09yacc newsrc.y X Xy.tab.o: lex.yy.c avl.h news.h newsrcfile.h utils.h X Xclean:: X`09$(RM) y.tab.c lex.yy.c X XInstallAppDefaults(XRn) X $ CALL UNPACK IMAKEFILE.;1 997782490 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/internals.c, Vv 1.16 90/09/29 01:12:47 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * internals.c: routines for handling the internal data structures X * calls server routines, is calls by the user interface code X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#include X#ifdef MOTIF X#include X#else X#include X#endif X#endif X#include X#include X#include "config.h" X#include "utils.h" X#include X#ifndef VMS X#include X#include X#else X#ifndef R_OK X#define F_OK 0 /* does file exist */ X#define X_OK 1 /* is it executable by caller */ X#define W_OK 2 /* writable by caller */ X#define R_OK 4 /* readable by caller */ X#endif /* R_OK */ X#define index strchr X#include X#include X#endif /* VMS */ X#ifdef aiws X#include X#endif /* aiws */ X#include "avl.h" X#include "news.h" X#include "newsrcfile.h" X#include "resources.h" X#include "server.h" X#include "mesg.h" X#include "error_hnds.h" X#include "save.h" X#include "internals.h" X#include "xrn.h" X X#ifdef SYSV_REGEX X extern char *regcmp(); X extern char *regex(); X#else X extern char *re_comp(); X#endif X X#define SETARTICLES(newsgroup) if (newsgroup->articles == 0) (void) getartic Vles(newsgroup) X Xstatic char *strip(); X X#define BUFFER_SIZE 1024 X#define LABEL_SIZE 128 X#define FATAL 0 X#define OKAY 1 X/* X * length of lines in the top text window X */ X#define LINE_LENGTH 100 X X#ifdef XRN_PREFETCH X/* don't prefetch the next group if you got to a group via 'goto newsgroup' V */ X#define OKAY_TO_XRN_PREFETCH_GROUP 1 X#define DO_NOT_XRN_PREFETCH_GROUP 0 X X/* X * this flag is set to DO_NOT_XRN_PREFETCH_GROUP if you got to the current X * group by 'goto newsgroup' (jumpToNewsgroup). You do not want to prefetch X * the next group if you are randomly jumping around. The next group X * after the one jumped to is probably not the next one you will go to. X */ Xstatic int PrefetchGroupMode = OKAY_TO_XRN_PREFETCH_GROUP; X#endif /* XRN_PREFETCH */ X X/* X * next article to get when faulting in articles that are of the top X * of the subject screen. X */ Xstatic art_num NextPreviousArticle; X `20 X/* storage for all newsgroups, key is the name of the group */ Xavl_tree *NewsGroupTable = NIL(avl_tree); X X/* number of groups in the active file */ Xint ActiveGroupsCount = 0; X X/* number of the group currently being processed */ Xng_num CurrentGroupNumber = NO_GROUP; X X/* number of groups in the .newsrc file */ Xng_num MaxGroupNumber = 0; X X#ifdef XRN_PREFETCH X/* set to the value of a group if that group has been prefetched */ Xstatic ng_num PrefetchedGroup = NO_GROUP; X#endif /* XRN_PREFETCH */ X X/* index number of last article read */ Xstatic int PrevArtIndx`5B5`5D = `7B-1,-1,-1,-1,-1`7D; X Xvoid XcheckLock() X/* X * see if another xrn is running X */ X`7B X#ifndef VMS X char *buffer = utTildeExpand("`7E/.xrnlock"); X#else X char *buffer = "SYS$LOGIN:XRN.LOCK"; X char *ptr; X struct _itemList `7B X`09short item_size; X`09short item_code; X`09int item_ptr; X`09int item_rtn_size; X`09int end_list; X `7D itemList; X#endif /* VMS */ X char host`5B64`5D; X char myhost`5B64`5D; X int pid; X FILE *fp; X X if (!buffer) `7B X`09/* silently ignore this condition */ X`09return; X `7D X X#ifndef VMS X if (gethostname(myhost, sizeof(myhost)) == -1) `7B X`09(void) strcpy(myhost, "bogusHost"); X `7D X#else X ptr = getenv("SYS$NODE"); X (void) strcpy(myhost, ptr); X ptr = index(myhost, ':'); X if (ptr != NIL(char)) `7B X`09*ptr = '\0'; X `7D X X if (*myhost == NIL(char)) `7B X`09(void) strcpy(myhost, "bogusHost"); X `7D X#endif /* VMS */ X X if ((fp = fopen(buffer, "r")) == NULL) `7B X`09if ((fp = fopen(buffer, "w")) == NULL) `7B X`09 /* silently ignore this condition */ X`09 return; X`09`7D X`09(void) fprintf(fp, "%s %d\n", myhost, getpid()); X`09(void) fclose(fp); X`09return; X `7D X X (void) fscanf(fp, "%s %d", host, &pid); X X#ifndef VMS X /* see if I'm on the same host */ X if (strcmp(host, myhost) == 0) `7B X`09if ((kill(pid, 0) == -1) && (errno == ESRCH)) `7B X`09 /* hey, it's not running.... */ X`09 /* why do it right when you can just do this... */ X`09 removeLock(); X`09 checkLock(); X`09 return; X`09`7D X `7D X#else X /* see if I'm on the same host */ X if (strcmp(host, myhost) == 0) `7B X`09int status, pidTmp; X`09/* whoa! I am, see if the process is mine */ X`09if (pid == getpid()) `7B X`09 /* It's mine.. so delete it */ X`09 /* why do it right when you can just do this... */ X`09 (void) fclose(fp); X`09 removeLock(); X`09 checkLock(); X`09 return; X`09`7D X`09/* whoa! I am, see if the process is running */ X`09itemList.item_size = 4; X`09itemList.item_code = JPI$_PID; X`09itemList.item_ptr = &pidTmp; X`09itemList.item_rtn_size = 0; X`09itemList.end_list = 0; X X`09pidTmp = 0; X`09status = SYS$GETJPIW(0, &pid, 0, &itemList, 0, 0, 0); X`09if (status == SS$_NONEXPR) `7B X`09 /* hey, it's not running.... */ X`09 /* why do it right when you can just do this... */ X`09 removeLock(); X`09 checkLock(); X`09 return; X`09`7D X `7D X#endif X X (void) fprintf(stderr, "An XRN of yours is running on %s as process %d.\ Vn", X`09`09 host, pid); X (void) fprintf(stderr, "If it is no longer running, remove %s\n", X`09`09 buffer); X exit(-1); X X return; X`7D X X Xvoid XremoveLock() X`7B X#ifndef VMS X char *buffer = utTildeExpand("`7E/.xrnlock"); X#else X char *buffer = "SYS$LOGIN:XRN.LOCK"; X#endif /* VMS */ X X if (buffer) `7B X`09(void) unlink(buffer); X `7D X return; X`7D X Xvoid XinitializeNews() X/* X * initialize the program and the news system X * read newsrc, etc X * X * returns: void X * X */ X`7B X start_server(app_resources.nntpServer); X X do `7B X`09 NewsGroupTable = avl_init_table(strcmp); X `20 X`09 getactive(); X`09`20 X`09 if (readnewsrc(app_resources.newsrcFile, X`09`09`09app_resources.saveNewsrcFile)) X`09 break; X`09`20 X`09 ehErrorRetryXRN("Can not read the .newsrc file", True); X X`09 avl_free_table(NewsGroupTable, XtFree, XtFree); X `7D while (1); X`09 X#ifndef FIXED_ACTIVE_FILE X badActiveFileCheck(); X#endif X return; X`7D X X Xvoid XrescanServer() X/* X * get the active file again and grow the Newsrc array if necessary X */ X`7B X int old = ActiveGroupsCount; X X /* update the newsrc file */ X while (!updatenewsrc()) X`09ehErrorRetryXRN("Can not update the newsrc file", True); X X /* close and reopen the connection - till the server is fixed */ X close_server(); X start_server(NIL(char)); X `20 X getactive(); X X if (ActiveGroupsCount > old) `7B X`09/* new newsgroups were found, allocate a bigger array */ X`09Newsrc = (struct newsgroup **) XtRealloc((char *) Newsrc, (unsigned) (siz Veof(struct newsgroup *) * ActiveGroupsCount)); X `7D X X#ifndef FIXED_ACTIVE_FILE X badActiveFileCheck(); X#endif X X return; X`7D X X#define lsDestroy(lst) \ X if (lst != NIL(struct list)) `7B \ X`09struct list *_next; \ X`09do `7B \ X`09 _next = lst->next; \ X`09 FREE(lst); \ X`09 lst = _next; \ X`09`7D while (lst != NIL(struct list)); \ X `7D X X Xint XunreadArticleCount(newsgroup) Xstruct newsgroup *newsgroup; X/* X * accurately count the number of unread articles in a group X * X * returns: the number of unread articles in the group X */ X`7B X art_num i; X#ifdef STUPIDMMU X struct article *articles; X struct list *item; X#else X struct article *articles = GETARTICLES(newsgroup); X#endif X int count = 0; X X if (EMPTY_GROUP(newsgroup)) `7B X`09return 0; X `7D X `20 X if ((newsgroup->first == 0) && (newsgroup->last == 0)) `7B X`09return 0; X `7D X `20 X#ifdef STUPIDMMU X /* try to be clever and not use articles array */ X if (!newsgroup->articles) `7B X`09int cleared = 0; X X`09if (!newsgroup->nglist) X`09 return 0; X X`09/* process the .newsrc line */ X X`09for (item = newsgroup->nglist; item != NIL(struct list); X`09`09 item = item->next) `7B X X`09 /* this is really stupid, we need this because X`09 rescans cause a newsgroup to forget its previous idea of X`09 first */ X`09 int start; X X`09 switch (item->type) `7B X`09`09case SINGLE: X`09`09if (item->contents.single > newsgroup->last) `7B X`09`09 /* something really bad has happened */ X`09`09 mesgPane(XRN_SERIOUS, "Article numbering problem, marking all arti Vcles in %s as unread", X`09`09 newsgroup->name); X`09`09 lsDestroy(newsgroup->nglist); X`09`09 newsgroup->nglist = NIL(struct list); X`09`09 return 0; X`09`09`7D X`09`09if (item->contents.single >= newsgroup->first) `7B X`09`09 cleared++; X`09`09`7D X`09`09break; X X`09`09case RANGE: X`09`09if ((item->contents.range.start > newsgroup->last) `7C`7C X`09`09 (item->contents.range.end > newsgroup->last)) `7B X`09`09 /* something really bad has happened */ X`09`09 mesgPane(XRN_SERIOUS, "Article numbering problem, marking all arti Vcles in %s as unread", X`09`09`09 newsgroup->name); X`09`09 lsDestroy(newsgroup->nglist); X`09`09 newsgroup->nglist = NIL(struct list); X`09`09 return 0; X`09`09`7D X`09`09if (item->contents.range.start < newsgroup->first) `7B X`09`09 start = newsgroup->first; X`09`09`7D else `7B X`09`09 start = item->contents.range.start; X`09`09`7D X`09`09 X`09`09if (item->contents.range.end < newsgroup->first) `7B X`09`09 break; X`09`09`7D X`09`09cleared += item->contents.range.end - start + 1; X`09 `7D X`09`7D X`09return(newsgroup->last - newsgroup->first + 1 - cleared); X `7D X#endif X X#ifdef STUPIDMMU X articles = newsgroup->articles; X#endif X for (i = newsgroup->first; i <= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X`09if (IS_UNREAD(articles`5Bindx`5D) && !IS_UNAVAIL(articles`5Bindx`5D)) `7B X`09 count++; X`09`7D X `7D X X return count; X`7D X X Xint XtotalArticleCount(newsgroup) Xstruct newsgroup *newsgroup; X/* X * accurately count the number of articles in a group X * X * returns: the total number of articles in the group X */ X`7B X art_num i; X struct article *articles = GETARTICLES(newsgroup); X int count = 0; X `20 X if (EMPTY_GROUP(newsgroup)) `7B X`09return 0; X `7D X `20 X if ((newsgroup->first == 0) && (newsgroup->last == 0)) `7B X`09return 0; X `7D X `20 X for (i = newsgroup->first; i <= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X`09if (!IS_UNAVAIL(articles`5Bindx`5D)) `7B X`09 count++; X`09`7D X `7D X X return count; X`7D X X Xstatic void XsetCurrentArticle(newsgroup) Xstruct newsgroup *newsgroup; X/* X * find the first unread article in a group and set 'current' to it X * X * returns: void X * X */ X`7B X struct article *articles = GETARTICLES(newsgroup); X art_num i; X `20 X X newsgroup->current = newsgroup->last + 1; X `20 X for (i = newsgroup->first; i<= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X`09if (IS_UNREAD(articles`5Bindx`5D) && !IS_UNAVAIL(articles`5Bindx`5D)) `7B X`09 newsgroup->current = i; X`09 return; X`09`7D X `7D X return; X`7D X Xint XunreadNews() X`7B X int i, count = 0; X struct newsgroup *newsgroup; X X for (i = 0; i < MaxGroupNumber; i++) `7B X`09newsgroup = Newsrc`5Bi`5D; X`09if (IS_SUBSCRIBED(newsgroup)) `7B X`09 count += unreadArticleCount(newsgroup); X`09`7D X `7D X return count; X`7D X X Xchar ** XunreadGroups(mode) Xint mode; X/* X * build and return an array of information about groups that need to be rea Vd X */ X`7B X char dummy`5BLINE_LENGTH`5D; X struct newsgroup *newsgroup; X ng_num i; X int unread, j; X int bytes = 0, subscribedGroups = 0; X char *string, **ar; X X ar = ARRAYALLOC(char *, MaxGroupNumber); X X for (i = 0; i < MaxGroupNumber; i++) `7B X`09newsgroup = Newsrc`5Bi`5D; X X`09if (IS_SUBSCRIBED(newsgroup) && X`09 (((unread = unreadArticleCount(newsgroup)) > 0) `7C`7C mode)) `7B X`09 int total = totalArticleCount(newsgroup); X`09 (void) sprintf(dummy, "%6s %7s %-40.40s%5d article%s + %5d old", X`09 (unread>0 ? "Unread" : ""), X`09 (total>0 ? "news in" : ""), X`09`09`09 newsgroup->name, unread, X`09`09`09 ((unread != 1) ? "s" : " "), X`09`09`09 total-unread); X X`09 ar`5BsubscribedGroups++`5D = XtNewString(dummy); X`09 bytes += utStrlen(dummy); X`09`7D X `7D X X ar`5BsubscribedGroups++`5D = 0; X return ar; X`7D X X Xchar ** XnewGroups() X/* X * determine the newsgroups that are not in the .newsrc file X * X * returns a string representing the information X */ X`7B X int count = 0; X avl_generator *gen; X char *key, *value; X char **ar; X X ar = ARRAYALLOC(char *, ActiveGroupsCount + 1); X X gen = avl_init_gen(NewsGroupTable, AVL_FORWARD); X X while (avl_gen(gen, &key, &value)) `7B X`09struct newsgroup *newsgroup = (struct newsgroup *) value; X X`09if (IS_NOENTRY(newsgroup)) `7B X`09 ar`5Bcount++`5D = XtNewString(newsgroup->name); X`09`7D X `7D X X avl_free_gen(gen); X X /* no new groups return */ X if (count == 0) `7B X`09FREE(ar);`09 X`09return (char **) 0; X `7D X X ar`5Bcount`5D = NIL(char); X return ar; X`7D X X X#ifdef XRN_PREFETCH X Xvoid XfreePrefetchedGroupArticle() X`7B X struct newsgroup *pfgroup; X struct article *articles; X long indx; X X if (PrefetchedGroup != NO_GROUP) `7B X`09pfgroup = Newsrc`5BPrefetchedGroup`5D; X`09articles = GETARTICLES(pfgroup); X`09indx = pfgroup->current - pfgroup->first; X `20 X`09/* free the first article if it has been prefetched */ X`09if (IS_FETCHED(articles`5Bindx`5D)) `7B X`09 CLEAR_FILE(articles`5Bindx`5D); X`09`7D X `7D X `20 X return; X`7D X X#endif /* XRN_PREFETCH */ X X X#ifdef STUPIDMMU X X/* utterly disgusting interface so things will work like before X`09should store this info in some other format than struct list X`09and some other field than nglist X*/ X Xvoid XupdateNglist(newsgroup) Xstruct newsgroup *newsgroup; X`7B X X`09int nocomma = 1, inrange = 1; X`09art_num lastread = 1, j; X`09struct list *item, *it, *next; X X`09if ((newsgroup->articles == NIL(struct article)) X`09`09`09`09`7C`7C newsgroup->nglist) `7B X`09 printf("unexpected call to updateNglist\n"); X`09 return; X`09`7D X`09 X`09if (newsgroup->last >= newsgroup->first) `7B X X`09 for (j = newsgroup->first; j <= newsgroup->last; j++) `7B X`09`09if (inrange && IS_UNREAD(newsgroup->articles`5BINDEX(j)`5D) && X`09`09 !IS_UNAVAIL(newsgroup->articles`5BINDEX(j)`5D)) `7B X`09`09 if (lastread == j - 1) `7B X`09`09`09item = ALLOC(struct list); X`09`09`09item->type = SINGLE; X`09`09`09item->contents.single = lastread; X`09`09`09item->next = newsgroup->nglist; X`09`09`09newsgroup->nglist = item; X`09`09 `7D else `7B X`09`09`09if ((j - 1) > 0) `7B X`09`09`09 item = ALLOC(struct list); X`09`09`09 item->type = RANGE; X`09`09`09 item->contents.range.start = lastread; X`09`09`09 item->contents.range.end = j - 1; X`09`09`09 item->next = newsgroup->nglist; X`09`09`09 newsgroup->nglist = item; X`09`09`09`7D X`09`09 `7D X X`09`09 inrange = 0; X`09`09`7D else if (!inrange && IS_READ(newsgroup->articles`5BINDEX(j)`5D)) ` V7B X`09`09 inrange = 1; X`09`09 lastread = j; X`09`09`7D X`09 `7D X`09 `20 X`09 if (inrange) `7B X`09`09if (lastread == newsgroup->last) `7B X`09`09 item = ALLOC(struct list); X`09`09 item->type = SINGLE; X`09`09 item->contents.single = lastread; X`09`09 item->next = newsgroup->nglist; X`09`09 newsgroup->nglist = item; X`09`09`7D else `7B X`09`09 item = ALLOC(struct list); X`09`09 item->type = RANGE; X`09`09 item->contents.range.start = lastread; X`09`09 item->contents.range.end = newsgroup->last; X`09`09 item->next = newsgroup->nglist; X`09`09 newsgroup->nglist = item; X`09`09`7D X`09 `7D X`09`7D else `7B X`09 if (newsgroup->last > 1) `7B X`09`09 item = ALLOC(struct list); X`09`09 item->type = RANGE; X`09`09 item->contents.range.start = 1; X`09`09 item->contents.range.end = lastread; X`09`09 item->next = newsgroup->nglist; X`09`09 newsgroup->nglist = item; X`09 `7D X`09`7D X X`09/* reverse order */ X`09for (it = newsgroup->nglist, newsgroup->nglist = NIL(struct list); X`09`09`09it; it = next) `7B X`09 next = it->next; X`09 it->next = newsgroup->nglist; X`09 newsgroup->nglist = it; X`09`7D X`7D X Xvoid XdumpNg(newsgroup) Xstruct newsgroup *newsgroup; X`7B X`09struct list *it; X X`09for (it = (struct list *) newsgroup->nglist; it; it = it->next) `7B X`09 printf("type = %d", it->type); X`09 if (it->type == RANGE) `7B X`09 printf(" start = %d, end = %d, next = 0x%x\n", X`09 it->contents.range.start, it->contents.range.end, X`09 it->next); X`09 `7D else `7B X`09 printf(" single = %d, next = 0x%x\n", it->contents.single, X`09 it->next); X`09 `7D X`09`7D X`7D X X#endif X Xvoid XreleaseNewsgroupResources() X/* X * release some resources X * X * returns: void X */ X`7B X int i; X X for (i = 0; i < 5; i++)`20 X`09PrevArtIndx`5Bi`5D = -1; X /* X * CurrentGroupNumber can be invalid when called from the X * signal catcher X */ X if (CurrentGroupNumber != NO_GROUP && X`09Newsrc`5BCurrentGroupNumber`5D != NIL(struct newsgroup) ) `7B X`09struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X`09struct article *articles = GETARTICLES(newsgroup); X`09art_num art; X X`09if ((newsgroup->last == 0) `7C`7C EMPTY_GROUP(newsgroup)) `7B X`09 return; X`09`7D X X`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09 long indx = INDEX(art); X`09 `20 X`09 CLEAR_SUBJECT(articles`5Bindx`5D); X`09 CLEAR_AUTHOR(articles`5Bindx`5D); X`09 CLEAR_LINES(articles`5Bindx`5D); X`09 CLEAR_FILE(articles`5Bindx`5D); X#ifndef STUPIDMMU X`09 SET_STRIPPED_HEADERS(articles`5Bindx`5D); X`09 SET_UNROTATED(articles`5Bindx`5D); X#endif X`09`7D X#ifdef STUPIDMMU X`09/* free the articles array every time */ X`09updateNglist(newsgroup); X`09CLEAR_ARTICLES(newsgroup); X#endif X `7D X X if (app_resources.updateNewsrc == TRUE) `7B X`09if (!updatenewsrc()) `7B X`09 ehErrorExitXRN("Can not update the newsrc file"); X`09`7D X `7D X X return; X`7D X Xvoid clearArtCache() X`7B X int i; X for (i = 0; i < 5; i++) X`09PrevArtIndx`5Bi`5D = -1; X return; X`7D Xvoid XarticleArrayResync(newsgroup, first, last, number) Xstruct newsgroup *newsgroup; Xart_num first, last; Xint number; X/* X * update an article array if the first and/or last article numbers change X * X * returns: void X */ X`7B X#ifdef STUPIDMMU X struct article *articles; X#else X struct article *articles = GETARTICLES(newsgroup); X#endif X struct article *newarticles; X int i; X X X /* X * if there are actually no articles in the group, free up the X * article array and set the first/last values X */ X `20 X if (number == 0) `7B X`09CLEAR_ARTICLES(newsgroup); X`09newsgroup->first = newsgroup->last + 1; X`09return; X `7D X `20 X /* refuse to resync if last == 0 */ X if (last == 0) `7B X`09return; X `7D X X if (first > last) `7B X`09/* all articles have been removed */ X`09CLEAR_ARTICLES(newsgroup); X`09newsgroup->first = newsgroup->last + 1; X`09return; X `7D X X /* don't allow last to go backwards!!! */ X if (last < newsgroup->last) `7B X`09last = newsgroup->last; X `7D X`09 X if ((first != newsgroup->first) `7C`7C (last != newsgroup->last)) `7B X#ifdef STUPIDMMU X`09/* only do this if the articles array has been allocated */ X`09if (newsgroup->articles) `7B X#endif X`09/* the first/last values have changed, resync */ X`09newarticles = ARRAYALLOC(struct article, last - first + 1); X X`09/* X`09 * initialize the new article structures X`09 */ X`09 X`09for (i = first; i <= last; i++) `7B X`09 newarticles`5Bi - first`5D.subject = NIL(char); X`09 newarticles`5Bi - first`5D.author = NIL(char); X`09 newarticles`5Bi - first`5D.filename = NIL(char); X`09 newarticles`5Bi - first`5D.lines = NIL(char); X`09 if (i < newsgroup->first) `7B X`09`09/* handle first decreasing... mark them as read */ X`09`09newarticles`5Bi - first`5D.status = ART_CLEAR_READ; X`09 `7D else `7B X`09`09newarticles`5Bi - first`5D.status = ART_CLEAR; X`09 `7D X`09`7D X X#ifdef STUPIDMMU X`09articles = newsgroup->articles; X#endif X`09if ((!EMPTY_GROUP(newsgroup)) && X`09 (newsgroup->articles != NIL(struct article))) `7B X`09 for (i = first; i <= last; i++) `7B X`09`09if ((i >= newsgroup->first) && (i <= newsgroup->last)) `7B X`09`09 newarticles`5Bi - first`5D = articles`5BINDEX(i)`5D; X`09`09`7D X`09 `7D X X`09 /* free up the old resources - before the new first */ X`09 for (i = newsgroup->first; i < first; i++) `7B X`09`09long indx = INDEX(i); X`09`09CLEAR_SUBJECT(articles`5Bindx`5D); X`09`09CLEAR_AUTHOR(articles`5Bindx`5D); X`09`09CLEAR_LINES(articles`5Bindx`5D); X`09`09CLEAR_FILE(articles`5Bindx`5D); X`09 `7D X`09 /* after the new last */ X`09 for (i = last + 1; i < newsgroup->last; i++) `7B X`09`09long indx = INDEX(i); X`09`09CLEAR_SUBJECT(articles`5Bindx`5D); X`09`09CLEAR_AUTHOR(articles`5Bindx`5D); X`09`09CLEAR_LINES(articles`5Bindx`5D); X`09`09CLEAR_FILE(articles`5Bindx`5D); X`09 `7D X`09`7D X X`09if (articles != NIL(struct article)) `7B X`09 FREE(articles); X`09`7D X`09newsgroup->articles = newarticles; X X#ifdef STUPIDMMU X`09`7D X#endif X X`09newsgroup->first = first; X`09newsgroup->last = last; X `7D X X return; X`7D X X Xstatic char * XlocalKillFile(newsgroup, mode) Xstruct newsgroup *newsgroup; Xint mode; X`7B X static char buffer`5BBUFFER_SIZE`5D; X char *ptr; X int i; X X if (!createNewsDir()) `7B X`09return NIL(char); X `7D X X (void) strcpy(buffer, app_resources.expandedSaveDir); X i = strlen(buffer); X X#ifndef VMS X buffer`5Bi++`5D = '/'; X X for (ptr = newsgroup->name; *ptr != 0; ptr++) `7B X`09if (*ptr == '.') `7B X`09 if (mode) `7B X`09`09buffer`5Bi`5D = '\0'; X`09`09(void) mkdir(buffer, 0777); X`09 `7D X`09 buffer`5Bi`5D = '/'; X`09 i++; X`09`7D else `7B X`09 buffer`5Bi++`5D = *ptr; X`09`7D X `7D X buffer`5Bi`5D = '\0'; X if (mode) `7B X`09(void) mkdir(buffer, 0777); X `7D X (void) strcpy(&buffer`5Bi`5D, "/KILL"); X#else X i = i + utGroupToVmsFilename(&buffer`5Bi`5D, newsgroup->name); X (void) strcpy(&buffer`5Bi`5D, ".KILL"); X#endif X X return buffer; X`7D X X Xchar * XglobalKillFile() X`7B X static char buffer`5BBUFFER_SIZE`5D; X X if (!createNewsDir()) `7B X`09return NIL(char); X `7D X (void) strcpy(buffer, app_resources.expandedSaveDir); X#ifndef VMS X (void) strcat(buffer, "/KILL"); X#else X (void) strcat(buffer, "NEWS$GLOBAL.KILL"); X#endif X return buffer; X`7D X X Xvoid XkillItem(item, type) Xchar *item; Xint type; X/* X * add a kill subject/author entry to a kill file X */ X`7B X char input`5BBUFFER_SIZE`5D, *iptr; X char output`5BBUFFER_SIZE`5D, *optr; X FILE *fp; X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X char *file; X X if (type == KILL_LOCAL) `7B X`09file = localKillFile(newsgroup, 1); X `7D else `7B X`09file = globalKillFile(); X `7D X X if ((fp = fopen(file, "a")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, "Can not open the %s kill file for %s",`20 X`09`09 (type == KILL_LOCAL) ? "local" : "global", X`09`09 newsgroup->name); X`09return; X `7D X /* get rid of all magic characters */ X (void) strncpy(input, item, sizeof(input)); X iptr = input; X optr = output; X while (*iptr) `7B X`09if ((*iptr == '/') `7C`7C X`09 (*iptr == '\\') `7C`7C X`09 (*iptr == '(') `7C`7C X`09 (*iptr == '`5B') `7C`7C X`09 (*iptr == '+') `7C`7C X`09 (*iptr == '-') `7C`7C X`09 (*iptr == ':') `7C`7C X`09 (*iptr == '.') `7C`7C X`09 (*iptr == '`5E') `7C`7C X`09 (*iptr == '*') `7C`7C X`09 (*iptr == '$') `7C`7C X`09 (*iptr == '\'') `7C`7C X`09 (*iptr == '\"')) `7B X`09 *iptr = '.'; X`09`7D X`09*optr++ = *iptr++; X `7D X *optr = '\0'; X X fprintf(fp, "/%.24s/:j\n", output); X (void) fclose(fp); X return; X`7D X X X/* XXX THIS ROUTINE REALLY NEEDS TO BE CLEANED UP */ Xstatic void XkillArticles(newsgroup, fp) Xstruct newsgroup *newsgroup; XFILE *fp; X/* X * kill all subjects in the newsgroup that match the kill X * orders in fp. X */ X`7B X char string`5BBUFFER_SIZE`5D, pattern`5BBUFFER_SIZE`5D, commands`5BBUFFE VR_SIZE`5D; X char dummy`5BBUFFER_SIZE`5D; X art_num i, start = newsgroup->current; X char *subject, *author, *subj, *ptr, *pptr; X int scount = 0, kcount = 0, ucount = 0, mcount = 0; X int append; X char *reRet; X char type; X X info("processing KILL file"); X X /* XXX don't reprocess global each time, keep in persistent hash table * V/ X X while (fgets(string, sizeof(string), fp) != NULL) `7B X`09append = 0; X X`09/* X`09 * see if there is a 'THRU artnum' line, if so, X`09 * only compare subjects from that article on X`09 * XXX need to update THRU X`09 */ X`09if (STREQN(string, "THRU", 4)) `7B X`09 i = atol(&string`5B5`5D); X`09 /* if THRU is less than current, ignore it */ X`09 if (i + 1 > newsgroup->current) `7B X`09`09start = i + 1; X`09 `7D else `7B X`09`09start = newsgroup->current; X`09 `7D X`09 continue; X`09`7D X X`09if (*string == '&') `7B X`09 /* 'rn' switch setting, ignore */ X`09 continue; X`09`7D X X X`09/* X`09 * process kill file request should be in the form X`09 */ X`09ptr = string + 1; X`09pptr = pattern; X X`09while (*ptr && (*ptr != '/' `7C`7C ((*ptr == '/') && *(ptr - 1) == '\\')) V) `7B X`09 *pptr++ = *ptr; X`09 ptr++; X`09`7D X`09*pptr = '\0'; X X`09if (!*ptr) `7B X`09 mesgPane(XRN_SERIOUS, "Malformed KILL file entry (pattern): %s (%s)", X`09`09 string, pattern); X`09 continue; X`09`7D X X`09/* rn puts ': *' in front of patterns, xrn doesn't */ X`09if (strncmp(pattern, ": *", 3) == 0) `7B X`09 /* deal with overlapping strings */ X`09 (void) strcpy(dummy, pattern + 3); X`09 (void) strcpy(pattern, dummy); X`09`7D X X#ifdef SYSV_REGEX X`09if ((reRet = regcmp(pattern, NULL)) == NULL) `7B X`09 mesgPane(XRN_SERIOUS, "Bad KILL file pattern: %s", string); X#else X`09if ((reRet = re_comp(pattern)) != NIL(char)) `7B X`09 mesgPane(XRN_SERIOUS, "Bad KILL file pattern: %s\n%s", string, reRet) V; X#endif X`09 continue; X`09`7D X X`09ptr++;`09/* skip past the slash */ X`09(void) strcpy(commands, ptr); X`09if ((ptr = index(commands, ':')) == NIL(char)) `7B X`09 mesgPane(XRN_SERIOUS, "Malformed KILL file entry (command): %s (%s)", X`09`09 string, commands); X`09 continue; X`09`7D X`09ptr++;`09/* skip past the colon */ X`09type = *ptr; X X`09switch (type) `7B X`09 case 'j': X`09 case 'm': X`09 case 's': X`09 break; X`09 default: X`09 mesgPane(XRN_INFO, X`09`09`09 "unknown KILL file option: %s", string); X`09 break; X`09`7D X X`09for (i = start; i <= newsgroup->last; i++) `7B X X`09 /* short cut */ X`09 if (IS_UNAVAIL(newsgroup->articles`5BINDEX(i)`5D) `7C`7C X`09`09((type == 'j') && IS_READ(newsgroup->articles`5BINDEX(i)`5D)) `7C`7C X`09`09((type == 'm') && IS_UNREAD(newsgroup->articles`5BINDEX(i)`5D))) `7B X`09`09continue; X`09 `7D X X`09 if (newsgroup->articles`5BINDEX(i)`5D.subject `7C`7C X`09 newsgroup->articles`5BINDEX(i)`5D.author) `7B X X`09`09subject = newsgroup->articles`5BINDEX(i)`5D.subject; X`09`09author = newsgroup->articles`5BINDEX(i)`5D.author; X X`09`09if (subject) `7B X`09`09 subj = strip(subject); X`09`09`7D X X#ifdef SYSV_REGEX X`09`09if ((subject && (regex(reRet, subj) != NULL)) `7C`7C X`09`09 (author && (regex(reRet, author) != NULL))) `7B X#else X`09`09if ((subject && re_exec(subj)) `7C`7C X`09`09 (author && re_exec(author))) `7B X#endif X`09`09 switch (type) `7B X`09`09`09case 'j': X`09`09`09 SET_READ(newsgroup->articles`5BINDEX(i)`5D); X`09`09`09 mesgPane(XRN_INFO `7C append, "killed - %s", X`09`09`09`09 subject); X`09`09`09 append = XRN_APPEND; X`09`09`09 kcount++; X`09`09`09 break; X X`09`09`09case 'm': X`09`09`09 SET_UNREAD(newsgroup->articles`5BINDEX(i)`5D); X`09`09`09 mesgPane(XRN_INFO `7C append, "marked unread - %s", X`09`09`09`09 subject); X`09`09`09 append = XRN_APPEND; X`09`09`09 mcount++; X`09`09`09 break; X X`09`09`09case 's': X`09`09`09 (void) saveArticle(NIL(char), newsgroup, i); X`09`09`09 mesgPane(XRN_INFO `7C append, "saved - %s", X`09`09`09`09 subject); X`09`09`09 append = XRN_APPEND; X`09`09`09 scount++; X`09`09`09 break; X X`09`09`09default: X`09`09`09 ucount++; X`09`09`09 break; X`09`09 `7D X`09`09`7D X`09 `7D X`09`7D X `7D X X append = 0; X X if (kcount) `7B X`09mesgPane(XRN_INFO `7C append, "killed %d article%s in %s", X`09`09 kcount, (kcount == 1) ? "" : "s", newsgroup->name); X`09append = XRN_APPEND; X `7D X X if (mcount) `7B X`09mesgPane(XRN_INFO `7C append, "marked %d article%s unread in %s", X`09`09 mcount, (mcount == 1) ? "" : "s", newsgroup->name); X`09append = XRN_APPEND; X `7D X X if (scount) `7B X`09mesgPane(XRN_INFO `7C append, "saved %d article%s in %s", X`09`09 scount, (scount == 1) ? "" : "s", newsgroup->name); X`09append = XRN_APPEND; X `7D X X if (ucount) `7B X`09mesgPane(XRN_INFO `7C append, X`09`09 "matched %d article%s with unknown option in %s", X`09`09 ucount, (ucount == 1) ? "" : "s", newsgroup->name); X`09append = XRN_APPEND; X `7D X X return; X`7D X X Xstatic void XcheckKillFiles(newsgroup) Xstruct newsgroup *newsgroup; X/* X * mark articles as read if in the kill files X */ X`7B X FILE *fp; X X if ((fp = fopen(globalKillFile(), "r")) != NULL) `7B X`09killArticles(newsgroup, fp); X`09(void) fclose(fp); X `7D X X if ((fp = fopen(localKillFile(newsgroup, 0), "r")) != NULL) `7B X`09killArticles(newsgroup, fp); X`09(void) fclose(fp); X `7D X X return; X`7D X X Xstatic void XsetUpGroup(newsgroup, killfilesp) Xstruct newsgroup *newsgroup; Xint killfilesp;`09`09/* check kill files? no for jumpToNewsgroup */ X`7B X art_num first, last; X int number; X `20 X /* get the latest group information */ X if (!getgroup(newsgroup->name, &first, &last, &number)) `7B X`09return; X `7D X if (!EMPTY_GROUP(newsgroup)) `7B X`09articleArrayResync(newsgroup, first, last, number); X`09setCurrentArticle(newsgroup); X`09NextPreviousArticle = newsgroup->current; X`09getsubjectlist(newsgroup, newsgroup->current, newsgroup->last); X`09getauthorlist(newsgroup, newsgroup->current, newsgroup->last); X`09getlineslist(newsgroup, newsgroup->current, newsgroup->last); X`09if (killfilesp && (app_resources.killFiles == TRUE)) `7B X`09 checkKillFiles(newsgroup); X`09`7D X `7D X return; X`7D X X `20 Xint XgotoNewsgroup(name) Xchar *name; X/* X * goto a particular newsgroup X * invalidate the prefetched group if it is not the new one X */ X`7B X char *ptr; X struct newsgroup *newsgroup; X X#ifdef XRN_PREFETCH X PrefetchGroupMode = OKAY_TO_XRN_PREFETCH_GROUP; X#endif /* XRN_PREFETCH */ X `20 X if (!avl_lookup(NewsGroupTable, name, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", name); X`09return BAD_GROUP; X `7D X X newsgroup = (struct newsgroup *) ptr; X CurrentGroupNumber = newsgroup->newsrc; X#ifdef XRN_PREFETCH X if (CurrentGroupNumber != PrefetchedGroup) `7B X`09freePrefetchedGroupArticle(); X`09PrefetchedGroup = NO_GROUP; X `7D X#endif /* XRN_PREFETCH */ X return GOOD_GROUP; X`7D X `20 Xint XgotoNewsgroupForRead(name) Xchar *name; X/* X * goto a particular newsgroup X * invalidate the prefetched group if it is not the new one X * if all of the articles have been read, unmark the last one X */ X`7B X char *ptr; X struct newsgroup *newsgroup; X art_num i; X X#ifdef XRN_PREFETCH X PrefetchGroupMode = OKAY_TO_XRN_PREFETCH_GROUP; X#endif /* XRN_PREFETCH */ X `20 X if (!avl_lookup(NewsGroupTable, name, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", name); X`09return BAD_GROUP; X `7D X X newsgroup = (struct newsgroup *) ptr; X CurrentGroupNumber = newsgroup->newsrc; X `20 X if (EMPTY_GROUP(newsgroup)) `7B X`09mesgPane(XRN_SERIOUS, X`09 "Cannot go to the newsgroup, no articles available"); X`09return BAD_GROUP; X `7D X /* X * if there are no unread articles, find the last available one X * and mark it as unread X * X * XXX bug if the last article becomes unavailable X */ X if (unreadArticleCount(newsgroup) == 0) `7B X`09assert(newsgroup->articles != NIL(struct article)); X`09for (i = newsgroup->last; i >= newsgroup->first; i--) `7B X`09 if (!IS_UNAVAIL(newsgroup->articles`5BINDEX(i)`5D)) `7B X`09`09SET_UNREAD(newsgroup->articles`5BINDEX(i)`5D); X`09`09break; X`09 `7D X`09`7D X `7D X#ifdef XRN_PREFETCH X if (CurrentGroupNumber != PrefetchedGroup) `7B X`09freePrefetchedGroupArticle(); X`09PrefetchedGroup = NO_GROUP; X `7D X#endif /* XRN_PREFETCH */ X return GOOD_GROUP; X`7D X `20 X Xint XsetNewsgroup(name) Xchar *name; X/* X * set the current state to indicate that we're in a particular newsgroup, X * but DO NOT invalidate the prefetched group if it is not the new one X */ X`7B X char *ptr; X struct newsgroup *newsgroup; X X if (!avl_lookup(NewsGroupTable, name, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", name); X`09return BAD_GROUP; X `7D X X newsgroup = (struct newsgroup *) ptr; X CurrentGroupNumber = newsgroup->newsrc; X return GOOD_GROUP; X`7D X Xstatic struct newsgroup * XfindNewsGroupMatch(name) Xchar *name; X`7B X static char *reRet; X int i; X X#ifdef SYSV_REGEX X if ((reRet = regcmp(name, NULL)) == NULL) `7B X`09return NIL(struct newsgroup); X `7D X#else X if ((reRet = re_comp(name)) != NULL) `7B X`09return NIL(struct newsgroup); X `7D X#endif X X X for (i = 0; i < MaxGroupNumber; i++) `7B X`09struct newsgroup *newsgroup = Newsrc`5Bi`5D; X#ifdef SYSV_REGEX X`09if (regex(reRet, newsgroup->name) != NULL) `7B X`09 return newsgroup; X`09`7D X#else X`09if (re_exec(newsgroup->name)) `7B X`09 return newsgroup; X`09`7D X#endif X`09 `20 X `7D X X return NIL(struct newsgroup); X`7D X `20 X Xint XjumpToNewsgroup(name) Xchar *name; X/* X * goto a particular newsgroup X * if all of the articles have been read, unmark the last one X */ X`7B X char *ptr; X struct newsgroup *newsgroup; X art_num i; X `20 X#ifdef XRN_PREFETCH `20 X PrefetchGroupMode = DO_NOT_XRN_PREFETCH_GROUP; X#endif /* XRN_PREFETCH */ X if (!avl_lookup(NewsGroupTable, name, &ptr)) `7B X`09/* is not the full name, try regexp matching */ X`09if ((newsgroup = findNewsGroupMatch(name)) == NIL(struct newsgroup)) `7B X`09 mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", name); X`09 return BAD_GROUP; X`09`7D X `7D else `7B X`09newsgroup = (struct newsgroup *) ptr; X `7D X X CurrentGroupNumber = newsgroup->newsrc; X X if (EMPTY_GROUP(newsgroup)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot go to the newsgroup, no articles available" V); X`09return BAD_GROUP; X `7D X X#ifdef STUPIDMMU X SETARTICLES(newsgroup); X#endif X X if (!IS_SUBSCRIBED(newsgroup)) `7B X`09updateArticleArray(newsgroup); X `7D X X /* X * if there are no unread articles, find the last available one X * and mark it as unread X * X * XXX bug if the last article becomes unavailable X */ X if (unreadArticleCount(newsgroup) == 0) `7B X`09assert(newsgroup->articles != NIL(struct article)); X`09for (i = newsgroup->last; i >= newsgroup->first; i--) `7B X`09 if (!IS_UNAVAIL(newsgroup->articles`5BINDEX(i)`5D)) `7B X`09`09SET_UNREAD(newsgroup->articles`5BINDEX(i)`5D); X`09`09break; X`09 `7D X`09`7D X `7D X#ifdef XRN_PREFETCH X if (CurrentGroupNumber != PrefetchedGroup) `7B X`09freePrefetchedGroupArticle(); X`09PrefetchedGroup = NO_GROUP; X `7D X X if (PrefetchedGroup != NO_GROUP) `7B X`09CurrentGroupNumber = PrefetchedGroup; X`09PrefetchedGroup = NO_GROUP; X`09newsgroup = Newsrc`5BCurrentGroupNumber`5D; X`09return GOOD_GROUP; X `7D X#endif /* XRN_PREFETCH */ X setUpGroup(newsgroup, 0); X return GOOD_GROUP; X`7D X `20 X Xint XgetNewsgroup() X/* X * get the newsgroup X * X * returns: XRN_NOMORE - bad group X * XRN_OKAY - okay X */ X`7B X struct newsgroup *newsgroup; X X#ifdef XRN_PREFETCH `20 X if (PrefetchedGroup != NO_GROUP) `7B X`09CurrentGroupNumber = PrefetchedGroup; X`09PrefetchedGroup = NO_GROUP; X`09return XRN_OKAY; X `7D X#endif /* XRN_PREFETCH */ X newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X if (IS_SUBSCRIBED(newsgroup) && (unreadArticleCount(newsgroup) > 0)) `7B X`09setUpGroup(newsgroup, 1); X`09return XRN_OKAY; X `7D X `20 X return XRN_NOMORE; X`7D X X Xvoid XcatchUp() X/* X * mark all articles in a newsgroup as read X * X * other functions will take care of releasing resources X * X * returns: void X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num art; X X SETARTICLES(newsgroup); X for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09if (!IS_MARKED(newsgroup->articles`5BINDEX(art)`5D)) `7B X`09 SET_READ(newsgroup->articles`5BINDEX(art)`5D); X`09`7D else `7B X`09 SET_UNREAD(newsgroup->articles`5BINDEX(art)`5D); X`09 SET_UNMARKED(newsgroup->articles`5BINDEX(art)`5D); X`09`7D X `7D X return; X`7D X X Xint Xissubscribed() X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X if (IS_SUBSCRIBED(newsgroup)) `7B X`09return 1; X `7D else `7B X`09return 0; X `7D X`7D X X Xvoid Xsubscribe() X/* X * subscribe to a newsgroup X * X * returns: void X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X `20 X if (!IS_SUBSCRIBED(newsgroup)) `7B X`09SET_SUB(newsgroup); X`09updateArticleArray(newsgroup); X `7D X return; X`7D X X Xvoid Xunsubscribe() X/* X * unsubscribe to a newsgroup X * X * returns: void X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X `20 X SET_UNSUB(newsgroup); X return; X`7D X X Xstatic char * XbuildQuestion(newsgroup) Xstruct newsgroup *newsgroup; X/* X * build a string that is used as the question for what X * to do at the end of an article X * X * returns: the question in a static area X * X */ X`7B X static char dummy`5BLABEL_SIZE`5D; X art_num i; X struct article *articles = GETARTICLES(newsgroup); X long unread = 0; X ng_num number; X struct newsgroup *nextnewsgroup; X int found; X X `20 X for (i = newsgroup->first; i <= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X`09if (IS_UNREAD(articles`5Bindx`5D) && !IS_UNAVAIL(articles`5Bindx`5D)) `7B X`09 unread++; X`09`7D X `7D X`09 `20 X found = 0; X for (number = CurrentGroupNumber + 1; number < MaxGroupNumber; number++) V `7B X`09nextnewsgroup = Newsrc`5Bnumber`5D; X`09/* find a group that is subscribed to and has unread articles */ X`09if (IS_SUBSCRIBED(nextnewsgroup) && (unreadArticleCount(nextnewsgroup) > V 0)) `7B X`09 found = 1; X`09 break; X`09`7D X `7D X`09 `20 X if (found) `7B X`09if (unread <= 0) `7B X`09 (void) sprintf(dummy, "Article %ld in %s (Next group: %s)", X`09`09`09 newsgroup->current, newsgroup->name, X`09`09`09 nextnewsgroup->name); X`09`7D else `7B X`09 (void) sprintf(dummy, "Article %ld in %s (%ld remaining) (Next group: V %s)", X`09`09`09 newsgroup->current, newsgroup->name, unread, X`09`09`09 nextnewsgroup->name); X`09`7D X `7D else `7B X`09if (unread <= 0) `7B X`09 (void) sprintf(dummy, "Article %ld in %s", X`09`09`09 newsgroup->current, newsgroup->name); X`09`7D else `7B X`09 (void) sprintf(dummy, "Article %ld in %s (%ld remaining)", X`09`09`09 newsgroup->current, newsgroup->name, unread); X`09`7D X `7D X return dummy; X`7D X X X#ifdef XRN_PREFETCH X Xint XinvalidatePrefetchedGroup(newsgroup) Xstruct newsgroup *newsgroup; X/* X * invalidatePrefetchedGroup sees if a group has been prefetched, X * and if so, goes back to the old group and invalidates the prefetch X * X * returns 0 on failure, non-zero on success X */ X`7B X if (PrefetchedGroup != NO_GROUP) `7B X`09freePrefetchedGroupArticle(); X`09if (!getgroup(newsgroup->name, NIL(art_num), NIL(art_num), NIL(int))) `7B X`09 return FATAL; X`09`7D X`09PrefetchedGroup = NO_GROUP; X `7D X return OKAY; X`7D X#endif /* XRN_PREFETCH */ X Xstatic void XhandleXref(article) Xart_num article; X`7B X char *string, *ptr, *token, group`5BGROUP_NAME_SIZE`5D, *gptr; X int count, number; X struct newsgroup *newsgroup; X X `20 X xhdr(article, "xref", &string); X X if (string == NIL(char)) `7B X`09/* no xrefs */ X`09return; X `7D X X /* X * an xrefs line is of the form: X * X * host group:number group:number .... group:number X */ X X if ((ptr = index(string, ' ')) == NIL(char)) `7B X`09FREE(string); X`09return; X `7D X X while ((token = strtok(ptr, " ")) != NIL(char)) `7B X`09ptr = NIL(char); X`09 X`09count = sscanf(token, "%`5B`5E: `5D:%d", group, &number); X`09if (count != 2) `7B X`09 /* bogus entry */ X`09 continue; X`09`7D X X`09if (!avl_lookup(NewsGroupTable, group, &gptr)) `7B X`09 /* bogus group */ X`09 continue; X`09`7D X X`09/* only Xref groups that are subscribed to */ X`09 X`09newsgroup = (struct newsgroup *) gptr; X X#ifndef STUPIDMMU`09/* defer until we have to do this */ X`09SETARTICLES(newsgroup); X#endif X`09if (IS_SUBSCRIBED(newsgroup) && X`09 (number >= newsgroup->first) && (number <= newsgroup->last)) `7B X#ifdef STUPIDMMU X`09 SETARTICLES(newsgroup); X#endif X X`09 SET_READ(newsgroup->articles`5BINDEX(number)`5D); X X#ifdef STUPIDMMU X`09 /* this is horribly inefficient X`09 should splice directly into nglist X`09 or use some other representation XXX */ X`09 if (newsgroup != Newsrc`5BCurrentGroupNumber`5D) `7B X`09 updateNglist(newsgroup); X`09 CLEAR_ARTICLES(newsgroup); X`09 `7D X#endif X X`09`7D X `7D X FREE(string); X return; X`7D X Xint XgetArticleText(filename, question) Xchar **filename; Xchar **question; X/* X * get the next article X * X * returns: XRN_ERROR - article has been canceled X * XRN_OKAY - article returned X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X long indx = CURRENT; X int header, rotation; X int i; X static int artIndex = -1; X X/* X * Point to next cell in the index array, wrapping around. X */ X if (artIndex < 4) `7B X`09artIndex++; X `7D else `7B X`09artIndex = 0; X `7D X/* X * Is this article one of the last five read? If so, re-use the X * stored article array X */ X for (i = 0; i < 5; i++) `7B X`09if (PrevArtIndx`5Bi`5D == indx) `7B X`09 artIndex = i; X`09 break; X`09`7D X `7D X/* X * If No match found, we free the article text for the current X * cell in the storage array. Else, it's left in the cache. X */ X if ((PrevArtIndx`5BartIndex`5D != -1) && (PrevArtIndx`5BartIndex`5D != i Vndx)) `7B X`09if (PrevArtIndx`5BartIndex`5D < 0 `7C`7C X`09 PrevArtIndx`5BartIndex`5D > newsgroup->last - newsgroup->first) `7B X`09`09PrevArtIndx`5BartIndex`5D = -1; X`09`7D else `7B X`09 CLEAR_FILE(articles`5BPrevArtIndx`5BartIndex`5D`5D); X`09 SET_UNFETCHED(articles`5BPrevArtIndx`5BartIndex`5D`5D); X`09 PrevArtIndx`5BartIndex`5D = -1; X`09`7D X `7D X X if (IS_UNFETCHED(articles`5Bindx`5D)) `7B X#ifdef XRN_PREFETCH X`09/* X`09 * handle the case where this is a 'prev' request at the last X`09 * article and the next newsgroup has been prefetched. X`09 * X`09 * must go back to the current newsgroup so the article can be X`09 * retrieved from the server X`09 */ X`09if (!invalidatePrefetchedGroup(newsgroup)) `7B X`09 mesgPane(XRN_SERIOUS, "The newsgroup `60%s' has been deleted out from V underneath us", newsgroup->name); X`09 return XRN_ERROR; X`09`7D X#endif /* XRN_PREFETCH */ X`09 X`09/* get the article and handle unavailable ones.... */ X`09header = (IS_ALL_HEADERS(articles`5Bindx`5D) ? FULL_HEADER : NORMAL_HEADE VR); X`09rotation = (IS_ROTATED(articles`5Bindx`5D) ? ROTATED : NOT_ROTATED); X`09 X`09if ((articles`5Bindx`5D.filename = getarticle(newsgroup->current, &articl Ves`5Bindx`5D.position, header, rotation)) == NIL(char)) `7B X`09 SET_UNAVAIL(articles`5Bindx`5D); X`09 mesgPane(XRN_SERIOUS, "Can not get the next article, it was canceled V by the author or the news file system filled"); X`09 return XRN_ERROR; X`09`7D X`09SET_FETCHED(articles`5Bindx`5D); X`09 X `7D else `7B X`09if (articles`5Bindx`5D.filename == NIL(char)) `7B X`09 /* refetch the text */ X`09 SET_UNFETCHED(articles`5Bindx`5D); X`09 return getArticleText(filename, question); X`09`7D`09 `20 X `7D X X *filename = articles`5Bindx`5D.filename; X SET_READ(articles`5Bindx`5D); X *question = buildQuestion(newsgroup); X handleXref(newsgroup->current); X/* X * Save the index of this article in the X * cache array X */ X PrevArtIndx`5BartIndex`5D = indx; X return XRN_OKAY; X`7D X X Xint XtoggleHeaders(filename, question) Xchar **filename; Xchar **question; X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X long indx = CURRENT; X int i; X/* X * Find the article in the storage array and "forget" it. X */ X for (i = 0; i < 5; i++) `7B X`09if (PrevArtIndx`5Bi`5D == indx) `7B X`09 CLEAR_FILE(articles`5BCURRENT`5D); X`09 SET_UNFETCHED(articles`5BCURRENT`5D); X`09 PrevArtIndx`5Bi`5D = -1; X`09 break; X`09`7D X `7D X X if (IS_ALL_HEADERS(articles`5BCURRENT`5D)) `7B X`09SET_STRIPPED_HEADERS(articles`5BCURRENT`5D); X `7D else `7B X`09SET_ALL_HEADERS(articles`5BCURRENT`5D); X `7D`09 X CLEAR_FILE(articles`5BCURRENT`5D); X return getArticleText(filename, question); X`7D X X Xint XtoggleRotation(filename, question) Xchar **filename; Xchar **question; X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X X if (IS_ROTATED(articles`5BCURRENT`5D)) `7B X`09SET_UNROTATED(articles`5BCURRENT`5D); X `7D else `7B X`09SET_ROTATED(articles`5BCURRENT`5D); X `7D`09 X CLEAR_FILE(articles`5BCURRENT`5D); X return getArticleText(filename, question); X`7D X X X#ifdef XRN_PREFETCH X Xvoid XprefetchNextGroup() X/* X * prefetch the next group X * X * sequence of events: X * - put the server into the next group X * - get the first unread article X * - mark that we are in a new group (but don't change CurrentGroupNumber V) X * X * returns: void X */ X`7B X struct newsgroup *newsgroup; X struct article *articles; X long indx; X ng_num number; X X X if (PrefetchGroupMode == DO_NOT_XRN_PREFETCH_GROUP) `7B X`09return; X `7D X X for (number = CurrentGroupNumber + 1; number < MaxGroupNumber; number++) V `7B X`09newsgroup = Newsrc`5Bnumber`5D; X`09/* find a group that is subscribed to and has unread articles */ X`09if (IS_SUBSCRIBED(newsgroup) && (unreadArticleCount(newsgroup) > 0)) `7B X`09 break; X`09`7D X `7D X X if (number == MaxGroupNumber) `7B X`09return; X `7D X if (unreadArticleCount(newsgroup) > app_resources.prefetchMax) `7B X`09return; X `7D X X setUpGroup(newsgroup, 1); X indx = CURRENT; X articles = GETARTICLES(newsgroup); X `20 X if (articles == NIL(struct article)) `7B X`09return;`09`09/* none - must have expired... */ X `7D X `20 X /* if the current article is unfetched, fetch it */ X if (IS_UNFETCHED(articles`5Bindx`5D)) `7B X`09/* if the article can be fetched, mark it so */ X`09if ((articles`5Bindx`5D.filename = getarticle(newsgroup->current, &articl Ves`5Bindx`5D.position, NORMAL_HEADER, NOT_ROTATED)) != NIL(char)) `7B X`09 SET_FETCHED(articles`5Bindx`5D); X`09`7D X `7D X `20 X PrefetchedGroup = number; X X return; X`7D X X Xvoid XprefetchNextArticle() X/* X * prefetch the next article, will prefetch the next unread article in X * the next group at the end of the current group X * X * returns: void X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X long indx; X `20 X X /* X * if this is the last article, prefetch the next group, and the X * first article of the next group X */ X if (newsgroup->current == newsgroup->last) `7B X`09prefetchNextGroup(); X`09return; X `7D X X indx = INDEX(newsgroup->current + 1); X X if (IS_UNFETCHED(articles`5Bindx`5D)) `7B X`09/* X`09 * XXX HP Global optimizer did the wrong thing when the X`09 * assignment and the if where in the same statement`20 X`09 */ X`09articles`5Bindx`5D.filename = getarticle(newsgroup->current + 1, &article Vs`5Bindx`5D.position, NORMAL_HEADER, NOT_ROTATED); X`09if (articles`5Bindx`5D.filename == NIL(char)) `7B X`09 return; X`09`7D X`09SET_FETCHED(articles`5Bindx`5D); X`09SET_STRIPPED_HEADERS(articles`5Bindx`5D); X`09SET_UNROTATED(articles`5Bindx`5D); X`09return; X `7D X return; X`7D X X#endif /* XRN_PREFETCH */ X X X#ifdef STUPIDMMU Xvoid Xcornered(newsgroup) Xstruct newsgroup *newsgroup; X`7B X struct list *item; X art_num art; X X if (!newsgroup->nglist) `7B X fprintf(stderr, "XRN error in `60cornered': expecting nglist to be val Vid\n"); X return; X `7D X X /* process the .newsrc line */ X X for (item = newsgroup->nglist; item != NIL(struct list); item = item->ne Vxt) `7B X`09switch (item->type) `7B X`09 case SINGLE: X`09 if (item->contents.single > newsgroup->last) `7B X`09`09/* something really bad has happened, reset */ X`09`09mesgPane(XRN_SERIOUS, "Article numbering problem, marking all articles V in %s as unread", X`09`09`09 newsgroup->name); X`09`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09`09 newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR; X`09`09`7D X`09`09lsDestroy(newsgroup->nglist); X`09`09newsgroup->nglist = NIL(struct list); X`09`09return; X`09 `7D X`09 if (item->contents.single >= newsgroup->first) `7B X`09`09newsgroup->articles`5BINDEX(item->contents.single)`5D.status = ART_CLE VAR_READ; X`09 `7D X`09 break; X X`09 case RANGE: X`09 if ((item->contents.range.start > newsgroup->last) `7C`7C X`09`09(item->contents.range.end > newsgroup->last)) `7B X`09`09/* something really bad has happened, reset */ X`09`09mesgPane(XRN_SERIOUS, "Article numbering problem, marking all articles V in %s as unread\n", X`09`09`09 newsgroup->name); X`09`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09`09 newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR; X`09`09`7D X`09`09lsDestroy(newsgroup->nglist); X`09`09newsgroup->nglist = NIL(struct list); X`09`09return; X`09 `7D X`09 if (item->contents.range.start < newsgroup->first) `7B X`09`09item->contents.range.start = newsgroup->first; X`09 `7D X`09 `20 X`09 if (item->contents.range.end < newsgroup->first) `7B X`09`09break; X`09 `7D X`09 for (art = item->contents.range.start; art <= item->contents.range.en Vd; art++) `7B X`09`09newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR_READ; X`09 `7D X`09`7D X `7D X X lsDestroy(newsgroup->nglist); X newsgroup->nglist = NIL(struct list); X `20 X`7D X#endif X X Xvoid XupdateArticleArray(newsgroup) Xstruct newsgroup *newsgroup; /* newsgroup to update article array for * V/ X/* X * mark the articles in a group that have been read X * X * returns: void X * X */ X`7B X struct list *item; X art_num art; X extern void XtFree(); X#ifndef FIXED_C_NEWS_ACTIVE_FILE X int number; X#endif X X if (newsgroup->last == 0) `7B X`09return; X `7D X X if (EMPTY_GROUP(newsgroup)) `7B X`09newsgroup->articles = NIL(struct article); X`09return; X `7D X X if (newsgroup->nglist == NIL(struct list)) `7B X`09return; X `7D X X if (!IS_SUBSCRIBED(newsgroup)) `7B X`09newsgroup->articles = NIL(struct article); X`09return; X `7D X X#ifdef STUPIDMMU X if (!newsgroup->articles) `7B X`09return; X `7D X#endif X X#ifndef FIXED_C_NEWS_ACTIVE_FILE X /* get the group range to fix c-news low number problem */ X if ((XRNState & XRN_NEWS_UP) == XRN_NEWS_UP) `7B X`09(void) getgroup(newsgroup->name, &newsgroup->first, &newsgroup->last, &nu Vmber); X `7D X#endif X X SETARTICLES(newsgroup); X X /* process the .newsrc line */ X X for (item = newsgroup->nglist; item != NIL(struct list); item = item->ne Vxt) `7B X`09switch (item->type) `7B X`09 case SINGLE: X`09 if (item->contents.single > newsgroup->last) `7B X`09`09/* something really bad has happened, reset */ X`09`09mesgPane(XRN_SERIOUS, "Article numbering problem, marking all articles V in %s as unread", X`09`09`09 newsgroup->name); X`09`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09`09 if (newsgroup->articles != NIL(struct article)) X`09`09`09newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR; X`09`09`7D X`09`09lsDestroy(newsgroup->nglist); X`09`09newsgroup->nglist = NIL(struct list); X`09`09return; X`09 `7D X`09 if (item->contents.single >= newsgroup->first) `7B X`09`09newsgroup->articles`5BINDEX(item->contents.single)`5D.status = ART_CLE VAR_READ; X`09 `7D X`09 break; X X`09 case RANGE: X`09 if ((item->contents.range.start > newsgroup->last) `7C`7C X`09`09(item->contents.range.end > newsgroup->last)) `7B X`09`09/* something really bad has happened, reset */ X`09`09if (newsgroup->first != 0 && newsgroup->last !=0) X`09`09 mesgPane(XRN_SERIOUS, X`09"Article numbering problem, marking all articles in %s as unread\n", X`09`09`09 newsgroup->name); X`09`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09`09 if (newsgroup->articles != NIL(struct article)) X`09`09`09newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR; X`09`09`7D X`09`09lsDestroy(newsgroup->nglist); X`09`09newsgroup->nglist = NIL(struct list); X`09`09return; X`09 `7D X`09 if (item->contents.range.start < newsgroup->first) `7B X`09`09item->contents.range.start = newsgroup->first; X`09 `7D X`09 `20 X`09 if (item->contents.range.end < newsgroup->first) `7B X`09`09break; X`09 `7D X`09 for (art = item->contents.range.start; art <= item->contents.range.en Vd; art++) `7B X`09`09newsgroup->articles`5BINDEX(art)`5D.status = ART_CLEAR_READ; X`09 `7D X`09`7D X `7D X X lsDestroy(newsgroup->nglist); X newsgroup->nglist = NIL(struct list); X `20 X return; X`7D X X Xvoid XmarkArticleAsRead(article) Xlong article; X/* X * mark an article as read X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X SETARTICLES(newsgroup); X SET_READ(newsgroup->articles`5BINDEX((art_num) article)`5D); X SET_UNMARKED(newsgroup->articles`5BINDEX((art_num) article)`5D); X return; X`7D X X `20 Xvoid XmarkArticleAsUnread(article) Xlong article; X/* X * mark an article as unread X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X SETARTICLES(newsgroup); X SET_UNREAD(newsgroup->articles`5BINDEX((art_num) article)`5D); X SET_MARKED(newsgroup->articles`5BINDEX((art_num) article)`5D); X return; X`7D X `20 X X X/* X * handle adding items to the newsrc X * X * 3 cases X * X * 1. add to the beginning X * move 0 to MaxGroupNumber-1 down 1, update newsrc fields X * update 0 X * inc MaxGroupNumber X * 2. add to the end X * inc MaxGroupNumber X * update MaxGroupNumber-1 X * 3. add after a group (newloc is the current location of the group) X * move newloc+1 to end down 1, update newsrc fields X * update newloc X * in MaxGroupNumber X * X * And the case of 'subscribe' (assumes it moves) X * X * 1. add to the beginning X * move 0 to oldloc-1 down 1, update newsrc fields X * update 0 X * 2. add to the end X * move oldloc+1 to MaxGroupNumber-1 update 1, update newsrc fields X * upadte MaxGroupNumber-1 X * 3. add after a group X * X */ X Xint XaddToNewsrcBeginning(newGroup, status) Xchar *newGroup; Xint status; X`7B X char *ptr; X struct newsgroup *newsgroup; X ng_num i; X `20 X if (!avl_lookup(NewsGroupTable, newGroup, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", newGroup); X`09return BAD_GROUP; X `7D X `20 X newsgroup = (struct newsgroup *) ptr; X X CLEAR_NOENTRY(newsgroup); X if (status == SUBSCRIBE) `7B X`09SET_SUB(newsgroup); X `7D else `7B X`09SET_UNSUB(newsgroup); X `7D X if (newsgroup->newsrc == NOT_IN_NEWSRC) `7B X`09for (i = MaxGroupNumber - 1; i >= 0; i--) `7B X`09 Newsrc`5Bi + 1`5D = Newsrc`5Bi`5D; X`09 Newsrc`5Bi + 1`5D->newsrc = i + 1; X`09`7D X `20 X`09MaxGroupNumber++; X`09 X `7D else `7B X`09for (i = newsgroup->newsrc - 1; i >= 0; i--) `7B X`09 Newsrc`5Bi + 1`5D = Newsrc`5Bi`5D; X`09 Newsrc`5Bi + 1`5D->newsrc = i + 1; X`09`7D X `7D X `20 X newsgroup->newsrc = 0; X Newsrc`5B0`5D = newsgroup; X `20 X return GOOD_GROUP; X`7D X X Xint XaddToNewsrcEnd(newGroup, status) Xchar *newGroup; Xint status; X`7B X char *ptr; X struct newsgroup *newsgroup; X ng_num i; X `20 X if (!avl_lookup(NewsGroupTable, newGroup, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", newGroup); X`09return BAD_GROUP; X `7D X `20 X newsgroup = (struct newsgroup *) ptr; X X CLEAR_NOENTRY(newsgroup); X if (status == SUBSCRIBE) `7B X`09SET_SUB(newsgroup); X `7D else `7B X`09SET_UNSUB(newsgroup); X `7D X if (newsgroup->newsrc == NOT_IN_NEWSRC) `7B X`09MaxGroupNumber++; X `7D else `7B X`09for (i = newsgroup->newsrc + 1; i < MaxGroupNumber; i++) `7B X`09 Newsrc`5Bi - 1`5D = Newsrc`5Bi`5D; X`09 Newsrc`5Bi - 1`5D->newsrc = i - 1; X`09`7D X `7D X `20 X newsgroup->newsrc = MaxGroupNumber - 1; X Newsrc`5BMaxGroupNumber - 1`5D = newsgroup; X `20 X return GOOD_GROUP; X`7D X X Xint XaddToNewsrcAfterGroup(newGroup, afterGroup, status) Xchar *newGroup; Xchar *afterGroup; Xint status; X`7B X char *ptr; X struct newsgroup *newsgroup, *ng; X ng_num newloc, i; X `20 X if (!avl_lookup(NewsGroupTable, newGroup, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", newGroup); X`09return BAD_GROUP; X `7D X `20 X newsgroup = (struct newsgroup *) ptr; X X CLEAR_NOENTRY(newsgroup); X if (status == SUBSCRIBE) `7B X`09SET_SUB(newsgroup); X `7D else `7B X`09SET_UNSUB(newsgroup); X `7D X if (!avl_lookup(NewsGroupTable, afterGroup, &ptr)) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' does not exist", afterGroup); X`09return BAD_GROUP; X `7D X `20 X ng = (struct newsgroup *) ptr; X newloc = ng->newsrc; X X if (newloc == NOT_IN_NEWSRC) `7B X`09mesgPane(XRN_SERIOUS, "Newsgroup `60%s' is not in your .newsrc file", aft VerGroup); X`09return BAD_GROUP; X `7D X X if (newsgroup->newsrc == NOT_IN_NEWSRC) `7B X`09for (i = MaxGroupNumber - 1; i >= newloc + 1; i--) `7B X`09 Newsrc`5Bi + 1`5D = Newsrc`5Bi`5D; X`09 Newsrc`5Bi + 1`5D->newsrc = i + 1; X`09`7D X X`09MaxGroupNumber++; X`09newsgroup->newsrc = newloc + 1; X`09Newsrc`5Bnewloc + 1`5D = newsgroup; X X `7D else `7B X`09 X`09if (newloc + 1 < newsgroup->newsrc) `7B X`09 for (i = newsgroup->newsrc - 1; i >= newloc + 1; i--) `7B X`09`09Newsrc`5Bi + 1`5D = Newsrc`5Bi`5D; X`09`09Newsrc`5Bi + 1`5D->newsrc = i + 1; X`09 `7D X`09 newsgroup->newsrc = newloc + 1; X`09 Newsrc`5Bnewloc + 1`5D = newsgroup; X`09 `20 X`09`7D else if (newsgroup->newsrc < newloc + 1) `7B X`09 for (i = newsgroup->newsrc + 1; i < newloc + 1; i++) `7B X`09`09Newsrc`5Bi - 1`5D = Newsrc`5Bi`5D; X`09`09Newsrc`5Bi - 1`5D->newsrc = i - 1; X`09 `7D X`09 newsgroup->newsrc = newloc; X`09 Newsrc`5Bnewloc`5D = newsgroup; X`09`7D X`09/* if its in the correct location already, don't touch it */ X `7D X `20 X return GOOD_GROUP; X`7D X X`09 Xchar ** XgetStatusString(sorted) Xint sorted; X/* X * build and return a string array that shows the subscription status X * of all newsgroups; assumes all groups have been subscribed or X * unsubscribed to by this time. X * X * if sorted is non-zero, the list is sorted alphabetically, if X * zero, the list is returned as it exists in the newsrc file X */ X`7B X int i, count = 0; X char buffer`5B1024`5D; X avl_generator *gen; X char *key, *value; X char **ar; X X ar = ARRAYALLOC(char *, ActiveGroupsCount + 1); X X if (sorted) `7B X`09gen = avl_init_gen(NewsGroupTable, AVL_FORWARD); X X`09while (avl_gen(gen, &key, &value)) `7B X`09 struct newsgroup *newsgroup = (struct newsgroup *) value; X`09 `20 X`09 (void) sprintf(buffer, "%-60s%s", X`09`09`09 newsgroup->name, X`09`09`09 IS_SUBSCRIBED(newsgroup) ? "subscribed " : "unsubscribed"); X`09 ar`5Bcount++`5D = XtNewString(buffer); X`09`7D X`09avl_free_gen(gen); X`09 X `7D else `7B X`09for (i = 0; i < MaxGroupNumber; i++) `7B X`09 struct newsgroup *newsgroup = (struct newsgroup *) Newsrc`5Bi`5D; X`09 `20 X`09 (void) sprintf(buffer, "%-60s%s", X`09`09`09 newsgroup->name, X`09`09`09 IS_SUBSCRIBED(newsgroup) ? "subscribed " : "unsubscribed"); X`09 ar`5Bcount++`5D = XtNewString(buffer); X`09`7D X `7D`09 `20 X `20 X ar`5Bcount++`5D = NIL(char); X return ar; X`7D X X Xchar ** XgetUnSortedSubjects(mode) Xint mode; X/* X * build and return the subjects string X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X int lineLength; X art_num i; X int`09 j; X char *start, *end; X char **ar; X X if (EMPTY_GROUP(newsgroup)) `7B X`09return NIL(char *); X `7D X X if (app_resources.displayLineCount) `7B X`09lineLength = 52 + 1 + 6 + 1 + 20 + 1; X `7D else `7B X`09lineLength = 53 + 2 + 24 + 1; X `7D X X if (mode == ALL) `7B X`09newsgroup->current = NextPreviousArticle; X `7D else `7B X`09setCurrentArticle(newsgroup); X `7D X if (newsgroup->current > newsgroup->last) `7B X`09return NIL(char*); X `7D X X NextPreviousArticle = newsgroup->current; X X if ((newsgroup->last - newsgroup->current + 1) < 0) `7B X`09(void) sprintf(error_buffer, "Active File Error: last - current + 1 < 0 ( V%s)\n", X`09`09`09 newsgroup->name); X`09ehErrorExitXRN(error_buffer); X `7D X`09 X/* X * Allocate a pointer array - with an end null string followed by X * an end pointer of NULL X */ X ar = ARRAYALLOC(char *, (newsgroup->last - newsgroup->current + 3)); X for (i = 0; i <= (newsgroup->last - newsgroup->current);i++) `7B X`09ar`5Bi`5D = XtMalloc(lineLength); X `7D X *ar`5B0`5D = '\0'; X X j = 0; X for (i = newsgroup->current; i <= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X`09 X`09end = ar`5Bj`5D; X`09/* canceled and empty articles will not have a subject entry */ X`09if (articles`5Bindx`5D.subject != NIL(char)) `7B X`09 char buffer`5BLINE_LENGTH`5D; X`09 `20 X`09 /* don't put articles in the string if already read ... */ X`09 if ((mode == ALL) `7C`7C IS_UNREAD(articles`5Bindx`5D)) `7B X`09`09if (app_resources.displayLineCount) `7B X`09`09 (void) sprintf(buffer, "%-52.52s %6.6s %-20.20s", X`09`09`09`09 articles`5Bindx`5D.subject, X`09`09`09`09 (articles`5Bindx`5D.lines != NIL(char) ? X`09`09`09`09 articles`5Bindx`5D.lines : " "), X`09`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09`09`7D else `7B X`09`09 (void) sprintf(buffer, "%-53.53s %-24.24s", X`09`09`09`09 articles`5Bindx`5D.subject, X`09`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09`09`7D X`09`09(void) strcpy(end, buffer); X`09`09 X`09`09/* mark articles if they have already been read */ X`09`09if (IS_READ(articles`5Bindx`5D)) `7B X`09`09 *end = '+'; X`09`09`7D else `7B X`09`09 *end = ' '; X`09`09`7D X`09`09if (IS_SAVED(articles`5Bindx`5D)) `7B X`09`09 *(end + 1) = 'S'; X`09`09`7D else `7B X`09`09 *(end + 1) = ' '; X`09`09`7D X X`09`09j++; X`09 `7D X`09`7D else `7B X`09 /* if you can't get the subject, mark the article as unavailable */ X`09 SET_UNAVAIL(articles`5Bindx`5D); X`09`7D X `7D X X ar`5Bj`5D = XtMalloc(lineLength); X ar`5Bj`5D`5B0`5D = '\0'; X j++; X ar`5Bj`5D = NIL(char); X return ar; X`7D X X Xstruct entry `7B X char *beginning; X char *end; X int left; X int size; X int startingArticle; X`7D; X X X#define CHUNK (4 * (52 + 2 + 24 + 1 + 1)) X X Xstatic void Xvalfree(val) Xstruct entry *val; X`7B X XtFree(val->beginning); X return; X`7D X X Xstatic int XpteCompare(a, b) Xchar *a, *b; X`7B X struct entry **pa = (struct entry **) a; X struct entry **pb = (struct entry **) b; X X return (*pa)->startingArticle - (*pb)->startingArticle; X`7D X X X/* X * XXX AVL TREE is the wrong data structure here, st table would be X * better.... no need for ordering based on subject string X */ Xstatic char ** XgetSortedSubjects(mode) Xint mode; X/* X * build and return the subjects string X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X int lineLength; X art_num i; X int j; X char *start, *end; X char **ar; X X struct entry *pte; X struct entry **pteArray; X X avl_generator *gen; X char *key, *ptr, *p; X avl_tree *tree; X char curSub`5B31`5D; X int treeSize, sz, len, chunkSize; X X if (EMPTY_GROUP(newsgroup)) `7B X`09return NIL(char*); X `7D X X if (app_resources.displayLineCount) `7B X`09lineLength = 51 + 1 + 6 + 1 + 20 + 1; X `7D else `7B X`09lineLength = 52 + 2 + 24 + 1; X `7D X`09 X tree = avl_init_table(utSubjectCompare); X X if (mode == ALL) `7B X`09newsgroup->current = NextPreviousArticle; X `7D else `7B X`09setCurrentArticle(newsgroup); X `7D X if (newsgroup->current > newsgroup->last) `7B X`09return NIL(char*); X `7D X X NextPreviousArticle = newsgroup->current; X X if ((newsgroup->last - newsgroup->current + 1) < 0) `7B X`09(void) sprintf(error_buffer, "Active File Error: last - current + 1 < 0 ( V%s)\n", X`09`09`09 newsgroup->name); X`09ehErrorExitXRN(error_buffer); X `7D X`09 X /*`20 X * build the subject groups`20 X */ X for (i = newsgroup->current; i <= newsgroup->last; i++) `7B X`09long indx = INDEX(i); X X`09/* canceled and empty articles will not have a subject entry */ X`09if (articles`5Bindx`5D.subject != NIL(char)) `7B X`09 char buffer`5BLINE_LENGTH`5D; X X`09 /* don't put articles in the string if already read ... */ X`09 if ((mode == ALL) `7C`7C IS_UNREAD(articles`5Bindx`5D)) `7B X`09`09if (app_resources.displayLineCount) `7B X`09`09 (void) sprintf(buffer, "%-51.51s %6.6s %-20.20s\n", X`09`09`09`09 articles`5Bindx`5D.subject, X`09`09`09`09 (articles`5Bindx`5D.lines != NIL(char) ? X`09`09`09`09 articles`5Bindx`5D.lines : " "), X`09`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09`09`7D else `7B X`09`09 (void) sprintf(buffer, "%-52.52s %-24.24s\n", X`09`09`09`09 articles`5Bindx`5D.subject, X`09`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09`09`7D X X`09`09(void) strncpy(curSub, getSubject(i), sizeof(curSub)); X`09`09/* mark articles if they have already been read */ X`09`09if (IS_READ(articles`5Bindx`5D)) `7B X`09`09 buffer`5B0`5D = '+'; X`09`09`7D else `7B X`09`09 buffer`5B0`5D = ' '; X`09`09`7D X`09`09if (IS_SAVED(articles`5Bindx`5D)) `7B X`09`09 buffer`5B1`5D = 'S'; X`09`09`7D else `7B X`09`09 buffer`5B1`5D = ' '; X`09`09`7D X`09`09curSub`5Bsizeof(curSub)-1`5D = '\0'; X X`09`09if (avl_lookup(tree, curSub, &ptr)) `7B X`09`09 /* add to the end */ X`09`09 pte = (struct entry *) ptr; X`09`09 if (lineLength >= pte->left) `7B X`09`09`09/* grow the string */ X`09`09`09pte->size += CHUNK; X`09`09`09pte->left += CHUNK; X`09`09`09sz = pte->end - pte->beginning; X`09`09`09pte->beginning = XtRealloc(pte->beginning, pte->size); X`09`09`09pte->end = pte->beginning + sz; X`09`09`09*(pte->end) = '\0'; X`09`09 `7D X`09`09 (void) strcpy(pte->end, buffer); X`09`09 pte->end += lineLength; X`09`09 pte->left -= lineLength; X`09`09 *(pte->end) = '\0'; X`09`09`7D else `7B X`09`09 /* create new */ X`09`09 pte = ALLOC(struct entry); X`09`09 pte->startingArticle = i; X`09`09 pte->beginning = ARRAYALLOC(char, CHUNK); X`09`09 (void) strcpy(pte->beginning, buffer); X`09`09 pte->size = CHUNK; X`09`09 pte->left = pte->size - lineLength; X`09`09 pte->end = pte->beginning + lineLength; X`09`09 *(pte->end) = '\0'; X`09`09 (void) avl_insert(tree, XtNewString(curSub), (char *) pte); X`09`09`7D X`09 `7D X`09`7D else `7B X`09 /* if you can't get the subject, mark the article as unavailable */ X`09 SET_UNAVAIL(articles`5Bindx`5D); X`09`7D X `7D X X i = 0; X treeSize = avl_count(tree); X if (treeSize == 0) `7B`09`09/* No articles */ X`09avl_free_table(tree, XtFree, valfree); X`09return NIL(char*); X `7D X X pteArray = ARRAYALLOC(struct entry *, treeSize); X gen = avl_init_gen(tree, AVL_FORWARD); X while (avl_gen(gen, &key, &ptr)) `7B X`09pteArray`5Bi++`5D = (struct entry *) ptr; X `7D X avl_free_gen(gen); X X /* sort by article number */ X qsort((char *) pteArray, treeSize, sizeof(struct pte *), pteCompare); X X/* X * Allocate a pointer array - with an end null string followed by X * an end pointer of NULL X */ X X ar = ARRAYALLOC(char *, (newsgroup->last - newsgroup->current + 3)); X for (i = 0; i <= (newsgroup->last - newsgroup->current);i++) `7B X`09ar`5Bi`5D = XtMalloc(lineLength); X `7D X *ar`5B0`5D = '\0'; X X j = 0; X for (i = 0; i < treeSize; i++) `7B X`09ptr = pteArray`5Bi`5D->beginning; X`09chunkSize = pteArray`5Bi`5D->end - pteArray`5Bi`5D->beginning; X`09while (chunkSize > 0) `7B X`09 strncpy(ar`5Bj`5D, ptr, lineLength); X`09 p = ar`5Bj`5D + lineLength - 1; X`09 *p = '\0'; X`09 chunkSize -= lineLength; X`09 ptr += lineLength; X`09 j++; X`09`7D X `7D X X avl_free_table(tree, XtFree, valfree); X FREE(pteArray); X ar`5Bj`5D = XtMalloc(lineLength); X ar`5Bj`5D`5B0`5D = '\0'; X j++; X ar`5Bj`5D = NIL(char); X return ar; X`7D X X Xchar ** XgetSubjects(mode) Xint mode; X`7B X if (app_resources.sortedSubjects) `7B X`09return getSortedSubjects(mode); X `7D else `7B X`09return getUnSortedSubjects(mode); X `7D X`7D X Xvoid XgotoArticle(article) Xlong article; X/* X * set the internal pointers to a particular article X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X newsgroup->current = (art_num) article; X NextPreviousArticle = (art_num) article; X return; X`7D X X Xint XcheckArticle(art) Xart_num art; X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X /* Check if requested article is not available */ X if (art < newsgroup->first `7C`7C art > newsgroup->last) `7B X return XRN_ERROR; X `7D X return XRN_OKAY; X`7D `20 X X Xvoid XbogusNewsgroup() X/* X * first and last are the same and there are no articles X * X * representation bug in the news system active file X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X X if (newsgroup->articles != NIL(struct article)) `7B X`09SET_READ(newsgroup->articles`5BLAST`5D); X`09SET_UNAVAIL(newsgroup->articles`5BLAST`5D); X `7D X X mesgPane(XRN_INFO, "No articles in `60%s', probably killed or canceled", V newsgroup->name); X `20 X return; X`7D X X X#define STRIPLEADINGSPACES for (; *start == ' '; start++); X#define STRIPENDINGSPACES for ( ; *end == ' '; *end = '\0', end--); X Xstatic char * Xstrip(str) Xchar *str; X`7B X register char *start, *end, *ptr; X static char work`5BBUFFER_SIZE`5D; X X if (str == NIL(char)) `7B X`09return NIL(char); X `7D X (void) strncpy(work, str, BUFFER_SIZE); X start = work; X work`5BBUFFER_SIZE - 1`5D = '\0'; X end = index(start, '\0') - 1; X X /* a ':' separates the article number from the subject line */ X start = index(start, ':'); X assert(start != NIL(char)); X start++; X X STRIPLEADINGSPACES; X X /* strip leading '`5BrR`5D`5BeE`5D: ' and 'Re`5EN: ' */ X while (STREQN(start, "Re: ", 4) `7C`7C X`09 STREQN(start, "RE: ", 4) `7C`7C X`09 STREQN(start, "re: ", 4) `7C`7C X`09 STREQN(start, "Re: ", 4)) `7B X`09start += 4; X`09 X`09/* strip leading spaces after '`5BrR`5De: ' */ X`09STRIPLEADINGSPACES; X `7D X X while (STREQN(start, "Re`5E", 3)) `7B X`09start += 3; X`09ptr = index(start, ':'); X`09if (ptr != NIL(char)) `7B X`09 start = ptr + 1; X`09`7D X`09STRIPLEADINGSPACES; X `7D X X STRIPENDINGSPACES; X X return start; X`7D X X Xchar * XgetSubject(article) Xlong article; X/* X * return the subject of an article with trailing/leading spaces stripped, X * leading '`5BrR`5De: ' stripped, and trailing ' (`5BwW`5Das: ' stripped X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X art_num artnum = (art_num) article; X X SETARTICLES(newsgroup); X X return strip(newsgroup->articles`5BINDEX(artnum)`5D.subject); X`7D X X Xchar * XgetAuthor(article) Xlong article; X/* X * return the author of an article X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X X return articles`5BINDEX((art_num) article)`5D.author; X`7D X Xchar * XgetPrevSubject() X/* X * get the previous subject (article number is NextPreviousArticle). X * only called when going off the top of the subject string X * X * returns a point to a static area X * X * NextPreviousArticle is set to current on building the subject string. X * NextPreviousArticle is decremented by this routine. X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X struct article *articles = GETARTICLES(newsgroup); X static char buffer`5BBUFFER_SIZE`5D; X X#ifdef XRN_PREFETCH X if (!invalidatePrefetchedGroup(newsgroup)) `7B X`09mesgPane(XRN_SERIOUS, "The newsgroup has been deleted out from underneath V us"); X`09return NIL(char); X `7D X#endif /* XRN_PREFETCH */ X X /* search for the next available article in the reverse direction */ X for (NextPreviousArticle--; X`09 NextPreviousArticle >= newsgroup->first; NextPreviousArticle--) `7B X`09long indx = INDEX(NextPreviousArticle); X`09 X#ifdef notdef X`09(void) sprintf(error_buffer, "searching article %ld", NextPreviousArticle V); X`09infoNow(error_buffer); X#endif X X`09/* get the subject (and author) if it does not already exist */ X`09if (articles`5Bindx`5D.subject == NIL(char)) `7B X X`09 /* get the subject and a few more */ X`09 getsubjectlist(newsgroup, X`09`09`09 MAX(newsgroup->first, NextPreviousArticle - SUBJECTS), X`09`09`09 NextPreviousArticle); X`09`7D X X`09if (articles`5Bindx`5D.author == NIL(char)) `7B X`09 getauthorlist(newsgroup, X`09`09`09 MAX(newsgroup->first, NextPreviousArticle - SUBJECTS), X`09`09`09 NextPreviousArticle); X X`09`7D X X`09if (articles`5Bindx`5D.lines == NIL(char)) `7B X`09 getlineslist(newsgroup, X`09`09`09 MAX(newsgroup->first, NextPreviousArticle - SUBJECTS), X`09`09`09 NextPreviousArticle); X`09`7D X X`09if (articles`5Bindx`5D.subject) `7B X`09 if (app_resources.displayLineCount) `7B X`09`09(void) sprintf(buffer, "%-51.51s %6.6s %-20.20s", X`09`09`09 articles`5Bindx`5D.subject, X`09`09`09 (articles`5Bindx`5D.lines != NIL(char) ? X`09`09`09 articles`5Bindx`5D.lines : " "), X`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09 `7D else `7B X`09`09(void) sprintf(buffer, "%-52.52s %-24.24s", X`09`09`09 articles`5Bindx`5D.subject, X`09`09`09 (articles`5Bindx`5D.author == NIL(char) ? X`09`09`09`09 "(none)" : articles`5Bindx`5D.author)); X`09 `7D X X`09 return buffer; X`09`7D X`09/* continue on */ X `7D X X return NIL(char); X`7D X X Xstatic art_num justInCase; /* old NextPreviousArticle, just in case the se Varch fails */ X Xvoid XstartSearch() X/* the front-end is about to do an article search, save the starting point * V/ X`7B X justInCase = NextPreviousArticle; X return; X`7D X X Xvoid XfailedSearch() X/* the article search failed, restore the original point */ X`7B X NextPreviousArticle = justInCase; X return; X`7D X X Xvoid XfillUpArray(art) Xart_num art; X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X X if (art < newsgroup->current) `7B X`09getsubjectlist(newsgroup, art, newsgroup->current - 1); X`09getauthorlist(newsgroup, art, newsgroup->current - 1); X`09getlineslist(newsgroup, art, newsgroup->current - 1); X `7D X return; X`7D X X X/* X * getinfofromfile`09Get a string from a named file X *`09`09`09Handle white space and comments. X * X *`09Parameters:`09"file" is the name of the file to read. X * X *`09Returns:`09Pointer to static data area containing the X *`09`09`09first non-ws/comment line in the file. X *`09`09`09NULL on error (or lack of entry in file). X * X *`09Side effects:`09None. X */ X Xchar * Xgetinfofromfile(file) Xchar`09*file; X`7B X`09register FILE`09*fp; X`09register char`09*cp; X`09static char`09buf`5B256`5D; X`09char`09`09*getenv(); X X`09if (file == NULL) X`09`09return (NULL); X X`09fp = fopen(file, "r"); X`09if (fp == NULL) X`09`09return (NULL); X X`09while (fgets(buf, sizeof (buf), fp) != NULL) `7B X`09`09if (*buf == '\n' `7C`7C *buf == '#') X`09`09`09continue; X`09`09cp = index(buf, '\n'); X`09`09if (cp) X`09`09`09*cp = '\0'; X`09`09(void) fclose(fp); X`09`09return (buf); X`09`7D X X`09(void) fclose(fp); X`09return (NULL);`09`09`09 /* No entry */ X`7D X $ CALL UNPACK INTERNALS.C;1 609431282 $ create 'f' X#ifndef INTERNALS_H X#define INTERNALS_H X X/* X * $Header: /users/ricks/xrn/src/RCS/internals.h,v 1.10 90/09/29 01:10:43 ri Vcks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X X/* X * internals.h: news system interface X */ X X#define XRN_ERROR 0 X#define XRN_NOMORE 0 X#define XRN_OKAY 1 X X/*`20 X * kill file stuff X */ X#define KILL_GLOBAL 0 X#define KILL_LOCAL 1 Xextern void killItem(/* char *item, int type */); X X/* X * routines for adding newsgroups to the newsrc file X */ X`20 X/* 'status' values for the 'add' functions */ X#define SUBSCRIBE 1 X#define UNSUBSCRIBE 0 X Xextern int addToNewsrcAfterGroup(/* char *newGroup, *afterGroup, int status V */); Xextern int addToNewsrcEnd(/* char *newGroup, int status */); Xextern int addToNewsrcBeginning(/* char *newGroup, int status */); X X X/* X * routines for doing newsgroup management X */ X X/* jump/goto/add newsgroup codes */ X#define BAD_GROUP -1 X#define GOOD_GROUP 1 X X/* set the internal group to 'name', with prefetch invalidation */ Xextern int gotoNewsgroup(/* char *name */); Xextern int gotoNewsgroupForRead(/* char *name */); X/* same thing, but without prefetch invalidation */ Xextern int setNewsgroup(/* char *name */); X X/* set the internal group to 'name', and if all of the articles are read, un Vmark the last one */ Xextern int jumpToNewsgroup(/* char *name */); X X/* getNewsgroup returns 0 if a bad group, 1 if okay */ Xextern int getNewsgroup(); X X#ifdef XRN_PREFETCH X/* X * invalidatePrefetchedGroup sees if a group has been prefetched, X * and if so, goes back to the old group and invalidates the prefetch X * X * returns 0 on failure, non-zero on success X */ Xextern int invalidatePrefetchedGroup(/* struct newsgroup *newsgroup */); X#endif /* XRN_PREFETCH */ X X/* subscribe to the current newsgroup */ Xextern void subscribe(); X/* unsubscribe to the current newsgroup */ Xextern void unsubscribe(); X X/* check subscription status */ Xextern int issubscribed(); X X/* updates the .newsrc file so that the current newsgroup is marked as all r Vead */ Xextern void catchUp(); X X X/* X * routines for doing article management X */ X Xextern void gotoArticle(/* long article */); X Xextern int getArticleText(/* char **filename, char **question */); Xextern int toggleHeaders(/* char **filename, char **question */); Xextern int toggleRotation(/* char **filename, char **question */); X X#ifdef XRN_PREFETCH Xextern void prefetchNextArticle(); X#endif /* XRN_PREFETCH */ X X/* mark articles */ Xextern void markArticleAsRead(/* long article */); Xextern void markArticleAsUnread(/* long article */); X X/* get a single subject line, stripped of leading/trailing spaces, Re: */ Xextern char *getSubject(/* long article */); Xextern char *getAuthor(/* long article */); X X/* get the subject line for the previous subject (and get the article too) * V/ X/* only called when going off the top of the subject string */ Xextern char *getPrevSubject(); X Xextern void startSearch(); Xextern void failedSearch(); X X/* X * information gathering routines X */ X Xextern void checkLock(); Xextern void removeLock(); X `20 X/* read the .newsrc file, find out what to read */ Xextern void initializeNews(/* char *newsrcfile */); X X/* query the server for new information */ Xextern void rescanServer(); X X/* return the new newsgroups string */ Xextern char **newGroups(); X X/* return the unread newsgroups string */ Xextern char **unreadGroups(); X X/* return the subject string */ X#define ALL 0 X#define UNREAD 1 Xextern char **getSubjects(/* int mode */); X X/* build and return the status string */ Xextern char **getStatusString(); X Xextern void bogusNewsgroup(); X Xextern void releaseNewsgroupResources(); Xextern void clearArtCache(); X X#ifdef XRN_PREFETCH Xextern void freePrefetchedGroupArticle(); X#endif /* XRN_PREFETCH */ X Xextern void fillUpArray(/* art_num art */); X X#define GETARTICLES(newsgroup) (newsgroup->articles) ? (newsgroup->articles) V : getarticles(newsgroup) Xstruct article *getarticles(); X X#endif /* INTERNALS_H */ $ CALL UNPACK INTERNALS.H;1 1297033265 $ create 'f' X/*LINTLIBRARY*/ X#ifndef lint Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn-11/src/RCS/list.c,v V 1.4 89/10/03 16:08:42 ricks Exp $"; X#endif X X/* X * List Management Package X * X * Copyright (c) 1988, 1989, David S. Harrison. All rights reserved. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * List Management Package X *`20 X * David Harrison X * University of California, Berkeley, 1985 X * X * This package implements a simple generic linked list data type. It X * uses a doubly linked list structure and provides some standard operations X * for storing and retrieving data from the list. X */ X X#ifndef VMS X#include X#else X#include X#endif X#include "list.h"`09`09/* Self declaration */ X X#define alloc(type)`09(type *) XtMalloc(sizeof(type)) X#define NIL(type)`09(type *) 0 Xtypedef char *Pointer; X X/* X * The list identifier is in reality a pointer to the following list X * descriptor structure. Lists are doubly linked with both top and X * bottom pointers stored in the list descriptor. The length X * of the list is also stored in the descriptor. X */ X Xtypedef struct list_elem `7B`09/* One list element */ X struct list_desc *mainList;`09/* List descriptor */ X struct list_elem *prevPtr;`09/* Previous element */ X struct list_elem *nextPtr;`09/* Next list element */ X Pointer userData;`09`09/* User pointer */ X`7D lsElem; X Xtypedef struct list_desc `7B`09/* List descriptor record */ X lsElem *topPtr, *botPtr;`09/* Pointer to top and bottom of list */ X int length;`09`09`09/* Length of list */ X`7D lsDesc; X X/* X * Generators are in reality pointers to the generation descriptor`20 X * defined below. A generator has a current spot which is *between* X * two items. Thus, a generator consists of two pointers: record X * before spot and record after spot. A pointer to the main list X * is included so the top and bottom pointers of the list can be X * modified if needed. X */ X Xtypedef struct gen_desc `7B`09/* Generator Descriptor `09*/ X lsDesc *mainList;`09`09/* Pointer to list descriptor */ X lsElem *beforeSpot;`09`09/* Item before the current spot */ X lsElem *afterSpot;`09`09/* Item after the current spot */ X`7D lsGenInternal; X X/* X * Handles are in reality pointers to lsElem records. They are X * cheap to generate and need not be disposed. X */ X X X`0C X/* X * List Creation and Deletion X */ X XlsList lsCreate() X/* X * Creates a new linked list and returns its handle. The handle is used X * by all other list manipulation routines and should not be discarded. X */ X`7B X lsDesc *newList; X X newList = alloc(lsDesc); X newList->topPtr = newList->botPtr = NIL(lsElem); X newList->length = 0; X return( (lsList) newList ); X`7D X XlsStatus lsDestroy(list, delFunc) XlsList list;`09`09`09/* List to destroy */ Xvoid (*delFunc)();`09`09/* Routine to release user data */ X/* X * Frees all resources associated with the specified list. It frees memory X * associated with all elements of the list and then deletes the list. X * User data is released by calling 'delFunc' with the pointer as the X * argument. Accessing a list after its destruction is a no-no. X */ X`7B X lsDesc *realList; X lsElem *indx, *temp; X X realList = (lsDesc *) list; X /* Get rid of elements */ X indx = realList->topPtr; X while (indx != NIL(lsElem)) `7B X`09temp = indx; indx = indx->nextPtr; X`09if (delFunc) X`09 (*delFunc)(temp->userData); X`09XtFree((Pointer) temp); X `7D X /* Get rid of descriptor */ X XtFree((Pointer) realList); X return(LS_OK); X`7D X X`0C X X/* X * Adding New Elements to the Beginning and End of a List X */ X XlsStatus lsNewBegin(list, data, itemHandle) XlsList list;`09`09`09/* List to add element to */ XPointer data;`09`09`09/* Arbitrary pointer to data */ XlsHandle *itemHandle;`09`09/* Handle to data (returned) */ X/* X * Adds a new item to the start of a previously created linked list. X * If 'itemHandle' is non-zero, it will be filled with a handle X * which can be used to generate a generator positioned at the X * item without generating through the list. X */ X`7B X lsDesc *realList = (lsDesc *) list; X lsElem *newElem; X X newElem = alloc(lsElem); X newElem->userData = data; X newElem->nextPtr = realList->topPtr; X newElem->prevPtr = NIL(lsElem); X newElem->mainList = realList; X if (realList->topPtr == NIL(lsElem)) `7B X`09/* The new item is both the top and bottom element */ X`09realList->botPtr = newElem; X `7D else `7B X`09/* There was a top element - make its prev correct */ X`09realList->topPtr->prevPtr = newElem; X `7D X realList->topPtr = newElem; X realList->length += 1; X if (itemHandle) *itemHandle = (lsHandle) newElem; X return(LS_OK); X`7D X XlsStatus lsNewEnd(list, data, itemHandle) XlsList list;`09`09`09/* List to append element to */ XPointer data;`09`09`09/* Arbitrary pointer to data */ XlsHandle *itemHandle;`09`09/* Handle to data (returned) */ X/* X * Adds a new item to the end of a previously created linked list. X * This routine appends the item in constant time and X * can be used freely without guilt. X */ X`7B X lsDesc *realList = (lsDesc *) list; X lsElem *newElem; X X newElem = alloc(lsElem); X newElem->userData = data; X newElem->prevPtr = realList->botPtr; X newElem->nextPtr = NIL(lsElem); X newElem->mainList = realList; X if (realList->topPtr == NIL(lsElem)) X realList->topPtr = newElem; X if (realList->botPtr != NIL(lsElem)) X realList->botPtr->nextPtr = newElem; X realList->botPtr = newElem; X realList->length += 1; X if (itemHandle) *itemHandle = (lsHandle) newElem; X return(LS_OK); X`7D X`0C X/* X * Retrieving the first and last items of a list X */ X XlsStatus lsFirstItem(list, data, itemHandle) XlsList list;`09`09`09/* List to get item from */ XPointer *data;`09`09`09/* User data (returned) */ XlsHandle *itemHandle;`09/* Handle to data (returned) */ X/* X * Returns the first item in the list. If the list is empty, X * it returns LS_NOMORE. Otherwise, it returns LS_OK. X * If 'itemHandle' is non-zero, it will be filled with a X * handle which may be used to generate a generator. X */ X`7B X lsDesc *realList = (lsDesc *) list; X X if (realList->topPtr != NIL(lsElem)) `7B X`09*data = realList->topPtr->userData; X`09if (itemHandle) *itemHandle = (lsHandle) (realList->topPtr); X`09return(LS_OK); X `7D else `7B X`09*data = (Pointer) 0; X`09if (itemHandle) *itemHandle = (lsHandle) 0; X`09return(LS_NOMORE); X `7D X`7D X XlsStatus lsLastItem(list, data, itemHandle) XlsList list;`09`09`09/* List to get item from */ XPointer *data;`09`09`09/* User data (returned) */ XlsHandle *itemHandle;`09/* Handle to data (returned) */ X/* X * Returns the last item of a list. If the list is empty, X * the routine returns LS_NOMORE. Otherwise, 'data' will X * be set to the last item and the routine will return LS_OK. X * If 'itemHandle' is non-zero, it will be filled with a X * handle which can be used to generate a generator postioned X * at this item. X */ X`7B X lsDesc *realList = (lsDesc *) list; X X if (realList->botPtr != NIL(lsElem)) `7B X`09*data = realList->botPtr->userData; X`09if (itemHandle) *itemHandle = (lsHandle) (realList->botPtr); X`09return(LS_OK); X `7D else `7B X`09*data = (Pointer) 0; X`09if (itemHandle) *itemHandle = (lsHandle) 0; X`09return(LS_NOMORE); X `7D X`7D X X`0C X X/* Length of a list */ X Xint lsLength(list) XlsList list;`09`09`09/* List to get the length of */ X/* X * Returns the length of the list. The list must have been X * already created using lsCreate. X */ X`7B X lsDesc *realList = (lsDesc *) list; X X return(realList->length); X`7D X X`0C X X/* X * Deleting first and last items of a list X */ X XlsStatus lsDelBegin(list, data) XlsList list;`09`09`09/* List to delete item from */ XPointer *data;`09`09`09/* First item (returned) */ X/* X * This routine deletes the first item of a list. The user X * data associated with the item is returned so the caller X * may dispose of it. Returns LS_NOMORE if there is no X * item to delete. X */ X`7B X lsDesc *realList = (lsDesc *) list; X lsElem *temp; X X if (realList->topPtr == NIL(lsElem)) `7B X`09/* Nothing to delete */ X`09*data = (Pointer) 0; X`09return LS_NOMORE; X `7D else `7B X`09*data = realList->topPtr->userData; X`09temp = realList->topPtr; X`09realList->topPtr = realList->topPtr->nextPtr; X`09if (temp->nextPtr != NIL(lsElem)) `7B X`09 /* There is something after the first item */ X`09 temp->nextPtr->prevPtr = NIL(lsElem); X`09`7D else `7B X`09 /* Nothing after it - bottom becomes null as well */ X`09 realList->botPtr = NIL(lsElem); X`09`7D X`09XtFree((Pointer) temp); X`09realList->length -= 1; X `7D X return LS_OK; X`7D X X XlsStatus lsDelEnd(list, data) XlsList list;`09`09`09/* List to delete item from */ XPointer *data;`09`09`09/* Last item (returned) */ X/* X * This routine deletes the last item of a list. The user X * data associated with the item is returned so the caller X * may dispose of it. Returns LS_NOMORE if there is nothing X * to delete. X */ X`7B X lsDesc *realList = (lsDesc *) list; X lsElem *temp; X X if (realList->botPtr == NIL(lsElem)) `7B X`09/* Nothing to delete */ X`09*data = (Pointer) 0; X`09return LS_NOMORE; X `7D else `7B X`09*data = realList->botPtr->userData; X`09temp = realList->botPtr; X`09realList->botPtr = realList->botPtr->prevPtr; X`09if (temp->prevPtr != NIL(lsElem)) `7B X`09 /* There is something before the last item */ X`09 temp->prevPtr->nextPtr = NIL(lsElem); X`09`7D else `7B X`09 /* Nothing before it - top becomes null as well */ X`09 realList->topPtr = NIL(lsElem); X`09`7D X`09XtFree((Pointer) temp); X`09realList->length -= 1; X `7D X return LS_OK; X`7D X X`0C X/* X * List Generation Routines X * X * nowPtr is the element just before the next one to be generated X */ X XlsGen lsStart(list) XlsList list;`09`09`09/* List to generate items from */ X/* X * This routine defines a generator which is used to step through X * each item of the list. It returns a generator handle which should X * be used when calling lsNext, lsPrev, lsInBefore, lsInAfter, lsDelete, X * or lsFinish. X */ X`7B X lsDesc *realList = (lsDesc *) list; X lsGenInternal *newGen; X X newGen = alloc(lsGenInternal); X newGen->mainList = realList; X newGen->beforeSpot = NIL(lsElem); X newGen->afterSpot = realList->topPtr; X return ( (lsGen) newGen ); X`7D X XlsGen lsGenHandle(itemHandle, data, option) XlsHandle itemHandle;`09`09/* Handle of an item */ XPointer *data;`09`09`09/* Data associated with item */ Xint option;`09`09`09/* LS_BEFORE or LS_AFTER */ X/* X * This routine produces a generator given a handle. Handles X * are produced whenever an item is added to a list. The generator X * produced by this routine may be used when calling any of`20 X * the standard generation routines. NOTE: the generator X * should be freed using lsFinish. The 'option' parameter X * determines whether the generator spot is before or after X * the handle item. X */ X`7B X lsElem *realItem = (lsElem *) itemHandle; X lsGenInternal *newGen; X X newGen = alloc(lsGenInternal); X newGen->mainList = realItem->mainList; X *data = realItem->userData; X if (option & LS_BEFORE) `7B X`09newGen->beforeSpot = realItem->prevPtr; X`09newGen->afterSpot = realItem; X `7D else if (option & LS_AFTER) `7B X`09newGen->beforeSpot = realItem; X`09newGen->afterSpot = realItem->nextPtr; X `7D else `7B X`09XtFree((Pointer) newGen); X`09newGen = (lsGenInternal *) 0; X `7D X return ( (lsGen) newGen ); X`7D X X XlsList lsQueryHandle(itemHandle) XlsHandle itemHandle;`09`09/* Handle of an item */ X/* X * This routine returns the associated list of the specified X * handle. Returns 0 if there were problems. X */ X`7B X lsElem *realHandle = (lsElem *) itemHandle; X X if (realHandle) `7B X`09return (lsList) realHandle->mainList; X `7D else `7B X`09return (lsList) 0; X `7D X`7D X XlsStatus lsNext(generator, data, itemHandle) XlsGen generator;`09`09/* Generator handle */ XPointer *data;`09`09`09/* User data (return) */ XlsHandle *itemHandle;`09`09/* Handle to item (return) */ X/* X * Generates the item after the item previously generated by lsNext X * or lsPrev. It returns a pointer to the user data structure in 'data'. ` V20 X * 'itemHandle' may be used to get a generation handle without X * generating through the list to find the item. If there are no more`20 X * elements to generate, the routine returns LS_NOMORE (normally it`20 X * returns LS_OK). lsNext DOES NOT automatically clean up after all`20 X * elements have been generated. lsFinish must be called explicitly to do t Vhis. X */ X`7B X register lsGenInternal *realGen = (lsGenInternal *) generator; X X if (realGen->afterSpot == NIL(lsElem)) `7B X`09/* No more stuff to generate */ X`09*data = (Pointer) 0; X`09if (itemHandle) *itemHandle = (lsHandle) 0; X`09return LS_NOMORE; X `7D else `7B X`09*data = realGen->afterSpot->userData; X`09if (itemHandle) *itemHandle = (lsHandle) (realGen->afterSpot); X`09/* Move the pointers down one */ X`09realGen->beforeSpot = realGen->afterSpot; X`09realGen->afterSpot = realGen->afterSpot->nextPtr; X`09return LS_OK; X `7D X`7D X X XlsStatus lsPrev(generator, data, itemHandle) XlsGen generator;`09`09/* Generator handle */ XPointer *data;`09`09`09/* User data (return) */ XlsHandle *itemHandle;`09/* Handle to item (return) */ X/* X * Generates the item before the item previously generated by lsNext X * or lsPrev. It returns a pointer to the user data structure in 'data'. ` V20 X * 'itemHandle' may be used to get a generation handle without X * generating through the list to find the item. If there are no more`20 X * elements to generate, the routine returns LS_NOMORE (normally it`20 X * returns LS_OK). lsPrev DOES NOT automatically clean up after all`20 X * elements have been generated. lsFinish must be called explicitly to do t Vhis. X */ X`7B X register lsGenInternal *realGen = (lsGenInternal *) generator; X X if (realGen->beforeSpot == NIL(lsElem)) `7B X`09/* No more stuff to generate */ X`09*data = (Pointer) 0; X`09if (itemHandle) *itemHandle = (lsHandle) 0; X`09return LS_NOMORE; X `7D else `7B X`09*data = realGen->beforeSpot->userData; X`09if (itemHandle) *itemHandle = (lsHandle) (realGen->afterSpot); X`09/* Move the pointers down one */ X`09realGen->afterSpot = realGen->beforeSpot; X`09realGen->beforeSpot = realGen->beforeSpot->prevPtr; X`09return LS_OK; X `7D X X`7D X XlsStatus lsInBefore(generator, data, itemHandle) XlsGen generator;`09`09/* Generator handle */ XPointer data;`09`09`09/* Arbitrary pointer to data */ XlsHandle *itemHandle;`09`09/* Handle to item (return) */ X/* X * Inserts an element BEFORE the current spot. The item generated X * by lsNext will be unchanged; the inserted item will be generated X * by lsPrev. This modifies the list. 'itemHandle' may be used at`20 X * a later time to produce a generation handle without generating`20 X * through the list. X */ X`7B X lsGenInternal *realGen = (lsGenInternal *) generator; X lsElem *newElem; X X if (realGen->beforeSpot == NIL(lsElem)) `7B X`09/* Item added to the beginning of the list */ X`09(void) lsNewBegin((lsList) realGen->mainList, data, itemHandle); X`09realGen->beforeSpot = realGen->mainList->topPtr; X`09return LS_OK; X `7D else if (realGen->afterSpot == NIL(lsElem)) `7B X`09/* Item added to the end of the list */ X`09(void) lsNewEnd((lsList) realGen->mainList, data, itemHandle); X`09realGen->afterSpot = realGen->mainList->botPtr; X`09return LS_OK; X `7D else `7B X`09/* Item added in the middle of the list */ X`09newElem = alloc(lsElem); X`09newElem->mainList = realGen->mainList; X`09newElem->prevPtr = realGen->beforeSpot; X`09newElem->nextPtr = realGen->afterSpot; X`09newElem->userData = data; X`09realGen->beforeSpot->nextPtr = newElem; X`09realGen->afterSpot->prevPtr = newElem; X`09realGen->beforeSpot = newElem; X`09realGen->mainList->length += 1; X`09if (itemHandle) *itemHandle = (lsHandle) newElem; X`09return LS_OK; X `7D X`7D X XlsStatus lsInAfter(generator, data, itemHandle) XlsGen generator;`09`09/* Generator handle */ XPointer data;`09`09`09/* Arbitrary pointer to data */ XlsHandle *itemHandle;`09/* Handle to item (return) */ X/* X * Inserts an element AFTER the current spot. The next item generated X * by lsNext will be the new element. The next item generated by X * lsPrev is unchanged. This modifies the list. 'itemHandle' may X * be used at a later time to generate a generation handle without X * searching through the list to find the item. X */ X`7B X lsGenInternal *realGen = (lsGenInternal *) generator; X lsElem *newElem; X X if (realGen->beforeSpot == NIL(lsElem)) `7B X`09/* Item added to the beginning of the list */ X`09(void) lsNewBegin((lsList) realGen->mainList, data, itemHandle); X`09realGen->beforeSpot = realGen->mainList->topPtr; X`09return LS_OK; X `7D else if (realGen->afterSpot == NIL(lsElem)) `7B X`09/* Item added to the end of the list */ X`09(void) lsNewEnd((lsList) realGen->mainList, data, itemHandle); X`09realGen->afterSpot = realGen->mainList->botPtr; X`09return LS_OK; X `7D else `7B X`09/* Item added in the middle of the list */ X`09newElem = alloc(lsElem); X`09newElem->mainList = realGen->mainList; X`09newElem->prevPtr = realGen->beforeSpot; X`09newElem->nextPtr = realGen->afterSpot; X`09newElem->userData = data; X`09realGen->beforeSpot->nextPtr = newElem; X`09realGen->afterSpot->prevPtr = newElem; X`09realGen->afterSpot = newElem; X`09realGen->mainList->length += 1; X`09if (itemHandle) *itemHandle = (lsHandle) newElem; X`09return LS_OK; X `7D X`7D X`09 X XlsStatus lsDelBefore(generator, data) XlsGen generator;`09`09/* Generator handle */ XPointer *data;`09`09`09/* Deleted item (returned) */ X/* X * Removes the item before the current spot. The next call to lsPrev X * will return the item before the deleted item. The next call to lsNext X * will be uneffected. This modifies the list. The routine returns`20 X * LS_BADSTATE if the user tries to call the routine and there is X * no item before the current spot. This routine returns the userData X * of the deleted item so it may be freed (if necessary). X */ X`7B X lsGenInternal *realGen = (lsGenInternal *) generator; X lsElem *doomedItem; X X if (realGen->beforeSpot == NIL(lsElem)) `7B X`09/* No item to delete */ X`09*data = (Pointer) 0; X`09return LS_BADSTATE; X `7D else if (realGen->beforeSpot == realGen->mainList->topPtr) `7B X`09/* Delete the first item of the list */ X`09return lsDelBegin((lsList) realGen->mainList, data); X `7D else if (realGen->beforeSpot == realGen->mainList->botPtr) `7B X`09/* Delete the last item of the list */ X`09return lsDelEnd((lsList) realGen->mainList, data); X `7D else `7B X`09/* Normal mid list deletion */ X`09doomedItem = realGen->beforeSpot; X`09doomedItem->prevPtr->nextPtr = doomedItem->nextPtr; X`09doomedItem->nextPtr->prevPtr = doomedItem->prevPtr; X`09realGen->beforeSpot = doomedItem->prevPtr; X`09realGen->mainList->length -= 1; X`09*data = doomedItem->userData; X`09XtFree((Pointer) doomedItem); X`09return LS_OK; X `7D X`7D X X XlsStatus lsDelAfter(generator, data) XlsGen generator;`09`09/* Generator handle */ XPointer *data;`09`09`09/* Deleted item (returned) */ X/* X * Removes the item after the current spot. The next call to lsNext X * will return the item after the deleted item. The next call to lsPrev X * will be uneffected. This modifies the list. The routine returns`20 X * LS_BADSTATE if the user tries to call the routine and there is X * no item after the current spot. This routine returns the userData X * of the deleted item so it may be freed (if necessary). X */ X`7B X lsGenInternal *realGen = (lsGenInternal *) generator; X lsElem *doomedItem; X X if (realGen->afterSpot == NIL(lsElem)) `7B X`09/* No item to delete */ X`09*data = (Pointer) 0; X`09return LS_BADSTATE; X `7D else if (realGen->afterSpot == realGen->mainList->topPtr) `7B X`09/* Delete the first item of the list */ X`09return lsDelBegin((lsList) realGen->mainList, data); X `7D else if (realGen->afterSpot == realGen->mainList->botPtr) `7B X`09/* Delete the last item of the list */ X`09return lsDelEnd((lsList) realGen->mainList, data); X `7D else `7B X`09/* Normal mid list deletion */ X`09doomedItem = realGen->afterSpot; X`09doomedItem->prevPtr->nextPtr = doomedItem->nextPtr; X`09doomedItem->nextPtr->prevPtr = doomedItem->prevPtr; X`09realGen->afterSpot = doomedItem->nextPtr; X`09realGen->mainList->length -= 1; X`09*data = doomedItem->userData; X`09XtFree((Pointer) doomedItem); X`09return LS_OK; X `7D X`7D X X X XlsStatus lsFinish(generator) XlsGen generator;`09`09/* Generator handle */ X/* X * Marks the completion of a generation of list items. This routine should X * be called after calls to lsNext to free resources used by the X * generator. This rule applies even if all items of a list are X * generated by lsNext. X */ X`7B X lsGenInternal *realGen = (lsGenInternal *) generator; X X XtFree((Pointer) realGen); X return(LS_OK); X`7D $ CALL UNPACK LIST.C;1 325965461 $ create 'f' X X#ifndef LIST_H X#define LIST_H X X/* X * $Header: /users/ricks/xrn-11/src/RCS/list.h,v 1.2 89/08/19 14:30:17 ricks V Rel $ X */ X X/* X * List Management Package X * X * Copyright (c) 1988, 1989, David S. Harrison. All rights reserved. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X Xtypedef char *lsPointer; X X/* This can be typedef'ed to void if supported */ Xtypedef struct ls_dummy_defn `7B X int dummy;`09`09`09/* Not used */ X`7D ls_dummy; X Xtypedef ls_dummy *lsList;`09/* List handle */ Xtypedef ls_dummy *lsGen;`09/* List generator handle */ Xtypedef ls_dummy *lsHandle;`09/* Handle to an item */ Xtypedef int lsStatus;`09`09/* Return codes */ X X#define`09LS_NIL`09`090`09/* Nil for lsList */ X X#define LS_BADSTATE`09-3`09/* Bad generator state */ X#define LS_BADPARAM`09-2`09/* Bad parameter value */ X#define LS_NOMORE`09-1`09/* No more items */ X X#define`09LS_OK`09`090 X X#define LS_BEFORE`091`09/* Set spot before object */ X#define LS_AFTER`092`09/* Set spot after object */ X X/* X * For all those routines that take a handle, this macro can be X * used when no handle is required. X */ X X#define LS_NH`09`09(lsHandle *) 0 X Xextern lsList lsCreate(); X /* Create a new list */ Xextern lsStatus lsDestroy(); X /* Delete a previously created list */ X Xextern lsStatus lsFirstItem(); X /* Gets the first item of a list */ Xextern lsStatus lsLastItem(); X /* Gets the last item of a list */ X Xextern lsStatus lsNewBegin(); X /* Add item to start of list */ Xextern lsStatus lsNewEnd(); X /* Add item to end of list */ X Xextern lsStatus lsDelBegin(); X /* Delete first item of a list */ Xextern lsStatus lsDelEnd(); X /* Delete last item of a list */ X Xextern int lsLength(); X /* Returns the length of the list */ X Xextern lsGen lsStart(); X /* Begin generation of items in a list */ Xextern lsGen lsGenHandle(); X /* Produces a generator given a handle */ Xextern lsList lsQueryHandle(); X /* Returns the list of a handle */ Xextern lsStatus lsNext(); X /* Generate next item in sequence */ Xextern lsStatus lsPrev(); X /* Generate previous item in sequence */ Xextern lsStatus lsInBefore(); X /* Insert an item before the most recently generated by lsNext */ Xextern lsStatus lsInAfter(); X /* Insert an item after the most recently generated by lsNext */ Xextern lsStatus lsDelBefore(); X /* Delete the item before the current spot */ Xextern lsStatus lsDelAfter(); X /* Delete the item after the current spot */ Xextern lsStatus lsFinish(); X /* End generation of items in a list */ X X#endif $ CALL UNPACK LIST.H;1 1484676937 $ create 'f' X$ cc/nolist avl X$ cc/nolist buttons/opt=noinline`09! makes the compile faster X$ cc/nolist clientlib X$ cc/nolist compose X$ cc/nolist cursor X$ cc/nolist dialogs X$ cc/nolist error_hnds X$ cc/nolist internals X$ cc/nolist list X$ cc/nolist menus X$ cc/nolist mesg X$ cc/nolist newsrcfile X$ cc/nolist newsrc_parse X$ cc/nolist pane X$ cc/nolist resources X$ cc/nolist save X$ cc/nolist server X$ cc/nolist slist X$ cc/nolist t6 X$ cc/nolist t7 X$ cc/nolist utils X$ cc/nolist xmisc X$ cc/nolist xrn X$ cc/nolist xthelper X$ link/exe=dxrn sys$input/opt Xxrn,buttons,compose,cursor,dialogs,error_hnds,menus,mesg Xnewsrcfile,newsrc_parse,resources,internals,save,server,utils Xxmisc,xthelper,avl,list,clientlib,t6,t7,pane,slist Xsys$share:decw$dwtlibshr/share Xsys$share:decw$xlibshr/share Xsys$share:vaxcrtl/share X! X! Remove this or put in your TCP/IP library X! Xsys$share:ucx$ipc/library X$ exit $ CALL UNPACK MAKE-DXRN.COM;1 940613897 $ create 'f' X$ @sys$common:`5Bdecw$motif`5Ddxm_logicals X$ ! If you're using Motif V1.0, change the X$ ! compile lines to 'cc/nolist/define=(MOTIF,MOTIF_V1_0). X$ ! X$ cc/nolist/define=MOTIF avl X$ cc/nolist/define=MOTIF buttons/opt=noinline`09! Makes the compile faster X$ cc/nolist/define=MOTIF clientlib X$ cc/nolist/define=MOTIF compose X$ cc/nolist/define=MOTIF cursor X$ cc/nolist/define=MOTIF dialogs X$ cc/nolist/define=MOTIF error_hnds X$ cc/nolist/define=MOTIF internals X$ cc/nolist/define=MOTIF list X$ cc/nolist/define=MOTIF menus X$ cc/nolist/define=MOTIF mesg X$ cc/nolist/define=MOTIF newsrcfile X$ cc/nolist/define=MOTIF newsrc_parse X$ cc/nolist/define=MOTIF resources X$ cc/nolist/define=MOTIF save X$ cc/nolist/define=MOTIF server X$ cc/nolist/define=MOTIF slist X$ cc/nolist/define=MOTIF t6 X$ cc/nolist/define=MOTIF t7 X$ cc/nolist/define=MOTIF utils X$ cc/nolist/define=MOTIF xmisc X$ cc/nolist/define=MOTIF xrn X$ cc/nolist/define=MOTIF xthelper X$ link/exe=mxrn sys$input/opt Xxrn,buttons,compose,cursor,dialogs,error_hnds,menus,mesg Xnewsrcfile,newsrc_parse,resources,internals,save,server,utils Xxmisc,xthelper,avl,list,clientlib,t6,t7,slist X!use these libraries for Motif V1.0: X!Xm:DECW$MOTIF$XM.OLB/LIBRARY X!Xt:DECW$MOTIF$XT.OLB/LIBRARY X!Xt:CLIB.OLB/LIBRARY X! X!use these for Motif V1.1. X! Xsys$share:decw$motif$dxmshr/shareable Xsys$share:decw$motif$xmshr/shareable Xsys$share:decw$motif$xtshr/shareable X! X!use these for either version. X! Xsys$share:decw$xlibshr/share Xsys$share:vaxcrtl/share X! X! Remove this or put in your TCP/IP library X! Xsys$share:ucx$ipc/library X$ exit $ CALL UNPACK MAKE-MXRN.COM;1 1362449828 $ create 'f' X# X# xrn - an X-based NNTP news reader X# X# Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmier V. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation, and that the name of the University of California not X# be used in advertising or publicity pertaining to distribution of`20 X# the software without specific, written prior permission. The University X# of California makes no representations about the suitability of this X# software for any purpose. It is provided "as is" without express or X# implied warranty. X# X# THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X# FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X# X# The following may need changing for your site: X# X# CC, DEST, LD, LDFLAGS, LIBS, MANDIR, MANSUFFIX, INCLUDES X# X# The libraries -lPW and -lBSD should be included for machines running X# HP-UX. This may apply to other SYSV systems. X# X X# CC = gcc X X SHELL = `09/bin/sh X X DEFINES = X DEST = /usr/local/bin X HDRS = avl.h buttons.h codes.h compose.h config.h copyright.h \ X`09`09 cursor.h dialogs.h error_hnds.h internals.h mesg.h \ X`09`09 modes.h news.h newsrcfile.h resources.h save.h server.h \ X`09`09 utils.h xmisc.h xrn.h xthelper.h slist.h slistP.h Pane.h \ X`09`09 PaneP.h X CFLAGS = $(INCLUDES) $(STD_DEFINES) $(DEFINES) X INCLUDES = X INSTALL = cp X LDFLAGS =`20 X DWTLIB = -ldwt X XLIB = -lX11 X LIBS = $(DWTLIB) $(XLIB) X INCLUDES =`20 X MANDIR = /usr/local/man/man1 X MANPAGE = xrn.man X MANSUFFIX = 1 X RM_CMD = rm *.CKP *.ln *.BAK *.bak *.o core errs ,* *`7E *.a \ X`09`09`09.emacs_* tags TAGS make.log MakeOut X`20 X OBJS = avl.o buttons.o clientlib.o compose.o cursor.o dialogs.o \ X`09 menus.o mesg.o error_hnds.o list.o newsrcfile.o resources.o \ X`09 internals.o save.o server.o utils.o xmisc.o xrn.o \ X`09 xthelper.o pane.o slist.o X X PRINT = pr X PROGRAM = dxrn X SRCS = avl.c buttons.c clientlib.c compose.c \ X`09 cursor.c dialogs.c error_hnds.c internals.c menus.c mesg.c \ X`09 newsrcfile.c resources.c save.c server.c utils.c \ X`09 pane.c slist.c xmisc.c xrn.c xthelper.c X X Xall:`09`09$(PROGRAM) X X$(PROGRAM): $(OBJS) y.tab.o X`09`09@echo "Linking $(PROGRAM) ..." X`09`09$(CC) $(LDFLAGS) $(OBJS) y.tab.o $(LIBS) -o $(PROGRAM) X`09`09@echo "done" X Xlex.yy.c:`09newsrc.l X`09`09lex newsrc.l X Xy.tab.c:`09newsrc.y X`09`09yacc newsrc.y X Xy.tab.o:`09lex.yy.c avl.h news.h newsrcfile.h utils.h X Xclean:;`09`09@rm -f $(OBJS) core y.tab.o y.tab.c lex.yy.c X Xinstall:`09$(PROGRAM) X`09`09@echo Installing $(PROGRAM) in $(DEST) X`09`09@if `5B $(DEST) ! = . `5D; then \ X`09`09(rm -f $(DEST)/$(PROGRAM); \ X`09`09$(INSTALL) $(PROGRAM) $(DEST); \ X`09`09chmod 755 $(DEST)/$(PROGRAM)); fi X Xinstall-man:`09$(MANPAGE) X`09`09@cp $(MANPAGE) $(MANDIR)/`60basename $(MANPAGE) .man`60.$(MANSUFFIX) X Xprint:;`09`09@$(PRINT) $(HDRS) $(SRCS) newsrc.l newsrc.y X Xtags: $(HDRS) $(SRCS) newsrc.l newsrc.y X`09`09@ctags $(HDRS) $(SRCS) newsrc.l newsrc.y X X $ CALL UNPACK MAKEFILE.;1 1379338932 $ create 'f' X# X# xrn - an X-based NNTP news reader X# X# Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmier V. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation, and that the name of the University of California not X# be used in advertising or publicity pertaining to distribution of`20 X# the software without specific, written prior permission. The University X# of California makes no representations about the suitability of this X# software for any purpose. It is provided "as is" without express or X# implied warranty. X# X# THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X# FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X# X# The following may need changing for your site: X# X# CC, DEST, LD, LDFLAGS, LIBS, MANDIR, MANSUFFIX, INCLUDES X# X# The libraries -lPW and -lBSD should be included for machines running X# HP-UX. This may apply to other SYSV systems. X# X X# CC = gcc X X SHELL = `09/bin/sh X X DEFINES = -DDECNET X DEST = /usr/local/bin X HDRS = avl.h buttons.h codes.h compose.h config.h copyright.h \ X`09`09 cursor.h dialogs.h error_hnds.h internals.h mesg.h \ X`09`09 modes.h news.h newsrcfile.h resources.h save.h server.h \ X`09`09 utils.h xmisc.h xrn.h xthelper.h slist.h slistP.h Pane.h \ X`09`09 PaneP.h X CFLAGS = $(INCLUDES) $(STD_DEFINES) $(DEFINES) X INCLUDES = X INSTALL = cp X LDFLAGS =`20 X DWTLIB = -ldwt X XLIB = -lX11 X DNETLIB = -ldnet X LIBS = $(DWTLIB) $(XLIB) $(DNETLIB) X INCLUDES =`20 X MANDIR = /usr/local/man/man1 X MANPAGE = xrn.man X MANSUFFIX = 1 X RM_CMD = rm *.CKP *.ln *.BAK *.bak *.o core errs ,* *`7E *.a \ X`09`09`09.emacs_* tags TAGS make.log MakeOut X`20 X OBJS = avl.o buttons.o clientlib.o compose.o cursor.o dialogs.o \ X`09 menus.o mesg.o error_hnds.o list.o newsrcfile.o resources.o \ X`09 internals.o save.o server.o utils.o xmisc.o xrn.o \ X`09 xthelper.o pane.o slist.o X X PRINT = pr X PROGRAM = dxrn X SRCS = avl.c buttons.c clientlib.c compose.c \ X`09 cursor.c dialogs.c error_hnds.c internals.c menus.c mesg.c \ X`09 newsrcfile.c resources.c save.c server.c utils.c \ X`09 pane.c slist.c xmisc.c xrn.c xthelper.c`20 X X Xall:`09`09$(PROGRAM) X X$(PROGRAM): $(OBJS) y.tab.o X`09`09@echo "Linking $(PROGRAM) ..." X`09`09$(CC) $(LDFLAGS) $(OBJS) y.tab.o $(LIBS) -o $(PROGRAM) X`09`09@echo "done" X Xlex.yy.c:`09newsrc.l X`09`09lex newsrc.l X Xy.tab.c:`09newsrc.y X`09`09yacc newsrc.y X Xy.tab.o:`09lex.yy.c avl.h news.h newsrcfile.h utils.h X Xclean:;`09`09@rm -f $(OBJS) core y.tab.o y.tab.c lex.yy.c X Xinstall:`09$(PROGRAM) X`09`09@echo Installing $(PROGRAM) in $(DEST) X`09`09@if `5B $(DEST) ! = . `5D; then \ X`09`09(rm -f $(DEST)/$(PROGRAM); \ X`09`09$(INSTALL) $(PROGRAM) $(DEST); \ X`09`09chmod 755 $(DEST)/$(PROGRAM)); fi X Xinstall-man:`09$(MANPAGE) X`09`09@cp $(MANPAGE) $(MANDIR)/`60basename $(MANPAGE) .man`60.$(MANSUFFIX) X Xprint:;`09`09@$(PRINT) $(HDRS) $(SRCS) newsrc.l newsrc.y X Xtags: $(HDRS) $(SRCS) newsrc.l newsrc.y X`09`09@ctags $(HDRS) $(SRCS) newsrc.l newsrc.y X X $ CALL UNPACK MAKEFILE.DECNET;1 861263088 $ create 'f' X# X# xrn - an X-based NNTP news reader X# X# Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmier V. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation, and that the name of the University of California not X# be used in advertising or publicity pertaining to distribution of`20 X# the software without specific, written prior permission. The University X# of California makes no representations about the suitability of this X# software for any purpose. It is provided "as is" without express or X# implied warranty. X# X# THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X# FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X# X# The following may need changing for your site: X# X# CC, DEST, LD, LDFLAGS, LIBS, MANDIR, MANSUFFIX, INCLUDES X# X# The libraries -lPW and -lBSD should be included for machines running X# HP-UX. This may apply to other SYSV systems. X# X X# CC = gcc X X SHELL = `09/bin/sh X X# for MOTIF V1.0, you'll need to define MOTIF_V1_0. X# DEFINES = -DMOTIF -DMOTIF_V1_0 X DEFINES = -DMOTIF X DEST = /usr/local/bin X HDRS = avl.h buttons.h codes.h compose.h config.h copyright.h \ X`09`09 cursor.h dialogs.h error_hnds.h internals.h mesg.h \ X`09`09 modes.h news.h newsrcfile.h resources.h save.h server.h \ X`09`09 utils.h xmisc.h xrn.h xthelper.h slist.h slistP.h X CFLAGS = $(INCLUDES) $(STD_DEFINES) $(DEFINES) X INCLUDES = X INSTALL = cp X LDFLAGS =`20 X XLIB = -lX11 X XTOOLLIB = /usr/lib/DXM/lib/Xt/libXt.a X MTOOLLIB = /usr/lib/DXM/lib/Xm/libXm.a X LIBS = $(MTOOLLIB) $(XTOOLLIB) $(XLIB) X INCLUDES = -I/usr/lib/DXM/lib -I/usr/lib/DXM/lib/Xt X MANDIR = /usr/local/man/man1 X MANPAGE = xrn.man X MANSUFFIX = 1 X RM_CMD = rm *.CKP *.ln *.BAK *.bak *.o core errs ,* *`7E *.a \ X`09`09`09.emacs_* tags TAGS make.log MakeOut X`20 X OBJS = avl.o buttons.o clientlib.o compose.o cursor.o dialogs.o \ X`09 mesg.o error_hnds.o list.o menus.o newsrcfile.o resources.o \ X`09 internals.o save.o server.o utils.o xmisc.o xrn.o \ X`09 xthelper.o slist.o`20 X X PRINT = pr X PROGRAM = mxrn X SRCS = avl.c buttons.c clientlib.c compose.c \ X`09 cursor.c dialogs.c error_hnds.c internals.c menus.c mesg.c \ X`09 newsrcfile.c resources.c save.c server.c utils.c \ X`09 slist.c xmisc.c xrn.c xthelper.c`20 X X Xall:`09`09$(PROGRAM) X X$(PROGRAM): $(OBJS) y.tab.o X`09`09@echo "Linking $(PROGRAM) ..." X`09`09$(CC) $(LDFLAGS) $(OBJS) y.tab.o $(LIBS) -o $(PROGRAM) X`09`09@echo "done" X Xlex.yy.c:`09newsrc.l X`09`09lex newsrc.l X Xy.tab.c:`09newsrc.y X`09`09yacc newsrc.y X Xy.tab.o:`09lex.yy.c avl.h news.h newsrcfile.h utils.h X Xclean:;`09`09@rm -f $(OBJS) core y.tab.o y.tab.c lex.yy.c X Xinstall:`09$(PROGRAM) X`09`09@echo Installing $(PROGRAM) in $(DEST) X`09`09@if `5B $(DEST) ! = . `5D; then \ X`09`09(rm -f $(DEST)/$(PROGRAM); \ X`09`09$(INSTALL) $(PROGRAM) $(DEST); \ X`09`09chmod 755 $(DEST)/$(PROGRAM)); fi X Xinstall-man:`09$(MANPAGE) X`09`09@cp $(MANPAGE) $(MANDIR)/`60basename $(MANPAGE) .man`60.$(MANSUFFIX) X Xprint:;`09`09@$(PRINT) $(HDRS) $(SRCS) newsrc.l newsrc.y X Xtags: $(HDRS) $(SRCS) newsrc.l newsrc.y X`09`09@ctags $(HDRS) $(SRCS) newsrc.l newsrc.y X X $ CALL UNPACK MAKEFILE.MOTIF;1 87078732 $ create 'f' X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * menus.c: create the menus X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#else X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#else X#ifndef VMS X#include X#else X#include X#endif X#endif /* MOTIF */ X#include "xmisc.h" X#include "xrn.h" X#include "utils.h" X#include "resources.h" X#include "mesg.h" X#include "modes.h" X X#ifndef MOTIF X#define XmToggleButtonGadgetGetState DwtToggleButtonGetState X#define XmToggleButtonGadgetSetState DwtToggleButtonSetState X#define XmToggleButtonGetState DwtToggleButtonGetState X#define XmToggleButtonSetState DwtToggleButtonSetState X#define XmTextSetString DwtSTextSetString X#define XmTextGetString DwtSTextGetString X#define XmStringLtoRCreate(a,b) DwtLatin1String(a) X#define XmStringFree XtFree X#define XmNx DwtNx X#define XmNy DwtNy X#define XmNwidth DwtNwidth X#define XmNheight DwtNheight X#define XmNlabelString DwtNlabel X#define XmCreatePushButton DwtPushButtonCreate X#define XmCreatePushButtonGadget DwtPushButtonGadgetCreate X#define XmCreateLabel DwtLabelCreate X#define XmCreateLabelGadget DwtLabelGadgetCreate X#define XmString DwtCompString X#define XmNborderWidth DwtNborderWidth X#define XmNresizePolicy DwtNresize X#define XmRESIZE_GROW DwtResizeGrowOnly X#define XmNautoUnmanage DwtNautoUnmanage X#define XmNfontList DwtNfont X#define XmNdialogStyle DwtNstyle X#define XmDIALOG_APPLICATION_MODAL DwtModal X#define XmNvisibleItemCount DwtNvisibleItemsCount X#define XmNactivateCallback DwtNactivateCallback X#define XmNdefaultButton DwtNdefaultPushbutton X#define XmNitems DwtNitems X#define XmNitemCount DwtNitemsCount X#define XmNsingleSelectionCallback DwtNsingleCallback X#define XmCreateBulletinBoardDialog DwtDialogBoxPopupCreate X#define XmListDeselectAllItems DwtListBoxDeselectAllItems X#define XmCreateScrolledList DwtListBoxCreate X#endif X Xstatic void makeCustomMenu(); Xstatic void makeGeneralMenu(); Xstatic void doPopups(); Xstatic void CustomizeAddMenus(); Xstatic void CustomizeAddPopups(); Xstatic void CustomizeAllMenus(); Xstatic void CustomizeAllPopups(); Xstatic void CustomizeArtMenus(); Xstatic void CustomizeArtPopups(); Xstatic void CustomizeNgMenus(); Xstatic void CustomizeNgPopups(); Xstatic void CustomizeGeneral(); Xstatic void CustomizeSave(); Xstatic void cgOK(); Xstatic void cgApply(); Xstatic void cgCancel(); Xstatic void addClick(); Xstatic void removeClick(); Xstatic void cmOK(); Xstatic void cmApply(); Xstatic void cmCancel(); Xstatic XtCallbackRec addMenusCallbacks`5B`5D = `7B X `7BCustomizeAddMenus, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec addPopupsCallbacks`5B`5D = `7B X `7BCustomizeAddPopups, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec artMenusCallbacks`5B`5D = `7B X `7BCustomizeArtMenus, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec artPopupsCallbacks`5B`5D = `7B X `7BCustomizeArtPopups, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec ngMenusCallbacks`5B`5D = `7B X `7BCustomizeNgMenus, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec ngPopupsCallbacks`5B`5D = `7B X `7BCustomizeNgPopups, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec allMenusCallbacks`5B`5D = `7B X `7BCustomizeAllMenus, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec allPopupsCallbacks`5B`5D = `7B X `7BCustomizeAllPopups, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec artGeneralCallbacks`5B`5D = `7B X `7BCustomizeGeneral, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec addGeneralCallbacks`5B`5D = `7B X `7BCustomizeGeneral, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec ngGeneralCallbacks`5B`5D = `7B X `7BCustomizeGeneral, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec allGeneralCallbacks`5B`5D = `7B X `7BCustomizeGeneral, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec addSaveCustomCallbacks`5B`5D = `7B X `7BCustomizeSave, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec allSaveCustomCallbacks`5B`5D = `7B X `7BCustomizeSave, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec artSaveCustomCallbacks`5B`5D = `7B X `7BCustomizeSave, NULL`7D, X `7BNULL, NULL`7D, X`7D; Xstatic XtCallbackRec ngSaveCustomCallbacks`5B`5D = `7B X `7BCustomizeSave, NULL`7D, X `7BNULL, NULL`7D, X`7D; X Xstatic XtCallbackRec cgOKCallback`5B`5D = `7B X `7BcgOK, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec cgApplyCallback`5B`5D = `7B X `7BcgApply, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec cgCancelCallback`5B`5D = `7B X `7BcgCancel, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec cmOKCallback`5B`5D = `7B X `7BcmOK, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec cmApplyCallback`5B`5D = `7B X `7BcmApply, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec cmCancelCallback`5B`5D = `7B X `7BcmCancel, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec addCallback`5B`5D = `7B X `7BaddClick, NULL`7D, X `7BNULL, NULL`7D X`7D; Xstatic XtCallbackRec removeCallback`5B`5D = `7B X `7BremoveClick, NULL`7D, X `7BNULL, NULL`7D X`7D; XXmString addItems`5B50`5D; XXmString removeItems`5B50`5D; X#ifdef MOTIF XXmFontList fontList; X#else XDwtFontList fontList; X#endif X Xextern void createButtons(); Xstatic XrmDatabase`09xrmDB; Xextern char`09`09customName`5B512`5D; Xextern int`09`09Mode;`09`09`09/* Current mode */ XXFontStruct *font; Xtypedef struct buttonDefs `7B X char *name; X char *label; X int addPos; X int removePos; X XmString listString; X`7D ButtonDefs; X XButtonDefs addButtons`5B`5D = `7B X `7B"addQuit","Quit",0,0,NULL`7D, X `7B"addFirst","Add First",0,0,NULL`7D, X `7B"addLast","Add Last",0,0,NULL`7D, X `7B"addAfter","Add After Group",0,0,NULL`7D, X `7B"addUnsub","Add Unsubscribed",0,0,NULL`7D, X`7D; XButtonDefs ngButtons`5B`5D = `7B X `7B"ngExit","Exit",0,0,NULL`7D, X `7B"ngQuit","Quit",0,0,NULL`7D, X `7B"ngRead","Read Group",0,0,NULL`7D, X `7B"ngOpen","Open Group",0,0,NULL`7D, X `7B"ngNext","Next",0,0,NULL`7D, X `7B"ngPrev","Prev",0,0,NULL`7D, X `7B"ngCatchUp","Catch Up",0,0,NULL`7D, X `7B"ngSubscribe","Subscribe",0,0,NULL`7D, X `7B"ngUnsub","Unsubscribe",0,0,NULL`7D, X `7B"ngGoto","Go To Newsgroup",0,0,NULL`7D, X `7B"ngToggleGroups","Toggle Groups",0,0,NULL`7D, X `7B"ngAllGroups","All Groups",0,0,NULL`7D, X `7B"ngRescan","Rescan",0,0,NULL`7D, X `7B"ngPrevGroup","Prev Group",0,0,NULL`7D, X `7B"ngSelect","Select Groups",0,0,NULL`7D, X `7B"ngMove","Move",0,0,NULL`7D, X `7B"ngCheckPoint","Checkpoint",0,0,NULL`7D, X `7B"ngPost","Post",0,0,NULL`7D, X `7B"ngGripe","Gripe",0,0,NULL`7D, X`7D; X XButtonDefs allButtons`5B`5D = `7B X `7B"allQuit","Quit",0,0,NULL`7D, X `7B"allSub","Subscribe",0,0,NULL`7D, X `7B"allFirst","Subscribe First",0,0,NULL`7D, X `7B"allLast","Subscribe Last",0,0,NULL`7D, X `7B"allAfter","Subscribe After Group",0,0,NULL`7D, X `7B"allUnsub","Unsubscribe",0,0,NULL`7D, X `7B"allGoto","Go To Group",0,0,NULL`7D, X `7B"allSelect","Select Groups",0,0,NULL`7D, X `7B"allMove","Move",0,0,NULL`7D, X `7B"allToggle","Toggle Order",0,0,NULL`7D, X `7B"allScroll","Scroll Forward",0,0,NULL`7D, X `7B"allScrollBack","Scroll Backward",0,0,NULL`7D, X `7B"allSearch","Search",0,0,NULL`7D, X `7B"allContinue","Continue",0,0,NULL`7D, X `7B"allCancelSearch","Cancel Search",0,0,NULL`7D, X`7D; X XButtonDefs artButtons`5B`5D = `7B X `7B"artQuit","Quit",0,0,NULL`7D, X `7B"artNext","Next",0,0,NULL`7D, X `7B"artNextUnread","Next Unread",0,0,NULL`7D, X `7B"artPrev","Prev",0,0,NULL`7D, X `7B"artLast","Last",0,0,NULL`7D, X `7B"artNextGroup","Next Newsgroup",0,0,NULL`7D, X `7B"artGotoArticle","Go To Article",0,0,NULL`7D, X `7B"artCatchUp","Catch Up",0,0,NULL`7D, X `7B"artFedUp","Fed Up",0,0,NULL`7D, X `7B"artMarkRead","Mark Read",0,0,NULL`7D, X `7B"artMarkUnread","Mark Unread",0,0,NULL`7D, X `7B"artUnsub","Unsubscribe",0,0,NULL`7D, X `7B"artScroll","Scroll Forward",0,0,NULL`7D, X `7B"artScrollBack","Scroll Backward",0,0,NULL`7D, X `7B"artScrollEnd","Scroll to End",0,0,NULL`7D, X `7B"artScrollBeginning","Scroll to Start",0,0,NULL`7D, X `7B"artSubNext","Subject Next",0,0,NULL`7D, X `7B"artSubPrev","Subject Prev",0,0,NULL`7D, X `7B"artKillSession","Session Kill",0,0,NULL`7D, X `7B"artKillLocal","Local Kill",0,0,NULL`7D, X `7B"artKillGlobal","Global Kill",0,0,NULL`7D, X `7B"artKillAuthor","Author Kill",0,0,NULL`7D, X `7B"artSubSearch","Subject Search",0,0,NULL`7D, X `7B"artContinue","Continue Search",0,0,NULL`7D, X `7B"artCancelSearch","Cancel Search",0,0,NULL`7D, X `7B"artSorted","Toggle Order",0,0,NULL`7D, X `7B"artPost","Post",0,0,NULL`7D, X `7B"artExit","Exit",0,0,NULL`7D, X `7B"artCheckPoint","CheckPoint newsrc",0,0,NULL`7D, X `7B"artGripe","Gripe",0,0,NULL`7D, X `7B"artListOld","List Old",0,0,NULL`7D, X`7D; XButtonDefs artSpecButtons`5B`5D = `7B X `7B"artSave","Save",0,0,NULL`7D, X `7B"artReply","Reply",0,0,NULL`7D, X `7B"artForward","Forward",0,0,NULL`7D, X `7B"artFollowup","Followup",0,0,NULL`7D, X `7B"artCancel","Cancel",0,0,NULL`7D, X `7B"artRot13","Rot-13",0,0,NULL`7D, X `7B"artHeader","Toggle Header",0,0,NULL`7D, X `7B"artPrint","Print",0,0,NULL`7D, X`7D; XButtonDefs `09*currentButtons; Xstatic int`09currentCount; Xstatic int`09menuMode; X#define addMenu 1 X#define addPop 2 X#define allMenu 3 X#define allPop 4 X#define artMenu 5 X#define artPop 6 X#define ngMenu 7 X#define ngPop 8 X Xstatic Widget ngPulldowns`5B5`5D; Xstatic Widget artPulldowns`5B7`5D; Xstatic Widget allPulldowns`5B5`5D; Xstatic Widget addPulldowns`5B3`5D; Xstatic Widget tempPulldown; Xstatic Widget tempMenu; Xexternaldef(ngmenus) Widget ngMenus`5B5`5D; Xexternaldef(artmenus) Widget artMenus`5B7`5D; Xexternaldef(allmenus) Widget allMenus`5B5`5D; Xexternaldef(allmenus) Widget addMenus`5B3`5D; Xexternaldef(addpopupbuttons) Widget *AddPopupButtons = NIL(Widget); Xexternaldef(ngpopupbuttons) Widget *NgPopupButtons = NIL(Widget); Xexternaldef(allpopupbuttons) Widget *AllPopupButtons = NIL(Widget); Xexternaldef(artpopupbuttons) Widget *ArtPopupButtons = NIL(Widget); X Xexternalref XtCallbackRec addQuitCallbacks`5B`5D; Xexternalref XtCallbackRec addFirstCallbacks`5B`5D; Xexternalref XtCallbackRec addLastCallbacks`5B`5D; Xexternalref XtCallbackRec addAfterCallbacks`5B`5D; Xexternalref XtCallbackRec addUnsubCallbacks`5B`5D; Xexternalref XtCallbackRec ngExitCallbacks`5B`5D; Xexternalref XtCallbackRec ngQuitCallbacks`5B`5D; Xexternalref XtCallbackRec ngReadCallbacks`5B`5D; Xexternalref XtCallbackRec ngOpenCallbacks`5B`5D; Xexternalref XtCallbackRec ngNextCallbacks`5B`5D; Xexternalref XtCallbackRec ngPrevCallbacks`5B`5D; Xexternalref XtCallbackRec ngCatchUpCallbacks`5B`5D; Xexternalref XtCallbackRec ngSubscribeCallbacks`5B`5D; Xexternalref XtCallbackRec ngUnsubCallbacks`5B`5D; Xexternalref XtCallbackRec ngGotoCallbacks`5B`5D; Xexternalref XtCallbackRec ngToggleGroupsCallbacks`5B`5D; Xexternalref XtCallbackRec ngAllGroupsCallbacks`5B`5D; Xexternalref XtCallbackRec ngRescanCallbacks`5B`5D; Xexternalref XtCallbackRec ngPrevGroupCallbacks`5B`5D; Xexternalref XtCallbackRec ngSelectCallbacks`5B`5D; Xexternalref XtCallbackRec ngMoveCallbacks`5B`5D; Xexternalref XtCallbackRec ngCheckPointCallbacks`5B`5D; Xexternalref XtCallbackRec ngPostCallbacks`5B`5D; Xexternalref XtCallbackRec ngGripeCallbacks`5B`5D; Xexternalref XtCallbackRec allQuitCallbacks`5B`5D; Xexternalref XtCallbackRec allSubCallbacks`5B`5D; Xexternalref XtCallbackRec allFirstCallbacks`5B`5D; Xexternalref XtCallbackRec allLastCallbacks`5B`5D; Xexternalref XtCallbackRec allAfterCallbacks`5B`5D; Xexternalref XtCallbackRec allUnsubCallbacks`5B`5D; Xexternalref XtCallbackRec allGotoCallbacks`5B`5D; Xexternalref XtCallbackRec allSelectCallbacks`5B`5D; Xexternalref XtCallbackRec allMoveCallbacks`5B`5D; Xexternalref XtCallbackRec allToggleCallbacks`5B`5D; Xexternalref XtCallbackRec allScrollCallbacks`5B`5D; Xexternalref XtCallbackRec allScrollBackCallbacks`5B`5D; Xexternalref XtCallbackRec allSearchCallbacks`5B`5D; Xexternalref XtCallbackRec allContinueCallbacks`5B`5D; Xexternalref XtCallbackRec allCancelSearchCallbacks`5B`5D; Xexternalref XtCallbackRec artQuitCallbacks`5B`5D; Xexternalref XtCallbackRec artNextCallbacks`5B`5D; Xexternalref XtCallbackRec artNextUnreadCallbacks`5B`5D; Xexternalref XtCallbackRec artPrevCallbacks`5B`5D; Xexternalref XtCallbackRec artLastCallbacks`5B`5D; Xexternalref XtCallbackRec artNextGroupCallbacks`5B`5D; Xexternalref XtCallbackRec artGotoArticleCallbacks`5B`5D; Xexternalref XtCallbackRec artCatchUpCallbacks`5B`5D; Xexternalref XtCallbackRec artFedUpCallbacks`5B`5D; Xexternalref XtCallbackRec artMarkReadCallbacks`5B`5D; Xexternalref XtCallbackRec artMarkUnreadCallbacks`5B`5D; Xexternalref XtCallbackRec artUnsubCallbacks`5B`5D; Xexternalref XtCallbackRec artScrollCallbacks`5B`5D; Xexternalref XtCallbackRec artScrollBackCallbacks`5B`5D; Xexternalref XtCallbackRec artScrollEndCallbacks`5B`5D; Xexternalref XtCallbackRec artScrollBeginningCallbacks`5B`5D; Xexternalref XtCallbackRec artSubNextCallbacks`5B`5D; Xexternalref XtCallbackRec artSubPrevCallbacks`5B`5D; Xexternalref XtCallbackRec artKillSessionCallbacks`5B`5D; Xexternalref XtCallbackRec artKillLocalCallbacks`5B`5D; Xexternalref XtCallbackRec artKillGlobalCallbacks`5B`5D; Xexternalref XtCallbackRec artKillAuthorCallbacks`5B`5D; Xexternalref XtCallbackRec artSubSearchCallbacks`5B`5D; Xexternalref XtCallbackRec artContinueCallbacks`5B`5D; Xexternalref XtCallbackRec artCancelSearchCallbacks`5B`5D; Xexternalref XtCallbackRec artSortedCallbacks`5B`5D; Xexternalref XtCallbackRec artPostCallbacks`5B`5D; Xexternalref XtCallbackRec artExitCallbacks`5B`5D; Xexternalref XtCallbackRec artCheckPointCallbacks`5B`5D; Xexternalref XtCallbackRec artGripeCallbacks`5B`5D; Xexternalref XtCallbackRec artListOldCallbacks`5B`5D; Xexternalref XtCallbackRec artSaveCallbacks`5B`5D; Xexternalref XtCallbackRec artReplyCallbacks`5B`5D; Xexternalref XtCallbackRec artForwardCallbacks`5B`5D; Xexternalref XtCallbackRec artFollowupCallbacks`5B`5D; Xexternalref XtCallbackRec artCancelCallbacks`5B`5D; Xexternalref XtCallbackRec artRot13Callbacks`5B`5D; Xexternalref XtCallbackRec artHeaderCallbacks`5B`5D; Xexternalref XtCallbackRec artPrintCallbacks`5B`5D; Xtypedef struct buttonList `7B X char *label; X Arg *buttonArgs; X unsigned int size; X char *message; X`7D ButtonList; Xexternalref ButtonList AddButtonList`5B`5D; Xexternalref int AddPopupCount; Xexternalref ButtonList NgButtonList`5B`5D; Xexternalref int NgPopupCount; Xexternalref ButtonList AllButtonList`5B`5D; Xexternalref int AllPopupCount; Xexternalref ButtonList ArtButtonList`5B`5D; Xexternalref int ArtPopupCount; Xexternalref ButtonList ArtSpecButtonList`5B`5D; Xexternalref int ArtSpecPopupCount; Xexternalref int ArtSpecButtonListCount; Xstatic Widget customDialog = NULL; Xstatic Widget addList; Xstatic Widget removeList; Xstatic Widget okButton; Xstatic Widget applyButton; Xstatic Widget cancelButton; Xstatic int AddCount; Xstatic int NgCount; Xstatic int AllCount; Xstatic int ArtCount; Xstatic int ArtSpecCount; X Xstatic Widget generalDialog = NULL; Xstatic Widget saveBox; Xstatic Widget saveRadio; Xstatic Widget confBox; Xstatic Widget whichBox; Xstatic Widget genOkButton; Xstatic Widget genApplyButton; Xstatic Widget genCancelButton; Xstatic Widget cgIncludePrefix; Xstatic Widget cgNNTP; Xstatic Widget cgNewsrc; Xstatic Widget cgSaveNewsrc; Xstatic Widget cgSaveDir; Xstatic Widget cgSigFile; Xstatic Widget cgTempDir; Xstatic Widget cgTopLines; Xstatic Widget cgMinLines; Xstatic Widget cgMaxLines; Xstatic Widget cgEditCmd; Xstatic Widget cgPrtCmd; Xstatic Widget cgReplyTo; Xstatic Widget cgReplyPath; Xstatic Widget cgOrganization; Xstatic Widget cgHostName; Xstatic Widget cgSavePost; Xstatic Widget cgDeadLetters; X#ifndef VMS Xstatic Widget cgMailer; X#else Xstatic Widget cgPersonal; X#endif Xstatic Widget cgLineLength; Xstatic Widget cgWrapLength; Xstatic Widget cgRescan; Xstatic Widget cgWhichMb2Button; Xstatic Widget cgWhichMb3Button; Xstatic Widget cgSubjReadButton; Xstatic Widget cgInfoButton; Xstatic Widget cgKillButton; Xstatic Widget cgUpdateButton; Xstatic Widget cgInclHdrButton; Xstatic Widget cgInclSepButton; Xstatic Widget cgPageArtButton; Xstatic Widget cgSubjSortButton; Xstatic Widget cgAuthorFullButton; Xstatic Widget cgLineCountButton; Xstatic Widget cgAutoReadButton; Xstatic Widget cgCCButton; Xstatic Widget saveMbxButton; Xstatic Widget saveHeadersButton; Xstatic Widget saveSubdirsButton; Xstatic Widget saveOneDirButton; Xstatic Widget confQuitButton; Xstatic Widget confExitButton; Xstatic Widget confCatchUpButton; Xstatic Widget confArtCatchUpButton; Xstatic Widget confUnsubButton; Xstatic Widget confArtUnsubButton; Xstatic Widget confArtEndButton; Xstatic Widget confOverButton; X X#ifdef __STDC__ X#ifdef MOTIF X#define menuBtn(type, lbl, text)`09`09`09`09`09\ X label = XmStringLtoRCreate(text, XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNactivateCallback, type##lbl##Callbacks);`09`09\ X XtManageChild(XmCreatePushButton(type##Pulldowns`5Bi`5D, #lbl, cb, 2));\ X XmStringFree(label) X X#define menuPulldown(type, lbl)`09`09`09`09`09`09\ X i++;`09`09`09`09`09`09`09`09\ X type##Pulldowns`5Bi`5D = XmCreatePulldownMenu(MenuBar,#lbl, NULL, 0);`09 V\ X XtManageChild(XmCreateSeparator(type##Pulldowns`5Bi`5D, "sep", NULL, 0)) V;\ X label = XmStringLtoRCreate(#lbl, XmSTRING_DEFAULT_CHARSET);`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNsubMenuId, type##Pulldowns`5Bi`5D);`09`09`09\ X type##Menus`5Bi`5D = XmCreateCascadeButton(MenuBar, #lbl, cb, 2);`09\ X XmStringFree(label) X X#define subMenuPulldown(type,name,lbl)`09`09`09`09`09\ X tempPulldown = XmCreatePulldownMenu(type##Pulldowns`5Bi`5D, #name,NULL,0 V);\ X label = XmStringLtoRCreate(lbl,XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNsubMenuId, tempPulldown);`09`09`09\ X tempMenu = XmCreateCascadeButton(type##Pulldowns`5Bi`5D, #name, cb, 2);\ X XtManageChild(tempMenu);`09`09`09`09`09`09\ X XmStringFree(label); X X#define subMenuBtn(type,sub,name,lbl)`09`09`09`09`09\ X label = XmStringLtoRCreate(lbl,XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNactivateCallback, sub##Callbacks);`09`09\ X XtManageChild(XmCreatePushButton(tempPulldown, #name, cb, 2));`09\ X XmStringFree(label); X X#else X#define menuBtn(type, lbl, text)`09`09`09`09`09\ X label = DwtLatin1String(text);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNactivateCallback, type##lbl##Callbacks);`09\ X XtManageChild(DwtPushButtonCreate(type##Pulldowns`5Bi`5D, #lbl, cb, 2)); V\ X XtFree(label) X X#define menuPulldown(type, lbl)`09`09`09`09`09`09\ X i++;`09`09`09`09`09`09`09`09\ X type##Pulldowns`5Bi`5D = DwtMenu(MenuBar,#lbl, 0, 0, `09`09`09\ X`09DwtMenuPulldown, DwtOrientationVertical, NULL, NULL, NULL);`09\ X label = DwtLatin1String(#lbl);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNsubMenuId, type##Pulldowns`5Bi`5D);`09`09`09\ X type##Menus`5Bi`5D = DwtPullDownMenuEntryCreate(MenuBar,#lbl, cb, 2);`09 V\ X XtFree(label) X X#define subMenuPulldown(type,name,lbl)`09`09`09`09`09\ X tempPulldown = DwtMenu(type##Pulldowns`5Bi`5D, #name,0,0,`09`09\ X`09DwtMenuPulldown, DwtOrientationVertical, NULL, NULL, NULL);`09\ X label = DwtLatin1String(lbl);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNsubMenuId, tempPulldown);`09`09`09\ X tempMenu = DwtPullDownMenuEntryCreate(type##Pulldowns`5Bi`5D, #name, cb, V 2);\ X XtManageChild(tempMenu);`09`09`09`09`09`09\ X XtFree(label); X X#define subMenuBtn(type,sub,name,lbl)`09`09`09`09`09\ X label = DwtLatin1String(lbl);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNactivateCallback, sub##Callbacks);`09`09\ X XtManageChild(DwtPushButtonCreate(tempPulldown, #name, cb, 2));`09\ X XtFree(label); X X#endif X#else /* STDC */ X#ifdef MOTIF X#define menuBtn(type, lbl, text)`09`09`09`09`09\ X label = XmStringLtoRCreate(text, XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNactivateCallback, type/**/lbl/**/Callbacks);`09\ X XtManageChild(XmCreatePushButton(type/**/Pulldowns`5Bi`5D, "lbl", cb, 2) V);\ X XmStringFree(label) X X#define menuPulldown(type, lbl)`09`09`09`09`09`09\ X i++;`09`09`09`09`09`09`09`09\ X type/**/Pulldowns`5Bi`5D = XmCreatePulldownMenu(MenuBar,"lbl", NULL, 0); V\ X XtManageChild(XmCreateSeparator(type/**/Pulldowns`5Bi`5D, "sep", NULL, 0 V));\ X label = XmStringLtoRCreate("lbl", XmSTRING_DEFAULT_CHARSET);`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNsubMenuId, type/**/Pulldowns`5Bi`5D);`09`09\ X type/**/Menus`5Bi`5D = XmCreateCascadeButton(MenuBar, "lbl", cb, 2);`09\ X XmStringFree(label) X X#define subMenuPulldown(type,name,lbl)`09`09`09`09`09\ X tempPulldown = XmCreatePulldownMenu(type/**/Pulldowns`5Bi`5D, "name",NUL VL,0);\ X label = XmStringLtoRCreate(lbl,XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNsubMenuId, tempPulldown);`09`09`09\ X tempMenu = XmCreateCascadeButton(type/**/Pulldowns`5Bi`5D, "name", cb, 2 V);\ X XtManageChild(tempMenu);`09`09`09`09`09`09\ X XmStringFree(label); X X#define subMenuBtn(type,sub,name,lbl)`09`09`09`09`09\ X label = XmStringLtoRCreate(lbl,XmSTRING_DEFAULT_CHARSET);`09`09\ X XtSetArg(cb`5B0`5D, XmNlabelString, label);`09`09`09`09\ X XtSetArg(cb`5B1`5D, XmNactivateCallback, sub/**/Callbacks);`09`09\ X XtManageChild(XmCreatePushButton(tempPulldown, "name", cb, 2));`09\ X XmStringFree(label); X X#else X#define menuBtn(type, lbl, text)`09`09`09`09`09\ X label = DwtLatin1String(text);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNactivateCallback, type/**/lbl/**/Callbacks);`09\ X XtManageChild(DwtPushButtonCreate(type/**/Pulldowns`5Bi`5D, "lbl", cb, 2 V));\ X XtFree(label) X X#define menuPulldown(type, lbl)`09`09`09`09`09`09\ X i++;`09`09`09`09`09`09`09`09\ X type/**/Pulldowns`5Bi`5D = DwtMenu(MenuBar,"lbl", 0, 0, `09`09\ X`09DwtMenuPulldown, DwtOrientationVertical, NULL, NULL, NULL);`09\ X label = DwtLatin1String("lbl");`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNsubMenuId, type/**/Pulldowns`5Bi`5D);`09`09\ X type/**/Menus`5Bi`5D = DwtPullDownMenuEntryCreate(MenuBar,"lbl", cb, 2); V\ X XtFree(label) X X#define subMenuPulldown(type,name,lbl)`09`09`09`09`09\ X tempPulldown = DwtMenu(type/**/Pulldowns`5Bi`5D, "name",0,0,`09`09\ X`09DwtMenuPulldown, DwtOrientationVertical, NULL, NULL, NULL);`09\ X label = DwtLatin1String(lbl);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNsubMenuId, tempPulldown);`09`09`09\ X tempMenu = DwtPullDownMenuEntryCreate(type/**/Pulldowns`5Bi`5D, "name", V cb, 2);\ X XtManageChild(tempMenu);`09`09`09`09`09`09\ X XtFree(label); X X#define subMenuBtn(type,sub,name,lbl)`09`09`09`09`09\ X label = DwtLatin1String(lbl);`09`09`09`09`09\ X XtSetArg(cb`5B0`5D, DwtNlabel, label);`09`09`09`09`09\ X XtSetArg(cb`5B1`5D, DwtNactivateCallback, sub/**/Callbacks);`09`09\ X XtManageChild(DwtPushButtonCreate(tempPulldown, "name", cb, 2));`09\ X XtFree(label); X X#endif X#endif /* STDC */ X Xvoid XmakeMenus() X`7B X Arg cb`5B2`5D; X XmString label; X int i = -1; X X AddCount = AddPopupCount;`09`09`09`09/* store original counters */ X NgCount = NgPopupCount; X AllCount = AllPopupCount; X ArtCount = ArtPopupCount; X ArtSpecCount = ArtSpecPopupCount; X font = XLoadQueryFont(XtDisplay(TopLevel), X`09"-*-Menu-Medium-R-Normal--12-120-75-*"); X if (font == NULL) `7B X font = XLoadQueryFont(XtDisplay(TopLevel), X`09 "-*-Helvetica-Bold-R-Normal--12-120-*"); X`09if (font == NULL) `7B X font = XLoadQueryFont(XtDisplay(TopLevel),"fixed"); X `7D X `7D X if (font == NULL) `7B X`09printf("Can't find any fonts!"); X`09exit(0); X `7D X#ifdef MOTIF X fontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET); X#else X fontList = DwtCreateFontList(font, 1); /* ISO_LATIN1 */ X#endif X X menuPulldown(add,File); X`09menuBtn(add,Quit,"Quit - Unsubscribe Remaining Entries"); X menuPulldown(add,Add); X`09menuBtn(add,First,"Add as First Entry"); X`09menuBtn(add,Last,"Add as Last Entry"); X`09menuBtn(add,After,"Add After Other Group"); X`09menuBtn(add,Unsub,"Add Unsubscribed"); X menuPulldown(add,Customize); X`09subMenuPulldown(add,addNg,"Newsgroup Mode"); X`09subMenuBtn(add,ngMenus,addNgMenus,"Menu Buttons..."); X`09subMenuBtn(add,ngPopups,addNgPopups,"Popup Buttons..."); X`09subMenuPulldown(add,addArt,"Article Mode"); X`09subMenuBtn(add,artMenus,addArtMenus,"Menu Buttons..."); X`09subMenuBtn(add,artPopups,addArtPopups,"Popup Buttons..."); X`09subMenuPulldown(add,addAll,"All Groups Mode"); X`09subMenuBtn(add,allMenus,addAllMenus,"Menu Buttons..."); X`09subMenuBtn(add,allPopups,addAllPopups,"Popup Buttons..."); X`09subMenuPulldown(add,addArt,"Add Groups Mode"); X`09subMenuBtn(add,addMenus,addAddMenus,"Menu Buttons..."); X`09subMenuBtn(add,addPopups,addAddPopups,"Popup Buttons..."); X`09menuBtn(add,General,"General..."); X`09menuBtn(add,SaveCustom,"Save Current Settings"); X X i = -1; X menuPulldown(ng,File); X`09menuBtn(ng,Quit,"Quit"); X`09menuBtn(ng,Exit,"Exit - No Newsrc Update"); X menuPulldown(ng,Group); X`09menuBtn(ng,Read,"Read Newsgroup"); X`09menuBtn(ng,Open,"Open Newsgroup"); X`09menuBtn(ng,CatchUp,"Catch Up Newsgroup"); X`09menuBtn(ng,Subscribe,"Subscribe"); X`09menuBtn(ng,Unsub,"Unsubscribe"); X`09menuBtn(ng,Goto,"Go To Newsgroup"); X`09menuBtn(ng,Rescan,"Rescan Server"); X`09menuBtn(ng,CheckPoint,"Checkpoint Newsrc"); X`09menuBtn(ng,AllGroups,"View All Groups"); X`09menuBtn(ng,ToggleGroups,"Toggle Groups"); X menuPulldown(ng,Move); X`09menuBtn(ng,Select,"Select Groups To Move"); X`09menuBtn(ng,Move,"Move Selected Groups"); X menuPulldown(ng,Send); X `09menuBtn(ng,Gripe,"Send Gripe to Maintainer"); X`09menuBtn(ng,Post,"Post an Article"); X menuPulldown(ng,Customize); X`09subMenuPulldown(ng,ngNg,"Newsgroup Mode"); X`09subMenuBtn(ng,ngMenus,ngNgMenus,"Menu Buttons..."); X`09subMenuBtn(ng,ngPopups,ngNgPopups,"Popup Buttons..."); X`09subMenuPulldown(ng,ngArt,"Article Mode"); X`09subMenuBtn(ng,artMenus,ngArtMenus,"Menu Buttons..."); X`09subMenuBtn(ng,artPopups,ngArtPopups,"Popup Buttons..."); X`09subMenuPulldown(ng,ngAll,"All Groups Mode"); X`09subMenuBtn(ng,allMenus,ngAllMenus,"Menu Buttons..."); X`09subMenuBtn(ng,allPopups,ngAllPopups,"Popup Buttons..."); X`09subMenuPulldown(ng,ngArt,"Add Groups Mode"); X`09subMenuBtn(ng,addMenus,ngAddMenus,"Menu Buttons..."); X`09subMenuBtn(ng,addPopups,ngAddPopups,"Popup Buttons..."); X`09menuBtn(ng,General,"General..."); X`09menuBtn(ng,SaveCustom,"Save Current Settings"); X X i = -1; X menuPulldown(art,File); X`09menuBtn(art,CheckPoint,"Checkpoint .newsrc"); X `09menuBtn(art,Quit,"Return to Newsgroup Mode"); X`09menuBtn(art,Exit,"Mark All Unread and Exit"); X menuPulldown(art,Read); X`09menuBtn(art,NextUnread,"Next Unread"); X`09menuBtn(art,SubNext,"Next With Current Subject"); X`09menuBtn(art,SubPrev,"Previous With Current Subject"); X`09menuBtn(art,Next,"Next Article"); X`09menuBtn(art,Prev,"Previous Article"); X`09menuBtn(art,Last,"Last Article Read"); X menuPulldown(art,Group); X`09menuBtn(art,NextGroup,"Move to Next Group"); X`09menuBtn(art,CatchUp,"Catch Up Group"); X`09menuBtn(art,FedUp,"Mark All Read and Go To Next Group"); X`09menuBtn(art,Unsub,"Unsubscribe"); X menuPulldown(art,Article); X`09menuBtn(art,GotoArticle,"Go To Article"); X`09menuBtn(art,MarkRead,"Mark Selected Articles Read"); X`09menuBtn(art,MarkUnread,"Mark Selected Articles Unread"); X`09menuBtn(art,Post,"Post an Article"); X`09menuBtn(art,Print,"Print Current Article"); X`09menuBtn(art,Save,"Save Current Article"); X`09menuBtn(art,Reply,"Send a Reply"); X`09menuBtn(art,Forward,"Forward Current Article"); X`09menuBtn(art,Followup,"Post a Followup to Current Article"); X`09menuBtn(art,Rot13,"Decode Encoded Article"); X`09menuBtn(art,Sorted,"Toggle Subject Sorting"); X`09menuBtn(art,Header,"Toggle Full/Stripped Header"); X menuBtn(art,ListOld,"List all articles"); X`09menuBtn(art,Gripe,"Send a Gripe"); X menuPulldown(art,Kill); X`09menuBtn(art,KillSession,"This Session Only"); X`09menuBtn(art,KillLocal,"This Newsgroup Only"); X`09menuBtn(art,KillGlobal,"All Newsgroups"); X`09menuBtn(art,KillAuthor,"All Articles With This Author"); X menuPulldown(art,Search); X`09menuBtn(art,SubSearch,"Subject Search"); X`09menuBtn(art,Continue,"Continue Search"); X`09menuBtn(art,CancelSearch,"Cancel Search"); X menuPulldown(art,Customize); X`09subMenuPulldown(art,artNg,"Newsgroup Mode"); X`09subMenuBtn(art,ngMenus,artNgMenus,"Menu Buttons..."); X`09subMenuBtn(art,ngPopups,artNgPopups,"Popup Buttons..."); X`09subMenuPulldown(art,artArt,"Article Mode"); X`09subMenuBtn(art,artMenus,artArtMenus,"Menu Buttons..."); X`09subMenuBtn(art,artPopups,artArtPopups,"Popup Buttons..."); X`09subMenuPulldown(art,artAll,"All Groups Mode"); X`09subMenuBtn(art,allMenus,artAllMenus,"Menu Buttons..."); X`09subMenuBtn(art,allPopups,artAllPopups,"Popup Buttons..."); X`09subMenuPulldown(art,artArt,"Add Groups Mode"); X`09subMenuBtn(art,addMenus,artAddMenus,"Menu Buttons..."); X`09subMenuBtn(art,addPopups,artAddPopups,"Popup Buttons..."); X`09menuBtn(art,General,"General..."); X`09menuBtn(art,SaveCustom,"Save Current Settings"); X X i = -1; X menuPulldown(all,File); X`09menuBtn(all,Quit,"Quit"); X`09menuBtn(all,Goto,"Go To Group"); X menuPulldown(all,Subscribe); X`09menuBtn(all,Sub,"Subscribe"); X`09menuBtn(all,First,"Subscribe First"); X`09menuBtn(all,Last,"Subscribe Last"); X`09menuBtn(all,After,"Subscribe After Group"); X`09menuBtn(all,Unsub,"Unsubscribe"); X menuPulldown(all,Move); X`09menuBtn(all,Select,"Select Groups to Move"); X`09menuBtn(all,Move,"Move Groups"); X`09menuBtn(all,Toggle,"Toggle Newsrc/Alpha Order"); X menuPulldown(all,Search); X`09menuBtn(all,Search,"Search for Group"); X menuBtn(all,Continue,"Continue search"); X menuBtn(all,CancelSearch,"Cancel search"); X menuPulldown(all,Customize); X`09subMenuPulldown(all,allNg,"Newsgroup Mode"); X`09subMenuBtn(all,ngMenus,allNgMenus,"Menu Buttons..."); X`09subMenuBtn(all,ngPopups,allNgPopups,"Popup Buttons..."); X`09subMenuPulldown(all,allArt,"Article Mode"); X`09subMenuBtn(all,artMenus,allArtMenus,"Menu Buttons..."); X`09subMenuBtn(all,artPopups,allArtPopups,"Popup Buttons..."); X`09subMenuPulldown(all,allAll,"All Groups Mode"); X`09subMenuBtn(all,allMenus,allAllMenus,"Menu Buttons..."); X`09subMenuBtn(all,allPopups,allAllPopups,"Popup Buttons..."); X`09subMenuPulldown(all,allArt,"Add Groups Mode"); X`09subMenuBtn(all,addMenus,allAddMenus,"Menu Buttons..."); X`09subMenuBtn(all,addPopups,allAddPopups,"Popup Buttons..."); X`09menuBtn(all,General,"General..."); X`09menuBtn(all,SaveCustom,"Save Current Settings"); X`7D Xstatic Widget popup_menu; X Xstatic void pop_up(widget, event, params, num_params) XWidget`09widget; XXButtonPressedEvent *event; Xchar`09*params; Xint`09num_params; X`7B X if (!XtIsRealized(popup_menu)) X`09XtRealizeWidget(popup_menu); X X#ifdef MOTIF X XmMenuPosition(popup_menu, event); X#else X DwtMenuPosition(popup_menu, event); X#endif X XtManageChild(popup_menu); X`7D X X#ifndef MOTIF Xstatic void motionhint(m,closure,event) X MenuWidget m; X Opaque closure; X XPointerMovedEvent *event; X`7B X if (event->is_hint == NotifyHint) `7B X`09if (event->state & Button1Mask `7C`7C event->state & Button2Mask `7C`7C X`09`09event->state & Button3Mask) `7B X`09 event->state `7C= Button2Mask;`09/* hack in MB2 for XUI */ X`09`7D X `7D X`7D`09 `20 X#endif X Xstatic char popup2Trans`5B`5D = ":pop_up()"; Xstatic char popup3Trans`5B`5D = ":pop_up()"; X Xstatic XtTranslations popupParsed; X Xstatic XtActionsRec popupAction`5B`5D = `7B X `7B"pop_up", (XtActionProc)pop_up`7D, X`7D; Xexternalref XtCallbackRec artSubNextCallbacks`5B`5D; Xexternalref XtCallbackRec artQuitCallbacks`5B`5D; X Xvoid makePopup(parent) XWidget`09parent; X`7B X Arg args`5B10`5D; X Widget pop; X int i; X X XtAddActions(popupAction, XtNumber(popupAction)); X if (app_resources.popupButton == 3) `7B X`09popupParsed = XtParseTranslationTable(popup3Trans); X `7D else `7B X`09popupParsed = XtParseTranslationTable(popup2Trans); X `7D X XtOverrideTranslations(parent, popupParsed); X X#ifdef MOTIF X if (app_resources.popupButton == 2) `7B X`09XtSetArg(args`5B0`5D, XmNwhichButton, Button2); X `7D else `7B X`09XtSetArg(args`5B0`5D, XmNwhichButton, Button3); X `7D X popup_menu = XmCreatePopupMenu(parent, "popup", args, 1); X#else X if (app_resources.popupButton == 2) `7B X`09popup_menu = DwtMenuPopupCreate(parent,"popup", NULL, 0); X `7D else `7B X`09i = 0; X`09XtSetArg(args`5Bi`5D, DwtNwidth, 5);i++; X`09XtSetArg(args`5Bi`5D, DwtNheight, 5);i++; X`09XtSetArg(args`5Bi`5D, XtNallowShellResize, True);i++; X`09XtSetArg(args`5Bi`5D, XtNoverrideRedirect, True);i++; X`09pop = XtCreatePopupShell("popShell", menupopupWidgetClass,`20 X`09`09`09`09 parent, args, i); X`09i = 0; X`09XtSetArg(args`5Bi`5D, DwtNmenuType, DwtMenuPopup);i++; X`09popup_menu = XtCreateWidget("popup", menuwidgetclass, pop, args, i); X`09XGrabButton(`09`09`09/* Do a grab for the button */ X`09 XtDisplay(popup_menu),`09/* event that pops the menu up */ X`09 app_resources.popupButton,`09/* for the parent of the shell */ X`09 AnyModifier,`09`09/* widget */ X`09 XtWindow(parent), X`09 True, X`09 ButtonReleaseMask `7C PointerMotionHintMask, X`09 GrabModeAsync, X`09 GrabModeAsync, X`09 None, X`09 None); X XtAddEventHandler(popup_menu, PointerMotionHintMask`7CButtonMotionMa Vsk, X`09`09FALSE, motionhint, NULL); X `7D X#endif X AddPopupButtons = ARRAYALLOC(Widget, AddPopupCount); X doPopups(app_resources.addPopupList, popup_menu, AddPopupButtons, X`09`09AddButtonList, &AddPopupCount); X X NgPopupButtons = ARRAYALLOC(Widget, NgPopupCount); X doPopups(app_resources.ngPopupList, popup_menu, NgPopupButtons, X`09`09NgButtonList, &NgPopupCount); X X AllPopupButtons = ARRAYALLOC(Widget, AllPopupCount); X doPopups(app_resources.allPopupList, popup_menu, AllPopupButtons, X`09`09AllButtonList, &AllPopupCount); X X ArtPopupButtons = ARRAYALLOC(Widget, ArtPopupCount); X doPopups(app_resources.artPopupList, popup_menu, ArtPopupButtons, X`09`09ArtButtonList, &ArtPopupCount); X`7D Xstatic void XdoPopups(resource, box, buttons, buttonList, size) Xchar *resource; XWidget box; XWidget *buttons; XButtonList *buttonList; Xint *size; X`7B X char *ptr, *token, *savePtr; X int j, i = 0; X Arg arg`5B1`5D; X X if (resource) `7B X`09savePtr = ptr = XtNewString(resource); X X`09while ((token = strtok(ptr, ", \t\n")) != NIL(char)) `7B X`09 /* find name */ X`09 for (j = 0; j < *size; j++) `7B X`09`09if (STREQ(token, (char *) buttonList`5Bj`5D.buttonArgs`5B0`5D.value)) V `7B X#ifdef MOTIF X`09`09 if (buttonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09`09buttonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)XmStringLtoRCreate( X`09`09`09`09buttonList`5Bj`5D.label, XmSTRING_DEFAULT_CHARSET); X`09`09 `7D X`09`09 buttons`5Bi`5D = XmCreatePushButtonGadget(box, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs, X`09`09`09`09`09 buttonList`5Bj`5D.size); X#else X`09`09 if (buttonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09`09buttonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)DwtLatin1String(buttonList`5Bj`5D.label); X`09`09 `7D X`09`09 buttons`5Bi`5D = DwtPushButtonGadgetCreate(box, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09`09 buttonList`5Bj`5D.buttonArgs, X`09`09`09`09`09 buttonList`5Bj`5D.size); X#endif X`09`09 i++; X`09`09 break; X`09`09`7D X`09 `7D X`09 if (j == *size && buttonList == ArtButtonList) `7B X`09`09for (j = 0; j < ArtSpecButtonListCount; j++) `7B X`09`09 if (STREQ(token, X`09`09`09(char *) ArtSpecButtonList`5Bj`5D.buttonArgs`5B0`5D.value)) `7B X#ifdef MOTIF X`09`09`09if (ArtSpecButtonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09 `09 ArtSpecButtonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)XmStringLtoRCreate( X`09`09`09 ArtSpecButtonList`5Bj`5D.label, XmSTRING_DEFAULT_CHARSET); X`09`09`09`7D X`09`09 `09buttons`5Bi`5D = XmCreatePushButtonGadget(box, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.buttonArgs, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.size); X#else X`09`09`09if (ArtSpecButtonList`5Bj`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09 `09 ArtSpecButtonList`5Bj`5D.buttonArgs`5B1`5D.value = X`09`09`09 (XtArgVal)DwtLatin1String(ArtSpecButtonList`5Bj`5D.label); X`09`09`09`7D X`09`09 `09buttons`5Bi`5D = DwtPushButtonGadgetCreate(box, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.buttonArgs`5B0`5D.value, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.buttonArgs, X`09`09`09`09 ArtSpecButtonList`5Bj`5D.size); X#endif X`09`09 `09i++; X`09`09 `09break; X`09`09 `7D X`09 `7D X`09`09if (j == ArtSpecButtonListCount) `7B X`09`09 j = *size; X`09`09`7D X`09 `7D X`09 if (j == *size) `7B X`09`09mesgPane(XRN_SERIOUS, "XRN error: bad button name: %s", token); X`09 `7D X`09 ptr = NIL(char); X`09`7D X`09*size = i; X`09XtFree(savePtr); X`09 X `7D else `7B X`09for (i = 0; i < *size; i++) `7B X`09 `20 X#ifdef MOTIF X`09 if (buttonList`5Bi`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09 buttonList`5Bi`5D.buttonArgs`5B1`5D.value = X`09 `09 (XtArgVal) XmStringLtoRCreate(buttonList`5Bi`5D.label, X`09`09`09`09XmSTRING_DEFAULT_CHARSET); X`09 `7D X`09 buttons`5Bi`5D = XmCreatePushButtonGadget(box, X`09`09`09`09`09buttonList`5Bi`5D.buttonArgs`5B0`5D.value, X`09`09`09`09`09buttonList`5Bi`5D.buttonArgs, X`09`09`09`09`09buttonList`5Bi`5D.size); X#else X`09 if (buttonList`5Bi`5D.buttonArgs`5B1`5D.value == NULL) `7B X`09`09buttonList`5Bi`5D.buttonArgs`5B1`5D.value = X`09 `09 (XtArgVal)DwtLatin1String(buttonList`5Bi`5D.label); X`09 `7D X`09 buttons`5Bi`5D = DwtPushButtonGadgetCreate(box, X`09`09`09`09buttonList`5Bi`5D.buttonArgs`5B0`5D.value, X`09`09`09`09buttonList`5Bi`5D.buttonArgs, X`09`09`09`09buttonList`5Bi`5D.size); X#endif X`09`7D X `7D X return; X`7D Xvoid XresetPopupSize() X`7B X#ifndef MOTIF X static Arg popupResizeArg`5B`5D = `7B X`09`7BDwtNheight, 0`7D, X `7D; X XtSetValues(popup_menu, popupResizeArg, XtNumber(popupResizeArg)); X#endif X`7D X Xstatic Widget makeButton(parent, name, label) XWidget parent; Xchar *name; Xchar *label; X`7B X#ifdef MOTIF X XmString str; X Arg arg`5B1`5D; X Widget ret; X str = XmStringLtoRCreate(label, XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5B0`5D,XmNlabelString, str); X XtManageChild(ret = XmCreateToggleButtonGadget(parent, name, arg, 1)); X XmStringFree(str); X return ret; X#else X DwtCompString str; X Arg arg`5B1`5D; X Widget ret; X str = DwtLatin1String(label); X XtSetArg(arg`5B0`5D,DwtNlabel, str); X XtManageChild(ret = DwtToggleButtonGadgetCreate(parent, name, arg, 1)); X XtFree(str); X return ret; X#endif X`7D Xstatic Widget pushButton(x,y,parent,name,label) XDimension x; XDimension y; XWidget parent; Xchar *name; Xchar *label; X`7B X#ifdef MOTIF X XmString str; X Arg arg`5B3`5D; X Widget ret; X X XtSetArg(arg`5B0`5D, XmNx, x);XtSetArg(arg`5B1`5D,XmNy,y); X str = XmStringLtoRCreate(label, XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5B2`5D,XmNlabelString, str); X XtManageChild(ret = XmCreateToggleButtonGadget(parent, name, arg, 3)); X XmStringFree(str); X return ret; X X#else X DwtCompString str; X Arg arg`5B4`5D; X Widget ret; X X XtSetArg(arg`5B0`5D, DwtNx, x);XtSetArg(arg`5B1`5D,DwtNy,y); X str = DwtLatin1String(label); X XtSetArg(arg`5B2`5D,DwtNlabel, str); X XtSetArg(arg`5B3`5D, DwtNfont,fontList); X XtManageChild(ret =`09DwtToggleButtonGadgetCreate(parent, name, arg, 4)) V; X XtFree(str); X X return ret; X#endif X`7D Xstatic void makeLabel(x,y,text) XDimension x; XDimension y; Xchar *text; X`7B X XmString str; X int i; X Arg arg`5B10`5D; X X#ifdef MOTIF X str = XmStringLtoRCreate(text,XmSTRING_DEFAULT_CHARSET); X i = 0; X XtSetArg(arg`5Bi`5D, XmNx,`09`09x);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09y);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString, `09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(XmCreateLabelGadget(generalDialog,"genLbl",arg,i)); X#else X str = DwtLatin1String(text); X i = 0; X XtSetArg(arg`5Bi`5D, DwtNx,`09`09x);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09y);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNlabel, `09str);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(DwtLabelGadgetCreate(generalDialog,"genLbl",arg,i)); X#endif X`7D X Xstatic Widget makeText(x,y,cols) XDimension x; XDimension y; XDimension cols; X`7B X int i; X Arg arg`5B10`5D; X Widget ret; X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNx,`09`09x);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09y);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNrows,`09`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNcolumns,`09cols);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(ret = XmCreateText(generalDialog,"genTxt",arg,i)); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNx,`09`09x);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09y);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNrows,`09`091);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNcols,`09`09cols);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNresizeWidth,`09False);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(ret = DwtSTextCreate(generalDialog,"genTxt",arg,i)); X#endif X return ret; X`7D Xstatic void makeGeneralMenu() X`7B X Arg arg`5B10`5D; X int i; X XmString str; X X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNwidth, `09`09640);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNheight,`09`09600);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNresizePolicy,`09XmRESIZE_GROW);`09i++; X XtSetArg(arg`5Bi`5D, XmNautoUnmanage,`09False);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, XmNdialogStyle,`09XmDIALOG_APPLICATION_MODAL);i++; X generalDialog = XmCreateBulletinBoardDialog(TopLevel, "generalDialog",ar Vg,i); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNunits,`09`09DwtPixelUnits);`09i++; X XtSetArg(arg`5Bi`5D, DwtNwidth, `09640);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNautoUnmanage,`09False);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, DwtNstyle,`09`09DwtModal);`09i++; X generalDialog = DwtDialogBoxPopupCreate(TopLevel, "generalDialog",arg,i) V; X#endif X X makeLabel(20,30,"NNTP Server"); X cgNNTP = makeText(150,25,28); X makeLabel(400,30,"Include Prefix"); X cgIncludePrefix = makeText(520, 25, 4); X X makeLabel(20,70,"Host Name"); X cgHostName = makeText(150,65,28); X makeLabel(400,70,"Newsrc file"); X cgNewsrc = makeText(520,65,28); X X makeLabel(20,110,"Saved Newsrc file"); X cgSaveNewsrc = makeText(150,105,28); X makeLabel(400,110,"Save directory"); X cgSaveDir = makeText(520,105,28); X X makeLabel(20,150,"Signature file"); X cgSigFile = makeText(150,145,28); X makeLabel(400,150,"Temp directory"); X cgTempDir = makeText(520,145,28); X X makeLabel(20,190,"Save Postings"); X cgSavePost = makeText(150,185,28); X makeLabel(400,190,"Dead Letters"); X cgDeadLetters = makeText(520,185,28); X X#ifndef VMS X makeLabel(20,230,"Mailer"); X cgMailer = makeText(150,225,60); X#else X makeLabel(20,230,"Personal Name"); X cgPersonal = makeText(150,225,60); X#endif X X makeLabel(20,270,"Line Length"); X cgLineLength = makeText(150,265,3); X makeLabel(225,270,"Wrap Length"); X cgWrapLength = makeText(320,265,3); X makeLabel(400,270,"Rescan Time"); X cgRescan = makeText(520,265,4); X X makeLabel(20,310,"Top Lines"); X cgTopLines = makeText(150,305,3); X makeLabel(225,310,"Min Lines"); X cgMinLines = makeText(320,305,3); X makeLabel(400,310,"Max Lines"); X cgMaxLines = makeText(520,305,3); X X makeLabel(20,350,"Editor Command"); X cgEditCmd = makeText(150,345,28); X makeLabel(400,350,"Print Command"); X cgPrtCmd = makeText(520,345,28); X X makeLabel(20,390,"Reply To"); X cgReplyTo = makeText(150,385,28); X makeLabel(400,390,"Reply Path"); X cgReplyPath = makeText(520,385,28); X X makeLabel(20,430,"Organization"); X cgOrganization = makeText(150,425,60); X X cgSubjReadButton = pushButton(100,480,generalDialog,"cgSubjRead","Subjec Vt Read"); X cgInfoButton = pushButton(240,480,generalDialog,"cgInfo","Info Messages" V); X cgKillButton = pushButton(410,480,generalDialog,"cgKill","Kill Files"); X cgUpdateButton = pushButton(520,480,generalDialog,"cgUpdate","Update New Vsrc"); X cgInclHdrButton = pushButton(100,510,generalDialog,"cgInclHdr","Include V Header"); X cgInclSepButton = pushButton(240,510,generalDialog,"cgInclSep","Include V Separator"); X cgPageArtButton = pushButton(410,510,generalDialog,"cgPageArt","Page Art Vicles"); X cgSubjSortButton = pushButton(520,510,generalDialog,"cgSubjSort","Sorted V Subjects"); X cgAuthorFullButton = pushButton(100,540,generalDialog,"cgAuthorFull","Fu Vll Name"); X cgLineCountButton = pushButton(240,540,generalDialog,"cgLineCount","Show V Line Count"); X cgAutoReadButton = pushButton(410,540,generalDialog,"cgAutoRead", "Read V First"); X cgCCButton = pushButton(520,540,generalDialog,"cgCC", "CC in Mail"); X X makeLabel(335,570,"Save Mode"); X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNx,`09`09165);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09595);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNwidth,`09`0925);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNheight,`09`0983);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNorientation,`09XmHORIZONTAL);`09i++; X XtSetArg(arg`5Bi`5D, XmNisHomogeneous,`09False);`09`09i++; X XtManageChild(saveBox = X`09XmCreateRowColumn(generalDialog, "saveBox", arg,i) X`09); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNx,`09`09165);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09595);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNorientation,`09DwtOrientationHorizontal);`09i++ V; X XtSetArg(arg`5Bi`5D, DwtNmenuIsHomogeneous,False);`09i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(saveBox = X`09DwtMenuCreate(generalDialog, "saveBox", arg,i) X`09); X#endif X saveMbxButton = makeButton(saveBox,"saveMbx","Mailbox"); X saveHeadersButton = makeButton(saveBox,"saveHeaders","Headers"); X X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNorientation,`09XmHORIZONTAL);`09i++; X XtManageChild(saveRadio = X`09XmCreateRadioBox(saveBox, "saveRadio", arg,i) X`09); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNborderWidth,`092);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNorientation,`09DwtOrientationHorizontal);`09i++ V; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(saveRadio = X`09DwtRadioBoxCreate(saveBox, "saveRadio", arg,i) X`09); X#endif X saveSubdirsButton = makeButton(saveRadio,"saveSubdirs","Subdirectory"); X saveOneDirButton = makeButton(saveRadio,"saveOneDir","One Directory"); X X makeLabel(80,650,"Popup Button"); X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNx,`09`0965);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09675);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNorientation,`09XmHORIZONTAL);`09i++; X XtManageChild(whichBox = X`09XmCreateRadioBox(generalDialog, "saveBox", arg,i) X`09); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNx,`09`0965);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09675);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNorientation,`09DwtOrientationHorizontal);`09i++ V; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(whichBox = X`09DwtRadioBoxCreate(generalDialog, "saveBox", arg,i) X`09); X#endif X cgWhichMb2Button = makeButton(whichBox,"cgWhichMb2","MB2"); X cgWhichMb3Button = makeButton(whichBox,"cgWhichMb3","MB3"); X X makeLabel(375,650,"Confirm"); X#ifdef MOTIF X i = 0; X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNx,`09`09210);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09675);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNwidth,`09`0925);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNheight,`09`0925);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNnumColumns,`092);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNpacking,`09XmPACK_COLUMN);`09i++; X XtSetArg(arg`5Bi`5D, XmNorientation,`09XmHORIZONTAL);`09i++; X XtManageChild(confBox = X`09XmCreateRowColumn(generalDialog, "confBox", arg,i) X`09); X#else X i = 0; X XtSetArg(arg`5Bi`5D, DwtNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNx,`09`09210);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09675);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNmenuNumColumns,2);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNmenuPacking,`09DwtMenuPackingColumn);i++; X XtSetArg(arg`5Bi`5D, DwtNorientation,`09DwtOrientationHorizontal);`09i++ V; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild(confBox = X`09DwtMenuCreate(generalDialog, "confBox", arg,i) X`09); X X#endif X confQuitButton = makeButton(confBox,"confQuit","Quit"); X confExitButton = makeButton(confBox,"confExit","Exit"); X confCatchUpButton = makeButton(confBox,"confCatchUp","NG Catch Up"); X confArtCatchUpButton = makeButton(confBox,"confArtCatchUp","Art Catch Up V"); X confUnsubButton = makeButton(confBox,"confUnsub","NG Unsub"); X confArtUnsubButton = makeButton(confBox,"confArtUnsub","Art Unsub"); X confArtEndButton = makeButton(confBox,"confArtEnd","Subject End"); X confOverButton = makeButton(confBox,"confOver", "Overwrite"); X X#ifdef MOTIF X i = 0; X str = XmStringLtoRCreate("OK", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`0975);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNshowAsDefault,`09True);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cgOKCallback); i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild( X`09genOkButton = XmCreatePushButton(generalDialog, "cgokButton", arg, i)); X i = 0; X str = XmStringLtoRCreate("Apply", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09310);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cgApplyCallback);i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild( X`09genApplyButton = XmCreatePushButton(generalDialog, "cgapplyButton", arg, V i)); X i = 0; X str = XmStringLtoRCreate("Cancel", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09550);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cgCancelCallback);i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild( X`09genCancelButton = XmCreatePushButton(generalDialog, "cgcancelButton", arg V,i)); X i = 0; X XtSetArg(arg`5Bi`5D, XmNdefaultButton, genOkButton);i++; X XtSetValues(generalDialog, arg, i); X#else X i = 0; X str = DwtLatin1String("OK"); X XtSetArg(arg`5Bi`5D, DwtNx,`09`0975);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNlabel,`09`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNactivateCallback,cgOKCallback); i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild( X`09genOkButton = DwtPushButtonCreate(generalDialog, "cgokButton", arg, i)); X i = 0; X str = DwtLatin1String("Apply"); X XtSetArg(arg`5Bi`5D, DwtNx,`09`09310);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNlabel,`09`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNactivateCallback,cgApplyCallback);i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild( X`09genApplyButton = DwtPushButtonCreate(generalDialog, "cgapplyButton", arg, V i)); X i = 0; X str = DwtLatin1String("Cancel"); X XtSetArg(arg`5Bi`5D, DwtNx,`09`09550);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNy,`09`09750);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNlabel,`09`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNactivateCallback,cgCancelCallback);i++; X XtSetArg(arg`5Bi`5D, DwtNfont,`09`09fontList);`09i++; X XtManageChild( X`09genCancelButton = DwtPushButtonCreate(generalDialog, "cgcancelButton", ar Vg,i)); X i = 0; X XtSetArg(arg`5Bi`5D, DwtNdefaultButton, genOkButton);i++; X XtSetValues(generalDialog, arg, i); X#endif X`7D Xstatic void updateText(widget, field) XWidget widget; Xchar **field; X`7B X char *tempStr; X#ifdef MOTIF X tempStr = XmTextGetString(widget); X#else X tempStr = DwtSTextGetString(widget); X#endif X X if (tempStr == NULL `7C`7C strlen(tempStr) == 0) `7B X`09*field = NULL; X `7D else `7B X`09*field = tempStr; X `7D X`7D Xstatic int getInt(widget,def) XWidget widget; Xint def; X`7B X int ret; X char *tempStr; X X ret = def; X#ifdef MOTIF X tempStr = XmTextGetString(widget); X#else X tempStr = DwtSTextGetString(widget); X#endif X if (tempStr != NULL && strlen(tempStr) != 0) `7B X`09ret = atoi(tempStr); X `7D X XtFree(tempStr); X return ret; X`7D Xstatic void UpdateGeneral() X`7B X char *tempStr; X int value; X int topLines, minLines, maxLines; X int lineLength, breakLength, rescanTime; X updateText(cgNNTP,&app_resources.nntpServer); X updateText(cgNewsrc,&app_resources.newsrcFile); X updateText(cgIncludePrefix,&app_resources.includePrefix); X updateText(cgSaveNewsrc,&app_resources.saveNewsrcFile); X updateText(cgSaveDir,&app_resources.saveDir); X updateText(cgSigFile,&app_resources.signatureFile); X updateText(cgTempDir,&app_resources.tmpDir); X topLines = getInt(cgTopLines, app_resources.topLines); X minLines = getInt(cgMinLines, app_resources.minLines); X maxLines = getInt(cgMaxLines, app_resources.maxLines); X if (topLines < 3) `7B X`09warning("Top Lines must be greater than 3. Top/Min/Max Lines not changed" V); X `7D else `7B X`09if (topLines > 40) `7B X`09 warning("Top Lines must be less than 40. Top/Min/Max Lines not change Vd."); X`09`7D else `7B X`09 if (minLines > topLines) `7B X`09`09warning("Min Lines must be > Top Lines. Top/Min/Max Lines not changed" V); X`09 `7D else `7B X`09`09if (maxLines >= topLines) `7B X`09`09 warning("Max lines must be < Top Lines. Top/Min/Max Lines not chan Vged."); X`09`09`7D else `7B X`09`09 if (maxLines < minLines) `7B X`09`09`09warning("Max Lines must be >= Min Lines. Top/Min/Max not changed"); X`09`09 `7D else `7B X`09`09`09app_resources.topLines = topLines; X`09`09`09app_resources.minLines = minLines; X`09`09`09app_resources.maxLines = maxLines; X`09`09 `7D X`09`09`7D X`09 `7D X`09`7D X `7D X updateText(cgEditCmd,&app_resources.editorCommand); X updateText(cgPrtCmd,&app_resources.printCommand); X updateText(cgReplyTo,&app_resources.replyTo); X updateText(cgReplyPath,&app_resources.replyPath); X updateText(cgOrganization,&app_resources.organization); X updateText(cgHostName,&app_resources.hostName); X updateText(cgSavePost,&app_resources.savePostings); X updateText(cgDeadLetters,&app_resources.deadLetters); X#ifndef VMS X updateText(cgMailer,&app_resources.mailer); X#else X updateText(cgPersonal,&app_resources.personalName); X#endif X lineLength = getInt(cgLineLength,app_resources.lineLength); X if (lineLength < 40 `7C`7C lineLength > 250) `7B X`09warning("Line length out of range. Use 40 thru 250"); X `7D else `7B X app_resources.lineLength = lineLength; X `7D X breakLength = getInt(cgWrapLength,app_resources.breakLength); X if (breakLength < lineLength) `7B X`09warning("Wrap length must be greater than Line Length"); X `7D else `7B X`09if (breakLength > 250) `7B X`09 warning("Break length out of range. Must be less than 250"); X `09`7D else `7B X`09 app_resources.breakLength = breakLength; X`09`7D X `7D X rescanTime = getInt(cgRescan,app_resources.rescanTime); X app_resources.rescanTime = rescanTime; X X app_resources.saveMode = 0; X if (XmToggleButtonGadgetGetState(saveMbxButton)) `7B X`09app_resources.saveMode `7C= MAILBOX_SAVE; X `7D X if (XmToggleButtonGadgetGetState(saveHeadersButton)) X`09app_resources.saveMode `7C= HEADERS_SAVE; X if (XmToggleButtonGadgetGetState(saveSubdirsButton)) X`09app_resources.saveMode `7C= SUBDIRS_SAVE; X if (XmToggleButtonGadgetGetState(saveOneDirButton)) X`09app_resources.saveMode `7C= ONEDIR_SAVE; X app_resources.confirmMode = 0; X if (XmToggleButtonGadgetGetState(confQuitButton)) X`09app_resources.confirmMode `7C= NG_QUIT; X if (XmToggleButtonGadgetGetState(confExitButton)) X`09app_resources.confirmMode `7C= NG_EXIT; X if (XmToggleButtonGadgetGetState(confCatchUpButton)) X`09app_resources.confirmMode `7C= NG_CATCHUP; X if (XmToggleButtonGadgetGetState(confArtCatchUpButton)) X`09app_resources.confirmMode `7C= ART_CATCHUP; X if (XmToggleButtonGadgetGetState(confUnsubButton)) X`09app_resources.confirmMode `7C= NG_UNSUBSCRIBE; X if (XmToggleButtonGadgetGetState(confArtUnsubButton)) X`09app_resources.confirmMode `7C= ART_UNSUBSCRIBE; X if (XmToggleButtonGadgetGetState(confArtEndButton)) X`09app_resources.confirmMode `7C= ART_ENDACTION; X if (XmToggleButtonGadgetGetState(confOverButton)) X`09app_resources.confirmMode `7C= ART_SAVE; X app_resources.subjectRead = XmToggleButtonGadgetGetState(cgSubjReadButto Vn); X app_resources.info = XmToggleButtonGadgetGetState(cgInfoButton); X app_resources.killFiles = XmToggleButtonGadgetGetState(cgKillButton); X app_resources.updateNewsrc = XmToggleButtonGadgetGetState(cgUpdateButton V); X app_resources.includeHeader = XmToggleButtonGadgetGetState(cgInclHdrButt Von); X app_resources.includeHeader = XmToggleButtonGadgetGetState(cgInclSepButt Von); X app_resources.pageArticles = XmToggleButtonGadgetGetState(cgPageArtButto Vn); X app_resources.sortedSubjects = XmToggleButtonGadgetGetState(cgSubjSortBu Vtton); X app_resources.authorFullName = XmToggleButtonGadgetGetState(cgAuthorFull VButton); X app_resources.displayLineCount = XmToggleButtonGadgetGetState(cgLineCoun VtButton); X app_resources.autoRead = XmToggleButtonGetState(cgAutoReadButton); X app_resources.cc = XmToggleButtonGetState(cgCCButton); X if (XmToggleButtonGetState(cgWhichMb2Button)) `7B X`09app_resources.popupButton = 2; X `7D else `7B X`09app_resources.popupButton = 3; X `7D X`7D Xstatic void CustomizeGeneral() X`7B X char tempStr`5B20`5D; X X if (generalDialog == 0) `7B X`09makeGeneralMenu(); X `7D X XmTextSetString(cgNNTP,app_resources.nntpServer); X XmTextSetString(cgNewsrc,app_resources.newsrcFile); X XmTextSetString(cgIncludePrefix, app_resources.includePrefix); X XmTextSetString(cgSaveNewsrc,app_resources.saveNewsrcFile); X XmTextSetString(cgSaveDir,app_resources.saveDir); X XmTextSetString(cgSigFile,app_resources.signatureFile); X XmTextSetString(cgTempDir,app_resources.tmpDir); X sprintf(tempStr,"%d",app_resources.topLines); X XmTextSetString(cgTopLines,tempStr); X sprintf(tempStr,"%d",app_resources.minLines); X XmTextSetString(cgMinLines,tempStr); X sprintf(tempStr,"%d",app_resources.maxLines); X XmTextSetString(cgMaxLines,tempStr); X XmTextSetString(cgEditCmd,app_resources.editorCommand); X XmTextSetString(cgPrtCmd,app_resources.printCommand); X XmTextSetString(cgReplyTo,app_resources.replyTo); X XmTextSetString(cgReplyPath,app_resources.replyPath); X XmTextSetString(cgOrganization,app_resources.organization); X XmTextSetString(cgHostName,app_resources.hostName); X XmTextSetString(cgSavePost,app_resources.savePostings); X XmTextSetString(cgDeadLetters,app_resources.deadLetters); X#ifndef VMS X XmTextSetString(cgMailer,app_resources.mailer); X#else X XmTextSetString(cgPersonal,app_resources.personalName); X#endif X sprintf(tempStr,"%d",app_resources.lineLength); X XmTextSetString(cgLineLength,tempStr); X sprintf(tempStr,"%d",app_resources.breakLength); X XmTextSetString(cgWrapLength,tempStr); X sprintf(tempStr,"%d",app_resources.rescanTime); X XmTextSetString(cgRescan,tempStr); X X XmToggleButtonGadgetSetState(saveMbxButton, X`09(app_resources.saveMode & MAILBOX_SAVE) ? True : False, False); X#ifdef VMS X XtSetSensitive(saveMbxButton, False); X#endif X XmToggleButtonGadgetSetState(saveHeadersButton, X`09(app_resources.saveMode & HEADERS_SAVE) ? True : False, False); X XmToggleButtonGadgetSetState(saveSubdirsButton, X`09(app_resources.saveMode & SUBDIRS_SAVE) ? True : False, False); X XmToggleButtonGadgetSetState(saveOneDirButton, X`09(app_resources.saveMode & ONEDIR_SAVE) ? True : False, False); X XmToggleButtonGadgetSetState(confQuitButton, X`09(app_resources.confirmMode & NG_QUIT) ? True : False, False); X XmToggleButtonGadgetSetState(confExitButton, X`09(app_resources.confirmMode & NG_EXIT) ? True : False, False); X XmToggleButtonGadgetSetState(confCatchUpButton, X`09(app_resources.confirmMode & NG_CATCHUP) ? True : False, False); X XmToggleButtonGadgetSetState(confArtCatchUpButton, X`09(app_resources.confirmMode & ART_CATCHUP) ? True : False, False); X XmToggleButtonGadgetSetState(confUnsubButton, X`09(app_resources.confirmMode & NG_UNSUBSCRIBE) ? True : False, False); X XmToggleButtonGadgetSetState(confArtUnsubButton, X`09(app_resources.confirmMode & ART_UNSUBSCRIBE) ? True : False, False); X XmToggleButtonGadgetSetState(confArtEndButton, X`09(app_resources.confirmMode & ART_ENDACTION) ? True : False, False); X XmToggleButtonGadgetSetState(confOverButton, X`09(app_resources.confirmMode & ART_SAVE) ? True : False, False); X XmToggleButtonGadgetSetState(cgSubjReadButton, X`09`09app_resources.subjectRead, False); X XmToggleButtonGadgetSetState(cgInfoButton, X`09`09app_resources.info, False); X XmToggleButtonGadgetSetState(cgKillButton, X`09`09app_resources.killFiles, False); X XmToggleButtonGadgetSetState(cgUpdateButton, X`09`09app_resources.updateNewsrc, False); X XmToggleButtonGadgetSetState(cgInclHdrButton, X`09`09app_resources.includeHeader, False); X XmToggleButtonGadgetSetState(cgInclSepButton, X`09`09app_resources.includeHeader, False); X XmToggleButtonGadgetSetState(cgPageArtButton, X`09`09app_resources.pageArticles, False); X XmToggleButtonGadgetSetState(cgSubjSortButton, X`09`09app_resources.sortedSubjects, False); X XmToggleButtonGadgetSetState(cgAuthorFullButton, X`09`09app_resources.authorFullName, False); X XmToggleButtonGadgetSetState(cgLineCountButton, X`09`09app_resources.displayLineCount, False); X XmToggleButtonGadgetSetState(cgAutoReadButton, X`09`09app_resources.autoRead, False); X XmToggleButtonGadgetSetState(cgCCButton, X`09`09app_resources.cc, False); X if (app_resources.popupButton == 2) `7B X`09XmToggleButtonGadgetSetState(cgWhichMb2Button, True, False); X`09XmToggleButtonGadgetSetState(cgWhichMb3Button, False, False); X `7D else `7B X`09XmToggleButtonGadgetSetState(cgWhichMb2Button, False, False); X`09XmToggleButtonGadgetSetState(cgWhichMb3Button, True, False); X `7D X XtManageChild(generalDialog); X XtRealizeWidget(XtParent(generalDialog)); X`7D Xstatic void putStr(name, src) Xchar *name; Xchar *src; X`7B X char resName`5B512`5D; X char *trim; X X strcpy(resName, app_resources.progName); X strcat(resName, "."); X strcat(resName, name); X X if (src != NULL) `7B X`09trim = utTrimSpaces(src); X`09XrmPutStringResource(&xrmDB, resName, trim); X `7D X`7D Xstatic void putBool(name, src) Xchar *name; XBoolean src; X`7B X char resName`5B512`5D; X X strcpy(resName, app_resources.progName); X strcat(resName, "."); X strcat(resName, name); X X if (src) `7B X`09XrmPutStringResource(&xrmDB, resName, "on"); X `7D else `7B X`09XrmPutStringResource(&xrmDB, resName, "off"); X `7D X`7D Xstatic void putInt(name, src) Xchar *name; Xint src; X`7B X char resName`5B512`5D; X char numStr`5B20`5D; X X strcpy(resName, app_resources.progName); X strcat(resName, "."); X strcat(resName, name); X X sprintf(numStr, "%d", src); X XrmPutStringResource(&xrmDB, resName, numStr); X`7D Xstatic void CustomizeSave() X`7B X char tmpStr`5B512`5D; X static int width = 0;`09/* Gross hack dept: real X11R3 measures */ X static int height = 0;`09/* using Dimension (shorts) but Motif V1.0 */ X static int x = 0;`09`09/* uses ints. So we use int and zero 'em */ X static int y = 0;`09`09/* first so the high order word is OK. */ X static Arg sizeArgs`5B`5D = `7B X`09`7BXtNwidth, (XtArgVal) &width`7D, X`09`7BXtNheight,(XtArgVal) &height`7D, X `7D; X X xrmDB = XrmGetFileDatabase(customName); X#ifndef VMS X if (xrmDB != NULL) `7B X`09sprintf(tmpStr, "%s.old", customName); X`09utCopyFile(customName, tmpStr); X `7D X#endif X#ifdef MOTIF X XtGetValues(Frame, sizeArgs, XtNumber(sizeArgs)); X XtTranslateCoords(TopLevel, 0, 0, &x, &y); X sprintf(tmpStr, "%dx%d+%d+%d", width, height, x, y); X XrmPutStringResource(&xrmDB, "mxrn.geometry", tmpStr); X#else X XtGetValues(TopLevel, sizeArgs, XtNumber(sizeArgs)); X XtTranslateCoords(TopLevel, 0, 0, &x, &y); X sprintf(tmpStr, "%dx%d+%d+%d", width, height, x, y); X XrmPutStringResource(&xrmDB, "dxrn.geometry", tmpStr); X#endif X putStr("replyPath",app_resources.replyPath); X putStr("saveDir",app_resources.saveDir); X putStr("newsrcFile",app_resources.newsrcFile); X putStr("saveNewsrcFile",app_resources.saveNewsrcFile); X putStr("signatureFile",app_resources.signatureFile); X putStr("nntpServer",app_resources.nntpServer); X putInt("topLines",app_resources.topLines); X tmpStr`5B0`5D = '\0'; X if (app_resources.saveMode & MAILBOX_SAVE) `7B X`09strcpy(tmpStr, "mailbox,"); X `7D X if (app_resources.saveMode & NOHEADERS_SAVE) `7B X`09strcat(tmpStr,"noheaders,"); X `7D X if (app_resources.saveMode & SUBDIRS_SAVE) `7B X`09strcat(tmpStr,"subdirs"); X `7D else `7B X`09strcat(tmpStr,"onedir"); X `7D X#ifdef MOTIF X XrmPutStringResource(&xrmDB, "mxrn.saveMode", tmpStr); X#else X XrmPutStringResource(&xrmDB, "dxrn.saveMode", tmpStr); X#endif X putStr("savePostings",app_resources.savePostings); X putStr("deadLetters",app_resources.deadLetters); X putInt("minLines",app_resources.minLines); X putInt("maxLines",app_resources.maxLines); X#ifndef VMS X putStr("mailer",app_resources.mailer); X#else X putStr("personalName",app_resources.personalName); X#endif X putBool("subjectRead",app_resources.subjectRead); X putBool("info",app_resources.info); X putStr("tmpDir",app_resources.tmpDir); X tmpStr`5B0`5D = '\0'; X if (app_resources.confirmMode & NG_QUIT) X`09strcat(tmpStr,"ngQuit,"); X if (app_resources.confirmMode & NG_EXIT) X`09strcat(tmpStr,"ngExit,"); X if (app_resources.confirmMode & NG_CATCHUP) X`09strcat(tmpStr,"ngCatchUp,"); X if (app_resources.confirmMode & ART_CATCHUP) X`09strcat(tmpStr,"artCatchUp,"); X if (app_resources.confirmMode & NG_UNSUBSCRIBE) X`09strcat(tmpStr,"ngUnsub,"); X if (app_resources.confirmMode & ART_UNSUBSCRIBE) X`09strcat(tmpStr,"artUnsub,"); X if (app_resources.confirmMode & ART_ENDACTION) X`09strcat(tmpStr,"artEndAction,"); X if (app_resources.confirmMode & ART_SAVE) X`09strcat(tmpStr,"artSave,"); X tmpStr`5Bstrlen(tmpStr)-1`5D = '\0'; X#ifdef MOTIF X XrmPutStringResource(&xrmDB, "mxrn.confirm", tmpStr); X#else X XrmPutStringResource(&xrmDB, "dxrn.confirm", tmpStr); X#endif X putBool("killFiles",app_resources.killFiles); X putStr("editorCommand",app_resources.editorCommand); X putStr("organization",app_resources.organization); X putStr("replyTo",app_resources.replyTo); X putBool("includeHeader",app_resources.includeHeader); X putBool("includeSep",app_resources.includeSep); X putBool("updateNewsrc",app_resources.updateNewsrc); X putInt("lineLength",app_resources.lineLength); X putInt("breakLength",app_resources.breakLength); X putInt("rescanTime",app_resources.rescanTime); X putBool("pageArticles",app_resources.pageArticles); X putBool("sortedSubjects",app_resources.sortedSubjects); X putBool("authorFullName",app_resources.authorFullName); X putBool("displayLineCount",app_resources.displayLineCount); X putBool("autoRead",app_resources.autoRead); X putBool("cc",app_resources.cc); X putStr("addButtonList",app_resources.addButtonList); X putStr("ngButtonList",app_resources.ngButtonList); X putStr("allButtonList",app_resources.allButtonList); X putStr("artButtonList",app_resources.artButtonList); X putStr("artSpecButtonList",app_resources.artSpecButtonList); X putStr("printCommand",app_resources.printCommand); X putStr("includePrefix",app_resources.includePrefix); X putStr("hostName",app_resources.hostName); X putStr("replyPath",app_resources.replyPath); X putStr("addPopupList",app_resources.addPopupList); X putStr("ngPopupList",app_resources.ngPopupList); X putStr("allPopupList",app_resources.allPopupList); X putStr("artPopupList",app_resources.artPopupList); X putInt("popupButton",app_resources.popupButton); X X XrmPutFileDatabase(xrmDB, customName); X xrmDB = NULL; X`7D Xstatic void cgOK() X`7B X UpdateGeneral(); X XtUnmanageChild(generalDialog); X`7D Xstatic void cgApply() X`7B X UpdateGeneral(); X`7D Xstatic void cgCancel() X`7B X XtUnmanageChild(generalDialog); X`7D X`0C Xstatic void makeCustomMenu() X`7B X Arg arg`5B20`5D; X int i; X XmString str; X X i = 0; X XtSetArg(arg`5Bi`5D, XmNwidth, `09`09430);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNheight,`09`09330);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNresizePolicy,`09XmRESIZE_GROW);`09i++; X XtSetArg(arg`5Bi`5D, XmNautoUnmanage,`09False);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, XmNdialogStyle,`09XmDIALOG_APPLICATION_MODAL);i++; X#ifndef MOTIF X XtSetArg(arg`5Bi`5D, DwtNunits,`09`09DwtPixelUnits);`09i++; X#endif X customDialog = XmCreateBulletinBoardDialog(TopLevel, "customDialog",arg, Vi); X X i = 0; X str = XmStringLtoRCreate("Click on these items to",XmSTRING_DEFAULT_CHAR VSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`0960);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0925);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(XmCreateLabelGadget(customDialog,"label1",arg,i)); X i = 0; X str = XmStringLtoRCreate("add them to the menu",XmSTRING_DEFAULT_CHARSET V); X XtSetArg(arg`5Bi`5D, XmNx,`09`0960);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0950);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(XmCreateLabelGadget(customDialog,"label2",arg,i)); X i = 0; X str = XmStringLtoRCreate("Click on these items to",XmSTRING_DEFAULT_CHAR VSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09320);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0925);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(XmCreateLabelGadget(customDialog,"label3",arg,i)); X i = 0; X str = XmStringLtoRCreate("remove them from the menu",XmSTRING_DEFAULT_CH VARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09320);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0950);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtManageChild(XmCreateLabelGadget(customDialog,"label4",arg,i)); X X i = 0; X XtSetArg(arg`5Bi`5D, XmNwidth,`09`09200);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNvisibleItemCount,10);`09`09i++; X#ifdef MOTIF X XtSetArg(arg`5Bi`5D, XmNscrollBarDisplayPolicy, XmSTATIC);i++; X XtSetArg(arg`5Bi`5D, XmNlistSizePolicy, XmCONSTANT);`09i++; X XtSetArg(arg`5Bi`5D, XmNselectionPolicy,XmSINGLE_SELECT);i++; X#else X XtSetArg(arg`5Bi`5D, DwtNresize,`09DwtResizeFixed);i++; X XtSetArg(arg`5Bi`5D, DwtNsingleSelection,True);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNhorizontal,`09True);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNx,`09`0930);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0980);`09`09i++; X#endif X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X addList = XmCreateScrolledList(customDialog,"addList", arg, i); X i = 0; X XtSetArg(arg`5Bi`5D, XmNx,`09`0930);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0980);`09`09i++; X XtSetValues(XtParent(addList), arg, i); /* set the scroll window */ X XtManageChild(addList); X X i = 0; X XtSetArg(arg`5Bi`5D, XmNwidth,`09`09200);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNvisibleItemCount,10);`09`09i++; X#ifdef MOTIF X XtSetArg(arg`5Bi`5D, XmNscrollBarDisplayPolicy, XmSTATIC);i++; X XtSetArg(arg`5Bi`5D, XmNlistSizePolicy, XmCONSTANT);`09i++; X XtSetArg(arg`5Bi`5D, XmNselectionPolicy,XmSINGLE_SELECT);i++; X#else X XtSetArg(arg`5Bi`5D, XmNx,`09`09300);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0980);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNresize,`09DwtResizeFixed);i++; X XtSetArg(arg`5Bi`5D, DwtNsingleSelection,True);`09`09i++; X XtSetArg(arg`5Bi`5D, DwtNhorizontal,`09True);`09`09i++; X#endif X XtSetArg(arg`5Bi`5D, XmNborderWidth,`091);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X removeList = XmCreateScrolledList(customDialog,"removeList", arg, i); X i = 0; X XtSetArg(arg`5Bi`5D, XmNx,`09`09300);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`0980);`09`09i++; X XtSetValues(XtParent(removeList), arg, i); /* set the scroll window */ X XtManageChild(removeList); X X i = 0; X str = XmStringLtoRCreate("OK", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`0955);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09350);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X#ifdef MOTIF X XtSetArg(arg`5Bi`5D, XmNshowAsDefault,`09True);`09`09i++; X#endif X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cmOKCallback); i++; X XtManageChild( X`09okButton = XmCreatePushButton(customDialog, "okButton", arg, i)); X i = 0; X str = XmStringLtoRCreate("Apply", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09225);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09350);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cmApplyCallback); i++; X XtManageChild( X`09applyButton = XmCreatePushButton(customDialog, "applyButton", arg, i)); X i = 0; X str = XmStringLtoRCreate("Cancel", XmSTRING_DEFAULT_CHARSET); X XtSetArg(arg`5Bi`5D, XmNx,`09`09430);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNy,`09`09350);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNlabelString,`09str);`09`09i++; X XtSetArg(arg`5Bi`5D, XmNfontList,`09fontList);`09i++; X XtSetArg(arg`5Bi`5D, XmNactivateCallback,cmCancelCallback); i++; X XtManageChild( X`09cancelButton = XmCreatePushButton(customDialog, "cancelButton", arg,i)); X i = 0; X XtSetArg(arg`5Bi`5D, XmNdefaultButton, okButton);i++; X XtSetValues(customDialog, arg, i); X`7D Xstatic void LoadCustomList(string) Xchar`09*string; X`7B X int i, j, add, rem; X char *ptr, *token, *savePtr; X Arg arg`5B10`5D; X X if (customDialog == 0) `7B X`09makeCustomMenu(); X `7D X i = 0; X#ifdef MOTIF X XtSetArg(arg`5Bi`5D, XmNsingleSelectionCallback, addCallback);i++; X#else X XtSetArg(arg`5Bi`5D, DwtNsingleCallback, addCallback);i++; X XtSetArg(arg`5Bi`5D, DwtNsingleConfirmCallback, addCallback);i++; X#endif X XtSetValues(addList, arg, i); X i = 0; X#ifdef MOTIF X XtSetArg(arg`5Bi`5D, XmNsingleSelectionCallback, removeCallback);i++; X#else X XtSetArg(arg`5Bi`5D, DwtNsingleCallback, removeCallback);i++; X XtSetArg(arg`5Bi`5D, DwtNsingleConfirmCallback, removeCallback);i++; X#endif X XtSetValues(removeList, arg, i); X for (i = 0; i < currentCount;i++) `7B X`09if (currentButtons`5Bi`5D.listString == NULL) X`09 currentButtons`5Bi`5D.listString = X`09 XmStringLtoRCreate(currentButtons`5Bi`5D.label, X`09`09`09XmSTRING_DEFAULT_CHARSET); X`09if (string != NULL) `7B X`09 currentButtons`5Bi`5D.addPos = -1; X`09 currentButtons`5Bi`5D.removePos = -1; X`09`7D else `7B X`09 currentButtons`5Bi`5D.addPos = -1; X`09 currentButtons`5Bi`5D.removePos = i; X`09`7D X `7D X add = 0; X rem = 0; X X if (string != NULL) `7B X`09savePtr = ptr = XtNewString(string); X X`09while ((token = strtok(ptr, ", \t\n")) != NIL(char)) `7B X`09 for (j = 0; j < currentCount; j++) `7B`09 X`09`09if (STREQ(token, (char *) currentButtons`5Bj`5D.name)) `7B X`09`09 currentButtons`5Bj`5D.removePos = rem; X`09`09 removeItems`5Brem`5D = currentButtons`5Bj`5D.listString; X`09`09 rem++; X`09`09 break; X`09`09`7D X`09 `7D X`09 ptr = NULL; X`09`7D X`09XtFree (savePtr); X`09for (i = 0; i < currentCount; i++) `7B X`09 if (currentButtons`5Bi`5D.removePos == -1) `7B X`09`09currentButtons`5Bi`5D.addPos = add; X`09`09addItems`5Badd`5D = currentButtons`5Bi`5D.listString; X`09`09add++; X`09 `7D X`09`7D X `7D else `7B X`09for (rem = 0; rem < currentCount; rem++) X`09 removeItems`5Brem`5D = currentButtons`5Brem`5D.listString; X `7D X i = 0; X XtSetArg(arg`5Bi`5D, XmNitems, addItems);i++; X XtSetArg(arg`5Bi`5D, XmNitemCount, add); i++; X XtSetValues(addList, arg, i); X i = 0; X XtSetArg(arg`5Bi`5D, XmNitems, removeItems);i++; X XtSetArg(arg`5Bi`5D, XmNitemCount, rem); i++; X XtSetValues(removeList, arg, i); X`7D Xstatic void addClick(w, call_data, click) XWidget `09`09`09w; Xcaddr_t`09`09`09call_data; X#ifdef MOTIF XXmListCallbackStruct `09*click; X#else XDwtListBoxCallbackStruct *click; X#endif X`7B X int i, add, rem, addCount, removeCount; X#ifdef MOTIF X int selItem = click->item_position - 1; X#else X int selItem = click->item_number - 1; X#endif X int item; X Arg arg`5B10`5D; X X XmListDeselectAllItems(w); X addCount = add = 0; X removeCount = rem = 0; X for (i = 0; i < currentCount; i++) `7B X`09if (currentButtons`5Bi`5D.addPos != -1) `7B X`09 addCount++; X`09`7D X`09if (currentButtons`5Bi`5D.removePos != -1) `7B X`09 removeCount++; X`09`7D X`09if (currentButtons`5Bi`5D.addPos == selItem) `7B X`09 item = i; X`09`7D X `7D X X for (i = 0; i < currentCount; i++) `7B X`09if (currentButtons`5Bi`5D.addPos > selItem) `7B X`09 currentButtons`5Bi`5D.addPos = currentButtons`5Bi`5D.addPos - 1; X`09`7D X `7D X currentButtons`5Bitem`5D.removePos = removeCount; X currentButtons`5Bitem`5D.addPos = -1; X X addCount = addCount - 1; X removeCount = removeCount + 1; X for (i = 0; i < currentCount; i++) `7B X`09if ((add = currentButtons`5Bi`5D.addPos) != -1) `7B X`09 addItems`5Badd`5D = currentButtons`5Bi`5D.listString; X`09`7D X`09if ((rem = currentButtons`5Bi`5D.removePos) != -1) `7B X`09 removeItems`5Brem`5D = currentButtons`5Bi`5D.listString; X`09`7D X `7D X#ifdef MOTIF X XmListDeletePos(addList, selItem+1); X if (removeCount > 1) `7B X XmListAddItem(removeList, removeItems`5BremoveCount-1`5D, 0); X `7D else `7B X`09i = 0; X`09XtSetArg(arg`5Bi`5D, XmNitems, removeItems);i++; X`09XtSetArg(arg`5Bi`5D, XmNitemCount, removeCount); i++; X`09XtSetValues(removeList, arg, i); X `7D X#else X DwtListBoxDeletePos(addList, selItem+1); X DwtListBoxAddItem(removeList, removeItems`5BremoveCount-1`5D, removeCoun Vt); X#endif X`7D Xstatic void removeClick(w, call_data, click) XWidget `09`09`09w; Xcaddr_t`09`09`09call_data; X#ifdef MOTIF XXmListCallbackStruct `09*click; X#else XDwtListBoxCallbackStruct `09*click; X#endif X`7B X int i, add, rem, addCount, removeCount; X#ifdef MOTIF X int selItem = click->item_position - 1; X#else X int selItem = click->item_number - 1; X#endif X int item; X Arg arg`5B10`5D; X X XmListDeselectAllItems(w); X addCount = add = 0; X removeCount = rem = 0; X for (i = 0; i < currentCount; i++) `7B X`09if (currentButtons`5Bi`5D.addPos != -1) `7B X`09 addCount++; X`09`7D X`09if (currentButtons`5Bi`5D.removePos != -1) `7B X`09 removeCount++; X`09`7D X`09if (currentButtons`5Bi`5D.removePos == selItem) `7B X`09 item = i; X`09`7D X `7D X for (i = 0; i < currentCount; i++) `7B X`09if (currentButtons`5Bi`5D.removePos > selItem) `7B X`09 currentButtons`5Bi`5D.removePos = currentButtons`5Bi`5D.removePos - 1 V; X`09`7D X `7D X X currentButtons`5Bitem`5D.addPos = addCount; X currentButtons`5Bitem`5D.removePos = -1; X X addCount = addCount + 1; X removeCount = removeCount - 1; X for (i = 0; i < currentCount; i++) `7B X`09if ((add = currentButtons`5Bi`5D.addPos) != -1) `7B X`09 addItems`5Badd`5D = currentButtons`5Bi`5D.listString; X`09`7D X`09if ((rem = currentButtons`5Bi`5D.removePos) != -1) `7B X`09 removeItems`5Brem`5D = currentButtons`5Bi`5D.listString; X`09`7D X `7D X#ifdef MOTIF X XmListDeletePos(removeList, selItem+1); X if (addCount > 1) `7B X XmListAddItem(addList, addItems`5BaddCount-1`5D, 0); X `7D else `7B X`09i = 0; X`09XtSetArg(arg`5Bi`5D, XmNitems, addItems);i++; X`09XtSetArg(arg`5Bi`5D, XmNitemCount, addCount); i++; X`09XtSetValues(addList, arg, i); X `7D X#else X DwtListBoxDeletePos(removeList, selItem+1); X DwtListBoxAddItem(addList, addItems`5BaddCount-1`5D, addCount); X#endif X`7D Xstatic void CustomizeAddMenus() X`7B X currentButtons = addButtons; X currentCount = XtNumber(addButtons); X menuMode = addMenu; X LoadCustomList(app_resources.addButtonList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeAddPopups() X`7B X currentButtons = addButtons; X currentCount = XtNumber(addButtons); X menuMode = addPop; X LoadCustomList(app_resources.addPopupList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeAllMenus() X`7B X currentButtons = allButtons; X currentCount = XtNumber(allButtons); X menuMode = allMenu; X LoadCustomList(app_resources.allButtonList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeAllPopups() X`7B X currentButtons = allButtons; X currentCount = XtNumber(allButtons); X menuMode = allPop; X LoadCustomList(app_resources.allPopupList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeArtMenus() X`7B X currentButtons = artButtons; X currentCount = XtNumber(artButtons); X menuMode = artMenu; X LoadCustomList(app_resources.artButtonList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeArtPopups() X`7B X currentButtons = artButtons; X currentCount = XtNumber(artButtons); X menuMode = artPop; X LoadCustomList(app_resources.artPopupList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeNgMenus() X`7B X currentButtons = ngButtons; X currentCount = XtNumber(ngButtons); X menuMode = ngMenu; X LoadCustomList(app_resources.ngButtonList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void CustomizeNgPopups() X`7B X currentButtons = ngButtons; X currentCount = XtNumber(ngButtons); X menuMode = ngPop; X LoadCustomList(app_resources.ngPopupList); X XtManageChild(customDialog); X XtRealizeWidget(XtParent(customDialog)); X`7D Xstatic void UpdateMenu() X`7B X char menuString`5B2048`5D; X int i,j; X X menuString`5B0`5D = '\0'; X X for (i = 0; i < currentCount; i++) `7B X for (j = 0; j < currentCount; j++) `7B X`09 if (currentButtons`5Bj`5D.removePos == i) `7B X`09`09strcat(menuString,currentButtons`5Bj`5D.name); X`09`09strcat(menuString,","); X`09`09break; X`09 `7D X`09`7D X `7D X menuString`5Bstrlen(menuString)-1`5D = '\0'; X switch (menuMode) `7B X`09case addMenu: X`09 app_resources.addButtonList = XtNewString(menuString); X`09 createButtons(ADD_MODE); X`09 break; X`09case addPop: X`09 app_resources.addPopupList = XtNewString(menuString); X`09 XtUnmanageChildren(AddPopupButtons, AddPopupCount); X`09 AddPopupCount = AddCount; X`09 doPopups(app_resources.addPopupList, popup_menu, AddPopupButtons, X`09`09AddButtonList, &AddPopupCount); X`09 if (Mode == ADD_MODE) `7B X`09`09XtManageChildren(AddPopupButtons, AddPopupCount); X`09`09resetPopupSize(); X`09 `7D X`09 break; X`09case allMenu: X`09 app_resources.allButtonList = XtNewString(menuString); X`09 createButtons(ALL_MODE); X`09 break; X`09case allPop: X`09 app_resources.allPopupList = XtNewString(menuString); X`09 XtUnmanageChildren(AllPopupButtons, AllPopupCount); X`09 AllPopupCount = AllCount; X`09 doPopups(app_resources.allPopupList, popup_menu, AllPopupButtons, X`09`09AllButtonList, &AllPopupCount); X`09 if (Mode == ALL_MODE) `7B X`09`09XtManageChildren(AllPopupButtons, AllPopupCount); X`09`09resetPopupSize(); X`09 `7D X`09 break; X`09case artMenu: X`09 app_resources.artButtonList = XtNewString(menuString); X`09 createButtons(ARTICLE_MODE); X`09 break; X`09case artPop: X`09 app_resources.artPopupList = XtNewString(menuString); X`09 XtUnmanageChildren(ArtPopupButtons, ArtPopupCount); X`09 ArtPopupCount = ArtCount; X`09 ArtSpecPopupCount = ArtSpecCount; X`09 doPopups(app_resources.artPopupList, popup_menu, ArtPopupButtons, X`09`09ArtButtonList, &ArtPopupCount); X`09 if (Mode == ARTICLE_MODE) `7B X`09`09XtManageChildren(ArtPopupButtons, ArtPopupCount); X`09`09resetPopupSize(); X`09 `7D X`09 break; X`09case ngMenu: X`09 app_resources.ngButtonList = XtNewString(menuString); X`09 createButtons(NEWSGROUP_MODE); X`09 break; X`09case ngPop: X`09 app_resources.ngPopupList = XtNewString(menuString); X`09 XtUnmanageChildren(NgPopupButtons, NgPopupCount); X`09 NgPopupCount = NgCount; X`09 doPopups(app_resources.ngPopupList, popup_menu, NgPopupButtons, X`09`09NgButtonList, &NgPopupCount); X`09 if (Mode == NEWSGROUP_MODE) `7B X`09`09XtManageChildren(NgPopupButtons, NgPopupCount); X`09`09resetPopupSize(); X`09 `7D X`09 break; X `7D X`7D Xstatic void cmOK() X`7B X UpdateMenu(); X XtUnmanageChild(customDialog); X`7D Xstatic void cmApply() X`7B X UpdateMenu(); X`7D Xstatic void cmCancel() X`7B X XtUnmanageChild(customDialog); X`7D $ CALL UNPACK MENUS.C;1 927241093 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/mesg.c,v 1.6 V 90/09/29 01:12:57 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * mesg.c: message box X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include "utils.h" X#include "config.h" X#ifndef VMS X#include X#include X#include X#include X#else X#include X#include X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#else /* MOTIF */ X#ifndef DwtNmenuExtendLastRow X#define DwtNmenuExtendLastRow "menuExtendLastRow" X#endif X#ifndef VMS X#include X#else X#include X#endif /* VMS */ X#include "Pane.h" X#endif /* MOTIF */ X#include "xthelper.h" X#include "resources.h" X#include "xrn.h" X#include "mesg.h" X#if defined(__STDC__) && !defined(NOSTDHDRS) X#include X#else X#include X#endif X Xchar error_buffer`5B2048`5D; X X/* entire widget */ Xstatic Widget MesgTopLevel = (Widget) 0; X/* text window */ Xstatic Widget MesgText = (Widget) 0; X Xstatic Boolean MesgMapped = False; X X#define MESG_SIZE 4096 Xstatic char MesgString`5BMESG_SIZE`5D; X X X/*ARGSUSED*/ Xstatic void XdismissFunction(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X MesgMapped = False; X XtUnmapWidget(MesgTopLevel); X return; X`7D X X X#undef lint X#ifdef lint X#define BUTTON(nm,lbl) X#else X#ifdef MOTIF X#ifdef __STDC__ X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) #nm`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) #lbl`7D,`09`09\ X `7BXmNactivateCallback, (XtArgVal) nm##Callbacks`7D \ X`7D; X#else X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) "nm"`7D,`09`09`09\ X `7BXtNlabel, (XtArgVal) "lbl"`7D,`09`09\ X `7BXmNactivateCallback, (XtArgVal) nm/**/Callbacks`7D \ X`7D; X#endif X#else /* MOTIF */ X#ifdef __STDC__ X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic XtCallbackRec nm##Callbacks`5B`5D = `7B`09\ X `7Bnm##Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm##Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) #nm`7D,`09`09`09\ X `7BDwtNlabel, (XtArgVal) #lbl`7D,`09`09\ X `7BDwtNactivateCallback, (XtArgVal) nm##Callbacks`7D, \ X `7BDwtNborderWidth, (XtArgVal) 1`7D,`09`09\ X`7D; X#else X#define BUTTON(nm,lbl)`09`09`09`09\ Xstatic XtCallbackRec nm/**/Callbacks`5B`5D = `7B`09\ X `7Bnm/**/Function, NULL`7D,`09`09`09\ X `7BNULL, NULL`7D`09`09`09`09\ X`7D;`09`09`09`09`09`09\ Xstatic Arg nm/**/Args`5B`5D = `7B`09`09`09\ X `7BXtNname, (XtArgVal) "nm"`7D,`09`09`09\ X `7BDwtNlabel, (XtArgVal) "lbl"`7D,`09`09\ X `7BDwtNactivateCallback, (XtArgVal) nm/**/Callbacks`7D,`09\ X `7BDwtNborderWidth, (XtArgVal) 1`7D,`09`09\ X`7D; X#endif X#endif /* MOTIF */ X#endif /* lint */ X X XBUTTON(dismiss,dismiss); X X/*ARGSUSED*/ X/*VARARGS2*/ X#if defined(__STDC__) && !defined(NOSTDHDRS) Xvoid XmesgPane(int type, char *fmtString, ...) X#else Xvoid XmesgPane(type, fmtString, va_alist) Xint type;`09`09/* XRN_INFO, XRN_SERIOUS */ Xchar *fmtString; X#endif X#if !defined(__STDC__) `7C`7C defined(NOSTDHDRS) X va_dcl X#endif X/* X * brings up a new vertical pane, not moded X * X * the pane consists of 3 parts: title bar, scrollable text window, X * button box X */ X`7B X va_list args; X Widget pane, buttonBox, label, frame; X Arg fontArgs`5B1`5D; X Arg paneArgs`5B4`5D; X int x = 0; X int y = 0; X int width = 0; X int height = 0; X#ifdef MOTIF X XmString labelString; X#else X DwtCompString labelString; X#endif X static Arg labelArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNlabelString, (XtArgVal) NULL`7D, X`09`7BXmNskipAdjust, (XtArgVal) True`7D, X#else X`09`7BDwtNlabel,`09(XtArgVal) NULL`7D, X#endif X `7D; X static Arg boxArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNnumColumns,`09`09(XtArgVal) 1`7D, X`09`7BXmNadjustLast, `09(XtArgVal) False`7D, X`09`7BXmNorientation,`09(XtArgVal) XmHORIZONTAL`7D, X`09`7BXmNpacking,`09`09(XtArgVal) XmPACK_COLUMN`7D, X`09`7BXmNallowResize,`09(XtArgVal) True`7D, X`09`7BXmNskipAdjust, `09(XtArgVal) True`7D, X#else X`09`7BDwtNresizeHeight,`09(XtArgVal) True`7D, X`09`7BDwtNresizeWidth,`09(XtArgVal) False`7D, X`09`7BDwtNorientation,`09(XtArgVal) DwtOrientationHorizontal`7D, X`09`7BDwtNmenuPacking,`09(XtArgVal) DwtMenuPackingTight`7D, X`09`7BDwtNmenuExtendLastRow, (XtArgVal) False`7D, X`09`7BDwtNborderWidth,`09(XtArgVal) 3`7D, X`09`7BDwtNentryBorder,`09(XtArgVal) 2`7D, X`09`7BDwtNchildOverlap,`09(XtArgVal) False`7D, X`09`7BDwtNmenuNumColumns,`09(XtArgVal) 4`7D, X`09`7BDwtNmin,`09`09(XtArgVal) 30`7D, X#endif X `7D; X static Arg shellArgs`5B`5D = `7B X`09`7BXtNinput, (XtArgVal) True`7D, X`09`7BXtNsaveUnder, (XtArgVal) False`7D, X `7D; X static Arg textArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNrows,`09`09(XtArgVal) 10`7D, X`09`7BXmNcolumns,`09`09(XtArgVal) 80`7D, X`09`7BXmNwordWrap, `09`09(XtArgVal) TRUE`7D, X`09`7BXmNscrollVertical, `09(XtArgVal) TRUE`7D, X`09`7BXmNeditMode, `09`09(XtArgVal) XmMULTI_LINE_EDIT`7D, X`09`7BXmNeditable,`09`09(XtArgVal) FALSE`7D, X#else X`09`7BDwtNrows,`09`09(XtArgVal) 10`7D, X`09`7BDwtNcols,`09`09(XtArgVal) 80`7D, X`09`7BDwtNwordWrap, `09`09(XtArgVal) TRUE`7D, X`09`7BDwtNscrollVertical, `09(XtArgVal) TRUE`7D, X`09`7BDwtNeditable,`09`09(XtArgVal) FALSE`7D, X#endif X `7D; X X#if defined(__STDC__) && !defined(NOSTDHDRS) X va_start(args, fmtString); X#else `20 X va_start(args); X#endif X if ((XRNState & XRN_X_UP) != XRN_X_UP) `7B X`09(void) vfprintf(stderr, fmtString, args); X`09(void) fprintf(stderr, "\n"); X`09return; X `7D X X if ((type == XRN_INFO) && (app_resources.info == False)) `7B X`09(void) vsprintf(MesgString, fmtString, args); X`09infoNow(MesgString); X`09return; X `7D X X if (MesgTopLevel != (Widget) 0 && !MesgMapped) `7B X#ifdef MOTIF X`09XmTextSetString(MesgText, MesgString); X`09XmTextShowPosition (MesgText, (XmTextPosition) sizeof(MesgString)); X#else X`09DwtSTextSetString(MesgText, MesgString); X`09DwtTextShowPosition(MesgText, sizeof(MesgString)); X#endif X`09XtMapWidget(MesgTopLevel); X`09MesgMapped = True; X`09return; X `7D X if (MesgTopLevel == (Widget) 0) `7B X`09MesgTopLevel = XtCreatePopupShell("Information", topLevelShellWidgetClass V, X`09`09`09`09`09 TopLevel, shellArgs, XtNumber(shellArgs)); X X`09XtSetArg(paneArgs`5B0`5D, XtNx, &x); X`09XtSetArg(paneArgs`5B1`5D, XtNy, &y); X`09XtSetArg(paneArgs`5B2`5D, XtNwidth, &width); X`09XtSetArg(paneArgs`5B3`5D, XtNheight, &height); X`09XtGetValues(TopLevel, paneArgs, XtNumber(paneArgs)); X`09XtSetArg(paneArgs`5B0`5D, XtNx, x); X`09XtSetArg(paneArgs`5B1`5D, XtNy, y); X`09XtSetArg(paneArgs`5B2`5D, XtNwidth, width); X`09XtSetArg(paneArgs`5B3`5D, XtNheight, height); X#ifdef MOTIF X`09pane = XtCreateManagedWidget("pane", xmPanedWindowWidgetClass, X`09`09`09`09 MesgTopLevel, paneArgs, XtNumber(paneArgs)); X#else X`09pane = DwtPaneCreate(MesgTopLevel, "mesgPane",`20 X`09`09`09`09 paneArgs, 3); X`09XtManageChild(pane); X#endif X X`09(void) vsprintf(MesgString, fmtString, args); X X`09if (labelArgs`5B0`5D.value == NULL) `7B X#ifdef MOTIF X`09 labelArgs`5B0`5D.value = (XtArgVal) XmStringLtoRCreate( X`09`09"Information (can be left up or dismissed)", X`09`09XmSTRING_DEFAULT_CHARSET); X#else X`09 labelArgs`5B0`5D.value = (XtArgVal) DwtLatin1String( X`09`09"Information (can be left up or dismissed)"); X#endif X`09`7D X#ifdef MOTIF X`09label = XtCreateManagedWidget("label", xmLabelWidgetClass, pane, X`09`09`09`09 labelArgs, XtNumber(labelArgs)); X X`09frame = XtCreateManagedWidget("mesgFrame", xmFrameWidgetClass, X`09`09`09`09`09pane, NULL, 0); X`09MesgText = XmCreateScrolledText(frame, "text",`20 X`09`09`09`09`09 textArgs, XtNumber(textArgs)); X#else X`09label = DwtLabelCreate(pane, "label",`20 X`09`09`09`09 labelArgs, XtNumber(labelArgs)); X X`09XtManageChild(label); X`09MesgText = DwtSTextCreate(pane, "text",`20 X`09`09`09`09`09 textArgs, XtNumber(textArgs)); X#endif X`09XtManageChild(MesgText); X X#ifdef MOTIF X`09buttonBox = XtCreateManagedWidget("box", xmRowColumnWidgetClass, pane, X`09`09`09`09`09 boxArgs, XtNumber(boxArgs)); X`09dismissArgs`5B1`5D.value = (XtArgVal) XmStringLtoRCreate( X`09`09`09`09`09`09dismissArgs`5B0`5D.value, X`09`09`09`09`09`09XmSTRING_DEFAULT_CHARSET); X`09XtCreateManagedWidget("dismiss", xmPushButtonWidgetClass, buttonBox, X`09`09`09 dismissArgs, XtNumber(dismissArgs)); X `20 X#else X`09buttonBox = DwtMenuCreate(pane, "box",`20 X`09`09`09`09`09 boxArgs, XtNumber(boxArgs)); X`09XtManageChild(buttonBox); X`09dismissArgs`5B1`5D.value = (XtArgVal) DwtLatin1String(dismissArgs`5B0`5D. Vvalue); X`09XtManageChild(DwtPushButtonCreate(buttonBox, "dismiss", X`09`09`09 dismissArgs, XtNumber(dismissArgs))); X `20 X#endif X`09XtRealizeWidget(MesgTopLevel); X X`09XtPopup(MesgTopLevel, XtGrabNone); X`09MesgMapped = True; X X`09/* xthCenterWidgetOverCursor(MesgTopLevel); */ X X#ifdef MOTIF X`09XmTextSetString(MesgText, MesgString); X`09XmTextShowPosition (MesgText, (XmTextPosition) sizeof(MesgString)); X#else X`09DwtSTextSetString(MesgText, MesgString); X`09DwtTextShowPosition(MesgText, sizeof(MesgString)); X#endif X X `7D else `7B X`09long len; X`09long newlen; X`09char addBuff`5BMESG_SIZE`5D; X X`09(void) vsprintf(addBuff, fmtString, args); X`09len = utStrlen(MesgString); X`09newlen = utStrlen(addBuff); X X`09if ((len + 10 + newlen) > MESG_SIZE) `7B X`09 (void) strcpy(MesgString, addBuff); X#ifdef MOTIF X`09 XmTextSetString(MesgText, MesgString); X`09 XmTextShowPosition(MesgText, (XmTextPosition) sizeof(MesgString)); X#else X`09 DwtSTextSetString(MesgText, MesgString); X`09 DwtTextShowPosition(MesgText, sizeof(MesgString)); X#endif X`09 return; X`09`7D X X`09if (! (type & XRN_APPEND)) `7B X`09 (void) strcat(&MesgString`5Blen`5D, "\n--------\n"); X`09 (void) strcat(&MesgString`5Blen + 10`5D, addBuff); X`09 `7D X`09else `7B X`09 (void) strcat(&MesgString`5Blen`5D, "\n"); X`09 (void) strcat(&MesgString`5Blen + 1`5D, addBuff); X`09`7D X X#ifdef MOTIF X`09XmTextSetString(MesgText, MesgString); X`09XmTextShowPosition(MesgText, (XmTextPosition) sizeof(MesgString)); X#else X`09DwtSTextSetString(MesgText, MesgString); X`09DwtTextShowPosition(MesgText, sizeof(MesgString)); X#endif X `7D X `20 X return; X`7D X X Xvoid Xinfo(msg) Xchar *msg; X/* X * put an informational 'msg' into the top information label X */ X`7B X Arg infoLineArg`5B1`5D; X#ifdef MOTIF X XmString labelString; X#else X DwtCompString labelString; X#endif X X if ((XRNState & XRN_X_UP) == XRN_X_UP) `7B X#ifdef MOTIF X`09labelString = XmStringLtoRCreate(msg, XmSTRING_DEFAULT_CHARSET); X`09XtSetArg(infoLineArg`5B0`5D, XmNlabelString, labelString); X`09XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XmStringFree(labelString); X#else X`09labelString = DwtLatin1String(msg); X`09XtSetArg(infoLineArg`5B0`5D, DwtNlabel, labelString); X`09XtSetValues(TopInfoLine, infoLineArg, XtNumber(infoLineArg)); X`09XtFree(labelString); X#endif X `7D else `7B X`09(void) fprintf(stderr, "XRN: %s\n", msg); X `7D X return; X`7D X X Xvoid XinfoNow(msg) Xchar *msg; X/* X * put an informational 'msg' into the top information label and force an up Vdate X */ X`7B X info(msg); X if ((XRNState & XRN_X_UP) == XRN_X_UP) `7B X`09xthHandleAllPendingEvents(); X `7D X return; X`7D X $ CALL UNPACK MESG.C;1 490196800 $ create 'f' X#ifndef MESG_H X#define MESG_H X X/* X * $Header: /users/ricks/xrn/src/RCS/mesg.h,v 1.5 90/09/29 01:10:47 ricks Ex Vp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * mesg.h: display info, warning, and error messages X * X */ X X#define XRN_INFO `091<<0 X#define XRN_SERIOUS `091<<1 X#define XRN_APPEND`091<<2 X Xextern void info(/* char *msg */); Xextern void infoNow(/* char *msg */); X#if defined(__STDC__) && !defined(NOSTDHDRS) Xextern void mesgPane(int /*type*/, char * /*fmtString*/, ...); X#else Xextern void mesgPane(/* int type, char *fmtString, args */); X#endif X Xextern char error_buffer`5B2048`5D; X X#endif /* MESG_H */ $ CALL UNPACK MESG.H;1 957821219 $ create 'f' X#ifndef MODES_H X#define MODES_H X X/* X * $Header: /users/ricks/xrn/src/RCS/modes.h,v 1.7 90/09/29 02:27:42 ricks E Vxp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * modes.h: definitions of the various XRN modes X */ X X/* definition of the modes */ X#define NEWSGROUP_MODE 0 X#define ARTICLE_MODE 1 X#define ADD_MODE 2 X#define ALL_MODE 3 X#define NO_MODE 4 X#define MAX_MODE 4 X X#define ABORT -1 X#define ERROR 0 X#define NOMATCH 1 X#define MATCH 2 X#define WINDOWCHANGE 3 X#define EXIT 4 X X#define BACK 0 X#define FORWARD 1 X X#endif /* MODES_H */ $ CALL UNPACK MODES.H;1 1112029439 $ create 'f' X#define mxrn_width 32 X#define mxrn_height 40 Xstatic char mxrn_bits`5B`5D = `7B X 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xa0, 0x09, 0x8a, 0x4e, 0xc4, X 0x19, 0x53, 0xd2, 0xa4, 0xa9, 0x22, 0x52, 0xc5, 0x49, 0x22, 0x4e, 0xa6, X 0x49, 0x52, 0x52, 0xc4, 0x49, 0x8a, 0x52, 0xa4, 0x01, 0x00, 0x00, 0xc0, X 0x01, 0x00, 0x00, 0xa0, 0xfd, 0xff, 0xff, 0xcf, 0x05, 0x00, 0x00, 0xa8, X 0x85, 0xb9, 0x52, 0xc8, 0x85, 0xaa, 0x22, 0xa8, 0x85, 0xa9, 0x26, 0xc8, X 0x05, 0x00, 0x00, 0xa8, 0x05, 0xb5, 0x32, 0xc8, 0x05, 0x97, 0x12, 0xa8, X 0x05, 0xb5, 0x1b, 0xc8, 0x05, 0x00, 0x00, 0xa8, 0xf5, 0xff, 0xff, 0xcb, X 0x05, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0xc8, 0xc5, 0xf8, 0x97, 0xa9, X 0x35, 0x0b, 0xf4, 0xca, 0x05, 0x08, 0x04, 0xa8, 0x45, 0x98, 0xb4, 0xcb, X 0xb5, 0x0b, 0x04, 0xa8, 0x05, 0x88, 0xc4, 0xcb, 0xb5, 0x7b, 0x74, 0xaa, X 0xc5, 0x08, 0x04, 0xc8, 0x05, 0xf8, 0xb7, 0xab, 0xf5, 0x03, 0x60, 0xc8, X 0x85, 0xb8, 0x07, 0xa8, 0x05, 0x00, 0x00, 0xc8, 0xfd, 0xff, 0xff, 0xaf, X 0x01, 0x00, 0x00, 0xc0, 0xab, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0xd5, X 0xff, 0xff, 0xff, 0xff`7D; $ CALL UNPACK MXRN.XBM;1 456095782 $ create 'f' X#ifndef NEWS_H X#define NEWS_H X X/* X * $Header: /net/opus/mnt/ricks/src/X/xrn/RCS/news.h,v 1.10 90/09/29 01:10:5 V3 ricks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X X#ifndef AVL_H X#include "avl.h" X#endif X X/* X * news.h: internal data structures X * X */ X X/* handle first and/or last article number changes */ Xextern void articleArrayResync(/* struct newsgroup *newsgroup, int first, in Vt list */); Xextern void updateArticleArray(/* struct newsgroup *newsgroup */); X Xtypedef long art_num; /* easy way to pick out variables refering to artic Vles */ Xtypedef long ng_num; /* easy way to pick out newsgroup variables V */ X Xextern avl_tree *NewsGroupTable; Xextern int ActiveGroupsCount; X X/* this is indexed via 'current - first' */ Xstruct article `7B X unsigned long status; X /* ART_* */ X char *subject; /* subject line */ X char *author; /* author name */ X char *lines; /* number of lines in the article */ X char *filename; /* name of the article file */ X long position; /* header/body seperation point (bytes) */ X`7D; X X Xstruct newsgroup `7B X char *name; /* name of the group V */ X ng_num newsrc; /* index of this group into Newsrc V */ X unsigned long status; X /* NG_* */ X art_num first; /* first available article number V */ X art_num last; /* last article number V */ X art_num current; /* current article number V */ X struct article *articles; X struct list *nglist; /* newsgroup entry for unsubscribed groups V */ X`7D; X X/* X * NOTE: if first > last, that means that there are no articles available fo Vr X * the group and no articles array will exist X */ X X X/* article has been read / is unread */ X#define ART_READ 0x0001 X#define ART_UNREAD 0x0002 X/* article has been fetched / is unfetched */ X#define ART_FETCHED 0x0010 X#define ART_UNFETCHED 0x0020 X/* article is not available */ X#define ART_UNAVAIL 0x0040 X X/* headers */ X#define ART_ALL_HEADERS 0x0100 X#define ART_STRIPPED_HEADERS 0x0200 X X/* rotation */ X#define ART_ROTATED 0x0400 X#define ART_UNROTATED 0x0800 X X/* saved */ X#define ART_SAVED 0x4000 X#define ART_UNSAVED 0x8000 X X/* marked */ X#define ART_MARKED 0x1000 X#define ART_UNMARKED 0x2000 X X#define ART_CLEAR (ART_UNREAD `7C ART_UNFETCHED `7C ART_STRIPPED_HEADE VRS `7C ART_UNROTATED `7C ART_UNMARKED) X#define ART_CLEAR_READ (ART_READ `7C ART_UNFETCHED `7C ART_STRIPPED_HEADERS V `7C ART_UNROTATED `7C ART_UNMARKED) X X/* helper macros */ X#define IS_READ(art) (((art).status & ART_READ) == ART_READ) X#define IS_UNREAD(art) (((art).status & ART_UNREAD) == ART_UNREAD) X#define IS_FETCHED(art) (((art).status & ART_FETCHED) == ART_FETCHED) X#define IS_UNFETCHED(art) (((art).status & ART_UNFETCHED) == ART_UNFETCHED) X#define IS_UNAVAIL(art) (((art).status & ART_UNAVAIL) == ART_UNAVAIL) X#define IS_ALL_HEADERS(art) (((art).status & ART_ALL_HEADERS) == ART_ALL_HEA VDERS) X#define IS_ROTATED(art) (((art).status & ART_ROTATED) == ART_ROTATED) X#define IS_SAVED(art) (((art).status & ART_SAVED) == ART_SAVED) X#define IS_MARKED(art) (((art).status & ART_MARKED) == ART_MARKED) X `20 X `20 X#define SET_READ(art) ((art).status &= `7EART_UNREAD, (art).status `7C= ART_ VREAD) X#define SET_UNREAD(art) ((art).status &= `7EART_READ, (art).status `7C= ART_ VUNREAD) X#define SET_FETCHED(art) ((art).status &= `7EART_UNFETCHED, (art).status `7C V= ART_FETCHED) X#define SET_UNFETCHED(art) ((art).status &= `7EART_FETCHED, (art).status `7C V= ART_UNFETCHED) X#define SET_STRIPPED_HEADERS(art) ((art).status &= `7EART_ALL_HEADERS, (art) V.status `7C= ART_STRIPPED_HEADERS) X#define SET_ALL_HEADERS(art) ((art).status &= `7EART_STRIPPED_HEADERS, (art) V.status `7C= ART_ALL_HEADERS) X#define SET_UNROTATED(art) ((art).status &= `7EART_ROTATED, (art).status `7C V= ART_UNROTATED) X#define SET_ROTATED(art) ((art).status &= `7EART_UNROTATED, (art).status `7C V= ART_ROTATED) X#define SET_UNAVAIL(art) ((art).status `7C= ART_UNAVAIL) X#define SET_SAVED(art) ((art).status &= `7EART_UNSAVED, (art).status `7C= AR VT_SAVED) X#define SET_MARKED(art) ((art).status &= `7EART_UNMARKED, (art).status `7C= V ART_MARKED) X#define SET_UNMARKED(art) ((art).status &= `7EART_MARKED, (art).status `7C= V ART_UNMARKED) X X#define CLEAR_FILE(art) \ X if ((art).filename != NIL(char)) `7B \ X SET_UNFETCHED(art); \ X FREE((art).filename); \ X (art).filename = NIL(char); \ X `7D`09 X X#define CLEAR_SUBJECT(art) \ X if ((art).subject != NIL(char)) `7B \ X FREE((art).subject); \ X (art).subject = NIL(char); \ X `7D`09 X X#define CLEAR_AUTHOR(art) \ X if ((art).author != NIL(char)) `7B \ X FREE((art).author); \ X (art).author = NIL(char); \ X `7D`09 X X#define CLEAR_LINES(art) \ X if ((art).lines != NIL(char)) `7B \ X FREE((art).lines); \ X (art).lines = NIL(char); \ X `7D`09 X X/* newsgroup is subscribed/unsubscribed to */ X#define NG_SUB 0x0010 X#define NG_UNSUB 0x0020 X/* no entry in the .newsrc for this group */ X#define NG_NOENTRY 0x0040 X/* newsgroup can be posted to / can not be posted to / is moderated */ X#define NG_POSTABLE 0x1000 X#define NG_UNPOSTABLE 0x2000 X#define NG_MODERATED 0x4000 X X#define IS_SUBSCRIBED(ng) (((ng)->status & NG_SUB) == NG_SUB) X#define IS_NOENTRY(ng) (((ng)->status & NG_NOENTRY) == NG_NOENTRY) X `20 X#define SET_SUB(ng) ((ng)->status &= `7ENG_UNSUB, (ng)->status `7C= NG_SU VB) X#define SET_UNSUB(ng) ((ng)->status &= `7ENG_SUB, (ng)->status `7C= NG_UNSU VB) X#define CLEAR_NOENTRY(ng) ((ng)->status &= `7ENG_NOENTRY) X X#define EMPTY_GROUP(ng) ((ng)->last < (ng)->first) X `20 X#define CLEAR_ARTICLES(ng) \ X if ((ng)->articles != NIL(struct article)) `7B \ X FREE((ng)->articles); \ X (ng)->articles = NIL(struct article); \ X `7D`09 X X#define INDEX(artnum) (artnum - newsgroup->first) X#define CURRENT INDEX(newsgroup->current) X#define LAST INDEX(newsgroup->last) X Xextern ng_num CurrentGroupNumber; /* current index into the newsrc array V */ Xextern ng_num MaxGroupNumber; /* size of the newsrc array V */ X Xstruct newsgroup **Newsrc; /* sequence list for .newsrc file V */ X X#define NOT_IN_NEWSRC -1 /* must be less than 0 */ X X/* not a valid group (must be less than 0) */ X#define NO_GROUP -1 X X X#define GROUP_NAME_SIZE 128 X X#endif /* NEWS_H */ $ CALL UNPACK NEWS.H;1 1327394726 $ create 'f' X Xextern char *XtNewString(); Xletter `5Ba-zA-Z`5D Xany `5Ba-zA-Z$0-9.\-+_`7B`7D\`7C&`5D Xdigit `5B0-9`5D X%% X yyin = Newsrcfp; X`5E`5B \t`5D*"\n" ; X"\n" return(EOL); X"-" return(DASH); X"," return(COMMA); X`5B:!`5D `7Byylval.character = yytext`5B0`5D; return(SEPARATOR) V; `7D; `20 X`7Bdigit`7D+ `7Byylval.integer = atoi(yytext); return(NUMBER); `7D; X`7Bletter`7D`7Bany`7D+ `7Byylval.string = XtNewString(yytext); return(NAM VE); `7D; X`5E`7Bany`7D+ `7Byylval.string = XtNewString(yytext); return(NAME) V; `7D; X`5B \t`5D ; X`5E"options ".*"\n" `7B X optionsLine = XtNewString(yytext); X optionsLine`5ButStrlen(optionsLine) - 1`5D = '\0'; X `7D; X%% X/* X * $Header: /users/ricks/xrn/src/RCS/newsrc.l,v 1.8 90/09/29 01:14:03 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X Xyywrap() X`7B X return(1); X`7D X X/*ARGSUSED*/ Xyyerror(s) Xchar *s; X`7B X /* lint/kludge */ X#ifdef lint X (void) yyinput(); X (void) yyoutput(0); X (void) yyunput(0); X#endif /* lint */ X`7D X $ CALL UNPACK NEWSRC.L;1 1516660790 $ create 'f' X%`7B X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/newsrc.y,v 1 V.8 90/09/29 01:14:08 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * newsrc.y - yacc parser for the newsrc file X */ X X#include "copyright.h" X#include X#include X#include "config.h" X#include "utils.h" X#include "avl.h" X#include "mesg.h" X#include "news.h" X#include "newsrcfile.h" X%`7D X `20 X%union `7B X int integer; X char *string; X char character; X struct list *item; X`7D X X X%token NAME X%token SEPARATOR X%token NUMBER X%token EOL X%token DASH X%token COMMA X X%type artlist X%type articles X X%start goal X X%% Xgoal : newsrc_file ; X Xnewsrc_file : newsrc_line X `7C newsrc_file newsrc_line ; X Xnewsrc_line : NAME SEPARATOR artlist EOL X `7B X`09`09 struct newsgroup *newsgroup; X`09`09 char *dummy; X X`09`09 if (!avl_lookup(NewsGroupTable, $1, &dummy)) `7B X`09`09`09mesgPane(XRN_SERIOUS, "Bogus newsgroup `60%s', removing from the ne Vwsrc file", $1); X`09`09 `7D else `7B X`09`09`09newsgroup = (struct newsgroup *) dummy; X`09`09`09if (IS_NOENTRY(newsgroup)) `7B X`09`09`09 CLEAR_NOENTRY(newsgroup); X`09`09`09 newsgroup->status `7C= ($2 == ':' ? NG_SUB : NG_UNSUB); X`09`09`09 newsgroup->nglist = $3; X`09`09`09 updateArticleArray(newsgroup); X`09`09`09 newsgroup->newsrc = MaxGroupNumber; X`09`09`09 Newsrc`5BMaxGroupNumber++`5D = newsgroup; X`09`09`09`7D else `7B X`09`09`09 mesgPane(XRN_SERIOUS, "Duplicate entry for `60%s', using first V one", X`09`09`09`09`09 $1); X`09`09`09`7D X`09`09 `7D X`09 `7D X `7C NAME SEPARATOR EOL X `7B X`09`09 struct newsgroup *newsgroup; X`09`09 char *dummy; X X`09`09 if (!avl_lookup(NewsGroupTable, $1, &dummy)) `7B X`09`09`09mesgPane(XRN_SERIOUS, "Bogus newsgroup `60%s', removing from the ne Vwsrc file", $1); X`09`09 `7D else `7B X`09`09`09newsgroup = (struct newsgroup *) dummy; X`09`09`09if (IS_NOENTRY(newsgroup)) `7B X`09`09`09 CLEAR_NOENTRY(newsgroup); X`09`09`09 newsgroup->status `7C= ($2 == ':' ? NG_SUB : NG_UNSUB); X`09`09`09 newsgroup->nglist = NIL(struct list); X`09`09`09 updateArticleArray(newsgroup); X`09`09`09 newsgroup->newsrc = MaxGroupNumber; X`09`09`09 Newsrc`5BMaxGroupNumber++`5D = newsgroup; X`09`09`09`7D else `7B X`09`09`09 mesgPane(XRN_SERIOUS, "Duplicate entry for `60%s', using first V one", X`09`09`09`09`09 $1); X`09`09`09`7D X`09`09 `7D X`09 `7D X ; X Xartlist : articles X `7B X`09`09 $$ = $1; X`09`09`7D X `7C artlist COMMA articles X `7B X`09`09 struct list *temp; X X`09`09 $$ = $1; X`09`09 for (temp = $$; temp != NIL(struct list); temp = temp->next) `7B X`09`09`09if (temp->next == NIL(struct list)) `7B X`09`09`09 temp->next = $3; X`09`09`09 break; X`09`09`09`7D X`09`09 `7D X`09`09`7D X ; X Xarticles : NUMBER X `7B X`09`09 $$ = ALLOC(struct list); X`09`09 $$->type = SINGLE; X`09`09 $$->contents.single = (art_num) $1; X`09`09 $$->next = NIL(struct list); X`09`09`7D X `7C NUMBER DASH NUMBER X `7B X`09`09 $$ = ALLOC(struct list); X`09`09 $$->type = RANGE; X`09`09 $$->contents.range.start = (art_num) $1; X`09`09 $$->contents.range.end = (art_num) $3; X`09`09 $$->next = NIL(struct list); X`09`09`7D X ; X X `20 X%% X#include "lex.yy.c" X $ CALL UNPACK NEWSRC.Y;1 957435623 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/newsrcfile.c V,v 1.14 90/09/29 01:13:00 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * newsrcfile.c: routines for reading and updating the newsrc file X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#include X#else X#include X#include X#endif X#include X#include "config.h" X#include "utils.h" X#include X#ifdef VMS X#ifndef R_OK X#define F_OK 0 /* does file exist */ X#define X_OK 1 /* is it executable by caller */ X#define W_OK 2 /* writable by caller */ X#define R_OK 4 /* readable by caller */ X#endif /* R_OK */ X#define index strchr X#endif /* VMS */ X#ifdef aiws X#include X#endif /* aiws */ X#include "news.h" X#include "error_hnds.h" X#include "mesg.h" X#include "xrn.h" X#include "dialogs.h" X#include "resources.h" X#include "newsrcfile.h" X Xchar *NewsrcFile; /* newsrc file name */ XFILE *Newsrcfp; /* newsrc file pointer */ Xchar *optionsLine; /*`60options' line */ X X#define OKAY 1 X#define FATAL 0 X X X/* X * copy newsrc file to .oldnewsrc file X */ X Xstatic int XcopyNewsrcFile(old, save) Xchar *old; /* name of file to save */ Xchar *save; /* name of file to save to */ X`7B X FILE *orig, *new; X char buf`5BBUFSIZ`5D; X char *newFile; X int num_read; X X if ((orig = fopen(old, "r")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot open the .newsrc file (%s) for copying: %s", old, X`09`09 errmsg(errno)); X`09return FATAL; X `7D X X if ((newFile = utTildeExpand(save)) == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot tilde expand the .newsrc save file (%s)", save); X`09return FATAL; X `7D X X if (STREQ(newFile, "")) `7B X`09 mesgPane(XRN_SERIOUS, "hmmm.... file name is \"\"\n"); X`09 return FATAL; X `7D X X /* if .oldnewsrc is a link to .newsrc we could have trouble, so unlink i Vt */ X (void) unlink(newFile); X `20 X if ((new = fopen(newFile, "w")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, "Cannot open the .newsrc save file (%s): %s", X`09`09 save, errmsg(errno)); X`09return FATAL; X `7D X X while (num_read = fread(buf, sizeof(char), BUFSIZ, orig)) `7B X`09 if (! fwrite(buf, sizeof(char), num_read, new)) `7B X`09 mesgPane(XRN_SERIOUS, X`09`09 "Error writing to .newsrc save file (%s): %s", X`09`09 save, errmsg(errno)); X`09 return FATAL; X`09 `7D X `7D X X (void) fclose(orig); X if (fclose(new) == EOF) `7B X`09 mesgPane(XRN_SERIOUS, "Error writing to .newsrc save file (%s): %s", X`09`09 save, errmsg(errno)); X`09 return FATAL; X `7D X X return OKAY; X`7D X X Xint Xreadnewsrc(newsrcfile, savenewsrcfile) Xchar *newsrcfile; Xchar *savenewsrcfile; X/* X * read, parse, and process the .newsrc file X * X * returns: 0 for fatal error, non-zero for okay X * X */ X`7B X struct stat buf; X char *name; X char *nntp; X int nameLth; X#ifdef VMS X int nntp_len; X char *nntp_end; X#endif X `20 X /* create the Newsrc array structure */ X Newsrc = ARRAYALLOC(struct newsgroup *, ActiveGroupsCount); X X optionsLine = NIL(char); X X if ((NewsrcFile = utTildeExpand(newsrcfile)) == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot tilde expand the newsrc file name (%s)", X`09`09 newsrcfile); X`09return FATAL; X `7D X X /* check for .newsrc-NNTPSERVER */ X X if (app_resources.nntpServer) `7B X`09nntp = app_resources.nntpServer; X `7D else `7B X nntp = getenv("NNTPSERVER"); X `7D X X if (nntp) `7B X#ifdef VMS X`09if (nntp_end = index(nntp,':')) `7B /* Look for the : in the name */ X`09 nntp_len = nntp_end-nntp;`09 /* Get the length of the first X`09`09`09`09`09 part */ X`09`7D else nntp_len = strlen(nntp);`09 /* If no colon, use the whole X`09`09`09`09`09 string */ X`09nameLth = strlen(NewsrcFile) + nntp_len; X#else X nameLth = strlen(NewsrcFile) + strlen(nntp); X#endif X name = ARRAYALLOC(char, nameLth + 20); X (void) strcpy(name, NewsrcFile); X (void) strcat(name, "-"); X#ifdef VMS X`09(void) strncat(name, nntp, nntp_len); X#else X (void) strcat(name, nntp); X#endif X `20 X if (access(name, R_OK) != 0) `7B X`09 NewsrcFile = XtNewString(NewsrcFile); X`09`7D else `7B X`09 NewsrcFile = XtNewString(name); X `7D X`09FREE(name); X `7D else `7B X NewsrcFile = XtNewString(NewsrcFile); X `7D X X if (access(NewsrcFile, R_OK) != 0) `7B X X`09if (errno != ENOENT) `7B X`09 mesgPane(XRN_SERIOUS, "Cannot read newsrc file (%s): %s", X`09`09 NewsrcFile, errmsg(errno)); X`09 return FATAL; X`09`7D X`09mesgPane(XRN_INFO, "Creating a newsrc (%s) file for you", NewsrcFile); X`09if ((Newsrcfp = fopen(NewsrcFile, "w")) == NULL) `7B X`09 mesgPane(XRN_SERIOUS, "Cannot create a newsrc file (%s): %s", X`09`09 NewsrcFile, errmsg(errno)); X`09 return(FATAL); X`09`7D X`09(void) fprintf(Newsrcfp, "news.announce.newusers:\n"); X`09(void) fclose(Newsrcfp); X `7D X X if (stat(NewsrcFile, &buf) == -1) `7B X`09mesgPane(XRN_SERIOUS, "Cannot stat %s: %s", NewsrcFile, errmsg(errno)); X`09return FATAL; X `7D X X if (buf.st_size == 0) `7B X`09mesgPane(XRN_SERIOUS, "%s is zero length, aborting", NewsrcFile); X`09return FATAL; X `7D X X if ((Newsrcfp = fopen(NewsrcFile, "r")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot open the newsrc file for reading, %s: %s", X`09`09 NewsrcFile, errmsg(errno)); X`09return FATAL; X `7D X X if (yyparse() != 0) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot parse the newsrc file (%s) -- error on line %ld", X`09`09 NewsrcFile, MaxGroupNumber + 1); X`09return FATAL; X `7D X X if (!copyNewsrcFile(NewsrcFile, savenewsrcfile)) X`09 return FATAL; X X (void) fclose(Newsrcfp); X `20 X Newsrcfp = NIL(FILE); X X return(OKAY); X`7D X X Xstatic char * XngEntry(newsgroup) Xstruct newsgroup *newsgroup; X`7B X int first = 1; X struct list *item; X char buffer`5B32`5D, *end; X static char line`5B4096`5D; X X end = line; X *end = '\0'; X X /* process the .newsrc line */ X X for (item = newsgroup->nglist; item != NIL(struct list); item = item->ne Vxt) `7B X`09switch (item->type) `7B X`09 case SINGLE: X`09 (void) sprintf(buffer, "%d", item->contents.single); X`09 break; X X`09 case RANGE: X`09 if (item->contents.range.start != item->contents.range.end) `7B X`09`09(void) sprintf(buffer, "%d-%d", X`09`09`09 item->contents.range.start, X`09`09`09 item->contents.range.end); X`09 `7D else `7B X`09`09(void) sprintf(buffer, "%d", item->contents.range.start); X`09 `7D X`09 break; X`09`7D X`09if (!first) `7B X`09 (void) strcat(end++, ","); X`09`7D X`09first = 0; X`09(void) strcat(end, buffer); X`09end += utStrlen(buffer); X `7D X return(line); X`7D X X Xint Xupdatenewsrc() X/* X * write out an up to date copy of the .newsrc file X * X * returns: 0 for fatal error, non-zero for okay X * X */ X`7B X ng_num indx; X X static FILE *newsrcfp; /* file pointer for the newsc file */ X static struct stat lastStat; /* last stat done on the file */ X struct stat currentStat; /* current stat */ X static int done = 0; X#ifndef VMS X static char tempfile`5B4096`5D; X#endif /* VMS */ X X if (!done) `7B X (void) stat(NewsrcFile, &lastStat); X`09/* must be in the same filesystem so `60rename' will work */ X#ifndef VMS X`09(void) sprintf(tempfile, "%s.temp", NewsrcFile); X#endif /* VMS */ X`09done = 1; X `7D X X (void) stat(NewsrcFile, ¤tStat); X X if (currentStat.st_mtime > lastStat.st_mtime) `7B X`09if (ConfirmationBox(TopLevel, ".newsrc file updated by another program, c Vontinue?") == XRN_CB_ABORT) `7B X`09 ehNoUpdateExitXRN(); X`09`7D X `7D X X#ifndef VMS X if ((newsrcfp = fopen(tempfile, "w")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot open the .newsrc temporary file (%s): %s", tempfile, X`09`09 errmsg(errno)); X`09return(FATAL); X `7D X#else X if ((newsrcfp = fopen(NewsrcFile, "w")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, X`09`09 "Cannot create a new version of the .newsrc file (%s): %s", X`09`09 NewsrcFile, errmsg(errno)); X`09return(FATAL); X `7D X#endif /* VMS */ X X /* X * handle outputing the options line X */ X if (optionsLine != NIL(char)) `7B X`09(void) fprintf(newsrcfp, "%s\n", optionsLine); X `7D X X for (indx = 0; indx < MaxGroupNumber; indx++) `7B X`09struct newsgroup *newsgroup = Newsrc`5Bindx`5D; X`09int nocomma = 1, inrange = 1; X`09art_num lastread = 1, j; X X`09(void) fprintf(newsrcfp, "%s%c", newsgroup->name, X`09`09 (IS_SUBSCRIBED(newsgroup) ? ':' : '!')); X X`09if (newsgroup->last == 0) `7B X`09 (void) fprintf(newsrcfp, "\n"); X`09 continue; X`09`7D X X`09if (newsgroup->articles == NIL(struct article)) `7B X`09 if (newsgroup->nglist) `7B X`09`09fprintf(newsrcfp, " %s\n", ngEntry(newsgroup)); X`09 `7D else `7B X`09`09(void) fprintf(newsrcfp, " 1-%d\n", newsgroup->last); X`09 `7D X`09 continue; X`09`7D X`09 X`09if (newsgroup->last >= newsgroup->first) `7B X X`09 for (j = newsgroup->first; j <= newsgroup->last; j++) `7B X`09`09if (inrange && IS_UNREAD(newsgroup->articles`5BINDEX(j)`5D) && X`09`09 !IS_UNAVAIL(newsgroup->articles`5BINDEX(j)`5D)) `7B X`09`09 if (lastread == j - 1) `7B X`09`09`09(void) fprintf(newsrcfp, "%c%ld", X`09`09`09`09 (nocomma ? ' ' : ','), lastread); X`09`09`09nocomma = 0; X`09`09 `7D else `7B X`09`09`09if ((j - 1) > 0) `7B X`09`09`09 (void) fprintf(newsrcfp, "%c%ld-%ld", X`09`09`09`09`09 (nocomma ? ' ' : ','), lastread, X`09`09`09`09`09 j - 1); X`09`09`09 nocomma = 0; X`09`09`09`7D X`09`09 `7D X X`09`09 inrange = 0; X`09`09`7D else if (!inrange && IS_READ(newsgroup->articles`5BINDEX(j)`5D)) ` V7B X`09`09 inrange = 1; X`09`09 lastread = j; X`09`09`7D X`09 `7D X`09 `20 X`09 if (inrange) `7B X`09`09if (lastread == newsgroup->last) `7B X`09`09 (void) fprintf(newsrcfp, "%c%ld", X`09`09`09`09 (nocomma ? ' ' : ','), lastread); X`09`09`7D else `7B X`09`09 (void) fprintf(newsrcfp, "%c%ld-%ld", X`09`09`09`09 (nocomma ? ' ' : ','), lastread, X`09`09`09`09 newsgroup->last); X`09`09`7D X`09 `7D X`09`7D else `7B X`09 if (newsgroup->last > 1) `7B X`09`09(void) fprintf(newsrcfp, " 1-%ld", newsgroup->last); X`09 `7D X`09`7D X`09 `20 X`09(void) fprintf(newsrcfp, "\n"); X `7D X (void) fclose(newsrcfp); X X#ifndef VMS X#ifdef ISC_TCP X /* the following added to fix a bug in ISC TCP/IP rename() - jrh@dell.de Vll.com (James Howard) */ X if (unlink(NewsrcFile) != 0) `7B X`09mesgPane(XRN_SERIOUS, "Error unlinking %s: %s", NewsrcFile, X`09`09 errmsg(errno)); X`09return(FATAL); X `7D X#endif /* ISC_TCP */ X X if (rename(tempfile, NewsrcFile) != 0) `7B X`09mesgPane(XRN_SERIOUS, "Rename of %s to %s failed: %s", tempfile, X`09`09 NewsrcFile, errmsg(errno)); X`09return(FATAL); X `7D X#endif /* VMS */ X X (void) stat(NewsrcFile, &lastStat); X X return(OKAY); X`7D X $ CALL UNPACK NEWSRCFILE.C;1 57460705 $ create 'f' X#ifndef NEWSRCFILE_H X#define NEWSRCFILE_H X X/* X * $Header: /users/ricks/xrn/src/RCS/newsrcfile.h,v 1.7 90/09/29 01:11:01 ri Vcks Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X X#ifndef NEWS_H X#include "news.h" X#endif X X/* X * newsrcfile.h: handle the newsrc file (reading and updating) X */ X X/* return 1 for okay, 0 for fatal error */ Xextern int readnewsrc(/* char *newsrcfile */); Xextern int updatenewsrc(); Xextern int copyNewsrcFile(/* char *old, *save */); X Xextern char *NewsrcFile; Xextern FILE *Newsrcfp; Xextern char *optionsLine; X X/* values for 'type' */ X#define SINGLE 1 X#define RANGE 2 X Xstruct list `7B X int type; X union `7B X`09art_num single; X`09struct rn `7B X`09 art_num start; X`09 art_num end; X`09`7D range; X `7D contents; X struct list *next; X`7D; X X#endif /* NEWSRCFILE_H */ $ CALL UNPACK NEWSRCFILE.H;1 1950392347 $ create 'f' X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn-11/src/RCS/newsrc.y, Vv 1.6 90/04/15 12:23:00 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988,1989,1990,Ellen M. Sentovich and Rick L. Spickelmier. X * X * Permission to use,copy,modify,and distribute this software and its X * documentation for any purpose and without fee is hereby granted,provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation,and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific,written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE,INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS,IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL,INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE,DATA OR PROFITS,WHETHER IN AN ACTION OF X * CONTRACT,NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * newsrc.y - yacc parser for the newsrc file X */ X X#include "copyright.h" X#include X#include X#include X#include "config.h" X#include "utils.h" X#include "avl.h" X#include "mesg.h" X#include "news.h" X#include "newsrcfile.h" X Xtypedef union `7B X int integer; X char *string; X char character; X struct list *item; X`7D YYSTYPE; X#define NAME 257 X#define SEPARATOR 258 X#define NUMBER 259 X#define EOL 260 X#define DASH 261 X#define COMMA 262 X#define yyclearin yychar = -1 X#define yyerrok yyerrflag = 0 Xextern int yychar; Xextern short yyerrflag; X#ifndef YYMAXDEPTH X#define YYMAXDEPTH 150 X#endif XYYSTYPE yylval,yyval; X#define YYERRCODE 256 X#include "newsrc_parse.h" X Xshort yyexca`5B`5D =`7B-1,1,0,-1,-2,0,`7D; X#define YYNPROD 10 X#define YYLAST 23 Xshort yyact`5B`5D=`7B11,6,12,13,10,8,15,10,4,9,3,2,1,5,7,0,0,0,0,0,0,0,14 `7 VD; Xshort yypact`5B`5D=`7B-249,-1000,-249,-1000,-257,-1000,-255,-260,-1000,-1000 V, X-258,-1000,-252,-253,-1000,-1000`7D; Xshort yypgo`5B`5D=`7B0,14,9,12,11,10`7D; Xshort yyr1`5B`5D=`7B0,3,4,4,5,5,1,1,2,2`7D; Xshort yyr2`5B`5D=`7B0,1,1,2,4,3,1,3,1,3`7D; Xshort yychk`5B`5D=`7B-1000,-3,-4,-5,257,-5,258,-1,260,-2,259,260,262,261,-2, V259`7D; Xshort yydef`5B`5D=`7B0,-2,1,2,0,3,0,0,5,6,8,4,0,0,7,9 `7D; X#define YYFLAG -1000 X#define YYERROR goto yyerrlab X#define YYACCEPT return(0) X#define YYABORT return(1) X X/*`09parser for yacc output`09*/ X XYYSTYPE yyv`5BYYMAXDEPTH`5D; /* where the values are stored */ Xint yychar = -1; /* current input token number */ Xint yynerrs = 0; /* number of errors */ Xshort yyerrflag = 0; /* error recovery flag */ X Xyyparse() `7B X`09short yys`5BYYMAXDEPTH`5D; X`09short yyj,yym; X`09register YYSTYPE *yypvt; X`09register short yystate,*yyps,yyn; X`09register YYSTYPE *yypv; X`09register short *yyxi; X X`09yystate = 0; X`09yychar = -1; X`09yynerrs = 0; X`09yyerrflag = 0; X`09yyps= &yys`5B-1`5D; X`09yypv= &yyv`5B-1`5D; X X yystack: /* put a state and value onto the stack */ X X`09`09if( ++yyps> &yys`5BYYMAXDEPTH`5D ) `7B yyerror( "yacc stack overflow" V ); return(1); `7D X`09`09*yyps = yystate; X`09`09++yypv; X`09`09*yypv = yyval; X X yynewstate: X X`09yyn = yypact`5Byystate`5D; X X`09if( yyn<= YYFLAG ) goto yydefault; /* simple state */ X X`09if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; X`09if( (yyn += yychar)<0 `7C`7C yyn >= YYLAST ) goto yydefault; X X`09if( yychk`5B yyn=yyact`5B yyn `5D `5D == yychar )`7B /* valid shift */ X`09`09yychar = -1; X`09`09yyval = yylval; X`09`09yystate = yyn; X`09`09if( yyerrflag > 0 ) --yyerrflag; X`09`09goto yystack; X`09`09`7D X X yydefault: X`09/* default state action */ X X`09if( (yyn=yydef`5Byystate`5D) == -2 ) `7B X`09`09if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; X`09`09/* look through exception table */ X X`09`09for( yyxi=yyexca; (*yyxi!= (-1)) `7C`7C (yyxi`5B1`5D!=yystate) ; yyxi V += 2 ) ; /* VOID */ X X`09`09while( *(yyxi+=2) >= 0 )`7B X`09`09`09if( *yyxi == yychar ) break; X`09`09`09`7D X`09`09if( (yyn = yyxi`5B1`5D) < 0 ) return(0); /* accept */ X`09`09`7D X X`09if( yyn == 0 )`7B /* error */ X`09`09/* error ... attempt to resume parsing */ X X`09`09switch( yyerrflag )`7B X X`09`09case 0: /* brand new error */ X X`09`09`09yyerror( "syntax error" ); X`09`09yyerrlab: X`09`09`09++yynerrs; X X`09`09case 1: X`09`09case 2: /* incompletely recovered error ... try again */ X X`09`09`09yyerrflag = 3; X X`09`09`09/* find a state where "error" is a legal shift action */ X X`09`09`09while ( yyps >= yys ) `7B X`09`09`09 yyn = yypact`5B*yyps`5D + YYERRCODE; X`09`09`09 if( yyn>= 0 && yyn < YYLAST && yychk`5Byyact`5Byyn`5D`5D == YYER VRCODE )`7B X`09`09`09 yystate = yyact`5Byyn`5D; /* simulate a shift of "error" */ X`09`09`09 goto yystack; X`09`09`09 `7D X`09`09`09 yyn = yypact`5B*yyps`5D; X X`09`09`09 /* the current yyps has no shift onn "error",pop stack */ X`09`09`09 --yyps; X`09`09`09 --yypv; X`09`09`09 `7D X X`09`09`09/* there is no state on the stack with an error shift ... abort */ X X`09yyabort: X`09`09`09return(1); X X X`09`09case 3: /* no shift yet; clobber input char */ X X`09`09`09if( yychar == 0 ) goto yyabort; /* don't discard EOF,quit */ X`09`09`09yychar = -1; X`09`09`09goto yynewstate; /* try again in the same state */ X X`09`09`09`7D X X`09`09`7D X X`09/* reduction by production yyn */ X X`09`09yyps -= yyr2`5Byyn`5D; X`09`09yypvt = yypv; X`09`09yypv -= yyr2`5Byyn`5D; X`09`09yyval = yypv`5B1`5D; X`09`09yym=yyn; X`09`09`09/* consult goto table to find next state */ X`09`09yyn = yyr1`5Byyn`5D; X`09`09yyj = yypgo`5Byyn`5D + *yyps + 1; X`09`09if( yyj>=YYLAST `7C`7C yychk`5B yystate = yyact`5Byyj`5D `5D != -yyn ) V yystate = yyact`5Byypgo`5Byyn`5D`5D; X`09`09switch(yym)`7B X`09`09`09 Xcase 4: X`7B X`09`09 struct newsgroup *newsgroup; X`09`09 char *dummy; X X`09`09 if (!avl_lookup(NewsGroupTable,yypvt`5B-3`5D.string,&dummy)) `7B X`09`09`09mesgPane(XRN_SERIOUS,"Bogus newsgroup `60%s',removing from the news Vrc file",yypvt`5B-3`5D.string); X`09`09 `7D else `7B X`09`09`09newsgroup = (struct newsgroup *) dummy; X`09`09`09if (IS_NOENTRY(newsgroup)) `7B X`09`09`09 CLEAR_NOENTRY(newsgroup); X`09`09`09 newsgroup->status `7C= (yypvt`5B-2`5D.character == ':' ? NG_SUB V : NG_UNSUB); X`09`09`09 newsgroup->nglist = yypvt`5B-1`5D.item; X`09`09`09 updateArticleArray(newsgroup); X`09`09`09 newsgroup->newsrc = MaxGroupNumber; X`09`09`09 Newsrc`5BMaxGroupNumber++`5D = newsgroup; X`09`09`09`7D else `7B X`09`09`09 mesgPane(XRN_SERIOUS,"Duplicate entry for `60%s',using first on Ve", X`09`09`09`09`09 yypvt`5B-3`5D.string); X`09`09`09`7D X`09`09 `7D X`09 `7D break; Xcase 5: X`7B X`09`09 struct newsgroup *newsgroup; X`09`09 char *dummy; X X`09`09 if (!avl_lookup(NewsGroupTable,yypvt`5B-2`5D.string,&dummy)) `7B X`09`09`09mesgPane(XRN_SERIOUS,"Bogus newsgroup `60%s',removing from the news Vrc file",yypvt`5B-2`5D.string); X`09`09 `7D else `7B X`09`09`09newsgroup = (struct newsgroup *) dummy; X`09`09`09if (IS_NOENTRY(newsgroup)) `7B X`09`09`09 CLEAR_NOENTRY(newsgroup); X`09`09`09 newsgroup->status `7C= (yypvt`5B-1`5D.character == ':' ? NG_SUB V : NG_UNSUB); X`09`09`09 newsgroup->nglist = NIL(struct list); X`09`09`09 updateArticleArray(newsgroup); X`09`09`09 newsgroup->newsrc = MaxGroupNumber; X`09`09`09 Newsrc`5BMaxGroupNumber++`5D = newsgroup; X`09`09`09`7D else `7B X`09`09`09 mesgPane(XRN_SERIOUS,"Duplicate entry for `60%s',using first on Ve", X`09`09`09`09`09 yypvt`5B-2`5D.string); X`09`09`09`7D X`09`09 `7D X`09 `7D break; Xcase 6: X`7B X`09`09 yyval.item = yypvt`5B-0`5D.item; X`09`09`7D break; Xcase 7: X`7B X`09`09 struct list *temp; X X`09`09 yyval.item = yypvt`5B-2`5D.item; X`09`09 for (temp = yyval.item; temp != NIL(struct list); temp = temp->nex Vt) `7B X`09`09`09if (temp->next == NIL(struct list)) `7B X`09`09`09 temp->next = yypvt`5B-0`5D.item; X`09`09`09 break; X`09`09`09`7D X`09`09 `7D X`09`09`7D break; Xcase 8: X`7B X`09`09 yyval.item = ALLOC(struct list); X`09`09 yyval.item->type = SINGLE; X`09`09 yyval.item->contents.single = (art_num) yypvt`5B-0`5D.integer; X`09`09 yyval.item->next = NIL(struct list); X`09`09`7D break; Xcase 9: X`7B X`09`09 yyval.item = ALLOC(struct list); X`09`09 yyval.item->type = RANGE; X`09`09 yyval.item->contents.range.start = (art_num) yypvt`5B-2`5D.integer V; X`09`09 yyval.item->contents.range.end = (art_num) yypvt`5B-0`5D.integer; X`09`09 yyval.item->next = NIL(struct list); X`09`09`7D break;`20 X`09`09`7D X`09`09goto yystack; /* stack new state and value */ X X`09`7D $ CALL UNPACK NEWSRC_PARSE.C;1 1393737391 $ create 'f' X#include X#define U(x) ((x)&0377) X#define NLSTATE yyprevious=YYNEWLINE X#define BEGIN yybgin = yysvec + 1 + X#define INITIAL 0 X#define YYLERR yysvec X#define YYSTATE (yyestate-yysvec-1) X#define YYLMAX 200 X#define output(c) putc(c,yyout) X#define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylin Veno++,yytchar):yytchar)==EOF?0:yytchar) X#define unput(c) `7Byytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytch Var;`7D X#define yymore() (yymorfg=1) X#define ECHO fprintf(yyout,"%s",yytext) X#define REJECT `7B nstr = yyreject(); goto yyfussy;`7D Xint yyleng; extern char yytext`5B`5D; Xint yymorfg; Xextern char *yysptr,yysbuf`5B`5D; Xint yytchar; XFILE *yyin,*yyout; Xextern int yylineno; Xstruct yysvf `7B`20 X`09struct yywork *yystoff; X`09struct yysvf *yyother; X`09int *yystops;`7D; Xstruct yysvf *yyestate; Xextern struct yysvf yysvec`5B`5D,*yybgin; X#define YYNEWLINE 10 Xyylex()`7B Xint nstr; extern int yyprevious; X yyin = Newsrcfp; Xwhile((nstr = yylook()) >= 0) Xyyfussy: switch(nstr)`7B Xcase 0: Xif(yywrap()) return(0); break; Xcase 1:;break; Xcase 2:return(EOL);break; Xcase 3:return(DASH);break; Xcase 4:return(COMMA);break; Xcase 5:`7Byylval.character = yytext`5B0`5D; return(SEPARATOR); `7Dbreak; Xcase 6:`7Byylval.integer = atoi(yytext); return(NUMBER); `7Dbreak; Xcase 7:`7Byylval.string = XtNewString(yytext); return(NAME); `7Dbreak; Xcase 8:`7Byylval.string = XtNewString(yytext); return(NAME); `7Dbreak; Xcase 9:;break; Xcase 10:`7B X optionsLine = XtNewString(yytext); X optionsLine`5ButStrlen(optionsLine) - 1`5D = '\0'; X`7Dbreak; Xcase -1:break; Xdefault:fprintf(yyout,"bad switch yylook %d",nstr);`7D return(0); `7D X/* end of yylex */ X/* X * $Header: /users/ricks/xrn-11/src/RCS/newsrc.l,v 1.6 90/06/22 10:29:00 ric Vks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988,1989,1990,Ellen M. Sentovich and Rick L. Spickelmier. X * X * Permission to use,copy,modify,and distribute this software and its X * documentation for any purpose and without fee is hereby granted,provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation,and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific,written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE,INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS,IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL,INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE,DATA OR PROFITS,WHETHER IN AN ACTION OF X * CONTRACT,NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X Xyywrap() X`7B X return(1); X`7D X X/*ARGSUSED*/ Xyyerror(s) Xchar *s; X`7B`7D X Xint yyvstop`5B`5D =`7B0,9,0,2,0,5,0,4,0,3,0,6,0,9,0,1,2,0,8,0,3,8,0,6,8,0, X8,0,8,0,7,0,1,0,7,8,0,7,8,0,7,8,0,7,8,0,7,8,0,7,8,0,7,8,0,10,0,0`7D; X#define YYTYPE unsigned char Xstruct yywork `7B YYTYPE verify,advance; `7D yycrank`5B`5D =`7B X0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,4,0,0,0,0,0,0,0,0, X0,0,10,18,10,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, X0,0,1,3,1,5,0,0,0,0,0,0,0,0,0,0,10,18,26,27,0,0,0,0,0,0,1,6,1,7,0,0, X0,0,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,5,0,0,0,0,0,0,0,0, X0,0,0,0,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9, X1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,0,0,0,0,0,0,0,0, X0,0,0,0,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9, X1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,2,10,2,11,8,8,8,8, X8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 V,14, X14,14,14,14,16,21,2,10,2,5,21,22,22,23,2,12,23,24,2,12,24,25,25,26, X0,0,0,0,2,12,2,6,2,13,2,12,0,0,2,14,2,14,2,14,2,14,2,14,2,14,2,14,2,14,2,14, X2,14,2,5,0,0,0,0,0,0,0,0,0,0,0,0,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15, X2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15, X2,15,2,15,2,15,2,15,2,15,2,15,0,0,0,0,0,0,0,0,2,12,0,0,2,15,2,15,2,15,2,15, X2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,15,2,16,2,15,2,15,2,15,2,15,2 V,15, X2,15,2,15,2,15,2,15,2,15,2,15,2,12,2,12,2,12,9,17,0,0,9,17,0,0,0,0,0,0,0,0, X9,17,0,0,9,17,9,17,0,0,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,0,0 V, X0,0,0,0,0,0,0,0,0,0,0,0,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17, X9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9 V,17, X0,0,0,0,0,0,0,0,9,17,0,0,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17, X9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9,17,9 V,17, X9,17,9,17,9,17,12,12,0,0,12,12,0,0,0,0,0,0,0,0,12,12,0,0,12,12,12,12,0,0,12, V12, X12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,0,0,0,0,0, X0,0,0,0,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, X12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, X12,12,12,12,12,12,12,12,12,12,12,12,0,0,0,0,0,0,0,0,12,12,0,0, X12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, X12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, X12,12,12,12,12,12,12,12,12,12,15,20,0,0,15,20,0,0,0,0,0,0,0,0, X15,20,0,0,15,20,15,20,0,0,15,20,15,20,15,20,15,20,15,20,15,20,15,20, X15,20,15,20,15,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,20,15,20, X15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20, X15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20, X0,0,0,0,0,0,0,0,15,20,0,0,15,20,15,20,15,20,15,20,15,20,15,20, X15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20, X15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,15,20,27,27, X0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,27,27,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0, X0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,27, X0,0,0,0,27,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,27,0,0, X0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,27,0,0`7D; Xstruct yysvf yysvec`5B`5D =`7B0,0,0,yycrank+1,0,0,yycrank+115,0,0, Xyycrank+0,0,yyvstop+1,yycrank+0,0,yyvstop+3,yycrank+0,0,yyvstop+5, Xyycrank+0,0,yyvstop+7,yycrank+0,0,yyvstop+9,yycrank+78,0,yyvstop+11, Xyycrank+205,0,0,yycrank+8,0,yyvstop+13,yycrank+0,0,yyvstop+15, Xyycrank+295,0,yyvstop+18,yycrank+0,yysvec+12,yyvstop+20, Xyycrank+88,yysvec+12,yyvstop+23,yycrank+385,0,yyvstop+26, Xyycrank+34,yysvec+15,yyvstop+28,yycrank+0,yysvec+9,yyvstop+30, Xyycrank+0,yysvec+10,0,yycrank+0,0,yyvstop+32,yycrank+0,yysvec+15,yyvstop+34, Xyycrank+33,yysvec+15,yyvstop+37,yycrank+45,yysvec+15,yyvstop+40, Xyycrank+41,yysvec+15,yyvstop+43,yycrank+44,yysvec+15,yyvstop+46, Xyycrank+40,yysvec+15,yyvstop+49,yycrank+9,yysvec+15,yyvstop+52, Xyycrank+-510,0,0,yycrank+0,0,yyvstop+55,0,0,0`7D; Xstruct yywork *yytop = yycrank+575; Xstruct yysvf *yybgin = yysvec+1; Xchar yymatch`5B`5D =`7B00,01,01,01,01,01,01,01,01,011,012,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X011,'!',01,01,'$',01,'$',01,01,01,01,'$',01,'$','$',01, X'0','0','0','0','0','0','0','0','0','0','!',01,01,01,01,01, X01,'A','A','A','A','A','A','A','A','A','A','A','A','A','A','A', X'A','A','A','A','A','A','A','A','A','A','A',01,01,01,01,'$', X01,'A','A','A','A','A','A','A','A','A','A','A','A','A','A','A', X'A','A','A','A','A','A','A','A','A','A','A','$','$','$',01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01, X01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,01,0`7D; Xchar yyextra`5B`5D =`7B0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0`7D; X Xint yylineno =1; X#define YYU(x) x X#define NLSTATE yyprevious=YYNEWLINE Xchar yytext`5BYYLMAX`5D; Xstruct yysvf *yylstate `5BYYLMAX`5D,**yylsp,**yyolsp; Xchar yysbuf`5BYYLMAX`5D; Xchar *yysptr = yysbuf; Xint *yyfnd; Xextern struct yysvf *yyestate; Xint yyprevious = YYNEWLINE; Xyylook()`7B X`09register struct yysvf *yystate,**lsp; X`09register struct yywork *yyt; X`09struct yysvf *yyz; X`09int yych; X`09struct yywork *yyr; X`09char *yylastch; X`09/* start off machines */ X`09if (!yymorfg) X`09`09yylastch = yytext; X`09else `7B X`09`09yymorfg=0; X`09`09yylastch = yytext+yyleng; X`09`09`7D X`09for(;;)`7B X`09`09lsp = yylstate; X`09`09yyestate = yystate = yybgin; X`09`09if (yyprevious==YYNEWLINE) yystate++; X`09`09for (;;)`7B X`09`09`09yyt = yystate->yystoff; X`09`09`09if(yyt == yycrank)`7B`09`09/* may not be any transitions */ X`09`09`09`09yyz = yystate->yyother; X`09`09`09`09if(yyz == 0)break; X`09`09`09`09if(yyz->yystoff == yycrank)break; X`09`09`09`09`7D X`09`09`09*yylastch++ = yych = input(); X`09`09tryagain: X`09`09`09yyr = yyt; X`09`09`09if ( (int)yyt > (int)yycrank)`7B X`09`09`09`09yyt = yyr + yych; X`09`09`09`09if (yyt <= yytop && yyt->verify+yysvec == yystate)`7B X`09`09`09`09`09if(yyt->advance+yysvec == YYLERR)`09/* error transitions */ X`09`09`09`09`09`09`7Bunput(*--yylastch);break;`7D X`09`09`09`09`09*lsp++ = yystate = yyt->advance+yysvec; X`09`09`09`09`09goto contin; X`09`09`09`09`09`7D X`09`09`09`09`7D X`09`09`09else if((int)yyt < (int)yycrank) `7B`09`09/* r < yycrank */ X`09`09`09`09yyt = yyr = yycrank+(yycrank-yyt); X`09`09`09`09yyt = yyt + yych; X`09`09`09`09if(yyt <= yytop && yyt->verify+yysvec == yystate)`7B X`09`09`09`09`09if(yyt->advance+yysvec == YYLERR)`09/* error transitions */ X`09`09`09`09`09`09`7Bunput(*--yylastch);break;`7D X`09`09`09`09`09*lsp++ = yystate = yyt->advance+yysvec; X`09`09`09`09`09goto contin; X`09`09`09`09`09`7D X`09`09`09`09yyt = yyr + YYU(yymatch`5Byych`5D); X`09`09`09`09if(yyt <= yytop && yyt->verify+yysvec == yystate)`7B X`09`09`09`09`09if(yyt->advance+yysvec == YYLERR)`09/* error transition */ X`09`09`09`09`09`09`7Bunput(*--yylastch);break;`7D X`09`09`09`09`09*lsp++ = yystate = yyt->advance+yysvec; X`09`09`09`09`09goto contin; X`09`09`09`09`09`7D X`09`09`09`09`7D X`09`09`09if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycr Vank)`7B X`09`09`09`09goto tryagain; X`09`09`09`09`7D X`09`09`09else X`09`09`09`09`7Bunput(*--yylastch);break;`7D X`09`09contin: X`09`09`09; X`09`09`09`7D X`09`09while (lsp-- > yylstate)`7B X`09`09`09*yylastch-- = 0; X`09`09`09if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0)`7B X`09`09`09`09yyolsp = lsp; X`09`09`09`09if(yyextra`5B*yyfnd`5D)`7B`09`09/* must backup */ X`09`09`09`09`09while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate) V`7B X`09`09`09`09`09`09lsp--; X`09`09`09`09`09`09unput(*yylastch--); X`09`09`09`09`09`09`7D X`09`09`09`09`09`7D X`09`09`09`09yyprevious = YYU(*yylastch); X`09`09`09`09yylsp = lsp; X`09`09`09`09yyleng = yylastch-yytext+1; X`09`09`09`09yytext`5Byyleng`5D = 0; X`09`09`09`09return(*yyfnd++); X`09`09`09`09`7D X`09`09`09unput(*yylastch); X`09`09`09`7D X`09`09if (yytext`5B0`5D == 0 /* && feof(yyin) */) X`09`09`09`7B X`09`09`09yysptr=yysbuf; X`09`09`09return(0); X`09`09`09`7D X`09`09yyprevious = yytext`5B0`5D = input(); X`09`09if (yyprevious>0) X`09`09`09output(yyprevious); X`09`09yylastch=yytext; X`09`09`7D X`09`7D Xyyback(p,m) X`09int *p; X`7B Xif (p==0) return(0); Xwhile (*p) X`09`7B X`09if (*p++ == m) X`09`09return(1); X`09`7D Xreturn(0); X`7D X`09/* the following are only used in the lex library */ Xyyinput()`7B X`09return(input()); X`09`7D Xyyoutput(c) X int c; `7B X`09output(c); X`09`7D Xyyunput(c) X int c; `7B X`09unput(c); X`09`7D $ CALL UNPACK NEWSRC_PARSE.H;1 540091606 $ create 'f' X# X# xrn - an X-based interface to the USENET news system X# X# Copyright (c) 1988, Ellen M. Sentovich and Rick L. Spickelmier. All right Vs reserved. X# X# Use and copying of this software and preparation of derivative works X# based upon this software are permitted. However, any distribution of X# this software or derivative works must include the above copyright X# notice. X# X# This software is made available AS IS, and neither the Electronics X# Research Laboratory or the University of California make any X# warranty about the software, its performance or its conformity to X# any specification. X# X# Suggestions, comments, or improvements are welcome and should be X# addressed to: X# X# xrn@eros.berkeley.edu X# ..!ucbvax!eros!xrn X# X XSHELL = /bin/sh X XTARGET = xrn X XOBJECTS = buttons.o \ X compose.o \ X`09 cursor.o \ X dialogs.o \ X error.o \ X error_hnds.o \ X newsrcfile.o \ X resources.o \ X rn.o \ X saveArticle.o \ X complete.o \ X server.o \ X utils.o \ X xmisc.o \ X xrn.o \ X xthelper.o \ X y.tab.o X XSOURCES = buttons.c \ X compose.c \ X cursor.c \ X dialogs.c \ X error.c \ X error_hnds.c \ X newsrcfile.c \ X resources.c \ X rn.c \ X saveArticle.c \ X complete.c \ X server.c \ X utils.c \ X xmisc.c \ X xrn.c \ X xthelper.c`20 X XOTHERS = newsrc.l \ X newsrc.y X XHEADERS = buttons.h \ X compose.h \ X config.h \ X`09 cursor.h \ X dialogs.h \ X error_hndrs.h \ X library.h \ X`09 modes.h \ X news.h \ X newsrcfile.h \ X resources.h \ X rn.h \ X saveArticle.h \ X complete.h \ X server.h \ X utils.h \ X xmisc.h \ X xthelper.h \ X xrn.h X XLIBS = ./nntp/libnntp.a \ X ./avl/libavl.a \ X ./list/liblist.a \ X -lXaw -lXmu -lXt -lX11 X XLINTLIBS = ./nntp/llib-lnntp.ln \ X`09 ./avl/llib-lavl.ln \ X ./list/llib-llist.ln X X# for AIX (IBM RT/PC), add '-I/usr/include/bsd' to INCLUDES XINCLUDES = -I. -Inntp -Iavl -Ilist X# for AIX (IBM RT/PC), add '-a' to LDFLAGS XLDFLAGS = -g X X# PREFETCH: do some simple minded prefetching of articles and groups X#DEFINES = -DPREFETCH XCFLAGS = $(LDFLAGS) $(INCLUDES) $(DEFINES) XLINTFLAGS = X X$(TARGET): $(OBJECTS) _makeablelibs X`09rm -f $(TARGET) X`09$(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) X Xxrn.o: xrn.c X`09$(CC) $(CFLAGS) "-DCUR_DATE=\"`60date `7C awk '`7Bprint $$2, $$3, $$6`7D' V`60\"" -c xrn.c X Xlex.yy.c: newsrc.l X`09lex newsrc.l X Xy.tab.c: newsrc.y X`09yacc newsrc.y X X.saberinit: X`09echo "load(\"" $(CFLAGS) $(SOURCES) y.tab.c "\");" > .saberinit X`09echo "load(\"" $(CFLAGS) $(LIBS) "\");" >> .saberinit X X_makeablelibs: X`09cd nntp; make "CC=$(CC)" "LDFLAGS=$(LDFLAGS)" libnntp.a X`09cd avl; make "CC=$(CC)" "LDFLAGS=$(LDFLAGS)" libavl.a X`09cd list; make "CC=$(CC)" "LDFLAGS=$(LDFLAGS)" liblist.a X X./nntp/llib-lnntp.ln: X`09(cd nntp; make llib-lnntp.ln) X X./avl/llib-lavl.ln: X`09(cd avl; make llib-lavl.ln) X X./list/llib-llist.ln: X`09(cd list; make llib-llist.ln) X X# X# The greps are to get rid of lint errors in the X and Xt libraries X# that we decided not to fix... X# X Xlint: $(LINTLIBS) X`09lint $(LINTFLAGS) $(INCLUDES) $(DEFINES) $(SOURCES) $(LINTLIBS) -lXaw -lX Vmu -lXt -lX11 X XTAGS: $(HEADERS) $(SOURCES) X`09etags $(HEADERS) $(SOURCES) X Xclean:`20 X`09-rm -f $(OBJECTS) $(TARGET) lex.yy.c y.tab.c make.out lint.out X`09(cd nntp; make clean) X`09(cd avl; make clean) X`09(cd list; make clean) X Xdepend: lex.yy.c y.tab.c X`09@sed '/`5E#--DO NOT CHANGE ANYTHING AFTER THIS LINE/,$$d' Makefile >mktem Vp X`09@echo '#--DO NOT CHANGE ANYTHING AFTER THIS LINE' >>mktemp X`09@./utils/cc-M $(CFLAGS) $(SOURCES) y.tab.c lex.yy.c >>mktemp X`09@mv mktemp Makefile X X X#--DO NOT CHANGE ANYTHING AFTER THIS LINE Xbuttons.o: buttons.c avl/avl.h buttons.h compose.h copyright.h cursor.h Xbuttons.o: dialogs.h error.h error_hnds.h modes.h port.h resources.h rn.h Xbuttons.o: saveArticle.h utils.h xmisc.h xrn.h xthelper.h Xcompose.o: compose.c avl/avl.h config.h copyright.h dialogs.h error.h Xcompose.o: news.h nntp/codes.h port.h resources.h rn.h server.h utils.h Xcompose.o: xrn.h xthelper.h Xcursor.o: cursor.c copyright.h cursor.h error.h modes.h port.h rn.h utils.h Xcursor.o: xrn.h Xdialogs.o: dialogs.c complete.h copyright.h dialogs.h port.h utils.h Xdialogs.o: xmisc.h xthelper.h Xerror.o: error.c copyright.h error.h port.h utils.h xmisc.h xrn.h Xerror.o: xthelper.h Xerror_hnds.o: error_hnds.c avl/avl.h copyright.h dialogs.h error.h Xerror_hnds.o: error_hnds.h port.h utils.h xmisc.h xrn.h xthelper.h Xnewsrcfile.o: newsrcfile.c avl/avl.h copyright.h dialogs.h error_hnds.h Xnewsrcfile.o: list/list.h news.h newsrcfile.h port.h utils.h xrn.h Xresources.o: resources.c avl/avl.h config.h copyright.h port.h resources.h Xresources.o: utils.h xthelper.h Xrn.o: rn.c avl/avl.h config.h copyright.h error.h error_hnds.h list/list.h Xrn.o: news.h newsrcfile.h nntp/codes.h port.h resources.h rn.h Xrn.o: saveArticle.h server.h utils.h XsaveArticle.o: saveArticle.c avl/avl.h config.h copyright.h error.h news.h XsaveArticle.o: nntp/codes.h port.h resources.h saveArticle.h server.h XsaveArticle.o: utils.h Xcomplete.o: complete.c avl/avl.h complete.h copyright.h error.h news.h Xcomplete.o: port.h utils.h Xserver.o: server.c avl/avl.h config.h copyright.h error.h error_hnds.h Xserver.o: news.h nntp/codes.h port.h resources.h server.h utils.h Xutils.o: utils.c copyright.h error.h port.h utils.h Xxmisc.o: xmisc.c avl/avl.h calvin.icon copyright.h port.h resources.h rn.h Xxmisc.o: utils.h xmisc.h xrn.h xrn.icon xthelper.h Xxrn.o: xrn.c avl/avl.h buttons.h config.h copyright.h error.h error_hnds.h Xxrn.o: port.h resources.h rn.h utils.h xmisc.h xrn.h xthelper.h Xxthelper.o: xthelper.c copyright.h port.h utils.h xmisc.h xrn.h xthelper.h Xy.tab.o: y.tab.c avl/avl.h copyright.h lex.yy.c list/list.h news.h Xy.tab.o: newsrcfile.h port.h utils.h Xlex.yy.o: lex.yy.c $ CALL UNPACK ORIGMAKEFILE.;1 422602080 $ create 'f' X#ifdef VMS X/* X * Note: Using #module in Unix will get interpreted by the preprocessor as a V`20 X *`09 control line and blow up. Do not uncomment the following line. X * X * module PANE "3.2" X */ X#else X#ifndef lint Xstatic char rcsid`5B`5D = "$Header: Pane.c,v 1.1 89/01/03 16:59:31 gringort V Exp $"; X#endif lint X#endif VMS X/* X * Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachus Vetts. X *`20 X * All Rights Reserved X *`20 X * Permission to use, copy, modify, and distribute this software and its`20 X * documentation for any purpose and without fee is hereby granted,`20 X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in`20 X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. V `20 X *`20 X *`20 X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X/* X * V1.0a 12-Jan-1988`09MRR X *`09 Add our logicals to #includes. X * V1.0b 26-Feb-1988`09RDB X *`09 Fix bugs with allowresizing & geometry manager X * V1.0c 01-Mar-1988`09PMB X *`09 Merge with latest copy of pane widget. X * V1.0d 17-Mar-1988`09RDB X *`09 fix major bugs and enhancements X * V1.1`09 1-Apr-1988`09MR X *`09 Make work with BL7.2 - add class_part_initialize, X *`09 add time argument to AcceptFocus. X * V1.2`09 13-Apr-1988`09JV X *`09 Make work with BL7.6 - changed DwtNcallback to DwtNmapCallback X * V1.3`09 20-Apr-1988`09MRR X *`09 Upward compatibility support. X * V1.4`09 13-Jun-1988`09MRR X *`09 Add help support. X * V1.5`09 30-Jun-1988`09MRR X *`09 Support for Help-MBx. X * V1.6`09 19-Jul-1988`09MRR X *`09 Help modifier changed to @Help. X * V1.7`09 20-Jul-1988`09RDB X *`09 Initialization Bug X * V1.8`09 01-Sep-1988`09RDB X *`09 Resize on DwtPaneSetMax error X *`09 Knob draging problem X * V1.9`09 07-Sep-1988`09RDB X *`09 Color changes on 8 plane GPX on Knob drag X * V1.10 08-Sep-1988`09RDB X *`09 Extra knob appearing when managing and unmanaging widgets X * V1.11 06-Oct-1988 RDB X *`09 During Resize check if widget height also changed. X * V1.12 19-Oct-1988`09RDB X *`09 change cursor to vertical or horizontial cursor and`20 X *`09 MB2 & MB3 pushes fixed X * V1.13 31-Oct-1988 RDB X *`09 Add DwtPaneAddChild calls X * V1.14 01-Nov-1988`09RDB X *`09 Change resize to resizable and allowresizing to resize X * V1.15 07-Nov-1988`09RDB X *`09 Allow shared panes X * V1.16 29-Nov-1988 RDB X *`09 Add Destory routine X *`09 Add SetValues routine X *`09 Fix SetConstraintValues routine X *`09 Add DeleteChild routine X *`09 Add FocusCallbacks X *`09 Add MapCallbacks X *`09 Fix FocusNext, FocusPrev routines X *`09 Fix compiledtextbindings X *`09 Add VMS routines for all the public routines. X * V1.17 06-Jan-1989`09JG X *`09 Make work on PMAX X * V2.0 15-Feb-1989 MRR X *`09 AcceptFocus should return what child's accept_focus returns. X * V2.1 22-Feb-1989 RDB X *`09 Fix set min and max resize but when pane is shared X * V2.2`09 1-Mar-1989`09MRR X *`09 GC's gotten with XtGetGC should be removed with XtDestroyGC, X *`09 not XFreeGC. X * V2.3`09 7-Mar-1989`09RDB X *`09 Orientation (w) defined incorrectly X * V2.4`09 9-Mar-1989`09MRR X *`09 CvtStringToOrientation and DwtPrivate no longer needed. X * V2.5`09 9-Mar-1989`09MRR X *`09 Copy DwtUpdateCallback here and rename as LclUpdateCallback. X * V2.6`09 14-Mar-1989`09RDB X *`09 Change the default width and height to be 200 instead of 100 X * V2.7`09 23-Mar-1989`09RDB X *`09 change resource default for Foreground X * V2.8`09 24-mar-1989`09RDB X *`09 Make knobs mullions X * V2.9`09 30-Mar-1989`09RDB X *`09 Redo definitions for panewidgetclass, panewidgetclassrec, mullions X *`09 Style guide compliancy on vertical & horizontal cursor X * V2.10 04-Apr-1989`09RDB X *`09 Change MullionSize to be something like borderwidth & X *`09 add MullionLength to be the total height of a mullion X * V2.11 05-Apr-1989`09RDb X *`09 Make LclUpdateCallback static X * V2.12 03-May-1989`09RDB X *`09 MB2 & MB3 cursor changes X * V2.13 12-May-1989`09RDB X *`09 make widget_size the PanePart not PaneRec X * V2.14 15-May-1989`09RDB X *`09 Geometry Manager doesn't allow widgets to resize X *`09 DwtPaneMakeViewable error in selecting right subwidget X * V3.0`09 22-Aug-1989 MRR X *`09 Copied to V3 library. X * V3.1`09 29-Aug-1989`09RDB X *`09 Fix DwtPaneMakeViewable error in setting the widget position X * V3.2`09 30-AUG-1989 RDB X *`09 Remove Const from Joel X * V3.3`09 23-Oct-1989`09RDB X *`09 New version of pane widget X */ X#define PANE X X#ifdef VMS X#include X#include X#include "PaneP.h" X#include "Pane.h" X#else X#define NOT_VMS_V1 /* required for part offsets to work before Ultrix 2.2 */ V`20 X#include X#include X#include X#include "PaneP.h" X#include "Pane.h" X#endif X X#ifdef __STDC__ X#undef DwtField X#undef DwtPartOffset X#define DwtField(widget, offsetrecord, part, variable, type) \ X`09(*(type *)(((char *) (widget)) + offsetrecord`5BDwt##part##Index`5D + \ X`09`09XtOffset(part##Part *, variable))) X#define DwtPartOffset(part, variable) \ X ((Dwt##part##Index) << HALFLONGBITS) + XtOffset(part##Part *, variab Vle) X#endif X X#define NoMask 0L X`20 X#ifndef VMS Xextern char *DwtDescToNull(); /* jmg */ X#endif VMS X`20 X/* X * 'Length' is defined as height for vpanes, and width for hpanes. 'Breadth V' X * is the other dimension. X */ X`20 X#define DwtPaneIndex (DwtConstraintIndex + 1) X`20 X/* Macros to access pane fields */ X#define PaneField(w,class,field,type)`09`09`09`09\ X`09DwtField((w),`09`09`09`09`09`09\ X`09`09 ((PaneClass)(w)->core.widget_class)->`09`09\ X`09`09 `09pane_class.paneoffsets,class,`09`09\ X`09`09 field,`09`09`09`09`09`09\ X`09`09 type) X`20 X#define X(w)`09`09PaneField(w,Core,x,Position) X#define Y(w)`09`09PaneField(w,Core,y,Position) X`20 X#define Width(w)`09`09PaneField(w,Core,width,Dimension) X#define Height(w)`09`09PaneField(w,Core,height,Dimension) X#define BackgroundPixel(w)`09PaneField(w,Core,background_pixel,Pixel) X`20 X#define Children(w)`09`09PaneField(w,Composite,children,WidgetList) X#define NumChildren(w)`09`09PaneField(w,Composite,num_children,Cardinal) X`20 X#define MullionSize(w)`09`09PaneField(w,Pane,mullionsize,Dimension) X#define MullionLength(w)`09PaneField(w,Pane,mullionlength,Dimension) X#define LeftMullion(w)`09`09PaneField(w,Pane,leftmullion,Boolean) X#define Orientation(w)`09`09PaneField(w,Pane,orientation,unsigned char) X#define PaneNumChildren(w)`09PaneField(w,Pane,num_children,Cardinal) X#define PaneChildren(w)`09`09PaneField(w,Pane,children,WidgetList) X#define InterSub(w)`09`09PaneField(w,Pane,intersub,Dimension) X#define ResizeMode(w)`09`09PaneField(w,Pane,resize_mode,unsigned char) X#define Foreground(w)`09`09PaneField(w,Pane,foreground,Pixel) X#define InvGC(w)`09`09PaneField(w,Pane,invgc,GC) X#define WhichAdjust(w)`09`09PaneField(w,Pane,whichadjust,Widget) X#define OrigLoc(w)`09`09PaneField(w,Pane,origloc,Position) X#define OverrideText(w)`09`09PaneField(w,Pane,overridetext,Boolean) X#define LastHadFocus(w)`09`09PaneField(w,Pane,lasthadfocus,Widget) X#define HelpCallback(w)`09`09PaneField(w,Pane,helpcallback,DwtCallbackStruct V) X`20 X#define FindLength(width, height) \ X ((Orientation(pane) == DwtOrientationVertical) ? (height) : (width)) X#define FindBreadth(width, height) \ X ((Orientation(pane) == DwtOrientationVertical) ? (width) : (height)) X`20 X#define FindWidth(length, breadth) \ X ((Orientation(pane) == DwtOrientationVertical) ? (breadth) : (length)) X#define FindHeight(length, breadth) \ X ((Orientation(pane) == DwtOrientationVertical) ? (length) : (breadth)) X`20 X#define FindStartLoc(x, y) \ X ((Orientation(pane) == DwtOrientationVertical) ? (y) : (x)) X`20 X/* Use direct method for Length, safe because core fields guaranteed X * to be a same offset */ X#define Length(widget)`09FindLength(widget->core.width, widget->core.height) X#define Breadth(widget)`09FindBreadth(widget->core.width, widget->core.heigh Vt) X#define StartLoc(widget)FindStartLoc(widget->core.x, widget->core.y) X#define LengthMullion(subdata) (subdata->resizable ? MullionLength(pane) : I VnterSub(pane)) X X#define EventToTime(evtTime, event)`09`09`09`09`09 \ X switch ((event)->type) `7B`09`09`09`09`09`09 \ X case KeyPress: `09`09`09`09`09`09`09 \ X case KeyRelease: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xkey.time; break;`09`09`09 \ X case ButtonPress: `09`09`09`09`09`09 \ X case ButtonRelease: `09`09`09`09`09`09 \ X `09`09(evtTime) = (event)->xbutton.time; break;`09`09 \ X`09case MotionNotify: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xmotion.time; break;`09`09 \ X`09case EnterNotify: `09`09`09`09`09`09 \ X`09case LeaveNotify: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xcrossing.time; break;`09`09 \ X`09case PropertyNotify:`09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xproperty.time; break;`09`09 \ X`09case SelectionClear: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xselectionclear.time; break; `09 \ X`09case SelectionRequest: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xselectionrequest.time; break;`09 \ X`09case SelectionNotify: `09`09`09`09`09`09 \ X`09`09(evtTime) = (event)->xselection.time; break;`09`09 \ X`09default: `09`09`09`09`09`09`09 \ X`09`09(evtTime) = CurrentTime; break;`09`09`09`09 \ X `7D X`20 Xstatic Dimension`09resource_min`09 = 1; Xstatic Dimension`09resource_max`09 = 10000; Xstatic Dimension`09resource_mullion = 2; Xstatic short`09`09resource_spacing = 1; Xstatic unsigned char`09resource_vert = DwtOrientationVertical; Xstatic Position `09resource_0_position `09= 0; X`20 Xstatic DwtPartResource resources`5B`5D = `7B X`20 X `7B`09DwtNorientation, `09`09`09/* fixed -- jg */ X`09DwtCOrientation, X`09XtROrientation,`20 X`09sizeof(unsigned char), X`09DwtPartOffset(Pane,orientation),`20 X`09DwtROrientation,`20 X`09(caddr_t) &resource_vert`7D, X`20 X `7B`09DwtNmullionSize, `09`09`09/* fixed -- jg */ X`09DwtCMullionSize,`20 X`09XtRDimension,`20 X`09sizeof(Dimension), X`09DwtPartOffset(Pane,mullionsize),`20 X`09XtRDimension,`20 X`09(caddr_t) &resource_mullion`7D, X`20 X `7B`09DwtNforeground, `09`09`09/* fixed -- jg */ X`09DwtCForeground,`20 X`09XtRPixel,`20 X`09sizeof(Pixel), X`09DwtPartOffset(Pane,foreground),`20 X`09XtRString,`20 X`09DwtSForegroundDefault`7D, X`20 X `7B`09DwtNspacing, `09`09`09/* fixed -- jg */ X`09DwtCSpacing,`20 X`09XtRShort,`20 X`09sizeof(short), X`09DwtPartOffset(Pane,intersub),`20 X`09XtRShort,`20 X`09(caddr_t) &resource_spacing`7D, X`20 X `7B`09DwtNresize, `09`09`09/* fixed -- jg */ X`09DwtCResize,`20 X`09DwtRResize,`20 X`09sizeof(int), X`09DwtPartOffset(Pane,resize_mode), X`09XtRImmediate,`20 X`09(caddr_t) DwtResizeGrowOnly`7D, X`20 X `7B`09DwtNoverrideText,`09`09/* fixed -- jg */ X`09DwtCOverrideText,`20 X`09XtRBoolean,`20 X`09sizeof(Boolean), X`09DwtPartOffset(Pane,overridetext),`20 X`09XtRImmediate,`20 X`09(caddr_t) FALSE`7D, X`20 X `7B DwtNmapCallback, X`09XtCCallback,`20 X`09XtRCallback,`20 X`09sizeof(DwtCallbackPtr), X`09DwtPartOffset(Pane,map_callback),`20 X`09XtRCallback,`20 X`09(caddr_t) NULL`7D,`09/* fixed -- jg */ X`20 X `7B DwtNunmapCallback, X`09XtCCallback,`20 X`09XtRCallback,`20 X`09sizeof(DwtCallbackPtr), X`09DwtPartOffset(Pane,unmap_callback),`20 X`09XtRCallback,`20 X`09(caddr_t) NULL`7D, X`20 X `7B`09DwtNfocusCallback,`09/* fixed -- jg */ X`09XtCCallback,`20 X`09XtRCallback,`20 X`09sizeof(DwtCallbackPtr), X`09DwtPartOffset(Pane,focus_callback),`20 X`09XtRCallback,`20 X`09(caddr_t) NULL`7D, X`20 X `7B`09DwtNhelpCallback,`09/* fixed -- jg */ X`09XtCCallback,`20 X`09XtRCallback,`20 X`09sizeof(DwtCallbackPtr), X`09DwtPartOffset(Pane,helpcallback),`20 X`09XtRCallback,`20 X`09(caddr_t) NULL`7D, X`7D; X`20 Xstatic XtResource constraints`5B`5D = `7B X `7B`09DwtNmin,`20 X`09DwtCMin, X`09XtRDimension,`20 X`09sizeof(Dimension), X`09XtOffset(Constraints,min),`20 X`09XtRDimension,`20 X`09(caddr_t) &resource_min`7D, X`20 X `7B`09DwtNmax,`20 X`09DwtCMax,`20 X`09XtRDimension,`20 X`09sizeof(Dimension), X`09XtOffset(Constraints,max),`20 X`09XtRDimension,`20 X`09(caddr_t) &resource_max`7D, X`20 X `7B`09DwtNposition, X`09DwtCPosition, X`09XtRPosition,`20 X`09sizeof(Position), X`09XtOffset(Constraints,position),`20 X`09XtRPosition, X`09(caddr_t) &resource_0_position`7D, X`20 X `7B`09DwtNresizable, X`09XtCBoolean,`20 X`09XtRBoolean,`20 X`09sizeof(Boolean), X`09XtOffset(Constraints,resizable),`20 X`09XtRImmediate,`20 X`09(caddr_t) TRUE`7D, X`20 X `7B`09DwtNsharedFlag, X`09DwtCSharedFlag,`20 X`09XtRInt,`20 X`09sizeof(int), X`09XtOffset(Constraints,sharedflag),`20 X`09XtRImmediate,`20 X`09(caddr_t) NoSharedPaneMask`7D, X`20 X`7D; X`20 X/* 0xff09 = Tab */ Xstatic char *textbindings = X "Shift0xff09:`09focus-prev()\n\ X 0xff09: `09`09focus-next()"; X`20 X`20 Xstatic XtTranslations compiledtextbindings = NULL; X `20 Xstatic void LclUpdateCallback(); Xstatic void Help(); Xstatic void HandleMullionEvents(); Xstatic void HandleCancelMullionEvents(); Xstatic void GrabFocus(); Xstatic void FocusNext(); Xstatic void FocusPrev(); Xstatic Boolean AcceptFocus(); Xstatic XtGeometryResult GeometryManager(); Xstatic Boolean SetConstraintValues(); Xstatic void MullionInitialize(); Xstatic void ChangeManaged(); Xstatic void InsertChild(); Xstatic void DeleteChild(); X`20 Xstatic char DefaultMullionTranslation`5B`5D = X ":`09`09`09 mullion-enter()\n\ X :`09`09`09`09`09mullion-exit()\n\ X `7EShift `7ECtrl `7EMod1 `7E@Help: mullion-star Vt()\n\ X `7EShift `7ECtrl `7EMod1 `7E@Help Button1: mullion-adju Vst()\n\ X `7EShift `7ECtrl `7EMod1 `7E@Help : mullion-end( V)\n\ X `7EShift `7ECtrl `7EMod1 `7E@Help: mullion-canc Vel()\n\ X `7EShift `7ECtrl `7EMod1 `7E@Help: mullion-canc Vel()\n\ X @Help:`09`09`09`09`09Help()"; X`20 Xstatic char DefaultTranslation`5B`5D = X "@Help: `09`09`09`09Help()"; X`20 Xstatic XtActionsRec ActionsTable`5B`5D =`20 X `7B X`09`7B"mullion-enter",`09`09(XtActionProc) HandleMullionEvents`7D, X`09`7B"mullion-exit",`09`09(XtActionProc) HandleMullionEvents`7D, X`09`7B"mullion-start",`09`09(XtActionProc) HandleMullionEvents`7D, X`09`7B"mullion-adjust",`09`09(XtActionProc) HandleMullionEvents`7D, X`09`7B"mullion-end",`09`09(XtActionProc) HandleMullionEvents`7D, X`09`7B"mullion-cancel",`09`09(XtActionProc) HandleCancelMullionEvents`7D, X`09`7B"grab-focus",`09`09(XtActionProc) GrabFocus`7D, X`09`7B"focus-next",`09`09(XtActionProc) FocusNext`7D, X`09`7B"focus-prev",`09`09(XtActionProc) FocusPrev`7D, X `09`7B"Help", `09(XtActionProc) Help`7D, X `7BNULL, NULL`7D X `7D; X`20 Xstatic Cursor VPaneCursor=NULL, HPaneCursor=NULL; X`0C Xexternaldef(panewidgetclassrec) PaneClassRec panewidgetclassrec = `7B X `7B X/* core_class fields */ X /* superclass */ (WidgetClass) &constraintClassRec, X /* class_name */ "Pane", X /* widget_size */`09sizeof(PanePart), X /* class_initialize */ ClassInitialize, X /* class_part_initial */`09NULL, X /* class_inited */`09FALSE, X /* initialize */ Initialize, X /* initialize_hook */`09NULL, X /* realize */ Realize, X /* actions */ ActionsTable, X /* num_actions`09 */`09XtNumber(ActionsTable), X /* resources */ (XtResource *) resources, X /* num_resources */ XtNumber(resources), X /* xrm_class */ NULLQUARK, X /* compress_motion`09 */`09TRUE, X /* compress_exposure */`09TRUE, X /* compress_enterleave*/`09TRUE, X /* visible_interest */ FALSE, X /* destroy */ Destroy, X /* resize */ Resize, X /* expose */ NULL, X /* set_values */ SetValues, X /* set_values_hook */ NULL, X /* set_values_almost */ NULL, X /* get_values_hook */ NULL, X /* accept_focus */ AcceptFocus, X /* version`09`09 */`09XtVersionDontCheck, X /* callbacks */ NULL, X /* tm_table */ DefaultTranslation, X /* disp accelerator */ NULL, X /* extension`09 */`09NULL X `7D,`7B X/* composite_class fields */ X /* geometry_manager */ GeometryManager, X /* change_managed */ ChangeManaged, X /* insert_child`09 */`09InsertChild, X /* delete_child`09 */`09DeleteChild, X /* extension`09 */`09NULL X `7D,`7B X/* constraint_class fields */ X /* constraint resource list */ (XtResourceList) constraints, X /* number of constraints in list */ XtNumber(constraints), X /* size of constraint record */ sizeof(ConstraintsRec), X /* constraint initialization */ NULL, X /* constraint destroy proc */ NULL, X /* constraint set_values proc */ SetConstraintValues, X /* extension`09`09`09 */ NULL X `7D,`7B X /* offsets`09`09 */`09NULL, X /* mumble`09`09 */`090`09/* Make C compiler happy */ X `7D X`7D; X`20 Xexternaldef(panewidgetclass) PaneClass panewidgetclass = &panewidgetclassrec V; X`20 Xstatic struct _WidgetClassRec mullionClassRec = `7B X /* superclass */ (WidgetClass) &widgetClassRec, X /* class name */ "Mullion", X /* size */ sizeof(MullionRec), X /* class initialize */ NULL, X /* class_part_initial */ NULL, X /* class_inited */ FALSE, X /* initialize */ MullionInitialize, X /* initialize_hook */ NULL, X /* realize */ XtInheritRealize, X /* actions */ ActionsTable, X /* num_actions */ XtNumber(ActionsTable), X /* resources`09 */ NULL, X /* num_resources */ 0, X /* xrm_class */ NULLQUARK, X /* compress_motion */ TRUE, X /* compress_exposure */ TRUE, X /* compress enterleave*/ TRUE, X /* visible_interest */ FALSE, X /* destroy */ NULL, X /* resize */ NULL, X /* expose */ NULL, X /* set_values */ NULL, X /* set_values_hook */ NULL, X /* set_values_almost */ NULL, X /* get_values_hook */ NULL, X /* accept_focus */ NULL, X /* version`09`09 */ XtVersionDontCheck, X /* callbacks */ NULL, X /* tm_table */ DefaultMullionTranslation, X /* query_geometry`09 */ XtInheritQueryGeometry, X /* display_accelerator*/ NULL, X /* extension`09 */ NULL X`7D; X`20 Xstatic WidgetClass mullionWidgetClass = (WidgetClass) &mullionClassRec; X`20 X#define DataFromWidget(subwidget) (Constraints)subwidget->core.constraints X`20 Xstatic void MullionInitialize(unused_request, w) XWidget unused_request, w; X`7B X PaneWidget pane = (PaneWidget) w->core.parent; X w->core.border_pixel = Foreground(pane); X w->core.border_width = MullionSize(pane); X w->core.width = FindWidth(InterSub(pane),Breadth(pane)); X w->core.height = FindHeight(InterSub(pane),Breadth(pane)); X w->core.x = w->core.y = -99; X`7D X`20 X`0C X/* X * Figure out what length of the window we're actually using. Ideally, this X * will be the same as the window's length, but it will often be different X * (for example, when we don't have enough windows to take up the entire X * window's length.) X */ X`20 Xstatic Dimension LengthUsed(pane) XPaneWidget pane; X`7B X Dimension result; X int i, cnt; X Constraints subdata, nextsubdata; X Boolean allfixed; X X if (PaneNumChildren(pane) == 0) return 0; X result = 0; X for (i=0 ; iresizable) X`09`09`7B X`09`09result += InterSub(pane); X`09`09`7D X`09 else X`09`09`7B X`09`09allfixed = TRUE; X`09`09for (cnt = i + 1; cnt < PaneNumChildren(pane); cnt++) X`09`09 `7B X`09`09 nextsubdata = DataFromWidget(PaneChildren(pane)`5Bcnt`5D); X`09`09 if (nextsubdata->resizable) X`09`09`09`7B X`09`09`09allfixed = FALSE; X`09`09`09break; X`09`09`09`7D X`09`09 `7D X`09`09if (allfixed) X`09`09 `7B X`09`09 result += InterSub(pane); X`09`09 `7D X`09`09 else X`09`09 `7B X`09`09 result += MullionLength(pane); X`09`09 `7D X`09`09`7D X`09 `7D`20 X`09`7D X return result; X`7D X`20 X`20 X`0C X/* X * Set the dheight field of each subwidget to be the appropriate height if w Ve X * want to move the border below the given subwidget by the given number of X * pixels. X */ X`20 Xstatic void RefigureDlengths(pane, sub, delta) XPaneWidget pane; XWidget sub; Xint delta; X`7B X int cur_above, min_above, max_above; X int cur_below, min_below, max_below; X int used; X Boolean currentlyabove; X Widget subwidget; X Constraints subdata; X int i, which, temp, newlength; X `20 X /* X * if we allow resizing of the pane we will just reset the child`20 X * between the min and the max if it isn't already. X */ X if (ResizeMode(pane) != DwtResizeFixed) `7B X`09for (i=0 ; i subdata->dlength) X`09`09`09subdata->dlength = Length(subwidget); X`09 /* if the subwidget cannot be resized set the min and max to X`09 * the created length of the widget. X`09 */`20 X`09 if (subdata->resizable) X`09`09`7B X`09`09if (subdata->dlength < subdata->min) X`09`09 subdata->dlength = subdata->min; X`09`09if (subdata->dlength >subdata->max) X`09`09 subdata->dlength = subdata->max; X`09`09`7D X`09 else X`09`09`7B X`09`09subdata->min = subdata->max = subdata->dlength; X`09`09`7D X`09`7D/* end for */ X`09return; X `7D X /* Ok no resizing allowed so we have to be a little more particular X */ X cur_above = min_above = max_above = 0; X cur_below = min_below = max_below = 0; X currentlyabove = TRUE; X /* Find the length above & including the changed widget & the length X * below this widget. Total above & below on current, maximium and X * minimium X */ X for (i=0 ; imin; X`09 max_above += subdata->max; X`09`7D else `7B X`09 cur_below += Length(subwidget); X`09 min_below += subdata->min; X`09 max_below += subdata->max; X`09`7D X`09if (subwidget == sub) `7B X`09 which = i; X`09 currentlyabove = FALSE; X`09`7D X `7D /* end for loop */ X if (currentlyabove) X`09XtWarning("Never found the subwidget in Pane."); X used = LengthUsed(pane); X if (used < Length(pane)) min_below -= Length(pane) - used; X else max_below += used - Length(pane); X if (delta < min_above - cur_above) delta = min_above - cur_above; X if (delta < cur_below - max_below) delta = cur_below - max_below; X if (delta > max_above - cur_above) delta = max_above - cur_above; X if (delta > cur_below - min_below) delta = cur_below - min_below; X temp = delta; X /* a for loop is easier to read here. Also why continue if temp = 0? X * And further more there is no good reason to reset temp. X */ X for (i = which; i >= 0; i--) X`09`7B X`09subwidget = PaneChildren(pane)`5Bi`5D; X`09subdata = DataFromWidget(subwidget); X`09/* only make changes if we can resize this widget X`09 */ X`09if (subdata->resizable) X`09 `7B X`09 newlength = Length(subwidget) + temp; X`09 if (newlength < (int) subdata->min) newlength = subdata->min; X`09 if (newlength > (int) subdata->max) newlength = subdata->max; X`09 subdata->dlength = newlength; X`09 `7D X`09else X`09 `7B X`09 subdata->min = subdata->max = subdata->dlength = Length(subwidget); X`09 `7D X`09temp -= (subdata->dlength - Length(subwidget)); X`09`7D X /* take what ever was gained on the top and put it on the bottom X */ X temp = -delta; X for (i = which+1; i < PaneNumChildren(pane); i++) X`09`7B X`09subwidget = PaneChildren(pane)`5Bi`5D; X`09subdata = DataFromWidget(subwidget); X`09/* only make changes if we can resize this widget X`09 */ X`09if (subdata->resizable) X`09 `7B X`09 newlength = Length(subwidget) + temp; X`09 if (newlength < (int) subdata->min) newlength = subdata->min; X`09 if (newlength > (int) subdata->max) newlength = subdata->max; X`09 subdata->dlength = newlength; X`09 `7D X`09else X`09 `7B X`09 subdata->min = subdata->max = subdata->dlength = Length(subwidget); X`09 `7D X`09temp -= (subdata->dlength - Length(subwidget)); X`09`7D X`7D X`20 X`20 X`0C Xstatic void TryToFillPane(pane) XPaneWidget pane; X`7B X int used, length; X length = Length(pane); X used = LengthUsed(pane); X if (PaneNumChildren(pane) > 0) X`09RefigureDlengths(pane, PaneChildren(pane)`5BPaneNumChildren(pane)-1`5D, X`09`09`09 length - used); X`7D X`20 X`0C Xstatic void CommitNewSizes(pane, dontnotify) XPaneWidget pane; XWidget dontnotify; X`7B X XWindowChanges changes; X Position loc; X int i, cnt;`20 X Widget subwidget, nextsubwidget, mullion; X Constraints subdata, nextsubdata; X Boolean allfixed; X loc = 0; X for (i=0 ; idlength, Breadth(pane)); X`09changes.height = FindHeight(subdata->dlength, Breadth(pane)); X`09changes.border_width = 0; X`09if (changes.x != subwidget->core.x `7C`7C changes.y != subwidget->core.y V `7C`7C X`09 changes.width != subwidget->core.width `7C`7C X`09 changes.height != subwidget->core.height `7C`7C X`09 changes.border_width != subwidget->core.border_width)`20 X`09 `7B X`09 subwidget->core.x = changes.x; X`09 subwidget->core.y = changes.y; X`09 subwidget->core.width = changes.width; X`09 subwidget->core.height = changes.height; X`09 subwidget->core.border_width = changes.border_width; X`09 if (XtIsRealized(subwidget)) `20 X`09`09`7B X`09`09XConfigureWindow(XtDisplay(subwidget), XtWindow(subwidget), X`09`09 (unsigned) CWX `7CCWY `7C CWWidth `7C CWHeight `7C CWBorderWidth, X`09`09 &changes); X`09`09`7D X`09 if (subwidget != dontnotify && X`09`09 XtClass(subwidget)->core_class.resize != (XtWidgetProc) NULL) X`09`09`7B X`09`09(*(subwidget->core.widget_class->core_class.resize))(subwidget); X`09`09`7D X`09 `7D X`09loc += Length(subwidget); X X`09/* Now position the mullion`20 X`09 */ X`09mullion = subdata->mullion; X`20 X`09/* Get any new width and height X`09 */ X`09changes.width = FindWidth(InterSub(pane),Breadth(pane)); X`09changes.height = FindHeight(InterSub(pane),Breadth(pane)); X`09changes.border_width = MullionSize(pane); X`20 X`09/* Move this mullion where they can't get to it if: X`09 * - the subwidget is a fixed size X`09 * - the next subwidgets are all a fixed size`20 X`09 * - the subwidget is the last child X`09 */ X`09if (i < PaneNumChildren(pane) - 1)`20 X`09 `7B`20 X`09 if (!subdata->resizable) X`09`09`7B X`09`09changes.x = changes.y = -99; X`09`09loc += InterSub(pane); X`09`09`7D X`09 else X`09`09`7B X`09`09allfixed = TRUE; X`09`09for (cnt = i + 1; cnt < PaneNumChildren(pane); cnt++) X`09`09 `7B X`09`09 nextsubwidget = PaneChildren(pane)`5Bcnt`5D; X`09`09 nextsubdata = DataFromWidget(nextsubwidget); X`09`09 if (nextsubdata->resizable) X`09`09`09`7B X`09`09`09allfixed = FALSE; X`09`09`09break; X`09`09`09`7D X`09`09 `7D X`09`09if (allfixed) X`09`09 `7B X`09`09 changes.x = changes.y = -99; X`09`09 loc += InterSub(pane); X`09`09 `7D X`09`09 else X`09`09 `7B X`09`09 changes.x = FindWidth(loc, 0); X`09`09 changes.y = FindHeight(loc, 0); X`09`09 loc += MullionLength(pane); X`09`09 `7D X`09`09`7D X`20 X`09 `7D`20 X`09else`20 X`09 `7B X `09 changes.x = changes.y = -99; X`09 loc += InterSub(pane); X`09 `7D X`09if (changes.x != mullion->core.x `7C`7C`20 X`09 changes.y != mullion->core.y `7C`7C X`09 changes.width != mullion->core.width `7C`7C`20 X`09 changes.height != mullion->core.height `7C`7C X`09 changes.border_width != mullion->core.border_width)`20 X`09 `7B X`09 mullion->core.x = changes.x; X`09 mullion->core.y = changes.y; X`09 mullion->core.width = changes.width; X`09 mullion->core.height = changes.height; X`09 mullion->core.border_width = changes.border_width; X`09 if (XtIsRealized(mullion)) X`09`09`7B X`09`09XConfigureWindow(XtDisplay(mullion), XtWindow(mullion), X`09`09 (unsigned) CWX `7C CWY `7C CWWidth `7C CWHeight `7C CWBorderWidth, X`09`09 &changes); X`09`09XRaiseWindow(XtDisplay(mullion), XtWindow(mullion)); X`09`09`7D X`09 `7D X`09else X`09 `7B X`09 if (XtIsRealized(mullion)) X`09`09XRaiseWindow(XtDisplay(mullion), XtWindow(mullion)); X`09 `7D X `7D X`7D X`20 X`20 X`0C X/* X * Invert the given border. X */ X`20 Xstatic void InvertIt(pane, loc, mullionlength) XPaneWidget pane; XPosition loc; XDimension mullionlength; X`7B X loc += mullionlength / 2 + 1; /* Deal with X's definition that wide */ X`09`09`09`09 /* lines are centered around the */ X`09`09`09`09 /* specified points. */ X`20 X XDrawLine(XtDisplay(pane), XtWindow(pane), InvGC(pane), X`09 FindWidth(loc, 0), FindHeight(loc, 0), X`09 FindWidth(loc, Breadth(pane)), FindHeight(loc, Breadth(pane))); X`7D X`20 X`20 X`0C X/* X * Move the magic borders to the location specified by the current dlength X * values.`20 X */ X`20 Xstatic void MoveMagicBorders(pane) XPaneWidget pane; X`7B X Position loc; X int i, cnt; X Constraints subdata, nextsubdata; X Boolean allfixed; X X loc = 0; X for (i=0 ; idlength; X`09if (loc != subdata->magicborder)`20 X`09 `7B X`09 if (PaneChildren(pane)`5Bi`5D == WhichAdjust(pane)) X`09`09`7B X`09`09if (subdata->magicborder != OrigLoc(pane))`20 X`09`09 InvertIt(pane, subdata->magicborder, LengthMullion(subdata)); X`09`09if (loc != OrigLoc(pane))`20 X`09`09 InvertIt(pane, loc, LengthMullion(subdata));`20 X`09`09`7D X`09 else X`09`09`7B X`09`09if (subdata->magicborder !=`20 X`09`09 (StartLoc(PaneChildren(pane)`5Bi`5D) + Length(PaneChildren(pane)`5B Vi`5D))) X`09`09 InvertIt(pane, subdata->magicborder, LengthMullion(subdata)); X`09`09if (loc !=`20 X`09`09 (StartLoc(PaneChildren(pane)`5Bi`5D) + Length(PaneChildren(pane)`5B Vi`5D))) X`09`09 InvertIt(pane, loc, LengthMullion(subdata)); X`09`09`7D X`09 subdata->magicborder = loc; X`09 `7D X`09if (i < PaneNumChildren(pane) - 1)`20 X`09 `7B`20 X`09 if (!subdata->resizable) X`09`09`7B X`09`09loc += InterSub(pane); X`09`09`7D X`09 else X`09`09`7B X`09`09allfixed = TRUE; X`09`09for (cnt = i + 1; cnt < PaneNumChildren(pane); cnt++) X`09`09 `7B X`09`09 nextsubdata = DataFromWidget(PaneChildren(pane)`5Bcnt`5D); X`09`09 if (nextsubdata->resizable) X`09`09`09`7B X`09`09`09allfixed = FALSE; X`09`09`09break; X`09`09`09`7D X`09`09 `7D X`09`09if (allfixed) X`09`09 `7B X`09`09 loc += InterSub(pane); X`09`09 `7D X`09`09 else X`09`09 `7B X`09`09 loc += MullionLength(pane); X`09`09 `7D X`09`09`7D X`09 `7D`20 X`09else`20 X`09 `7B X`09 loc += InterSub(pane); X`09 `7D X`09`7D X`7D X`20 X`0C X/* X * Turn on the magic borders. X */ X`20 Xstatic void DrawMagicBorders(pane) XPaneWidget pane; X`7B X Position loc; X int i, cnt; X Constraints subdata, nextsubdata; X Boolean allfixed; X X loc = 0; X for (i=0 ; idlength; X`09subdata->magicborder = loc; X`09if (i < PaneNumChildren(pane) - 1)`20 X`09 `7B`20 X`09 if (!subdata->resizable) X`09`09`7B X`09`09loc += InterSub(pane); X`09`09`7D X`09 else X`09`09`7B X`09`09allfixed = TRUE; X`09`09for (cnt = i + 1; cnt < PaneNumChildren(pane); cnt++) X`09`09 `7B X`09`09 nextsubdata = DataFromWidget(PaneChildren(pane)`5Bcnt`5D); X`09`09 if (nextsubdata->resizable) X`09`09`09`7B X`09`09`09allfixed = FALSE; X`09`09`09break; X`09`09`09`7D X`09`09 `7D X`09`09if (allfixed) X`09`09 `7B X`09`09 loc += InterSub(pane); X`09`09 `7D X`09`09 else X`09`09 `7B X`09`09 loc += MullionLength(pane); X`09`09 `7D X`09`09`7D X`09 `7D`20 X`09else`20 X`09 `7B X`09 loc += InterSub(pane); X`09 `7D X `7D X`7D X`20 X`0C X/* X * Turn off the magic borders. X */ X`20 Xstatic void EraseMagicBorders(pane) XPaneWidget pane; X`7B X int`09`09i; X Constraints subdata; X for (i=0 ; imagicborder != OrigLoc(pane)) X`09`09InvertIt(pane, subdata->magicborder, LengthMullion(subdata)); X`09 `7D X`09else X`09 `7B X`09 subdata = DataFromWidget(PaneChildren(pane)`5Bi`5D); X`09 if (subdata->magicborder !=`20 X`09 (StartLoc(PaneChildren(pane)`5Bi`5D) + Length(PaneChildren(pane)`5 VBi`5D))) X`09`09InvertIt(pane, subdata->magicborder, LengthMullion(subdata)); X`09 `7D X`09`7D X XClearWindow(XtDisplay(pane), XtWindow(pane)); X`7D X`20 X`20 X`0C X/* X * Find where (lengthwise) in the pane window the given event is pointing. X * (The event was delivered to the given widget.) X */ X`20 Xstatic Position FindWherePointing(pane, widget, event) XPaneWidget pane; XWidget widget; XXEvent *event; X`7B X Position x, y; X x = event->xbutton.x; X y = event->xbutton.y; X while (widget != (Widget) pane) `7B X`09x += widget->core.x; X`09y += widget->core.y; X`09widget = widget->core.parent; X `7D X return FindLength(x, y); X`7D X`20 X`20 X`0C X/* X * Given that the button down event was delivered to the mullion, X * figure out which window is above the border that the user is trying to X * adjust. `20 X */ X`20 Xstatic Widget FindWhichAdjust(pane, widget, event) XPaneWidget pane; XWidget widget; XXEvent *event; X`7B X Widget result; X Position where, loc; X int i; X Constraints subdata; X X where = FindWherePointing(pane, widget, event); X loc = MullionLength(pane)/2 + 1; X result = PaneChildren(pane)`5B0`5D; X for (i=0 ; icore.parent; X if (PaneNumChildren(pane) == 0) return; X switch (event->type) `7B X case EnterNotify: X`09if (Orientation(pane) == DwtOrientationVertical) X`09 `7B X`09 XDefineCursor (XtDisplay(widget->core.parent), XtWindow(widget->core. Vparent), VPaneCursor); X`09 `7D X`09else X`09 `7B X`09 XDefineCursor (XtDisplay(widget->core.parent), XtWindow(widget->core. Vparent), HPaneCursor); X`09 `7D X`09LeftMullion(pane) = False; X`09break; X case LeaveNotify: X`09if (WhichAdjust(pane) == NULL) X`09 `7B X`09 XUndefineCursor (XtDisplay(widget->core.parent), XtWindow(widget->cor Ve.parent)); X`09 `7D X`09else X`09 `7B X`09 LeftMullion(pane) = True; X`09 `7D X`09break; X case ButtonPress: X`09WhichAdjust(pane) = FindWhichAdjust(pane, widget, event); X/* X * The OrigLoc is the Origicnal location of the dividing line between two pa Vnes. It is X * calculated by adding the starting location (x or y depending on orientati Von) to X * the length (width or height depending on orientation)`20 X */ X`09OrigLoc(pane) = StartLoc(WhichAdjust(pane)) + Length(WhichAdjust(pane)); X`09RefigureDlengths(pane, WhichAdjust(pane), 0); X`09DrawMagicBorders(pane); X`09break; X case MotionNotify: X`09if (WhichAdjust(pane) == NULL) break; X`09RefigureDlengths(pane, WhichAdjust(pane), X`09`09`09 FindWherePointing(pane, widget, event) - X`09`09`09 OrigLoc(pane)); X`09MoveMagicBorders(pane); X`09break; X case ButtonRelease: X/*`20 X * make sure the operation wasn't canceled`20 X*/ X`09if (WhichAdjust(pane) != NULL)`20 X`09 `7B X`09 RefigureDlengths(pane, WhichAdjust(pane), X`09`09`09 FindWherePointing(pane, widget, event) - X`09`09`09`09 OrigLoc(pane)); X`09 MoveMagicBorders(pane); X`09 EraseMagicBorders(pane); X`09 CommitNewSizes(pane, (Widget) NULL); X`09 WhichAdjust(pane) = NULL; X`09 `7D X`09if (LeftMullion(pane)) X`09 `7B X`09 XUndefineCursor (XtDisplay(widget->core.parent), XtWindow(widget->cor Ve.parent)); X`09 LeftMullion(pane) = False; X`09 `7D X`09break; X `7D X`7D X`20 X/* X * Handle cancel (MB2 & MB3 press) button events in the mullion window. X */ X`20 Xstatic void HandleCancelMullionEvents(widget) XWidget widget; X`7B X PaneWidget pane = (PaneWidget) widget->core.parent; X if (PaneNumChildren(pane) == 0) return; X if (LeftMullion(pane)) X`09`7B X`09EraseMagicBorders(pane); X`09XUndefineCursor (XtDisplay(widget->core.parent), XtWindow(widget->core.pa Vrent)); X`09LeftMullion(pane) = False; X`09`7D X WhichAdjust(pane) = NULL; X`7D X`0C Xstatic void ClassInitialize(unused_w) XWidget unused_w; X`7B X DwtResolvePartOffsets(panewidgetclass, X`09`09 &panewidgetclassrec.pane_class.paneoffsets); X compiledtextbindings = XtParseTranslationTable (textbindings); X`7D X `20 X`20 X`20 X`20 X`0C X/* X * Initialize this instance of pane. X */ X`20 Xstatic void Initialize(unused_request, w) XWidget unused_request, w; X`7B X PaneWidget pane = (PaneWidget) w; X XGCValues values; X`20 X/* X** Create the pane cursors... X*/ X if (VPaneCursor == NULL) X`09`7B X /* X * Local data for the pane cursor X *`09Note: Normally one would do this sort of thing in ClassInitialize b Vut, X *`09setting up cursors requires a live widget which ClassInit doesn't h Vave. X */ X`09XColor cursor_fore, cursor_back; X`09Font cursor_font; X`09int cursor_wait; X`20 X /* X ** Set up the colors X */ X`09cursor_fore.pixel = 0; X`09cursor_fore.red = 65535; X`09cursor_fore.green = 65535; X`09cursor_fore.blue = 65535; X`20 X`09cursor_back.pixel = 0; X`09cursor_back.red = 0; X`09cursor_back.green = 0; X`09cursor_back.blue = 0; X`20 X`09cursor_font = XLoadFont (XtDisplay(w), "decw$cursor"); X`09cursor_wait = decw$c_vpane_cursor; X`09VPaneCursor = XCreateGlyphCursor (XtDisplay(w), cursor_font, cursor_font, V cursor_wait,`20 X`09`09`09`09`09`09 cursor_wait + 1, &cursor_fore, &cursor_back); X`09cursor_wait = decw$c_hpane_cursor; X`09HPaneCursor = XCreateGlyphCursor (XtDisplay(w), cursor_font, cursor_font, V cursor_wait,`20 X`09`09`09`09`09`09 cursor_wait + 1, &cursor_fore, &cursor_back); X`09XUnloadFont (XtDisplay(w), cursor_font); X`09`7D X`20 X if (Width(pane) == 0) Width(pane) = 200; /* Better default?%%% */ X if (Height(pane) == 0) Height(pane) = 200; X PaneNumChildren(pane) = 0; X PaneChildren(pane) = NULL; X WhichAdjust(pane) = NULL; X OrigLoc(pane) = 0; X LastHadFocus(pane) = NULL; X MullionLength(pane) = (MullionSize(pane) * 2) + InterSub(pane); X values.function = GXinvert; X values.foreground = BackgroundPixel(pane) `5E Foreground(pane); X if (values.foreground == 0) values.foreground = 1; X values.line_width = InterSub(pane); X if (values.line_width == 1) X`09values.line_width = 0;`09/* Take advantage of fast server lines. */ X values.plane_mask = BackgroundPixel(pane) `5E Foreground(pane); X values.fill_style = FillSolid; X values.subwindow_mode = IncludeInferiors; X InvGC(pane) = XtGetGC(w, X`09`09`09 (XtGCMask) GCFunction `7C GCForeground X`09`09`09 `7C GCLineWidth `7C GCPlaneMask `7C GCFillStyle X`09`09`09 `7C GCSubwindowMode, X`09`09`09 &values); X`7D X`20 X`0C X/* X * Realize the pane widget. X */ X`20 Xstatic void Realize(w, vMask, attributes) XWidget w; XMask *vMask; XXSetWindowAttributes *attributes; X`7B X PaneWidget pane = (PaneWidget) w; X Mask valueMask = *vMask; X`20 X if (ResizeMode(pane) != DwtResizeFixed) `7B X/* X * For now the ResizeMode is forced to DwtResizeFixed so that you can move t Vhe X * mullion once you get this beast up. If the user wants to change the pane V widget X * back he should call DwtPaneAllowResizing, do the work in adjusting the wi Vdget X * and then reset the value back. X *`20 X * This needs to be changed and modeled after the DIALOG widget. See the`20 X * adapt_to_kids routine. X */ X`09ResizeMode(pane) = DwtResizeFixed; X`09TryToFillPane(pane); X`09CommitNewSizes(pane, (Widget) NULL); X `7D X `20 X attributes->bit_gravity = NorthWestGravity; X attributes->background_pixel = Foreground(pane); X valueMask `7C= CWBitGravity `7C CWBackPixel; X `20 X XtCreateWindow(w, (unsigned int) InputOutput, (Visual *) CopyFromParent, X`09`09 valueMask, attributes); X`7D X`20 X`0C X/* X * Destroy the pane widget. X */ X`20 Xstatic void Destroy(w) XWidget w; X`7B X PaneWidget pane = (PaneWidget) w; X`20 X/* Free the memory allocated for the children that are displayed and those i Vn`20 X * the composite field. We created and allocated space for them it so we X * must Free it. X */ X XtFree((char *)Children(pane)); X XtFree((char *)PaneChildren(pane)); X`20 X/* X * Remove all callbacks that were created X */ X XtRemoveAllCallbacks ((Widget)pane, DwtNhelpCallback); X XtRemoveAllCallbacks ((Widget)pane, DwtNfocusCallback); X XtRemoveAllCallbacks ((Widget)pane, DwtNmapCallback); X XtRemoveAllCallbacks ((Widget)pane, DwtNunmapCallback); X/* X * Free the InvGC that was created X */ X XtDestroyGC (InvGC(pane)); X`7D X`20 X`0C X/* X * The purpose of this routine is to check and see in the Vertical`20 X * orientation if a change in width will also change a subwidgets height X */ X`20 Xstatic void CheckHeightChanges(pane) X PaneWidget pane; X`7B X XtWidgetGeometry intended, reply; X Widget subwidget; X Constraints subdata; X int i; X`20 X if (Orientation(pane) != DwtOrientationVertical) return;`20 X`20 X intended.request_mode = CWWidth;`09`09/* ask about this width */ X`20 X for (i=0 ; iresizable) X`09 `7B X`09 intended.width = Width(pane); /* if it affects the size */ X`09`09`09`09`09 /* he'll tell us */ X`20 X`09 switch (XtQueryGeometry (subwidget, &intended, &reply)) X`09`09`7B X`09`09case XtGeometryAlmost:`09`09/* he wants to compromise */ X`20 X`09`09 if ((reply.request_mode & CWHeight) && X`09`09`09 subwidget->core.height != reply.height) X`09`09`09`7B X`09`09`09/* take height he suggests */ X`09`09`09subwidget->core.height = reply.height;`09 X`09`09`09RefigureDlengths(pane,subwidget,subdata->dlength - X`09`09`09`09`09 reply.height); X`09`09`09`7D X`09`09 break; X`20 X`09`09case XtGeometryYes: X`09`09case XtGeometryNo: X`09`09`09/* he agrees, no problem w/ */ X`09`09`09/* current height */ X`09`09 break; X`09`09`7D /* end case */ X`09 `7D /* end if */ X`09`7D /* end for loop */ X`7D X`20 X`0C X/* X * The pane widget has been resized; handle everything. X */ X`20 Xstatic void Resize(w) XWidget w; X`7B X PaneWidget pane = (PaneWidget) w; X CheckHeightChanges(pane); X TryToFillPane(pane); X CommitNewSizes(pane, (Widget) NULL); X`7D X`20 X`0C X/* X * Resources in the pane widget have changed; handle it. X */ X`20 Xstatic Boolean SetValues (old, unused_request, new) X Widget old, unused_request, new; X`7B X PaneWidget`09oldpane = (PaneWidget) old; X PaneWidget`09newpane = (PaneWidget) new; X Boolean`09redisplay = FALSE; X XGCValues`09values; X`20 X/* X * Update the callbacks X */ X LclUpdateCallback (`09 &(oldpane->pane.map_callback), X`09`09`09 (Widget) newpane, &(newpane->pane.map_callback), DwtNmapCallback); X LclUpdateCallback (`09 &(oldpane->pane.unmap_callback), X`09`09`09 (Widget) newpane, &(newpane->pane.unmap_callback), DwtNunmapCallba Vck); X LclUpdateCallback (`09 &(oldpane->pane.helpcallback), X`09`09`09 (Widget) newpane, &(newpane->pane.helpcallback), DwtNhelpCallback) V; X LclUpdateCallback (`09 &(oldpane->pane.focus_callback), X`09`09`09 (Widget) newpane, &(newpane->pane.focus_callback), DwtNfocusCallba Vck); X`20 X/* X * For now ignore orientation changes X */ X if (Orientation(newpane) != Orientation(oldpane)) X`09`7B X`09Orientation(newpane) = Orientation(oldpane); X`09`7D X`20 X/* X * For now ignore resize mode change X */ X if (ResizeMode(newpane) != ResizeMode(oldpane)) X`09`7B X`09ResizeMode(newpane) = ResizeMode(oldpane); X`09`7D X/* X * Something should be done with foreground here but I don't think that work Vs X * anyway so wait till you fix it latter X */ X`20 X/* X * Check the mullion and spacing for changes. If so set redisplay X */ X if ((MullionSize(newpane) != MullionSize(oldpane)) `7C`7C X`09(InterSub(newpane) != InterSub(oldpane))) X`09 `7B X/* X * Change the inverted lines width to InterSub new length X */ X`09 if (InterSub(newpane) != InterSub(oldpane)) X`09`09`7B X`09`09values.line_width = InterSub(newpane); X`09`09if (values.line_width == 1) X`09`09 values.line_width = 0;`09/* Take advantage of fast server lines. * V/ X`09`09XChangeGC (XtDisplay(newpane),InvGC(newpane), GCLineWidth, &values); X`09`09`7D X#ifdef bugfixed X/* X * Currently there is a bug in the XConfirgureWindow which prevents reseting V of X * the border width. In the mean time don't allow any change in MullionSize. X */ X`09 MullionLength(newpane) = (MullionSize(newpane) * 2) + InterSub(newpan Ve); X#else X`09 MullionSize(newpane) = MullionSize(oldpane); X#endif X/*`20 X * if the mullions need to be changed in width and or height they will be ch Vanged X * in the CommitNewSizes routine.`20 X */ X`09 redisplay = TRUE; X`09 TryToFillPane(newpane); X`09 CommitNewSizes(newpane, (Widget) NULL); X`09 `7D X`20 X return redisplay; X`7D`09 X X/* X * SetValue on the callback is interpreted as replacing X * all callbacks X */ X Xstatic void XLclUpdateCallback (rstruct, s, sstruct, argname) X DwtCallbackStructPtr rstruct;`09`09/* the real callback list */ X Widget s;`09`09`09`09`09/* the scratch widget*/ X DwtCallbackStructPtr sstruct;`09`09/* the scratch callback list */ X char *argname; X`7B X DwtCallbackPtr list; X X /* X * if a new callback has been specified in the scratch widget, X * remove and deallocate old callback and init new`20 X */ X if (rstruct->ecallback != sstruct->ecallback) X `7B X`09list = (DwtCallbackPtr)sstruct->ecallback; X`09/* X`09 * Copy the old callback list into the new widget, since X`09 * XtRemoveCallbacks needs the "real" widget X `09 */ X *sstruct = *rstruct; X`09XtRemoveAllCallbacks(s, argname); X`09sstruct->ecallback = NULL; X`09XtAddCallbacks(s, argname, list); X `7D X`7D X`20 X`20 X`20 X`0C Xstatic Boolean SetConstraintValues(current, unused_widget, newWidget) X Widget current, unused_widget, newWidget; X`7B X Constraints cur, new; X Cardinal`09position; X Dimension`09min, max; X Boolean`09resizable; X Cardinal`09sharedflag; X Boolean`09do_add_widget = FALSE; X`20 X cur = DataFromWidget(current); X new = DataFromWidget(newWidget); X position = new->position; X min = new->min; X max = new->max; X resizable = new->resizable; X sharedflag = new->sharedflag; X`20 X if (max == 0) X`09max = resource_max; X if (min == 0) X`09min = resource_min; X/* X * We have to reset all of these because the address of newWidget what is`20 X * acutally stored in the pane widget. If you use the current widget you'll X * stack dump. X */ X if (position != cur->position) X`09`7B X`09do_add_widget = TRUE; X`09new->position = cur->position; X`09`7D X if (min != cur->min) X`09`7B X`09do_add_widget = TRUE; X`09new->min = cur->min; X`09`7D X if (max != cur->max) X`09`7B X`09do_add_widget = TRUE; X`09new->max = cur->max; X`09`7D X if (resizable != cur->resizable) X`09`7B X`09do_add_widget = TRUE; X`09new->resizable = cur->resizable; X`09`7D X if (sharedflag != cur->sharedflag) X`09`7B X`09do_add_widget = TRUE; X`09new->sharedflag = cur->sharedflag; X`09`7D X`20 X/*`20 X * This is just like DwtPaneAddWidget so I'll just call it and`20 X * let it take care of everything. X */ X if (do_add_widget) X`09`7B X`09DwtPaneAddWidget (newWidget, position, min, max, resizable, sharedflag); X`09/* We must reset all of these because it is possible they have changed X`09 * and if we don't change them they will just get changed back to what X`09 * they were when we leave this routine. X`09 */ X`09current->core.x = newWidget->core.x; X`09current->core.y = newWidget->core.y; X`09current->core.width = newWidget->core.width; X`09current->core.height = newWidget->core.height; X`09`7D X return TRUE; X`7D X`20 X`0C X/* X * One of our subwidgets is trying to resize itself. For now we will only X * deal with DwtResizeFixed. Anything else won't work right. X */ X`20 Xstatic XtGeometryResult GeometryManager(subwidget, request, reply) XWidget subwidget; XXtWidgetGeometry *request, *reply; X`7B X XtGeometryResult result; X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints subdata; X Dimension rlength, rbreadth; X X if ((request->request_mode & CWWidth) == 0) X`09request->width = subwidget->core.width; X if ((request->request_mode & CWHeight) == 0) X`09request->height = subwidget->core.height; X rlength = FindLength(request->width, request->height); X rbreadth = FindBreadth(request->width, request->height); X subdata = DataFromWidget(subwidget); X result = XtGeometryAlmost; X if (rlength < subdata->min)`20 X`09`7B X`09rlength = subdata->min; X`09`7D`20 X else if (rlength > subdata->max)`20 X`09`7B X`09rlength = subdata->max; X`09`7D; X if (rbreadth > Breadth(pane)) X`09`7B X`09 result = XtGeometryNo; X`09 rbreadth = Breadth(pane); X`09`7D; X if (rbreadth == Breadth(pane))`20 X`09`7B X`09if (subdata->dlength == rlength) X`09 `7B X`09 /* X`09 * I know this seams bizare since everthing looks like it is`20 X`09 * already set. However the Text widget does things in a funny X`09 * order and it resets the height back so we must redo the`20 X`09 * CommitNewSizes to get the widget back in sinc with the X`09 * constraint. X`09 */ X`09 CommitNewSizes(pane, (Widget) NULL);`20 X`09 result = XtGeometryDone; X`09 `7D X`09else X`09 `7B X`09 RefigureDlengths(pane, subwidget, rlength - subdata->dlength); X`09 CommitNewSizes(pane, (Widget) NULL);`20 X`09 if (subdata->dlength == FindLength(request->width, request->height))` V20 X`09`09result = XtGeometryDone; X`09 `7D; X`09`7D X if (result != XtGeometryDone)`20 X`09`7B X`09*reply = *request; X`09rbreadth = Breadth(pane); X`09reply->width = FindWidth(rlength, rbreadth); X`09reply->height = FindHeight(rlength, rbreadth); X`09`7D X return result; X`7D X`20 X`20 X`20 X`0C X/* X * One of our subwidgets has changed its managed status. X */ X`20 Xstatic void ChangeManaged(w) XWidget w; X`7B X XWindowChanges changes; X PaneWidget pane = (PaneWidget) w; X Widget subwidget, cursubwidget; X Constraints subdata, cursubdata; X int position, i; X`20 X PaneNumChildren(pane) = 0; X for (i=(NumChildren(pane)+1)/2 ; icore.managed &&`20 X`09`09(subdata->sharedflag == NoSharedPaneMask `7C`7C X`09`09subdata->sharedflag == (SharedPaneMask `7C ViewableInPaneMask))) X`09 `7B X`09 if (subdata->sharedflag & SharedPaneMask) X`09`09`7B X`09`09XtSetMappedWhenManaged (subwidget, TRUE); X`09`09`7D X`09 /* X`09 * NOTE:The only reason we do the realizing here is because if X`09 *`09 it isn't realized the mullions don't show up on top. Once X`09 *`09 mullions are removed you can get rid of this if statement X`09 */ X`09 if (XtIsRealized(pane) && !(XtIsRealized(subwidget))) X`09`09`7B X`09`09XtRealizeWidget(subwidget); X`09`09`7D; X`09 PaneChildren(pane)`5B(PaneNumChildren(pane))++`5D = subwidget; X`09 `7D X`09else if (subwidget->core.being_destroyed) X`09 `7B X`09/* X`09 * This subwidget is in the process of being destroyed. X`09 * If this widget is shared then give the pane to first subwidget sharing V`20 X`09 * the same position. X`09 */ X`09 for (position=(NumChildren(pane)/2)+subdata->position;`20 X`09`09 position <= NumChildren(pane);`20 X`09`09 position++) X`09`09`7B X`09`09cursubwidget = Children(pane) `5Bposition-1`5D; X`09`09cursubdata = DataFromWidget (cursubwidget); X`09`09if (cursubdata->position != subdata->position `7C`7C X`09`09 cursubwidget == subwidget) X`09`09 continue; X`09`09DwtPaneMakeViewable (cursubwidget); X`09 /* X`09 * It is necessary to add the subwidget to the PaneChildren list if X`09 * we have already gone passed it. It will be in the correct order X`09 * since PaneChildren are based on position. X`09 */ X`09`09if (position < i) X`09`09 PaneChildren(pane)`5B(PaneNumChildren(pane))++`5D = subwidget; X`09`09break; X`09`09`7D X`09 `7D X`09else X`09 `7B X`09 /* X`09 * UnMap any shared panes that aren't used X`09 */ X`09 if (subdata->sharedflag & SharedPaneMask) X`09`09`7B X`09`09XtSetMappedWhenManaged (subwidget, FALSE); X`09`09XtSetMappedWhenManaged (subdata->mullion, FALSE); X`09`09`7D X`09 else X`09`09`7B X`09`09/* X`09`09 * Move the mullion widget into oblivion X`09`09 */ X`09`09changes.x = changes.y = -99; X`09`09if (changes.x != subdata->mullion->core.x `7C`7C`20 X`09`09`09changes.y != subdata->mullion->core.y) X`09`09 `7B X`09`09 subdata->mullion->core.x = changes.x; X`09`09 subdata->mullion->core.y = changes.y; X`09`09 if (XtIsRealized(subdata->mullion)) X`09`09`09XConfigureWindow(XtDisplay(subdata->mullion),`20 X`09`09`09`09XtWindow(subdata->mullion), CWX `7C CWY, &changes); X`09`09 `7D X`09`09`7D X`09 `7D X `7D X/* X * Ok now you only have those children that are managed so fill the pane. X */ X TryToFillPane(pane); X CommitNewSizes(pane, (Widget) NULL); X`7D X`20 X`0C Xstatic void RememberFocus(w, unused_tag, cb) XWidget w; Xcaddr_t unused_tag; XDwtAnyCallbackStruct * cb; X`7B X DwtAnyCallbackStruct focus_cb; X PaneWidget pane = (PaneWidget) XtParent(w); X LastHadFocus(pane) = w; X`20 X focus_cb.reason = DwtCRFocus; X focus_cb.event = cb->event; X XtCallCallbacks ((Widget)pane, DwtNfocusCallback, cb); X`7D X`20 X`20 X`0C X/* X * A new subwidget has been added. X */ Xstatic DwtCallback focus_cb`5B2`5D = `7BRememberFocus, NULL, NULL`7D; X`20 Xstatic void InsertChild(subwidget) XWidget subwidget; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Widget cursubwidget; X Constraints subdata, cursubdata; X int i, position; X`20 X`20 X /* check for mullion class here since when we create the mullion this co Vde X * will get called again. Get the desired length from the actual length X * and then create a mullion for this widget. Finally position the widge Vt X * where the user wants it X */ X if (XtClass(subwidget) != mullionWidgetClass)`20 X`09`7B X`09subdata = (Constraints)subwidget->core.constraints; X`09subdata->dlength = Length(subwidget); X`09if (subdata->max == 0) X`09 subdata->max = resource_max; X`09if (subdata->min == 0) X`09 subdata->min = resource_min; X`09if (subdata->max < subdata->min)`20 X`09 subdata->max = subdata->min; X`20 X`09subdata->mullion = XtCreateWidget("mullion", (WidgetClass) mullionWidgetC Vlass, (Widget) pane, X`09`09`09`09 (ArgList) NULL, (Cardinal) 0); X`09XtManageChild(subdata->mullion); X`09if (subdata->position) X`09 `7B X`09 position = subdata->position + ((NumChildren(pane)+1)/2); X`09 if (position > (NumChildren(pane)+1)) X`09`09`7B X`09`09position = (NumChildren(pane)+1); X`09`09`7D X`09 `7D X`09else X`09 `7B X`09 position = (NumChildren(pane)+1);`20 X`09 `7D X`09subdata->position = position - ((NumChildren(pane)+1)/2);`20 X`09position--; X`09`7D`20 X else`20 X`09`7B X`09position = (NumChildren(pane)/2); X`09`7D X Children(pane) =`20 X (WidgetList) XtRealloc((caddr_t) Children(pane), X `09(unsigned) (NumChildren(pane) + 1) * sizeof(Widget)); X`20 X /* Ripple children up one space from "position" */ X for (i = NumChildren(pane); i > position; i--) X`09`7B X`09if (XtClass (Children(pane)`5Bi-1`5D) != mullionWidgetClass && X`09 XtClass (subwidget) != mullionWidgetClass) X`09 `7B X`09 cursubwidget = Children(pane)`5Bi-1`5D; X`09 cursubdata = (Constraints)cursubwidget->core.constraints; X`09 /*`20 X`09 * Check to see if the position of the current subwidget is less X`09 * than that of the subwidget we are creating. If it is then that X`09 * means there are other subwidgets below this one which are also X`09 * shared and I should exit at this point to store this new`20 X`09 * subwidget in the list of children. X`09 */ X`09 if (cursubdata->position < subdata->position) X`09`09`7B X`09`09break; X`09`09`7D X`09 else`20 X`09`09`7B X`09`09/* X`09`09 * Check to see if the position of the current subwidget and X`09`09 * the created subwidget are the same. If they are and`20 X`09`09 * the new one is shared, then set the old one to X`09`09 * shared as well. Also set the current subwidgets inview to X`09`09 * false if the subwidget will be in view. X`09`09 * X`09`09 * Otherwise, if the subwidget isn't shared the new one just`20 X`09`09 * wants the currents ones position so bump it up by one. X`09`09 */ X`09`09if ((cursubdata->position == subdata->position) &&`20 X`09`09`09(subdata->sharedflag & SharedPaneMask)) X`09`09 `7B X`09`09 if (subdata->sharedflag & ViewableInPaneMask)`20 X`09`09`09`7B X`09`09`09cursubdata->sharedflag = SharedPaneMask; X`09`09`09`7D X`09`09 else X`09`09`09`7B X`09`09`09/*`20 X`09`09`09 * Only set those that aren't shared. Those that are`20 X`09`09`09 * shared are already set and since the new one does X`09`09`09 * not want to be viewable we will just keep what we X`09`09`09 * have. X`09`09`09 */ X`09`09`09if (cursubdata->sharedflag == NoSharedPaneMask) X`09`09`09 `7B X`09`09`09 cursubdata->sharedflag = SharedPaneMask `7C ViewableInPaneMask; X`09`09`09 `7D X`09`09`09`7D X`09`09 `7D X`09`09else if (subdata->sharedflag == NoSharedPaneMask) X`09`09 `7B X`09`09 cursubdata->position++; X`09`09 `7D X`09`09`7D /* end else */ X`09 `7D /* end if */ X Children(pane)`5Bi`5D = Children(pane)`5Bi-1`5D; X`09`7D X Children(pane)`5Bi`5D = subwidget; X NumChildren(pane)++; X PaneChildren(pane) = (WidgetList) X`09XtRealloc((char *)PaneChildren(pane), X`09`09 (Cardinal) NumChildren(pane) * sizeof(Widget)); X`20 X /* this allows text widgets tabs to work like normal`20 X */ X if (OverrideText(pane) && XtIsSubclass(subwidget, textwidgetclass))`20 X`09`7B X`09XtOverrideTranslations(subwidget, compiledtextbindings); X`09if (LastHadFocus(pane) == NULL) X`09 LastHadFocus(pane) = subwidget; X`09`7D X if (XtHasCallbacks(subwidget, DwtNfocusCallback) != XtCallbackNoList) X`09XtAddCallbacks(subwidget, DwtNfocusCallback, focus_cb); X`7D X `20 X`20 X`0C X/* X * A subwidget has been removed. X */ X`20 Xstatic void DeleteChild(subwidget)`20 XWidget subwidget; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints subdata; X int i, position; X`20 X/* X * Destroy will destroy mullion and the child. If it is a mullion being`20 X * deleted skip the stuff about subdata and shared position. X */ X if (XtClass(subwidget) != mullionWidgetClass)`20 X`09`7B X`09subdata = DataFromWidget(subwidget); X /*`20 X * destory the mullion`20 X */ X`09XtDestroyWidget (subdata->mullion); X`09`7D X/* X * Ok now we need to remove this widget from the composite list`20 X */ X for (position = 0; position < NumChildren(pane); position++)`20 X`09`7B X if (Children(pane) `5Bposition`5D == subwidget)`20 X`09 `7B X break; X`09 `7D X`09`7D X`20 X if (position == NumChildren(pane)) return; X`20 X /* Ripple children down one space from "position" */ X NumChildren(pane)--; X for (i = position; i < NumChildren(pane); i++)`20 X`09`7B X Children(pane) `5Bi`5D = Children(pane) `5Bi+1`5D; X`09`7D X`7D`20 X`20 X`20 X`0C X/*---------------------------------------------------*/ X/* this routine will be called from the widget's */ X/* main event handler via the translation manager. */ X/*---------------------------------------------------*/ X`20 Xstatic void Help(w, event) XWidget w; XXEvent *event; X`7B X DwtAnyCallbackStruct temp; X`20 X temp.reason = DwtCRHelpRequested; X temp.event = event; X`20 X if (XtClass(w) == (WidgetClass) panewidgetclass) X`09`7B X `09XtCallCallbacks(w, DwtNhelpCallback, &temp); X`09`7D X else X`09`7B X`09XtCallCallbacks(XtParent(w), DwtNhelpCallback, &temp); X`09`7D; X`7D X`20 X`0C X/* X ************************************************************************* X * X * Public creation entry points X * X ************************************************************************* X */ X/* X * low level create entry point X */ X`20 XWidget DwtPaneCreate (p, name, al, ac) X Widget p;`09`09`09`09/* parent widget */ X char *name;`09`09`09/* pane widget name */ X ArgList al; X Cardinal ac; `20 X`7B X return XtCreateWidget(name, (WidgetClass) panewidgetclass, p, al, ac); X`7D X`20 X#ifdef VMS XWidget DWT$PANE_CREATE (p, name$dsc, al, ac) X Widget`09`09`09*p;`09`09/* parent widget */ X struct dsc$descriptor_s `09*name$dsc; X ArgList`09`09`09al; X int`09`09`09`09*ac; `20 X`7B X PaneWidget pane; X char *name; X`20 X name = DwtDescToNull(name$dsc); `20 X pane = (PaneWidget) XtCreateWidget(name, (WidgetClass) panewidgetclass, V *p, al, *ac); X`20 X XtFree(name); X return (Widget) pane; X`7D X#endif /* VMS */`20 X`0C `20 X/* X * high level pane create routine X */ X`20 XWidget DwtHVPane(p,`20 X`09 name,`20 X`09 x, y,`20 X`09 width, height, X`09 orientation, X`09 mapcallback, helpcallback) X`20 X Widget p;`09`09`09`09/* parent widget */ X char *name;`09`09`09/* pane widget name */ X Position`09 x, y;`09`09`09/* location of pane widget */ X Dimension`09 width, height;`09`09/* size of pane widget */ X int`09`09 orientation;`09`09`09/* horizontal or vertical X DwtCallbackPtr mapcallback;`09`09`09/* callback for data struct */ X DwtCallbackPtr helpcallback;`09`09/* help requested */ X`7B X Arg al`5B25`5D; X Cardinal ac = 0; X`20 X /* X * set up the parameters we are given X */ X`20 X XtSetArg (al`5Bac`5D, XtNname,`09`09name);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNx,`09`09x);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNy,`09`09y);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNwidth,`09`09width);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNheight,`09height);`09ac++; X XtSetArg (al`5Bac`5D, DwtNorientation,`09orientation);`09ac++; X`20 X`20 X if (mapcallback != NULL)`20 X`09`7B X`09XtSetArg (al`5Bac`5D, DwtNmapCallback, mapcallback); X`09ac++; X`09`7D X`20 X if (helpcallback != NULL)`20 X`09`7B X`09XtSetArg (al`5Bac`5D, DwtNhelpCallback, helpcallback); X`09ac++; X`09`7D X`20 X return XtCreateWidget (name, (WidgetClass) panewidgetclass, p, al, ac); X`7D X X#ifdef VMS`20 XWidget DWT$H_V_PANE(p,`20 X`09 name$dsc,`20 X`09 x, y,`20 X`09 width, height, X`09 orientation, X`09 mapcallback, helpcallback) X`20 X Widget *p;`09`09`09`09/* parent widget */ X struct dsc$descriptor_s `09*name$dsc;`09/* form widget name */ X Position`09 *x, *y;`09`09`09/* location of form widget */ X Dimension`09 *width, *height;`09`09/* size of the widget */ X int`09`09 *orientation;`09`09`09/* pane orientation */ X DwtCallbackPtr *mapcallback;`09`09/* callback */ X DwtCallbackPtr *helpcallback;`09`09/* help requested */ X`7B X PaneWidget pane; X Arg al`5B25`5D; X int ac = 0; X char *name; X`20 X name = DwtDescToNull(name$dsc); X /* X * set up the parameters we are given X */ X`20 X XtSetArg (al`5Bac`5D, XtNname,`09 name);`09 ac++; X XtSetArg (al`5Bac`5D, XtNname,`09`09name);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNx,`09`09x);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNy,`09`09y);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNwidth,`09`09width);`09`09ac++; X XtSetArg (al`5Bac`5D, XtNheight,`09height);`09ac++; X XtSetArg (al`5Bac`5D, DwtNorientation,`09orientation);`09ac++; X`20 X`20 X if (mapcallback != NULL)`20 X`09`7B X`09XtSetArg (al`5Bac`5D, DwtNmapCallback, mapcallback); X`09ac++; X`09`7D X`20 X if (helpcallback != NULL)`20 X`09`7B X`09XtSetArg (al`5Bac`5D, DwtNhelpCallback, helpcallback); X`09ac++; X`09`7D X`20 X pane = (PaneWidget)XtCreateWidget (name, (WidgetClass) panewidgetclass, V *p, al, ac); X`20 X XtFree(name); X return (Widget) pane; X`7D X#endif /* VMS */`20 X`0C `20 X/* X * high level pane add widget routine X */ X`20 Xvoid DwtPaneAddWidget(subwidget, position, min, max, resizable, sharedflag) X Widget`09subwidget; X Cardinal`09position; X Dimension`09min, max; X Boolean`09resizable; X Cardinal`09sharedflag; X`7B X XWindowChanges changes; X PaneWidget`09pane = (PaneWidget) subwidget->core.parent; X Widget`09cursubwidget; X Constraints subdata, cursubdata, cursubdata2; X int`09`09i, curpos, lastsharedposition; X Boolean`09subnotfound=TRUE, subnotplaced=TRUE, cursubnotreset=TRUE; X`20 X/* X * Get the position the window is currently in X */ X subdata = DataFromWidget(subwidget); X curpos = subdata->position; X`20 X/* X * Compare that to the position the user desires and change the windows arou Vnd X */ X if (position > (NumChildren(pane)/2)) X`09position = (NumChildren(pane)/2); X if (position != curpos && position != 0) X`09`7B X`09if (position < curpos) X`09 `7B X`09 for (i = NumChildren(pane); i >= position*2; i--) X`09`09`7B X`09`09cursubwidget = Children(pane)`5Bi-1`5D; X`09`09cursubdata = DataFromWidget(cursubwidget); X`09`09/*`20 X`09`09 * Check to see if the position of the current subwidget is less X`09`09 * than that of the subwidget. If it is then that X`09`09 * means there are other subwidgets below this one which are also X`09`09 * shared and I should exit at this point to store this new`20 X`09`09 * subwidget in the list of children. X`09`09 */ X`09`09if (cursubdata->position < position) X`09`09 `7B X`09`09 Children(pane)`5Bi`5D = subwidget; X`09`09 subdata->position = position; X`09`09 break; X`09`09 `7D X`09`09/* X`09`09 * if subwidget came from a shared position we need to make`20 X`09`09 * sure that at least one of the old widgets that shared the`20 X`09`09 * position will now be displayed X`09`09 */ X`09`09if (cursubdata->position == subdata->position &&`20 X`09`09`09subdata->sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 if (cursubnotreset) X`09`09`09`7B X`09`09`09cursubdata->sharedflag = SharedPaneMask `7C ViewableInPaneMask; X`09`09`09cursubnotreset = FALSE; X`09`09`09`7D X`09`09 `7D X`09`09/* X`09`09 * move the subwidgets up one unless`20 X`09`09 * the current subwidget is subwidget we are trying to change or X`09`09 * the current subs position > the current position or X`09`09 */ X`09`09if (cursubwidget == subwidget `7C`7C subnotfound) X`09`09 `7B X`09`09 if (cursubwidget == subwidget) X`09`09`09`7B X`09`09`09subnotfound = FALSE; X`09`09`09continue; X`09`09`09`7D X`09`09 `7D X`09`09else X`09`09 `7B X`09`09 Children(pane)`5Bi`5D = Children(pane)`5Bi-1`5D; X`09`09 `7D X`09`09/* X`09`09 * Reposition the current subwidgets position as appropriate X`09`09 */ X`09`09if (subnotfound) X`09`09 `7B X`09`09 /* X`09`09 * This is a little tricky here. This will before you find X`09`09 * the subwidget. If the subwidget was not formerly`20 X`09`09 * shared and is not to be shared `7C`7C the subwidget was formerl Vy X`09`09 * shared and will be shared at its new position we will not X`09`09 * change the position. For the other two conditions we do. X`09`09 * In one case it is necessary to subtract and the other add X`09`09 * to the position X`09`09 */ X`09`09 if ((subdata->sharedflag == NoSharedPaneMask) && X`09`09`09(sharedflag & SharedPaneMask)) X`09`09`09 cursubdata->position--; X`09`09 else if ((subdata->sharedflag & SharedPaneMask) && X`09`09`09(sharedflag == NoSharedPaneMask)) X`09`09`09 cursubdata->position++; X`09`09 `7D X`09`09else X`09`09 `7B X`09`09 /* X`09`09 * Only change the position if our subwidget wont be shared. X`09`09 * Otherwise the position will still be occupied. X`09`09 */ X`09`09 if (sharedflag == NoSharedPaneMask) X`09`09`09cursubdata->position++; X`09`09 `7D X`09`09/* X`09`09 * Check to see if the position of the current subwidget and X`09`09 * the subwidget's new position are the same. If they are and`20 X`09`09 * the new one is shared, then set the old one to X`09`09 * shared as well. Also set the current subwidgets inview to X`09`09 * false if the subwidget will be in view. X`09`09 * X`09`09 * Otherwise, if the subwidget isn't shared the new one just`20 X`09`09 * wants the currents ones position so bump it up by one. X`09`09 */ X`09`09if(cursubdata->position == position &&`20 X`09`09`09sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 if (sharedflag & ViewableInPaneMask)`20 X`09`09`09`7B X`09`09`09cursubdata->sharedflag = SharedPaneMask; X`09`09`09`7D X`09`09 else X`09`09`09`7B X`09`09`09/*`20 X`09`09`09 * Only set those that aren't shared. Those that are`20 X`09`09`09 * shared are already set and since the new one does X`09`09`09 * not want to be viewable we will just keep what we X`09`09`09 * have. X`09`09`09 */ X`09`09`09if (cursubdata->sharedflag == NoSharedPaneMask) X`09`09`09 `7B X`09`09`09 cursubdata->sharedflag = SharedPaneMask `7C ViewableInPaneMask; X`09`09`09 `7D X`09`09`09`7D X`09`09 `7D X`09`09`7D /* end for loop */ X`09 `7D X`09else`09/* position > curpos */ X`09 `7B X`09 for (i = (NumChildren(pane)/2)+curpos; i <= NumChildren(pane); i++) X`09`09`7B X`09`09cursubwidget = Children(pane)`5Bi-1`5D; X`09`09cursubdata = DataFromWidget(cursubwidget); X`09`09/* X`09`09 * Even though you start at the current position it is possible X`09`09 * for the position to be less than the current position due to X`09`09 * shared panes. X`09`09 */ X`09`09if (cursubdata->position < curpos `7C`7C cursubwidget == subwidget X`09`09 `7C`7C (subnotfound)) X`09`09 `7B X`09`09 if (cursubwidget == subwidget) X`09`09`09 subnotfound = FALSE; X`09`09 continue; X`09`09 `7D X`09`09/* X`09`09 * if subwidget came from a shared position we need to make`20 X`09`09 * sure that at least one of the old widgets that shared the`20 X`09`09 * position will now be displayed X`09`09 */ X`09`09if (cursubdata->position == subdata->position &&`20 X`09`09`09subdata->sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 if (cursubnotreset) X`09`09`09`7B X`09`09`09cursubdata->sharedflag = SharedPaneMask `7C ViewableInPaneMask; X`09`09`09cursubnotreset = FALSE; X`09`09`09`7D X`09`09 `7D X`09`09/* X`09`09 * move the subwidgets up one unless`20 X`09`09 * the current subwidget is subwidget we are trying to change or X`09`09 * the current subs position > the desired position or X`09`09 * the current subs position = the desired postion and the sub X`09`09 * we were working with was previously shared. X`09`09 */ X`09`09if (cursubdata->position > position `7C`7C X`09`09 ((subdata->sharedflag & SharedPaneMask) &&`20 X`09`09 cursubdata->position == position)) X`09`09 `7B X`09`09 /*`20 X`09`09 * Place subwidget only once after you moved all subs X`09`09 */ X`09`09 if (subnotplaced) X`09`09`09`7B X`09`09`09Children(pane)`5Bi-2`5D = subwidget; X`09`09`09subdata->position = position; X`09`09`09subnotplaced=FALSE; X`09`09`09`7D X`09`09 `7D X`09`09else X`09`09 `7B X`09`09 Children(pane)`5Bi-2`5D = Children(pane)`5Bi-1`5D; X`09`09 `7D X`09`09/* X`09`09 * Reposition the current subwidgets position as appropriate X`09`09 */ X`09`09if (subnotplaced) X`09`09 `7B X`09`09 /* X`09`09 * Only change the position if our subwidget wasn't shared. X`09`09 * Otherwise the position will still be occupied. X`09`09 */ X`09`09 if (subdata->sharedflag == NoSharedPaneMask) X`09`09`09cursubdata->position--; X`09`09 `7D X`09`09else X`09`09 `7B X`09`09 /* X`09`09 * This is a little tricky here. This will happen after you X`09`09 * placed the subwidget. If the subwidget was not formerly`20 X`09`09 * shared and is not to be shared `7C`7C the subwidget was formerl Vy X`09`09 * shared and will be shared at its new position we will not X`09`09 * change the position. For the other two conditions we do. X`09`09 * In one case it is necessary to subtract and the other add X`09`09 * to the position X`09`09 */ X`09`09 if ((subdata->sharedflag == NoSharedPaneMask) && X`09`09`09(sharedflag & SharedPaneMask)) X`09`09`09 cursubdata->position--; X`09`09 else if ((subdata->sharedflag & SharedPaneMask) && X`09`09`09(sharedflag == NoSharedPaneMask)) X`09`09`09 cursubdata->position++; X`09`09 `7D X`09`09/* X`09`09 * Check to see if the position of the current subwidget and X`09`09 * the subwidget's new position are the same. If they are and`20 X`09`09 * the new one is shared, then set the old one to X`09`09 * shared as well. Also set the current subwidgets inview to X`09`09 * false if the subwidget will be in view. X`09`09 * X`09`09 * Otherwise, if the subwidget isn't shared the new one just`20 X`09`09 * wants the currents ones position so bump it up by one. X`09`09 */ X`09`09if(cursubdata->position == position &&`20 X`09`09`09sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 if (sharedflag & ViewableInPaneMask)`20 X`09`09`09`7B X`09`09`09cursubdata->sharedflag = SharedPaneMask; X`09`09`09`7D X`09`09 else X`09`09`09`7B X`09`09`09/*`20 X`09`09`09 * Only set those that aren't shared. Those that are`20 X`09`09`09 * shared are already set and since the new one does X`09`09`09 * not want to be viewable we will just keep what we X`09`09`09 * have. X`09`09`09 */ X`09`09`09if (cursubdata->sharedflag == NoSharedPaneMask) X`09`09`09 `7B X`09`09`09 cursubdata->sharedflag = SharedPaneMask `7C ViewableInPaneMask; X`09`09`09 `7D X`09`09`09`7D X`09`09 `7D X`09`09`7D /* end for loop */ X`09 `7D`09`09`09 `20 X`09/* X`09 * Now that the position has been properly set we can take care of`20 X`09 * the shared flag.`20 X`09 */ X`09subdata->sharedflag = sharedflag; X`09/* X`09 * Just for grins lets loop back through and make sure that if a`20 X`09 * subwidget says that it is shared it really is. X`09 */ X`09for (i=NumChildren(pane)/2; isharedflag & SharedPaneMask) X`09`09`7B X`09`09if (i+1 != NumChildren(pane))`09/* Dont check passed bountry */ X`09`09 `7B X`09`09 cursubdata2 = DataFromWidget(Children(pane)`5Bi+1`5D); X`09`09 if (cursubdata->position == cursubdata2->position) X`09`09`09lastsharedposition = cursubdata->position; X`09`09 `7D X`09`09if (lastsharedposition != cursubdata->position) X`09`09 `7B X`09`09 cursubdata->sharedflag = NoSharedPaneMask; X`09`09 XtSetMappedWhenManaged (cursubwidget, TRUE); X`09`09 `7D X`09`09`7D X`09 `7D X`09`7D X else X`09`7B X`09/* X`09 * There was no change in position so if the user wants this subwidget X`09 * to be viewable lets do it for him. X`09 */ X`09if (sharedflag & ViewableInPaneMask) X`09 DwtPaneMakeViewable (subwidget); X`09`7D X`20 X subdata->resizable = resizable; X if (max == 0) X`09max = resource_max; X if (min == 0) X`09min = resource_min; X if (max < min)`20 X`09max = min; X if (subdata->resizable) X`09`7B X`09subdata->min = min; X`09subdata->max = max; X`09`7D X if (subwidget->core.managed) X`09`7B X`09PaneNumChildren(pane) = 0; X`09for (i=NumChildren(pane)/2; icore.managed &&`20 X`09`09 (cursubdata->sharedflag == NoSharedPaneMask `7C`7C X`09`09 cursubdata->sharedflag == (SharedPaneMask `7C ViewableInPaneMask)) V) X`09`09`7B X`09`09if (cursubdata->sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 XtSetMappedWhenManaged (cursubwidget, TRUE); X`09`09 `7D X`09`09PaneChildren(pane)`5B(PaneNumChildren(pane))++`5D = cursubwidget; X`09`09`7D X`09 else X`09`09`7B X`09`09/* X`09`09 * UnMap any shared panes that aren't used X`09`09 */ X`09`09if (cursubdata->sharedflag & SharedPaneMask) X`09`09 `7B X`09`09 XtSetMappedWhenManaged (cursubwidget, FALSE); X`09`09 XtSetMappedWhenManaged (cursubdata->mullion, FALSE); X`09`09 `7D X`09`09else X`09`09 `7B X`09`09 /* X`09`09 * Move the mullion widget into oblivion X`09`09 */ X`09`09 changes.x = changes.y = -99; X`09`09 if (changes.x != cursubdata->mullion->core.x `7C`7C`20 X`09`09`09 changes.y != cursubdata->mullion->core.y) X`09`09`09`7B X`09`09`09cursubdata->mullion->core.x = changes.x; X`09`09`09cursubdata->mullion->core.y = changes.y; X`09`09`09if (XtIsRealized(cursubdata->mullion)) X`09`09`09 XConfigureWindow(XtDisplay(cursubdata->mullion),`20 X`09`09`09`09 XtWindow(cursubdata->mullion), CWX `7C CWY, &changes); X`09`09`09`7D X`09`09 `7D X`09`09`7D X`09 `7D /* end for loop */ X`09`7D /* end if subwidget is managed */ X /* X * Ok now you only have those children that are managed so fill the pane V. X */ X/* X * Check to see if the dlength for the subwidget is greater than the max. If V it X * is then I must call RefigureDlengths instead of TryToFillPane. TryToFillP Vane X * will use the current length which hasn't been change so it will pass a de Vlta X * change to RefigureDlengths of 0 which does zippo. Since I know the amount V I X * need to change I'll just call RefigureDlengths directly. X */ X`09if (subdata->dlength > subdata->max) X`09 `7B X`09 RefigureDlengths (pane, subwidget, subdata->dlength - subdata->max); X`09 `7D X`09else if (subdata->dlength < subdata->min) X`09 `7B X`09 RefigureDlengths (pane, subwidget, subdata->dlength - subdata->min); X`09 `7D X`09else X`09 `7B X`09 TryToFillPane(pane); X`09 `7D X`09CommitNewSizes(pane, (Widget) NULL); X`7D X X#ifdef VMS`20 Xvoid DWT$PANE_ADD_WIDGET(subwidget,`20 X`09 position, X`09 min, max,`20 X`09 resizable, X`09 sharedflag) X`20 X Widget *subwidget;`09`09`09/* widget */ X Cardinal`09 *position;`09`09`09/* position of the subwidget */ X Dimension`09 *min, *max;`09`09`09/* min & max size of the widget */ X Boolean`09 *resizable;`09`09`09/* is the widget resizeable */ X Cardinal`09 *sharedflag;`09`09`09/* shared flag */ X`7B X DwtPaneAddWidget (*subwidget,*position,*min,*max,*resizable,*sharedflag) V; X`7D X#endif /* VMS */`20 X`20 Xvoid DwtPaneGetMinMax(subwidget, min, max) XWidget subwidget; XDimension *min, *max; X`7B X Constraints subdata; X subdata = DataFromWidget(subwidget); X if (subdata) `7B X`09*min = subdata->min; X`09*max = subdata->max; X `7D else X`09XtWarning("DwtPaneGetMinMax called with bad widget."); X`7D X X#ifdef VMS`20 Xvoid DWT$PANE_GET_MIN_MAX(subwidget,`20 X`09 min, max) X Widget subwidget;`09`09`09/* widget */ X Dimension`09 *min, *max;`09`09`09/* min & max size of the widget */ X`7B X Constraints subdata; X subdata = DataFromWidget(subwidget); X if (subdata) `7B X`09*min = subdata->min; X`09*max = subdata->max; X `7D else X`09XtWarning("DwtPaneGetMinMax called with bad widget."); X`7D X#endif /* VMS */`20 X`20 X`0C X/* X * NOTE: In setting the min or max in DwtPaneSetMinMax, DwtPaneSetMin, or X *`09DwtPaneSetMax we donot check for valid min, max values. Values less X *`09than 1 will certianly cause stack dumps and min > max will also`20 X *`09cause some form of headache, though I haven't tried it yet. Most X *`09DW code doesn't check for valid attributes so I see no reason to X *`09do so here either. X */ X`20 Xvoid DwtPaneSetMinMax(subwidget, min, max) XWidget subwidget; XDimension min, max; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints subdata; X`20 X if (max == 0) X`09max = resource_max; X if (min == 0) X`09min = resource_min; X if (max < min)`20 X`09max = min; X subdata = DataFromWidget(subwidget); X if (subdata->resizable) X`09`7B X`09subdata->min = min; X`09subdata->max = max; X`09`7D X X if (subdata->sharedflag & SharedPaneMask) X`09`7B X`09Widget subwidget2; X`09Constraints subdata2; X`09int i, visable_child=NULL; X X`09for (i=(NumChildren(pane)+1)/2 ; iposition != subdata->position) `7C`7C X`09`09(subwidget2 == subwidget)) X`09`09`7B X`09`09continue; X`09`09`7D; X`09 subdata2->min = subdata->min; X`09 subdata2->max = subdata->max; X`09 if (subdata2->sharedflag & ViewableInPaneMask) X`09`09`7B X`09`09visable_child = i; X`09`09`7D X`09 `7D X`09if (visable_child != NULL) X`09 `7B X`09 subwidget = Children(pane)`5Bvisable_child`5D; X`09 subdata = DataFromWidget(subwidget); X`09 `7D X`09`7D X /* only try to fill pane and commit sizes if we really need to X */ X if (subdata->dlength < subdata->min `7C`7C subdata->dlength > subdata->m Vax) X`09`7B X/* X * Check to see if the dlength for the subwidget is greater than the max. If V it X * is then I must call RefigureDlengths instead of TryToFillPane. TryToFillP Vane X * will use the current length which hasn't been change so it will pass a de Vlta X * change to RefigureDlengths of 0 which does zippo. Since I know the amount V I X * need to change I'll just call RefigureDlengths directly. X */ X`09if (subdata->dlength > subdata->max) X`09 `7B X`09 RefigureDlengths (pane, subwidget, subdata->dlength - subdata->max); X`09 `7D X`09else if (subdata->dlength < subdata->min) X`09 `7B X`09 RefigureDlengths (pane, subwidget, subdata->dlength - subdata->min); X`09 `7D X`09else X`09 `7B X`09 TryToFillPane(pane); X`09 `7D X`09CommitNewSizes(pane, (Widget) NULL); X`09`7D X`7D X`20 X#ifdef VMS Xvoid DWT$PANE_SET_MIN_MAX(subwidget,`20 X`09 min, max) X Widget *subwidget;`09`09`09/* widget */ X Dimension`09 *min, *max;`09`09`09/* min & max size of the widget */ X`7B X DwtPaneSetMinMax(*subwidget,*min,*max); X`7D X#endif /* VMS */`20 X`0C Xvoid DwtPaneSetMin(subwidget, min) XWidget subwidget; XDimension min; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints subdata; X if (min == 0) X`09min = resource_min; X subdata = DataFromWidget(subwidget); X if (subdata->resizable) X`09`7B X`09subdata->min = min; X`09if (subdata->max < subdata->min) X`09 subdata->max = subdata->min; X`09`7D X X if (subdata->sharedflag & SharedPaneMask) X`09`7B X`09Widget subwidget2; X`09Constraints subdata2; X`09int i, visable_child=NULL; X X`09for (i=(NumChildren(pane)+1)/2 ; iposition != subdata->position) `7C`7C X`09`09(subwidget2 == subwidget)) X`09`09`7B X`09`09continue; X`09`09`7D; X`09 subdata2->min = subdata->min; X`09 if (subdata2->sharedflag & ViewableInPaneMask) X`09`09`7B X`09`09visable_child = i; X`09`09`7D X`09 `7D X`09if (visable_child != NULL) X`09 `7B X`09 subwidget = Children(pane)`5Bvisable_child`5D; X`09 subdata = DataFromWidget(subwidget); X`09 `7D X`09`7D X X if (subdata->dlength < subdata->min) X`09`7B X`09RefigureDlengths (pane, subwidget, subdata->dlength - subdata->min); X`09CommitNewSizes(pane, (Widget) NULL); X`09`7D X`7D X`20 X#ifdef VMS Xvoid DWT$PANE_SET_MIN(subwidget, min) X Widget *subwidget;`09`09`09/* widget */ X Dimension`09 *min;`09`09`09`09/* min size of the widget */ X`7B X DwtPaneSetMin(*subwidget,*min); X`7D X#endif /* VMS */`20 X`0C Xvoid DwtPaneSetMax(subwidget, max) XWidget subwidget; XDimension max; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints subdata; X if (max == 0) X`09max = resource_max; X subdata = DataFromWidget(subwidget); X if (max < subdata->min)`20 X`09max = subdata->min; X if (subdata->resizable) X`09`7B X`09subdata->max = max; X`09`7D X if (subdata->sharedflag & SharedPaneMask) X`09`7B X`09Widget subwidget2; X`09Constraints subdata2; X`09int i, visable_child=NULL; X X`09for (i=(NumChildren(pane)+1)/2 ; iposition != subdata->position) `7C`7C X`09`09(subwidget2 == subwidget)) X`09`09`7B X`09`09continue; X`09`09`7D; X`09 subdata2->max = subdata->max; X`09 if (subdata2->sharedflag & ViewableInPaneMask) X`09`09`7B X`09`09visable_child = i; X`09`09`7D X`09 `7D X`09if (visable_child != NULL) X`09 `7B X`09 subwidget = Children(pane)`5Bvisable_child`5D; X`09 subdata = DataFromWidget(subwidget); X`09 `7D X`09`7D X if (subdata->dlength > subdata->max) X`09`7B X`09RefigureDlengths (pane, subwidget, subdata->dlength - subdata->max); X`09CommitNewSizes(pane, (Widget) NULL); X`09`7D X`7D X`20 X#ifdef VMS Xvoid DWT$PANE_SET_MAX(subwidget, max) X Widget *subwidget;`09`09`09/* widget */ X Dimension`09 *max;`09`09`09`09/* max size of the widget */ X`7B X DwtPaneSetMax(*subwidget,*max); X`7D X#endif /* VMS */`20 X`0C X/* this needs to be incorporated into set values */ Xvoid DwtPaneAllowResizing(pane, allowtype) XPaneWidget pane; Xint allowtype; X`7B X ResizeMode(pane) = allowtype; X if (!allowtype) TryToFillPane(pane); X`7D X`20 X`20 X`0C Xvoid DwtPaneMakeViewable(subwidget) XWidget subwidget; X`7B X PaneWidget pane = (PaneWidget) subwidget->core.parent; X Constraints cursubdata, subdata; X Widget cursubwidget, curmullion, mullion; X XWindowChanges changes; X int`09viewable, notviewable, position; X`20 X/* X * The current subwidget is the one occuppying the same position in the`20 X * PaneChildren Widget list. If not then we need to go down the list till we X * find the one that is sharing this position X */ X subdata = DataFromWidget(subwidget); X for (position = subdata->position; position > 0; position--) X`09`7B X`09cursubwidget = PaneChildren(pane)`5Bposition - 1`5D; X`09cursubdata = DataFromWidget(cursubwidget); X`09if (cursubdata->position == subdata->position) X`09 break; X`09`7D; X`20 X/* X * If this subwidget is the one currently displayed or is not in a shared pa Vne X * or it is not managed then don't bother doing any of this work. X */ X if (subwidget == cursubwidget `7C`7C !subwidget->core.managed `7C`7C`20 X`09 subdata->sharedflag == NoSharedPaneMask) X`09return; X`20 X viewable = SharedPaneMask `7C ViewableInPaneMask; X notviewable = SharedPaneMask; X`20 X/* X * Get the subdata of widget currently viewable and set the mullions X */ X curmullion = cursubdata->mullion; X mullion = subdata->mullion; X`20 X`20 X/* X * Set the changes based on the current widget attributes X */ X changes.x = cursubwidget->core.x; X changes.y = cursubwidget->core.y; X changes.width = cursubwidget->core.width; X changes.height = cursubwidget->core.height; X changes.border_width = 0; X if (changes.x != subwidget->core.x `7C`7C changes.y != subwidget->core.y V `7C`7C X`09 changes.width != subwidget->core.width `7C`7C X`09 changes.height != subwidget->core.height `7C`7C X`09 changes.border_width != subwidget->core.border_width)`20 X`09`7B X`09subwidget->core.x = changes.x; X`09subwidget->core.y = changes.y; X`09subwidget->core.width = changes.width; X`09subwidget->core.height = changes.height; X`09subwidget->core.border_width = changes.border_width; X`09if (XtIsRealized(subwidget)) `20 X`09 `7B X`09 XConfigureWindow(XtDisplay(subwidget), XtWindow(subwidget), X`09`09`09 CWX `7CCWY `7C CWWidth `7C CWHeight `7C CWBorderWidth, X`09`09`09 &changes); X`09 `7D X`09if (XtClass(subwidget)->core_class.resize != (XtWidgetProc) NULL) X`09 `7B X`09 (*(subwidget->core.widget_class->core_class.resize))(subwidget); X`09 `7D X`09`7D X`20 X/* X * Set the current widgets and subwidget's shared pane attributes X */ X cursubdata->sharedflag = notviewable; X subdata->sharedflag = viewable; X X/* X * Set the min and the max values based on the currently visable widget X */ X subdata->min = cursubdata->min; X subdata->max = cursubdata->max; X`20 X/* X * Unmap the current widget and map the subwidget by setting mapped_when_man Vaged X */ X XtSetMappedWhenManaged (subwidget, TRUE); X XtSetMappedWhenManaged (cursubwidget, FALSE); X`20 X/* X * If the cursubwidget was the last to have focus change it to the subwidget X */ X if (LastHadFocus(pane) == cursubwidget) X`09LastHadFocus(pane) = subwidget; X`20 X/* X * Set the changes based on the current mullions attributes X */ X changes.x = curmullion->core.x; X changes.y = curmullion->core.y; X if (changes.x != mullion->core.x `7C`7C changes.y != mullion->core.y)`20 X`09`7B X`09mullion->core.x = changes.x; X`09mullion->core.y = changes.y; X`09if (XtIsRealized(subwidget)) `20 X`09 `7B X`09 XConfigureWindow(XtDisplay(mullion), XtWindow(mullion), X`09`09`09 CWX `7C CWY, &changes); X`09 `7D X`09`7D X/* X * Unmap the current widget and map the subwidget by setting mapped_when_man Vaged X */ X XtSetMappedWhenManaged (mullion, TRUE); X XtSetMappedWhenManaged (curmullion, FALSE); X`20 X PaneChildren(pane)`5Bposition - 1`5D = subwidget; X `20 X`7D X`20 X#ifdef VMS Xvoid DWT$PANE_MAKE_VIEWABLE(subwidget) X Widget *subwidget;`09`09`09/* widget */ X`7B X DwtPaneMakeViewable(*subwidget); X`7D X#endif /* VMS */`20 X`0C Xunsigned int PaneInitializeForDRM () X`7B Xint`09stat; X`20 X/* Initialize DRM V */ X/* This MUST be done before the XtInitialize call... V */ X/* V `20 V */ XDwtInitializeDRM (); X`20 Xstat = DwtRegisterClass (DRMwcUnknown, "pane_widget", X`09"DwtPaneCreate", DwtPaneCreate, panewidgetclass); X`20 Xif (stat != DRMSuccess) X`09`7B X`09printf ("pane widget registration failed\n"); X`09return stat; X`09`7D; X`20 Xreturn stat; X`7D X`0C X#define AcceptFocusProc(w) ((w)->core.widget_class->core_class.accept_focus) Xstatic Boolean AcceptFocus(w, time) XWidget w; XTime *time; X`7B X PaneWidget pane = (PaneWidget) w; X int i; X Boolean took_focus; X X if (LastHadFocus(pane) == NULL) `7B X`09for (i=0 ; X`09 i=0 ; j--) `7B X`09if (AcceptFocusProc(PaneChildren(pane)`5Bj`5D) != NULL) `7B X`09 LastHadFocus(pane) = PaneChildren(pane)`5Bj`5D; X`09 AcceptFocus(XtParent(w), &time); X`09 return; X`09`7D X `7D X`7D X`20 X/* DEC/CMS REPLACEMENT HISTORY, Element PANE.C */ X/* *3 30-AUG-1989 15:59:18 BRINKLEY "const removed" */ X/* *2 29-AUG-1989 16:42:50 BRINKLEY "bug fixed" */ X/* *1 22-AUG-1989 16:55:37 RYAN "Initial elements for V3" */ X/* DEC/CMS REPLACEMENT HISTORY, Element PANE.C */ $ CALL UNPACK PANE.C;1 1176557696 $ create 'f' X/* X* $Header: Pane.h,v 1.4 88/02/26 13:50:51 weissman Exp $ X*/ X X/* X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. X *`20 X * All Rights Reserved X *`20 X * Permission to use, copy, modify, and distribute this software and its`20 X * documentation for any purpose and without fee is hereby granted,`20 X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in`20 X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. V `20 X *`20 X *`20 X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X/* X * V1.0a 17-Mar-1988`09RDB X *`09fix major bugs and enhancements X * V1.4`09 03-Nov-1988`09RDB X *`09updates and revisions X * V2.0`09 04-Apr-1989`09RDB X *`09updates and revisions X * V2.1`09 11-Apr-1989`09RDB X *`09add leftmullion X */ X X#ifndef _DwtPane_h X#define _DwtPane_h X X#define NoSharedPaneMask`090L X#define`09SharedPaneMask`09`09(1L<<0) X#define`09ViewableInPaneMask`09(1L<<1) X X/*********************************************************************** X * X * Pane Widget (subclass of CompositeClass) X * X ***********************************************************************/ X X/* New fields */ X#define DwtNmullionSize`09`09"mullionSize" X#define DwtNmin`09`09`09"min" X#define DwtNmax`09`09`09"max" X#define DwtNoverrideText`09"overrideText" X#define DwtNposition`09`09"position" X#define DwtNsharedFlag`09`09"sharedFlag" X X#define DwtCMullionSize`09`09"MullionSize" X#define DwtCMin`09`09`09"Min" X#define DwtCMax`09`09`09"Max" X#define DwtCOverrideText`09"OverrideText" X#define DwtCPosition`09`09"Position" X#define DwtCSharedFlag`09`09"SharedFlag" X X/* X * New fields for the Pane widget class record`20 X */ Xtypedef struct `7B X DwtOffsetPtr`09paneoffsets; X int mumble; /* No new procedures */ X`7D PaneClassPart; X`20 X/*`20 X * Full class record declaration X */ Xtypedef struct _PaneClassRec `7B X CoreClassPart`09core_class; X CompositeClassPart composite_class; X ConstraintClassPart constraint_class; X PaneClassPart`09pane_class; X`7D PaneClassRec, *PaneClass; X`20 X`20 X/* X * New fields for the Pane widget record X */ Xtypedef struct _PanePart `7B X DwtCallbackStruct helpcallback,`09/* Help callback */ X map_callback, /* about to be mapped */ X`09`09 unmap_callback, /* just been unmapped */ V `20 X`09`09 focus_callback;`09/* grabbed input focus */ X unsigned char orientation;`09`09/* Horizontal or Vertical pane. */ X Pixel foreground;`09`09/* Foreground color for mullions, borders, etc. * V/ X Dimension mullionsize;`09/* Size of mullions. same as borderwidth */ X Dimension mullionlength;`09/* Actual Size of mullions. */ X Boolean leftmullion;`09/* Have we actually left the mullion area */ X short intersub;`09`09/* Number of pixels between subwidgets. */ X WidgetList children;`09/* List of subwidgets. */ X Cardinal num_children;`09/* Number of subwidgets. */ X int resize_mode;`09`09/* If TRUE, children are allowed to change */ X`09`09`09`09/* their length to whatever they want, and */ X`09`09`09`09/* we don't attempt to make things add up to */ X`09`09`09`09/* the correct total length. */ X GC invgc;`09`09`09/* GC to use to draw magic borders */ X Widget whichadjust;`09`09/* Which window we're currently dragging. */ X Position origloc;`09`09/* Where the button was originally pressed. */ X Boolean overridetext;`09/* Whether to override text bindings. */ X Widget lasthadfocus;`09/* The last widget to which we gave focus. */ X`7D PanePart; X`20 X/**************************************************************** X * X * Full instance record declaration X * X ****************************************************************/ X`20 Xtypedef struct _PaneRec `7B X CorePart`09 core; X CompositePart composite; X ConstraintPart constraint; X PanePart`09 pane; X`7D PaneRec, *PaneWidget; X`20 X/*`20 X * Data to be kept for each child. X */ Xtypedef struct _ConstraintsRec `7B X Dimension min, max;`09`09/* Limits on length of this widget. */ X Dimension dlength;`09`09/* Desired length for this widget. */ X Widget mullion;`09`09/* Widget used for the mullion below this */ X`09`09`09`09/* widget (if any) */ X Position magicborder;`09/* Where the last magic border was drawn. */ X Position position;`09`09/* Where to place this beast */ X Cardinal sharedflag;`09/* The position is shared with another widget */ X`09`09`09`09/* Also is the subwidget viewable */ X Boolean resizable;`09`09/* allow widget to be resized by pane? */ X X`7D ConstraintsRec,*Constraints; X`20 X#ifndef PANE Xexternal PaneClassRec panewidgetclassrec; Xexternal PaneClass panewidgetclass; X#endif X Xextern Widget DwtPaneCreate(); /* parent,name,arglist,argCount */ X /* Widget parent; */ X /* char *name; */ X /* Arg *arglist; */ X /* int argCount; */ X Xextern Widget DwtHVPane(); /* parent, name, x, y, width, height, orientation V, mapcallback, helpcallback */ X /* Widget`09`09parent; */ X /* char`09`09*name; */ X /* Position`09`09x, y; */ X /* Dimension`09width, height; */ X /* int`09`09orientation; */ X /* DwtCallBackPtr`09mapcallback, helpcallback; */ X Xextern void DwtPaneAddWidget(); /* subwidget, position, min, max, resizeable V, sharedflag */ X /* Widget subwidget; */ X /* Cardinal position */ X /* Dimension *min, *max; */ X /* Boolean resizable */ X /* Cardinal`09sharedflag */ X Xextern void DwtPaneGetMinMax(); /* subwidget, min, max */ X /* Widget subwidget; */ X /* Dimension *min, *max; */ X Xextern void DwtPaneSetMinMax(); /* subwidget, min, max */ X /* Widget subwidget; */ X /* Dimension min, max; */ X Xextern void DwtPaneSetMin(); /* subwidget, min*/ X /* Widget subwidget; */ X /* Dimension min; */ X Xextern void DwtPaneSetMax(); /* subwidget, max */ X /* Widget subwidget; */ X /* Dimension max; */ X Xextern void DwtPaneAllowResizing(); /* pane, allow */ X /* PaneWidget pane; */ X /* int allowtype; */ X Xextern void DwtPaneMakeViewable(); /* subwidget*/ X /* Widget subwidget; */ X Xextern unsigned int PaneInitializeForDRM(); X X#endif _DwtPane_h X/* DON'T ADD STUFF AFTER THIS #endif */ X X/* DEC/CMS REPLACEMENT HISTORY, Element PANE.H */ X/* *6 11-APR-1989 11:27:31 BRINKLEY "leftmullion added" */ X/* *5 5-APR-1989 09:40:03 BRINKLEY "final standard I hope" */ X/* *4 30-MAR-1989 14:16:55 BRINKLEY "definitions of global variables fix Ved" */ X/* *3 28-MAR-1989 11:07:53 BRINKLEY "Style Guide Conformity" */ X/* *2 6-JAN-1989 12:35:18 BRINKLEY "new version of pane widget" */ X/* *1 20-DEC-1988 14:51:23 RYAN "Initial elements for V2" */ X/* DEC/CMS REPLACEMENT HISTORY, Element PANE.H */ $ CALL UNPACK PANE.H;1 1848239330 $ create 'f' X/* X * $Header: PaneP.h,v 1.2 89/01/05 17:58:38 gringort Exp $ X */ X`20 X/* X * Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachus Vetts. X *`20 X * All Rights Reserved X *`20 X * Permission to use, copy, modify, and distribute this software and its`20 X * documentation for any purpose and without fee is hereby granted,`20 X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in`20 X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. V `20 X *`20 X *`20 X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X/*`20 X * PanePrivate.h - Private definitions for Pane widget X *`20 X * Author:`09Terry Weissman X * `09`09Digital Equipment Corporation X * `09`09Western Software Laboratory X * Date:`09Tue 6 Oct 1987 X * X * V1.0d 17-Mar-1988`09RDB X *`09fix major bugs and enhancements X * V1.1 15-Apr-1988`09MRR X *`09Upward compatibility support. X * V1.4`09 02-Nov-1988`09RDB X *`09Apply standards to definitions X * V1.5`09 06-Jan-1988`09JG X *`09Modify for PMAX X */ X`20 X#ifndef _DwtPanePrivate_h X#define _DwtPanePrivate_h X`20 X/*********************************************************************** X * X * Pane Widget Private Data X * X ***********************************************************************/ X`20 Xtypedef struct _MullionPart `7B X DwtCallbackStruct helpcallback; X`7D MullionPart; X`20 Xtypedef struct _MullionRec `7B X CorePart`09core; X MullionPart`09mullion; X`7D MullionRec, *MullionWidget; X/* $Log:`09PaneP.h,v $ X * Revision 1.2 89/01/05 17:58:38 gringort X * fixed position X *`20 X * Revision 1.1 89/01/03 16:59:56 gringort X * Initial revision X *`20 X * Revision 1.3 88/02/26 13:29:52 weissman X * Add focus handling to subwindows. X *`20 X * Revision 1.2 87/12/16 15:31:12 weissman X * Conversion to BL6. X *`20 X * Revision 1.1 87/12/16 15:31:12 asente X * Initial revision X *`20 X * Revision 1.1 87/11/12 13:36:57 susan X * Initial revision X *`20 X * Revision 1.1 87/11/04 15:03:12 chow X * Initial revision X *`20 X * Revision 1.1 87/11/01 12:25:01 haynes X * Initial revision X *`20 X * */ X`20 X`20 X#endif _DwtPanePrivate_h X/* DON'T ADD STUFF AFTER THIS #endif */ X`20 X/* DEC/CMS REPLACEMENT HISTORY, Element PANEP.H */ X/* *4 30-MAR-1989 14:17:07 BRINKLEY "definitions of global variables fix Ved" */ X/* *3 28-MAR-1989 11:07:58 BRINKLEY "Style Guide Conformity" */ X/* *2 6-JAN-1989 12:36:17 BRINKLEY "new version" */ X/* *1 20-DEC-1988 14:51:26 RYAN "Initial elements for V2" */ X/* DEC/CMS REPLACEMENT HISTORY, Element PANEP.H */ $ CALL UNPACK PANEP.H;1 1211786543 $ create 'f' XReturn-Path: dbrooks@osf.org XReceived: from eros.Berkeley.EDU by shambhala.Berkeley.EDU (5.61/1.28) X`09id AA00465; Fri, 19 Jan 90 15:24:07 -0800 XReceived: by eros.berkeley.edu (5.57/1.28) X`09id AA27473; Fri, 19 Jan 90 15:24:01 PST XReceived: from penge.osf.org by postman.osf.org (5.61/OSF 0.9) X`09id AA19887; Fri, 19 Jan 90 18:23:54 -0500 XReceived: by penge.osf.org.osf.org (5.61/4.7) id AA01939; Fri, 19 Jan 90 18: V23:52 -0500 XDate: Fri, 19 Jan 90 18:23:52 -0500 XFrom: dbrooks@osf.org XMessage-Id: <9001192323.AA01939@penge.osf.org.osf.org> XTo: xrn@eros.berkeley.edu XSubject: mailer script for xrn X XThankyou for xrn 6.4. You say I'm on the mailing list, but does that Xmean I should have been notified about 6.3 and 6.4? I wasn't. X XThought you might like the script I use for printing articles. Its only Xinteresting feature is that it puts the Subject on the cover page and Xpage headers... X X#!/bin/csh -f X# Command to print stdin with a Subject: line Xset title = `60tee /tmp/xrnp$$ `7C sed '/`5ESubject: /\\!d\\\ Xs/Subject: //'`60 Xpr -h "$`7Btitle`7D" /tmp/xrnp$$ `7C lpr -J"$`7Btitle`7D" Xrm -rf /tmp/xrnp$$ X XI'm not a sed hacker; I just fiddled until it worked. X--`20 XDavid Brooks`09`09`09`09dbrooks@osf.org XOpen Software Foundation`09`09uunet!osf.org!dbrooks $ CALL UNPACK PRINTER.;1 1309306834 $ create 'f' X X/* X * $Header: /users/ricks/xrn/src/RCS/README,v 1.11 90/09/29 02:32:37 ricks E Vxp Locker: ricks $ X */ X XHow to get XRN: X X% ftp shambhala.berkeley.edu (128.32.132.54) Xuser: anonymous Xpassword: guest Xftp> cd pub/xrn Xftp> binary Xftp> get xrn6-13.tar.Z Xftp> quit X% uncompress xrn6-13.tar.Z X% tar xf xrn6-13.tar X X XHow to install XRN: X X0. See the file CHANGES for a list of changes from the last release. X X1. Does an NNTP server (version 1.5 or greater) exist on your network? X - if not, get the NNTP server code and install it X (via anonymous ftp from ucbvax.berkeley.edu) X - make sure that XHDR (in nntp/common/conf.h) was defined X when your NNTP server was installed. X (XRN will tell you if it has not been defined) X X2. Look at `60config.h' and make the necessary modifications X (default settings, location of various files, domain name, etc.) X X3. Make xrn X `20 X a. Build the Makefile X X 1. If you have X11 installed, build the Makefile: X `20 X`09 xmkmf`20 X X b. If you don't have xmkmf, but the X libraries are installed in the X `60right places': X X`09 make -f Makefile.NoXtr X X`09 you may need to specify values for LDOPTIONS and INCLUDES X`09 (see Makefile.NoXtr) X X c. Build xrn X X`09 make xrn X X4. Installl xrn AND the application defaults X X make install X X5. Check out `60Xresources.sample' for example resource settings X X`09 Ellen Sentovich (ellen@ic.berkeley.edu) X`09 Rick Spickelmier (ricks@berkeley.edu) X $ CALL UNPACK README.;1 1346643344 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /net/opus/mnt/ricks/src/X/xrn/RCS/res Vources.c,v 1.23 90/09/29 01:13:03 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * resources.c: routines for handling resource management X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include "xrn.h" X#include "utils.h" X#include "config.h" X#ifndef VMS X#include X#include X#include X#else X#include X#include X#include X#endif X#include "avl.h" X#include "xthelper.h" X#include "mesg.h" X#include "xrn.h" X#include "resources.h" X#include "error_hnds.h" X#include "internals.h" X#ifdef VMS X#define index strchr X#endif /* VMS */ X X/* X * resources and command list X */ X X/* extra name and class specifications */ X#define XtCgeometry "Geometry" X#ifdef VMS X#define XtNgeometry`09 "geometry" X#endif X#define XtNiconGeometry "iconGeometry" X#define XtCiconGeometry "IconGeometry" X#define XtNnntpServer "nntpServer" X#define XtCnntpServer "NntpServer" X#define XtNnewsrcFile "newsrcFile" X#define XtCnewsrcFile "NewsrcFile" X#define XtNsaveNewsrcFile "saveNewsrcFile" X#define XtCsaveNewsrcFile "SaveNewsrcFile" X#define XtNsaveDir "saveDir" X#define XtCsaveDir "SaveDir" X#define XtNsignatureFile "signatureFile" X#define XtCsignatureFile "SignatureFile" X#define XtNtopLines "topLines" X#define XtCtopLines "TopLines" X#define XtNsaveMode "saveMode" X#define XtCsaveMode "SaveMode" X#define XtNleaveHeaders "leaveHeaders" X#define XtCleaveHeaders "LeaveHeaders" X#define XtNstripHeaders "stripHeaders" X#define XtCstripHeaders "StripHeaders" X#define XtNdeadLetters "deadLetters" X#define XtCdeadLetters "DeadLetters" X#define XtNsavePostings "savePostings" X#define XtCsavePostings "SavePostings" X#define XtNminLines "minLines" X#define XtCminLines "MinLines" X#define XtNmaxLines "maxLines" X#define XtCmaxLines "MaxLines" X#define XtNdefaultLines "defaultLines" X#define XtCdefaultLines "DefaultLines" X#define XtNcancelCount "cancelCount" X#define XtCcancelCount "CancelCount" X#ifndef VMS X#define XtNmailer "mailer" X#define XtCmailer "Mailer" X#else X#define XtNpersonalName`09 "personalName" X#define XtCPersonalName`09 "personalName" X#endif X#define XtNeditorCommand "editorCommand" X#define XtCeditorCommand "EditorCommand" X#define XtNincludeHeader "includeHeader" X#define XtCincludeHeader "IncludeHeader" X#define XtNincludePrefix "includePrefix" X#define XtCincludePrefix "IncludePrefix" X#define XtNincludeSep "includeSep" X#define XtCincludeSep "IncludeSep" X#define XtNupdateNewsrc "updateNewsrc" X#define XtCupdateNewsrc "UpdateNewsrc" X#define XtNsortedSubjects "sortedSubjects" X#define XtCsortedSubjects "SortedSubjects" X#define XtNtmpDir "tmpDir" X#define XtCtmpDir "TmpDir" X#define XtNsubjectRead "subjectRead" X#define XtCsubjectRead "SubjectRead" X#define XtNinfo`09 `09 "info" X#define XtCInfo`09 `09 "Info" X#define XtNtypeAhead "typeAhead" X#define XtCtypeAhead "TypeAhead" X#define XtNconfirm "confirm" X#define XtCconfirm "Confirm" X#define XtNkillFiles "killFiles" X#define XtCkillFiles "KillFiles" X#define XtNcalvin "calvin" X#define XtCcalvin "Calvin" X#define XtNlineLength "lineLength" X#define XtClineLength "LineLength" X#define XtNbreakLength "breakLength" X#define XtCbreakLength "BreakLength" X#define XtNrescanTime`09 "rescanTime" X#define XtCRescanTime`09 "RescanTime" X#define XtNorganization`09 "organization" X#define XtCorganization`09 "Organization" X#define XtNdistribution "distribution" X#define XtCdistribution "Distribution" X#define XtNreplyTo`09 "replyTo" X#define XtCreplyTo`09 "ReplyTo" X#define XtNprefetchMax "prefetchMax" X#define XtCprefetchMax "PrefetchMax" X#define XtNautoRead`09 "autoRead" X#define XtCAutoRead`09 "AutoRead" X X#define XtNaddButtonList "addButtonList" X#define XtCAddButtonList "AddButtonList" X#define XtNngButtonList "ngButtonList" X#define XtCNgButtonList "NgButtonList" X#define XtNallButtonList "allButtonList" X#define XtCAllButtonList "AllButtonList" X#define XtNartButtonList "artButtonList" X#define XtCArtButtonList "ArtButtonList" X#define XtNartSpecButtonList "artSpecButtonList" X#define XtCArtSpecButtonList "ArtSpecButtonList" X#define XtNaddPopupList "addPopupList" X#define XtCAddPopupList "AddPopupList" X#define XtNngPopupList "ngPopupList" X#define XtCNgPopupList "NgPopupList" X#define XtNallPopupList "allPopupList" X#define XtCAllPopupList "AllPopupList" X#define XtNartPopupList "artPopupList" X#define XtCArtPopupList "ArtPopupList" X X#define XtNaddBindings`09 "addBindings" X#define XtCAddBindings`09 "AddBindings" X#define XtNngBindings`09 "ngBindings" X#define XtCNgBindings`09 "NgBindings" X#define XtNartBindings`09 "artBindings" X#define XtCArtBindings`09 "ArtBindings" X#define XtNallBindings`09 "allBindings" X#define XtCAllBindings`09 "AllBindings" X X#define XtNpageArticles`09 "pageArticles" X#define XtCPageArticles`09 "PageArticles" X#define XtNprintCommand`09 "printCommand" X#define XtCPrintCommand`09 "PrintCommand" X#define XtNhostName`09 "hostName" X#define XtCHostName`09 "HostName" X#define XtNreplyPath`09 "replyPath" X#define XtCReplyPath`09 "ReplyPath" X#define XtNpopupButton`09 "popupButton" X#define XtCPopupButton`09 "PopupButton" X X#define XtNdumpCore`09"dumpCore" X#define XtCDebug`09"Debug" X#define XtNcc`09 `09"cc" X#define XtCCC`09 `09"CC" X X#define XtNversion`09"version" X#define XtCversion`09"version" X X#define XtNverboseKill`09"verboseKill" X#define XtCVerboseKill "VerboseKill" X X#define XtNunreadIconName "unreadIconName" X#define XtCUnreadIconName "UnreadIconName" X X#define XtNuseGadgets`09"useGadgets" X#define XtCUseGadgets`09"UseGadgets" X X#define XtNauthorFullName`09"authorFullName" X#define XtCAuthorFullName`09"AuthorFullName" X X#ifdef REALLY_USE_LOCALTIME X#define XtNdisplayLocalTime`09"displayLocalTime" X#define XtCDisplayLocalTime`09"DisplayLocalTime" X#endif X X#define XtNdisplayLineCount`09"displayLineCount" X#define XtCDisplayLineCount`09"DisplayLineCount" X X#define XtNsaveString`09"saveString" X#define XtCSaveString`09"SaveString" X#define XtNresetSave`09"resetSave" X#define XtCResetSave`09"ResetSave" X Xstatic Boolean defaultFalse = False; Xstatic Boolean defaultTrue = True; X#ifndef MOTIF Xstatic char title`5B`5D = "dxrn V6.14"; Xstatic char unreadTitle`5B`5D = "dxrn V6.14 (New News)"; X#else Xstatic char title`5B`5D = "mxrn V6.14"; Xstatic char unreadTitle`5B`5D = "mxrn V6.14 (New News)"; X#endif X X Xapp_resourceRec app_resources; Xstatic char defaultNgButtons`5B`5D = X"ngQuit,ngRead,ngSubscribe,ngUnsub,ngCatchUp,ngGoto,ngRescan,ngCheckPoint,ng VSelect,ngMove,ngPost"; X Xstatic char defaultNgPopups`5B`5D = X"ngQuit,ngRead,ngSubscribe,ngUnsub,ngCatchUp,ngGoto,ngRescan,ngCheckPoint,ng VPost"; X Xstatic char defaultArtButtons`5B`5D = X"artQuit,artNext,artPrev,artNextUnread,artSubNext,artSubPrev,artLast,artNext VGroup,artCatchUp,artMarkRead,artMarkUnread"; X Xstatic char defaultArtPopups`5B`5D = X"artQuit,artNext,artPrev,artNextUnread,artSubNext,artSubPrev,artLast,artNext VGroup,artSave,artReply,artForward,artFollowup,artMarkUnread"; X X/* X * resources 'xrn' needs to get, rather than ones that the individual X * widgets will handle X */ Xstatic XtResource resources`5B`5D = `7B X `7BXtNgeometry, XtCgeometry, XtRString, sizeof(char *), X XtOffset(app_res,geometry), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNiconGeometry, XtCiconGeometry, XtRString, sizeof(char *), X XtOffset(app_res,iconGeometry), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNiconName, XtCIconName, XtRString, sizeof(char *), X XtOffset(app_res,iconName), XtRString, X#ifdef SHORT_ICONNAME X#ifndef MOTIF X`09(caddr_t) "dxrn"`7D, X#else X`09(caddr_t) "mxrn"`7D, X#endif X#else X`09(caddr_t) title`7D, X#endif X `7BXtNunreadIconName, XtCUnreadIconName, XtRString, sizeof(char *), X XtOffset(app_res,unreadIconName), XtRString, X#ifdef SHORT_ICONNAME X#ifndef MOTIF X`09(caddr_t) "dxrn (New News)"`7D, X#else X`09(caddr_t) "mxrn (New News)"`7D, X#endif X#else X`09(caddr_t) unreadTitle`7D, X#endif X `20 X `7BXtNtitle, XtCTitle, XtRString, sizeof(char *), X XtOffset(app_res,title), XtRString, (caddr_t) title`7D, X `20 X `7BXtNnntpServer, XtCnntpServer, XtRString, sizeof(char *), X XtOffset(app_res,nntpServer), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNnewsrcFile, XtCnewsrcFile, XtRString, sizeof(char *), X XtOffset(app_res,newsrcFile), XtRString, (caddr_t) NEWSRCFILE`7D, X `20 X `7BXtNsaveNewsrcFile, XtCsaveNewsrcFile, XtRString, sizeof(char *), X XtOffset(app_res,saveNewsrcFile), XtRString, (caddr_t) SAVENEWSRCFILE` V7D, X `20 X `7BXtNsaveDir, XtCsaveDir, XtRString, sizeof(char *), X XtOffset(app_res,saveDir), XtRString, (caddr_t) SAVEDIR`7D, X `20 X `7BXtNsignatureFile, XtCsignatureFile, XtRString, sizeof(char *), X XtOffset(app_res,signatureFile), XtRString, (caddr_t) SIGNATUREFILE`7D V, X `20 X `7BXtNtopLines, XtCtopLines, XtRInt, sizeof(int), X XtOffset(app_res,topLines), XtRString, (caddr_t) TOPLINES`7D, X `20 X `7BXtNsaveMode, XtCsaveMode, XtRString, sizeof(char *), X XtOffset(app_res,strSaveMode), XtRString, (caddr_t) SAVEMODE`7D, X `20 X `7BXtNleaveHeaders, XtCleaveHeaders, XtRString, sizeof(char *), X XtOffset(app_res,leaveHeaders), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNstripHeaders, XtCstripHeaders, XtRString, sizeof(char *), X XtOffset(app_res,stripHeaders), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNdeadLetters, XtCdeadLetters, XtRString, sizeof(char *), X XtOffset(app_res,deadLetters), XtRString, (caddr_t) DEADLETTER`7D, X X `7BXtNsavePostings, XtCsavePostings, XtRString, sizeof(char *), X XtOffset(app_res,savePostings), XtRString, (caddr_t) SAVEPOSTINGS`7D, X `20 X `7BXtNminLines, XtCminLines, XtRInt, sizeof(int), X XtOffset(app_res,minLines), XtRImmediate, (caddr_t) -1`7D, X X `7BXtNmaxLines, XtCmaxLines, XtRInt, sizeof(int), X XtOffset(app_res,maxLines), XtRImmediate, (caddr_t) -1`7D, X `20 X `7BXtNdefaultLines, XtCdefaultLines, XtRInt, sizeof(int), X XtOffset(app_res,defaultLines), XtRString, (caddr_t) MINLINES`7D, X X `7BXtNcancelCount, XtCcancelCount, XtRInt, sizeof(int), X XtOffset(app_res,cancelCount), XtRString, (caddr_t) CANCELCOUNT`7D, X X#ifndef VMS X `7BXtNmailer, XtCmailer, XtRString, sizeof(char *), X XtOffset(app_res,mailer), XtRString, (caddr_t) SENDMAIL`7D, X#else X `7BXtNpersonalName, XtCPersonalName, XtRString, sizeof(char *), X XtOffset(app_res,personalName), XtRImmediate, (caddr_t) NULL`7D, X#endif `20 X X `7BXtNeditorCommand, XtCeditorCommand, XtRString, sizeof(char *), X XtOffset(app_res,editorCommand), XtRString, (caddr_t) NULL`7D, X X `7BXtNincludeHeader, XtCincludeHeader, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,includeHeader), XtRBoolean, (caddr_t) &defaultFalse`7D V, X X `7BXtNversion, XtCversion, XtRString, sizeof(char *), X XtOffset(app_res,version), XtRString, (caddr_t) NULL`7D, X X `7BXtNincludePrefix, XtCincludePrefix, XtRString, sizeof(char *), X XtOffset(app_res,includePrefix), XtRString, (caddr_t) INCLUDEPREFIX`7D V, X X `7BXtNincludeSep, XtCincludeSep, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,includeSep), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNupdateNewsrc, XtCupdateNewsrc, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,updateNewsrc), XtRBoolean, (caddr_t) &defaultFalse`7D, X X `7BXtNsortedSubjects, XtCsortedSubjects, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,sortedSubjects), XtRBoolean, (caddr_t) &defaultFalse`7 VD, X X `7BXtNtmpDir, XtCtmpDir, XtRString, sizeof(char *), X XtOffset(app_res,tmpDir), XtRString, (caddr_t) NULL`7D, X X `7BXtNsubjectRead, XtCsubjectRead, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,subjectRead), XtRBoolean, (caddr_t) &defaultFalse`7D, X `20 X `7BXtNinfo, XtCInfo, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,info), XtRBoolean, (caddr_t) &defaultTrue`7D, X `20 X `7BXtNtypeAhead, XtCtypeAhead, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,typeAhead), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNconfirm, XtCconfirm, XtRString, sizeof(char *), X XtOffset(app_res,confirm), XtRString, (caddr_t) NULL`7D, X X `7BXtNkillFiles, XtCkillFiles, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,killFiles), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNcalvin, XtCcalvin, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,calvin), XtRBoolean, (caddr_t) &defaultFalse`7D, X `20 X `7BXtNlineLength, XtClineLength, XtRInt, sizeof(int), X XtOffset(app_res,lineLength), XtRString, (caddr_t) LINELENGTH`7D, X `20 X `7BXtNbreakLength, XtCbreakLength, XtRInt, sizeof(int), X XtOffset(app_res,breakLength), XtRString, (caddr_t) BREAKLENGTH`7D, X X `7BXtNrescanTime, XtCRescanTime, XtRInt, sizeof(int), X XtOffset(app_res,rescanTime), XtRString, (caddr_t) RESCAN_TIME`7D, X X `7BXtNorganization, XtCorganization, XtRString, sizeof(char *), X XtOffset(app_res,organization), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNdistribution, XtCdistribution, XtRString, sizeof(char *), X XtOffset(app_res,distribution), XtRString, (caddr_t) NULL`7D, X `20 X `7BXtNreplyTo, XtCreplyTo, XtRString, sizeof(char *), X XtOffset(app_res,replyTo), XtRString, (caddr_t) NULL`7D, X `20 X#ifdef XRN_PREFETCH X `7BXtNprefetchMax, XtCprefetchMax, XtRInt, sizeof(int), X XtOffset(app_res,prefetchMax), XtRString, (caddr_t) XRN_PREFETCH_MAX` V7D, X#endif X X `7BXtNaddButtonList, XtCAddButtonList, XtRString, sizeof(char *), X XtOffset(app_res,addButtonList), XtRString, (caddr_t) NULL`7D, X X `7BXtNngButtonList, XtCNgButtonList, XtRString, sizeof(char *), X XtOffset(app_res,ngButtonList), XtRString, (caddr_t) defaultNgButtons` V7D, X X `7BXtNallButtonList, XtCAllButtonList, XtRString, sizeof(char *), X XtOffset(app_res,allButtonList), XtRString, (caddr_t) NULL`7D, X X `7BXtNartButtonList, XtCArtButtonList, XtRString, sizeof(char *), X XtOffset(app_res,artButtonList), XtRString, (caddr_t) defaultArtButton Vs`7D, X X `7BXtNartSpecButtonList, XtCArtSpecButtonList, XtRString, sizeof(char *), X XtOffset(app_res,artSpecButtonList), XtRString, (caddr_t) NULL`7D, X X `7BXtNaddBindings, XtCAddBindings, XtRString, sizeof(char *), X XtOffset(app_res,addBindings), XtRString, (caddr_t) NULL`7D, X X `7BXtNngBindings, XtCNgBindings, XtRString, sizeof(char *), X XtOffset(app_res,ngBindings), XtRString, (caddr_t) NULL`7D, X X `7BXtNartBindings, XtCArtBindings, XtRString, sizeof(char *), X XtOffset(app_res,artBindings), XtRString, (caddr_t) NULL`7D, X X `7BXtNallBindings, XtCAllBindings, XtRString, sizeof(char *), X XtOffset(app_res,allBindings), XtRString, (caddr_t) NULL`7D, X X `7BXtNpageArticles, XtCPageArticles, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,pageArticles), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNprintCommand, XtCPrintCommand, XtRString, sizeof(char *), X XtOffset(app_res,printCommand), XtRString, (caddr_t) PRINTCOMMAND`7D, X X `7BXtNhostName, XtCHostName, XtRString, sizeof(char *), X XtOffset(app_res,hostName), XtRString, (caddr_t) NULL`7D, X X `7BXtNreplyPath, XtCReplyPath, XtRString, sizeof(char *), X XtOffset(app_res,replyPath), XtRString, (caddr_t) NULL`7D, X X `7BXtNaddPopupList, XtCAddPopupList, XtRString, sizeof(char *), X XtOffset(app_res,addPopupList), XtRString, (caddr_t) NULL`7D, X X `7BXtNngPopupList, XtCNgPopupList, XtRString, sizeof(char *), X XtOffset(app_res,ngPopupList), XtRString, (caddr_t) defaultNgPopups`7D V, X X `7BXtNallPopupList, XtCAllPopupList, XtRString, sizeof(char *), X XtOffset(app_res,allPopupList), XtRString, (caddr_t) NULL`7D, X X `7BXtNartPopupList, XtCArtPopupList, XtRString, sizeof(char *), X XtOffset(app_res,artPopupList), XtRString, (caddr_t) defaultArtPopups` V7D, X X#ifdef MOTIF X `7BXtNpopupButton, XtCPopupButton, XtRInt,`09 sizeof(int), X XtOffset(app_res, popupButton), XtRImmediate, (caddr_t) 3`7D, X#else X `7BXtNpopupButton, XtCPopupButton, XtRInt,`09 sizeof(int), X XtOffset(app_res, popupButton), XtRImmediate, (caddr_t) 2`7D, X#endif X `7BXtNdumpCore, XtCDebug, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,dumpCore), XtRBoolean, (caddr_t) X#ifdef DUMPCORE X`09`09`09`09`09`09`09&defaultTrue`7D, X#else X`09`09`09`09`09`09`09&defaultFalse`7D, X#endif X `7BXtNautoRead, XtCAutoRead, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,autoRead), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNcc, XtCCC, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,cc), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNverboseKill, XtCVerboseKill, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,verboseKill), XtRBoolean, (caddr_t) &defaultTrue`7D, X X `7BXtNuseGadgets, XtCUseGadgets, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,useGadgets), XtRBoolean, (caddr_t) &defaultFalse`7D, X X `7BXtNauthorFullName, XtCAuthorFullName, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,authorFullName), XtRBoolean, (caddr_t) &defaultFalse`7 VD, X X#ifdef REALLY_USE_LOCALTIME X `7BXtNdisplayLocalTime, XtCDisplayLocalTime, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,displayLocalTime), XtRBoolean, (caddr_t) &defaultTrue` V7D, X#endif X X `7BXtNdisplayLineCount, XtCDisplayLineCount, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,displayLineCount), XtRBoolean, (caddr_t) &defaultFalse V`7D, X X `7BXtNsaveString, XtCSaveString, XtRString, sizeof(char *), X XtOffset(app_res,saveString), XtRString, (caddr_t) NULL`7D, X X `7BXtNresetSave, XtCResetSave, XtRBoolean, sizeof(Boolean), X XtOffset(app_res,resetSave), XtRBoolean, (caddr_t) &defaultTrue`7D, X X`7D; X X X/* X * allowed command line options X */ X#ifndef VMS Xstatic XrmOptionDescRec optionList`5B`5D = `7B X `7B"-iconGeometry", XtNiconGeometry, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-nntpServer", XtNnntpServer, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-newsrcFile", XtNnewsrcFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-saveNewsrcFile", XtNsaveNewsrcFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-saveDir", XtNsaveDir, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-signatureFile", XtNsignatureFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-topLines", XtNtopLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-saveMode", XtNsaveMode, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-leaveHeaders", XtNleaveHeaders, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-stripHeaders", XtNstripHeaders, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-deadLetters", XtNdeadLetters, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-savePostings", XtNsavePostings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-minLines", XtNminLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-maxLines", XtNmaxLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-cancelCount", XtNcancelCount, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-mailer", XtNmailer, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-editorCommand", XtNeditorCommand, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-includeHeader", XtNincludeHeader, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+includeHeader", XtNincludeHeader, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-includePrefix", XtNincludePrefix, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-includeSep", XtNincludeSep, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+includeSep", XtNincludeSep, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-updateNewsrc", XtNupdateNewsrc, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+updateNewsrc", XtNupdateNewsrc, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-sortedSubjects", XtNsortedSubjects, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+sortedSubjects", XtNsortedSubjects, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-tmpDir", XtNtmpDir, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-subjectRead", XtNsubjectRead, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+subjectRead", XtNsubjectRead, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-info", `09XtNinfo, XrmoptionNoArg, (caddr_t) "off"`7 VD, X `7B"+info", `09XtNinfo, XrmoptionNoArg, (caddr_t) "on"`7D V, X `7B"-typeAhead", `09XtNtypeAhead, XrmoptionNoArg, (caddr_t) "o Vff"`7D, X `7B"+typeAhead", `09XtNtypeAhead, XrmoptionNoArg, (caddr_t) "o Vn"`7D, X `7B"-confirm", XtNconfirm, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-killFiles", XtNkillFiles, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+killFiles", XtNkillFiles, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-calvin", XtNcalvin, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-lineLength", XtNlineLength, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-breakLength", XtNbreakLength, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-rescanTime",`09XtNrescanTime,`09 XrmoptionSepArg, (caddr_t) NULL V`7D, X `7B"-organization", XtNorganization, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-replyTo", XtNreplyTo, XrmoptionSepArg, (caddr_t) NUL VL`7D, X#ifdef XRN_PREFETCH X `7B"-prefetchMax", XtNprefetchMax, XrmoptionSepArg, (caddr_t) NUL VL`7D, X#endif X `7B"-addButtonList", XtNaddButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngButtonList", XtNngButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allButtonList", XtNallButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artButtonList", XtNartButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artSpecButtonList", XtNartSpecButtonList, XrmoptionSepArg, (cadd Vr_t) NULL`7D, X `7B"-addBindings", XtNaddBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngBindings", XtNngBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artBindings", XtNartBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allBindings", XtNallBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-pageArticles",`09XtNpageArticles, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+pageArticles",`09XtNpageArticles, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-printCommand", XtNprintCommand, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-distribution", XtNdistribution, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-hostName", `09XtNhostName, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-replyPath", `09XtNreplyPath, XrmoptionSepArg, (caddr_t) NU VLL`7D, X `7B"-addPopupList", XtNaddPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngPopupList", XtNngPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allPopupList", XtNallPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artPopupList", XtNartPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-popupButton",`09XtNpopupButton,`09 XrmoptionSepArg, (caddr_t) NU VLL`7D, X `7B"-dumpCore",`09XtNdumpCore,`09 XrmoptionNoArg, (caddr_t) "off"`7D V, X `7B"+dumpCore",`09XtNdumpCore,`09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-autoRead",`09XtNautoRead,`09 XrmoptionNoArg, (caddr_t) "off"`7D V, X `7B"+autoRead",`09XtNautoRead,`09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-cc",`09`09XtNcc,`09 `09 XrmoptionNoArg, (caddr_t) "off"`7D, X `7B"+cc",`09`09XtNcc,`09 `09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-unreadIconName", XtNunreadIconName, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-verboseKill",`09XtNverboseKill,`09 XrmoptionNoArg, (caddr_t) "o Vff"`7D, X `7B"+verboseKill",`09XtNverboseKill,`09 XrmoptionNoArg, (caddr_t) "o Vn"`7D, X `7B"-useGadgets", XtNuseGadgets, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+useGadgets", XtNuseGadgets, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-authorFullName",`09XtNauthorFullName, XrmoptionNoArg, (caddr_t) " Voff"`7D, X `7B"+authorFullName",`09XtNauthorFullName, XrmoptionNoArg, (caddr_t) " Von"`7D, X#ifdef REALLY_USE_LOCALTIME X `7B"-displayLocalTime",XtNdisplayLocalTime,XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+displayLocalTime",XtNdisplayLocalTime,XrmoptionNoArg, (caddr_t) "on V"`7D, X#endif X `7B"-displayLineCount",XtNdisplayLineCount,XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+displayLineCount",XtNdisplayLineCount,XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-saveString", XtNsaveString, XrmoptionSepArg, (caddr_t) NULL`7D, X `7B"-resetSave", XtNresetSave, XrmoptionNoArg, (caddr_t) "off"`7D, X `7B"+resetSave", XtNresetSave, XrmoptionNoArg, (caddr_t) "on"`7D, X`7D; `20 X#else Xstatic XrmOptionDescRec optionList`5B`5D = `7B X `7B"-icongeometry", XtNiconGeometry, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-nntpserver", XtNnntpServer, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-newsrcfile", XtNnewsrcFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-savenewsrcfile", XtNsaveNewsrcFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-savedir", XtNsaveDir, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-signaturefile", XtNsignatureFile, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-toplines", XtNtopLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-savemode", XtNsaveMode, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-leaveheaders", XtNleaveHeaders, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-stripheaders", XtNstripHeaders, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-deadletters", XtNdeadLetters, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-savepostings", XtNsavePostings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-minlines", XtNminLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-maxlines", XtNmaxLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-defaultlines", XtNdefaultLines, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-cancelcount", XtNcancelCount, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-personalname", XtNpersonalName, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-editorcommand", XtNeditorCommand, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-includeheader", XtNincludeHeader, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+includeheader", XtNincludeHeader, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-includeprefix", XtNincludePrefix, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-includesep", XtNincludeSep, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+includesep", XtNincludeSep, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-updatenewsrc", XtNupdateNewsrc, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+updatenewsrc", XtNupdateNewsrc, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-sortedsubjects", XtNsortedSubjects, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+sortedsubjects", XtNsortedSubjects, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-tmpdir", XtNtmpDir, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-subjectread", XtNsubjectRead, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+subjectread", XtNsubjectRead, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-info", `09XtNinfo, XrmoptionNoArg, (caddr_t) "off"`7 VD, X `7B"+info", `09XtNinfo, XrmoptionNoArg, (caddr_t) "on"`7D V, X `7B"-typeahead", `09XtNtypeAhead, XrmoptionNoArg, (caddr_t) "o Vff"`7D, X `7B"+typeahead", `09XtNtypeAhead, XrmoptionNoArg, (caddr_t) "o Vn"`7D, X `7B"-confirm", XtNconfirm, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-killfiles", XtNkillFiles, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+killfiles", XtNkillFiles, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-calvin", XtNcalvin, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-linelength", XtNlineLength, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-breaklength", XtNbreakLength, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-rescantime",`09XtNrescanTime,`09 XrmoptionSepArg, (caddr_t) NULL V`7D, X `7B"-organization", XtNorganization, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-replyto", XtNreplyTo, XrmoptionSepArg, (caddr_t) NUL VL`7D, X#ifdef XRN_PREFETCH X `7B"-prefetchmax", XtNprefetchMax, XrmoptionSepArg, (caddr_t) NUL VL`7D, X#endif X `7B"-addbuttonlist", XtNaddButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngbuttonlist", XtNngButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allbuttonlist", XtNallButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artbuttonlist", XtNartButtonList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artspecbuttonlist", XtNartSpecButtonList, XrmoptionSepArg, (cadd Vr_t) NULL`7D, X `7B"-addbindings", XtNaddBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngbindings", XtNngBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artbindings", XtNartBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allbindings", XtNallBindings, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-pagearticles",`09XtNpageArticles, XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+pagearticles",`09XtNpageArticles, XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-printcommand", XtNprintCommand, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-distribution", XtNdistribution, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-hostname", `09XtNhostName, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-replypath", `09XtNreplyPath, XrmoptionSepArg, (caddr_t) NU VLL`7D, X `7B"-addpopuplist", XtNaddPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-ngpopuplist", XtNngPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-allpopuplist", XtNallPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-artpopuplist", XtNartPopupList, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-popupbutton",`09XtNpopupButton,`09 XrmoptionSepArg, (caddr_t) NU VLL`7D, X `7B"-dumpcore",`09XtNdumpCore,`09 XrmoptionNoArg, (caddr_t) "off"`7D V, X `7B"+dumpcore",`09XtNdumpCore,`09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-autoread",`09XtNautoRead,`09 XrmoptionNoArg, (caddr_t) "off"`7D V, X `7B"+autoread",`09XtNautoRead,`09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-cc",`09`09XtNcc,`09 `09 XrmoptionNoArg, (caddr_t) "off"`7D, X `7B"+cc",`09`09XtNcc,`09 `09 XrmoptionNoArg, (caddr_t) "on"`7D, X `7B"-unreadiconname", XtNunreadIconName, XrmoptionSepArg, (caddr_t) NUL VL`7D, X `7B"-verbosekill",`09XtNverboseKill,`09 XrmoptionNoArg, (caddr_t) "o Vff"`7D, X `7B"+verbosekill",`09XtNverboseKill,`09 XrmoptionNoArg, (caddr_t) "o Vn"`7D, X `7B"-usegadgets", XtNuseGadgets, XrmoptionNoArg, (caddr_t) "off V"`7D, X `7B"+usegadgets", XtNuseGadgets, XrmoptionNoArg, (caddr_t) "on" V`7D, X `7B"-authorfullname",`09XtNauthorFullName, XrmoptionNoArg, (caddr_t) " Voff"`7D, X `7B"+authorfullname",`09XtNauthorFullName, XrmoptionNoArg, (caddr_t) " Von"`7D, X#ifdef REALLY_USE_LOCALTIME X `7B"-displaylocaltime",XtNdisplayLocalTime,XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+displaylocaltime",XtNdisplayLocalTime,XrmoptionNoArg, (caddr_t) "on V"`7D, X#endif X `7B"-displaylinecount",XtNdisplayLineCount,XrmoptionNoArg, (caddr_t) "of Vf"`7D, X `7B"+displaylinecount",XtNdisplayLineCount,XrmoptionNoArg, (caddr_t) "on V"`7D, X `7B"-savestring", XtNsaveString, XrmoptionSepArg, (caddr_t) NULL`7D, X `7B"-resetsave", XtNresetSave, XrmoptionNoArg, (caddr_t) "off"`7D, X `7B"+resetsave", XtNresetSave, XrmoptionNoArg, (caddr_t) "on"`7D, X`7D; `20 X#endif X Xstatic void Xusage(ac, av) Xint ac; Xchar **av; /* program name */ X/* X * print out the usage message X * X * returns: void X * `20 X */ X`7B X int i; X X (void) printf("Unknown options:"); X for (i = 1; i <= ac - 1; i++) `7B X`09if (index(av`5Bi`5D, ':') == NIL(char)) `7B X`09 printf(" %s", av`5Bi`5D); X`09`7D X `7D X printf("\n"); X printf("\t-geometry WxH+X+Y\tSize and position of window\n"); X printf("\t-iconGeometry +X+Y\tPosition of icon\n"); X printf("\t-nntpServer name\tNNTP server\n"); X printf("\t-newsrcFile file\t.newsrc filename\n"); X printf("\t-saveNewsrcFile file\tSaved .newsrc filename\n"); X printf("\t-saveDir directory\tDirectory for saving files\n"); X printf("\t-signatureFile file\tSignature file for posting\n"); X printf("\t-topLines number\tNumber of lines used by the top window\n"); X printf("\t-saveMode mode\t\tMethod of saving articles\n"); X printf("\t-leaveHeaders list\tHeaders to leave\n"); X printf("\t-stripHeaders list\tHeaders to strip\n"); X printf("\t-deadLetters file\tFile to store failed postings/messages\n"); X printf("\t-savePostings file\tFile to save postings/messages\n"); X printf("\t-minLines number\tMinimum number of lines above cursor\n"); X printf("\t-maxLines number\tMaximum number of lines above cursor\n"); X printf("\t-defaultLines number\tDefault number of lines above cursor\n") V; X printf("\t-cancelCount number\tNumber of articles to search before poppi Vng up the cancel button\n"); X#ifndef VMS X printf("\t-mailer\t\t\tMailer to use\n"); X#else X printf("\t\-personalName\t\tYour name\n"); X#endif X printf("\t-editorCommand\t\tEditor to use (defaults to the toolkit edito Vr)\n"); X printf("\t+/-includeHeader\tInclude original article's header\n"); X printf("\t+/-includeSep\t\tPut '>' in front of included lines\n"); X printf("\t-includePrefix\t\tPrefix `5B\"%s\"`5D for included lines\n", X`09 INCLUDEPREFIX); X printf("\t+/-updateNewsrc\t\tUpdate the .newsrc file each time a group i Vs exited\n"); X printf("\t+/-sortedSubjects\tSort or do not sort the subjects\n"); X printf("\t-tmpDir\t\t\tTemporary article directory\n"); X printf("\t+/-subjectRead\t\tChange default from next unread to subject n Vext\n"); X printf("\t+/-info\t\t\tPut all information in the message pane\n"); X printf("\t+/-typeAhead\t\tEnable typeahead\n"); X printf("\t-confirm\t\tTurn on/off confirmation boxes\n"); X printf("\t+/-killFiles\t\tTurn on/off the use of kill files\n"); X printf("\t-lineLength\t\tLength of lines for article postings\n"); X printf("\t-breakLength\t\tLength of line at which line wrapping begins\n V"); X printf("\t-rescanTime\t\tIdle time before checking for new articles\n"); X printf("\t-organization\t\tName of your organization\n"); X printf("\t-replyTo\t\tValue used for the Reply-To field\n"); X#ifdef XRN_PREFETCH X printf("\t-prefetchMax\t\tMaximum number of articles to prefetch\n"); X#endif X printf("\t-addButtonList\t\tList of Add mode buttons\n"); X printf("\t-ngButtonList\t\tList of Newsgroup mode buttons\n"); X printf("\t-allButtonList\t\tList of All mode buttons\n"); X printf("\t-artButtonList\t\tList of Article mode buttons (top box)\n"); X printf("\t-artSpecButtonList\tList of Article mode buttons (bottom box)\ Vn"); X printf("\t-addBindings\t\tAdd mode bindings\n"); X printf("\t-ngBindings\t\tNewsgroup mode bindings\n"); X printf("\t-artBindings\t\tArticle mode bindings\n"); X printf("\t-allBindings\t\tAll mode bindings\n"); X printf("\t+/-pageArticles\t\tSpacebar scrolls the current article\n"); X printf("\t-printCommand\t\tCommand to use to print out an article\n"); X printf("\t-distribution\t\tDefault distribution for messages\n"); X printf("\t-hostName\t\tOverride your host's default name\n"); X printf("\t-replyPath\t\tProvide default path for mail replies\n"); X printf("\t-addPopupList\t\tList of Add mode popup buttons\n"); X printf("\t-ngPopupList\t\tList of Newsgroup mode popup buttons\n"); X printf("\t-allPopupList\t\tList of All mode popup buttons\n"); X printf("\t-artPopupList\t\tList of Article mode popup buttons\n"); X printf("\t-popupButton\t\tButton for popup menus (2 or 3)\n"); X printf("\t+/-dumpCore\t\tDump core on error exit\n"); X printf("\t+/-cc\t\tInclude 'Cc: user' in replies\n"); X printf("\t+/-autoRead\t\tRead first article when opening group\n"); X printf("\t+/-verboseKill\t\tList subjects when killing articles\n"); X printf("\t+/-useGadgets\t\tUse Motif gadget buttons instead of widgets\n V"); X printf("\t+/-unreadIconName\t\tIcon name used when unread articles\n"); X printf("\t+/-authorFullName\t\tUse author's fullname in article list\n") V; X#ifdef REALLY_USE_LOCALTIME X printf("\t+/-displayLocalTime\t\tDisplay local time in the Date: field\n V"); X#endif X printf("\t+/-displayLineCount\t\tDisplay line count in the subject index V\n"); X printf("\t-saveString\t\tstring to use in the save dialog\n"); X printf("\t+/-resetSave\t\treset the save dialog string on each posting\n V"); X ehErrorExitXRN(""); X`7D X Xextern XrmDatabase XtDatabase(); Xstatic XrmDatabase`09xrmDB; Xstatic XrmDatabase`09sysDB; Xchar customName`5B512`5D; X XWidget XXrnInitialize(argc, argv) Xint argc; Xchar **argv; X/* X * initialize the toolkit, parse the command line, and handle the Xdefaults X * X * returns: top level widget X * X */ X`7B X Widget widget; X char *ptr; X static Arg shell_args`5B`5D = `7B X`09`7BXtNinput, (XtArgVal)True`7D, X`09`7BXtNiconName, (XtArgVal) NULL`7D, X`09`7BXtNtitle, (XtArgVal) NULL`7D, X `7D; X char verString`5B40`5D; X X /* set up the program name */ X#ifndef VMS X if ((ptr = rindex(argv`5B0`5D, '/')) == NIL(char)) `7B X`09(void) strncpy(app_resources.progName, argv`5B0`5D, X`09`09 sizeof(app_resources.progName)); X `7D else `7B X`09(void) strncpy(app_resources.progName, ++ptr, X`09`09 sizeof(app_resources.progName)); X `7D X if ((ptr = getenv("XAPPLRESDIR")) != NULL) `7B X`09strcpy(customName, ptr); X `7D else `7B X`09strcpy(customName, "`7E"); X `7D X#ifdef MOTIF X strcat(customName, "/.mxrn"); X#else X strcat(customName, "/.dxrn"); X#endif X ptr = utTildeExpand(customName); X strcpy(customName, ptr); `20 X#else X#ifdef MOTIF X (void) strcpy(app_resources.progName, "mxrn"); X (void) strcpy(argv`5B0`5D, "mxrn"); X (void) strcpy(customName, "decw$user_defaults:mxrn.dat"); X#else X (void) strcpy(app_resources.progName, "dxrn"); X (void) strcpy(argv`5B0`5D, "dxrn"); X (void) strcpy(customName, "decw$user_defaults:dxrn.dat"); X#endif X#endif X X XrmInitialize(); X#ifdef MOTIF X widget = XtInitialize(app_resources.progName, "mxrn", X`09`09`09 optionList, XtNumber(optionList), &argc, argv); X#else X widget = XtInitialize(app_resources.progName, "dxrn", X`09`09`09 optionList, XtNumber(optionList), &argc, argv); X#endif X X if (argc > 1) `7B X`09usage(argc, argv); X `7D X X /* check and set the lock file */ X checkLock(); X X xrmDB = XrmGetFileDatabase(customName); X sysDB = XtDatabase(XtDisplay(widget)); X if (xrmDB != NULL && sysDB != NULL) `7B X`09XrmMergeDatabases(xrmDB, &sysDB); X `7D X X /* get the resources needed by xrn itself */ X XtGetApplicationResources(widget, (caddr_t) &app_resources, X`09`09`09 resources, XtNumber(resources), 0, 0); X X /* set up the titles */ X shell_args`5B1`5D.value = (XtArgVal) app_resources.iconName; X shell_args`5B2`5D.value = (XtArgVal) app_resources.title; X X XtSetValues(widget, shell_args, XtNumber(shell_args)); X X /* article saving mode */ X X app_resources.saveMode = 0; X if (utSubstring(app_resources.strSaveMode, "mailbox") == 1) `7B X`09app_resources.saveMode `7C= MAILBOX_SAVE; X `7D else `7B X`09app_resources.saveMode `7C= NORMAL_SAVE; X `7D X if (utSubstring(app_resources.strSaveMode, "noheaders") == 1) `7B X`09app_resources.saveMode `7C= NOHEADERS_SAVE; X `7D else `7B X`09app_resources.saveMode `7C= HEADERS_SAVE; X `7D X X if (utSubstring(app_resources.strSaveMode, "subdirs") == 1) `7B X`09app_resources.saveMode `7C= SUBDIRS_SAVE; X `7D else if (utSubstring(app_resources.strSaveMode, "onedir") == 1) `7B X`09app_resources.saveMode `7C= ONEDIR_SAVE; X `7D else `7B X`09app_resources.saveMode `7C= SAVE_DIR_DEFAULT; X `7D X X /* header stripping mode */ X X /* STRIP_HEADERS with a NIL table will leave all headers (nothing to str Vip) */ X app_resources.headerTree = avl_init_table(strcmp); X app_resources.headerMode = STRIP_HEADERS; X X if ((app_resources.leaveHeaders != NIL(char)) && X`09(app_resources.stripHeaders != NIL(char))) `7B X`09ehErrorExitXRN("Only one of 'stripHeaders, leaveHeaders' allowed\n"); X `7D `20 X X if (app_resources.leaveHeaders != NIL(char)) `7B X`09char *p, *token; X`09 X`09app_resources.headerMode = LEAVE_HEADERS; X`09p = app_resources.leaveHeaders; X`09while ((token = strtok(p, ", \t\n")) != NIL(char)) `7B X`09 utDowncase(token); X`09 (void) avl_insert(app_resources.headerTree, token, (char *) 1); X`09 p = NIL(char); X`09`7D X`09 X `7D else if (app_resources.stripHeaders != NIL(char)) `7B X`09char *p, *token; X`09 X`09app_resources.headerMode = STRIP_HEADERS; X`09p = app_resources.stripHeaders; X`09while ((token = strtok(p, ", \t\n")) != NIL(char)) `7B X`09 utDowncase(token); X`09 (void) avl_insert(app_resources.headerTree, token, (char *) 1); X`09 p = NIL(char); X`09`7D X `7D X X /* confirm boxes */ X X app_resources.confirmMode = 0; X X if (app_resources.confirm != NIL(char)) `7B X`09char *p, *token; X X`09p = app_resources.confirm; X`09while ((token = strtok(p, ", \t\n")) != NIL(char)) `7B X`09 if (strcmp(token, "ngQuit") == 0) `7B X`09`09app_resources.confirmMode `7C= NG_QUIT; X`09 `7D else if (strcmp(token, "ngExit") == 0) `7B X`09`09app_resources.confirmMode `7C= NG_EXIT; X`09 `7D else if (strcmp(token, "ngCatchUp") == 0) `7B X`09`09app_resources.confirmMode `7C= NG_CATCHUP; X`09 `7D else if (strcmp(token, "artCatchUp") == 0) `7B X`09`09app_resources.confirmMode `7C= ART_CATCHUP; X`09 `7D else if (strcmp(token, "artFedUp") == 0) `7B X`09`09app_resources.confirmMode `7C= ART_FEDUP; X`09 `7D else if (strcmp(token, "ngUnsub") == 0) `7B X`09`09app_resources.confirmMode `7C= NG_UNSUBSCRIBE; X`09 `7D else if (strcmp(token, "artUnsub") == 0) `7B X`09`09app_resources.confirmMode `7C= ART_UNSUBSCRIBE; X`09 `7D else if (strcmp(token, "artEndAction") == 0) `7B X`09`09app_resources.confirmMode `7C= ART_ENDACTION; X`09 `7D else if (strcmp(token, "artSave") == 0) `7B X`09`09app_resources.confirmMode `7C= ART_SAVE; X`09 `7D else `7B X`09`09mesgPane(XRN_SERIOUS, "unknown confirm button: %s", token); X`09 `7D X`09 p = NIL(char); X`09`7D X `7D X X /* temporary directory */ X X if (app_resources.tmpDir == NIL(char)) `7B X`09char *p = getenv("TMPDIR"); X X`09if (p == NIL(char)) `7B X`09 /*`20 X`09 * XXX added to deal with a possible compiler problem on X`09 * the IBM RT running AOS using the hc2.1s compiler X`09 * (reported by Jay Ford ). X`09 */ X`09 char *tmp_ptr = TEMPORARY_DIRECTORY; X`09 app_resources.tmpDir = XtNewString(tmp_ptr); X`09`7D else `7B X`09 app_resources.tmpDir = XtNewString(p); X`09`7D X `7D X X app_resources.tmpDir = XtNewString(utTildeExpand(app_resources.tmpDir)); X X /* reply path */ X X if (app_resources.replyPath == NIL(char)) `7B X`09char *p = getenv("REPLYPATH"); X X`09if (p != NIL(char)) `7B X`09 app_resources.replyPath = XtNewString(p); X`09`7D X `7D X /* top list line limits */ X if (app_resources.topLines < 3) X`09app_resources.topLines = 3; X if (app_resources.minLines == -1) X`09app_resources.minLines = app_resources.topLines/2; X X if (app_resources.maxLines == -1) X`09app_resources.maxLines = app_resources.topLines/2; X X if (app_resources.popupButton != 2 && X app_resources.popupButton != 3) `7B X#ifdef MOTIF X`09printf("Invalid popup button, default 3 used.\n"); X app_resources.popupButton = 3; X#else X`09printf("Invalid popup button, default 2 used.\n"); X app_resources.popupButton = 2; X#endif X `7D X#ifdef VMS X ptr = getenv("FULLNAME"); X if (ptr != NULL) `7B X`09app_resources.personalName = XtNewString(ptr); X `7D X#endif X X /* line breaking */ X if (app_resources.editorCommand != NIL(char)) `7B X`09app_resources.breakLength = 0; X`09app_resources.lineLength = 0; X `7D X X return widget; X`7D $ CALL UNPACK RESOURCES.C;1 776652691 $ create 'f' X#ifndef RESOURCES_H X#define RESOURCES_H X X/* X * $Header: /net/opus/mnt/ricks/src/X/xrn/RCS/resources.h,v 1.15 90/09/29 01 V:11:05 ricks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X X#ifndef _XtIntrinsic_h X#include X#endif X X#ifndef AVL_H X#include "avl.h" X#endif X X/* X * resources.h: resources for xrn X */ X X#define NAME_SIZE 1024 X Xtypedef struct `7B X char progName`5BNAME_SIZE`5D; X char* version; X avl_tree *headerTree; X int headerMode; X char *geometry; X char *iconGeometry; X char *iconName; X char *unreadIconName; X char *title; X char *saveDir; X char *expandedSaveDir; X char *newsrcFile; X char *saveNewsrcFile; X char *signatureFile; X char *nntpServer; X int topLines; X int saveMode; X char *leaveHeaders; X char *stripHeaders; X char *savePostings; X char *deadLetters; X int minLines; X int maxLines; X int defaultLines; X int cancelCount; X#ifndef VMS X char *mailer; X#else X char *personalName; X#endif X Boolean iconOnStart; X Boolean subjectRead; X Boolean info; X char *tmpDir; X char *confirm; X int confirmMode; X Boolean killFiles; X Boolean calvin; X char *editorCommand; X char *strSaveMode; X char *organization; X char *distribution; X char *replyTo; X Boolean includeHeader; X char* includePrefix; X Boolean includeSep; X Boolean updateNewsrc; X int lineLength; X int breakLength; X int rescanTime; X Boolean pageArticles; X Boolean sortedSubjects; X Boolean typeAhead; X int prefetchMax; X char *addButtonList; X char *ngButtonList; X char *allButtonList; X char *artButtonList; X char *artSpecButtonList; X char *printCommand; X char *ngBindings; X char *allBindings; X char *addBindings; X char *artBindings; X char *hostName; X char *replyPath; X char *addPopupList; X char *ngPopupList; X char *allPopupList; X char *artPopupList; X int popupButton; X Boolean dumpCore; X Boolean verboseKill; X Boolean cc; X Boolean autoRead; X Boolean useGadgets; X Boolean authorFullName; X#ifdef REALLY_USE_LOCALTIME X Boolean displayLocalTime; X#endif X Boolean displayLineCount; X char *resetSave; X char *saveString; X`7D app_resourceRec, *app_res; X Xextern app_resourceRec app_resources; X Xextern Widget XrnInitialize(/* int argc, char **argv */); X X/* article save options */ X X#define MAILBOX_SAVE 0x01 X#define NORMAL_SAVE 0x02 X#define HEADERS_SAVE 0x10 X#define NOHEADERS_SAVE 0x20 X X#define ONEDIR_SAVE 0x100 X#define SUBDIRS_SAVE 0x200 X X/* confirm box options */ X X#define NG_EXIT 0x01 X#define NG_QUIT 0x02 X#define NG_CATCHUP 0x04 X#define NG_UNSUBSCRIBE 0x08 X#define ART_CATCHUP 0x10 X#define ART_PART_CATCHUP 0x20 X#define ART_UNSUBSCRIBE 0x40 X#define ART_FEDUP 0x80 X#define ART_ENDACTION 0x100 X#define ART_SAVE 0x200 X X/* header options */ X X#define STRIP_HEADERS 0 X#define LEAVE_HEADERS 1 X X#endif /* RESOURCES_H */ $ CALL UNPACK RESOURCES.H;1 491535381 $ create 'f' XReturn-Path: braun@thumper.bellcore.com XReceived: from eros.Berkeley.EDU by shambhala.Berkeley.EDU (5.61/1.28) X`09id AA14862; Mon, 23 Oct 89 07:01:47 -0700 XReceived: by eros.berkeley.edu (5.57/1.28) X`09id AA13983; Mon, 23 Oct 89 07:01:41 PDT XReceived: by thumper.bellcore.com (5.54/4.7) X`09id AA12009; Mon, 23 Oct 89 10:00:12 EDT XReceived: by wrath.bellcore.com (4.12/4.7) X`09id AA02716; Mon, 23 Oct 89 09:59:28 edt XDate: Mon, 23 Oct 89 09:59:28 edt XFrom: braun@thumper.bellcore.com (David A. Braun) XMessage-Id: <8910231359.AA02716@wrath.bellcore.com> XTo: xrn@eros.berkeley.edu XSubject: GRIPE about XRN 6.0 XCc: braun@thumper.bellcore.com X XIn reference to my previous gripe about invisible button captions. It seems Xto be related to the color selections in the default default definitions X(which are in ..../Xlib/app-defaults/XRn on my system). If I change all the Xcolors to Black or White in my personal defaults database (via xrdb) then Xeverything but the box borders is fine. I have to turn reverseVideo "off" Xfor xrn to get the boxes to show. I've attached the pertenent part of my Xdatabase below. X Xdave braun Xbraun@thumper.bellcore.com X X! X!`09X11 defaults file -- used by X programs to set their X!`09defaults X! X! X! -------------------------------------------------------- X! X!`09GLOBAL DEFAULTS X! X*Font:`09`09`09`09`099x15 X*BoldFont:`09`09`09`099x15 X*SaveUnder:`09`09`09`09on X*saveUnder:`09`09`09`09on X*saveunder:`09`09`09`09on X#ifdef REVERSEVIDEO X!*Border:`09`09`09`09white X!*BorderColor:`09`09`09white X*ReverseVideo:`09`09`09on X*reverse:`09`09`09`09on X*Reverse:`09`09`09`09on X#endif REVERSEVIDEO X#ifdef`09COLOR X*MenuMouse:`09`09`09`09`09red X*MenuBackground:`09`09`09green X*PaneForeground:`09`09`09red X*SelectionForeground:`09`09blue X#endif X*MenuMode:`09`09`09`09`09invert X*MenuStyle:`09`09`09`09`09right_hand X*MenuInactivePattern:`09`09dimple3 X*PaneFont:`09`09`09`09`09helvetica12bi X*SelectionFont:`09`09`09`09helvetica12 X! X!`09XRN X! X#ifndef COLOR X! X! first my version of the defaults X! XXrn*Geometry:`09`09`09`09`09800x680 XXrn*font:`09`09`09`09`09`098x13 XXrn*Label.font:`09`09`09`09`098x13 XXrn*Command.font:`09`09`09`099x15 XXrn*Dialog.borderWidth:`09`09`091 X! Xxrn*background:`09`09`09`09`09White Xxrn*foreground:`09`09`09`09`09Black Xxrn*font:`09`09`09`09`09`099x15 Xxrn*border:`09`09`09`09`09`09Black X! Xxrn*Text*background:`09`09`09White Xxrn*Text*foreground:`09`09`09Black Xxrn*Text*Background:`09`09`09White Xxrn*Text*Foreground:`09`09`09Black Xxrn*ScrollBarMgr.thickness:`09`0922 Xxrn*ScrollBar.background:`09 `09White Xxrn*ScrollBar.foreground:`09 `09Black Xxrn*ScrollBar.border:`09 `09`09Black X Xxrn*Label.background:`09`09`09White Xxrn*Label.foreground:`09`09`09Black Xxrn*Label.font:`09`09`09`09`09-adobe-times-bold-r-normal--14-140-75-75-p-77- Viso8859-1 X Xxrn*Command.foreground:`09`09`09Black Xxrn*Command.background:`09`09`09White Xxrn*Command.font:`09`09`09`09-adobe-itc avant garde gothic-book-r-normal--12 V-120-75-75-p-70-iso8859-1 X! Xxrn*Box.ngQuit.foreground:`09`09Black Xxrn*Box.ngQuit.background:`09`09White Xxrn*Box.ngExit.foreground:`09`09Black Xxrn*Box.ngExit.background:`09`09White Xxrn*Box.ngRescan.foreground:`09Black Xxrn*Box.ngRescan.background:`09White Xxrn*Box.ngUnsub.foreground:`09`09Black Xxrn*Box.ngUnsub.background: `09White Xxrn*Box.ngSubscribe.foreground: Black Xxrn*Box.ngSubscribe.background:`09White Xxrn*Box.artQuit.foreground:`09`09Black Xxrn*Box.artQuit.background:`09`09White Xxrn*Box.artSave.foreground:`09`09Black Xxrn*Box.artSave.background:`09`09White Xxrn*Box.artNextUnread.font:`09`099x15 Xxrn*Box.addQuit.foreground:`09`09Black Xxrn*Box.addQuit.background:`09`09White X! Xxrn*dialog*font:`09`09`09`09-adobe-helvetica-bold-r-normal--12-120-75-75-p-7 V0-iso8859-1 Xxrn*dialog*background:`09`09`09White Xxrn*dialog*foreground:`09`09`09Black Xxrn*dialog*Label.foreground:`09Black Xxrn*dialog*Command.foreground:`09Black Xxrn*dialog*Command.background:`09White Xxrn*dialog*Text.background:`09`09White Xxrn*dialog*Text.foreground:`09`09Black XXrn*dialog*borderWidth:`09`09`092 X#endif X! X! now my dung X! Xxrn*font:`09`09`099x15 Xxrn*nntpServer:`09`09bellcore Xxrn*editorCommand:`09xterm -e vi %s Xxrn*organization:`09Multimedia Communications Systems Research Group (Bellco Vre) Xxrn*replyTo:`09`09braun@thumper.bellcore.com Xxrn*leaveHeaders:`09subject,from Xxrn*ReverseVideo:`09off X $ CALL UNPACK REVERSE-VIDEO.;1 843236063 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/save.c,v 1.1 V2 90/09/29 01:13:07 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * save.c: routines for saving articles and sending articles to processes X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include X#include "utils.h" X#include "config.h" X#ifndef VMS X#include X#else X#define MAXPATHLEN 512 X#ifndef R_OK X#define F_OK 0 /* does file exist */ X#define X_OK 1 /* is it executable by caller */ X#define W_OK 2 /* writable by caller */ X#define R_OK 4 /* readable by caller */ X#endif /* R_OK */ X#define index strchr X#endif /* VMS */ X#include X#ifndef VMS X#include X#else X#include X#endif X#include "news.h" X#include "resources.h" X#include "dialogs.h" X#include "error_hnds.h" X#include "server.h" X#include "mesg.h" X#include "save.h" X#include "xmisc.h" X#include "xrn.h" X Xextern int errno; X X#define BUFFER_SIZE 1024 X X X#ifndef VMS Xstatic int XprocessArticle(command, artfile) Xchar *command; Xchar *artfile; X/* X * send the current article to 'command' X * X * returns: the exit status of the command X * X */ X`7B X FILE *process; X extern FILE *popen();`09/* sequent */ X char *artPtr; X int c, status; X X if ((process = popen(command, "w")) == NULL) `7B X`09mesgPane(XRN_SERIOUS, "can not start `60%s'", command); X`09return(0); X `7D X X artPtr = artfile; X while ((c = *artPtr) != '\0') `7B X`09(void) putc((char) c, process); X`09artPtr++; X `7D X X status = pclose(process); X X return(status); X`7D X#endif /* VMS */ X Xint XcreateNewsDir() X/* X * make sure that the news directory exists before trying to update it X * X * returns: 0 for failure, 1 for okay X */ X`7B X static int done = 0; X char *newdir; X X if (done) `7B X`09return(1); X `7D X if ((newdir = utTildeExpand(app_resources.saveDir)) == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot create save directory `60%s'", app_resource Vs.saveDir); X`09return(0); X `7D X if ((mkdir(newdir, 0777) == -1) && (errno != EEXIST)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot create save directory `60%s': %s", X`09`09 app_resources.saveDir, errmsg(errno)); X`09return(0); X `7D X done = 1; X app_resources.expandedSaveDir = XtNewString(newdir); X X return(1); X`7D X X X#ifdef VMS Xstatic void XVmsMakeDirName(dummy, savedir, Group) X char *dummy; X char *savedir; X char *Group; X`7B X int temp; X (void) strcpy(dummy, savedir);`09/* Copy save directory name */ X temp = strlen(dummy);`09`09/* Fetch the length */ X if (dummy`5Btemp-1`5D = '`5D') `7B`09`09/* If a directory spec, */ X dummy`5Btemp-1`5D = '.';`09`09/* Convert to a . */ X `7D else `7B X`09(void) strcat(dummy, "`5B.");`09/* Else, start directory */ X `7D X (void) strcat(dummy, Group);`09/* Add the group name */ X (void) strcat(dummy, "`5D");`09`09/* Now terminate the string */ X`7D X#endif /* VMS */ X X Xstatic char * XbuildFileName(filename, savedir, group) Xchar *filename; /* file name, possibly with a '`7E' */ Xchar *savedir; /* save directory */ Xchar *group; /* name of the news group */ X/* X * expand a file name for 'saving' a file X * X * returns: the name of the file or NIL(char) if the filename is bad X * (i.e. `7Euser/xx where 'user' is not a valid user name) X * the area returned is static X * X */ X`7B X char Group`5BGROUP_NAME_SIZE`5D; X#ifdef aiws X static char dummy`5BMAXPATH`5D; X#else X static char dummy`5BMAXPATHLEN`5D; X#endif /* aiws */ X#ifdef VMS X char *dot;`09 /* Pointer to dots to convert to underscores */ X#endif X X#ifndef VMS X /* Make a local copy of the group name for modification */ X (void) strncpy(Group, group, sizeof(Group)); X /* upcase the first letter of the group name (same as 'rn') */ X if (islower(Group`5B0`5D)) `7B X`09Group`5B0`5D = toupper(Group`5B0`5D); X `7D X#else /* VMS */ X /* First, use the generic group to filename conversion routine and X convert the group name to a filename */ X (void) utGroupToVmsFilename(Group, group); X X /* If we are in ONEDIR_SAVE mode, find the first underscore character X and convert it (back) to a dot. This is done for compatibility with X VNEWS. */ X if (app_resources.saveMode & ONEDIR_SAVE) `7B X`09if (dot = index(Group, '_')) `7B X`09 *dot = '.'; X`09`7D X `7D X#endif X X if ((filename == NIL(char)) `7C`7C (*filename == '\0')) `7B X`09if (app_resources.saveMode & ONEDIR_SAVE)`7B X#ifndef VMS X`09 (void) sprintf(dummy, "%s/%s", savedir, Group); X#else X`09 (void) sprintf(dummy, "%s%s", savedir, Group); X#endif X`09`7D else `7B X`09 /* use "saveDir/group" */ X#ifndef VMS X`09 (void) sprintf(dummy, "%s/%s", savedir, group); X#else X`09 VmsMakeDirName(dummy, savedir, Group); X#endif /* VMS */ X`09 (void) mkdir(utTildeExpand(dummy), 0777); X#ifndef VMS X`09 (void) strcat(dummy, "/"); X#endif /* VMS */ X`09 (void) strcat(dummy, Group); X#ifdef VMS X`09 if (!(app_resources.saveMode & ONEDIR_SAVE)) `7B X`09`09(void) strcat(dummy, ".ART"); X`09 `7D X#endif /* VMS */ X`09`7D X`09return(utTildeExpand(dummy)); X `7D X X#ifndef VMS X if ((filename`5B0`5D == '/') `7C`7C (filename`5B0`5D == '`7E')) `7B X`09return(utTildeExpand(filename)); X `7D X#else X if ((index(filename, ':')) `7C`7C (index(filename, '`5B')) X`09`09`7C`7C (index(filename, '<'))) `7B X`09return(utTildeExpand(filename)); X `7D X#endif /* VMS */ X X if (app_resources.saveMode & ONEDIR_SAVE) `7B X#ifndef VMS X`09(void) sprintf(dummy, "%s/%s", savedir, filename); X#else /* VMS */ X`09(void) sprintf(dummy, "%s%s", savedir, filename); X#endif /* VMS */ X `7D else `7B X`09/* use "saveDir/group/filename" */ X#ifndef VMS X`09(void) sprintf(dummy, "%s/%s", savedir, group); X#else /* VMS */ X`09VmsMakeDirName(dummy, savedir, Group); X#endif /* VMS */ X`09(void) mkdir(utTildeExpand(dummy), 0777); X#ifndef VMS X`09(void) strcat(dummy, "/"); X#endif /* VMS */ X`09(void) strcat(dummy, filename); X `7D X return(utTildeExpand(dummy)); X`7D X X Xint XsaveArticleByNumber(filename, art) Xchar *filename; Xart_num art; X`7B X return saveArticle(filename, Newsrc`5BCurrentGroupNumber`5D, art); X`7D X X Xint XsaveRangeOfArticles(filenameTemplate, start, end) Xchar *filenameTemplate; Xart_num start; Xart_num end; X/* X * save the a range of articles from start to end, X * X * filenameTemplate is a sprintf compatible string X * X * examples: "mg.%d", "`7C save-it" X * X * %d will be filled in with the article number X * X * returns: 1 for OKAY, 0 for FAILURE X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X /* art_num save_current = newsgroup->current; */ X art_num i; X char buffer`5B1024`5D; X X for (i = start; i <= end; i++) `7B X`09(void) sprintf(buffer, filenameTemplate, i); X`09saveArticle(buffer, newsgroup, i); X `7D X return(1); X`7D X X X#define XRNsave_OVERWRITE 1 X#define XRNsave_APPEND 2 X#define XRNsave_ABORT 3 Xstatic Widget OverBox = (Widget) 0;`09/* for overwrite dialog */ Xstatic int OverVal; X Xstatic void XoverwriteHandler(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X OverVal = (int) client_data; X return; X`7D X Xstatic int overwriteOK() X`7B X XEvent ev; X static struct DialogArg args`5B`5D = `7B X`09`7B"Overwrite", overwriteHandler, (caddr_t) XRNsave_OVERWRITE`7D, X`09`7B"Append", overwriteHandler, (caddr_t) XRNsave_APPEND`7D, X`09`7B"Abort", overwriteHandler, (caddr_t) XRNsave_ABORT`7D, X `7D; X X if (OverBox == (Widget) 0) `7B X`09OverBox = CreateDialog(TopLevel, X`09`09"File already exists. Overwrite or append?", X`09`09DIALOG_NOTEXT, args, XtNumber(args)); X `7D X OverVal = -1; X PopUpDialog(OverBox); X for (;;) `7B X`09XtNextEvent(&ev); X`09(void) XtDispatchEvent(&ev); X`09if (OverVal != -1) `7B X`09 PopDownDialog(OverBox); X`09 return(OverVal); X`09`7D X `7D X`7D Xint XsaveArticle(filename, newsgroup, art) Xchar *filename; Xstruct newsgroup *newsgroup; Xart_num art; X`7B X char timeString`5BBUFFER_SIZE`5D; X extern char *ctime(); X int error = 0; X time_t clockTime; X long pos; X char *artfile, *fullName; X char *artPtr, *strPtr, artChar; X FILE *fpsave; X int rotation; X char mode`5B2`5D, string`5BBUFFER_SIZE`5D; X int strUsed; X int c; X struct stat buf; X char *question; X X if ((filename != NIL(char)) && (*filename != '\0')) `7B X`09filename = utTrimSpaces(filename); X `7D X X /* get the FULL article */ X#ifdef XRN_PREFETCH X if (!invalidatePrefetchedGroup(newsgroup)) `7B X`09mesgPane(XRN_SERIOUS, "The newsgroup has been deleted out from underneath V us"); X`09return(0); X `7D X#endif /* XRN_PREFETCH */ X X rotation = (IS_ROTATED(newsgroup->articles`5BINDEX(art)`5D) ? ROTATED : V NOT_ROTATED); X/* X * Try to get the article out of the cache X */ X if (rotation == NOT_ROTATED) `7B X if ((artfile = newsgroup->articles`5BINDEX(art)`5D.filename) == NULL V) `7B X`09 artfile = getarticle(art, &pos, FULL_HEADER, rotation); X`09`7D else `7B X`09 artfile = XtNewString(artfile); X`09`7D X `7D else `7B X`09artfile = getarticle(art, &pos, FULL_HEADER, rotation); X `7D X X if (artfile == NULL) `7B X`09mesgPane(XRN_SERIOUS, "Could not get article %d to save",art); X return(0); X `7D X `20 X#ifndef VMS X /* see if the file name is actually a command specification */ X if ((filename != NIL(char)) && (filename`5B0`5D == '`7C')) `7B X`09int status; X`09(void) sprintf(error_buffer, "Piping article %ld into command `60%s'... V ", X`09`09 newsgroup->current, &filename`5B1`5D); X`09infoNow(error_buffer); X `09status = processArticle(utTrimSpaces(&filename`5B1`5D), artfile); X`09FREE(artfile); X`09if (status) `7B X`09 (void) sprintf(error_buffer, "`60%s' exited with status %d", X`09`09`09`09&filename`5B1`5D, status); X`09`7D else `7B X`09 (void) strcat(error_buffer, "done"); X`09`7D X`09(void) strcpy(&error_buffer`5Bstrlen(error_buffer) - 4`5D, "done"); X`09info(error_buffer); X`09return(status == 0); X `7D X#endif X X /* XXX not quite right, don't want to try to create it if not used... */ X if (!createNewsDir()) `7B X`09FREE(artfile); X`09return(0); X `7D X `20 X if ((fullName = buildFileName(filename, app_resources.saveDir, newsgroup V->name)) == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, "Cannot figure out file name `60%s': %s", X`09`09filename, errmsg(errno)); X`09FREE(artfile); X`09return(0); X `7D X X if (stat(fullName, &buf) == 0) `7B X`09if (app_resources.confirmMode & ART_SAVE) `7B X`09 switch (overwriteOK()) `7B X`09`09case XRNsave_ABORT: X`09`09return(0); X X`09`09case XRNsave_OVERWRITE: X`09`09(void) strcpy(mode, "w"); X`09`09busyCursor(); X`09`09break; X`09 `20 X`09`09case XRNsave_APPEND: X`09`09(void) strcpy(mode, "a"); X`09`09busyCursor(); X`09`09break; X`09 `7D X`09`7D else `7B X`09 (void) strcpy(mode, "a"); X`09`7D X `7D else `7B X`09(void) strcpy(mode, "w"); X `7D X `20 X if ((fpsave = fopen(fullName, mode)) == NULL) `7B X`09if (mode`5B0`5D == 'w') `7B X`09 (void) sprintf(error_buffer, "Cannot create file `60%s': %s", X`09`09fullName, errmsg(errno)); X`09`7D else `7B X`09 (void) sprintf(error_buffer, "Cannot append to file `60%s': %s", X`09`09fullName, errmsg(errno)); X`09`7D X`09mesgPane(XRN_SERIOUS, error_buffer); X`09FREE(artfile); X`09return(0); X `7D X X if (mode`5B0`5D == 'w') `7B X`09(void) sprintf(error_buffer, "Saving article %ld in file `60%s'... ", X`09`09`09 art, fullName); X `7D else `7B X`09(void) sprintf(error_buffer, "Appending article %ld to file `60%s'... V ", X`09`09 art, fullName); X `7D`09 X `20 X infoNow(error_buffer); X X if ((app_resources.saveMode & MAILBOX_SAVE) == MAILBOX_SAVE) `7B X`09(void) time(&clockTime); X`09(void) strcpy(timeString, ctime(&clockTime)); X`09timeString`5ButStrlen(timeString) - 1`5D = '\0'; /* get rid of the newli Vne */ X X artPtr = artfile; X`09while (*artPtr != '\0') `7B X`09 strPtr = string; X`09 strUsed = 0; X`09 while ((artChar = *artPtr) != '\0') `7B X`09`09*strPtr = artChar; X`09`09strPtr++;strUsed++; X`09`09if (artChar == '\0') X`09`09 break; X`09`09artPtr++; X`09`09if (artChar == '\n') X`09`09 break; X`09`09if (strUsed >= BUFFER_SIZE-1) X`09`09 break; X`09 `7D X`09 *strPtr = '\0'; X`09 if (STREQN(string, "Path:", 5)) `7B X`09`09string`5ButStrlen(string) - 1`5D = '\0'; /* get rid of the newline V */ X`09`09(void) fprintf(fpsave, "From %s %s\n", &string`5B6`5D, timeString); X`09`09break; X`09 `7D X`09`7D X `7D X X (void) fprintf(fpsave, "Article %ld of %s:\n", art, newsgroup->name); X X if ((app_resources.saveMode & MAILBOX_SAVE) == MAILBOX_SAVE) `7B X`09if ((app_resources.saveMode & HEADERS_SAVE) == HEADERS_SAVE) `7B X`09 int found = 0; X`09 `20 X`09 artPtr = artfile; X`09 while (*artPtr != '\0') `7B X`09`09strPtr = string; X`09`09strUsed = 0; X`09`09while ((artChar = *artPtr) != '\0') `7B X`09`09 *strPtr = artChar; X`09`09 strPtr++;strUsed++; X`09`09 if (artChar == '\0') X`09`09`09break; X`09`09 artPtr++; X`09`09 if (artChar == '\n') X`09`09`09break; X`09`09 if (strUsed >= BUFFER_SIZE - 1) X`09`09`09break; X`09`09`7D X`09 *strPtr = '\0'; X`09`09if (!found && STREQN(string, "From:", 5)) `7B X`09`09 found = 1; X`09`09 (void) fprintf(fpsave, ">From %s", &string`5B6`5D); X`09`09`7D else `7B X`09`09 (void) fputs(string, fpsave); X`09`09`7D X`09 `7D`09 `20 X`09`7D X `7D else `7B X`09artPtr = artfile; X`09while (*artPtr != '\0') `7B X`09 strPtr = string; X`09 strUsed = 0; X`09 while ((artChar = *artPtr) != '\0') `7B X`09`09*strPtr = artChar; X`09`09strPtr++;strUsed++; X`09`09if (artChar == '\0') X`09`09 break; X`09`09artPtr++; X`09`09if (artChar == '\n') X`09`09 break; X`09`09if (strUsed >= BUFFER_SIZE - 1) X`09`09 break; X`09 `7D X`09 *strPtr = '\0'; X`09 (void) fputs(string, fpsave); X`09`7D X `7D X X (void) fprintf(fpsave, "\n\n"); X (void) fclose(fpsave); X X FREE(artfile); X X (void) strcpy(&error_buffer`5ButStrlen(error_buffer) - 4`5D, "done"); X infoNow(error_buffer); X X SET_SAVED(newsgroup->articles`5BINDEX(art)`5D); X X return 1; X`7D X X Xint XsaveCurrentArticle(filename) Xchar *filename; X/* X * save the current article in 'filename' (if it begins with '`7C', send it V to X * a process) X * X * returns: 1 for OKAY, 0 for FAILURE X * X */ X`7B X struct newsgroup *newsgroup = Newsrc`5BCurrentGroupNumber`5D; X return saveArticle(filename, newsgroup, newsgroup->current); X`7D $ CALL UNPACK SAVE.C;1 1967959750 $ create 'f' X#ifndef SAVE_H X#define SAVE_H X X/* X * $Header: /users/ricks/xrn/src/RCS/save.h,v 1.7 90/09/29 01:11:07 ricks Ex Vp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * save.h: routines for saving articles and sending articles to processes X */ X X Xextern int saveCurrentArticle(/* char *filename */); Xextern int saveArticleByNumber(/* char *filename, art_num art */); X X#endif /* SAVEARTICLE_H */ $ CALL UNPACK SAVE.H;1 538853758 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/server.c,v 1 V.17 90/09/29 01:13:11 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * server.c: routines for communicating with the NNTP remote news server X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include X#include "utils.h" X#include X#ifndef VMS X#include X#else X#define MAXPATHLEN 512 X#define index strchr X#endif X#include "config.h" X#include "xrn.h" X#include "avl.h" X#include "news.h" X#include "mesg.h" X#include "error_hnds.h" X#include "resources.h" X#include "server.h" X#include "dialogs.h" X#include "xthelper.h" X X#define BUFFER_SIZE 1024 X#define MESSAGE_SIZE 1024 X Xextern Boolean allowErrors; X Xint ServerDown = 0; Xstatic char mybuf`5BMESSAGE_SIZE+100`5D =`20 X`09"The news server is not responding correctly, aborting\n"; X Xstatic void Xget_data_from_server(str, size) Xchar *str; /* string for message to be copied into */ Xint size; /* size of string */ X/* X * get data from the server (active file, article) X * X * on error, sets 'ServerDown' X * X * returns: void X */ X`7B X xthHandlePendingExposeEvents(); X if (get_server(str, size) < 0) `7B X`09ServerDown = 1; X `7D else `7B X`09ServerDown = 0; X `7D X return; X`7D X X Xstatic void Xcheck_time_out(command, response, size) Xchar *command; /* command to resend */ Xchar *response; /* response from the command */ Xint size; /* size of the response buffer */ X`7B X /* X * try to recover from a timeout X * X * this assumes that the timeout message stays the same X * since the error number (503) is used for more than just X * timeout X * X * Message is: X * 503 Timeout ... X */ X X if (ServerDown `7C`7C STREQN(response, "503 Timeout", 11)) `7B X X`09mesgPane(XRN_SERIOUS, "Lost connection to the NNTP server, attempting to V reconnect"); X`09start_server(NIL(char)); X`09mesgPane(XRN_INFO, "Reconnected to the NNTP server"); X`09 X`09/* X`09 * if it was an ARTICLE for XHDR command, then you must get the X`09 * server into the right state (GROUP mode), so resend the last X`09 * group command X`09 */ X`09if (STREQN(command, "ARTICLE", 7) `7C`7C STREQN(command, "XHDR", 4)) `7B X`09 if (getgroup(NIL(char), NIL(art_num), NIL(art_num), NIL(int)) == NO_G VROUP) `7B X`09`09return; X`09 `7D X`09 /* XXX should do some processing of changed first/last numbers */ X`09`7D X`09 X`09put_server(command); X`09get_data_from_server(response, size); X `7D X `20 X return; X`7D X X Xchar * Xgetarticle(artnumber, position, header, rotation) Xart_num artnumber; /* number of article in the current group to retrieve */ Xlong *position; /* byte position of header/body seperation */ Xint header, rotation; X/* X * retrieve article number 'artnumber' in the current group, update structur Ve X * X * returns: article text or NIL(char) if the article is not avaiable X * X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D, *msg; X#ifdef REALLY_USE_LOCALTIME X char temp`5BMESSAGE_SIZE`5D; X#endif X static char`09*artstring = NULL; X char *newartstring = NULL; X static int`09artstringsize = 0; X char *ptr; X char *endPtr; X int segSize; X char field`5BBUFFER_SIZE`5D; X int byteCount = 0, lineCount = 0; X X if (artstring == NULL) `7B X`09artstring = XtMalloc(100000); X artstringsize = 100000; X `7D X *position = 0; X *artstring = '\0'; X `20 X /* send ARTICLE */ X (void) sprintf(command, "ARTICLE %ld", artnumber); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X X if (*message != CHAR_OK) `7B X`09/* can't get article */ X`09return(NIL(char)); X `7D X X endPtr = artstring; X for (;;) `7B X`09if (byteCount + MESSAGE_SIZE > artstringsize) `7B X`09 newartstring = XtMalloc(artstringsize + 100000); X`09 artstringsize += 100000; X`09 strcpy (newartstring, artstring); X`09 XtFree(artstring); X`09 artstring = newartstring; X`09 endPtr = artstring + byteCount; X`09`7D X`09get_data_from_server(message, sizeof(message)); X X`09/* the article is ended by a '.' on a line by itself */ X`09if ((message`5B0`5D == '.') && (message`5B1`5D == '\0')) `7B X`09 /* check for a bogus message */ X`09 if (byteCount == 0) `7B X`09`09return(NIL(char)); X`09 `7D X`09 break; X`09`7D X X`09msg = &message`5B0`5D; X X`09/* find header/body seperation */ X`09if (*position == 0) `7B X`09 if (*msg == '\0') `7B X`09`09*position = byteCount; X`09 `7D X`09`7D X`09 `20 X`09if (*msg == '.') `7B X`09 msg++; X`09`7D X X`09if (*msg != '\0') `7B X`09 /* strip leading `5EH */ X`09 while (*msg == '\b') `7B X`09`09msg++; X`09 `7D X`09 /* strip '`5EH' */ X`09 for (ptr = index(msg + 1, '\b'); ptr != NIL(char); ptr = index(ptr, ' V\b')) `7B X`09`09if (ptr - 1 < msg) `7B X`09`09 /* too many backspaces, kill all leading back spaces */ X`09`09 while (*ptr == '\b') `7B X`09`09 (void) strcpy(ptr, ptr + 1); X`09`09`09ptr++; X`09`09 `7D X`09`09 break; X`09`09`7D X`09`09(void) strcpy(ptr - 1, ptr + 1); X`09`09ptr--; X`09 `7D X X#ifdef REALLY_USE_LOCALTIME X `09 if (app_resources.displayLocalTime && !strncmp(msg, "Date: ", 6)) ` V7B X`09`09 tconvert(temp, msg+6); X`09`09 (void) strcpy(msg+6, temp); X`09 `7D X#endif X`09 /* strip the headers */ X`09 if ((*position == 0) && (header == NORMAL_HEADER)) `7B X`09`09if ((ptr = index(msg, ':')) == NIL(char)) `7B X`09`09 continue; /* weird header line, skip */ X`09`09`7D X`09`09if (*(ptr+1) == '\0') `7B X`09`09 continue; /* empty field, skip */ X`09`09`7D X`09`09(void) strncpy(field, msg, (int) (ptr - msg)); X`09`09field`5B(int) (ptr - msg)`5D = '\0'; X`09`09utDowncase(field); X`09`09if (avl_lookup(app_resources.headerTree, field, &ptr)) `7B X`09`09 if (app_resources.headerMode == STRIP_HEADERS) `7B X`09`09`09continue; X`09`09 `7D X`09`09`7D else `7B X`09`09 if (app_resources.headerMode == LEAVE_HEADERS) `7B X`09`09`09continue; X`09`09 `7D X`09`09`7D X`09 `7D X X`09 /* handle rotation of the article body */ X`09 if ((rotation == ROTATED) && (*position != 0)) `7B X`09`09for (ptr = msg; *ptr != '\0'; ptr++) `7B X`09`09 if (isalpha(*ptr)) `7B X`09`09`09if ((*ptr & 31) <= 13) `7B X`09`09`09 *ptr = *ptr + 13; X`09`09`09`7D else `7B X`09`09`09 *ptr = *ptr - 13; X`09`09`09`7D X`09`09 `7D X`09`09`7D X`09 `7D X X`09 /* handle `5EL (poorly?) */ X`09 if (*msg == '\014') `7B X`09`09int i, lines; X`09`09lines = articleLines(); X`09`09lines -= lineCount % lines; X`09`09for (i = 0; i < lines; i++) `7B X`09`09 (void) strcpy(endPtr, "\n"); X`09`09 endPtr++; X`09`09`7D X`09`09byteCount += lines; X`09`09lineCount += lines; X`09`09continue; X`09 `7D X`09 (void) strcpy(endPtr, msg); X`09`7D X`09segSize = utStrlen(msg); X`09byteCount += segSize + 1; X`09endPtr += segSize; X`09*endPtr++ = '\n'; X`09*endPtr = '\0'; X`09lineCount++; X `7D X X return(XtNewString(artstring)); X`7D X X Xint Xgetgroup(name, first, last, number) Xchar *name; /* group name */ Xart_num *first; /* first article in the group */ Xart_num *last; /* last article in the group */ Xint *number; /* number of articles in the group, if 0, first and last are V bogus */ X/* X * enter a new group and get its statistics (and update the structure) X * allocate an array for the articles and process the .newsrc article X * info for this group X * X * returns: NO_GROUP on failure, 0 on success X * X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D; X char group`5BGROUP_NAME_SIZE`5D; X long code, num, count, frst, lst; X static char lastGroup`5BGROUP_NAME_SIZE`5D; X X if (name == NIL(char)) `7B X`09name = XtNewString(lastGroup); X `7D else `7B X`09(void) strcpy(lastGroup, name); X `7D X X (void) sprintf(command, "GROUP %s", name); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X `20 X if (*message != CHAR_OK) `7B X`09if (atoi(message) != ERR_NOGROUP) `7B X X`09`09(void) strcat(mybuf, "`09Request was: "); X`09`09(void) strcat(mybuf, command); X`09`09(void) strcat(mybuf, "\n"); X`09`09(void) strcat(mybuf, "`09Failing response was: "); X`09`09(void) strcat(mybuf, message); X`09`09ehErrorExitXRN(mybuf); X`09`7D X`09mesgPane(XRN_SERIOUS, "Can't get the group, looks like it was deleted out V from under us"); X`09 X`09/* remove the group from active use ??? */ X`09 X`09return(0); X `7D X X /* break up the message */ X count = sscanf(message, "%ld %ld %ld %ld %s", &code, &num, &frst, &lst, V group); X assert(count == 5); X X if (number != NIL(int)) `7B X`09*number = num; X `7D X if (first != NIL(art_num)) `7B X`09*first = frst; X `7D X if (last != NIL(art_num)) `7B X`09*last = lst; X `7D X X return(1); X`7D X X Xvoid Xgetactive() X/* X * get a list of all active newsgroups and create a structure for each one X * X * returns: void X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D, group`5BGROUP V_NAME_SIZE`5D; X char type`5BMESSAGE_SIZE`5D; X struct newsgroup *newsgroup; X art_num first, last; X char *ptr; X X (void) strcpy(command, "LIST"); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X `20 X if (*message != CHAR_OK) `7B X X`09(void) strcat(mybuf, "\tRequest was: "); X`09(void) strcat(mybuf, command); X`09(void) strcat(mybuf, "\n"); X`09(void) strcat(mybuf, "\tFailing response was: "); X`09(void) strcat(mybuf, message); X`09ehErrorExitXRN(mybuf); X `7D X X for (;;) `7B X`09get_data_from_server(message, sizeof(message)); X`09 X`09/* the list is ended by a '.' at the beginning of a line */ X`09if (*message == '.') `7B X`09 break; X`09`7D X X`09/* server returns: group last first y/m/x/=otherGroup */ X X`09if (sscanf(message, "%s %ld %ld %s", group, &last, &first, type) != 4) `7 VB X`09 mesgPane(XRN_SERIOUS, "Bogus active file entry, skipping\n%s", messag Ve); X`09 continue; X`09`7D X X`09if (type`5B0`5D == 'x') `7B X`09 /* bogus newsgroup, pay no attention to it */ X`09 continue; X`09`7D X X`09if (first == 0) `7B X`09 first = 1; X`09`7D X X`09if (!avl_lookup(NewsGroupTable, group, &ptr)) `7B X X`09 /* no entry, create a new group */ X`09 newsgroup = ALLOC(struct newsgroup); X`09 newsgroup->name = XtNewString(group); X`09 newsgroup->newsrc = NOT_IN_NEWSRC; X`09 newsgroup->status = NG_NOENTRY; X`09 newsgroup->first = first; X`09 newsgroup->last = last; X`09 newsgroup->nglist = 0; X#ifdef notdef X`09 if (last >= first) `7B X`09`09 (void) fprintf(stderr,"allocate %d bytes for %d articles in %s\n", V (newsgroup->last - newsgroup->first + 1) * sizeof (struct article),(newsgro Vup->last - newsgroup->first + 1), group); X`09`09newsgroup->articles = ARRAYALLOC(struct article, newsgroup->last - new Vsgroup->first + 1); X`09`09for (art = newsgroup->first; art <= newsgroup->last; art++) `7B X`09`09 long indx = INDEX(art); X`09 X`09`09 newsgroup->articles`5Bindx`5D.subject = NIL(char); X`09`09 newsgroup->articles`5Bindx`5D.author = NIL(char); X`09`09 newsgroup->articles`5Bindx`5D.lines = NIL(char); X`09`09 newsgroup->articles`5Bindx`5D.filename = NIL(char); X`09`09 newsgroup->articles`5Bindx`5D.status = ART_CLEAR; X`09`09`7D X`09 `7D else `7B X`09`09newsgroup->articles = NIL(struct article); X`09 `7D X#else X`09`09newsgroup->articles = NIL(struct article); X#endif X`09 `20 X`09 switch (type`5B0`5D) `7B X`09`09case 'y': X`09`09newsgroup->status `7C= NG_POSTABLE; X`09`09break; X X`09`09case 'm': X`09`09newsgroup->status `7C= NG_MODERATED; X`09`09break; X X`09`09case 'n': X`09`09newsgroup->status `7C= NG_UNPOSTABLE; X`09`09break; X X`09`09case '=': X`09`09/* X`09`09fprintf(stderr, "equivalenced ng (%s) for newsgroup %s\n", X`09`09`09&type`5B1`5D, newsgroup->name); X`09`09*/ X`09`09break; X X`09`09default: X`09`09/* X`09`09fprintf(stderr, "unexpected type (%s) for newsgroup %s\n", X`09`09`09type, newsgroup->name); X`09`09*/ X`09`09break; X X`09 `7D X`09 X`09 (void) avl_insert(NewsGroupTable, newsgroup->name, (char *) newsgroup V); X X`09 ActiveGroupsCount++; X`09 `20 X`09`7D else `7B X`09 `20 X`09 /* X`09 * entry exists, use it; must be a rescanning call X`09 * X`09 * just update the first and last values and adjust the X`09 * articles array X`09 */ X`09 `20 X`09 newsgroup = (struct newsgroup *) ptr; X X`09 /* X`09 * only allow last to increase or stay the same X`09 * - don't allow bogus last values to trash a group X`09 */ X`09 if (IS_SUBSCRIBED(newsgroup) && last >= newsgroup->last) `7B X`09`09/* XXX really should save up the resync and use the GROUP info also */ X`09`09articleArrayResync(newsgroup, first, last, 1); X`09 `7D X`09`7D X `7D X X return; X`7D X X Xvoid XbadActiveFileCheck() X/* X * check the case where the first and last article numbers are equal X * - unfortunately, this means two different things: X * 1) there are no articles in the group X * 2) there is one article in the group X * X * - so, to get rid of the ambiguity, we make a GROUP call X * and look at the 'number' of articles field to determine X * whether there are 0 or 1 articles X */ X`7B X avl_generator *gen; X char *key, *value; X int number; X X /* check out first == last groups */ X gen = avl_init_gen(NewsGroupTable, AVL_FORWARD); X X while (avl_gen(gen, &key, &value)) `7B X`09struct newsgroup *newsgroup = (struct newsgroup *) value; X X`09if (IS_SUBSCRIBED(newsgroup) && X`09 (newsgroup->first == newsgroup->last) && X`09 (newsgroup->first != 0)) `7B X X`09 (void) getgroup(newsgroup->name, NIL(art_num), NIL(art_num), &number) V; X`09 if (number == 0) `7B X`09`09articleArrayResync(newsgroup, newsgroup->first, newsgroup->last, numbe Vr); X`09 `7D X`09`7D X `7D X avl_free_gen(gen); X X return; X`7D X X Xvoid Xstart_server(nntpserver) Xchar *nntpserver; X/* X * initiate a connection to the news server X * X * nntpserver is the name of an alternate server (use the default if NULL) X * X * the server eventually used is remembered, so if this function is called X * again (for restarting after a timeout), it will use it. X * X * returns: void X * X */ X`7B X static char *server = NIL(char); /* for restarting */ X int response, connected, i; X#if !defined(VMS) && !defined(SVR4) X#if defined(__convexc__) X extern unsigned sleep(); X#else X extern void sleep(); X#endif X#endif X X if (server == NIL(char)) `7B X`09 X`09if (nntpserver != NIL(char)) `7B X`09 server = nntpserver; X`09 X`09`7D else `7B X`09 `20 X`09 if ((server = getserverbyfile(SERVER_FILE)) == NULL) `7B X`09`09mesgPane(XRN_SERIOUS, "Can't get the name of the news server from `60% Vs'.%s", X`09`09`09 SERVER_FILE, X#ifndef VMS X`09`09"Either fix this file, or put NNTPSERVER in your environment." X#else X`09`09"Either fix this file, or define logical NNTPSERVER" X#endif X`09`09); X`09`09ehErrorExitXRN(""); X`09 `7D X`09`7D X `7D X X do `7B X`09if ((response = server_init(server)) < 0) `7B X`09 connected = 0; X`09 close_server(); X`09 allowErrors = True; X`09 if (ConfirmationBox (TopLevel, X`09 "Failed to reconnect to the NNTP server (server_init), retry?")) `7 VB X`09`09for (i = 0; i < 60; i++) `7B X`09`09 xthHandleAllPendingEvents(); X`09`09 sleep(1); X`09`09`7D X`09`09allowErrors = False; X`09`09continue; X`09 `7D else `7B X`09`09ehCleanExitXRN(1); X`09 `7D X`09`7D X`09if (handle_server_response(response, server) < 0) `7B X`09 connected = 0; X`09 close_server(); X`09 allowErrors = True; X`09 if (ConfirmationBox (TopLevel, X "Failed to reconnect to the NNTP server (handle_response), retry?" V)) `7B X`09`09for (i = 0; i < 60; i++) `7B X`09`09 xthHandleAllPendingEvents(); X`09`09 sleep(1); X`09`09`7D X`09`09allowErrors = False; X`09`09continue; X`09 `7D else `7B X`09`09ehCleanExitXRN(1); X`09 `7D X`09`7D X`09connected = 1; X `7D while (!connected); X `20 X return; X`7D X `20 X Xvoid Xgetsubjectlist(newsgroup, first, last) Xstruct newsgroup *newsgroup; Xart_num first; Xart_num last; X/* X * get a list of subject lines for the current group in the range X * 'first' to 'last' X * X * returns: void X * X * Note that XHDR is not part of the rfc977 standard, but is implemented X * by the Berkeley NNTP server X * X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D, buffer`5BMESS VAGE_SIZE`5D; X char *subjectline; X long number; X X (void) sprintf(command, "XHDR subject %ld-%ld", first, last); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X X /* check for errors */ X if (*message != CHAR_OK) `7B X`09mesgPane(XRN_SERIOUS, X"XRN: serious error, your NNTP server does not have XHDR support.\n\ XEither you are running a pre-1.5 NNTP server or XHDR has\n\ Xnot been defined in 'nntp/common/conf.h'\n\ XXRN requires XHDR support to run."); X`09return; X `7D X X for(;;) `7B X X`09get_data_from_server(message, sizeof(message)); X`09 X`09if (*message == '.') `7B X`09 break; X`09`7D X X`09/* X`09 * message is of the form: X`09 * X`09 * Number SubjectLine X`09 * X`09 * 203 Re: Gnumacs Bindings X`09 * X`09 * must get the number since not all subjects will be returned X`09 */ X X`09number = atol(message); X`09subjectline = index(message, ' '); X`09(void) sprintf(buffer, " %5ld:%s", number, ++subjectline); X X`09newsgroup->articles`5BINDEX(number)`5D.subject = XtNewString(buffer); X `7D X return; X`7D X X Xvoid Xgetauthorlist(newsgroup, first, last) Xstruct newsgroup *newsgroup; Xart_num first; Xart_num last; X/* X * get a list of author lines for the current group in the range X * 'first' to 'last' X * X * returns: void X * X * Note that XHDR is not part of the rfc977 standard, but is implemented X * by the Berkeley NNTP server X * X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D; X char *author, *end, *brackbeg, *brackend; X long number; X X `20 X (void) sprintf(command, "XHDR from %ld-%ld", first, last); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X X /* check for errors */ X if (*message != CHAR_OK) `7B X`09mesgPane(XRN_SERIOUS, X"XRN: serious error, your NNTP server does not have XHDR support.\n\ XEither you are running a pre-1.5 NNTP server or XHDR has\n\ Xnot been defined in 'nntp/common/conf.h'\n\ XXRN requires XHDR support to run."); X`09return; X `7D X `20 X for(;;) `7B X X`09get_data_from_server(message, sizeof(message)); X`09 X`09if (*message == '.') `7B X`09 break; X`09`7D X X`09/* X`09 * message is of the form: X`09 * X`09 * Number Author X`09 * X`09 * 201 ricks@shambhala (Rick L. Spickelmier) X`09 * 202 Jens Thommasen X`09 * 203 X`09 * 302 "Rein Tollevik" X`09 * X`09 * must get the number since not all authors will be returned X`09 */ X X`09number = atol(message); X if (app_resources.authorFullName) `7B X`09/* Can be made fancyer at the expence of extra cpu time */ X`09author = index(message, ' '); X`09assert(author != NIL(char)); X`09author++; X X`09/* First check for case 1, user@domain ("name") -> name */ X X`09brackbeg = index(message, '('); X`09brackend = index(message, '\0') - sizeof(char); X`09/* brackend now points at the last ')' if this is case 1 */ X`09if (brackbeg != NIL(char) && (brackend > brackbeg) && X`09 (*brackend == ')')) `7B X`09 author = brackbeg + sizeof(char); X X`09 /* Remove surrounding quotes ? */ X`09 if ((*author == '"') && (*(brackend - sizeof(char)) == '"')) `7B X`09 author++; X`09 brackend--; X`09 `7D X X`09 /* Rather strip trailing spaces here */ X X`09 *brackend = '\0'; X`09`7D else `7B X`09 /* Check for case 2, "name" -> name */ X`09 brackbeg = index(message, '<'); X`09 if (brackbeg != NIL(char) && (index(brackbeg, '>') != NIL(char)) X`09`09&& (brackbeg > message)) `7B X`09`09while (*--brackbeg == ' ') X`09`09 ; X X`09`09/* Remove surrounding quotes ? */ X`09`09if ((*brackbeg == '"') && (*author == '"')) `7B X`09`09 *brackbeg = '\0'; X`09`09 author++; X X`09`09 /* Rather strip trailing spaces here */ X X`09`09`7D else `7B X`09`09 *++brackbeg = '\0'; X`09`09`7D X`09 `7D else `7B X X`09`09/*`20 X`09`09 * Check for case 3, -> usr@domain X`09 * X`09`09 * Don't need to do this again: X`09 * brackbeg = index(message, '<'); X */ X X`09`09brackend = index(message, '>'); X`09`09if ((author == brackbeg) && (brackend != NIL(char))) `7B X`09`09 author++; X`09`09 *brackend = '\0'; X`09`09`7D else `7B X`09`09 if ((end = index(author, ' ')) != NIL(char)) `7B X`09`09`09*end = '\0'; X`09`09 `7D X`09`09`7D X`09 `7D X`09`7D X `7D else `7B X`09if ((author = index(message, '<')) == NIL(char)) `7B X`09 /* first form */ X`09 author = index(message, ' '); X`09 assert(author != NIL(char)); X`09 author++; X`09 if ((end = index(author, ' ')) != NIL(char)) `7B X`09`09*end = '\0'; X`09 `7D X`09`7D else `7B X`09 /* second form */ X`09 author++; X`09 if ((end = index(author, '>')) != NIL(char)) `7B X`09`09*end = '\0'; X`09 `7D X`09`7D X `7D X /* X * do a final trimming - just in case the authors name ends X * in spaces or tabs - it does happen X */ X end = author + strlen(author) - 1; X while ((end > author) && ((*end == ' ') `7C`7C (*end == '\t'))) `7B X`09*end = '\0'; X`09end--; X `7D X newsgroup->articles`5BINDEX(number)`5D.author = XtNewString(author); X `7D X return; X`7D X Xvoid Xgetlineslist(newsgroup, first, last) Xstruct newsgroup *newsgroup; Xart_num first; Xart_num last; X/* X * get a list of number of lines per message for the current group in the X * range 'first' to 'last' X * X * returns: void X * X * Note that XHDR is not part of the rfc977 standard, but is implemented X * by the Berkeley NNTP server X * X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D, buffer`5BMESS VAGE_SIZE`5D; X char *numoflines, *end; X long number; X int lcv; X`20 X if (!app_resources.displayLineCount) `7B X`09return; X `7D X X (void) sprintf(command, "XHDR lines %ld-%ld", first, last); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X X /* check for errors */ X if (*message != CHAR_OK) `7B X mesgPane(XRN_SERIOUS, X"XRN: serious error, your NNTP server does not have XHDR support.\n\ XEither you are running a pre-1.5 NNTP server or XHDR has\n\ Xnot been defined in 'nntp/common/conf.h'\n\ XXRN requires XHDR support to run."); X return; X `7D X X for(;;) `7B X X get_data_from_server(message, sizeof(message)); X X if (*message == '.') `7B X break; X `7D X X /* X * message is of the form: X * X * Number NumberOfLines X * X * 203 ## X * X * must get the number since not all subjects will be returned X */ X X number = atol(message); X numoflines = index(message, ' '); X`09assert(numoflines != NIL(char)); X`09numoflines++; X`09if ((end = index(numoflines, ' ')) != NIL(char)) `7B X`09`09*end = '\0'; X`09`7D X`09if (numoflines`5B0`5D != '(') `7B X`09 numoflines`5Bstrlen(numoflines)+1`5D = '\0'; X`09 numoflines`5Bstrlen(numoflines)`5D = '`5D'; X`09 for (lcv=strlen(numoflines) ; lcv >= 0 ; lcv--) `7B X`09`09numoflines`5Blcv+1`5D = numoflines`5Blcv`5D; X`09 `7D X`09 numoflines`5B0`5D = '`5B'; X`09`7D else `7B X`09 numoflines`5B0`5D = '`5B'; X`09 numoflines`5Bstrlen(numoflines)-1`5D = '`5D'; X`09`7D X newsgroup->articles`5BINDEX(number)`5D.lines = XtNewString(numofline Vs); X `7D X return; X`7D X X X#ifndef INEWS Xstatic void XsendLine(str) Xchar *str; X`7B X int i; X X if (*str == '.') `7B X`09for (i = utStrlen(str); i >= 0; i--) `7B X`09 str`5Bi+1`5D = str`5Bi`5D; X`09`7D X`09str`5B0`5D = '.'; X `7D X put_server(str); X return; X`7D X#endif X X Xstatic char * XgetLine(ptr) Xchar **ptr; X`7B X static char line`5B512`5D; X char *end = index(*ptr, '\n'); X X if (end) `7B X`09(void) strncpy(line, *ptr, end - *ptr); X`09line`5Bend - *ptr`5D = '\0'; X`09*ptr = end + 1; X `7D else `7B X`09(void) strcpy(line, *ptr); X`09*ptr = 0; X `7D X return line; X`7D X X X/* X * Takes a block of text, wraps the text based on lineLength and X * breakLength resources, and returns a NULL-terminated allocated X * array of allocated strings representing the wrapped lines. The X * procedure which calls wrapText should use the wrapped Text and then X * free each string and free the array. X */ Xchar ** XwrapText(ptr) Xchar *ptr; X`7B X unsigned int c = 0;`09`09/* current line length */ X char **lines, *this_line; X unsigned int num_lines = 0; X int breakAt = app_resources.breakLength; X X lines = (char **) XtMalloc((Cardinal) 0); X X if (app_resources.breakLength && app_resources.lineLength) `7B X`09 /* X`09 * Do text wrapping. X`09 */ X`09 this_line = XtMalloc((Cardinal) (app_resources.breakLength + 1)); X X`09 while (*ptr != '\0') `7B X`09 if (c >= breakAt) `7B X`09`09 /* X`09`09 * Everything after the first line in a paragraph X`09`09 * should be wrapped at lineLength, not breakLength. X`09`09 * This prevents the last line of a paragraph from X`09`09 * ending up a little bit longer than all the other X`09`09 * lines (and extending into the margin), but not quite X`09`09 * breakLength characters lines long. X`09`09 */ X`09`09 breakAt = app_resources.lineLength; X`09`09 /* backoff to app_resources.lineLength */ X`09`09 ptr -= c - app_resources.lineLength; X`09`09 c = app_resources.lineLength; X`09`09 for (; c > 0 && *ptr != ' ' && *ptr != '\t'; ptr--) `7B X#ifdef notdef X`09`09 if (*ptr == '\t') `7B X`09`09 `7D X#endif X`09`09 c--; X`09`09 `7D X X`09`09 if (c == 0) `7B X`09`09 /* pathological, cut to app_resources.lineLength */ X`09`09 c = app_resources.lineLength; X`09`09 ptr += app_resources.lineLength - 1; X`09`09 `7D X X`09`09 /* output */ X`09`09 this_line`5Bc`5D = '\0'; X`09`09 lines = (char **) XtRealloc((char *) lines, (Cardinal) X`09`09`09`09`09 (sizeof(char *) * ++num_lines)); X`09`09 lines`5Bnum_lines-1`5D = this_line; X`09`09 this_line = XtMalloc((Cardinal) X`09`09`09`09 (app_resources.breakLength + 1)); X`09`09 c = 0; X`09`09 if (strncmp(lines`5Bnum_lines-1`5D, X`09`09`09 app_resources.includePrefix, X`09`09`09 utStrlen(app_resources.includePrefix)) == 0) `7B X`09`09 strcpy(this_line, app_resources.includePrefix); X`09`09 c += utStrlen(app_resources.includePrefix); X`09`09 `7D X X`09`09 /* X`09`09 * Delete any extra spaces, tabs or carriage returns at`20 X`09`09 * the beginning of the next line. This is necessary X`09`09 * because we may break a line in the middle of a X`09`09 * multi-space word break (e.g. the end of a sentence), X`09`09 * or right before the paragraph-ending carriage X`09`09 * return, which we've already printed as part of the X`09`09 * line above. X`09`09 */ X`09`09 while ((*ptr == ' ') `7C`7C (*ptr == '\t') `7C`7C (*ptr == '\n')) `7B X`09`09 ptr++; X`09`09 if (*(ptr-1) == '\n') X`09`09`09 /* We only one to get rid of one carriage return */ X`09`09`09 break; X`09`09 `7D X`09 `20 X`09`09 continue; X`09 `7D X X`09 if (*ptr == '\n') `7B X`09`09 this_line`5Bc`5D = '\0'; X`09`09 lines = (char **) XtRealloc((char *) lines, (Cardinal) X`09`09`09`09`09 (sizeof(char *) * ++num_lines)); X`09`09 lines`5Bnum_lines-1`5D = this_line; X`09`09 this_line = XtMalloc((Cardinal) X`09`09`09`09 (app_resources.breakLength + 1)); X`09`09 if (c == 0) X`09`09 breakAt = app_resources.breakLength; X`09`09 c = 0, ptr++; X`09`09 continue; X`09 `7D X X#ifdef notdef X`09 if (*ptr == '\t') `7B X`09`09 c += c % 8; X`09`09 continue; X`09 `7D X#endif X`09 `20 X`09 this_line`5Bc++`5D = *ptr++; X`09 `7D X X`09 if (c != 0) `7B X`09 this_line`5Bc`5D = '\0'; X`09 lines = (char **) XtRealloc((char *) lines, (Cardinal) X`09`09`09`09`09 (sizeof(char *) * ++num_lines)); X`09 lines`5Bnum_lines-1`5D = this_line; X`09 `7D X `7D X else `7B X`09 /* X`09 * Don't do text wrapping, just break the text at linefeeds. X`09 */ X`09 while (*ptr) `7B X`09 c = 0; X`09 for (; *ptr && (*ptr != '\n'); ptr++, c++) ; X`09 if (c `7C`7C *ptr) `7B X`09`09 this_line = XtMalloc((Cardinal) (c + 1)); X`09`09 lines = (char **) XtRealloc((char *) lines, X`09`09`09`09`09 (Cardinal) (sizeof(char *) * X`09`09`09`09`09`09`09 ++num_lines)); X`09`09 strncpy(this_line, &ptr`5B-c`5D, c); X`09`09 this_line`5Bc`5D = '\0'; X`09`09 lines`5Bnum_lines-1`5D = this_line; X`09`09 if (*ptr) X`09`09 ptr++; X`09 `7D X`09 `7D X `7D X `20 X lines = (char **) XtRealloc((char *) lines, X`09`09`09`09 (Cardinal) (sizeof(char *) * ++num_lines)); X lines`5Bnum_lines-1`5D = NULL; X X return(lines); X`7D X X X#ifndef VMS X Xint XmailArticle(article) Xchar *article; X`7B X extern FILE *popen();`09/* sequent */ X X FILE *fp; X char **lines_ptr, **lines; X char *ptr; X `20 X if ((fp = popen(app_resources.mailer, "w")) == NULL) X`09 return POST_FAILED; X X /* First, send everything up to the first blank line without any */ X /* wrapping. `09`09`09`09`09`09 */ X while (1) `7B X`09 ptr = index(article, '\n'); X`09 if ((ptr == article) `7C`7C (ptr == NULL)) X`09 /* line has nothing but newline or end of article */ X`09 break; X`09 (void) fwrite(article, sizeof(char), (unsigned) (ptr - article + 1), fp V); X`09 article = ptr + 1; X `7D X `20 X lines_ptr = lines = wrapText(article); X while (*lines) `7B X`09 (void) fwrite(*lines, sizeof(char), utStrlen(*lines), fp); X`09 (void) fwrite("\n", sizeof(char), 1, fp); /* wrapText deletes newlines V */ X`09 FREE(*lines); X`09 lines++; X `7D X FREE(lines_ptr); X X (void) pclose(fp); X return POST_OKAY; X`7D X#endif X X Xint XpostArticle(article, mode) Xchar *article; Xint mode; /* XRN_NEWS or XRN_MAIL */ X/* X * post an article X * X * returns 1 for success, 0 for failure X */ X`7B X char command`5BMESSAGE_SIZE`5D, message`5BMESSAGE_SIZE`5D; X char *ptr, *saveptr; X char **lines, **lines_ptr; X#ifdef INEWS X int exitstatus; X char buffer`5B1024`5D; X FILE *inews; X#endif X `20 X if (mode == XRN_MAIL) `7B X`09return mailArticle(article); X `7D X X#ifdef INEWS X (void) sprintf(buffer, "%s -h", INEWS); X if (!(inews = popen(buffer, "w"))) `7B X mesgPane(XRN_SERIOUS, "Faild to start inews\n"); X return(POST_FAILED); X `7D X#else X X (void) strcpy(command, "POST"); X put_server(command); X get_data_from_server(message, sizeof(message)); X X check_time_out(command, message, sizeof(message)); X X if (*message != CHAR_CONT) `7B X`09mesgPane(XRN_SERIOUS, "NNTP Serious Error: %s", message); X`09if (atoi(message) == ERR_NOPOST) `7B X`09 return(POST_NOTALLOWED); X`09`7D else `7B X`09 return(POST_FAILED); X`09`7D X `7D X#endif X X ptr = article; X X while (1) `7B X`09char *line; X X`09saveptr = ptr; X X`09line = getLine(&ptr); X`09if (index(line, ':')) `7B X#ifdef INEWS X`09 fputs(line, inews); X`09 fputc('\n', inews); X#else X`09 sendLine(line); X#endif X`09 continue; X`09`7D X`09break; X `7D X X#ifdef INEWS X fputs("\n\n", inews); X#else X sendLine("");`09`09/* send a blank line */ X#endif X X if (*saveptr != '\n') `7B X`09 /* if the skipped line was not blank, point back to it */ X`09 ptr = saveptr; X `7D X X lines_ptr = lines = wrapText(ptr); X while (*lines) `7B X#ifdef INEWS X fputs(*lines, inews); X`09 fputc('\n', inews); X#else X`09 sendLine(*lines); X#endif X`09 XtFree(*lines); X`09 lines++; X `7D X FREE(lines_ptr); X `20 X#ifdef INEWS X if (exitstatus = pclose(inews)) `7B X mesgPane(XRN_SERIOUS, "inews exit value: %d\n", exitstatus); X`09return(POST_FAILED); X `7D X#else X put_server("."); X X get_data_from_server(message, sizeof(message)); X X if (*message != CHAR_OK) `7B X`09mesgPane(XRN_SERIOUS, "NNTP Serious Error: %s", message); X`09return(POST_FAILED); X `7D X#endif X X return(POST_OKAY); X`7D X X X Xvoid Xxhdr(article, field, string) Xart_num article; Xchar *field; Xchar **string; X/* X * get header information about 'article' X * X * the results are stored in 'string' X */ X`7B X char buffer`5BBUFFER_SIZE`5D, message`5BMESSAGE_SIZE`5D, *ptr; X `20 X (void) sprintf(buffer, "XHDR %s %ld", field, article); X put_server(buffer); X get_data_from_server(message, sizeof(message)); X `20 X check_time_out(buffer, message, sizeof(message)); X `20 X /* check for errors */ X if (*message != CHAR_OK) `7B X`09*string = NIL(char); X`09mesgPane(XRN_SERIOUS, X"XRN: serious error, your NNTP server does not have XHDR support.\n\ XEither you are running a pre-1.5 NNTP server or XHDR has\n\ Xnot been defined in 'nntp/common/conf.h'\n\ XXRN requires XHDR support to run."); X`09return; X `7D X `20 X get_data_from_server(message, sizeof(message)); X X /* no information */ X if (*message == '.') `7B X`09*string = NIL(char); X`09return; X `7D X X ptr = index(message, ' '); X X /* malformed entry */ X if (ptr == NIL(char)) `7B X`09mesgPane(XRN_SERIOUS, X"XRN debugging message: malformed XHDR return\n\ Xcommand: %s, return: %s", X`09`09 buffer, message); X`09get_data_from_server(message, sizeof(message)); X`09return; X `7D X X ptr++; X X /* no information */ X if (STREQ(ptr, "(none)")) `7B X`09*string = NIL(char); X`09/* ending '.' */ X`09do `7B X`09 get_data_from_server(message, sizeof(message)); X`09`7D while (*message != '.'); X`09return; X `7D X X *string = XtNewString(ptr); X X /* ending '.' */ X do `7B X`09get_data_from_server(message, sizeof(message)); X `7D while (*message != '.'); X X return; X`7D X Xstruct article * Xgetarticles(newsgroup) Xstruct newsgroup *newsgroup; X`7B X art_num first = newsgroup->first, last = newsgroup->last, art; X#ifdef STUPIDMMU X void cornered(); X#endif X X if (last >= first && last != 0) `7B X`09newsgroup->articles = ARRAYALLOC(struct article, last - first + 1); X X`09for (art = first; art <= last; art++) `7B X`09 long indx = INDEX(art); X `20 X`09 newsgroup->articles`5Bindx`5D.subject = NIL(char); X`09 newsgroup->articles`5Bindx`5D.author = NIL(char); X`09 newsgroup->articles`5Bindx`5D.lines = NIL(char); X`09 newsgroup->articles`5Bindx`5D.filename = NIL(char); X`09 newsgroup->articles`5Bindx`5D.status = ART_CLEAR; X`09`7D X `7D X#ifdef STUPIDMMU X cornered(newsgroup); X#endif X return(newsgroup->articles); X`7D X $ CALL UNPACK SERVER.C;1 272092273 $ create 'f' X#ifndef SERVER_H X#define SERVER_H X X/* X * $Header: /users/ricks/xrn/src/RCS/server.h,v 1.9 90/09/29 02:27:46 ricks V Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * server.h: routines for communicating with the NNTP remote news server X * X */ X X#include "codes.h" X X/* X * function definitions for the nntp server (in nntp/clientlib.c) X */ X `20 Xextern void close_server(); Xextern int get_server(/* char *response, int size */); Xextern char *getserverbyfile(/* char *filename */); Xextern void put_server(/* char *request */); Xextern int server_init(/* char *servername */); Xextern void start_server(); X X/* get the list of active news groups from the news server */ Xextern void getactive(); X X/* see if the subscribed to groups have 0 or 1 article */ Xextern void badActiveFileCheck(); X X/* get a single article in the current group from the news server */ Xextern char *getarticle(/* art_num artnumber, long *position, header, rotati Von */); X#define FULL_HEADER 1 X#define NORMAL_HEADER 2 X#define NOT_ROTATED 1 X#define ROTATED 2 X X/* X * tell the server that the next set of article requests will be for this gr Voup X * returns NO_GROUP on failure X */ Xextern int getgroup(/* art_num *first, *last, int *number */); X X/* get a list of subject lines for a range of articles in the current group V from the server */ Xextern void getsubjectlist(/* newsgroup *ng, art_num first, art_num list */) V; Xextern void getauthorlist(/* newsgroup *ng, art_num first, art_num list */); X X X/* xhdr commands */ Xextern void xhdr(/* art_num article, char * field, char **string */); X X/* post article */ Xextern int postArticle(/* char *text, int mode */); X X#define XRN_MAIL`09 0 X#define XRN_NEWS`09 1 X X#define POST_FAILED 0 X#define POST_OKAY 1 X#define POST_NOTALLOWED 2 X#define POST_TRYAGAIN`09 3 X X#endif /* SERVER_H */ $ CALL UNPACK SERVER.H;1 373874175 $ create 'f' X/* SList.c X X**************************************************************************** V* X*`09`09`09`09`09`09`09`09`09 * X* COPYRIGHT (c) 1989 BY `09`09`09`09 * X* DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.`09`09 * X* ALL RIGHTS RESERVED.`09`09`09`09`09`09 `09 * X* `09`09`09`09`09`09`09`09`09 * X* THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED V * X* ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE V * X* INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER V * X* COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY V * X* OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY V * X* TRANSFERRED.`09`09`09`09`09`09`09 *`20 X* `09`09`09`09`09`09`09`09`09 * X* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE V * X* AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT V * X* CORPORATION.`09`09`09`09`09`09`09 * X* `09`09`09`09`09`09`09`09`09 * X* DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS V * X* SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.`09`09 * X*`09`09`09`09`09`09`09`09`09 * X**************************************************************************** V* X X`09This module implements the SList widget. X XThe SList widget can be used to present a list of options to the user. XBy using Button1 on the mouse, the user can select one or more options, Xand can scroll through the list using either the scrollbar or by autoscrolli Vng. X XThe widget and the application share an array in memory that stores the Xtext of the list items. The widget does not make a copy of the text array. X XThe application must not deallocate the memory for the text array Xwhile the SList widget is active. There is no special call to retrieve the Xselection list. X XThe SList widget can be created by calls to XtCreateWidget or in UIL. Its Xinterface with the application is simple and consists of the following calls V: X XSListInitializeForDRM() - must be called before any SList widgets are X created, if you are using UIL to create them. X`09`09 XSListCreate(pW, nameP, argsP, argCnt) - is a convenience routine (also X used by UIL/DRM) to create a SList widget. You will probably not X call this routine directly from an application. X XSListLoad(w, sLineP, sLineCnt) - may be called at any time to pass a X new SLine array address and count to the SList widget. If the X SList widget is visible, it is repainted with the new list contents. X XSListSelectAll(w, select) - may be called at any time to select or X unselect all the entries in the list. X XSListUnhighlight(w) - may be called to unhighlight the highlighted line, X if any. XSListHighlight(w) - Select the highlighted line. X XThere are two callbacks made by the widget: X X(1) select_callback is made whenever the user upclicks MB1 in the list. X(2) double_click_callback is made whenever the user double-clicks on an X item in the list. X XMODIFICATION HISTORY: X X*/ X#define SLIST X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#include X#include X#include X#ifdef USE_MRM X#include X#endif X#else X#ifdef unix X#include X#include X#else X#include X#include X#endif X#endif /* MOTIF */ X#include "slistP.h" X`0C Xstatic XtCallbackProc scrollCallback(); Xstatic XtCallbackRec VSCallBack`5B`5D =`20 X`7B X `7B(XtCallbackProc)`09scrollCallback, (caddr_t) NULL`7D, X `7BNULL,`09`09(caddr_t) NULL`7D, X`7D; X`0C Xstatic int ComputeMaxYAdjust(w) X SListWidget w; X`7B X int maxYAdjust = 2*w->slist.marginHeight + X`09w->slist.LineCnt*w->slist.cellHeight - `09w->core.height; X X if (maxYAdjust < 0) maxYAdjust = 0; X X return (maxYAdjust); X`7D Xstatic int YToLine(w, y) X SListWidget w; X int y; X`7B X int line; X X if (y < 0) line = -1; X else if (y >= w->core.height) line = w->slist.LineCnt; X else `7B X`09line = (y + w->slist.externalYAdjust - w->slist.marginHeight) /`20 X`09`09w->slist.cellHeight; X`09if (line < 0) line = -1; X`09else if (line >= w->slist.LineCnt) line = -1; X `7D X X return (line); X`7D X`0C Xstatic void SetInternalYAdjust(w, yAdjust) X SListWidget w; X int yAdjust; X`7B X int maxYAdjust = ComputeMaxYAdjust (w); X int open, above; X X if (yAdjust > maxYAdjust) yAdjust = maxYAdjust; X if (yAdjust < 0) yAdjust = 0; X X w->slist.internalYAdjust = yAdjust; X`7D X`0C Xstatic void Flip(w, line) X SListWidget w; X int line; X`7B X /* If we are busy scrolling, simply clear the line and mark it as expose Vd. X * It will be repainted when the scrolling completes. */ X X if (w->slist.gropIsPending) `7B X`09if (XtIsRealized (w)) XClearArea (XtDisplay (w), XtWindow (w), X`09 w->slist.leftMarginWidth + 1, X`09 w->slist.marginHeight + line * w->slist.cellHeight -`20 X`09 w->slist.requestedYAdjust + 1, X`09 w->core.width - w->slist.leftMarginWidth - w->slist.marginWidth - 2, X`09 w->slist.cellHeight - 2, X`09 0); X X`09w->slist.exposeMapP`5Bline`5D = 1; X`09w->slist.anyAreExposed = 1; X`09return; X `7D X X if (XtIsRealized (w)) XFillRectangle (XtDisplay (w), XtWindow (w), X`09w->slist.flipgc, X`09w->slist.leftMarginWidth + 1, X`09w->slist.marginHeight + line * w->slist.cellHeight - X`09w->slist.requestedYAdjust + 1, X`09w->core.width - w->slist.leftMarginWidth - w->slist.marginWidth - 2, X`09w->slist.cellHeight - 2); X`7D X Xstatic void Draw(w, line) X SListWidget w; X int line; X`7B X int select = w->slist.selectMapP`5Bline`5D; X int x = w->slist.leftMarginWidth + 1; X int y = w->slist.marginHeight + line * w->slist.cellHeight - X`09w->slist.requestedYAdjust + 1; X if (y < 0 `7C`7C y > w->core.height) return; X X if (!XtIsRealized (w)) return; X X if (select) `7B X`09XFillRectangle (XtDisplay (w), XtWindow (w), X`09 w->slist.normgc, x, y, X`09 w->core.width - x - w->slist.marginWidth - 1, X`09 w->slist.cellHeight - 2); X `7D else `7B X`09XClearArea (XtDisplay (w), XtWindow (w), x, y,`20 X`09 w->core.width - x - w->slist.marginWidth - 1, X`09 w->slist.cellHeight - 2, 0); X `7D X XDrawString ( X`09XtDisplay (w), XtWindow (w), X`09(select ? w->slist.invgc : w->slist.normtxtgc), X`09x + w->slist.textMarginWidth, X`09y + w->slist.yFontAdjust, X`09w->slist.LineP`5Bline`5D, strlen(w->slist.LineP`5Bline`5D)); X`7D X`0C Xstatic void StartScrollGrop(w) X SListWidget w; X`7B X Arg vsbArg`5B1`5D; X if (w->slist.gropIsPending) return; /* wait for pending op to complete * V/ X X /* Autoscroll. */ X X if (w->slist.scrollStrength) SetInternalYAdjust (w, X`09w->slist.internalYAdjust + w->slist.scrollStrength); X X if (w->slist.internalYAdjust == w->slist.requestedYAdjust) return; X X if (XtIsRealized (w)) `7B X`09int x = w->slist.marginWidth; X X`09XCopyArea (XtDisplay (w), XtWindow (w), XtWindow (w), X`09 w->slist.normgc, x, w->slist.internalYAdjust - w->slist.requestedYAdj Vust, X`09 w->core.width - x, X`09 w->core.height, x, 0); X X w->slist.gropIsPending = 1; X`09w->slist.requestedYAdjust = w->slist.internalYAdjust; X `7D else `7B X`09w->slist.externalYAdjust = w->slist.requestedYAdjust = X`09w->slist.internalYAdjust; X `7D X`7D X`0C Xstatic void CallSelectCallbacks(w, eventP) X SListWidget w; X XEvent *eventP; X`7B X SListCallbackStruct cbData; X X cbData.reason = SListCRSelect; X cbData.event = eventP; X cbData.select = w->slist.selectParity; X if (w->slist.upLine >= w->slist.downLine) `7B X`09cbData.item_number = w->slist.downLine; X`09cbData.item_count = w->slist.upLine - w->slist.downLine + 1; X `7D else `7B X`09cbData.item_number = w->slist.upLine; X`09cbData.item_count = w->slist.downLine - w->slist.upLine + 1; X `7D X XtCallCallbacks (w, SListNselectCallback, &cbData); X`7D Xstatic void CallDoubleClickCallbacks(w, eventP) X SListWidget w; X XEvent *eventP; X`7B X SListCallbackStruct cbData; X X cbData.reason = SListCRDoubleClick; X cbData.event = eventP; X cbData.item_number = w->slist.downLine; X cbData.item_count = 1; X XtCallCallbacks (w, SListNdoubleClickCallback, &cbData); X`7D X Xstatic void SetLineSelection(w, line, selected) X SListWidget w; X int line, selected; X`7B X int select; X X if ((line == -1) `7C`7C (line == w->slist.LineCnt)) return; X select = w->slist.selectMapP`5Bline`5D; X X if (select == selected) return; X X w->slist.selectMapP`5Bline`5D = selected; X Flip (w, line); X`7D X`0C Xstatic void NewAutoScrollPosition(w, y) X SListWidget w; X int y; X`7B `20 X int s; X X if (y < 0) s = y; X else if (y >= w->core.height) s = y - w->core.height; X else s = 0; X X w->slist.scrollStrength = s * w->slist.autoScrollFactor / 100; X X StartScrollGrop (w); X`7D X Xstatic void NewSelectPosition(w, y) X SListWidget w; X int y; X`7B X int line; X X if (y < 0) y = 0; X if (y >= w->core.height) y = w->core.height - w->slist.marginHeight; X line = YToLine (w, y); X if (line == -1) line = 0; X X while (line != w->slist.mouseLine) `7B X`09if (w->slist.mouseLine < line) X`09 if (w->slist.mouseLine < w->slist.downLine) `7B X`09`09int select = w->slist.selectMapP`5Bw->slist.mouseLine`5D; X`09`09SetLineSelection (w, (w->slist.mouseLine)++, select); X`09 `7D else SetLineSelection (w, ++(w->slist.mouseLine), w->slist.select VParity); X`09else X`09 if (w->slist.mouseLine > w->slist.downLine) `7B X`09`09int select = w->slist.selectMapP`5Bw->slist.mouseLine`5D; X`09`09SetLineSelection (w, (w->slist.mouseLine)--, select); X`09 `7D else SetLineSelection (w, --(w->slist.mouseLine), w->slist.select VParity); X `7D X`7D `20 X`0C Xstatic XtCallbackProc scrollCallback(w, closure, call_data) X Widget w; X caddr_t closure; X#ifdef MOTIF X XmScrollBarCallbackStruct *call_data; X#else X DwtScrollBarCallbackStruct *call_data; X#endif X`7B X XButtonEvent *ev; X SListWidget sl = (SListWidget) closure; X int open, above; X X switch (call_data->reason) `7B X#ifdef MOTIF X`09case XmCR_INCREMENT: X`09case XmCR_DECREMENT: X`09case XmCR_PAGE_INCREMENT: X`09case XmCR_PAGE_DECREMENT: X`09case XmCR_DRAG: X#else X`09case DwtCRUnitInc: X`09case DwtCRUnitDec: X`09case DwtCRPageInc: X`09case DwtCRPageDec: X`09case DwtCRDrag: X#endif X`09 sl->slist.internalYAdjust = X`09`09(call_data->value * sl->slist.cellHeight) +`20 X`09`09sl->slist.marginHeight; X`09 StartScrollGrop (sl); X`09 break; X X `7D X`7D X Xstatic void Repaint(); Xstatic void Mb1PressInList(w, eventP) X SListWidget w; X XButtonEvent *eventP; X`7B X int line; X int needsRepaint = 0; X X w->slist.mouseLine = w->slist.downLine = w->slist.upLine = line = YToLin Ve (w, eventP->y); X /* X * check for pending timer X */ X if (w->slist.ClickTimerID != 0) `7B X`09if (w->slist.downLine != w->slist.ClickLine) `7B`09/* Same line? */ X`09 XtRemoveTimeOut(w->slist.ClickTimerID);`09/* No, not a double click * V/ X`09 CallSelectCallbacks(w, NULL);`09/* deliver initial selection */ X`09 w->slist.ClickTimerID = 0;`09`09/* Zap the click timer */ X`09`7D else `7B X`09 w->slist.listIsGrabbed = 1;`09`09/* grabbed (for up-click) */ X`09 return;`09`09`09`09/* else wait for up-click */ X`09`7D X `7D X /* X * On MB1 down, deselect all. No deselect for Shift-MB1. X */ X if (!(eventP->state & ShiftMask)) `7B X`09w->slist.highlightedLine = -1; X`09for (line=0;line slist.LineCnt; line++) `7B X`09 if (w->slist.selectMapP`5Bline`5D != 0) `7B X`09`09needsRepaint = 1; X`09 `7D X`09 w->slist.selectMapP`5Bline`5D = 0; X`09`7D X `7D X if (needsRepaint) X`09Repaint (w); X X w->slist.listIsGrabbed = 1; X X w->slist.mouseLine = w->slist.downLine = w->slist.upLine = line = YToLin Ve (w, eventP->y); X X if ((line != -1) && (line != w->slist.LineCnt)) `7B X`09w->slist.selectParity = (w->slist.selectMapP`5Bline`5D == 0); X`09SetLineSelection (w, line, w->slist.selectParity); X `7D else w->slist.selectParity = 1; X`7D X Xstatic void ClickTimer(w, id) X SListWidget w; X XtIntervalId id; X`7B X/* X * Here when the timer expires X */ X X if (w->slist.DownCount > 1) `7B X`09CallDoubleClickCallbacks (w, NULL); /* call double click procs */ X `7D else `7B X`09CallSelectCallbacks (w, NULL);`09/* call select procs */ X `7D X w->slist.ClickTimerID = 0; X`7D Xstatic void ButtonReleaseHandler(w, closure, eventP) X SListWidget w; X Opaque closure; X XButtonEvent *eventP; X`7B X if (w->slist.listIsGrabbed) `7B X`09int y = eventP->y; X X`09/* If we're still autoScrolling, treat the upclick as though it were X`09 * at the top or bottom edge of the list. This prevents unseen X`09 * lines from being selected. */ X X`09if (y < 0) y = 0; X`09else if (y >= w->core.height) y = w->core.height - 1; X`09w->slist.upLine = YToLine(w, y); X`09if (w->slist.upLine == -1) X`09`09w->slist.upLine = w->slist.LineCnt; X`09NewAutoScrollPosition (w, 0);`09`09/* shut off autoscrolling */ X X`09w->slist.listIsGrabbed = 0; X`09if (w->slist.upLine != w->slist.downLine) `7B`09/* same line? if not...*/ X`09 if (w->slist.ClickTimerID != 0) `7B`09`09/* timer pending? */ X`09`09XtRemoveTimeOut(w->slist.ClickTimerID);/* Then cancel it */ X`09`09w->slist.ClickTimerID = 0; X`09 `7D X`09 CallSelectCallbacks (w, eventP);`09/* call select procs */ X`09`7D else `7B X/* X * same line - initiate double-click timer X */ X`09 if (w->slist.ClickTimerID == 0) `7B`09`09/* first time */ X`09`09w->slist.ClickTimerID = XtAppAddTimeOut (XtWidgetToApplicationContext( Vw), X`09`09`09`09(unsigned long) w->slist.ClickInterval, X`09`09`09`09(XtTimerCallbackProc) ClickTimer, X`09`09`09`09(caddr_t) w); X`09`09w->slist.DownCount = 1; X`09`09w->slist.DownTime = eventP->time; X`09`09w->slist.ClickLine = w->slist.upLine; X`09 `7D else `7B X`09`09w->slist.DownCount++;`09`09`09/* count another down */ X`09 `7D X`09`7D X `7D`20 X`7D X Xstatic void ButtonPressHandler(w, closure, eventP) X SListWidget w; X Opaque closure; X XButtonEvent *eventP; X`7B X X /* Handle chorded cancel by turning the ButtonPress into a ButtonRelease V. */ X X if (w->slist.listIsGrabbed) `7B X`09ButtonReleaseHandler (w, closure, eventP); X`09return; X `7D X X if (!w->slist.LineCnt) return;`09`09`09/* nothing to do */ X if (w->slist.gropIsPending) return; `09`09/* ignore if we're busy */ X X if (eventP->button == Button1) X`09Mb1PressInList (w, eventP); X X`7D X Xstatic void PointerMotionHandler(w, closure, eventP) X SListWidget w; X Opaque closure; X XMotionEvent *eventP; X`7B X if (w->slist.listIsGrabbed) `7B X NewSelectPosition (w, eventP->y); X`09NewAutoScrollPosition (w, eventP->y); X X `7D`20 X`7D X`0C Xstatic void DrawExposedLines(w) X SListWidget w; X`7B X int line, LineCnt; X char *exposeMapP; X X if (!w->slist.anyAreExposed) return;`09/* nothing to do */ X if (w->slist.gropIsPending) return;`09/* wait for pending op to complete V */ X X LineCnt = w->slist.LineCnt; X for (line=0, exposeMapP=w->slist.exposeMapP; lineslist.anyAreExposed = 0; X`7D X Xstatic void SaveExposeRegion(w, x, vY, width, height) X SListWidget w; X int x, vY, width, height; X`7B X int firstLine, lastLine, line; X X firstLine = (vY - w->slist.marginHeight) / w->slist.cellHeight; X if (firstLine < 0) firstLine = 0; X if (firstLine >= w->slist.LineCnt) return; X X lastLine = (vY + height - 1 - w->slist.marginHeight) / w->slist.cellHeig Vht; X if (lastLine >= w->slist.LineCnt) lastLine = w->slist.LineCnt - 1; X if (lastLine < 0) return; X X for (line=firstLine; line <= lastLine; line++) `7B X`09w->slist.exposeMapP`5Bline`5D = 1; X`09w->slist.anyAreExposed = 1; X `7D X`7D X Xstatic void Repaint(w) X SListWidget w; X`7B X if (XtIsRealized (w)) XClearArea (XtDisplay (w), XtWindow (w), 0, 0, X w->core.width, w->core.height, 0); X X SaveExposeRegion (w, 0, w->slist.internalYAdjust, w->core.width, X`09w->core.height); X X DrawExposedLines (w); X`7D X Xstatic void DoExpose(w, eventP) X SListWidget w; X XEvent *eventP; X`7B X if (XtIsRealized (w)) XClearArea (XtDisplay (w), XtWindow (w), X`09eventP->xexpose.x, X`09eventP->xexpose.y + w->slist.externalYAdjust - w->slist.requestedYAdjust, X`09eventP->xexpose.width, eventP->xexpose.height, 0); X X SaveExposeRegion (w, X`09eventP->xexpose.x, X`09eventP->xexpose.y + w->slist.externalYAdjust, X`09eventP->xexpose.width, X`09eventP->xexpose.height); X X /* If this is not a primary Expose event, simply return. */ X X if (eventP->xexpose.count) return; X X DrawExposedLines (w); X`7D X Xstatic void HandleNonmaskableEvent(w, closure, eventP) X SListWidget w; X int closure; /* notused */ X XEvent *eventP; X`7B X Arg vsbArg`5B1`5D; X if (eventP->xany.type == GraphicsExpose) `7B X`09SaveExposeRegion (w, X`09 eventP->xgraphicsexpose.x, X`09 eventP->xgraphicsexpose.y + w->slist.requestedYAdjust, X`09 eventP->xgraphicsexpose.width, X`09 eventP->xgraphicsexpose.height); X `20 X`09/* If this is not a primary GraphicsExpose event, return. */ X `20 X`09if (eventP->xgraphicsexpose.count) return; X `7D X X if ((eventP->xany.type == NoExpose) `7C`7C X (eventP->xany.type == GraphicsExpose)) `7B X`09w->slist.gropIsPending = 0; X X`09w->slist.externalYAdjust = w->slist.requestedYAdjust; X`09DrawExposedLines (w); X`09StartScrollGrop (w); X `7D X`7D X`0C Xstatic void DoChangeManaged(w) X Widget w; X`7B X`7D Xstatic void DoInsertChild(w) X Widget w; X`7B X SListWidget widget = (SListWidget) w->core.parent; X X widget->composite.children =`20 X`09(WidgetList) XtRealloc((caddr_t) widget->composite.children, X`09(unsigned) (widget->composite.num_children + 1) * sizeof (Widget)); X widget->composite.children`5Bwidget->composite.num_children`5D = w; X widget->composite.num_children++; X`7D Xstatic void FrameInsertChild(w) X Widget w; X`7B X SFrameWidget widget = (SFrameWidget) w->core.parent; X X widget->composite.children =`20 X`09(WidgetList) XtRealloc((caddr_t) widget->composite.children, X`09(unsigned) (widget->composite.num_children + 1) * sizeof (Widget)); X widget->composite.children`5Bwidget->composite.num_children`5D = w; X widget->composite.num_children++; X if (widget->core.height < w->core.height) X`09widget->core.height = w->core.height; X if (widget->core.width < w->core.width) X`09widget->core.width = w->core.width; X`7D Xstatic void DoDeleteChild(w) X Widget w; X`7B X`7D X Xstatic XtGeometryResult DoGeometryManager(w, requestP, replyP) X Widget w; X XtWidgetGeometry *requestP, *replyP; X`7B X if (requestP->request_mode & CWX) w->core.x = requestP->x; X if (requestP->request_mode & CWY) w->core.y = requestP->y; X if (requestP->request_mode & CWWidth) w->core.width = requestP->width; X if (requestP->request_mode & CWHeight) w->core.height = requestP->height V; X if (requestP->request_mode & CWBorderWidth) X`09w->core.border_width = requestP->border_width; X X return (XtGeometryYes);`09`09/* just say yes */ X`7D X`0C Xstatic void DoResize(); Xstatic void ResizeCallback(pW, w, cbDataP) X Widget pW;`09`09`09/* parent SFrame widget */ X SListWidget w; X Opaque cbDataP; X`7B X int width, height; X X if (!XtIsRealized (w)) return; X DoResize (w); X`7D X`0C Xstatic void DoInitialize(request, w) X SListWidget request, w; X`7B X XFontStruct *fontP; X XGCValues values; X static char dashList`5B`5D = `7B4, 4`7D; X int fontIndex; X Arg`09`09vsbArgs`5B30`5D; X int`09`09i; X int`09`09requiredWidth; X int`09`09charWidth = 0; X X w->slist.internalYAdjust = w->slist.externalYAdjust = 0; X w->slist.requestedYAdjust =`09w->slist.gropIsPending = 0; X w->slist.listIsGrabbed = 0; X w->slist.LineP = (char**) 0; X w->slist.selectMapP =`09(char*) 0; X w->slist.LineCnt = w->slist.anyAreExposed = 0; X w->slist.exposeMapP = (char*) 0; X w->slist.mapLen =`090; X w->slist.scrollStrength = 0; X w->slist.scrollbarOffset =`090; X X w->slist.highlightedLine = `09-1; X X w->slist.ClickTimerID = w->slist.DownCount = w->slist.ClickLine = 0; X X#ifdef MOTIF X if (w->slist.fontRecP == NULL) `7B X`09fontP = XLoadQueryFont(XtDisplay(w), "fixed"); X `7D else `7B X`09_XmFontListSearch(w->slist.fontRecP, "default", &fontIndex, &fontP); X `7D X w->slist.fontP = fontP; X#else X /* Simply use the first font in the font list. */ X X if (w->slist.fontRecP == NULL) `7B X`09fontP = w->slist.fontP = XLoadQueryFont(XtDisplay(w), "fixed"); X `7D else `7B X`09fontP = w->slist.fontP = w->slist.fontRecP->font; X `7D X#endif X /* Compute some useful constants. */ X X w->slist.cellHeight = fontP->max_bounds.descent + fontP->max_bounds.asce Vnt + 2; X w->slist.yFontAdjust = fontP->max_bounds.ascent; X X /* Make a reasonable initial size for the widget if none was specified. V */ X X if ((!XGetFontProperty(fontP, XA_QUAD_WIDTH, &charWidth)) `7C`7C charWid Vth==0)`7B X if (fontP->per_char && fontP->min_char_or_byte2 <= '0' && X fontP->max_char_or_byte2 >= '0') X charWidth = fontP->per_char`5B'0' - fontP->min_char_or_byte2`5D. Vwidth; X else X charWidth = fontP->max_bounds.width; X `7D X if (charWidth <= 0) charWidth = 1; X requiredWidth = 2*w->slist.marginWidth + w->slist.cols * charWidth; X if (w->core.width < requiredWidth) `7B X`09w->core.width = requiredWidth; X `7D X X if (!w->slist.rows) `7B X`09w->slist.rows = w->core.height / w->slist.cellHeight; X `7D else `7B X`09w->core.height = 2*w->slist.marginHeight + w->slist.rows * w->slist.cellH Veight; X `7D X w->slist.knownHeight = w->core.height; X w->slist.knownWidth = w->core.width; X X /* Load graphics contexts. */ X X#ifdef MOTIF X w->slist.foreground = w->primitive.foreground; X#endif X values.font = fontP->fid; X values.foreground = w->slist.foreground; X values.background = w->core.background_pixel; X values.function = GXcopy; X w->slist.normgc = XtGetGC (w, X`09GCFont `7C GCForeground `7C GCBackground `7C GCFunction, &values); X X w->slist.normtxtgc = XtGetGC (w, X`09GCClipXOrigin `7C GCFont `7C GCForeground `7C GCBackground `7C GCFunction V, &values); X X values.graphics_exposures = 0; X values.font = fontP->fid; X values.foreground = w->core.background_pixel; X values.background = w->slist.foreground; X values.function = GXcopy; X w->slist.invgc = XtGetGC(w, X`09GCClipXOrigin `7C GCFont `7C GCForeground `7C GCBackground `7C GCFunction V, &values); X X values.function = GXinvert; X values.plane_mask = w->core.background_pixel `5E w->slist.foreground; X w->slist.flipgc = XtGetGC (w, X`09GCFunction `7C GCPlaneMask, &values); X X i = 0; X VSCallBack`5B0`5D.closure = (caddr_t)w; X#ifdef MOTIF X w->slist.scrollbarOffset = w->core.width + w->slist.sepWidth; X XtSetArg(vsbArgs`5Bi`5D, XmNorientation, XmVERTICAL);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNx, w->slist.scrollbarOffset); Vi++; X XtSetArg(vsbArgs`5Bi`5D, XmNheight, w->core.height); `09`09i++ V; X XtSetArg(vsbArgs`5Bi`5D, XmNvalue, w->slist.externalYAdjust); Vi++; X if (w->slist.LineCnt > w->slist.rows) `7B X XtSetArg(vsbArgs`5Bi`5D, XmNminimum, 0);`09`09`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNmaximum, w->slist.LineCnt);`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize, w->slist.rows);`09`09i++; X `7D else `7B X`09XtSetArg(vsbArgs`5Bi`5D, XmNminimum, 0);`09`09`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNmaximum, 5);`09`09`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize, 5);`09`09`09i++; X `7D X XtSetArg(vsbArgs`5Bi`5D, XmNincrement, 1);`09`09`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNpageIncrement, w->slist.rows-1);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNincrementCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNdecrementCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNpageIncrementCallback, VSCallBack);`09`09i++ V; X XtSetArg(vsbArgs`5Bi`5D, XmNpageDecrementCallback, VSCallBack);`09`09i++ V; X XtSetArg(vsbArgs`5Bi`5D, XmNdragCallback, VSCallBack);`09`09i++; X w->slist.vScroll = XtCreateManagedWidget("vpaneScroll", X`09xmScrollBarWidgetClass, XtParent (w), vsbArgs, i); X w->slist.scrollbarWidth = w->slist.vScroll->core.width +`20 X`09`09`09 w->slist.vScroll->core.border_width; X w->slist.sepOffset = w->core.width; X i = 0; X XtSetArg(vsbArgs`5Bi`5D, XmNorientation, XmVERTICAL);`09`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNx, w->slist.sepOffset);`09`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNwidth, w->slist.sepWidth); `09`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, XmNheight,w->core.height);`09 `09`09i++; X X w->slist.sepW = XtCreateManagedWidget("vpaneSep", X`09xmSeparatorWidgetClass, XtParent (w), vsbArgs, i); X X#else X w->slist.scrollbarOffset = w->core.width; X XtSetArg(vsbArgs`5Bi`5D, DwtNorientation, DwtOrientationVertical); ` V09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNx, w->slist.scrollbarOffset); Vi++; X#ifdef notdef X XtSetArg(vsbArgs`5Bi`5D, DwtNwidth, w->slist.scrollbarWidth);` V09i++; X#endif X XtSetArg(vsbArgs`5Bi`5D, DwtNheight, w->core.height); `09`09i++ V; X XtSetArg(vsbArgs`5Bi`5D, DwtNvalue, w->slist.externalYAdjust); Vi++; X if (w->slist.LineCnt > w->slist.rows) `7B X XtSetArg(vsbArgs`5Bi`5D, DwtNminValue, 0);`09`09`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue, w->slist.LineCnt);`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, DwtNshown,`09 w->slist.rows);`09`09i++; X `7D else `7B X`09XtSetArg(vsbArgs`5Bi`5D, DwtNminValue, 0);`09`09`09i++; X`09XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue, 1);`09`09`09i++; X `7D X XtSetArg(vsbArgs`5Bi`5D, DwtNinc, 1);`09`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNunitIncCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNunitDecCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNpageIncCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNpageDecCallback, VSCallBack);`09`09i++; X XtSetArg(vsbArgs`5Bi`5D, DwtNdragCallback, VSCallBack);`09`09i++; X w->slist.vScroll = XtCreateManagedWidget("vpaneScroll", X`09scrollwidgetclass, XtParent (w), vsbArgs, i); X w->slist.scrollbarWidth = w->slist.vScroll->core.width +`20 X`09`09`09 w->slist.vScroll->core.border_width; X#endif X X`7D X Xstatic void DoRealize(w, maskP, attributesP) X SListWidget w; X Mask *maskP; X XSetWindowAttributes *attributesP; X`7B X X SFrameWidget sf = (SFrameWidget) w->core.parent; X Boolean ResizeNeeded = False; X X /* Make sure we resize to conform to our parent */ X X w->core.width = sf->core.parent->core.width - X`09(sf->core.border_width * 2) - X`09w->slist.scrollbarWidth; X w->core.height = sf->core.height - `09(sf->core.border_width * 2); X X if (w->core.width != w->slist.knownWidth `7C`7C X`09w->core.height != w->slist.knownHeight) X`09 ResizeNeeded = True; X X /* Make sure the window is automatically cleared whenever it is resized. V */ X X *maskP `7C= CWBitGravity; X attributesP->bit_gravity = ForgetGravity; X X XtCreateWindow (w, InputOutput, CopyFromParent, *maskP, attributesP); X X /* Register an event handler for nonmaskable events. In particular, X * we are interested in GraphicsExpose and NoExpose events. */ X X XtAddEventHandler (w, 0, 1, HandleNonmaskableEvent, w); X X /* Establish passive button grabs and declare event handlers. */ X X XGrabButton ( X`09XtDisplay (w),`09`09`09`09`09/* display */ X`091,`09`09`09`09`09`09/* button_grab */ X`09AnyModifier,`09`09`09`09`09/* modifiers */ X`09XtWindow (w), `09`09`09`09`09/* window */ X`090,`09`09`09`09`09`09/* owner_events */ X`09(ButtonPressMask `7C ButtonReleaseMask `7C Button1MotionMask), X`09`09`09`09`09`09`09/* event_mask */ X`09GrabModeAsync,`09`09`09`09`09/* pointer_mode */ X`09GrabModeAsync,`09`09`09`09`09/* keyboard_mode */ X`09None,`09`09`09`09`09`09/* confine_to */ X`09None);`09`09`09`09`09`09/* cursor */ X X XtAddRawEventHandler (w, ButtonPressMask, 0, ButtonPressHandler, 0); X XtAddRawEventHandler (w, PointerMotionMask, 0, PointerMotionHandler, 0); X XtAddRawEventHandler (w, ButtonReleaseMask, 0, ButtonReleaseHandler, 0); X X w->slist.leftMarginWidth = w->slist.marginWidth; X w->slist.scrollbarOffset = w->core.width; X#ifdef MOTIF X w->slist.sepOffset = w->core.width; X w->slist.scrollbarOffset = w->slist.sepWidth; X#endif X /* Trap resize events on our parent (SFrame) widget. */ X X XtAddCallback (w->core.parent, SFrameNresizeCallback, ResizeCallback, w) V; X X if (ResizeNeeded) X`09DoResize (w); X`7D X Xstatic void DoResize(w) X SListWidget w; X`7B X Arg vsbArgs`5B30`5D; X int i; X Boolean resized = False; X SFrameWidget sf = (SFrameWidget) w->core.parent; X X w->core.width = sf->core.width - w->slist.scrollbarWidth; X w->slist.scrollbarOffset = w->core.width; X X#ifdef MOTIF X w->slist.sepOffset = w->core.width - w->core.border_width * 2; X w->slist.scrollbarOffset = w->slist.sepOffset + w->slist.sepWidth - X`09w->core.border_width * 3; X w->core.width = w->core.width - w->slist.sepWidth -`20 X`09w->slist.vScroll->core.border_width * 2 - X`09w->slist.sepW->core.border_width; X#endif X X w->core.height = sf->core.height - (sf->core.border_width * 2); X X if (w->core.height != w->slist.knownHeight) `7B X`09resized = True; X`09w->slist.knownHeight = w->core.height; X`09SetInternalYAdjust (w, 0); X`09w->slist.rows = w->core.height / w->slist.cellHeight; X`09if (w->slist.vScroll != (Widget) NULL) `7B X`09 i = 0; X#ifdef MOTIF X`09 XtSetArg(vsbArgs`5Bi`5D, XmNheight, w->core.height);i++; X`09 XtSetValues(w->slist.sepW, vsbArgs, i); X`09 XtSetArg(vsbArgs`5Bi`5D, XmNvalue, 0);i++; X `09 XtSetArg(vsbArgs`5Bi`5D, XmNincrement, 1);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, XmNpageIncrement, w->slist.rows-1);i++; X`09 if (w->slist.LineCnt > w->slist.rows) `7B X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNminimum,0);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNmaximum,w->slist.LineCnt);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize, w->slist.rows);i++; X`09 `7D else `7B X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNminimum,0);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNmaximum,5);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize,5);i++; X`09 `7D X`09 XtSetValues(w->slist.vScroll, vsbArgs, i); X#else X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNheight, w->core.height);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNvalue, 0);i++; X`09 if (w->slist.LineCnt > w->slist.rows) `7B X`09`09XtSetArg(vsbArgs`5Bi`5D, DwtNminValue,0);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue,w->slist.LineCnt);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, DwtNshown, w->slist.rows/2);i++; X`09 `7D else `7B X`09`09XtSetArg(vsbArgs`5Bi`5D, DwtNminValue,0);i++; X`09`09XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue,1);i++; X`09 `7D X`09 XtSetValues(w->slist.vScroll, vsbArgs, i); X#endif X`09`7D X `7D X if (w->core.width != w->slist.knownWidth) `7B X`09resized = True; X`09w->slist.knownWidth = w->core.width; X`09w->slist.scrollbarOffset = w->core.width; X#ifdef MOTIF X`09w->slist.sepOffset = w->core.width; X`09w->slist.scrollbarOffset = w->core.width + w->slist.sepWidth; X#endif X`09if (w->slist.vScroll != (Widget) NULL) `7B X#ifdef MOTIF X`09 XtSetArg(vsbArgs`5B0`5D, XmNx, w->slist.scrollbarOffset); X`09 XtSetValues(w->slist.vScroll, vsbArgs, 1); X`09 XtSetArg(vsbArgs`5B0`5D, XmNx, w->slist.sepOffset); X`09 XtSetValues(w->slist.sepW, vsbArgs, 1); X#else X`09 XtSetArg(vsbArgs`5B0`5D, DwtNx, w->slist.scrollbarOffset); X`09 XtSetValues(w->slist.vScroll, vsbArgs, 1); X#endif X`09`7D X `7D X if (resized) `7B X`09XMoveResizeWindow(XtDisplay(w), XtWindow(w), X`09`09w->core.x, w->core.y, w->core.width, w->core.height); X`09Repaint (w); X `7D X`7D X Xstatic void DoDestroy(w) X SListWidget w; X`7B X`7D X`0C Xvoid SListLoad(w, LineP, LineCnt) X SListWidget w; X char **LineP; X int LineCnt; X`7B X int line; X char *exposeMapP; X char *selectMapP; X Arg vsbArgs`5B10`5D; X int i; X X w->slist.LineP = LineP; X w->slist.LineCnt = LineCnt; X X /* Reallocate the expose and select maps if not big enough. */ X X if (w->slist.mapLen < LineCnt) `7B X`09w->slist.mapLen = LineCnt + 100; X`09XtFree (w->slist.exposeMapP); X`09w->slist.exposeMapP = XtMalloc (w->slist.mapLen); X`09XtFree (w->slist.selectMapP); X`09w->slist.selectMapP = XtMalloc (w->slist.mapLen); X `7D X X /* Clear the maps. */ X X for (line=0, exposeMapP=w->slist.exposeMapP, selectMapP = w->slist.selec VtMapP; X`09 lineslist.highlightedLine = -1; X w->slist.anyAreExposed = w->slist.externalYAdjust = w->slist.requestedYA Vdjust = 0; X SetInternalYAdjust (w, 0); X if (w->slist.vScroll != (Widget) NULL) `7B X`09i = 0; X#ifdef MOTIF X`09XtSetArg(vsbArgs`5Bi`5D, XmNvalue, 0);i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNincrement, 1);i++; X`09XtSetArg(vsbArgs`5Bi`5D, XmNpageIncrement, w->slist.rows-1);i++; X`09if (w->slist.LineCnt > w->slist.rows) `7B X`09 XtSetArg(vsbArgs`5Bi`5D, XmNminimum,0);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, XmNmaximum,w->slist.LineCnt);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize, w->slist.rows);i++; X`09`7D else `7B X`09 XtSetArg(vsbArgs`5Bi`5D, XmNminimum,0);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, XmNmaximum,5);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, XmNsliderSize,5);i++; X`09`7D X#else X`09XtSetArg(vsbArgs`5Bi`5D, DwtNvalue, 0);i++; X`09XtSetArg(vsbArgs`5Bi`5D, DwtNminValue, 0);i++; X`09if (w->slist.LineCnt > w->slist.rows) `7B X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNminValue, 0);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue, w->slist.LineCnt);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNshown, w->slist.rows);i++; X`09`7D else `7B X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNminValue, 0);i++; X`09 XtSetArg(vsbArgs`5Bi`5D, DwtNmaxValue, 1);i++; X`09`7D X#endif X`09XtSetValues(w->slist.vScroll, vsbArgs, i); X `7D X X Repaint (w); X`7D X Xvoid SListSetTop(w, item) X SListWidget w; X int item; X`7B X int topLine; X Arg vsbArg`5B1`5D; X X topLine = (w->slist.externalYAdjust - w->slist.marginHeight) / w->slist. VcellHeight; X if (topLine < 0) topLine = -1; X else if (topLine > w->slist.LineCnt) topLine = w->slist.LineCnt; X if (item > w->slist.LineCnt - w->slist.rows) X`09item = w->slist.LineCnt - w->slist.rows; X if (item < 0) item = 0; X if (item == topLine) return; X w->slist.internalYAdjust = w->slist.requestedYAdjust = w->slist.external VYAdjust =`20 X`09w->slist.marginHeight + item * w->slist.cellHeight; X if (w->slist.vScroll != (Widget) NULL) `7B X#ifdef MOTIF X`09XtSetArg(vsbArg`5B0`5D, XmNvalue, item); X#else X`09XtSetArg(vsbArg`5B0`5D, DwtNvalue, item); X#endif X`09XtSetValues(w->slist.vScroll, vsbArg, 1); X `7D X Repaint(w); X`7D Xvoid SListUpdateLine(w, line) X SListWidget w; X int line; X`7B X Draw(w, line); X`7D Xvoid SListSelectAll(w, select) X SListWidget w; X int select; X`7B X int line; X int needsRepaint = 0; X X for (line=0; line slist.LineCnt; line++) `7B X`09if (line != w->slist.highlightedLine && X`09 w->slist.selectMapP`5Bline`5D != select) `7B X`09 needsRepaint = 1; X`09 w->slist.selectMapP`5Bline`5D = select; X`09`7D X `7D X if (needsRepaint) X`09Repaint (w); X`7D X Xvoid SListUnhighlight(w) X SListWidget w; X`7B X if (w->slist.highlightedLine == -1) return; X X SetLineSelection(w, w->slist.highlightedLine, False); X w->slist.highlightedLine = -1; X`7D Xvoid SListHighlight(w, line) X SListWidget w; X int line; X`7B X if (line == w->slist.highlightedLine) return;`09/* don't set it again */ X if (w->slist.highlightedLine != -1) `7B X`09SetLineSelection(w, w->slist.highlightedLine, False); X `7D `20 X X w->slist.highlightedLine = line; X SetLineSelection(w, line, True); X`7D Xint SListGetHighlight(w) X SListWidget w; X`7B X return w->slist.highlightedLine; X`7D X`0C X#ifndef XtCCallback X#define XtCCallback "Callback" X#endif X#ifndef XtRCallback X#define XtRCallback "Callback" X#endif X#define Offset(x) XtOffset(SListWidget, x) X X#ifdef MOTIF_V1_0 Xextern void _XmForegroundColorDefault(); X#endif Xstatic XtResource resources`5B`5D = `7B X#ifdef MOTIF X `7BXmNfont, XmCFontList, XmRFontList, sizeof(XmFontList *), X Offset(slist.fontRecP), XmRString, "fixed"`7D, X `7BXmNcolumns, XmCColumns, XmRInt, sizeof(int), X Offset(slist.cols), XmRImmediate, (caddr_t)1`7D, X `7BXmNrows, XmCRows, XmRInt, sizeof(int), X Offset(slist.rows), XmRImmediate, (caddr_t)1`7D, X `7BSListNseparatorWidth, SListCSeparatorWidth, XmRInt, sizeof(int), X Offset(slist.sepWidth), XmRImmediate, (caddr_t)5`7D, X `7BSListNselectCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), X Offset(slist.selectCallback), XmRCallback, (caddr_t)0`7D, X `7BSListNdoubleClickCallback, XmCCallback, XmRCallback, sizeof(XtCallbackL Vist), X Offset(slist.doubleClickCallback), XmRCallback, (caddr_t)0`7D, X#ifdef MOTIF_V1_0 X `7BSListNforeground, SListCForeground, XmRPixel, sizeof(Pixel), X Offset(primitive.foreground), XmRCallProc, X (caddr_t) _XmForegroundColorDefault`7D, X#else X `7BSListNforeground, SListCForeground, XmRPixel, sizeof(Pixel), X Offset(primitive.foreground), XmRString, XtExtdefaultforeground`7D, X#endif X `7BSListNmarginWidth, SListCMarginWidth, XmRInt, sizeof(int), X Offset(slist.marginWidth), XmRImmediate, (caddr_t)4`7D, X `7BSListNmarginHeight, SListCMarginHeight, XmRInt, sizeof(int), X Offset(slist.marginHeight), XmRImmediate, (caddr_t)6`7D, X `7BSListNtextMarginWidth, SListCTextMarginWidth, XmRInt, sizeof(int), X Offset(slist.textMarginWidth), XmRImmediate, (caddr_t)4`7D, X `7BSListNautoScrollFactor, SListCScrollFactor, XmRInt, sizeof(int), X Offset(slist.autoScrollFactor), XmRImmediate, (caddr_t)20`7D, X `7BSListNdoubleClickInterval, SListCDoubleClickInterval, XmRInt, sizeof(in Vt), X Offset(slist.ClickInterval), XmRImmediate, (caddr_t) 250`7D X#else X `7BDwtNfont, DwtCFontList, DwtRFontList, sizeof(DwtFontRec *), X Offset(slist.fontRecP), XtRString, "fixed"`7D, X `7BDwtNcols, DwtCCols, XtRInt, sizeof(int), X Offset(slist.cols), XtRImmediate, (caddr_t)1`7D, X `7BDwtNrows, DwtCRows, XtRInt, sizeof(int), X Offset(slist.rows), XtRImmediate, (caddr_t)1`7D, X `7BSListNselectCallback, XtCCallback, XtRCallback, sizeof(DwtCallbackPtr), X Offset(slist.selectCallback), XtRCallback, (caddr_t)0`7D, X `7BSListNdoubleClickCallback, XtCCallback, XtRCallback, sizeof(DwtCallback VPtr), X Offset(slist.doubleClickCallback), XtRCallback, (caddr_t)0`7D, X `7BSListNforeground, SListCForeground, XtRPixel, sizeof(Pixel), X Offset(slist.foreground), XtRString, DwtSForegroundDefault`7D, X `7BSListNmarginWidth, SListCMarginWidth, XtRInt, sizeof(int), X Offset(slist.marginWidth), XtRImmediate, (caddr_t)4`7D, X `7BSListNmarginHeight, SListCMarginHeight, XtRInt, sizeof(int), X Offset(slist.marginHeight), XtRImmediate, (caddr_t)6`7D, X `7BSListNtextMarginWidth, SListCTextMarginWidth, XtRInt, sizeof(int), X Offset(slist.textMarginWidth), XtRImmediate, (caddr_t)4`7D, X `7BSListNautoScrollFactor, SListCScrollFactor, XtRInt, sizeof(int), X Offset(slist.autoScrollFactor), XtRImmediate, (caddr_t)20`7D, X `7BSListNdoubleClickInterval, SListCDoubleClickInterval, XtRInt, sizeof(in Vt), X Offset(slist.ClickInterval), XtRImmediate, (caddr_t) 250`7D X#endif X`7D; X`0C Xexternaldef(slistwidgetclassrec) XSListClassRec slistwidgetclassrec = `7B X `7B/* core_class fields`09*/ X`09/* superclass`09`09*/`09(WidgetClass) &compositeClassRec, X`09/* class_name`09 `09*/`09"SList", X`09/* widget_size`09 `09*/`09sizeof(SListWidgetRec), X`09/* class_initialize `09*/ `09NULL, X`09/* class_part_initialize */`09NULL, X`09/* class_inited `09*/`09FALSE, X`09/* initialize`09 `09*/`09(XtInitProc) DoInitialize, X`09/* initialize_hook`09*/`09NULL, X`09/* realize`09`09*/`09(XtRealizeProc) DoRealize, X`09/* actions`09`09*/ `09NULL, X`09/* num_actions`09 `09*/`090, X`09/* resources`09 `09*/`09(XtResource *) resources, X`09/* num_resources`09*/`09(int) XtNumber(resources), X`09/* xrm_class`09 `09*/`09NULLQUARK, X`09/* compress_motion`09*/`09FALSE, X`09/* compress_exposure `09*/`09FALSE, X`09/* compress_enterleave`09*/`09FALSE, X`09/* visible_interest`09*/`09FALSE, X`09/* destroy`09`09*/`09(XtWidgetProc) DoDestroy, X`09/* resize`09`09*/`09(XtWidgetProc) DoResize, X`09/* expose`09`09*/`09(XtWidgetProc) DoExpose, X`09/* set_values`09 `09*/`09NULL, X`09/* set_values_hook`09*/`09NULL, X`09/* set_values_almost `09*/`09(XtAlmostProc) _XtInherit, X`09/* get_values_hook `09*/`09NULL, X`09/* accept_focus`09 `09*/`09NULL, X`09/* version`09`09*/`09(XtVersionType) XtVersionDontCheck, X`09/* callback_private `09*/`09NULL, X`09/* tm_table`09`09*/`09NULL, X`09/* query_geometry`09*/`09NULL, X`09/* display_accelerator`09*/`09NULL, X`09/* extension`09`09*/`09NULL X `7D, X `7B/* composite class fields`09*/ X`09/* geometry_manager`09*/`09DoGeometryManager, X`09/* change_managed`09*/`09DoChangeManaged, X`09/* insert_child`09`09*/`09DoInsertChild, X`09/* delete_child`09`09*/`09DoDeleteChild, X`09/* extension`09`09*/`090 X `7D X#ifdef MOTIF X ,`7B`09`09`09`09`09/* XmPrimitive`09`09*/ X _XtInherit,`09`09`09`09/* border_highlight`09*/ X _XtInherit,`09`09`09`09/* border_unhighlight`09*/ X#ifdef MOTIF_V1_0 X (XtTranslations)_XtInherit,`09`09/* translations`09`09*/ X#else X NULL,`09`09`09`09/* translations`09`09*/ X#endif X NULL,`09`09`09`09/* arm_and_activate`09*/ X NULL,`09`09`09`09/* syn resources`09*/ X 0,`09`09`09`09`09/* num syn_resources`09*/ X NULL,`09`09`09`09/* extension`09`09*/ X `7D X#endif X`7D; X Xexternaldef (slistwidgetclass) XSListClass slistwidgetclass = &slistwidgetclassrec; X XWidget SListCreate(pW, nameP, argsP, argCnt) X Widget pW; X char *nameP; X Arg *argsP; X int argCnt; X`7B X return (XtCreateWidget (nameP, slistwidgetclass, pW, argsP, argCnt)); X`7D X XBoolean SListIsSelected(sl, line) X SListWidget sl; X int line; X`7B X if (line > sl->slist.mapLen `7C`7C line < 0) X`09return False; X X return sl->slist.selectMapP`5Bline`5D; X`7D X#ifndef MOTIF Xvoid SListInitializeForDRM() X`7B X DwtRegisterClass (DRMwcUnknown, "SList", "SListCreate", SListCreate, X`09slistwidgetclass); X`7D X#else X#ifdef USE_MRM Xvoid SListInitializeForMRM() X`7B X MrmRegisterClass (MRMwcUnknown, "SList", "SListCreate", SListCreate, X`09slistwidgetclass); X`7D X#endif X#endif Xstatic void FrameDoResize(w) X SFrameWidget w; X`7B X SFrameResizeCallbackStruct cbData; X X cbData.reason = SFrameCRResize; X cbData.event = 0; X X XtCallCallbacks (w, SFrameNresizeCallback, &cbData); X`7D X Xstatic void FrameDoRealize(w, maskP, attributesP) X SFrameWidget w; X Mask *maskP; X XSetWindowAttributes *attributesP; X`7B X SFrameWidget p = (SFrameWidget) w->core.parent; X if (!w->core.width) w->core.width = 1; X if (!w->core.height) w->core.height = 1; X w->core.border_width = 0; X#ifdef MOTIF X if (!w->manager.shadow_thickness) X`09w->manager.shadow_thickness = p->manager.shadow_thickness; X#endif X XtCreateWindow (w, InputOutput, CopyFromParent, *maskP, attributesP); X`7D Xstatic void FrameInitialize (request, new) XSFrameWidget request, new; X X`7B X if (request -> core.width == 0)`20 X new -> core.width = 10; X X if (request -> core.height == 0)`20 X new -> core.height = 10; X`7D X`0C X#define FOffset(x) XtOffset (SFrameWidget, sframe.x) X Xstatic XtResource frameResources`5B`5D = `7B X `7BSFrameNresizeCallback, XtCCallback, XtRCallback, sizeof (XtCallbackLi Vst), X`09FOffset (resizeCallback), XtRCallback, 0`7D X`7D; X`0C Xexternaldef(sframewidgetclassrec) SFrameClassRec sframewidgetclassrec = `7B X `7B/* core class fields`09*/ X`09/* superclass`09`09*/`09(WidgetClass)&compositeClassRec, X`09/* class_name`09`09*/`09"SFrame", X`09/* widget_size`09`09*/`09sizeof (SFrameWidgetRec), X`09/* class_initialize`09*/`090, X`09/* class_part_initialize */`090, X`09/* class_inited`09`09*/`09FALSE, X`09/* initialize`09`09*/`09FrameInitialize, X`09/* initialize_hook`09*/`090, X`09/* realize`09`09*/`09FrameDoRealize, X`09/* actions`09`09*/ `090, X`09/* num_actions`09 `09*/`090, X`09/* resources`09`09*/`09frameResources, X`09/* num_resources`09*/`09XtNumber (frameResources), X`09/* xrm_class`09`09*/`09NULLQUARK, X`09/* compress_motion`09*/`09TRUE, X`09/* compress_exposure`09*/`09TRUE, X`09/* compress_enterleave`09*/`09TRUE, X`09/* visible_interest`09*/`09FALSE, X`09/* destroy`09`09*/`09NULL, X`09/* resize`09`09*/`09FrameDoResize, X`09/* expose`09`09*/`09NULL, X`09/* set_values`09`09*/`09NULL, X`09/* set_values_hook`09*/`09NULL, X`09/* set_values_almost`09*/`09_XtInherit, X`09/* get_values_hook`09*/`09NULL, X`09/* accept_focus`09`09*/`09NULL, X`09/* version`09`09*/`09XtVersionDontCheck, X`09/* callback_private`09*/`09NULL, X`09/* tm_table`09`09*/`09NULL, X`09/* query_geometry`09*/`09NULL, X`09/* display_accelerator`09*/`09NULL, X`09/* extension`09`09*/`09NULL, X `7D, X `7B/* composite class fields`09*/ X`09/* geometry_manager`09*/`09DoGeometryManager, X`09/* change_managed`09*/`09DoChangeManaged, X`09/* insert_child`09`09*/`09FrameInsertChild, X`09/* delete_child`09`09*/`09DoDeleteChild, X`09/* extension`09`09*/`09NULL, X `7D, X `7B/* Constraint class fields */ X`09/* resource_list`09*/`09NULL, X`09/* num_resources`09*/`090, X`09/* constraint size`09*/`09sizeof(SFrameConstraintRec), X`09/* init proc`09`09*/`09NULL, X`09/* destroy_proc`09`09*/`09NULL, X`09/* set_values proc`09*/`09NULL, X`09/* extension`09`09*/`09NULL, X `7D, X#ifdef MOTIF X `7B`09`09`09`09`09/* XmManager`09`09*/ X `09/* translations`09`09*/`09NULL, X `09/* get_resources`09*/`09NULL, X `09/* num_get_resources`09*/`090, X `09/* get_cont_resources`09*/`09NULL, X`09/* num_get_cont_resources */`090, X`09/* extensions`09`09*/`09NULL, X `7D, X#endif X `7B`09/* Frame class`09`09*/ X`09/* resizeCallback`09*`09NULL, X `09/* extension`09`09*/`09NULL, X `7D X`7D; X Xexternaldef(sframewidgetclass) WidgetClass sframewidgetclass = X (WidgetClass)&sframewidgetclassrec; X XWidget SFrameCreate(pW, nameP, argsP, argCnt) X Widget pW; X char *nameP; X Arg *argsP; X int argCnt; X`7B X return (XtCreateWidget (nameP, sframewidgetclass, pW, argsP, argCnt)); X`7D X X#ifndef MOTIF Xvoid SFrameInitializeForDRM() X`7B X DwtRegisterClass (DRMwcUnknown, "SFrame", "SFrameCreate", SFrameCreate, X`09sframewidgetclass); X`7D X#else X#ifdef USE_MRM Xvoid SFrameInitializeForMRM() X`7B X MrmRegisterClass (MRMwcUnknown, "SFrame", "SFrameCreate", SFrameCreate, X`09sframewidgetclass); X`7D X#endif X#endif $ CALL UNPACK SLIST.C;1 755161263 $ create 'f' X/* slist.h */ X X#ifndef _SList_h X#define _Slist_h X X/* Resource names */ X X#define SListNautoScrollFactor`09`09"autoScrollFactor" X#define SListNforeground`09`09"foreground" X#define SListNpointerForeground`09`09"pointerForeground" X#define SListNmarginHeight`09`09"marginHeight" X#define SListNmarginWidth`09`09"marginWidth" X#define SListNselectCallback`09`09"selectCallback" X#define SListNdoubleClickCallback`09"doubleClickCallback" X#define SListNcurrentPixmap`09`09"currentPixmap" X#define SListNscrollbarLines`09`09"scrollbarLines" X#define SListNstepperScrollFactor`09"stepperScrollFactor" X#define SListNtextMarginWidth`09`09"textMarginWidth" X#define SListNdoubleClickInterval`09"doubleClickInterval" X#define SListNseparatorWidth`09`09"separatorWidth" X#define SFrameNresizeCallback`09`09"resizeCallback" X X/* Resource classes */ X X#define SListCForeground`09`09"Foreground" X#define SListCPointerForeground`09`09"PointerForeground" X#define SListCMarginHeight`09`09"MarginHeight" X#define SListCMarginWidth`09`09"MarginWidth" X#define SListCCurrentPixmap`09`09"CurrentPixmap" X#define SListCScrollbarLines`09`09"ScrollbarLines" X#define SListCScrollFactor`09`09"ScrollFactor" X#define SListCTextMarginWidth`09`09"TextMarginWidth" X#define SListCDoubleClickInterval`09"DoubleClickInterval" X#define SListCSeparatorWidth`09`09"SeparatorWidth" X#define SFrameCResizeCallback`09`09"ResizeCallback" X X/* Callback structures */ X Xtypedef struct `7B X int`09`09reason; X XEvent`09*event; X int`09`09item_number;`09`09/* Item number selected */ X int`09`09item_count;`09`09/* Number of items selected */ X Boolean`09select;`09`09`09/* true for select, false for deselect */ X`7D SListCallbackStruct; X Xtypedef struct `7B X int`09`09reason; X XEvent`09*event; X`7D SFrameResizeCallbackStruct; X X/* Callback reasons */ X X#define SListCRSelect`09`09`091 X#define SListCRDoubleClick`09`092 X#define SFrameCRResize`09`091 X Xvoid SListLoad(/* widget, lineArray, lineCount */); Xvoid SListSetTop(/* widget, item */); Xvoid SListUpdateLine(/* widget, line */); Xvoid SListSelectAll(/* widget, select */); Xvoid SListUnhighlight(/* widget */); Xvoid SListHighlight(/* widget , line */); Xint SListGetHighlight(/* widget */); XBoolean SListIsSelected(/* widget, line */); XWidget SListCreate(/*widget, name, args, argCnt */); Xvoid SListInitializeForDRM(); XWidget SFrameCreate(/*widget, name, args, argCnt */); Xvoid SFrameInitializeForDRM(); X X#ifndef SLIST Xtypedef struct SListClassRec *slistwidgetclassrec; Xtypedef struct SFrameClassRec *sframewidgetclassrec; Xexternalref WidgetClass slistwidgetclass; Xexternalref WidgetClass sframewidgetclass; X#endif X X#endif /* _SList_h */ $ CALL UNPACK SLIST.H;1 996097351 $ create 'f' X/* slistP.h */ X X#ifndef _SListp_h X#define _Slistp_h X#include "slist.h" X Xtypedef struct `7B X int`09`09`09notused; X`7D SListClassPart; X Xtypedef struct _SListClassRec `7B X CoreClassPart`09core_class; X CompositeClassPart composite_class; X#ifdef MOTIF X XmPrimitiveClassPart primitive_class; X#endif X SListClassPart`09slist_class; X`7D SListClassRec, *SListClass; X Xtypedef struct _SListPart X`7B X /* Resource fields */ X#ifdef MOTIF X XmFontList`09`09*fontRecP;`09/* font */ X#else X DwtFontRec`09`09*fontRecP;`09/* font */ X#endif X Pixel`09`09foreground;`09/* foreground color */ X int`09`09`09marginWidth;`09/* margin width in pixels */ X int`09`09`09marginHeight;`09/* margin height in pixels */ X int`09`09`09textMarginWidth; /* text margin width in pixels */ X int`09`09`09autoScrollFactor; /* autoscroll speed factor */ X int`09`09`09cols;`09`09/* initial number of columns */ X int`09`09`09rows;`09`09/* initial number of rows */ X#ifdef MOTIF X XmAnyCallbackStruct`09selectCallback; /* Mb1 callback */ X XmAnyCallbackStruct`09doubleClickCallback; /* double click callback */ X int`09`09`09sepWidth;`09/* width of scrollbar separator */ X int`09`09`09sepOffset;`09/* offset to separator */ X#else X DwtCallbackStruct`09selectCallback; /* Mb1 callback */ X DwtCallbackStruct`09doubleClickCallback; /* double click callback */ X#endif X X /* Private fields */ X Widget`09`09vScroll;`09/* Vertical Scrollbar */ X Widget`09`09sepW;`09`09/* separator widget */ X XFontStruct`09`09*fontP;`09`09/* font */ X int`09`09`09cellHeight;`09/* cell height in pixels */ X int`09`09`09yFontAdjust;`09/* adjustment for text positioning */ X int`09`09`09scrollbarWidth;`09/* scrollbar width (excl separator) */ X int`09`09`09scrollbarOffset;/* scrollbar offset from left margin */ X int`09`09`09leftMarginWidth; /* scrollbar plus left margin */ X GC`09`09`09normgc;`09`09/* normal graphics context */ X GC`09`09`09normtxtgc;`09/* text graphics context */ X GC`09`09`09invgc;`09`09/* text reverse graphics context */ X GC`09`09`09flipgc;`09`09/* invert graphics context */ X int`09`09`09knownHeight;`09/* last known core.height */ X int`09`09`09knownWidth;`09/* last known core.width */ X char`09`09**LineP;`09/* address of text array */ X int`09`09`09LineCnt;`09/* entries used in text array */ X int`09`09`09listIsGrabbed;`09/* we are doing a drag select (T/F) */ X int`09`09`09mouseLine;`09/* line where mouse last seen */ X int`09`09`09highlightedLine; /* line which is highlighted (or -1) */ X int`09`09`09internalYAdjust; /* in pixels */ X int`09`09`09requestedYAdjust; /* in pixels */ X int`09`09`09externalYAdjust; /* in pixels */ X int`09`09`09gropIsPending;`09/* XCopyArea in progress */ X int`09`09`09scrollStrength;`09/* autoscroll factor */ X int`09`09`09anyAreExposed;`09/* some exposures are pending */ X char`09`09*exposeMapP;`09/* expose bytemap */ X char`09`09*selectMapP;`09/* select bytemap */ X int`09`09`09mapLen;`09`09/* allocated bytemap length */ X int`09`09`09selectParity;`09/* flavor of drag select (1/0) */ X int`09`09`09downLine;`09/* line where drag select started */ X int`09`09`09upLine;`09`09/* line where drag select ended */ X int `09`09ClickInterval;`09/* double click delay */ X XtIntervalId`09ClickTimerID;`09/* id for click timer */ X int`09`09`09DownCount;`09/* count of downclicks */ X Time`09`09DownTime;`09/* time of downclick */ X int`09`09`09ClickLine;`09/* line number of first click */ X`7D SListPart; X X/**************************************************************** X * X * Full instance record declaration X * X ****************************************************************/ X`20 Xtypedef struct _SListRec `7B X CorePart`09`09core;`09`09/* Core widget fields */ X CompositePart`09composite;`09/* Composite widget fields */ X#ifdef MOTIF X XmPrimitivePart`09primitive;`09/* Primitive widget fields */ X#endif X SListPart`09`09slist;`09`09/* SList widget fields */ X`7D SListWidgetRec, *SListWidget; X Xtypedef struct `7B X int`09`09`09notused; X`7D SFrameClassPart; X Xtypedef struct _SFrameClassRec `7B X CoreClassPart`09core_class; X CompositeClassPart`09composite_class; X ConstraintClassPart`09constraint_class; X#ifdef MOTIF X XmManagerClassPart`09manager_class; X#endif X SFrameClassPart`09sframe_class; X`7D SFrameClassRec, *SFrameClass; X Xtypedef struct `7B X XtCallbackList`09resizeCallback;`09/* resize callback */ X`7D SFramePart; X Xtypedef struct _SFrameRec `7B X CorePart`09`09core;`09`09/* core widget fields */ X CompositePart`09composite;`09/* composite widget fields */ X ConstraintPart`09constraint;`09/* constraint widget fields */ X#ifdef MOTIF X XmManagerPart`09manager;`09/* manager class fields */ X#endif X SFramePart`09`09sframe;`09`09/* widget class fields */ X /* resources */ X X /* private context */ X`7D SFrameWidgetRec, *SFrameWidget; X Xtypedef struct SFrameConstraintPart `7B X int dummy; X`7D SFrameConstraintPart, *SFrameConstraint; X Xtypedef struct SFrameConstraintRec `7B X#ifdef MOTIF X XmManagerConstraintPart `09manager; X#endif X SFrameConstraintPart`09frame; X`7D SFrameConstraintRec, *SFrameConstraintPtr; X X#endif /* _SListp_h */ $ CALL UNPACK SLISTP.H;1 756365827 $ create 'f' X#define smallicon_width 17 X#define smallicon_height 17 Xstatic char smallicon_bits`5B`5D = `7B X 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xaa, 0x00, X 0xaa, 0x4a, 0x00, 0xea, 0x4a, 0x00, 0xa6, 0x5a, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0xea, 0xd2, 0x00, 0x6e, 0x52, 0x00, 0x2e, 0x96, 0x00, X 0xea, 0xde, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x54, 0x55, 0x00, X 0x00, 0x00, 0x00`7D; $ CALL UNPACK SMALLICON.XBM;1 1075648165 $ create 'f' X/*#define`09DEBUG`091`09`09`09`09`09`09*/ X/* X *`09`09`09`09T . H X * X * Definitions for T. X */ X X#define`09EOS`09`090`09`09/* End of string`09`09*/ X#ifndef`09vax11c X#define`09MAXMEM`09`09100`09`09/* Remember one hundred pages`09*/ X#else X#define`09MAXMEM`09`091000`09`09/* Big memory */ X#endif X#define`09ROWS`09`0924`09`09/* Screen size rows (up/down)`09*/ X#define`09COLS`09`0980`09`09/* Screen size columns (across)`09*/ X#define`09HUGE`09`0932767`09`09/* A very large number`09`09*/ X#define`09MASK`09`090100000`09`09/* High bit for short int's`09*/ X X#define`09rsx_or_vax11c`091`09`09/* Hack to allow RSX code for VMS */ X#ifndef`09rsx X#ifndef`09vax11c X#undef`09rsx_or_vax11c X#endif X#endif X X#ifdef`09vms X/* X * Special definitions for RMS I/O package X */ Xtypedef struct rfa_struct `7B X`09unsigned short int`09word`5B3`5D; X`7D RFAVALUE; X#define`09FILETYPE`09char X#define`09FWILD`09`09rms_fwild X#define`09FNEXT`09`09rms_fnext X#define`09FGETNAME`09rms_getname X#define`09FWILDMODE`09"r" X#define`09kbin`09`09kbgetc X#else X/* X * Normal I/O X */ X#define`09RFAVALUE`09long X#define`09FILETYPE`09FILE X#define`09FWILD`09`09fwild X#define`09FNEXT`09`09fnext X#define`09FGETNAME`09fgetname X#define`09FWILDMODE`09"run" X#endif X/* X * Define information to seek within records X */ X Xtypedef struct `7B X`09RFAVALUE record_rfa;`09`09/* Returned by ftell()`09`09*/ X`09short int buff_offset;`09`09/* Offset in buff`5B`5D of record`09*/ X`09`09`09`09`09/* < 0 if start`09*/ X`09short int line_offset;`09`09/* Offset in textline`5B`5D`09`09*/ X`09`09`09`09`09/* < 0 if saved character`09*/ X`7D RFA; X X/* X * To locate a particular text line, the following information is needed: X *`09rec_rfa`09`09the place to seek to. `09`09set by getrecord() X *`09rec_bor`09`09the place in the record buffer.`09set by getbyte() X *`09rec_txt`09`09the start in the text buffer.`09set by getline() X *`09rec_savec`09not EOS if in a long line.`09set by getline() X * These are saved in memory`5B`5D by saveplace(). Saveplace() also remembe Vrs X * whether a record started with a form-feed, and whether a text line X * is the continuation of a long line. X */ X Xextern`09RFAVALUE magic_cookie;`09`09/* fseek() value to rewind file`09*/ Xextern`09RFAVALUE rec_rfa;`09`09/* Current record being read`09*/ X`09`09`09`09`09/* record.rfa = ftell() info`09*/ X`09`09`09`09`09/* record.place -> text buffer`09*/ X Xextern`09char`09*rec_bor;`09`09/* Next record start in buffer`09*/ Xextern`09char`09*rec_eor;`09`09/* End of record in buffer`09*/ Xextern`09char`09*rec_txt;`09`09/* Text start`09`09`09*/ Xextern`09char`09rec_savec;`09`09/* Saved character`09`09*/ X X#ifdef rsx X X/* X * The following is needed to handle various flavors of logical X * records on vms compatibility mode. X * X *`09R_SEQ`09is returned in FDB @ F.RTYP for VMS print file X *`09`09formatted records. This was determined by inspection. X * X *`09R_STM`09is returned in FDB @ F.RTYP for RMS Stream format. X *`09`09This, too, was determined the hard way. Note, however, X *`09`09that there are several flavors of stream. This is X *`09`09vanilla (). Vax-11 C writes only, while X *`09`09APL is reputed to write only. X * X *`09FD_VFC`09is returned in FDB @ F.RATT for VMS print file X *`09`09formatted records. This was determined by inspection. X * X *`09FD_FTN`09is returned in FDB @ F.RATT to indicate that the X *`09`09first byte of a file contains a Fortran carriage X *`09`09control character. This has not been seen in reality. X * X *`09F_SEQN`09is the offset in the FDB to the sequence number X *`09`09for sequenced records. (Needed for VMS print files) X * X * Note that F.RTYP must be at offset 0 in the FDB and F.RATT must X * be at offset 1. X * X */ X Xextern char`09*R_SEQ;`09`09`09/* Sequenced (printfile)`09*/ Xextern char`09*R_STM;`09`09`09/* RMS stream (on RSTS, too)`09*/ X/* extern char`09*FD_VFC; */`09`09/* Variable-len, fixed control`09*/ X#define`09FD_VFC`094`09`09`09/* VFC on VMS compatibility`09*/ Xextern char`09*FD_FTN; `09`09/* Fortran carriage control`09*/ Xextern char`09*FD_CR;`09`09`09/* Implied carriage return`09*/ Xextern char`09*F_RTYP;`09`09/* Record type in FDB`09`09*/ Xextern char`09*F_RATT;`09`09/* Record attributes in FDB`09*/ Xextern char`09*F_SEQN;`09`09/* Format control in FDB`09*/ X Xextern`09int`09`09max_size;`09/* Maximum file record size`09*/ Xextern`09int`09`09*fdb_seqn;`09/* infdb @ F.SEQN`09`09*/ Xextern`09int`09`09implied_cr;`09/* TRUE if vanilla file`09`09*/ Xextern`09int`09`09fortran_cr;`09/* TRUE if we hack Fortran VFC`09*/ Xextern`09int`09`09vms_printfile;`09/* TRUE if VMS VFC file`09`09*/ Xextern`09int`09`09$$vms;`09`09/* VMS compatibility signal`09*/ X X/* X * buff -> the current record read by getrecord(). Note that it is X * allocated with guard areas before and after for printfile formats. X */ X Xextern`09char`09`09*allobuff;`09/* from calloc()`09`09*/ Xextern`09char`09`09*buff;`09`09/* -> logical record for fget()`09*/ X X#endif X X#ifdef`09vax11c Xextern`09int`09`09max_size;`09/* Maximum file record size`09*/ Xextern`09int`09`09implied_cr;`09/* TRUE if vanilla file`09`09*/ Xextern`09int`09`09fortran_cr;`09/* TRUE if we hack Fortran VFC`09*/ Xextern`09int`09`09vms_printfile;`09/* TRUE if VMS VFC file`09`09*/ X/* X * buff -> the current record read by getrecord(). Note that it is X * allocated with guard areas before and after for printfile formats. X */ X Xextern`09char`09`09*allobuff;`09/* from calloc()`09`09*/ Xextern`09char`09`09*buff;`09`09/* -> logical record for fget()`09*/ X X#endif X X#ifdef`09rt11 X Xextern`09int`09`09max_size;`09/* Maximum record size`09`09*/ Xextern struct rt11record `7B X`09char`09`09guard; X`09char`09`09datum`5B513`5D; X`7D rt11record; X#define`09buff`09`09(&rt11record.datum`5B0`5D) X Xextern int`09`09$$rsts;`09`09/* True if rsts/e emulation`09*/ Xextern int`09`09ctrlc();`09/* Trap CTRL/Z on rsts`09`09*/ X#endif X X#ifdef`09vms X#ifndef vax11c X/* X * VMS native X */ Xextern`09int`09`09max_size;`09`09/* Maximum record size`09*/ Xextern struct vmsrecord `7B X`09char`09`09guard; X`09char`09`09datum`5B1024 + 1`5D; X`7D vmsrecord; X#define`09buff`09`09(&vmsrecord.datum`5B0`5D) X#endif X#endif X X/* X * Things for screen handling X */ X X#define`09IS_VT52`09`09(64+1) X#ifndef vax11c X#define`09IS_VT100`09(96+1) X#else X#define`09IS_VT100_START`09(96+1) X#define IS_VT100_END`09(101+1) X#endif X Xextern`09char`09`09**oldbuf;`09/* For screen package`09`09*/ Xextern`09char`09`09buffer`5B`5D;`09/* For screen package`09`09*/ Xextern`09int`09`09linesperscreen;`09/* Maximum lines per screen`09*/ Xextern`09int`09`09columnsperline;`09/* Maximum columns per line`09*/ Xextern`09int`09`09seeall;`09`09/* True if -e option`09`09*/ Xextern`09int`09`09vt100;`09`09/* True if vt100`09`09*/ Xextern`09int`09`09cursrow;`09/* Cursor row after screen`09*/ Xextern`09int`09`09curscol;`09/* Cursor column after screen`09*/ Xextern`09int`09`09escape;`09`09/* Either 0x1B or 0x9B`09`09*/ X X/* X * Finis is set when the user types CTRL/C or CTRL/Z in response to X * a "next screen" prompt. It forces an exit from the program. X * X * Breakout is set on end of file or when the user types 'X' in X * response to a "next screen" prompt. It exits the current file, X * going on to the next (wildcard) file. Note that the and X * commands clear breakout. X */ X X#define`09HELPROW`093 X Xextern`09char`09`09inline`5B81`5D;`09/* Argument line`09`09*/ Xextern`09FILETYPE`09*infd;`09`09/* Input file descriptor`09*/ Xextern`09char`09`09textline`5B513`5D;`09/* Current output text line`09*/ Xextern`09char`09`09file_name`5B81`5D;`09/* Input file name`09`09*/ Xextern`09char`09`09pfilename`5B81`5D;`09/* Process file name`09`09*/ Xextern`09char`09`09temptext`5B81`5D;`09/* Text work space`09`09*/ Xextern`09char`09`09rx_pattern`5B`5D;`09/* Grep pattern stored here`09*/ Xextern`09int`09`09iseof;`09`09/* switch`09`09*/ Xextern`09int`09`09ff_flag;`09/* Magic form feed signal`09*/ Xextern`09int`09`09finis;`09`09/* TRUE on CTRL/C or CTRL/Z`09*/ Xextern`09int`09`09breakout;`09/* TRUE on eXit`09`09`09*/ Xextern`09RFA`09`09memory`5BMAXMEM`5D;`09/* Top of page memory`09`09*/ Xextern`09RFA`09`09*memptr;`09/* Pointer within memory`5B`5D`09*/ X#define`09LASTMEM`09`09(&memory`5BMAXMEM - 1`5D) Xextern int`09`09eofseen;`09/* TRUE on eof`09`09`09*/ X#ifndef`09vms Xextern`09long`09`09ftell();`09/* Returns file position`09*/ X#endif X X#ifdef`09DEBUG Xextern int`09`09debug;`09`09/* Set for debugging`09`09*/ X#ifdef`09vax11c X#define`09_tracef`09`09printf X#endif X#endif $ CALL UNPACK T.H;1 588211801 $ create 'f' X/* X *`09re_comp(pattern) X *`09char *pattern; X * X * Compile the regular expression pattern. Return TRUE if success. X * The compiled pattern is stored in a global character vector 'rx_pattern' X * X * If an error occurred, re_comp() returns FALSE and rx_pattern contains X * an error message. X * X * X * Syntax errors print a message and return 0. Size errors abort. X * X * X * External routines: X *`09warn`09`09`09Print warning/error messages X *`09fatal`09`09`09Fatal error exit X * X * Regular expressions are defined as follows: X * X * x`09An ordinary character (not mentioned below) matches that character. X * '\'`09The backslash quotes any character. "\$" matches a dollar-sign. X * '`5E'`09A circumflex at the beginning of an expression matches the X * `09 beginning of a line. X * '$'`09A dollar-sign at the end of an expression matches the end of X * `09 a line. X * '.'`09A period matches any character except "new-line". X * ':a'`09A colon matches a class of characters described by the following X * ':d'`09 character. ":a" matches any alphabetic, ":d" matches digits, X * ':n'`09 ":n" matches alphanumerics, ": " matches spaces, tabs, and X * ': '`09 other control characters, such as new-line. X * '*'`09An expression followed by an asterisk matches zero or more X * `09 occurrances of that expression: "fo*" matches "f", "fo" X * `09 "foo", etc. X * '+'`09An expression followed by a plus sign matches one or more X * `09 occurrances of that expression: "fo+" matches "fo", etc. X * '-'`09An expression followed by a minus sign optionally matches X * `09 the expression. X * '`5B`5D'`09A string enclosed in square brackets matches any character in X * `09 that string, but no others. If the first character in the X * `09 string is a circumflex, the expression matches any character X * `09 except "new-line" and the characters in the string. For X * `09 example, "`5Bxyz`5D" matches "xx" and "zyx", while "`5B`5Exyz`5D" X * `09 matches "abc" but not "axb". A range of characters may be X * `09 specified by two characters seperated by "-". Note that, X * `09 `5Ba-z`5D matches alphabetics, while `5Bz-a`5D never matches. X *`20 X * The concatenation of regular expressions is a regular expression. X */ X X#include`09 X#ifdef vms X#include`09 X#define`09FALSE`090 X#define`09TRUE`091 X#endif X#include`09"t.h" X X#define PMAX`09256`09`09`09/* The longest pattern`09`09*/ X X/* X * Note: the following must be identical in re_grep() and re_comp(). X */ X X#define CHAR`091 X#define BOL`092 X#define EOL`093 X#define`09ANY`094 X#define CLASS`095 X#define`09NCLASS`096 X#define STAR`097 X#define`09PLUS`098 X#define`09MINUS`099 X#define`09ALPHA`0910 X#define`09DIGIT`0911 X#define`09NALPHA`0912 X#define`09PUNCT`0913 X#define`09CDIGIT`0914`09`09/* Not used`09`09`09`09*/ X#define RANGE`0915 X#define`09ENDPAT`0916 X Xstatic char`09*rx_pp;`09`09`09/* Work area pointer`09`09*/ Xchar`09`09rx_pattern`5BPMAX`5D;`09/* Pattern output here`09`09*/ Xstatic char *rx_bad(); X Xchar * Xre_comp(pattern) Xchar`09`09*pattern;`09/* Pattern to compile`09`09`09*/ X/* X * Compile the pattern. X */ X`7B X`09register char`09*s;`09`09/* Source string pointer`09*/ X`09register char`09*lp;`09`09/* Last pattern pointer`09`09*/ X`09register int`09c;`09`09/* Current character`09`09*/ X`09int`09`09o;`09`09/* Temp`09`09`09`09*/ X`09char`09`09*spp;`09`09/* Save beginning of pattern`09*/ X`09char`09`09*rx_cclass();`09/* Compile class routine`09*/ X X`09s = pattern; X`09rx_pp = rx_pattern; X`09while (c = *s++) `7B X`09`09/* X`09`09 * STAR, PLUS and MINUS are special. X`09`09 */ X`09`09if (c == '*' `7C`7C c == '+' `7C`7C c == '-') `7B X`09`09`09if (rx_pp == rx_pattern `7C`7C (o=rx_pp`5B-1`5D) == BOL `7C`7C X`09`09`09`09`09o == EOL `7C`7C o == STAR `7C`7C X`09`09`09`09`09o == PLUS `7C`7C o == MINUS) X`09`09`09`09return(rx_bad("Illegal occurrance op.", s)); X`09`09`09rx_store(ENDPAT); X`09`09`09rx_store(ENDPAT); X`09`09`09/* X`09`09`09 * Save the pattern's end and move it down one byte. X`09`09`09 */ X`09`09`09spp = rx_pp; X`09`09`09while (--rx_pp > lp) X`09`09`09`09*rx_pp = rx_pp`5B-1`5D; X`09`09`09*rx_pp = (c == '*') ? STAR : X`09`09`09`09(c == '-') ? MINUS : PLUS; X`09`09`09rx_pp = spp;`09`09/* Restore pattern end`09*/ X`09`09`09continue; X`09`09`7D X`09`09/* X`09`09 * All the rest. X`09`09 */ X`09`09lp = rx_pp;`09`09`09/* Remember start`09*/ X`09`09switch(c) `7B X X`09`09case '`5E': X`09`09`09rx_store(BOL); X`09`09`09break; X X`09`09case '$': X`09`09`09rx_store(EOL); X`09`09`09break; X X`09`09case '.': X`09`09`09rx_store(ANY); X`09`09`09break; X X`09`09case '`5B': X`09`09`09if ((s = rx_cclass(s)) == 0) X`09`09`09`09return("glump"); X`09`09`09break; X X`09`09case ':': X`09`09`09if (*s) `7B X`09`09`09`09c = *s++; X`09`09`09`09switch(tolower(c)) `7B X X`09`09`09`09case 'a': X`09`09`09`09`09rx_store(ALPHA); X`09`09`09`09`09break; X X`09`09`09`09case 'd': X`09`09`09`09`09rx_store(DIGIT); X`09`09`09`09`09break; X X`09`09`09`09case 'n': X`09`09`09`09`09rx_store(NALPHA); X`09`09`09`09`09break; X X`09`09`09`09case ' ': X`09`09`09`09`09rx_store(PUNCT); X`09`09`09`09`09break; X X`09`09`09`09default: X`09`09`09`09`09return(rx_bad("Unknown : type", s)); X X`09`09`09`09`7D X`09`09`09`09break; X`09`09`09`7D X`09`09`09else`09return(rx_bad("No : type", s)); X X`09`09case '\\': X`09`09`09if (*s) X`09`09`09`09c = *s++; X X`09`09default: X`09`09`09rx_store(CHAR); X`09`09`09rx_store(tolower(c)); X`09`09`7D X`09`7D X`09rx_store(ENDPAT); X`09rx_store(EOS);`09`09`09`09/* Terminate string`09*/ X`09return (NULL); X`7D X Xstatic char * Xrx_cclass(src) Xchar`09`09*src;`09`09/* Class start`09`09`09`09*/ X/* X * Compile a class (within `5B`5D) X */ X`7B X`09register char`09*s;`09`09/* Pattern pointer`09`09*/ X`09register char`09*cp;`09`09/* Pattern start`09`09*/ X`09register int`09c;`09`09/* Current character`09`09*/ X`09int`09`09o;`09`09/* Temp`09`09`09`09*/ X X`09s = src; X`09o = CLASS; X`09if (*s == '`5E') `7B X`09`09++s; X`09`09o = NCLASS; X`09`7D X`09rx_store(o); X`09cp = rx_pp; X`09rx_store(0);`09`09`09`09/* Byte count`09`09*/ X`09while ((c = *s++) && c!='`5D') `7B X`09`09if (c == '\\') `7B`09`09/* Store quoted char`09*/ X`09`09`09if ((c = *s++) == '\0')`09/* Gotta get something`09*/ X`09`09`09`09return(rx_bad("Class terminates badly", s)); X`09`09`09else`09rx_store(tolower(c)); X`09`09`7D X`09`09else if (c == '-' && X`09`09`09`09(rx_pp - cp) > 1 && *s != '`5D' && *s != '\0') `7B X`09`09`09c = rx_pp`5B-1`5D;`09`09/* Range start`09`09*/ X`09`09`09rx_pp`5B-1`5D = RANGE;`09/* Range signal`09`09*/ X`09`09`09rx_store(c);`09`09/* Re-store start`09*/ X`09`09`09c = *s++;`09`09/* Get end char and`09*/ X`09`09`09rx_store(tolower(c));`09/* Store it`09`09*/ X`09`09`7D X`09`09else `7B X`09`09`09rx_store(tolower(c));`09/* Store normal char`09*/ X`09`09`7D X`09`7D X`09if (c != '`5D') X`09`09return(rx_bad("Unterminated class", s)); X`09if ((c = (rx_pp - cp)) >= 256) X`09`09return(rx_bad("Class too large", s)); X`09if (c == 0) X`09`09return(rx_bad("Empty class", s)); X`09*cp = c; X`09return(s); X`7D X Xstatic Xrx_store(op) X`7B X`09if (rx_pp >= &rx_pattern`5BPMAX`5D) X`09`09perror("?RXCOMP-F-Pattern too complex"); X`09*rx_pp++ = op; X`7D X Xstatic char * Xrx_bad(message, stopbyte) Xchar`09`09*message;`09/* Error message`09`09`09*/ Xchar`09`09*stopbyte;`09/* Pattern end`09`09`09`09*/ X`7B X`09strcpy(rx_pattern, "Regular expression error \""); X`09strcat(rx_pattern, message); X`09strcat(rx_pattern, "\", stopped at \""); X`09strcat(rx_pattern, &stopbyte`5B-1`5D); X`09strcat(rx_pattern, "\""); X`09return (rx_pattern); X`7D X $ CALL UNPACK T6.C;1 1718599160 $ create 'f' X# X/* X *`09`09`09`09T 7 . C X * X *`09char * X *`09re_exec(string, pattern) X *`09char`09`09*string;`09-- Where to search for it X *`09char`09`09*pattern;`09-- What to search for X * X * Apply the regular expression (pattern`5B`5D) to the argument string`5B`5D V. X * Return 0 if it fails. If successful, return a pointer to the string. X * that matched. Regular expressions are defined in rxcomp(). X * X * Globals unique to this routine are preceeded by "re_". X */ X X#include`09 X#ifdef`09vms X#include`09 X#define`09FALSE`090 X#define`09TRUE`091 X#endif X#include`09"t.h" X X/* X * The following must be identical in rxcomp(). X */ X X#define CHAR`091 X#define BOL`092 X#define EOL`093 X#define`09ANY`094 X#define CLASS`095 X#define`09NCLASS`096 X#define STAR`097 X#define`09PLUS`098 X#define`09MINUS`099 X#define`09ALPHA`0910 X#define`09DIGIT`0911 X#define`09NALPHA`0912 X#define`09PUNCT`0913 X#define`09CDIGIT`0914`09`09/* Not used in this version`09`09*/ X#define RANGE`0915 X#define`09ENDPAT`0916 X Xstatic char`09*re_string;`09`09/* Remember start loc.`09`09*/ X Xchar * Xre_exec(string) Xchar`09`09*string;`09`09/* The string to look for`09*/ X/* X * Match the string, return TRUE if it does. X */ X`7B X`09char *pattern = rx_pattern; X`09register char`09*l;`09`09/* Line pointer`09`09`09*/ X`09char *re_pmatch(); X X`09re_string = string; X`09for (l = string; *l; l++) `7B X`09`09if (re_pmatch(l, string, pattern)) X`09`09`09return(l); X`09`7D X`09return(NULL); X`7D X Xstatic char * Xre_pmatch(line, start, pattern) Xchar`09`09*line;`09`09/* (partial) line to match`09`09*/ Xchar`09`09*start;`09`09/* Invariant line start`09`09`09*/ Xchar`09`09*pattern;`09/* (partial) pattern to match`09`09*/ X/* X * Do the actual work of matching (recursively). Line is the current X * piece of information to match. Start is the entire line -- as passed X * to t_rxgrep(). This is needed for the :c scan. X */ X`7B X`09register char`09*l;`09`09/* Current line pointer`09`09*/ X`09register char`09*p;`09`09/* Current pattern pointer`09*/ X`09register char`09c;`09`09/* Current character`09`09*/ X`09char`09`09*e;`09`09/* End for STAR and PLUS match`09*/ X`09int`09`09op;`09`09/* Pattern operation`09`09*/ X`09int`09`09n;`09`09/* Class counter`09`09*/ X`09char`09`09*are;`09`09/* Start of STAR match`09`09*/ X`09char`09`09*commapos;`09/* Comma position for :c match`09*/ X X`09l = line; X`09p = pattern; X`09commapos = 0;`20 X`09while ((op = *p++) != ENDPAT) `7B X`09`09switch(op) `7B X X`09`09case CHAR: X`09`09`09if (tolower(*l++) != *p++) X`09`09`09`09return(0); X`09`09`09break; X X`09`09case BOL: X`09`09`09if (l != re_string) X`09`09`09`09return(0); X`09`09`09break; X X`09`09case EOL: X`09`09`09if (*l != '\0') X`09`09`09`09return(0); X`09`09`09break; X X`09`09case ANY: X`09`09`09if (*l++ == '\0') X`09`09`09`09return(0); X`09`09`09break; X X`09`09case DIGIT: X`09`09`09if ((c = *l++) < '0' `7C`7C (c > '9')) X`09`09`09`09return(0); X`09`09`09break; X X`09`09case ALPHA: X`09`09`09c = tolower(*l++); X`09`09`09if (c < 'a' `7C`7C c > 'z') X`09`09`09`09return(0); X`09`09`09break; X X`09`09case NALPHA: X`09`09`09c = tolower(*l++); X`09`09`09if (c >= 'a' && c <= 'z') X`09`09`09`09break; X`09`09`09else if (c < '0' `7C`7C c > '9') X`09`09`09`09return(0); X`09`09`09break; X X`09`09case PUNCT: X`09`09`09c = *l++; X`09`09`09if (c == 0 `7C`7C c > ' ') X`09`09`09`09return(0); X`09`09`09break; X X`09`09case CLASS: X`09`09case NCLASS: X`09`09`09c = tolower(*l++); X`09`09`09n = *p++ & 0377; X`09`09`09do `7B X`09`09`09`09if (*p == RANGE) `7B X`09`09`09`09`09p += 3; X`09`09`09`09`09n -= 2; X`09`09`09`09`09if (c >= p`5B-2`5D && c <= p`5B-1`5D) X`09`09`09`09`09`09break; X`09`09`09`09`7D X`09`09`09`09else if (c == *p++) X`09`09`09`09`09break; X`09`09`09`7D while (--n > 1); X`09`09`09if ((op == CLASS) == (n <= 1)) X`09`09`09`09return(0); X`09`09`09if (op == CLASS) X`09`09`09`09p += n - 2; X`09`09`09break; X X`09`09case MINUS: X`09`09`09e = re_pmatch(l, start, p); X`09`09`09while (*p++ != ENDPAT);`09/* Skip over pattern`09*/ X`09`09`09if (e)`09`09`09/* Got a match?`09`09*/ X`09`09`09`09l = e;`09`09/* Yes, update string`09*/ X`09`09`09break;`09`09`09/* Always succeeds`09*/ X X`09`09case PLUS:`09`09`09/* One or more ...`09*/ X`09`09`09if ((l = re_pmatch(l, start, p)) == 0) X`09`09`09`09return(0);`09/* Gotta have a match`09*/ X`09`09case STAR:`09`09`09/* Zero or more ...`09*/ X`09`09`09are = l;`09`09/* Remember line start`09*/ X`09`09`09while (*l && (e = re_pmatch(l, start, p))) X`09`09`09`09l = e;`09`09/* Get longest match`09*/ X`09`09`09while (*p++ != ENDPAT);`09/* Skip over pattern`09*/ X`09`09`09while (l >= are) `7B`09/* Try to match rest`09*/ X`09`09`09`09if (e = re_pmatch(l, start, p)) X`09`09`09`09`09return(e); X`09`09`09`09--l;`09`09/* Nope, try earlier`09*/ X`09`09`09`7D X`09`09`09return(0);`09`09/* Nothing else worked`09*/ X X`09`09default: X`09`09`09abort();`09`09/* Illegal op code`09*/ X`09`09`7D X`09`7D X`09return(l); X`7D $ CALL UNPACK T7.C;1 1409950442 $ create 'f' X- keep bogus ng entries in the .newsrc file X- solve tzname problem X- facility to record all outgoing messages/articles X- handle =ng in active file X- read updated newsrc file X- save and re-edit buttons to editorCommand ending X X- read the bottom two messages in this file X- prefetch should occur at end of list, not largest number (sorted subject.. V.) X X X- saving articles in directories at the save level as KILL files...`20 X- RN DOTDIR stuff X- .xrnlock-serverName X- don't barf on bogus groups X- cleaner mail interface X- grab all of header, store it and all subject lines to use it X- command/key to skipped quoted/included sections X- edit kill file X- flag like 'subjectRead', but for next/next newsgroup X- iconification/deiconification detection for turning on/off rescan X- user selectable cursors X- text search X- rescan in article mode X- strip leading and trailing spaces from newsgroup name in the X Newsgroups field X- kill file processor remove group from string if unread == 0 X- control C to disconnect/reconnect and return to top level... X- different signature for news postings vs mail X- half-page scroll X- allow partial selection on subject line, allow partial X selection to determine what amount of the subject or author is X to be killed.... X- filling of saved articles X- include original article, include current article X- handle events when 'editorCommand' composition window is posted X- local server X- reference based searching X XA user here makes the following two suggestions: X X1. "Subject next" should not find messages that are already marked X read. X X2. When "Subject next" is used, it should become the default for the X action that doTheRightThing performs, like `5EN becomes the default X when you do it in rn. X XFrom: pierre@imag.fr (Pierre LAFORGUE) X XABOUT PREFIXING "FROM" LINES IN MAILBOX SAVING. X XWhen an article is saved in a mailbox, you prefix by ">" the first line Xbeginning by "From:". This is not exactly what is needed to get a correct Xseparation of the mails when the saved article is reread as a mailbox. X XI think the best would be: X- not to prefix the first "From: ", because mailers know the fact that there X may (must!) be a regular "From: " line some lines after the old-style X "From " line. X- prefix by ">" each "From " (not "From:") line following a empty line in th Ve X article. X XThe mail readers algorithm do the following: X- each time an empty line (or the beginning of the file of course) is X followed by a "From " line, it thinks it is a new mail, and it expects X that all the following lines (included a "From: " line) up to the next emp Vty X line are the mail header lines. X- after the empty line following the headers, it considers that all the X following lines, up to an empty line followed by a "From " line, compose X the mail text. X XWith the actual implementation of xrn, an article may appear as two mails if Xit contains an empty line followed by "From " in the text. X`20 X XFrom: Kendall Collett X XRick> Right now XRN lets you do MH-like folders, but not following XRick> the file system as you want. It does DIR/group-name/file-name XRick> (adding 'subdirs' to 'saveMode'). Your method would probably XRick> be easy to add (we already have the code to create the directory XRick> structure for KILL files). We'll put it on our list of things XRick> to do. X XThanks for your answer. I must be misunderstanding how the file-name Xworks. I tried using the subdirs saveMode, but my saved files end up in Xa file named (for instance) DIR/comp.misc/Comp.misc; MH saves messages Xin separate files with sequential number names, so you would have XDIR/comp.misc/1, DIR/comp.misc/2, and so on. I like being able to do Xthis because I use MH (mh-e) to peruse saved news articles. X $ CALL UNPACK TODO.;1 1360369529 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/utils.c,v 1. V11 90/09/29 01:13:39 ricks Exp Locker: ricks $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X X/* X * utils.c: random utility functions for xrn X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include X#include X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#else X#define MAXPATHLEN 512 X#define index strchr X#endif /* VMS */ X X#ifdef aiws Xstruct passwd *getpwuid(); Xstruct passwd *getpwnam(); X#endif /* aiws */ X X#if defined(sun) X#include X#endif X X#ifdef NEED_TEMPNAM X#ifndef VMS X#include X#else X#include X#endif X#endif X X#define USER_NAME_SIZE 32 X X#ifdef SYSV_REGEX X/*`20 X * kludge alert: this is here because (on A/UX 1.1) linking with X * the PW lib (necessary to get the regular expression routines,`20 X * regcmp/regex), causes symbol 'Error' to be undefined. X * `09glenn@mathcs.emory.edu 10/17/89`20 X * X * SYSV_REGEX may be overkill, need for macII and HPUX X * (Andy.Linton@comp.vuw.ac.nz 11/8/89) X */ Xint Error;`20 X#endif X Xchar * XutTrimSpaces(str) Xchar *str; X/* X * trim leading and trailing spaces from a string X * X * NOTE: this function modifiess the argument X * X * returns: the modified string X * X */ X`7B X char *end = &str`5ButStrlen(str) - 1`5D; X X while (*str == ' ') `7B X`09str++; X `7D X while (*end == ' ') `7B X`09*end = '\0'; X`09end--; X `7D X return(str); X`7D X X Xchar * XutTildeExpand(filename) Xchar *filename; /* file name, possibly with a '`7E' */ X/* X * tilde expand a file name X * X * returns: the expanded name of the file (in a static buffer) X * or NIL(char)`20 X */ X`7B X#ifdef aiws X static char dummy`5BMAXPATH`5D; X#else X static char dummy`5BMAXPATHLEN`5D; X#endif /* aiws */ X char username`5BUSER_NAME_SIZE`5D, *loc; X struct passwd *pw; X `20 X if ((filename == NIL(char)) `7C`7C STREQ(filename, "")) `7B X`09return(NIL(char)); X `7D X X if (filename`5B0`5D != '`7E') `7B X`09(void) strcpy(dummy, filename); X`09return(dummy); X `7D X X /* tilde at the beginning now */ X if (filename`5B1`5D == '/') `7B X`09/* current user */ X`09char *home, *getenv(); X`09 X`09if ((home = getenv("HOME")) == NIL(char)) `7B X#ifndef VMS X`09 /* fall back on /etc/passwd */ X`09 if ((pw = getpwuid(getuid())) == NIL(struct passwd)) `7B X`09`09return(NIL(char)); X`09 `7D X`09 (void) sprintf(dummy, "%s%s", pw->pw_dir, &filename`5B1`5D); X#else X`09 return (NIL(char)); X#endif X`09`7D else `7B X`09 (void) sprintf(dummy, "%s%s", home, &filename`5B1`5D); X`09`7D X`09 `20 X `7D else `7B X`09if ((loc = index(filename, '/')) == NIL(char)) `7B X`09 /* error - bad filename */ X`09 return(NIL(char)); X`09`7D X`09(void) strncpy(username, &filename`5B1`5D, loc - &filename`5B1`5D); X`09username`5Bloc - &filename`5B1`5D`5D = '\0'; X#ifndef VMS X`09if ((pw = getpwnam(username)) == NIL(struct passwd)) `7B X`09 return(NIL(char)); X`09`7D X`09(void) sprintf(dummy, "%s%s", pw->pw_dir, loc); X#else X`09return(getenv("USER")); X#endif X `7D X return(dummy); X`7D X X Xint XutSubstring(string, sub) Xchar *string; Xchar *sub; X`7B X int i; X int srcLen = utStrlen(string); X int subLen = utStrlen(sub); X X if (srcLen < subLen) X`09return(0); X `20 X for (i = 0; i < srcLen - subLen + 1; i++) `7B X`09if (STREQN(&string`5Bi`5D, sub, utStrlen(sub))) `7B X`09 return(1); X`09`7D X `7D X return(0); X`7D X X Xvoid XutDowncase(string) Xchar *string; X/* X * down case the characters in a string (in place) X */ X`7B X for ( ; *string != '\0'; string++) `7B X`09if (isupper(*string)) `7B X`09 *string = tolower(*string); X`09`7D X `7D X return; X`7D X X X#ifdef VMS `20 Xint XutGroupToVmsFilename(filename,group) X char *filename; X char *group; X`7B X char *ptr; X int i=0; X X for (ptr = group; *ptr != 0; ptr++) X `7B X`09if (isalnum(*ptr)) X`09`7B X`09 filename`5Bi++`5D = *ptr; X`09`7D X`09else X`09`7B X`09 switch (*ptr) X`09 `7B X`09`09case '.' : X`09`09 filename`5Bi++`5D = '_'; X`09`09 break; X`09`09case '-' : X`09`09 filename`5Bi++`5D = '-'; X`09`09 break; X`09`09default : X`09`09 i = i + sprintf(&filename`5Bi`5D, "$X%X$", *ptr); X`09`09 break; X`09 `7D X`09`7D X `7D X filename`5Bi`5D = 0; X return (i); X`7D X#endif X X X#ifdef VMS `20 Xextern int delete(); Xint unlink(foo) Xchar *foo; X`7B X return(delete(foo)); X`7D X#endif /* VMS */ X X X/* case insensitive, 24 character max, comparision for subjects */ X Xint XutSubjectCompare(str1, str2) Xchar *str1, *str2; X`7B X int count = 0; X char c1, c2; X X while (count++ < 24) `7B X`09if (!*str1 && !*str2) `7B X`09 return 0; X`09`7D X`09if (!*str1) `7B X`09 return -1; X`09`7D X`09if (!*str2) `7B X`09 return 1; X`09`7D X`09if (isupper(*str1)) `7B X`09 c1 = tolower(*str1); X`09`7D else `7B X`09 c1 = *str1; X`09`7D X`09if (isupper(*str2)) `7B X`09 c2 = tolower(*str2); X`09`7D else `7B X`09 c2 = *str2; X`09`7D X`09if (c1 != c2) `7B X`09 return (c1 - c2); X`09`7D X`09str1++; X`09str2++; X `7D X return 0; X`7D Xvoid XutCopyFile(old, save) Xchar *old; /* name of file to save */ Xchar *save; /* name of file to save to */ X`7B X FILE *orig, *new; X char buf`5BBUFSIZ`5D; X char *newFile; X int num_read; X X if ((orig = fopen(old, "r")) == NULL) `7B X`09return; X `7D X X if ((newFile = utTildeExpand(save)) == NIL(char)) `7B X`09return; X `7D X X /* if .old is a link to new we could have trouble, so unlink it */ X (void) unlink(newFile); X `20 X if ((new = fopen(newFile, "w")) == NULL) `7B X`09fclose(orig); X`09return; X `7D X X while (num_read = fread(buf, sizeof(char), BUFSIZ, orig)) `7B X`09(void) fwrite(buf, sizeof(char), num_read, new); X `7D X X (void) fclose(orig); X (void) fclose(new); X X return; X`7D X#ifdef NEED_TEMPNAM X X#define P_tmpdir`09"/usr/tmp/" X Xstatic char check_directory(dir) Xchar *dir; X`7B X struct stat statbuf; X X if (! dir) X`09 return 0; X else if (stat(dir, &statbuf) < 0) X`09 return 0; X else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) X`09 return 0; X else if (access(dir, W_OK `7C X_OK) < 0) X`09 return 0; X else X`09 return 1; X`7D X X/* function for creating temporary filenames */ Xchar *tempnam(dir, pfx) Xchar *dir, *pfx; X`7B X extern char *getenv(); X char *tmpdir = NULL, *env, *filename; X static char unique_letters`5B4`5D = "AAA"; X char addslash = 0; X `20 X /* X * If a directory is passed in, verify that it exists and is a X * directory and is writeable by this process. If no directory X * is passed in, or if the directory that is passed in does not X * exist, check the environment variable TMPDIR. If it isn't X * set, check the predefined constant P_tmpdir. If that isn't X * set, use "/tmp/". X */ X X if (dir && check_directory(dir)) X`09 tmpdir = dir; X else if ((env = getenv("TMPDIR")) && check_directory(env)) X`09 tmpdir = env; X#ifdef P_tmpdir X else if (check_directory(P_tmpdir)) X`09 tmpdir = P_tmpdir; X#endif X else X`09 tmpdir = "/tmp/"; X `20 X /* X * OK, now that we've got a directory, figure out whether or not X * there's a slash at the end of it. X */ X if (tmpdir`5Bstrlen(tmpdir) - 1`5D != '/') X`09 addslash = 1; X X /* X * Now figure out the set of unique letters. X */ X unique_letters`5B0`5D++; X if (unique_letters`5B0`5D > 'Z') `7B X`09 unique_letters`5B0`5D = 'A'; X`09 unique_letters`5B1`5D++; X`09 if (unique_letters`5B1`5D > 'Z') `7B X`09 unique_letters`5B1`5D = 'A'; X`09 unique_letters`5B2`5D++; X`09 if (unique_letters`5B2`5D > 'Z') `7B X`09`09 unique_letters`5B2`5D++; X`09 `7D X`09 `7D X `7D X X /* X * Allocate a string of sufficient length. X */ X filename = XtMalloc(strlen(tmpdir) + addslash + utStrlen(pfx) + 10); X X /* X * And create the string. X */ X (void) sprintf(filename, "%s%s%s%sa%05d", tmpdir, addslash ? "/" : "", X`09`09 pfx ? pfx : "", unique_letters, getpid()); X X return filename; X`7D X#endif X X X#ifdef REALLY_USE_LOCALTIME Xstatic int days`5B`5D = `7B 31,28,31,30,31,30,31,31,30,31,30,31`7D; X X/********************************************************************** XThis function performs the function of mktime as declared in time.h, Xbut which has no definition. It's the inverse of gmtime. X**********************************************************************/ X Xtime_t XmakeTime(tmp) Xstruct tm *tmp; X`7B X time_t ret; X int i; X X if (tmp->tm_year < 70) return 0; X ret = ((tmp->tm_year-70) / 4)*(366+365+365+365); X switch ((tmp->tm_year-70) % 4) `7B X case 1: X ret += 365; X break; X case 2: X ret += 365+365; X if (tmp->tm_mon > 1) `7B X ret += 1; X `7D X break; X case 3: X ret += 365+366+365; X `7D X for (i=0; itm_mon; i++) `7B X ret += days`5Bi`5D; X `7D X ret += tmp->tm_mday-1; X ret = ret*24+tmp->tm_hour; X if (tmp->tm_isdst) `7B X ret -= 1; X `7D X ret = ret*60+tmp->tm_min; X ret = ret*60+tmp->tm_sec; X return ret; X`7D X X#if defined(sun) X/* X * SunOS 4.0.x doesn't have strncasecmp so we need to write one X */ Xstrncasecmp(str1,str2,len) Xchar *str1, *str2; Xint len; X`7B X char *tmp1,*tmp2; X int i,result; X if ((tmp1 = (char *)malloc(len+1)) == NULL) `7B X perror("strncasecmp"); X exit(1); X `7D X if ((tmp2 = (char *)malloc(len+1)) == NULL) `7B X free(tmp1); X perror("strncasecmp"); X exit(1); X `7D X for (i = 0; i < len && str1`5Bi`5D != '\0'; i++) X if (isupper(str1`5Bi`5D)) X tmp1`5Bi`5D = tolower(str1`5Bi`5D); X else X tmp1`5Bi`5D = str1`5Bi`5D; X tmp1`5Bi`5D = '\0'; X for (i = 0; i < len && str2`5Bi`5D != '\0'; i++) X if (isupper(str2`5Bi`5D)) X tmp2`5Bi`5D = tolower(str2`5Bi`5D); X else X tmp2`5Bi`5D = str2`5Bi`5D; X tmp2`5Bi`5D = '\0'; X result = strncmp(tmp1,tmp2,len); X free(tmp1); X free(tmp2); X return result; X`7D X#endif X X/********************************************************************** XThis (ugly) function takes a source of the form "31 Aug 90 16:47:06 GMT" Xand writes into dest the equivalent in local time. If an invalid Xsource is given, the dest is a copy of the source. X XOptionally, there may be a "XXX, " prepending the source where XXX is Xa weekday name. X**********************************************************************/ X Xtconvert(dest, source) Xchar *dest, *source; X`7B X char *p, *fmt; X int h, m, s, day, mon, year; X struct tm *tmp, t; X time_t then; X int doWeekDay; X X strcpy(dest, source); X X /* Parse date */ X p = source; X if (!strncasecmp(p, "mon, ", 5) `7C`7C X !strncasecmp(p, "tue, ", 5) `7C`7C X !strncasecmp(p, "wed, ", 5) `7C`7C X !strncasecmp(p, "thu, ", 5) `7C`7C X !strncasecmp(p, "fri, ", 5) `7C`7C X !strncasecmp(p, "sat, ", 5) `7C`7C X !strncasecmp(p, "sun, ", 5)) `7B X p += 5; X doWeekDay = 1; X `7D else `7B X/* doWeekDay = 0; */ X doWeekDay = 1;`09`09/* Let's put the weekday in all postings */ X `7D X while (*p == ' ') `7B X p++; X `7D X if (!sscanf(p, "%d", &day)) `7B X return; X `7D X while (*p != ' ' && *p != '\0') `7B X p++; X `7D X if (*p == '\0') `7B X return; X `7D X while (*p == ' ' && *p != '\0') `7B X p++; X `7D X if (*p == '\0') `7B X return; X `7D X if (!strncasecmp(p, "jan", 3)) `7B X mon = 0; X `7D else if (!strncasecmp(p, "feb", 3)) `7B X mon = 1; X `7D else if (!strncasecmp(p, "mar", 3)) `7B X mon = 2; X `7D else if (!strncasecmp(p, "apr", 3)) `7B X mon = 3; X `7D else if (!strncasecmp(p, "may", 3)) `7B X mon = 4; X `7D else if (!strncasecmp(p, "jun", 3)) `7B X mon = 5; X `7D else if (!strncasecmp(p, "jul", 3)) `7B X mon = 6; X `7D else if (!strncasecmp(p, "aug", 3)) `7B X mon = 7; X `7D else if (!strncasecmp(p, "sep", 3)) `7B X mon = 8; X `7D else if (!strncasecmp(p, "oct", 3)) `7B X mon = 9; X `7D else if (!strncasecmp(p, "nov", 3)) `7B X mon = 10; X `7D else if (!strncasecmp(p, "dec", 3)) `7B X mon = 11; X `7D else `7B X return; X `7D X while (*p != ' ' && *p != '\0') `7B X p++; X `7D X if (*p == '\0') `7B X return; X `7D X if (!sscanf(p, "%d", &year)) `7B X return; X `7D X year = year % 100; X X /* Parse time */ X p = strrchr(source, ':'); X if (!p) `7B X return; X `7D X p--; X while (p > source && *p != ':') `7B X p--; X `7D X while (p > source && *p != ' ') `7B X p--; X `7D X if (!p) `7B X return; X `7D X sscanf(p, "%d", &h); X p = strchr(p, ':'); X if (!p++) `7B X return; X `7D X sscanf(p, "%d", &m); X p = strchr(p, ':'); X if (!p++) `7B X return; X `7D X sscanf(p, "%d", &s); X p = strchr(p, ' '); X if (!p++) `7B X return; X `7D X X /* Confirm GMT */ X if (strcmp(p, "GMT")) `7B X return; X `7D X X t.tm_sec = s; X t.tm_min = m; X t.tm_hour = h; X t.tm_mday = day; X t.tm_mon = mon; X t.tm_year = year; X t.tm_isdst = 0; X then = makeTime(&t); X tmp = localtime(&then); X `20 X/* ascftime is non-standard, sigh. X ascftime(dest, "%e %b %y %H:%M:%S %Z", tmp); X*/ X fmt = asctime(tmp); X /* Make this look like the original format */ X p = dest; X if (doWeekDay) `7B X switch (tmp->tm_wday) `7B X case 0: X strcpy(dest, "Sun, "); X break; X case 1: X strcpy(dest, "Mon, "); X break; X case 2: X strcpy(dest, "Tue, "); X break; X case 3: X strcpy(dest, "Wed, "); X break; X case 4: X strcpy(dest, "Thu, "); X break; X case 5: X strcpy(dest, "Fri, "); X break; X case 6: X strcpy(dest, "Sat, "); X break; X `7D X p += 5; X `7D X if (*(fmt+8) == ' ') `7B X strncpy(p, fmt+9, 2); X p += 2; X `7D else `7B X strncpy(p, fmt+8, 3); X p += 3; X `7D X strncpy(p, fmt+4, 4); X p += 4; X if ((tmp->tm_year % 100) < 10) `7B X sprintf(p, "0%d", tmp->tm_year % 100); X `7D else `7B X sprintf(p, "%d", tmp->tm_year % 100); X `7D X strcat(dest, fmt+10); X p = strrchr(dest, ' '); X#if defined(sun) X strcpy(p+1, tmp->tm_zone); X#else X if (daylight) `7B X strcpy(p+1, tzname`5B1`5D); X `7D else `7B X strcpy(p+1, tzname`5B0`5D); X `7D X#endif X X if (*dest == ' ') `7B X p = dest; X while (*p != '\0') `7B X *p = *(p+1); X p++; X `7D X `7D X`7D X#endif $ CALL UNPACK UTILS.C;1 2133983747 $ create 'f' X#ifndef UTILS_H X#define UTILS_H X X/* X * $Header: /users/ricks/xrn/src/RCS/utils.h,v 1.13 90/09/29 01:11:11 ricks V Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * utils.h: random utility functions and macros for xrn X */ X X#ifndef MOTIF X#ifndef VMS X#include X#else X#include X#endif X#else X#include X#endif X#ifndef MAX X#define MAX(a,b) (((a)>(b))?(a):(b)) X#endif X X#ifndef _ARGUMENTS X#if defined(FUNCPROTO) `7C`7C defined(__STD__) `7C`7C defined(__cplusplus) ` V7C`7C defined(c_plusplus) X#define _ARGUMENTS(arglist) arglist X#else X#define _ARGUMENTS(arglist) () X#endif X#endif X X#ifdef SYSV X#if defined(__STDC__) Xtypedef void (*SIG_PF0) (int, ...); X#else Xtypedef void`09(*SIG_PF0) (); X#endif X#else X#if defined(__STDC__) Xtypedef int (*SIG_PF0) (int, ...); X#else Xtypedef int`09(*SIG_PF0) (); X#endif X#endif X Xextern char *mktemp _ARGUMENTS((char *)); Xextern char *strtok _ARGUMENTS((char *, const char *)); Xextern char *index _ARGUMENTS((const char *, int)); Xextern char *rindex _ARGUMENTS((const char *, int)); Xextern char *getenv _ARGUMENTS((const char *)); X X X#ifdef macII Xextern int strcmp(); X#endif X X/* allocation macros */ X#define ALLOC(type) (type *) XtMalloc((unsigned) sizeof(type)) X#define ARRAYALLOC(type, sz) (type *) XtMalloc((unsigned) (sizeof(type) * ( Vsz))) X#define NIL(type) (type *) 0 X#define FREE(item) if ((char *) item != NIL(char)) XtFree((char * V) item), item = 0 X#ifdef VMS Xextern int utGroupToVmsFilename(char *filename, char *group); X#endif X#define STREQ(a,b) (strcmp(a, b) == 0) X#define STREQN(a,b,n) (strncmp(a, b, n) == 0) X Xextern char *utTrimSpaces _ARGUMENTS((char *)); Xextern char *utTildeExpand _ARGUMENTS((char *)); Xextern int utSubstring _ARGUMENTS((char *, char *)); Xextern void utDowncase _ARGUMENTS((char *)); Xextern void utCopyFile _ARGUMENTS((char *, char *)); X X#define utStrlen(s)`09((s) ? strlen(s) : 0) X Xextern int utSubjectCompare _ARGUMENTS((char *, char *)); X X#ifdef NEED_TEMPNAM Xextern char *tempnam _ARGUMENTS((char *, char *)); X#endif X X#endif /* UTILS_H */ $ CALL UNPACK UTILS.H;1 1579820669 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/xmisc.c,v 1. V10 90/09/29 01:13:43 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * xmisc.c: routines for handling miscellaneous x functions X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#include X#include X#include X#else X#include X#include X#include X#include X#endif X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#include X#ifdef USE_DEC_CURSOR X#include X#else X#include X#endif /* USE_DEC_CURSOR */ X#else X#include X#include X#include X#ifdef USE_DEC_CURSOR X#include X#else X#include X#endif /* USE_DEC_CURSOR */ X#endif X#ifdef MOTIF X#include X#else X#ifndef VMS X#include X#else X#include X#endif X#endif X#include "xthelper.h" X#include "resources.h" X#include "internals.h" X#include "xrn.h" X#include "xmisc.h" X X X/* XRN icon */ X X#ifdef MOTIF X#include "mxrn.xbm" X#else X#include "dxrn.xbm" X#endif X#include "calvin.icon" X#include "bigicon.xbm" X#include "smallicon.xbm" X#define MOTIF_WM 1 X#define DEC_WM 2 X#ifndef XtNiconifyPixmap X#define XtNiconifyPixmap "iconifyPixmap" X#endif X Xvoid XxmIconCreate(whichWidget) XWidget whichWidget; X`7B X static int WhichWM = -1; X char *bits; X int width, height; X static Pixmap icon_pixmap = (Pixmap) 0; X static Pixmap big_pixmap = (Pixmap) 0; X static Pixmap small_pixmap = (Pixmap) 0; X Arg arg`5B2`5D; X XIconSize *icon_size_list; X int numsizes; X Display *dpy; X `20 X if (WhichWM == -1) `7B X`09dpy = XtDisplay(whichWidget); X`09if (XGetIconSizes(dpy, RootWindow(dpy, DefaultScreen(dpy)), X`09`09`09&icon_size_list, &numsizes)) `7B X`09 if (numsizes > 0) `7B X`09`09if (icon_size_list`5B0`5D.width_inc > 1) `7B X`09`09 WhichWM = DEC_WM; X`09`09`7D else `7B X`09`09 WhichWM = MOTIF_WM; X`09`09`7D X`09 `7D else `7B X`09`09WhichWM = MOTIF_WM; X`09 `7D X`09`7D else `7B X`09 WhichWM = MOTIF_WM; X `7D X `7D`09 X`09 X if (app_resources.calvin) `7B X`09width = calvin_width; X`09height = calvin_height; X`09bits = calvin_bits; X `7D else `7B X#ifdef MOTIF X`09width = mxrn_width; X`09height = mxrn_height; X`09bits = mxrn_bits; X#else X`09width = dxrn_width; X`09height = dxrn_height; X`09bits = dxrn_bits; X#endif X `7D X X if (WhichWM != DEC_WM) `7B X`09 X /* XXX user sets iconPixmap resource, converter does the right thing.. * V/ X`09XtSetArg(arg`5B0`5D, XtNiconPixmap, &icon_pixmap); X`09XtGetValues(whichWidget, arg, 1); X`09if (icon_pixmap == (Pixmap) 0) `7B X`09 XtSetArg(arg`5B0`5D, XtNiconPixmap, X`09`09 XCreateBitmapFromData(XtDisplay(TopLevel), X`09`09`09`09 XtScreen(TopLevel)->root, X`09`09`09`09 bits, width, height)); X`09 XtSetValues(whichWidget, arg, 1); X`09`7D X X `7D else `7B X`09/* DEC window manager */ X`09if (big_pixmap == (Pixmap) 0) `7B X`09 big_pixmap = XCreateBitmapFromData(XtDisplay(TopLevel), X`09`09`09`09 XtScreen(TopLevel)->root, X`09`09`09`09 bigicon_bits, X`09`09`09`09 bigicon_width, bigicon_height); X`09`7D X`09if (small_pixmap == (Pixmap) 0) `7B X`09 small_pixmap = XCreateBitmapFromData(XtDisplay(TopLevel), X`09`09`09`09 XtScreen(TopLevel)->root, X`09`09`09`09 smallicon_bits, X`09`09`09`09 smallicon_width, smallicon_height); X`09`7D X`09XtSetArg(arg`5B0`5D, XtNiconPixmap, big_pixmap); X`09XtSetArg(arg`5B1`5D, XtNiconifyPixmap, small_pixmap); X`09XtSetValues(whichWidget, arg, 2); X `7D X if (app_resources.iconGeometry != NIL(char)) `7B X`09int scr, x, y, junk; X`09Arg args`5B2`5D; X X`09for(scr = 0;`09/* yyuucchh */ X`09 XtScreen(TopLevel) != ScreenOfDisplay(XtDisplay(TopLevel), scr); X`09 scr++); X X`09 XGeometry(XtDisplay(TopLevel), scr, app_resources.iconGeometry, X`09`09 "", 0, 0, 0, 0, 0, &x, &y, &junk, &junk); X`09 XtSetArg(args`5B0`5D, XtNiconX, x); X`09 XtSetArg(args`5B1`5D, XtNiconY, y); X`09 XtSetValues(whichWidget, args, XtNumber(args)); X `7D X return; X`7D X X X#ifndef USE_DEC_CURSOR X/*`20 X * create the normal and busy xrn cursors X */ X Xvoid XbusyCursor() X`7B X static Cursor BusyCursor = (Cursor) 0; X `20 X /* define an appropriate busy cursor */ X if (BusyCursor == (Cursor) 0) `7B X`09BusyCursor = XCreateFontCursor(XtDisplay(TopLevel), XC_watch); X `7D X XDefineCursor(XtDisplay(TopLevel), XtWindow(TopLevel), BusyCursor); X XDefineCursor(XtDisplay(TopLevel), XtWindow(TopList), BusyCursor); X XDefineCursor(XtDisplay(TopLevel), XtWindow(ArticleText), BusyCursor); X if (ComposeTopLevel != (Widget) 0) `7B X`09XDefineCursor(XtDisplay(ComposeTopLevel), X`09`09XtWindow(ComposeTopLevel), BusyCursor); X`09XDefineCursor(XtDisplay(ComposeText), X`09`09XtWindow(ComposeText), BusyCursor); X`09XDefineCursor(XtDisplay(HeaderText), X`09`09XtWindow(HeaderText), BusyCursor); X `7D X XFlush(XtDisplay(TopLevel)); X `20 X return; X`7D X#else /* USE_DEC_CURSOR */ X/*`20 X * create the normal and busy xrn cursors X */ X Xvoid XbusyCursor() X`7B X static Cursor BusyCursor = (Cursor) 0; X static Font cursorFont; X static XColor White, Black; X static Colormap colormap; X Arg arg`5B1`5D; X X /* define an appropriate busy cursor */ X if (BusyCursor == (Cursor) 0) `7B X`09XtSetArg(arg`5B0`5D, XtNcolormap, &colormap); X`09XtGetValues(TopLevel, arg, 1); X`09cursorFont = XLoadFont(XtDisplay(TopLevel), "decw$cursor"); X`09White.pixel = WhitePixelOfScreen(XtScreen(TopLevel)); X`09XQueryColor(XtDisplay(TopLevel), colormap, &White); X`09Black.pixel = BlackPixelOfScreen(XtScreen(TopLevel)); X`09XQueryColor(XtDisplay(TopLevel), colormap, &Black); X`09BusyCursor = XCreateGlyphCursor(XtDisplay(TopLevel), X`09`09`09cursorFont, cursorFont, decw$c_wait_cursor, X`09`09`09decw$c_wait_cursor+1, &Black, &White); X `7D X XDefineCursor(XtDisplay(TopLevel), XtWindow(TopLevel), BusyCursor); X XDefineCursor(XtDisplay(TopLevel), XtWindow(TopList), BusyCursor); X XDefineCursor(XtDisplay(TopLevel), XtWindow(ArticleText), BusyCursor); X if (ComposeTopLevel != (Widget) 0) `7B X`09XDefineCursor(XtDisplay(ComposeTopLevel), X`09`09XtWindow(ComposeTopLevel), BusyCursor); X`09XDefineCursor(XtDisplay(ComposeText), X`09`09XtWindow(ComposeText), BusyCursor); X`09XDefineCursor(XtDisplay(HeaderText), X`09`09XtWindow(HeaderText), BusyCursor); X `7D X XFlush(XtDisplay(TopLevel)); X `20 X return; X`7D X#endif X Xvoid XunbusyCursor() X`7B X XUndefineCursor(XtDisplay(TopLevel), XtWindow(TopLevel)); X XUndefineCursor(XtDisplay(TopLevel), XtWindow(TopList)); X XUndefineCursor(XtDisplay(TopLevel), XtWindow(ArticleText)); X if (ComposeTopLevel != (Widget) 0) `7B X`09XUndefineCursor(XtDisplay(ComposeTopLevel), XtWindow(ComposeTopLevel)); X`09XUndefineCursor(XtDisplay(ComposeText), XtWindow(ComposeText)); X`09XUndefineCursor(XtDisplay(HeaderText), XtWindow(HeaderText)); X `7D X XFlush(XtDisplay(TopLevel)); X `20 X return; X`7D X X/*ARGSUSED*/ Xvoid XCBbusyCursor(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X busyCursor(); X return; X`7D X X X/*ARGSUSED*/ Xvoid XCBunbusyCursor(widget, client_data, call_data) XWidget widget; Xcaddr_t client_data; Xcaddr_t call_data; X`7B X unbusyCursor(); X return; X`7D X X/*`20 X * find out the number of lines in the article display X */ X Xint XarticleLines() X`7B X Dimension height = 0; X Arg arg`5B1`5D; X X#ifdef MOTIF X XtSetArg(arg`5B0`5D, XmNrows, &height); X#else X XtSetArg(arg`5B0`5D, DwtNrows, &height); X#endif X XtGetValues(ArticleText, arg, 1); X if (height < 1 `7C`7C height > 60) height = 60; X return(height); X`7D $ CALL UNPACK XMISC.C;1 1144598280 $ create 'f' X#ifndef XMISC_H X#define XMISC_H X X/* X * $Header: /users/ricks/xrn/src/RCS/xmisc.h,v 1.7 90/09/29 02:29:47 ricks E Vxp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * xmisc.h: routines for handling miscellaneous x functions X * X */ X X/* create the icon and the handlers for it */ Xextern void xmIconCreate(); X Xextern void unbusyCursor(); Xextern void busyCursor(); X X/* suitable for call back use */ Xextern void CBunbusyCursor(/* Widget widget, caddr_t c1, c2 */); Xextern void CBbusyCursor(/* Widget widget, caddr_t c1, c2 */); X X/* find out the number of lines in the article display */ Xextern int articleLines(); X X#endif /* XMISC_H */ $ CALL UNPACK XMISC.H;1 1281754287 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/xrn.c,v 1.14 V 90/09/29 01:13:46 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * xrn.c: set up the main screens X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include "utils.h" X#include "config.h" X#ifndef VMS X#include X#include X#include X#include X#else X#include X#include X#include X#include X#endif X#ifdef MOTIF X#include X#include X#include X#include X#include X#include X#else X#ifndef VMS X#include X#include "Pane.h" X#include "slist.h" X#else X#include X#include "Pane.h" X#include "slist.h" X#endif`09/* VMS */ X#endif`09/* MOTIF */ X#include "xthelper.h" X#include "xmisc.h" X#include "resources.h" X#include "internals.h" X#include "error_hnds.h" X#include "buttons.h" X#include "xrn.h" X X#ifdef VMS X#define CUR_DATE __DATE__ X#endif X#ifdef MOTIF Xvoid PaneSetMinMax(); X#else X#ifndef DwtNmenuExtendLastRow X#define DwtNmenuExtendLastRow "menuExtendLastRow" X#endif X#endif X X#ifdef XFILESEARCHPATH Xstatic void AddPathToSearchPath(); X#endif X Xextern void makeMenus(); X X X/* global variables that represent the widgets that are dynamically changed V */ X XWidget TopLevel; XWidget Frame; XWidget TopButtonBox;`09/* button box containing the command buttons */ XWidget BottomButtonBox;`09/* button box containing the article specific butt Vons */ XWidget TopInfoLine;`09/* top button info line */ XWidget BottomInfoLine;`09/* bottom button info line */ XWidget TopList;`09`09/* newsgroup and article subject display */ XWidget TopFrame;`09/* Frame widget for top list`09`09 */ XWidget ArticleText;`09/* article display */ XWidget PopupMenu;`09/* the popup menus `09`09`09 */ XWidget MenuBar;`09`09/* the menu bar`09`09`09`09 */ Xint XRNState;`09`09/* XRN status: news and x */ X X X/*ARGSUSED*/ Xmain(argc, argv) Xint argc; Xchar **argv; X`7B X#ifdef MOTIF X Widget topShadowFrame, botShadowFrame; X#endif X Arg MinMaxArg`5B2`5D; X X static Arg titleArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNiconName, (XtArgVal) "mxrn"`7D, X`09`7BXmNtitle, (XtArgVal) NULL`7D, X#else X`09`7BXtNiconName, (XtArgVal) "dxrn"`7D, X`09`7BXtNtitle, (XtArgVal) NULL`7D, X#endif X`7D; X static Arg frameArgs`5B`5D = `7B`09`09`09/* main window description */ X`09`7BXtNx,`09`09`09(XtArgVal) 10`7D, X`09`7BXtNy, `09`09`09(XtArgVal) 10`7D, X`09`7BXtNwidth, `09`09(XtArgVal) 10`7D, X`09`7BXtNheight, `09`09(XtArgVal) 10`7D, X#ifdef MOTIF X`09`7BXmNallowResize,`09(XtArgVal) True`7D, X#endif X `7D; X static Arg infoArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNlabelString,`09(XtArgVal) 0`7D, X`09`7BXmNheight,`09`09(XtArgVal) 40`7D, X`09`7BXmNskipAdjust,`09`09(XtArgVal) TRUE`7D, X#else X`09`7BDwtNlabel,`09`09(XtArgVal) 0`7D, X`09`7BDwtNheight,`09`09(XtArgVal) 20`7D, X#endif X `7D; X#ifndef MOTIF X static Arg menuArgs`5B`5D = `7B X`09`7BDwtNx,`09`09 0`7D, X`09`7BDwtNy,`09`09 0`7D, X`09`7BDwtNspacing,`09 20`7D, X`09`7BDwtNorientation, DwtOrientationHorizontal`7D, X `7D; X#endif X static char title`5BLABEL_SIZE`5D; X#ifdef TITLEBAR X Widget titlebar; X static Arg labelArgs`5B1`5D; X#endif X static Arg fontArgs`5B2`5D; X static Dimension fontHeight, fontWidth, listHeight, paneHeight, paneWidt Vh; X#ifdef MOTIF X static XmString labelString; X#else X static DwtCompString labelString; X#endif X X static Arg topBoxArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNresizeHeight,`09(XtArgVal) True`7D, X`09`7BXmNresizeWidth,`09(XtArgVal) False`7D, X`09`7BXmNnumColumns,`09`09(XtArgVal) 3`7D, X`09`7BXmNadjustLast,`09`09(XtArgVal) False`7D, X`09`7BXmNorientation, `09(XtArgVal) XmHORIZONTAL`7D, X`09`7BXmNpacking,`09`09(XtArgVal) XmPACK_TIGHT`7D, X`09`7BXmNskipAdjust,`09`09(XtArgVal) TRUE`7D, X#else X`09`7BDwtNorientation, `09(XtArgVal) DwtOrientationHorizontal`7D, X`09`7BDwtNmenuPacking,`09(XtArgVal) DwtMenuPackingTight`7D, X`09`7BDwtNmenuNumColumns,`09(XtArgVal) 4`7D, X`09`7BDwtNmenuExtendLastRow, (XtArgVal) False`7D, X`09`7BDwtNborderWidth,`09(XtArgVal) 3`7D, X`09`7BDwtNentryBorder,`09(XtArgVal) 2`7D, X`09`7BDwtNspacing,`09`09(XtArgVal) 2`7D, X`09`7BDwtNchildOverlap,`09(XtArgVal) False`7D, X#endif X `7D; X static Arg bottomBoxArgs`5B`5D = `7B X#ifdef MOTIF X`09`7BXmNresizeHeight,`09(XtArgVal) True`7D, X`09`7BXmNresizeWidth,`09(XtArgVal) False`7D, X`09`7BXmNnumColumns,`09`09(XtArgVal) 1`7D, X`09`7BXmNadjustLast,`09`09(XtArgVal) False`7D, X`09`7BXmNorientation, `09(XtArgVal) XmHORIZONTAL`7D, X`09`7BXmNpacking,`09`09(XtArgVal) XmPACK_TIGHT`7D, X`09`7BXmNskipAdjust,`09`09(XtArgVal) TRUE`7D, X#else X`09`7BDwtNorientation, `09(XtArgVal) DwtOrientationHorizontal`7D, X`09`7BDwtNmenuPacking,`09(XtArgVal) DwtMenuPackingTight`7D, X`09`7BDwtNmenuExtendLastRow, (XtArgVal) False`7D, X`09`7BDwtNborderWidth,`09(XtArgVal) 3`7D, X`09`7BDwtNentryBorder,`09(XtArgVal) 2`7D, X`09`7BDwtNspacing,`09`09(XtArgVal) 2`7D, X`09`7BDwtNchildOverlap,`09(XtArgVal) False`7D, X`09`7BDwtNmenuNumColumns,`09(XtArgVal) 1`7D, X#endif X `7D; X static Arg listArgs`5B`5D = `7B`09`09`09/* newsgroup/subject list window V */ X#ifdef MOTIF X`09`7BXmNrows, `09`09(XtArgVal) 10`7D, X`09`7BXmNcolumns,`09`09(XtArgVal) 80`7D, X`09`7BXmNskipAdjust,`09`09(XtArgVal) TRUE`7D, X#else X`09`7BDwtNrows, `09`09(XtArgVal) 10`7D, X`09`7BDwtNcols,`09`09(XtArgVal) 80`7D, X#endif X `7D; X static Arg articleTextArgs`5B`5D = `7B`09`09/* article/all text window * V/ X#ifdef MOTIF X`09`7BXmNrows,`09`09(XtArgVal) 24`7D, X`09`7BXmNcolumns,`09`09(XtArgVal) 80`7D, X`09`7BXmNeditMode, `09`09(XtArgVal) XmMULTI_LINE_EDIT`7D, X`09`7BXmNwordWrap, `09`09(XtArgVal) TRUE`7D, X`09`7BXmNscrollHorizontal,`09(XtArgVal) TRUE`7D, X#else X`09`7BDwtNrows,`09`09(XtArgVal) 24`7D, X`09`7BDwtNcols,`09`09(XtArgVal) 80`7D, X`09`7BDwtNwordWrap, `09`09(XtArgVal) TRUE`7D, X`09`7BDwtNscrollVertical,`09(XtArgVal) TRUE`7D, X`09`7BDwtNeditable,`09`09(XtArgVal) FALSE`7D, X#endif X `7D; X X XRNState = 0; X X#ifdef XFILESEARCHPATH X AddPathToSearchPath(XFILESEARCHPATH); X#endif X `20 X TopLevel = XrnInitialize(argc, argv); X `20 X ehInstallSignalHandlers(); X ehInstallErrorHandlers(); X X if (app_resources.geometry != NIL(char)) `7B X`09int bmask; X`09bmask = XParseGeometry(app_resources.geometry, /* geometry specifi Vcation */ X`09`09`09 (int *) &frameArgs`5B0`5D.value, /* x */ X`09`09`09 (int *) &frameArgs`5B1`5D.value, /* y */ X`09`09`09 (int *) &frameArgs`5B2`5D.value, /* width */ X`09`09`09 (int *) &frameArgs`5B3`5D.value); /* height */ X X`09/* handle negative x and y values */ X`09if ((bmask & XNegative) == XNegative) `7B X`09 frameArgs`5B0`5D.value += (XtArgVal) DisplayWidth(XtDisplay(TopLevel) V, X`09`09`09`09 DefaultScreen(XtDisplay(TopLevel))); X`09 frameArgs`5B0`5D.value -= (int) frameArgs`5B2`5D.value; X`09`7D X`09if ((bmask & YNegative) == YNegative) `7B X`09 frameArgs`5B1`5D.value += (XtArgVal) DisplayHeight(XtDisplay(TopLevel V), X`09`09`09`09`09 DefaultScreen(XtDisplay(TopLevel))); X`09 frameArgs`5B1`5D.value -= (int) frameArgs`5B3`5D.value; X`09`7D X`09XtSetValues(TopLevel, frameArgs, XtNumber(frameArgs)); X `7D X `20 X /* create the pane and its widgets */ X `20 X#ifdef MOTIF X Frame = XtCreateManagedWidget("vpane", xmPanedWindowWidgetClass, TopLeve Vl, X`09`09`09`09 frameArgs, XtNumber(frameArgs)); X#else X Frame = (Widget) DwtPaneCreate(TopLevel, "vpane", frameArgs, X`09`09`09`09`09XtNumber(frameArgs)); X XtManageChild(Frame); X DwtPaneAllowResizing(Frame, DwtResizeShrinkWrap); X#endif X `20 X#ifdef __DATE__ X#ifdef MOTIF X (void) sprintf(title, "mxrn - version %s (compiled on %s)", X`09`09 XRN_VERSION, __DATE__); X#else X (void) sprintf(title, "dxrn - version %s (compiled on %s)", X`09`09 XRN_VERSION, __DATE__); X#endif X#else X#ifdef MOTIF X (void) sprintf(title, "mxrn - version %s", X`09`09 XRN_VERSION); X#else X (void) sprintf(title, "dxrn - version %s", X`09`09 XRN_VERSION); X#endif X#endif X X#ifdef MOTIF X#else X#endif X X#ifdef MOTIF X MenuBar = XmCreateMenuBar(Frame,"MenuBar", NULL, 0); X XtManageChild(MenuBar); X makeMenus(); X XtSetArg(fontArgs`5B0`5D, XmNheight, &fontHeight); X XtGetValues(MenuBar, fontArgs, 1); X fontHeight = fontHeight + 15; X PaneSetMinMax(MenuBar, fontHeight, fontHeight); X#else X MenuBar = DwtMenuBarCreate(Frame, "MenuBar", X`09menuArgs, XtNumber(menuArgs)); X XtManageChild(MenuBar); X makeMenus(); X XtSetArg(fontArgs`5B0`5D, DwtNheight, &fontHeight); X XtGetValues(MenuBar, fontArgs, 1); X fontHeight = fontHeight + 5; X DwtPaneSetMinMax(MenuBar, fontHeight, fontHeight); X#endif X X#ifdef TITLEBAR X#ifdef MOTIF X labelString = XmStringLtoRCreate(title, XmSTRING_DEFAULT_CHARSET); X#else X labelString = DwtLatin1String(title); X#endif X infoArgs`5B0`5D.value = (XtArgVal) labelString; X#ifdef MOTIF X XtSetArg(labelArgs`5B0`5D, XmNlabelString, labelString); X titlebar = XtCreateManagedWidget("titlebar", xmLabelWidgetClass, Frame, X`09`09`09`09 labelArgs, XtNumber(labelArgs)); X#else X XtSetArg(labelArgs`5B0`5D, DwtNlabel, labelString); X titlebar = DwtLabelCreate(Frame, "titlebar",`20 X`09`09`09`09 labelArgs, XtNumber(labelArgs)); X XtManageChild(titlebar); X#endif X X#ifdef MOTIF X XtSetArg(fontArgs`5B0`5D, XmNheight, &fontHeight); X XtGetValues(titlebar, fontArgs, 1); X#else X XtSetArg(fontArgs`5B0`5D, DwtNheight, &fontHeight); X XtSetArg(fontArgs`5B1`5D, DwtNwidth, &fontWidth); X XtGetValues(titlebar, fontArgs, 2); X#endif X X#ifdef MOTIF X PaneSetMinMax(titlebar, fontHeight, fontHeight); X#else X DwtPaneSetMinMax(titlebar, fontHeight, fontHeight); X paneHeight = fontHeight * 3; /* titlebar, top+bot info lines */ X paneWidth = fontWidth; X#endif X#endif /* TITLEBAR */ X X listArgs`5B0`5D.value = app_resources.topLines; X#ifdef MOTIF X topShadowFrame = XtCreateManagedWidget("topFrame", xmFrameWidgetClass, X`09`09`09`09`09 Frame, NULL, 0); X TopFrame = (Widget) SFrameCreate(topShadowFrame, "indexFrame", NULL, 0); X TopList = (Widget) SListCreate(TopFrame, "index", X`09`09listArgs, XtNumber(listArgs)); X#else X TopFrame = SFrameCreate(Frame, "index", NULL, 0); X TopList = SListCreate(TopFrame, "index", listArgs, XtNumber(listArgs)); X#endif X XtManageChild(TopFrame); X XtManageChild(TopList); X X#ifdef MOTIF X XtSetArg(fontArgs`5B0`5D, XmNheight, &listHeight); X XtGetValues(TopList, fontArgs, 1); X PaneSetMinMax(topShadowFrame, listHeight, listHeight); X PaneSetMinMax(TopList, listHeight, listHeight); X#else X XtSetArg(fontArgs`5B0`5D, DwtNheight, &listHeight); X XtSetArg(fontArgs`5B1`5D, DwtNwidth, &fontWidth); X XtGetValues(TopList, fontArgs, 2); X DwtPaneSetMinMax(TopFrame, listHeight, listHeight); X#ifdef TITLEBAR X paneHeight = paneHeight + listHeight + 6; X if (fontWidth > paneWidth) X`09paneWidth = fontWidth; X#else X paneHeight = listHeight + 6; X#endif X#endif X X#ifdef MOTIF X TopInfoLine = XtCreateManagedWidget("indexinfo", xmLabelWidgetClass, Fra Vme, X`09`09`09`09`09infoArgs, XtNumber(infoArgs)); X X#ifndef TITLEBAR X XtSetArg(fontArgs`5B0`5D, XmNheight, &fontHeight); X XtGetValues(TopInfoLine, fontArgs, 1); X fontHeight = fontHeight/2; X#endif X PaneSetMinMax(TopInfoLine, fontHeight, fontHeight); X X TopButtonBox = XtCreateManagedWidget("indexbuttons", X`09`09`09`09`09 xmRowColumnWidgetClass, Frame, X`09`09`09`09`09 topBoxArgs, XtNumber(topBoxArgs)); X /* article display text window */ X X botShadowFrame = XtCreateManagedWidget("botFrame", xmFrameWidgetClass, X`09`09`09`09`09 Frame, NULL, 0); X ArticleText = XmCreateScrolledText(botShadowFrame, "text", X`09`09articleTextArgs, XtNumber(articleTextArgs)); X XtSetValues(ArticleText, articleTextArgs, XtNumber(articleTextArgs)); X XtManageChild(ArticleText); X `20 X XtSetArg(fontArgs`5B0`5D, XmNheight, &listHeight); X XtGetValues(ArticleText, fontArgs, 1); X PaneSetMinMax(ArticleText, listHeight, listHeight); X X BottomInfoLine = XtCreateManagedWidget("textinfo", xmLabelWidgetClass, X`09`09`09`09`09 Frame, infoArgs, XtNumber(infoArgs)); X X PaneSetMinMax(BottomInfoLine, fontHeight, fontHeight); X BottomButtonBox = XtCreateManagedWidget("textbuttons", X`09`09`09`09`09 xmRowColumnWidgetClass, Frame, X`09`09`09`09`09 bottomBoxArgs, X`09`09`09`09`09 XtNumber(bottomBoxArgs)); X X XtSetArg(fontArgs`5B0`5D, XmNheight, &listHeight); X XtGetValues(BottomButtonBox, fontArgs, 1); X PaneSetMinMax(BottomButtonBox, listHeight, listHeight); X XmStringFree(labelString); X#else X TopInfoLine = DwtLabelCreate(Frame, "indexinfo",`20 X`09`09`09`09`09infoArgs, XtNumber(infoArgs)); X X XtManageChild(TopInfoLine); X#ifndef TITLEBAR X XtSetArg(fontArgs`5B0`5D, DwtNheight, &fontHeight); X XtGetValues(TopInfoLine, fontArgs, 1); X paneHeight = paneHeight + fontHeight * 3; X if (fontWidth > paneWidth) X`09paneWidth = fontWidth; X#endif X DwtPaneSetMinMax(TopInfoLine, fontHeight, fontHeight); X TopButtonBox = DwtMenuBarCreate(Frame, "indexbuttons", X`09`09`09`09`09 topBoxArgs, XtNumber(topBoxArgs)); X XtSetArg(fontArgs`5B0`5D, DwtNheight, &listHeight); X XtGetValues(TopButtonBox, fontArgs, 1); X paneHeight = paneHeight + listHeight * 5; /* two button boxes, total 5 l Vines*/ X /* article display text window */ X X XtManageChild(TopButtonBox); X ArticleText = DwtSTextCreate(Frame, "text", X`09`09articleTextArgs, XtNumber(articleTextArgs)); X XtSetValues(ArticleText, articleTextArgs, XtNumber(articleTextArgs)); X XtManageChild(ArticleText); X `20 X XtSetArg(fontArgs`5B0`5D, DwtNheight, &listHeight); X XtSetArg(fontArgs`5B1`5D, DwtNwidth, &fontWidth); X XtGetValues(ArticleText, fontArgs, 2); X paneHeight = paneHeight + listHeight; X if (fontWidth > paneWidth) X`09paneWidth = fontWidth; X BottomInfoLine = DwtLabelCreate(Frame, "textinfo",`20 X`09`09`09`09`09 infoArgs, XtNumber(infoArgs)); X X XtManageChild(BottomInfoLine); X DwtPaneSetMinMax(BottomInfoLine, fontHeight, fontHeight); X BottomButtonBox = DwtMenuBarCreate(Frame, "textbuttons", X`09`09`09`09`09 bottomBoxArgs, X`09`09`09`09`09 XtNumber(bottomBoxArgs)); X X DwtPaneSetMinMax(BottomButtonBox, fontHeight, fontHeight); X XtManageChild(BottomButtonBox); X X XtFree(labelString); X `20 X paneWidth += 20; X paneHeight += 50; X if (paneHeight > 860) paneHeight = 860; X XtSetArg(fontArgs`5B0`5D, DwtNheight, paneHeight); X XtSetArg(fontArgs`5B1`5D, DwtNwidth, paneWidth); X XtSetValues(Frame, fontArgs, 2); X#endif X X /* initialize the news system, read the newsrc file */ X initializeNews(); X XRNState `7C= XRN_NEWS_UP; X X /* create the icon */ X xmIconCreate(TopLevel); X /* X * This next call doesn't do anything by default, unless you X * modify the application defaults file, because there are no X * accelerators for Text in it. However, it makes it possible for X * users to add accelerators to their own resources, so that, for X * example, they can use the arrow keys to scroll through the X * index window rather than through the article text. To do that, X * they would put the following in their resources: X * X * xrn*index.accelerators: #override \n\ X * `09`09Down:`09next-line() \n\ X * `09`09Up:`09previous-line() X */ X#ifdef notdef X XtInstallAccelerators(ArticleText, Text); X#endif X `20 X XtRealizeWidget(TopLevel); X X makePopup(Frame); X X#ifndef TITLEBAR X XChangeProperty(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09 XA_WM_NAME, XA_STRING, 8, PropModeReplace, X`09`09`09title, sizeof(title)-1); X X#ifdef MOTIF X XChangeProperty(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09 XA_WM_ICON_NAME, XA_STRING, 8, PropModeReplace, X`09`09`09"mxrn", 4); X#else X XChangeProperty(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09 XA_WM_ICON_NAME, XA_STRING, 8, PropModeReplace, X`09`09`09"dxrn", 4); X#endif X#endif /* TITLEBAR */ X X /* set up the text window, mode buttons, and question */ X determineMode(); X X unbusyCursor(); X addTimeOut(); X XRNState `7C= XRN_X_UP; X XtMainLoop(); X exit(0); X`7D `20 X#ifdef MOTIF Xvoid PaneSetMinMax(w, min, max) XWidget w; XDimension min; XDimension max; X`7B X Arg minmax`5B5`5D; X int i = 0; X#ifdef MOTIF_V1_0 X if (max <= min) max = min + 1; X XtSetArg(minmax`5Bi`5D, XmNminimum, (XtArgVal) min);i++; X XtSetArg(minmax`5Bi`5D, XmNmaximum, (XtArgVal) max);i++; X#else X if (max < min) max = min + 1; X XtSetArg(minmax`5Bi`5D, XmNpaneMinimum, (XtArgVal) min);i++; X XtSetArg(minmax`5Bi`5D, XmNpaneMaximum, (XtArgVal) max);i++; X XtSetArg(minmax`5Bi`5D, XmNskipAdjust, (XtArgVal) True);i++; X XtSetArg(minmax`5Bi`5D, XmNallowResize, (XtArgVal) True);i++; X#endif X XtSetArg(minmax`5Bi`5D, XmNheight, (XtArgVal) min);i++; X XtSetValues(w, minmax, i); X`7D X#endif X#ifdef XFILESEARCHPATH Xstatic void XAddPathToSearchPath(path) Xchar *path; X`7B X char *old, *new; X X old = getenv("XFILESEARCHPATH"); X if (old) `7B X#if defined(mips) `7C`7C defined(hpux) `7C`7C defined(sun) X`09 /* +1 for =, +2 for :, +3 for null */ X`09 new = XtMalloc((Cardinal) (strlen("XFILESEARCHPATH") + X`09`09`09`09 strlen(old) + X`09`09`09`09 strlen(path) + 3)); X`09 (void) strcpy(new, "XFILESEARCHPATH"); X`09 (void) strcat(new, "="); X`09 (void) strcat(new, old); X`09 (void) strcat(new, ":"); X`09 (void) strcat(new, path); X`09 putenv(new); X#else X`09 /* +1 for colon, +2 for null */ X`09 new = XtMalloc((Cardinal) (strlen(old) + strlen(path) + 2)); X`09 (void) strcpy(new, old); X`09 (void) strcat(new, ":"); X`09 (void) strcat(new, path); X`09 setenv("XFILESEARCHPATH", new, 1); X#endif X `7D X else `7B X#if defined(mips) `7C`7C defined(hpux) `7C`7C defined(sun) X`09 new = XtMalloc((Cardinal) (strlen("XFILESEARCHPATH") + X`09`09`09`09 strlen(path) + 2)); X`09 (void) strcpy(new, "XFILESEARCHPATH"); X`09 (void) strcat(new, "="); X`09 (void) strcat(new, path); X`09 putenv(new); X#else X`09 setenv("XFILESEARCHPATH", path, 1); X#endif X `7D X`7D X#endif $ CALL UNPACK XRN.C;1 510469343 $ create 'f' X X X X 28 November 1988 XRN(1) X X X X NAME X mxrn/dxrn - an X-based interface to the USENET news system that X uses the NNTP remote news server X X SYNOPSIS X _`08m_`08x_`08r_`08n is an X-based interface to the USENET news sy Vstem that uses X the NNTP remote news server for accessing newsgroups and arti- X cles. By using the NNTP server, users can read news from per- X sonal workstations with the program accessing the news groups and X articles from a central repository on the local area network. X This manual page applies to version 6.14. X X DESCRIPTION X _`08m_`08x_`08r_`08n `5B-breakLength len`5D `5B-cancelCount number V`5D `5B+/-cc`5D `5B+/-confirm X list`5D `5B-deadLetters file`5D X `5B+/-displayLineCount`5D `5B-distribution dist`5D `5B+/-dumpCore` V5D `5B- X editorCommand command`5D `5B-iconGeometry +X+Y`5D `5B+/-includeHea Vder`5D X `5B-includePrefix "prefix text"`5D `5B+/-includeSep`5D `5B+/-inclu VdeSep`5D X `5B+/-info`5D `5B+/-killFiles`5D `5B-leaveHeaders list`5D `5B-line VLength len`5D X `5B-minLines number`5D `5B-maxLines number`5D `5B-newsrcFile file` V5D `5B- X nntpServer name`5D `5B-organization organization`5D `5B+/-pageArti Vcles`5D X `5B-printCommand command`5D `5B-replyTo name`5D `5B-rescanTime tim Ve`5D `5B+/- X resetString`5D `5B-saveDir directory`5D `5B-saveNewsrcFile file`5D V `5B- X saveString string`5D `5B-saveMode mode`5D `5B-savePostings file`5D V `5B- X signatureFile file`5D `5B+/-sortedSubjects`5D `5B-stripHeaders lis Vt`5D X `5B+/-subjectRead`5D `5B-topLines number`5D `5B-tmpDir directory`5 VD `5B+/- X typeAhead`5D `5B+/-updateNewsrc`5D `5B+/-verboseKill`5D `5B-addBut VtonList X list`5D `5B-ngButtonList list`5D `5B-artButtonList list`5D `5B- X artSpecButtonList list`5D `5B-allButtonList list`5D `5B-addBinding Vs bind- X ings`5D `5B-ngBindings bindings`5D `5B-artBindings bindings`5D `5B V- X allBindings bindings`5D X X Along with the standard toolkit options: display, geometry, xrm, X and iconic. X X BASIC OPERATION X X Don't let the size of this manual page alarm you. _`08m_`08x_`08r V_`08n is easy X to learn on-line without reading the documentation. This manual X page describes many features that may be obvious to the casual X observer, along with a large section on customization (such as X choosing colors and fonts). It also describes how to use scroll X bars, buttons, and select text; if you have used an X toolkit X application before, the section titled "BUTTONS, SCROLL BARS, and X SELECTION" can be skipped. X X _`08m_`08x_`08r_`08n uses the `60.newsrc' file to determine what g Vroups need to be X read. If the `60.newsrc' file does not exist, it is created, and X the user is subscribed to the news group X `60news.announce.newusers'. X X _`08m_`08x_`08r_`08n has four modes of operation: Add, Newsgroup, V All, and Arti- X cle modes. Add mode will be entered on startup if there are any X X X X UCB 1 X X X X X X X XRN(1) 28 November 1988 X X X groups that the news system knows about that are not in the X `60.newsrc' file (_`08i._`08e., new groups). In Add mode, the use Vr is X given a list of new groups. Groups can then be subscribed to and X placed in the `60.newsrc' file at the first position, the last X position, or after a group already in the `60.newsrc' file. When X Add mode is exited, any remaining groups are added unsubscribed, X so the user is not asked about them the next time _`08m_`08x_`08r_ V`08n is X started. On exit from Add mode, or on startup if there are no X new groups, Newsgroup mode is entered. Newsgroup mode displays X the subscribed to groups that have unread articles and the range X of available articles. The basic functions available in this X mode allow the user to read a group, mark all articles in a group X as read, unsubscribe from a group, move the cursor around the X newsgroup window, change the order of the list of newsgroups, X re-visit the most recently visited group, and quit _`08m_`08x_`08r V_`08n. In X addition, the user can subscribe to a group and specify its posi- X tion in the `60.newsrc' file, query the news server for new arti- X cles and groups, and go to groups that are either not subscribed X to or currently have no unread articles (_`08i._`08e., groups not X displayed on the screen). From Newsgroup mode the user can go X into All mode. In All mode the user is presented with a sorted X list of all known groups and their subscription status (sub- X scribed or unsubscribed) and can change their status or location X in the `60.newsrc' file. On exiting All mode the user is placed X back in Newsgroup mode. In order to read the articles in a par- X ticular group, the user goes from Newsgroup mode to Article mode. X In Article mode the user can sequence through the articles in the X group forward or backward, mark a group of articles as read or X unread, mark all articles in the current group as read, unsub- X scribe to the current group, return to the last article visited, X search forward or backward for an article subject (either for the X exact subject or for a regular expression in the subject), X locally kill all articles with a particular subject, and quit X (saving all changes) or exit (leaving all articles marked X unread). In addition, the user can save the current article in a X file, post an article to the group, post a followup to the X current article, mail a reply to the author of an article, and X return to Newsgroup mode. X X NEWS SYSTEM X X The news system is a set of bulletins, discussion groups, program X sources, and other bits of information distributed around the X world under the name `60USENET'. The information is generally X called `60news' and is broken up into `60newsgroups'. Each newsgr Voup X deals with a subject or set of subjects. The subjects for news- X groups are varied: from discussions about particular versions of X UNIX to movie reviews, from information on the X window system to X commentary on current social and political issues. X X For information on what newsgroups are available, answers to com- X monly asked questions, and newsgroup ediquette, read the articles X in the newsgroup `60news.announce.newsusers'. X X X X 2 X UCB X X X X X X X 28 November 1988 XRN(1) X X X NEWS SERVER X X In order to run _`08m_`08x_`08r_`08n on a machine, the machine mus Vt be running an X NNTP news server or be on a network that has a machine running an X NNTP news server (the source for an NNTP server can be retrieved X by anonymous ftp from the machine `60ucbvax.berkeley.edu' X `5B128.32.137.3, 10.2.0.78`5D). Either the file X `60/usr/local/lib/rn/server' must contain the name of the server X machine, the environment variable NNTPSERVER must be set to the X name of the server machine, the nntpServer Xdefault must be set X to the name of the server machine, or the `60-nntpServer' flag mus Vt X be specified on the command line (with the order of precedence X being command line, Xdefault, environment variable, file). X X SCREEN LAYOUT X X The screen displayed by _`08m_`08x_`08r_`08n consists of seven sec Vtions: a title X bar, two scrollable text windows, two information bars, and two X button boxes. The title bar displays the current version of the X program. The top text window displays information based on the X mode. In Add mode, the window displays all groups that are not X currently in the `60.newsrc' file, one per line. In Newsgroup X mode, the window displays the groups containing unread articles; X each group represented by a line of the form: X X Unread news in article(s) `5B, V`5D X X is the name of the group, is the number of X unread articles, and and are the numbers of the X first and last available articles, respectively. In Article X mode, the window displays a list of subjects for the articles in X the current group, with each subject line being represented by a X line of the form: X X `5B+u`5D`5BS`5D X X where is the article number, a `60+' in the first position X means that the article has been read, a `60u' in the first positio Vn X means that the article has been marked as unread, and a 'S' in X the second position means that the article has been saved to a X file. The top information bar displays information about the X mode, the buttons in the top button box, and error messages. The X top button box has buttons that are specific to the mode and X apply to the information in the top text window. The bottom text X window displays articles in Article mode and a list of all known X groups and their subscription status in All mode. The bottom X information bar displays information about the mode, the buttons X in the bottom button box, and error messages. The bottom button X box has buttons that are specific to the mode and apply to the X information in the bottom text window. X X X X X X X X UCB 3 X X X X X X X XRN(1) 28 November 1988 X X X BUTTONS, SCROLL BARS, AND SELECTION X X All button and text selection commands are done with the left X mouse button. Single-line text selection is accomplished by X clicking the left mouse button on the desired line. Multiple- X line selection is accomplished by clicking the left mouse button X on the first line, holding the button down, dragging the mouse to X the last line, and releasing the mouse button. Extended selec- X tion can be done by clicking on an article or range of articles, X then using shift-click to add or remove an article from the X selection. Selected lines appear in reverse video (the fore- X ground and background colors are switched). The text windows are X scrolled with the scroll bar on the right side of the window. X Clicking the left mouse button in the scroll bar will scroll the X text down some fraction of a page; the `60slider' or `60elevator' V in X the scrollbar can be dragged to perform more rapid scrolls. Hit- X ting the space bar (while the mouse cursor is in the top button X box) will do the right thing; scroll the article text window when X appropriate, go to the next article at the end of the current X article, go to newsgroup mode when done with all articles in the X current group, and go to the next group when in newsgroup mode. X X MODES X X The next few sections describe the individual modes in _`08m_`08x_ V`08r_`08n. X Each button in the various modes is described with the label for X the button and the name of the button. The name of the button X can be used in X resources, in the button lists, and in the bind- X ings tables. X X ADD MODE X X Add mode is entered when new groups have been detected (groups X that the news system knows about but are not in the `60.newsrc' X file). X X quit (addQuit) X Add remaining groups in the list to `60.newsrc' as unsub- X scribed; go to group mode. X X add first (addFirst) X Add the current group(s) to the beginning of the `60.newsrc' X file and mark as subscribed. The current group is the X selected group(s), or the group on the line containing the X cursor. X X add last (addLast) X Add the current group(s) to the end of the `60.newsrc' file X and mark as subscribed. X X add after group (addAfter) X Add the current group(s) after a group already in the X `60.newsrc'. A dialog box is used to allow the user to enter X the name of the group to add the group after. The mouse X X X 4 X UCB X X X X X X X 28 November 1988 XRN(1) X X X cursor must be in the dialog box for _`08m_`08x_`08r_`08n to V accept text X (however, it does not have to be in the type-in area). The X dialog box has two options: abort and add. No other buttons X on the screen will work until the user has selected an X option in the dialog box. Hitting carriage return is the X same as clicking the add button (in all _`08m_`08x_`08r_`08n V dialog boxes X hitting carriage return is the same as clicking in the X rightmost button of the dialog box). X X add unsubscribed (addUnsub) X Add the current group(s) to the end of the `60.newsrc' file X and mark as unsubscribed. X X X NEWSGROUP MODE X X Newsgroup mode informs the user of the groups with unread news X and gives the user control over which groups are visited. Click- X ing the middle button on the newsgroup entry will enter the news- X group. X X quit (ngQuit) X quit _`08m_`08x_`08r_`08n. X X read group (ngRead) X Read the articles in the current group. The current group X is either the one selected (if one is selected) or the one X on the line containing the cursor. If all groups have been X read, the user can still access groups by using the goto X newsgroup command. Hitting the space bar with the cursor in X the top button box will call this function. X X next (ngNext) X Move the cursor to the next group, leaving the articles in X the current group untouched. X X prev (ngPrev) X Move the cursor to the previous group, leaving the articles X in the current group untouched. X X catch up (ngCatchUp) X Mark all articles in the current group as read. X X subscribe (ngSubscribe) X Subscribe to a group. A dialog box is used to allow the X user to enter the name of the group. The dialog box has the X following options: abort, prev group (subscribe to the pre- X vious group visited), first (put group in the beginning of X the `60.newsrc' file), last (put group in the end of the X `60.newsrc' file), and current position (put group at the X position of the cursor). This command can also be used to X change the position of a subscribed group. Hitting carriage X return after typing in the name is the same as clicking the X current position button. X X X X UCB 5 X X X X X X X XRN(1) 28 November 1988 X X X unsubscribe (ngUnsub) X Unsubscribe from the current group. X X goto newsgroup (ngGoto) X Go to a group that is not currently displayed. The first X unread article is displayed. If all articles in the group X have been read, the last article in the group is displayed. X The name specified can be a substring of the group name or a X regular expression. X X all groups (ngAllGroups) X Display all of the groups that exist, their subscription X status, and a set of buttons for changing the status. X X rescan (ngRescan) X Query the server for any new groups or articles. X X prev group (ngPrevGroup) X Re-visit the previous group visited. X X list old (ngListOld) X List all of the groups subscribed to, independent of if they X have any unread articles. X X select groups (ngSelect) X Records the groups currently selected. If no groups are X selected, nothing is recorded. X X move (ngMove) X Moves the groups previously selected with the select groups X command to the current cursor position. If the cursor is X currently inside the groups to be moved, no groups are X moved. If any other button is invoked after select groups X and before move, the selection is lost, and no groups are X moved. X X exit (ngExit) X Quit _`08m_`08x_`08r_`08n, leaving the `60.newsrc' file uncha Vnged since the X last `60rescan' operation or `60checkpoint'. If `60updateNew Vsrc' X is on, then the `60.newsrc' file is kept up to date with the X last time Article mode was exited. X X checkpoint (ngCheckPoint) X Update the `60.newsrc' file. _`08m_`08x_`08r_`08n normally up Vdates the X `60.newsrc' file on `60rescan' and `60quit' in Newsgroup mode V. X This allows you to update the `60.newsrc' file without exitin Vg X _`08m_`08x_`08r_`08n or reconnecting to the server (see also V 'artCheck- X Point'). X X gripe (ngGripe) X Send a gripe (bug, bug fix, complaint, feature request, X etc.) to the authors of the program. X X post (ngPost) X X X 6 X UCB X X X X X X X 28 November 1988 XRN(1) X X X Post an article to a newsgroup. See "post" under Article X mode for more information. X X ALL MODE X X All mode allows the user to change both the subscription status X and the `60.newsrc' file position of any available group. All X operations can apply to multiple groups. Thus, the user should X never have to use a text editor on the `60.newsrc' file. Hitting X the space bar with the cursor in the top button box will scroll X the bottom text window. X X quit (allQuit) X Update the `60.newsrc' file and return to group mode. X X subscribe (allSub) X Subscribe to the current group, leaving it at its current X position in the `60.newsrc' file. X X subscribe first (allFirst) X Subscribe to the current group and add it to the beginning X of the `60.newsrc' file. X X subscribe last (allLast) X Subscribe to the current group and add it to the end of the X `60.newsrc' file. X X subscribe after group (allAfter) X Subscribe to the current group and add it after a particular X group in the `60.newsrc' file (which is entered with the use X of a dialog box). X X unsubscribe (allUnsub) X Unsubscribe the current group. X X goto group (allGoto) X Go to the current newsgroup. X X select groups (allSelect) X X move (allMove) X Same as the "select groups" and "move" buttons in Newsgroup X mode. X X toggle order (allToggle) X Toggle the order of the newsgroups in the window between X `60.newsrc' order and alphabetical order. X X scroll forward (allScroll) X Scroll the all groups window forward a page. X X scroll backward (allScrollBack) X Scroll the all groups window backwards a page. X X X X X UCB 7 X X X X X X X XRN(1) 28 November 1988 X X X Search (allSearch) X Search the all groups window for a group. X X Continue Search (allContinue) X Continue the all groups search. X X Cancel Search (allCancelSearch) X Cancel the all groups search. X X ARTICLE MODE X X Article mode is used for reading and manipulating articles in a X single group. When a group is entered, the list of article sub- X jects displayed contains those from the first unread article to X the last available article. Previous articles can be obtained by X using the prev or subject previous commands. Hitting the space X bar with the cursor in the top button box in Article mode will X `60`60do the right thing''; it will scroll an article if there is X more of the article to see and call the next unread function if X there is no more of the article to see. Clicking the middle but- X ton on the article entry will display the article. X X quit (artQuit) X Update the `60.newsrc' file and return to group mode. X X next unread (artNextUnread) X Display the selected article if it is unread; otherwise, X display the first unread article AFTER the cursor position. X If no unread articles exist, _`08m_`08x_`08r_`08n returns to V Newsgroup mode. X X next (artNext) X Display the selected article, if any; otherwise, display the X next article in the current group. Return to Newsgroup mode X after the last article has been reached. X X scroll forward (artScroll) X Scroll the article text forward a page. X X scroll backward (artScrollBack) X Scroll the article text backward a page. X X prev (artPrev) X Display the selected article, if any; otherwise, display the X previous article in the current group. X X last (artLast) X Display the last article accessed before the currently X displayed one. This command only keeps track of one previ- X ously accessed article, so invoking it repeatedly simply X toggles the display between two articles. X X next newsgroup (artNextGroup) X Go directly to the next newsgroup with unread news (bypass X newsgroup mode). X X X 8 X UCB X X X X X X X 28 November 1988 XRN(1) X X X goto article (artGotoArticle) X Go to the specified article number. Articles read in previ- X ous sessions can be accessed using this command. X X catch up (artCatchUp) X Mark all articles in the current group as read; return to X Newsgroup mode. If a particular article is selected, catch X up from the beginning of the group to the selected article. X X fed up (artFedUp) X Mark all articles in the current group as read; go to the X next newsgroup. X X mark read (artMarkRead) X Mark an article (or group of articles) as read. This com- X mand marks either the selected article(s) or the article the X cursor is on, and leaves the cursor at its current position. X X mark unread (artMarkUnread) X Mark an article (or group of articles) and unread. This X command marks either the selected article(s) or the article X the cursor is on, and leaves the cursor at its current posi- X tion. When an article is marked as unread, a 'u' is placed X in the far left column next to the article's subject. The X next, prev, subject next, and subject prev buttons will all X display this article if they come across it, but the next X unread button will not. The only way to mark an article as X read once it has been marked with a 'u' is to use the mark X read function. X X unsubscribe (artUnsub) X Unsubscribe from the current group; return to Newsgroup X mode. X X subject next (artSubNext) X Find and display the next article with the same subject as X the current article (stripping the '`5BrR`5D`5BeE`5D:' garbag Ve). If X there are no more articles with the current subject and X there are more unread articles, the first unread article is X selected. If there are no more articles with the current X subject and there are no more unread articles, Article mode X is exited. X X subject prev (artSubPrev) X Find and display the previous article with the same subject X as the current article. The search will proceed past the X current list of articles to scan articles read in previous X sessions. X X read. X List all articles available in the group, even those that have bee Vn X X session kill (artKillSession) X Mark all articles with the current subject as read, for this X X X X UCB 9 X X X X X X X XRN(1) 28 November 1988 X X X session only. X X local kill (artKillLocal) X Mark all articles with the current subject as read for this X group, and for this and all future sessions. X X global kill (artKillGlobal) X Mark all articles with the current subject as read for all X groups, and for this and all future sessions. X X author kill (artKillAuthor) X Mark all articles by the current author as read for this X session only. X X subject search (artSubSearch) X Begin a regular expression subject search. When this button X is invoked, a window pops up querying the user for a regular X expression (of the form used in ed), and a direction in X which to search. If a regular expression is not typed in, X the last regular expression is used, and the search direc- X tion is the one specified in the dialog box (this can be X used to switch the direction of the search without retyping X the expression). X X continue (artContinue) X Continue the last regular expression search by searching for X the same regular expression in the same direction. X X cancel search (artCancelSearch) X Cancel the regular expression search. X X toggle order (artSorted) X Change the order of entries in the subject window: article X number order or sorted by subject. X X post (artPost) X Post an article to the current group. A scrollable, edit- X able text window will appear with a header and the user's X `60`7E/.signature' file included. An appropriate header will V be X generated with a number of blank header fields that if left X blank will be deleted from the posting. The editor defaults X to the standard Xtoolkit editor (similar to emacs), and the X default can be overridden by using the command line option X -editorCommand or by setting the same Xdefault (see the sec- X tion on command line arguments). The mouse buttons can be X used to select text in this window (which can then be placed X in a file, for example). X X There are four buttons at the bottom of the window: abort, X send (to post the article), save (to save the article in a X file), and include (include the text of the article in the X reply or followup). Only one post (or followup or reply) X window can be active at a time. X X X X 10 X UCB X X X X X X X 28 November 1988 XRN(1) X X X exit (artExit) X Exit article mode, marking all articles listed in the top X window as unread. X X checkpoint (artCheckPoint) X Update the `60.newsrc' file. _`08m_`08x_`08r_`08n normally up Vdates the X `60.newsrc' file on `60rescan' and `60quit' in Newsgroup mode V. X This allows you to update the `60.newsrc' file without exitin Vg X _`08m_`08x_`08r_`08n or reconnecting to the server (see also V 'ngCheck- X Point'). X X gripe (artGripe) X Send a gripe (bug, bug fix, complaint, feature request, X etc.) to the authors of the program. X X save (artSave) X Save the current article in a file, or use the current arti- X cle as standard input to a command. The save command will X pop up a dialog box for the filename. The dialog box has X two buttons: abort and save. If the filename begins with a X `60`7C', the article will be sent to the command specified af Vter X the `60`7C'. Otherwise, the article will be appended to the X file specified. If the name is relative (does not begin X with `60/' or `60`7E'), it will be prepended by `60`7E/News/' V. If no X name is specified, it will be saved in `60`7E/News/', X where `60' is the name of the current group with X the first letter capitalized (follows the _`08r_`08n article V saving X conventions). If -saveMode is set to `60subdirs', then X `60`7E/News//' will be used instead of `60`7E/News V/'. X Multiple articles can be selected and saved with one com- X mand. If the filename contains the characters `60%d', the X article number will replace that string; otherwise, the X group of articles will be appended into a single save file. X For VMS, piping of articles to commands (`60`7C') is not sup- X ported. File names are used as given. If no filename is X given in a `60save' command, the group name will be used for V a X filename (with second and subsequent periods converted to X underscores; for example, `60comp.os_vms'. Subdirs save mode X on VMS uses the group name to create a subdirectory for sav- X ing the articles. X X reply (artReply) X Reply (by mail) to the author of the current article. See X post for a description of how to create and send a message. X X forward (artForward) X Send the current article to another person via mail. X X followup (artFollowup) X Post a followup article to the current article. See post X for a description of how to create and send an article. X X cancel (artCancel) X Cancel the current article. X X X X UCB 11 X X X X X X X XRN(1) 28 November 1988 X X X rot-13 (artRot13) X Decrypt a encrypted article. In the newsgroup `60rec.humor', X occasionally articles are submitted that may offend certain X people or groups of people. In order to minimize the X offense, these articles are posted in an encrypted form. X This button will decrypt them. X X toggle header (artHeader) X Show the full text of an article, including the full header. X X print article (artPrint) X Send the article to the printer (see the `60printCommand' com V- X mand line option). X X X CUSTOMIZING XRN X X Colors, fonts, and other _`08m_`08x_`08r_`08n options can be speci Vfied on the X command line or using X resources. With the exception of the X display name, all _`08m_`08x_`08r_`08n options can be specified us Ving X X resources. Options specified on the command line take precedence X over those specified using X resources. In addition, _`08m_`08x_`0 V8r_`08n has a X set of customization screens that can be used to tailor the X environment without editing resource files. For each customiza- X tion entry below, the corresponding resource entry and customiza- X tion menu entry are described. X X X COMMAND LINE ARGUMENTS X X Here are the current command line arguments (the X resources have X the same names and values as the command line arguments), under X VMS all command line arguments are in lowercase: X X +/-authorFullName X Display the full name of the author or the X user/hostname of the author. X X -breakLength len X Break lines longer than `60len' characters into multiple X lines. Default is 80 characters. If set to 0, line X breaking is disabled. Customize/General `60Wrap Length' X sets this. X X +/-cc put 'Cc: user' in replies. X X +/-confirm list X Turn on confirmation boxes for the buttons listed. X These boxes pop up to ask the user to verify the invo- X cation of "dangerous" actions (such as catch up and X unsubscribe). The list of buttons is a comma separated X list of button names. The buttons that can be con- X firmed: ngQuit, ngExit, ngCatchUp, artCatchUp, ngUnsub, X and artUnsub. Customize/General has a box containing X X X 12 X UCB X X X X X X X 28 November 1988 XRN(1) X X X buttons for each confirm option. X X -display display X specification of the X display. (Not for VMS). X X -deadLetters file X the name of the file to save failed postings and mes- X sages. Defaults to `60`7E/dead.letters'. X (SYS$SCRATCH:DEAD.LETTER on VMS). Customize/General X `60Dead Letters' sets this. X X +/-dumpCore X Dump core when a signal is detected. The X resources X class for the "dumpCore" X resource is "Debug". X X -editorCommand command X use an alternate editor for creating postings, follow- X ups, forwards, gripes, and replies. The argument, X `60command', must be a sprintf format string that con- X tains a `60%s' where the file name should be placed. X Examples are: X X xterm -e vi %s X xterm -e microEmacs %s X emacsclient %s X X The resulting command should handle all editing and win- X dowing. The article being followed up or replied to is X automatically included. Customize/General `60Editor Com- X mand' can be used to set this. X X -geometry =WxH+X+Y (Not for VMS). X specification of the _`08m_`08x_`08r_`08n window size an Vd location. X The window manager may choose to ignore this specifica- X tion. Using the Customize/Save menu item saves the X current geometry automatically. X X -hostName name X Sets the name of your internet host. Used for postings X to specify a useful path name when the default isn't X useful. Customize/General `60Host Name' sets this. X X -iconGeometry +X+Y X specification of the initial _`08m_`08x_`08r_`08n icon l Vocation. The X window manager may choose to ignore this specification. X X -iconic start up _`08m_`08x_`08r_`08n with the window iconified. X X +/-includeHeader X Include or do not include the original header in X included articles. The default is to not include the X header. Customize/General `60Include Header' X enables/disables headers. X X X X X UCB 13 X X X X X X X XRN(1) 28 November 1988 X X X -includePrefix prefix text X Change the standard prefix for each line of included X text from the default, "`7C> ", to the given text string V. X Customize/General `60Include Prefix' sets this. X X +/-includeSep X Include or do not include the prefix text ("`7C> ") in X front of included articles. The default is to include X the prefix text ("`7C> "). Customize/General `60Include X Separator' sets/clears this. X X +/-info Display all informative messages in the message pane. X Defaults to display all information in the message X pane. Customize/General `60Info Messages' sets and X clears this. X X +/-killFiles X turn the use of kill files on/off. The default is on. X Customize/General has a button to enable/disable kill X files. X X -leaveHeaders list X the header fields to leave in the article; a comma X separated case-insensitive list of field names (_`08i._` V08e., X subject,from,organization). This option takes pre- X cedence over `60stripHeaders'. X X -lineLength len X Length of lines that are broken. Default is 72 charac- X ters. If set to 0, line breaking is disabled. X Customize/General `60Line Length' sets this. X X -mailer mailer X the command to use for mailing replies. This command X must take all of it's input from stardard input (_`08m_` V08x_`08r_`08n X will not build a command line). The default is X `60/usr/lib/sendmail -oi -t'. (Not for VMS). X Customize/General `60mailer' sets this. X X -maxLines number X the maximum number of lines above the cursor in the X subject line display. If negative, the subject line X scrolls only at the bottom and only one line at a time. X Customize/General `60Max Lines' sets this. X X -minLines number X the minimum number of lines above the cursor in the X subject line display. If negative, the subject line X display scrolls only at the bottom and only one line at X a time. Customize/General `60Min Lines' sets this. X X -newsrcFile file X the newsrc file to use. Defaults to `60`7E/.newsrc'. X (SYS$LOGIN:NEWS.RC on VMS). If a file with a name of X X X 14 X UCB X X X X X X X 28 November 1988 XRN(1) X X X the form `60-' is found, it will X be used. For example, .newsrc-fumble for news server X node `60fumble'. Customize/General `60Newsrc file' sets X this. X X -nntpServer hostname X the NNTP server to use. Customize/General entry 'NNTP X Server' sets this. X X -organization organization X Set the organization name in postings and followups. X Customize/General `60Organization' sets this. X X +/-pageArticles X Space bar will either scroll the current article or go X to the next article. Customize/General `60Page Articles' X sets this. X X -personalName name X Sets your 'real' name for use in postings. X Customize/General `60Personal Name' sets this. X X -printCommand command X Set the command used for printing articles. The arti- X cle is sent to the command via standard input. X Defaults to `60enscript'. (PRINT/DELETE on VMS). X Customize/General `60Print Command' sets this. X X -replyPath path X The path to use for mailing replies. This should be a X sprintf-able string. Only available on VMS. This for- X mat string is used to build a mail address acceptable X to VMS mail for replies. For example, `60IN%"%"'. X Customize/General `60Reply Path' sets this. X X -replyTo name X Set the Reply-To field in postings and followups. X Customize/General `60Reply To' sets this. X X -rescanTime time X Amount of idle time (in seconds) before checking for X new articles. Customize/General `60Rescan Time' sets X this. X X -saveDir dir X the article saving directory. Defaults to `60`7E/News' X when -saveMode specifies `60onedir', or X `60`7E/News/newsgroup' when -saveMode specifies `60subdi Vrs'. X For VMS, defaults to SYS$SCRATCH:. Customize/General X `60Save directory' sets this. X X -saveNewsrcFile file X the saved `60.newsrc' filename. Before the `60.newsrc' X file is modified on startup, it is saved in a backup X X X X UCB 15 X X X X X X X XRN(1) 28 November 1988 X X X file. Defaults to `60`7E/.oldnewsrc'. X (SYS$LOGIN:OLDNEWS.RC on VMS). Customize/General X `60Saved Newsrc file' sets this. X X -saveMode mode X the mode for saving articles; a comma separated list of X options. The options can be `60mailbox' or `60normal', X `60headers' or `60noheaders', and `60onedir' or `60subd Virs'. X The default is `60normal,headers,onedir'. The X Customize/General screen has a `60Save Mode' box with X toggles for this option. X X -signatureFile file X the signature file to use. Defaults to `60`7E/.signatur Ve'. X (SYS$LOGIN:NEWS.SIGNATURE on VMS). Customize/General X `60Signature file' sets this. X X +/-sortedSubjects X Display the subject lines in the subject window sorted X by subject. Customize/General `60Sorted Subjects' sets X this. X X +/-subjectRead X When using the space bar to scroll, when an article is X finished, the space-bar scrolling invokes subject next X instead of next unread. Customize/General `60Subject X Read' sets and clears this. X X -stripHeaders list X the header fields to strip from the article; a comma X separated case-insensitive list of field names (_`08i._` V08e., X keywords,message-id). X X -savePostings file X the name of the file to save postings and messages (via X the `60save' button in the composition window). Default Vs X to `60`7E/Articles'. (SYS$SCRATCH:SAVED.POSTING on VMS.) X Customize/General `60Save Postings' sets this. X X -tmpDir directory X the directory to use for the temporary storage of arti- X cles fetched from the server. If this option and the X corresponding Xdefault do not exist, _`08m_`08x_`08r_`08 Vn will look for X the environment variable TMPDIR. The default is X `60/tmp'. (SYS$SCRATCH: on VMS.) Customize/General `60Te Vmp X directory' sets this. X X -topLines number X the number of lines to be used for the top text window X (where the unread groups and article subjects are X listed). Customize/General `60Top Lines' sets this. X X +/-updateNewsrc X Update the newsrc file when leaving Article mode. X X X 16 X UCB X X X X X X X 28 November 1988 XRN(1) X X X Customize/General `60Update Newsrc' sets/clears this. X X -ngButtonList list X X -artButtonList list X X -artSpecButtonList list X X -addButtonList list X X -allButtonList list X use the given list of buttons for the particular mode X in the order given rather than all of the buttons for X the mode in the default order. The list is a comma X separated list of button names. The names of the but- X tons appear next after the button label in the button X descriptions above. For example, a list of buttons for X Newsgroup mode might be: X ngQuit,ngRead,ngCatchUp,ngRescan,ngSubscribe,ngPost X Customization menus exist for buttons and menus for X each mode. X X -ngBindings bindings X X -allBindings bindings X X -addBindings bindings X X -artBindings bindings X use the given bindings for the key/mouse bindings for X the particular mode. The default key bindings are as X close to the `60rn (1)' key bindings as are possible wit Vh X _`08m_`08x_`08r_`08n. See the X toolkit documentation o Vn `60Translation X Tables' for information on the format of `60bindings'. X The actions defined in _`08m_`08x_`08r_`08n are the same V as the button X names. For example, a set of bindings for Newsgroup X mode might be: X xrn.ngBindings: \ X Q: ngQuit() \n\ X N: ngRead() \n\ X P: ngPrev() X X X RESOURCES X X _`08m_`08x_`08r_`08n takes a number of specifications for colors, V fonts, border X widths, and other program options. The format for an _`08m_`08x_` V08r_`08n X X resource is: X X dxrn.x.y....z.a: value X or.. X mxrn.x.y....z.a: value X X Where _`08x._`08y...._`08z specifies the path from the top level o Vf _`08m_`08x_`08r_`08n to a X particular item (think of _`08m_`08x_`08r_`08n as a hierarchical c Vollection of X X X X UCB 17 X X X X X X X XRN(1) 28 November 1988 X X X windows, panes, and buttons, and _`08x._`08y...._`08z is a path fr Vom the top X of the hierarchy to a node in the hierarchy), _`08a is the type of X default (_`08i._`08e., font, border, foreground, background, bor- X derWidth), and _`08v_`08a_`08l_`08u_`08e is the value of the defau Vlt (_`08i._`08e,. a color X name or hex representation, a font name, a numeric value). X Specifying a default for a item at some point in the hierarchy X will set that default for all items from that point down in the X hierarchy. A higher level default can be overridden by specify- X ing a default at a lower level directly. X X XRN widget hierarchy: X vpane (Paned) X titlebar (Label) (optional) X index (Text) (enclosed in topFrame for mxrn). X indexinfo (Label) X indexbuttons (Box) X buttonName (Pushbutton) X articleText (Text) (enclosed in botFrame for mxrn). X textinfo (Label) X textbuttons (Box) X buttonName (Command) X X composeTop (Shell) X pane (Paned) X headerText (Text) (enclosed in headerFrame for mxrn) X composeText (Text) (enclosed in textFrame for mxrn) X box (Box) X abort (Pushbutton) X send (Pushbutton) X save (Pushbutton) X includeArticle (Pushbutton) X includeFile (Pushbutton) X X dialogs... X X Examples of defaults are: X #bindings for article mode X mxrn.artBindings: \ X 0x20: doTheRightThing() \n\ X AltN: artNext() \n\ X N: artSubNext() \n\ X AltP: artPrev() \n\ X P: artSubPrev() \n\ X AltF: artFollowup() \n\ X AltR: artReply() \n\ X AltW: artSave() \n\ X AltC: artCancel() \n\ X AltV: artHeader() \n\ X CtrlX: artRot13() \n\ X Altu: artUnsub() \n\ X CtrlZ: artQuit()\n X \n X # X #layout/scrolling control for toplevel widget X X X 18 X UCB X X X X X X X 28 November 1988 XRN(1) X X X # X mxrn.topLines: 10 X mxrn.minLines: 3 X mxrn.maxLines: 8 X # X # which button pops up the popup menus X # X mxrn.popupButton: 2 X mxrn.saveMode: onedir X mxrn.includePrefix: > X # X # list of popup menus. best set using customize X # X mxrn.ngPopupList: ngQuit,ngRead,ngSubscribe,ngUnsub,ngCatchUp X mxrn.artPopupList: artQuit,artNext,artPrev,artNextUnread X # X # your name. please don't use mine! X # X mxrn.personalName: Rick Murphy X mxrn.includeHeader: off X mxrn.includeSep: on X # X # don't update newsrc each newsgroup X # X mxrn.updateNewsrc: off X # X # inhibit info messages, use kill files. X # X mxrn.info: off X mxrn.killFiles: on X # X # list of buttons in various modes X # X mxrn.artButtonList: artQuit,artFedUp,artPost X mxrn.ngButtonList: ngQuit,ngRead,ngSubscribe,ngUnsub,ngCatchUp X # X # leading text for 'reply' functions X # X mxrn.replyPath: decuac::"%s" X mxrn.lineLength: 72 X mxrn.breakLength: 80 X mxrn.pageArticles: off X mxrn.rescanTime: 1800 X mxrn.subjectRead: on X mxrn.replyTo: murphy@ufp.dco.dec.com X mxrn.organization: Digital Equipment Corporation, Landover MD X mxrn.geometry: 617x750+248+214 X mxrn.confirm: ngCatchUp,artCatchUp X mxrn.sortedSubjects: on X # X # examples of how to color pushbuttons. X # for `60dxrn' ignore the shadowColor entries. X # X mxrn*background: SkyBlue X X X X UCB 19 X X X X X X X XRN(1) 28 November 1988 X X X mxrn*foreground: white X mxrn*artPrint.background: #e0e000 X mxrn*artPrint.foreground: black X mxrn*artPrint.bottomShadowColor: #005400 X mxrn*artPrint.topShadowColor: yellow X mxrn*artQuit.background: red X mxrn*artQuit.foreground: White X mxrn*artQuit.bottomShadowColor: #770000 X mxrn*artQuit.topShadowColor: #ffb3cc X mxrn*ngRead.background: #00d800 X mxrn*ngRead.foreground: black X mxrn*ngRead.bottomShadowColor: #005400 X mxrn*ngRead.topShadowColor: green X mxrn*ngRescan.background: #e0e000 X mxrn*ngRescan.foreground: black X mxrn*ngRescan.bottomShadowColor: #005400 X mxrn*ngRescan.topShadowColor: yellow X mxrn*XmPushButton.background: #00d800 X mxrn*XmPushButton.foreground: black X mxrn*XmPushButton.font: *-*-Menu-Medium-R-Normal-*-*-100-*-*-* V-*-*-ISOLATIN1 X # X # resources for the newsgroup/subject list X # X mxrn*index.background: black X mxrn*index.foreground: white X # X # a fixed font is strongly recommended X # X mxrn*index.font: *-*-*-Medium-R-Normal-*-*-120-*-*-M-* X mxrn*index.fontList: *-*-*-Medium-R-Normal-*-*-120-*-*-M-* X mxrn*XmText.background: black X mxrn*XmText.foreground: white X mxrn*XmText.font: *-*-*-Medium-R-Normal-*-*-120-*-*-M-* X mxrn*XmText.fontList: *-*-*-Medium-R-Normal-*-*-120-*-*-M-* X composeTop*headerText*fontList: *-*-*-Medium-R-Normal-*-*-12 V0-*-*-M-* X composeTop*composeText*fontList:*-*-*-Medium-R-Normal-*-*-120-* V-*-M-* X mxrn*pointerForeground: red X mxrn*leaveHeaders: subject, newsgroups, from, reply-to X mxrn*sortedSubjects: on X # X # the following is recommended for VMS users. Otherwise, X # the `60delete' key deletes the wrong way! X # X *XmText.translations: \ X #override \n\ X ShiftDelete: delete-previous-character()\n\ X Delete: delete-previous-character()\n\ X ShiftLinefeed: delete-next-word()\n\ X Linefeed: delete-previous-word()\n\ X ShiftBackSpace: end-of-line()\n\ X BackSpace: beginning-of-line()\n\ X Ctrle: end-of-line()\n\ X Ctrlj: delete-previous-word()\n\ X Ctrlh: beginning-of-line()\n\ X X X 20 X UCB X X X X X X X 28 November 1988 XRN(1) X X X Ctrlr: redraw-display()\n\ X Ctrlu: delete-to-start-of-line()\n X \n X X X FILES X X `7E/.newsrc description of the groups and the articles read i Vn X each group (SYS$LOGIN:NEWS.RC for VMS) X `7E/.oldnewsrc backup of `7E/.newsrc (created at startup) X (SYS$LOGIN:OLDNEWS.RC on VMS) X `7E/.signature signature for use when sending messages X (SYS$LOGIN:NEWS.SIGNATURE on VMS) X `7E/News directory where articles are saved X (SYS$SCRATCH: on VMS) X `7E/Articles where `60saved' postings and messages are X stored X (SYS$SCRATCH:SAVED.POSTING on VMS) X `7E/dead.letter where failed postings and messages are store Vd X (SYS$SCRATCH:DEAD.LETTERS on VMS) X `7E/.xrnlock lock file (SYS$LOGIN:XRN.LOCK on VMS) X /usr/local/lib/rn/server location of the news server hostname X (optional) (SYS$LOGIN:NNTP.SERVER on VMS) X /usr/local/lib/news/hiddenhost location of the hiddenhost X name X (optional) (SYS$LOGIN:HIDDEN.HOST on VMS) X /usr/local/lib/news/pathhost location of the path host name X (optional) (SYS$LOGIN:PATH.HOST on VMS) X /usr/local/lib/news/domain location of the domain name X (optional) (SYS$LOGIN:DOMAIN.NAME on VMS) X /etc/uucpname location of the UUCP name for your host X (optional) X /usr/lib/sendmail default mailer X CHANGES list of changes from the previous version X TODO list of bugs and things to do X X X ENVIRONMENT VARIABLES X X Note: environment variables are implemented as logical names on X VMS. X NNTPSERVER hostname of the news server X TMPDIR temporary directory X DOMAIN name of your internet domain (".Berkeley.EDU", X ".orst.edu") X HIDDENHOST full domain-style name of the host that you want X your return path to be from ("decvax.dec.com", "Berkeley.EDU") X HIDDENPATH name of the host that you want put in the Path X field of messages. X USER login name of the user. X HOME home directory of the user. X FULLNAME full name of the user, used for the From field of mes- X sages. X X X X X UCB 21 X X X X X X X XRN(1) 28 November 1988 X X X SEE ALSO X readnews(1), rn(1), vnews(1), X(1), nntpd(8) X X X COMMENTS X X The name (_`08m_`08x_`08r_`08n) is a bit of a misnomer. _`08m_`08 Vx_`08r_`08n is not an X inter- X face to `60rn' (the terminal-based news reading program by Larry X Wall), but is an X-based news reader that has had part of the X functionality of `60rn' added since a number of our users are X (were?) `60rn' users (all of the code is new). Much of the `60rn' X funcionality that _`08m_`08x_`08r_`08n currently has was not in th Ve original plan X (KILL files, for example). X X The user interface look and feel is modeled after that of `60XMH' X (by Terry Weissman). X X The `60.newsrc' file is updated on executing the `60quit' command V in X Newsgroup mode, during every `60rescan', and by `60checkpoint'. I Vf X the `60updateNewsrc' option is set, the `60.newsrc' file will be X updated everytime Article mode is exited. X X _`08m_`08x_`08r_`08n catches signals and X errors and will clean u Vp on error exit X (remove temporary files, update the `60.newsrc' file). The cleanu Vp X will be done and then a death notifier box will be posted (if the X signal is SIGHUP or SIGINT, the death notifier will be skipped X and the program will exit). The "click to exit" button must be X pressed in the death notifier box for the program to exit. X X XREFS are handled by _`08m_`08x_`08r_`08n, however only articles t Vhat are actu- X ally read (not marked as read by 'catchup' or 'mark as read') X have their XREFS chased and only groups that are currently sub- X scribed to have XREFed articles marked as read. X X The default specifications for color and fonts can be confusing X (thousands of different X resources can be specified for _`08m_`08 Vx_`08r_`08n, no X two users' _`08m_`08x_`08r_`08n displays need to be the same). X X _`08m_`08x_`08r_`08n uses the XHDR command of the Berkeley NNTP ne Vws server (XHDR X is not part of the protocol defined by RFC 977). _`08m_`08x_`08r_ V`08n will X detect the presence of this command and complain if it does not X exist. X X Since the NNTP protocol does not define a unique response code X for server timeout, timeout recovery may not work if the format X of the timeout error message changes. X X _`08m_`08x_`08r_`08n assumes a `60smart' or `60lucky' mailer. X X _`08m_`08x_`08r_`08n notices that the `60.newsrc' file has been up Vdated by another X program while _`08m_`08x_`08r_`08n is running and informs the user V (and gives the X user the option to quit without updating the `60.newsrc' or to con V- X tinue on). X X X X 22 X UCB X X X X X X X 28 November 1988 XRN(1) X X X Article temporary files can be removed and _`08m_`08x_`08r_`08n wi Vll recover. X X _`08m_`08x_`08r_`08n strips `60`5EH' from articles. X X The v`7Bf,s`7Dprintf implementation included with _`08m_`08x_`08r_ V`08n is from Robert X A. Larson . X X The strtok implementation included with _`08m_`08x_`08r_`08n is fr Vom Henry X Spencer . X X X BUGS X X See TODO for a full list of bugs and things that need to be done. X X Incomplete KILL file support. X X See config.h for a list of defines you may want to use based on X problems that may exist in your version of the X11 toolkit and X widgets. X X Report bugs and requests for features to `60murphy@ufp.dco.dec.com V' X (...decwrl!ufp.enet!murphy) X X X ORIGINAL AUTHORS X Ellen M Sentovich (UC Berkeley, ellen@ic.berkeley.edu, X ...!ucbvax!ic!ellen) X Rick L Spickelmier (UC Berkeley, ricks@berkeley.edu, X ...!ucbvax!ricks) X See the FIXERS/CHANGES files for a listing of those who have X really been doing most of the work over the last year or so! X Rick Murphy (DEC, Landover MD) VMS, XUI, and Motif port. note: X Ellen Sentovich and Rick Spickelmier are responsible for writing X the code. Rick Murphy is responsible for writing the bugs. Don't X bother the Berkeley folks with reports of dxrn or mxrn bugs. X X X X X X X X X X X X X X X X X X X X X X UCB 23 X X X`1B9`1B9 $ CALL UNPACK XRN.DOC;1 158803388 $ create 'f' X#ifndef XRN_H X#define XRN_H X X/* X * $Header: /net/opus/mnt/ricks/src/X/xrn/RCS/xrn.h,v 1.16 90/09/29 01:11:20 V ricks Exp Locker: ricks $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X#ifndef MOTIF X#define XRN_VERSION "6.14-3 (for XUI)" X#else X#define XRN_VERSION "6.14-3 (for Motif)" X#endif X X#ifndef VMS X#include X#else X#include X#endif X X/* X * xrn.h: set up the main screens X * X */ X X/* global variables that represent the widgets that are dynamically changed V */ X Xextern Widget TopLevel; Xextern Widget Frame; Xextern Widget MenuBar;`09`09/* Top menu bar */ Xextern Widget TopButtonBox;`09/* button box containing the command buttons * V/ Xextern Widget BottomButtonBox;`09/* button box containing the article specif Vic buttons */ Xextern Widget TopInfoLine; /* top button info line V */ Xextern Widget BottomInfoLine; /* bottom button info line V */ Xextern Widget TopList;`09`09/* scrollable list window */ Xextern Widget ArticleText; Xextern Widget PopupMenu;`09/* the Popup */ Xextern Widget ComposeTopLevel;`09/* composition frame */ Xextern Widget ComposeText;`09/* composition article */ Xextern Widget HeaderText;`09/* composition header */ Xextern int XRNState; X Xextern int inCommand;`09`09/* executing a button function`09`09 */ X X#define XRN_X_UP 0x01 X#define XRN_NEWS_UP 0x10 X X#define LABEL_SIZE 128 X X#endif /* XRN_H */ $ CALL UNPACK XRN.H;1 639588176 $ create 'f' X#define xrn_width 50 X#define xrn_height 50 X#define xrn_x_hot -1 X#define xrn_y_hot -1 Xstatic char xrn_bits`5B`5D = `7B X 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x40, 0xc8, X 0x23, 0x04, 0x00, 0x02, 0x01, 0x80, 0x44, 0x64, 0x04, 0x00, 0x02, 0x01, X 0x80, 0x44, 0x64, 0x04, 0x00, 0x02, 0x01, 0x00, 0x43, 0xa2, 0x04, 0x00, X 0x02, 0x01, 0x00, 0xc3, 0x21, 0x05, 0x00, 0x02, 0x01, 0x80, 0x44, 0x23, X 0x06, 0x00, 0x02, 0x01, 0x80, 0x44, 0x22, 0x06, 0x00, 0x02, 0x01, 0x40, X 0x48, 0x24, 0x04, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, X 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x02, 0x81, 0x00, 0x00, X 0x00, 0x00, 0x0c, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0xe1, X 0xff, 0xff, 0xff, 0xff, 0x09, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x09, X 0x02, 0x21, 0xae, 0x66, 0xae, 0x14, 0x09, 0x02, 0x21, 0xe4, 0xa2, 0xaa, X 0x08, 0x09, 0x02, 0x21, 0xa4, 0x66, 0xaa, 0x09, 0x09, 0x02, 0x21, 0x00, X 0x00, 0x00, 0x00, 0x09, 0x02, 0x21, 0x40, 0x2d, 0x0d, 0x00, 0x09, 0x02, X 0x21, 0xc0, 0xc5, 0x08, 0x00, 0x09, 0x02, 0x21, 0x40, 0xcd, 0x0c, 0x00, X 0x09, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x21, 0xff, 0xff, X 0xff, 0x3f, 0x09, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x21, X 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x21, 0x28, 0xf8, 0xff, 0x2c, 0x09, X 0x02, 0x21, 0xd6, 0x09, 0x80, 0x30, 0x09, 0x02, 0x21, 0x00, 0xa8, 0x80, X 0x00, 0x09, 0x02, 0x21, 0x18, 0x48, 0x92, 0x3c, 0x09, 0x02, 0x21, 0xe6, X 0x89, 0x80, 0x00, 0x09, 0x02, 0x21, 0x00, 0x88, 0x90, 0x3c, 0x09, 0x02, X 0x21, 0xe6, 0x48, 0xaf, 0x10, 0x09, 0x02, 0x21, 0x38, 0x09, 0x80, 0x00, X 0x09, 0x02, 0x21, 0x00, 0xf8, 0xff, 0x3c, 0x09, 0x02, 0x21, 0xee, 0x01, X 0x00, 0x00, 0x09, 0x02, 0x21, 0x30, 0xb8, 0xf5, 0x00, 0x05, 0x02, 0x21, X 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0xe1, 0xff, 0xff, 0xff, 0xff, 0x01, X 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, X 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, X 0xff, 0x03`7D; $ CALL UNPACK XRN.ICON;1 1227496522 $ create 'f' X X#if !defined(lint) && !defined(SABER) Xstatic char XRNrcsid`5B`5D = "$Header: /users/ricks/xrn/src/RCS/xthelper.c,v V 1.11 90/09/29 01:13:51 ricks Exp $"; X#endif X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * xthelper.c: routines for simplifying the use of the X toolkit X * X */ X X#include "copyright.h" X#ifndef VMS X#include X#else X#include X#endif X#include "config.h" X#include "utils.h" X#ifndef VMS X#include X#include X#else X#include X#include X#endif X#ifdef MOTIF X#include X#endif X#include "xmisc.h" X#include "xrn.h" X#include "xthelper.h" X X Xvoid XxthCenterWidget(widget, x, y) XWidget widget; Xint x, y; X`7B X#ifdef MOTIF X Arg sargs`5B3`5D; X#else X Arg sargs`5B2`5D; X#endif X Arg gargs`5B2`5D; X X XtSetArg(gargs`5B0`5D, XtNwidth, 0); X XtSetArg(gargs`5B1`5D, XtNheight, 0); X XtGetValues(widget, gargs, XtNumber(gargs)); X X x -= ((int) gargs`5B0`5D.value) / 2; X y -= ((int) gargs`5B1`5D.value) / 2; X if (x + (int) gargs`5B0`5D.value > WidthOfScreen(XtScreen(widget))) `7B X`09x = WidthOfScreen(XtScreen(widget)) - (int) gargs`5B0`5D.value; X `7D X if (y + (int) gargs`5B1`5D.value > HeightOfScreen(XtScreen(widget))) `7B X`09y = HeightOfScreen(XtScreen(widget)) - (int) gargs`5B1`5D.value; X `7D X if (x < 0) `7B X`09x = 0; X `7D X if (y < 0) `7B X`09y = 0; X `7D X XtSetArg(sargs`5B0`5D, XtNx, x); X XtSetArg(sargs`5B1`5D, XtNy, y); X#ifdef MOTIF X XtSetArg(sargs`5B2`5D, XmNdefaultPosition, False); X#endif X XtSetValues(widget, sargs, XtNumber(sargs)); X return; X`7D X Xvoid XxthCenterWidgetOverCursor(widget) XWidget widget; X/* X * center a window over the cursor X * X * returns: void X * X */ X`7B X Window root, child; X int x, y, dummy; X unsigned int mask; X X (void) XQueryPointer(XtDisplay(TopLevel), XtWindow(TopLevel), X`09`09`09 &root, &child, X`09`09`09 &x, &y, &dummy, &dummy, X`09`09`09 &mask); X X xthCenterWidget(widget, x, y); X return; X`7D X X Xvoid XxthHandleAllPendingEvents() X`7B X `20 X XtInputMask mask; X XEvent`09event; X X if ((XRNState & XRN_X_UP) == XRN_X_UP) `7B X`09while ((mask = XtPending()) != 0) `7B X`09 if (mask == XtIMTimer) `7B X`09`09XtProcessEvent(XtIMAll); X`09 `7D else `7B X`09`09XtNextEvent(&event); X`09`09XtDispatchEvent(&event); X`09 `7D X`09`7D X `7D X return; X`7D X Xvoid XxthHandlePendingExposeEvents() X`7B X XtInputMask mask; X XEvent `09ev; X `20 X if ((XRNState & XRN_X_UP) == XRN_X_UP) `7B X`09XSync(XtDisplay(TopLevel), False); X`09while ((mask = XtPending()) != 0) `7B X`09 if (mask == XtIMTimer) `7B X`09`09XtProcessEvent(XtIMAll); X`09 `7D else `7B X`09`09XtNextEvent(&ev); X`09`09if (ev.type == KeyPress `7C`7C ev.type == ButtonPress) `7B X`09`09 XBell(XtDisplay(TopLevel), 0); X`09`09`7D else `7B X`09`09 XtDispatchEvent(&ev); X`09`09`7D X`09 `7D X`09`7D X `7D X return; X`7D $ CALL UNPACK XTHELPER.C;1 2068269634 $ create 'f' X#ifndef XTHELPER_H X#define XTHELPER_H X X/* X * $Header: /users/ricks/xrn/src/RCS/xthelper.h,v 1.6 90/09/29 02:29:40 rick Vs Exp $ X */ X X/* X * xrn - an X-based NNTP news reader X * X * Copyright (c) 1988, 1989, 1990, Ellen M. Sentovich and Rick L. Spickelmie Vr. X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, provided X * that the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of the University of California not X * be used in advertising or publicity pertaining to distribution of`20 X * the software without specific, written prior permission. The University X * of California makes no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE UNIVERSITY OF CALIFORNIA DISCLAIMS ALL WARRANTIES WITH REGARD TO`20 X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND`20 X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN`20 X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X */ X X/* X * xthelper.h: routines for simplifying the use of the X toolkit X * X */ X Xvoid xthCenterWidgetOverCursor(/* Widget widget */); Xvoid xthCenterWidget(/* Widget widget, int x, y */); Xvoid xthHandleAllPendingEvents(); Xvoid xthHandlePendingExposeEvents(); X X#endif /* XTHELPER_H */ $ CALL UNPACK XTHELPER.H;1 604920370 $ v=f$verify(v) $ EXIT