anton@bkj386.uucp (Anton Aylward) (11/28/90)
I've looked at a lot of screen packages and am very unhapy with them. Almost all turn areound and say "we aren't going to use the UNIX standard /etc/termcap or /usr/lib/terminfo", we're going to re- invent the wheel. This really burns me. it may be OK for in house developers and hackers who can waste time cutting new things like VVTERMCAP etc, but for us who have to shift product or install at a customer site its the pits. We get paid for results, not for wasting time hacking about. Now CURSES may not be perfect. it may be bloated and only do 80-90% of the job, but it is there. it is also a standard, as far as the TERMCAP/TERMINFO side goes. So how can we criticise it? Two ways, both of which go fully into the hands of ISC SCO INTEL etc: 1) it lacks colour ...... etc Yes it does/no it doesn't. NO it doesn't. I've been using ATT WGS machines with SVR3.2. They have colour capability in CURSES. If SCO etc choose not to implement this for their own reasons that's their problem. Go buy your UNIX from someone who adhere's to the standard. 2) it can't do <insert your favourite....> My "favourite" is ledger lines. I'm in the process of converting an application from ATT equipment (3B & WGS) to SCO XENIX. It was written for TERMINFO. The SCO TERMINFO lacks many features that were introduced in SVR2.0. In fact most of the SCO XENIX implemetation of TERMINFO & utilities is riddled with bugs. We're basically having to re-write CURSES, or the facilities we need! The stock solution is being told to upgrade to SCO UNIX (or something like that). This is fine for us, developing with the latest, most feature-full release. But what about customers buying the package from sortes and other outlets? To put this in persspective, would you consider buying, say, Norton Tools for DOS, if they were written so that they used the '286 & '386 extended instructions and the features of the VGA ? I mean this in the sense that you HAVE to upgrade to use the program at all! We're trying to make a design which will work if you haven't been obsesive about keeping up with new technology, if you don't have a colour screen (I'm a Brit, i spel funy!) if you don't have a VT220 with 16 functions keys and 8 display levels..... We're also trying to produce a product which can be installed without being an expert in TERMCAP or TERMINFO and without having to RTFM. One of our support group made the comment "If you have to _read_ the manual, its too complex" OK, maybe its a bit extreeme for you and me as developers, but the end users do have that attitude. So (flame down), can someone tell the net of a good, easy to use screen pacakge which does follow the UNIX standards ? /anton aylward Analysis Synthesis Consulting Inc anton@analsyn.uucp "12 Years with UNIX"
staceyc@sco.COM (Stacey Campbell) (12/06/90)
In article <1990Nov27.165132.1335@bkj386.uucp> anton@analsyn.UUCP writes: >Now CURSES may not be perfect. it may be bloated and only do >80-90% of the job, but it is there. it is also a standard, as >far as the TERMCAP/TERMINFO side goes. Agreed. Even if curses doesn't directly support some feature it will just take a little work to add the required top layer, which can then be used for other applications' development. > SVR3.2. They have colour capability in CURSES. If SCO > etc choose not to implement this for their own reasons > that's their problem. Go buy your UNIX from someone who > adhere's to the standard. Just so it is clear, SCO Unix V 3.2 (all versions) supports the stock AT&T System V 3.2 color curses. Anton is almost certainly referring to SCO Xenix. I've tossed in a fun little curses color demo at the bottom of this post, so anybody with any System V 3.2 Development System can give it a spin. > The SCO TERMINFO lacks many features that > were introduced in SVR2.0. In fact most of the SCO XENIX > implemetation of TERMINFO & utilities is riddled with > bugs. SCO Xenix comes with System V 3.[01] curses, not Sys V 2 (the clue is ACS character defines in /usr/include/tinfo.h). Historically SCO Xenix was based mostly around termcap curses simply because in the good old days BSD termcap curses was much more robust and useful than System V curses. IMHO System V 3.2 curses, and even to a degree System V 3.1 curses, are far and away better than BSD curses. > But what about customers buying the package from sortes > and other outlets? > > To put this in persspective, would you consider buying, > say, Norton Tools for DOS, if they were written so that > they used the '286 & '386 extended instructions and the > features of the VGA ? I mean this in the sense that > you HAVE to upgrade to use the program at all! System V 3.2 curses applications execute correctly on Xenix machines, terminfo files are backward compatible, though it is much nicer to use Unix terminfo files when on Xenix. There is no real system dependent issues when running a 386 Unix curses application on Xenix. The application only requires a working terminfo file. > We're also trying to produce a product which can be > installed without being an expert in TERMCAP or TERMINFO > and without having to RTFM. The terminfo(4) man page is a bit daunting. There is a reasonable Nutshell book that deals with both termcap and terminfo. Here's the demo program; #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 212 -rw------- Makefile # 6631 -rw-rw-r-- fire.c # # ============= Makefile ============== if test -f 'Makefile' -a X"$1" != X"-c"; then echo 'x - skipping Makefile (File already exists)' else echo 'x - extracting Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && CC= cc CFLAGS= -O -DM_TERMINFO -UM_TERMCAP LDFLAGS= -O OBJS= fire.o X #Unix LDLIBS= -lcurses -lm X #Xenix # LDLIBS= -ltinfo -lm X fire: $(OBJS) X $(CC) $(LDFLAGS) fire.o -o fire $(LDLIBS) X clean: X rm -f $(OBJS) fire SHAR_EOF chmod 0600 Makefile || echo 'restore of Makefile failed' Wc_c="`wc -c < 'Makefile'`" test 212 -eq "$Wc_c" || echo 'Makefile: original size 212, current size' "$Wc_c" fi # ============= fire.c ============== if test -f 'fire.c' -a X"$1" != X"-c"; then echo 'x - skipping fire.c (File already exists)' else echo 'x - extracting fire.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'fire.c' && #include <sys/types.h> #include <math.h> #include <curses.h> #include <string.h> X #ifndef COLOR_BLACK #define start_color() #define COLOR_PAIR(a) 0 #endif X extern double drand48(); extern void srand48(); extern long lrand48(); extern time_t time(); extern char *malloc(); extern void free(); extern unsigned int sleep(); X #define PART_COUNT 10 #define PART_VARIANCE 5 #define SIN_TABLE_SIZE 350 #define COLOR_MIXED -1 #define TABLE_SCALE(val) ((int)(val / M_PI * SIN_TABLE_SIZE)) #define BOUNDCHAR(win, y, x, char) \ X (((y) >= 0 && (y) < LINES && (x) >= 0 && (x) < COLS) ? \ X mvwaddch((win), (y), (x), (char)) : 0) #define PAT_RAND_SEQ 0x01 X typedef struct particle_t { X double y_scale; X double x_scale; X double x_inc; X double x; X int old_y, old_x; X int direction; X int color; X int sequence; X int pattern_inc; } particle_t; X typedef struct pattern_t { X char *string; X int mask; } pattern_t; X typedef struct object_t { X int rel_y, rel_x; X int part_count; X pattern_t *pattern; X int pat_cycle; X int color; X int done_count; X int life; X double y_mag, x_mag; X particle_t *particles; } object_t; X typedef struct object_list_t { X object_t *object; X struct object_list_t *next; } object_list_t; X static pattern_t Patterns[] = { X {"......+++++++******@@@@@@@", 0}, X {"|\\-/", PAT_RAND_SEQ}, X {".......ooooOOOOoooo", 0}, X {".........****.......", 0}, X {"*", 0} }; X #define PATTERN_SIZE (sizeof(Patterns) / sizeof(Patterns[0])) X static int ColorId = 1; #define RAND_COLOR() (lrand48() % ColorId + 1) X static void DoSinTable(); static void DisplayObject(); static void BuildParticles(); static object_t *BuildObject(); static void InitColors(); static void AddObject(); static void DoObjectList(); static void DeleteObject(); static void FreeMemory(); X int main(argc, argv) X int argc; char *argv[]; X { X double sin_table[SIN_TABLE_SIZE]; X object_list_t *top; X time_t show_over; X X nice(4); X printf("wait."); X fflush(stdout); X DoSinTable(sin_table); X srand48((long)time((time_t *)0)); X initscr(); X start_color(); X curs_set(FALSE); X InitColors(); X top = (object_list_t *)malloc(sizeof(object_list_t)); X top->object = BuildObject(); X top->next = 0; X show_over = time((time_t *)0) + 10000 * 60; X while (time((time_t *)0) < show_over) X { X if (! (lrand48() % 20)) X AddObject(&top); X else X if (! top) X { X sleep(1); X AddObject(&top); X } X DoObjectList(stdscr, sin_table, &top); X wrefresh(stdscr); X } X endwin(); X return 0; } X static void DoObjectList(win, sin_table, top) X WINDOW *win; double *sin_table; object_list_t **top; X { X object_list_t *now, *old; X X now = *top; X while (now) X { X DisplayObject(win, sin_table, now->object); X old = now; X now = now->next; X if (old->object->done_count >= old->object->part_count || X old->object->life < 0) X DeleteObject(old, top); X } } X static void DeleteObject(zap, top) X object_list_t *zap; object_list_t **top; X { X object_list_t *new, *last; X X if (zap == *top) X { X new = zap->next; X FreeMemory(zap); X *top = new; X return; X } X new = *top; X while (new != zap) X { X last = new; X new = new->next; X } X last->next = zap->next; X FreeMemory(zap); } X static void FreeMemory(item) X object_list_t *item; X { X free((char *)item->object->particles); X free((char *)item->object); X free((char *)item); } X static void AddObject(top) X object_list_t **top; X { X object_list_t *new_top; X X new_top = (object_list_t *)malloc(sizeof(object_list_t)); X new_top->object = BuildObject(); X new_top->next = *top; X *top = new_top; } X static object_t *BuildObject() X { X object_t *object; X X object = (object_t *)malloc(sizeof(object_t)); X object->part_count = lrand48() % PART_VARIANCE + PART_COUNT; X object->particles = (particle_t *)malloc(object->part_count * X sizeof(particle_t)); X object->pattern = &Patterns[lrand48() % PATTERN_SIZE]; X object->pat_cycle = strlen(object->pattern->string); X object->rel_y = LINES - lrand48() % 15; X object->rel_x = lrand48() % (COLS / 4 * 3) + COLS / 4 * 1 / 2; X object->color = lrand48() % 4 ? RAND_COLOR() : COLOR_MIXED; X object->done_count = 0; X object->y_mag = drand48() * 0.9 + 0.5; X object->x_mag = drand48() * 0.9 + 0.5; X object->life = lrand48() % 15 + 10; X BuildParticles(object); X X return object; } X static void DisplayObject(win, sin_table, object) X WINDOW *win; double *sin_table; object_t *object; X { X int i; X int draw_y, draw_x; X particle_t *p; X double y; X int sym; X X if (--object->life < 0) X { X for (i = 0; i < object->part_count; ++i) X { X p = &object->particles[i]; X BOUNDCHAR(win, p->old_y, p->old_x, ' '); X } X return; X } X for (i = 0; i < object->part_count; ++i) X { X p = &object->particles[i]; X if (p->x < M_PI) X { X BOUNDCHAR(win, p->old_y, p->old_x, ' '); X y = sin_table[TABLE_SCALE(p->x)] * p->y_scale; X draw_y = object->rel_y - y; X draw_x = object->rel_x + p->direction * p->x * X p->x_scale; X p->sequence += p->pattern_inc; X if (p->sequence < 0) X p->sequence = object->pat_cycle - 1; X else X if (p->sequence >= object->pat_cycle) X p->sequence = 0; X sym = object->pattern->string[p->sequence]; X BOUNDCHAR(win, draw_y, draw_x, X sym | COLOR_PAIR(p->color)); X p->old_y = draw_y; X p->old_x = draw_x; X p->x += p->x_inc; X if (p->x >= M_PI) X { X BOUNDCHAR(win, draw_y, draw_x, ' '); X ++object->done_count; X } X } X } } X static void DoSinTable(table) X double *table; X { X int i; X double inc; X double current; X X inc = M_PI / SIN_TABLE_SIZE; X for (i = 0, current = 0.0; i < SIN_TABLE_SIZE; ++i, current += inc) X { X table[i] = sin(current); X if (! (i % 66)) X { X putchar('.'); X fflush(stdout); X } X } } X static void BuildParticles(object) X object_t *object; X { X int i; X particle_t *p; X X for (i = 0; i < object->part_count; ++i) X { X p = &object->particles[i]; X p->y_scale = drand48() * (LINES - 1) * object->y_mag; X p->x_scale = drand48() * COLS / 6.0 * object->x_mag; X p->x_inc = drand48() * 0.05 + 0.1; X p->x = 0.0; X p->old_y = 0; X p->old_x = 0; X p->direction = lrand48() & 1 ? -1 : 1; X if (object->pattern->mask & PAT_RAND_SEQ) X { X p->sequence = lrand48() % object->pat_cycle; X p->pattern_inc = -p->direction; X } X else X { X p->sequence = 0; X p->pattern_inc = 1; X } X if (object->color == COLOR_MIXED) X p->color = RAND_COLOR(); X else X p->color = object->color; X } } X static void InitColors() X { #ifdef COLOR_BLACK X init_pair(ColorId++, COLOR_RED, COLOR_BLACK); X init_pair(ColorId++, COLOR_GREEN, COLOR_BLACK); X init_pair(ColorId++, COLOR_YELLOW, COLOR_BLACK); X init_pair(ColorId++, COLOR_BLUE, COLOR_BLACK); X init_pair(ColorId++, COLOR_MAGENTA, COLOR_BLACK); X init_pair(ColorId++, COLOR_CYAN, COLOR_BLACK); X init_pair(ColorId, COLOR_WHITE, COLOR_BLACK); #endif } X SHAR_EOF chmod 0664 fire.c || echo 'restore of fire.c failed' Wc_c="`wc -c < 'fire.c'`" test 6631 -eq "$Wc_c" || echo 'fire.c: original size 6631, current size' "$Wc_c" fi exit 0 -- Stacey Campbell staceyc@sco.com {uunet,decwrl,ucscc,att,sq,altos,lotus,phoenix,sun,microsoft,xbs}!sco!staceyc