Subject: tput enhancement patch...
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Christos Zoulas <Christos-Zoulas@deshaw.com>
List: current-users
Date: 01/22/1994 19:43:49
Chris said he would like a patch to parse arguments correctly for termcap, so
a stole the tcsh code that does it (it is legal since I wrote it).

I hope that it does not end up in the trash like my tsort and mail patches.

christos

*** tput.c.dist	Fri Dec 17 02:19:51 1993
--- tput.c	Sat Jan 22 19:38:49 1994
***************
*** 45,60 ****
  #include <sys/termios.h>
  #include <stdio.h>
  #include <unistd.h>
  
  main(argc, argv)
  	int argc;
  	char **argv;
  {
  	extern char *optarg;
  	extern int optind;
! 	int ch, exitval, n, outc();
  	char *cptr, *p, *term, buf[1024], tbuf[1024];
- 	char *getenv(), *tgetstr(), *realname();
  
  	term = NULL;
  	while ((ch = getopt(argc, argv, "T:")) != EOF)
--- 45,68 ----
  #include <sys/termios.h>
  #include <stdio.h>
  #include <unistd.h>
+ #include <stdlib.h>
+ #include <curses.h>
  
+ static void   prlongname __P((char *));
+ static void   setospeed __P((void));
+ static void   outc	 __P((int));
+ static void   usage __P((void));
+ static char **process __P((char *, char *, char **));
+ 
+ int
  main(argc, argv)
  	int argc;
  	char **argv;
  {
  	extern char *optarg;
  	extern int optind;
! 	int ch, exitval, n;
  	char *cptr, *p, *term, buf[1024], tbuf[1024];
  
  	term = NULL;
  	while ((ch = getopt(argc, argv, "T:")) != EOF)
***************
*** 78,84 ****
  		exit(2);
  	}
  	setospeed();
! 	for (cptr = buf, exitval = 0; p = *argv; ++argv) {
  		switch(*p) {
  		case 'c':
  			if (!strcmp(p, "clear"))
--- 86,92 ----
  		exit(2);
  	}
  	setospeed();
! 	for (exitval = 0; argv && (p = *argv) != NULL; ++argv) {
  		switch(*p) {
  		case 'c':
  			if (!strcmp(p, "clear"))
***************
*** 97,112 ****
  				p = "rs";
  			break;
  		}
  		if (tgetstr(p, &cptr))
! 			(void)tputs(buf, 1, outc);
  		else if ((n = tgetnum(p)) != -1)
  			(void)printf("%d\n", n);
  		else
  			exitval = !tgetflag(p);
  	}
! 	exit(exitval);
  }
  
  prlongname(buf)
  	char *buf;
  {
--- 105,122 ----
  				p = "rs";
  			break;
  		}
+ 		cptr = buf;
  		if (tgetstr(p, &cptr))
! 			argv = process(p, buf, argv);
  		else if ((n = tgetnum(p)) != -1)
  			(void)printf("%d\n", n);
  		else
  			exitval = !tgetflag(p);
  	}
! 	exit(argv ? exitval : 2);
  }
  
+ static void
  prlongname(buf)
  	char *buf;
  {
***************
*** 114,131 ****
  	int savech;
  	char *savep;
  
! 	for (p = buf; *p && *p != ':'; ++p);
  	savech = *(savep = p);
! 	for (*p = '\0'; p >= buf && *p != '|'; --p);
  	(void)printf("%s\n", p + 1);
  	*savep = savech;
  }
  
  setospeed()
  {
! 	extern int errno, ospeed;
  	struct termios t;
- 	char *strerror();
  
  	if (tcgetattr(STDOUT_FILENO, &t) != -1)
  		ospeed = 0;
--- 124,144 ----
  	int savech;
  	char *savep;
  
! 	for (p = buf; *p && *p != ':'; ++p)
! 		continue;
  	savech = *(savep = p);
! 	for (*p = '\0'; p >= buf && *p != '|'; --p)
! 		continue;
  	(void)printf("%s\n", p + 1);
  	*savep = savech;
  }
  
+ static void
  setospeed()
  {
! #undef ospeed
! 	extern short ospeed;
  	struct termios t;
  
  	if (tcgetattr(STDOUT_FILENO, &t) != -1)
  		ospeed = 0;
***************
*** 133,146 ****
--- 146,252 ----
  		ospeed = cfgetospeed(&t);
  }
  
+ static void
  outc(c)
  	int c;
  {
  	putchar(c);
  }
  
+ static void
  usage()
  {
  	(void)fprintf(stderr, "usage: tput [-T term] attribute ...\n");
  	exit(1);
+ }
+ 
+ static char **
+ process(cap, str, argv)
+ 	char *cap;
+ 	char *str;
+ 	char **argv;
+ {
+ 	static char errfew[] =
+ 		 "tput: Not enough arguments (%d) for capability `%s'\n";
+ 	static char errmany[] =
+ 		 "tput: Too many arguments (%d) for capability `%s'\n";
+ 	static char erresc[] =
+ 		 "tput: Unknown %% escape `%c' for capability `%s'\n";
+ 	/*
+ 	 * Count home many values we need for this capability.
+ 	 */
+ 	char *cp;
+ 	int arg_need, arg_rows, arg_cols;
+ 	for (cp = str, arg_need = 0; *cp; cp++)
+ 		if (*cp == '%')
+ 			    switch (*++cp) {
+ 			    case 'd':
+ 			    case '2':
+ 			    case '3':
+ 			    case '.':
+ 			    case '+':
+ 				    arg_need++;
+ 				    break;
+ 
+ 			    case '%':
+ 			    case '>':
+ 			    case 'i':
+ 			    case 'r':
+ 			    case 'n':
+ 			    case 'B':
+ 			    case 'D':
+ 				    break;
+ 
+ 			    default:
+ 				/*
+ 				 * hpux has lot's of them, but we complain
+ 				 */
+ 			        (void)fprintf(stderr, erresc, *cp, cap);
+ 				return NULL;
+ 			    }
+ 
+ 	/*
+ 	 * And print them
+ 	 */
+ 	switch (arg_need) {
+ 	case 0:
+ 		(void) tputs(str, 1, outc);
+ 		break;
+ 
+ 	case 1:
+ 		arg_cols = 0;
+ 
+ 		argv++;
+ 		if (!*argv || *argv[0] == '\0') {
+ 			(void)fprintf(stderr, errfew, 1, cap);
+ 			return NULL;
+ 		}
+ 		arg_rows = atoi(*argv);
+ 
+ 		(void)tputs(tgoto(str, arg_cols, arg_rows), 1, outc);
+ 		break;
+ 
+ 	case 2:
+ 		argv++;
+ 		if (!*argv || *argv[0] == '\0') {
+ 			(void)fprintf(stderr, errfew, 2, cap);
+ 			return NULL;
+ 		}
+ 		arg_cols = atoi(*argv);
+ 
+ 		argv++;
+ 		if (!*argv || *argv[0] == '\0') {
+ 			(void)fprintf(stderr, errfew, 2, cap);
+ 			return NULL;
+ 		}
+ 		arg_rows = atoi(*argv);
+ 
+ 		(void) tputs(tgoto(str, arg_cols, arg_rows), arg_rows, outc);
+ 		break;
+ 
+ 	default:
+ 		(void)fprintf(stderr, errmany, arg_need, cap);
+ 		return NULL;
+ 	}
+ 	return argv;
  }

------------------------------------------------------------------------------