Article 2713 of comp.sources.unix:
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!bloom-beacon.mit.edu!news.kei.com!newsfeed.internetmci.com!in1.uu.net!vixie!vixie!not-for-mail
From: wolf@prosun.first.gmd.de (Wolfgang Koehler)
Newsgroups: comp.sources.unix
Subject: v29i059: grafix-1.2 - a C++ library for easy X11 GUI apps, Part05/05
Date: 1 Dec 1995 11:59:13 -0800
Organization: Vixie Enterprises
Lines: 2455
Sender: vixie@vix.com
Approved: vixie@gw.home.vix.com
Message-ID: <49nmqh$96h@gw.home.vix.com>
References: <1.817847834.9257@gw.home.vix.com>
NNTP-Posting-Host: gw.home.vix.com

Submitted-By: wolf@prosun.first.gmd.de (Wolfgang Koehler)
Posting-Number: Volume 29, Issue 59
Archive-Name: grafix-1.2/part05

#!/bin/sh
# This is part 05 of Grafix
# ============= gccinc/sys/cdefs.h ==============
if test ! -d 'gccinc'; then
    echo 'x - creating directory gccinc'
    mkdir 'gccinc'
fi
if test ! -d 'gccinc/sys'; then
    echo 'x - creating directory gccinc/sys'
    mkdir 'gccinc/sys'
fi
if test -f 'gccinc/sys/cdefs.h' -a X"$1" != X"-c"; then
	echo 'x - skipping gccinc/sys/cdefs.h (File already exists)'
else
echo 'x - extracting gccinc/sys/cdefs.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gccinc/sys/cdefs.h' &&
/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
This file is part of the GNU C Library.
X
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
X
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.
X
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */
X
#ifndef	_SYS_CDEFS_H
X
#define	_SYS_CDEFS_H	1
X
#ifdef __GNU_LIBRARY__
#include <features.h>
#endif
X
#ifdef	__GNUC__
X
#ifndef __P
#define	__P(args)	args	/* GCC can always grok prototypes.  */
#endif
#define	__DOTS		, ...
X
/* Figure out how to declare functions that (1) depend only on their
X   parameters and have no side effects, or (2) don't return.  */
X
/*
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || defined(__cplusplus)
*/
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
X  /* Old GCC way. */
#ifndef	__CONSTVALUE
#define	__CONSTVALUE	__const__
#define	__CONSTVALUE2
#endif
#ifndef	__NORETURN
#define	__NORETURN	__volatile__
#define	__NORETURN2
#endif
#else
X  /* New GCC way. */
#ifndef	__CONSTVALUE
#define	__CONSTVALUE
#if defined(const) || !defined(__STDC__)
#define	__CONSTVALUE2	/* We don't want empty __attribute__ (()). */
#else
#define	__CONSTVALUE2	__attribute__ ((const))
#endif
#endif
#ifndef	__NORETURN
#define	__NORETURN
#ifdef noreturn
#define	__NORETURN2	/* We don't want empty __attribute__ (()). */
#else
#define	__NORETURN2	__attribute__ ((noreturn))
#endif
#endif
#endif
X
#else	/* Not GCC.  */
X
#define	__inline		/* No inline functions.  */
#define	__CONSTVALUE		/* No idempotent functions.  */
#define	__CONSTVALUE2
#define	__NORETURN		/* No functions-of-no-return.  */
#define	__NORETURN2
X
#if (defined (__STDC__) && __STDC__) || defined (__cplusplus)
X
#ifndef __P
#define	__P(args)	args
#endif
#define	__const		const
#define	__signed	signed
#define	__volatile	volatile
#define	__DOTS		, ...
X
#else	/* Not ANSI C or C++.  */
X
#ifndef __P
#define	__P(args)	()	/* No prototypes.  */
#endif
#define	__const			/* No ANSI C keywords.  */
#define	__signed
#define	__volatile
#define	__DOTS
X
#endif	/* ANSI C or C++.  */
X
#endif	/* GCC.  */
X
#if defined (__GNUC__) && __GNUC__ < 2
/* In GCC version 2, (__extension__ EXPR) will not complain
X   about GCC extensions used in EXPR under -ansi or -pedantic.  */
#define	__extension__
#endif
X
/* For these things, GCC behaves the ANSI way normally,
X   and the non-ANSI way under -traditional.  */
X
#if defined (__STDC__) && __STDC__
X
#define	__CONCAT(x,y)	x ## y
#define	__STRING(x)	#x
X
/* This is not a typedef so `const __ptr_t' does the right thing.  */
#define __ptr_t void *
typedef long double __long_double_t;
X
#else
X
#define	__CONCAT(x,y)	x/**/y
#define	__STRING(x)	"x"
X
#define __ptr_t char *
typedef double __long_double_t;
X
#endif
X
/* The BSD header files use the ANSI keywords unmodified.  (This means that
X   old programs may lose if they use the new keywords as identifiers.)  We
X   define them to their __ versions, which are taken care of above.  */
X
#ifdef	__USE_BSD
/* __attribute__ uses const. */
#if 0
#define	const		__const
#endif
#define	signed		__signed
#define	volatile	__volatile
#endif
X
/* C++ needs to know that types and declarations are C, not C++.  */
#ifdef	__cplusplus
#define	__BEGIN_DECLS	extern "C" {
#define	__END_DECLS	}
#else
#define	__BEGIN_DECLS
#define	__END_DECLS
#endif
X
#endif	 /* sys/cdefs.h */
SHAR_EOF
chmod 0644 gccinc/sys/cdefs.h ||
echo 'restore of gccinc/sys/cdefs.h failed'
Wc_c="`wc -c < 'gccinc/sys/cdefs.h'`"
test 3859 -eq "$Wc_c" ||
	echo 'gccinc/sys/cdefs.h: original size 3859, current size' "$Wc_c"
fi
# ============= class-browser.c ==============
if test -f 'class-browser.c' -a X"$1" != X"-c"; then
	echo 'x - skipping class-browser.c (File already exists)'
else
echo 'x - extracting class-browser.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'class-browser.c' &&
// class-browser.c
//          wolf 10/95
// complete graphic browser for class graphs : searches all class declarations
// in a set of source files, displays inheritance graph with buttons
// upon BPress the source pops up 
X
#include "tree.h" // includes window.h
#include "tree_icon.h"
X
#include "files.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <dirent.h>
#include "regex.h"
X
#if 0 
#define Dprintf(format, args...) printf(format, ## args)
#else
#define Dprintf(format, args...)
#endif
X
class class_popup : public main_window {
X  Bool unmapped;
public:
X  class_popup(char *name, char *decl, int ww, int wh, int x, int y) :
X  main_window(name,ww,wh,1,x,y) {
X    int nc = 0; // should be the length of decl !!
X    new text_viewer(*this,ww,wh,0,0,decl,nc); 
X    set_icon(tree_icon_bits, tree_icon_width, tree_icon_height);  
X    unmapped = True;
X  } 
X  void toggle() { // toggle between mappd/unmapped state
X    if (unmapped) RealizeChildren(); else Unmap();
X    unmapped = ! unmapped;
X  }
};
X
class ClassTree;
X
typedef list <ClassTree> Clist;
X
// ClassTree derived from Tree
// stores classname, subclasses, superclasses and textposition
class ClassTree : public Tree {
public:
X  Clist *parents;
X
X  char *declaration; // address of decl in some textbuffer
X  char *path; // filename
X  int tree; // index of separate tree (unused)
X  class_popup *class_pop;
X
X  ClassTree(char *name, char *decl = 0, char *path = 0) : Tree(name), 
X  declaration(decl), path(path) { 
X    parents = 0; 
X    class_pop = 0; 
X    tree = 0;
X  }
X
X  virtual void Press_cb(XButtonEvent *ev) { // activated from button press
X    if (declaration == 0) return; // no declaration given
X    if (class_pop == 0) {
X      char title[200]; sprintf(title,"%s (%s)",name,path); 
X      // raise popup just below the button, second press unmaps again
X      class_pop = new class_popup(title,declaration,500,200,
X				  ev->x_root, ev->y_root+20);
X    }
X    class_pop->toggle();
X  }
X
X  // aux function for line output concenated : x is set behind last char
X  void info_cat(window *infw, int &x, int y, char *str) {
X    infw->DrawString(x,y,str); 
X    x += 6*(strlen(str)+1);  // charwidth = 6 (+ 1 space behind)
X  }
X
X  virtual void Enter_cb(window *infw) { // activated from button Enter
X    if (infw) {      
X      infw->clear();
X      char text[200]; int x = 2, lhgt = 13, y = lhgt+2;
X      if (path) sprintf(text,"class '%s' defined in file '%s'",name,path);
X      else sprintf(text,"class '%s' is nowhere defined",name);
X      infw->DrawString(x,y,text); y += lhgt;      
X      Clist *ch;   
X      info_cat(infw,x,y,"base :");
X      for (ch = parents; ch; ch = ch->cdr) info_cat(infw,x,y,ch->car->name);
X      x = 2; y+= lhgt;  
X      info_cat(infw,x,y,"derived :"); 
X      for (ch = (Clist*) children; ch; ch = ch->cdr) 
X	info_cat(infw,x,y,ch->car->name);
X     }
X  }
};
X
ClassTree *SearchName(Clist *cl, char *sname) { 
X  // returns element with sname or 0
X  for( ; cl; cl = cl->cdr) 
X    if (strcmp(cl->car->name,sname) == 0) return(cl->car);
X  return 0;
}
X
class Regexp {
X  struct re_pattern_buffer rpb;
public:
X  char *exp;
X  Regexp(char *exp) : exp(exp) { 
X    rpb.buffer = malloc(100); 
X    rpb.allocated = 100;
X    rpb.translate = 0;
X    rpb.fastmap = (char *) malloc(256);
X    re_compile_pattern(exp,strlen(exp),&rpb);
X  }
X  Search(char *string, int size) { 
X    int pos = re_search(&rpb,string,size,0,size,0);
X    if (pos < 0) return -1;
X    int match = re_match(&rpb,string,size,pos,0);
X    return (pos+match); // returns pos *after* regexp
X  }
};
X
#define nil (char*)(-1)
X
class TextBuffer {
X  char *buf;
X  int length;
public:
X  TextBuffer(char *buf) : buf(buf) { length = strlen(buf); }
X
X  int ForwardSearch(Regexp *rex, int beg) {
X    Dprintf("searching for '%s' from %d ",rex->exp,beg);
X    int pos = rex->Search(buf+beg,length-beg);
X    Dprintf("returns %d\n",pos);
X    if (pos < 0) return -1; else return (pos + beg);
X  }
X  char *Text(int pos = 0) { return buf+pos; }
X  char *Line(int pos) { // search linestart *before* pos 
X    char *cp = buf+pos;
X    while (*cp != '\n' && cp-- > buf);
X    return cp;
X  }
X  int Length() { return length; }
};
X
char* strnnew (const char* s, int len) {
X  char* dup = new char[len + 1];
X  strncpy(dup, s, len);
X  dup[len] = '\0';
X  return dup;
}
X
inline int IsValidChar (char c) {
X  return isalpha(c) || c == '_' || c == '$';
}
X
inline int KeyWord (const char* string) {
X  return 
X    strcmp(string, "public") == 0 ||
X      strcmp(string, "protected") == 0 ||
X        strcmp(string, "private") == 0 ||
X	  strcmp(string, "virtual") == 0;
}
X
void print_classes(Clist *cl);
X
class ClassBuffer : public TextBuffer {
public:
X  ClassBuffer(char *buf) : TextBuffer(buf) {}
X
X  char* FindClassDecl(int& beg) {
X    static Regexp classkw("^class[ $]");
X    static Regexp delimiter("[:{;]");    
X    char *className = nil;
X    for (;;) {
X      beg = ForwardSearch(&classkw,beg);
X      if (beg < 0) break;
X      int tmp = beg;
X      int delim = ForwardSearch(&delimiter,tmp);
X      // check if only empty declaration
X      if (delim >= 0 && *Text(delim-1) != ';') {
X	className = Identifier(beg);
X	break;
X      }
X    }
X    return className;
X  }
X  
X  char* Identifier (int& beg) {
X    int i, j;
X    const char* text = Text();
X    char* string = nil;
X  
X    for (i = beg; i < Length(); ++i) 
X      if (IsValidChar(text[i])) break;
X    
X    for (j = i+1; j < Length(); ++j) {
X      char c = text[j];
X      if (!IsValidChar(c) && !isdigit(c)) break;
X    }
X    if (j < Length()) {
X      string = strnnew(&text[i], j-i);
X      beg = j;
X    }
X    return string;
X  }
X  
X  char* ParentName (int& beg) {
X    static Regexp delimiter("{");
X    int delim = ForwardSearch(&delimiter, beg);
X    if (delim < 0) return nil;
X  
X    for (;;) {
X      char* string = Identifier(beg);
X    
X      if (string == nil || beg >= delim) {
X	delete string;
X	beg = delim;
X	return nil;
X      
X      } else if (KeyWord(string)) {
X	delete string;
X	string = nil;
X	
X      } else return string;
X    }
X  }
X  // search for classdefs -> append to allcl
X  int SearchTextBuffer(Clist* &allcl, char* path) {
X    int nc = 0;
X    int beg = 0;
X    for (;;) { // search classname
X      char *className = FindClassDecl(beg);
X      if (className == nil) break;
X      char * decl = Line(beg);
X      Dprintf("\nnew class '%s' at %d\n",className, beg);
X      // print_classes(allcl);
X      ClassTree *cli = SearchName(allcl,className); 
X      nc++;
X      if (cli == 0) { // new class
X	cli = new ClassTree(className,decl,path);
X	allcl = allcl->push(cli);
X      } else { // already there : update 
X	cli->declaration = decl;
X	cli->path = path;
X      }
X      for (;;) { // search all parents
X	char* parentName = ParentName(beg);
X	if (parentName == nil) break;
X	
X	ClassTree *cpi = SearchName(allcl,parentName);
X	if (cpi == 0) { // new class (only the name)
X	  cpi = new ClassTree(parentName);
X	  allcl = allcl->push(cpi);
X	} // else already there : nothing 
X      
X	cli->parents = cli->parents->push(cpi); // my parentlist
X	cpi->children = cpi->children->push(cli); // I am child of parent
X	Dprintf(" '%s'",parentName);
X      }
X    }
X    return nc; // number of defined classes
X  }
};
X
typedef int (*IVPVP)(const void *,const void *); // the correct type for qsort
// compare function for qsort : sorting of child nodes
static int qcomp(const Tree **e1, const Tree **e2) { 
X  return ((*e2)->descendants - (*e1)->descendants);  
X  // return (strcmp((*e1)->name,(*e2)->name)); 
}
X
static char* help_text[] = { 
X  "Call the program with filenames or directory names as commandline args",
X  "eg.  \"class_browser win* ../grab/\"  or  \"class_browser . *.h *.c\" ",
X  "Directories given as argument are completely parsed",
X  "Only files that end in '.c' '.C' '.h' are recognized as C-files",
X  "All given files are parsed for class definitions and linked in one graph",
X  "The different colors represent the file where the class is defined","",
X  "By pressing a button with class name a window with the header pops up,",
X  "pressing again unmaps it","",
X  "The bottom window shows info about the class under the cursor","",
X  "'hardcopy' - makes a 'xwd | xpr | lpr' pipe to the printer",
X  "             but only the visual part is printed","",
X  "The program will fail for some exotic graphs at the moment", 0 };
X 
class Class_main : public Tree_main {
public: 
X  Class_main(char * WMName, int w, int h, Clist *cll) : 
X  Tree_main(WMName,w,h, (Tlist *) cll) {
X    new help_button(*mb,"help",help_text);
X  }
X
X  virtual void init() { // modify : change button colors
X    Tree_main::init(); // first usual init
X    hinf = 45; // larger info window
X
X    unsigned int pmax = 42, pid; // max number of colors
X    struct GC3 gc3[pmax]; // vector of button GCs
X    for (pid = 0; pid < pmax; pid++) {
X      unsigned short b = (pid % 7 + 7)*5040, r = (pid % 3 + 3) * 13100,
X      g = (pid / 21 + 9) * 6500; // the colors for the file indexed pid
X      color_GC(r,g,b,&gc3[pid]); // create new GCs
X    }
X    // compute colors directly from filename : everytime get the same color !
X    Clist *cll = (Clist *) tll; // linear list of all nodes
X    for (Clist *cl = cll; cl; cl = cl->cdr) { 
X      ClassTree *ci = cl->car; 
X      char* path = ci->path; 
X      if (path) { // if == 0 : no file with definition, used default color
X	char *slash = strrchr(path,'/');
X	if (slash) path = slash+1; // get rid of all before last slash 
X	for (pid=0; *path;) pid += (unsigned char) *(path++);
X	pid %= pmax; // simply rest of character sum 
X	ci->nb->set_GC(gc3+pid); // set the colors from gc3[pid]
X      }
X    }
X  }
X  // to be called when all classes read in : 
X  // build geometrical graph for display
X  // vwidth and vheight return size of needed virtual window
X  virtual void make_graph() {
X    Clist *cll = (Clist *) tll; // linear list of all nodes
X    int nclasses = tll->length(); //  total number of classes
X
X    // use iteration algorithm to assign each node a depth value starting with 0
X    // the outer loop (cl) goes with the linear list 
X    // the inner loop (chl) checks all children, if there a mismatch is found
X    // the outer is started again
X    // can be called dynamically
X    // suppositions : initial depth values = 0
X
X    int nloop = 0, maxnloop = 1000000 >? (nclasses*nclasses*nclasses);
X    Clist *cl = cll; 
X    do { 
X      ClassTree *ci = cl->car;
X      int dd = ci->depth; Clist *chl;
X      for (chl = (Clist*) ci->children; chl; chl = chl->cdr) {
X	Node *chn = chl->car; 
X	if (chn->depth < dd+1) { chn->depth = dd+1; break; } else
X	if (chn->depth > dd+1) { ci->depth = chn->depth - 1; break; }
X      } 
X      if (chl == 0) cl = cl->cdr; // the inner loop completed
X      else cl = cll; // there was a mismatch, start again
X      if (nloop++ > maxnloop) error("the class graph contains cycles");
X    } while(cl);
X
X    // printf("nloop = %d\n",nloop);
X    // second loop : look for the node with most desc to use as top
X    int ndescmax = 0; 
X    ClassTree *ctop = 0;
X    for (cl = cll; cl; cl = cl->cdr) { 
X      ClassTree *ci = cl->car;
X      int nd = ci->rec_descendants(); //
X      if (nd > ndescmax) { ndescmax = nd; ctop = ci; }
X    }
X
X    make_tree(ctop); // build main tree
X
X    // now all buttons not in the main tree must be inserted
X    // 1. : find all nodes with no parents
X    // 2. : sort them for number of descendants, so largest come first
X    // 3. : insert into existing tree
X
X    ClassTree *ctemp[nclasses];// for sorting children we must use a temp vector
X    // the number needed is less than nclass
X    int nc = 0;
X    for (cl = cll; cl; cl = cl->cdr) { 
X      ClassTree *ci = cl->car;
X      if (ci->parents == 0 && ci != ctop)  // has no superclasses -> subtree
X	ctemp[nc++] = ci;
X    }
X    qsort(ctemp, nc , sizeof(void*), (IVPVP) qcomp); // sort with qcomp
X
X    for (int i = 0; i < nc; i++) 
X      ctemp[i]->rec_insert(tcol, vheight, vwidth);
X
X   //for (Tlist *tl= tcol[1]; tl; tl = tl->cdr) printf("%s\n",tl->car->name);
X  }
};
X
// test if fina is a c-file eg. ends with  ".c/.C/.h"
Bool cfile(char *fina) { 
X  int length = strlen(fina); 
X  char clast = fina[length-1];
X  return fina[length-2] == '.' && (clast == 'c' || clast == 'C' || clast == 'h' );
}
X  
void parse_file(Clist* &allcl, char *fina) {
X  if (! cfile(fina) ) return; 
X  struct stat st; 
X  if (stat(fina, &st) != 0) return; 
X  if (st.st_mode & S_IFDIR) return;
X  int bufsize = st.st_size;
X  printf("file %s (%d byte)",fina,bufsize);
X  FILE *f = fopen(fina,"r"); if (f == 0) return; 
X
X  char *buf = new char[bufsize]; // the buffer for ClassBuffer
X  if (buf == 0) error("no space for textbuffer");
X  int c, n = 0;
X  while ((c = fgetc(f)) != EOF) buf[n++] = c;
X  buf[n] = 0;
X  if (n != bufsize) { printf("error reading %s %d\n",fina,n); exit(0); }
X  ClassBuffer *tb = new ClassBuffer(buf);
X  int nc = tb->SearchTextBuffer(allcl,fina);
X  printf(" has %d class definitions\n",nc);
X  if (nc == 0) { delete tb; delete buf; } // not needed
X  fclose(f);
}
X
void parse_directory(Clist* &allcl, char *path) {
X  printf("reading directory %s\n",path);
X  DIR *dirp = opendir(path);
X  struct dirent *dp; 
X  for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 
X    int length = strlen(dp->d_name);
X    if (dp->d_name[length-1] != '.') { // not for . or .. file
X      int plen = strlen(path); 
X      if (path[plen-1] == '/') path[plen-1] = 0; // eliminate tail-slashes
X      char *fina = new char[length+strlen(path)+2];
X      sprintf(fina,"%s/%s",path,dp->d_name);
X      parse_file(allcl,fina);
X    }
X  }
}
X
// output of all found classes with children and parents on stdout
void print_classes(Clist *cl) {
X  while (cl) {
X    ClassTree *ci = cl->car;
X    printf("\n%s %d %d",ci->name,ci->depth,ci->tree);
X    // char *decl = ci->declaration;
X    // for (int i=0; i< 10; i++) printf("%c",*(decl+i));
X    Clist *ch = (Clist*) ci->children;
X    if (ch) { 
X      printf(" [");
X      while (ch) { printf(" %s",ch->car->name); ch = ch->cdr; }
X      printf(" ]");
X    }
X    Clist *cp = ci->parents;
X    if (cp) { 
X      printf(" (");
X      while (cp) { printf(" %s",cp->car->name); cp = cp->cdr; }
X      printf(" )");
X    }
X    cl = cl->cdr;
X  }
X  printf("\n");
}
X
// call with filename arguments : 
// eg "*" "win*" "*.h" "f1.c f2.h" ". ../fgrab/"
// filenames other then .c/.h/.C are ignored
// directories as args are completely parsed
X 
int main(int argc, char* argv[]) {
X  Clist *AllClasses = 0; // linear list of all classes
X  // old version : explicit files
X  char *finas[] = {"window.h",  "lattice.h", "lat_win.c", "class_browser.c" };
X  int nfi = sizeof(finas)/sizeof(char*);
X  if (0) for (int i=0; i< nfi; i++) parse_file(AllClasses, finas[i]);
X  
X  if (argc < 2) parse_directory(AllClasses,"."); // if no argument given
X
X  for (int arg = 1; arg < argc; arg++) {
X    char *fina = argv[arg];
X    struct stat st; 
X    if (stat(fina, &st) == 0) { // else no file 
X      if (st.st_mode & S_IFDIR) // a directory
X	parse_directory(AllClasses,fina);
X      else
X	parse_file(AllClasses,fina);
X    }
X  }
X
X  int nctot = AllClasses->length();
X  printf("total %d classes\n",nctot);
X  // print_classes(AllClasses);
X  if (nctot == 0) return 0;
X  // **** the drawing ********
X  Class_main *mw = new Class_main(argv[0],400,450,AllClasses);
X  mw->init();
X  mw->main_loop();
}
SHAR_EOF
chmod 0644 class-browser.c ||
echo 'restore of class-browser.c failed'
Wc_c="`wc -c < 'class-browser.c'`"
test 15255 -eq "$Wc_c" ||
	echo 'class-browser.c: original size 15255, current size' "$Wc_c"
fi
# ============= hello.c ==============
if test -f 'hello.c' -a X"$1" != X"-c"; then
	echo 'x - skipping hello.c (File already exists)'
else
echo 'x - extracting hello.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'hello.c' &&
#include "window.h"
X
main(int argc, char *argv[]) {
X  main_window *mw = new main_window(argv[0],200,200);
X  new text_win(*mw,"Hello World !",180,20,10,50);
X  new quit_button(*mw,100,20,50,150);
X  mw->main_loop();
}
SHAR_EOF
chmod 0644 hello.c ||
echo 'restore of hello.c failed'
Wc_c="`wc -c < 'hello.c'`"
test 215 -eq "$Wc_c" ||
	echo 'hello.c: original size 215, current size' "$Wc_c"
fi
# ============= win-demo.c ==============
if test -f 'win-demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping win-demo.c (File already exists)'
else
echo 'x - extracting win-demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'win-demo.c' &&
// win-demo.c : 
//     demonstration of some basic classes and functionality of grafix
X
#include "window.h"
X
// derived class of window
class my_window : public window {
public: my_window(window & parent, int w, int h, int x, int y) :
X  window(parent,w,h,x,y) {}
X  virtual void redraw() { // virtual fn replaces window::redraw
X    int y; 
X    for (y=0; y < height ; y+= 3) line(0, y, width, y); 
X  }
};
X
X
// window shows a variable string which is selected from radio_menu 
// deft is the starting value
class displ : public window {
public:
X    char * val;
X    displ(window & parent, char * deft, int w, int h, int x, int y) :
X    window (parent,w,h,x,y) { val = deft; } 
X
X    virtual void redraw()  { clear(); PlaceText(val); }
X    virtual void action(char* /* menu */, char * value) { 
X      val = value;
X      redraw(); 
X    }
};
X
// test of  keyboard-Events : output of state and key
class key_test : public button { 
char info[200]; 
public:
X   key_test(window & parent, int w, int h, int x, int y) :
X     button (parent,"keyboard test",w,h,x,y) {
X     selection_mask |= KeyPressMask;
X   }
X   virtual void KeyPress_CB(XKeyEvent ev) { 
X     // only Shift state (0x1) is recongnized in  XLookupKeysym
X     KeySym keysym = XLookupKeysym(&ev,ev.state & 1);
X     sprintf(info,"state = 0x%x code = 0x%x keysym = 0x%lx -> '%s'",
X	     ev.state,ev.keycode,keysym,XKeysymToString(keysym));
X  //   for complicated chars (Alt Ctrl Alt Gr...) 
X  //   char bufret[20]; int bytes_buffer; KeySym keys_ret; XComposeStatus sio;
X  //   XLookupString(&ev,bufret,bytes_buffer,&keys_ret,&sio);
X  //   printf(" %s %x ",bufret,keys_ret);
X     printf("%s\n",info); 
X     Name = info; clear(); // draw info for Name
X     redraw();
X   }
X };
X
// quit as a callback function
void cb_fn() { printf(" cb   \n"); }
void quit() { exit(0); }
void funct(int n, char * s1, char * s2) {
X  printf("funct called with int %d, char * %s, char * %s\n",n,s1,s2); }
X
scrollbar * scbr;
main_window *mainw;
X
void sbinf() { printf(" %d",scbr->value); fflush(stdout); };
X
// lists all children recursively
void child_tree(window *pp) {
X  static int nest = 0;
X  win_list * cc = pp->children;
X  nest++;
X  while (cc) { 
X    window * cw = cc->child;
X    int i; for (i=0; i < nest; i++) printf("  "); // recursion depth
X    printf("Win %lx (%dx%d) at %d,%d\n",cw->Win,cw->width,cw->height,
X	   cc->x,cc->y);
X    child_tree(cw);
X    cc = cc->next; }
X  nest--;
}
X
void child_print(window *pp) {
X  printf("window tree of Win %lx (%dx%d)\n",pp->Win,pp->width,pp->height);
X  child_tree(pp);
} 
X
main(int /* argc */, char *argv[]) 
{ 
X  main_window *mainw = new main_window(argv[0], 300, 300);  // Main Window
X
X  // 1. child : a quit button
X  new quit_button(*mainw,100,20, 0, 0);
X  // 2. child : simple window  
X  window *child = new window(*mainw,  80, 100, 0, 100); 
X
X  // button instance as child of child (wo functionality) but help
X  char *text1[] = {"this is context sensitive","Help-Text",""
X		   "which is bound to button ",0};
X  new button(*child, "button", text1, 50, 20, 10, 10);
X  // a button with callback-function 
X  button *sb = new callback_button(*child, "cb-info", cb_fn, 50,20,10, 40); 
X  sb->CB_info = TRUE; // debug inform about all events
X
X  new callback_button(*child, "quit", quit, 50,20,10, 70);
X  
X  // a popup window connected with a popup-button  
X  main_window *popup = new main_window("popup", 200, 100); 
X  popup->CB_info = True;
X  new button(*popup, "hello", 100, 20, 0, 0);
X  new unmap_button(*popup, "delete",100, 20, 100, 0);
X  new popup_button(*mainw, popup, "popup", 100, 20, 0, 30);
X
X  // help button 
X  char * text[] = {"this is help text for help button", "here the 2. line", 0};
X  new help_button(*mainw, 20, 60, text);
X  new my_window(*mainw, 60, 60, 110, 0); // user-defined window 
X
X  // a simple pulldown window connected with pulldown_button 
X  // and two childs
X  pulldown_window * pulldown;
X  int w = 80, h = 20, x = 210, y = 0; 
X  pulldown = new pulldown_window (w, 200);
X
X  new button (*pulldown,"pp",w, 20, 0, 30);
X  new pulldown_button(*mainw, pulldown, "pulldown-1", w, h, x, y);
X  y+= 30;
X
X  struct but_cb pd_list[] = { {"button1", cb_fn}, {"quit", quit}};
X  make_pulldown_menu(*mainw, "pulldown-2", 2, pd_list, w, h, x, y); y+= 30;
X
X  // xwd_button : calls "xwd -id wid | xwud &" (produces copy on  screen)
X  xwd_button xwd(*mainw,"dump"," | xwud &", mainw, w, h, x, y); 
X  y+= 30;
X  
X  new template_button <void*>(*mainw,"children",child_print,
X			      mainw, w, h, x, y);
X  y+= 30;
X
X  // radio button menu with display of toggled value
X  window *radio = new window(*mainw,100,70,100,100); 
X  displ *dsp = new displ(*radio,"display",80,20,10,10);
X  char *blist[] = { "val-1", "***b2***", "val-2" , "xxxxxx", 0 };
X  char *help[] = {"this Help Text ","appears", "upon press", 
X		  "of the right mouse button","as popup",0};
X  make_radio_menu (*radio, "radio", blist, help, dsp, 80, 20, 10, 30); 
X
X  new key_test(*mainw,300,20,0,200);
X  
X  scbr = new scrollbar (*mainw,&sbinf,200,30,0,240,0,1000,500,"x = %3d");
X
X  // a menu bar with autoplace buttons
X  menu_bar *mb = new menu_bar(*mainw,300,25,0,270);
X  int value = 1; // a toggle value for toggle_button below
X  new button(*mb,"buttons"); new button(*mb, "with");
X  new button(*mb,"autosizing");
X  // Demo for function_button -> calls 'funct'
X  new function_button(*mb,"funct",(CB) funct,1,"2.arg","3.");
X  new toggle_button(*mb, "toggle", &value);
X  new quit_button(*mb);
X
X  mainw->main_loop();
X  // delete mainw; -> is done automatically !
}
X
X
X
X
SHAR_EOF
chmod 0644 win-demo.c ||
echo 'restore of win-demo.c failed'
Wc_c="`wc -c < 'win-demo.c'`"
test 5505 -eq "$Wc_c" ||
	echo 'win-demo.c: original size 5505, current size' "$Wc_c"
fi
# ============= edit-demo.c ==============
if test -f 'edit-demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping edit-demo.c (File already exists)'
else
echo 'x - extracting edit-demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'edit-demo.c' &&
// edit-demo.c : demonstration of edit_windows 
#include "window.h"
X
// derived from edit_window no init string, enter fn overwritten
// expects 2 ints as input
class myedit : public edit_window {
public: myedit(window &parent, int w,int h, int x, int y) : 
X  edit_window(parent,"",w,h,x,y) {}
X  virtual void enter() { 
X    int reg, arg;
X    printf("%s\n",value); 
X    if (sscanf(value,"%d%d",&reg,&arg) == 2) printf("ok %d %d\n",reg,arg);
X    else format_error();
X  } 
};
X
main(int argc, char *argv[]) { 
X  main_window *mw = new main_window(argv[0],200,100);
X  new edit_window(*mw,"1234",180,20,10,10);  
X  new myedit(*mw,180,20,10,40);
X  new quit_button(*mw,100,20,10,70);
X  mw->main_loop();
}
SHAR_EOF
chmod 0644 edit-demo.c ||
echo 'restore of edit-demo.c failed'
Wc_c="`wc -c < 'edit-demo.c'`"
test 696 -eq "$Wc_c" ||
	echo 'edit-demo.c: original size 696, current size' "$Wc_c"
fi
# ============= file-browser.c ==============
if test -f 'file-browser.c' -a X"$1" != X"-c"; then
	echo 'x - skipping file-browser.c (File already exists)'
else
echo 'x - extracting file-browser.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'file-browser.c' &&
#include <stdio.h>
#include <sys/stat.h>
#include "window.h"
#include "files.h"
X
// read opened FILE f into char array text, with line pointers lptr
// returns : number of lines read; fina only for print
char* read_file (FILE *f, char *fina, int &n) {
X
X  struct stat st; 
X  stat(fina, &st); 
X  int bufsize = st.st_size;
X  printf("file %s (%d byte)\n",fina,bufsize);
X
X  char *buf = new char[bufsize]; // it is needed later
X  int c;
X  n = 0;
X  while ((c = fgetc(f)) != EOF) buf[n++] = c;
X  buf[n] = 0;
X  if (n != bufsize) { printf("error reading %s %d\n",fina,n); exit(0); }
X  return buf;
}
X
// reads a new file and displays it in ts, 
// in fina the cosed file name is returned
void open_new_file(text_viewer *ts, char *fina, char *buf) {
X  char *defname = "*.c"; 
X  FILE *fload;
X  fload = open_file_interactive(defname,fina,MODE_READ);
X  if (fload == NULL) return;   
X  int nc; 
X  delete buf;
X  buf = read_file(fload,fina,nc);
X  ts->reset(buf,nc);
X  fclose(fload);
X  XStoreName(display,ts->mainw->Win,fina); // set WM name
}
X
int top = 0;
X
void spawn(char *last_fina) { // creates a new window with the last file
X  int ww = 300, wh = 300;
X  char *fina = new char [200]; strcpy(fina,last_fina);
X
X  FILE *f = fopen(fina,"r"); 
X  if (f == NULL) { printf("cannot open file '%s'\n",fina); return; }
X  int nc;
X  char *buf = read_file(f,fina,nc);
X  main_window *sw = new main_window(fina,ww,wh+20);
X  text_viewer *tv = new text_viewer(*sw,ww,wh,0,20,buf,nc); 
X
X  menu_bar *mb = new menu_bar(*sw,ww,20,0,0);
X  new function_button(*mb,"new file",(CB) open_new_file,tv,fina, buf);
X  new function_button(*mb,"spawn",(CB) spawn,fina);
X
X  // only the top window has a quit button the others have delete_buttons
X  // that delete the sw-window tree
X  // upon delete also the new arrays (lptr, text, fina) should be deleted
X  if (top == 0) new quit_button(*mb); else new delete_button(*mb,sw);
X
X  // to have only one main_loop :
X  if (top++ == 0) sw->main_loop(); else sw->RealizeChildren();
X 
}
X
int main(int argc, char **argv) {
X  // if argument given : display it
X  char *fina = (argc > 1) ? argv[1] : "files.c"; 
X  spawn(fina) ;
}
X
X
X
X
SHAR_EOF
chmod 0644 file-browser.c ||
echo 'restore of file-browser.c failed'
Wc_c="`wc -c < 'file-browser.c'`"
test 2123 -eq "$Wc_c" ||
	echo 'file-browser.c: original size 2123, current size' "$Wc_c"
fi
# ============= cursors.c ==============
if test -f 'cursors.c' -a X"$1" != X"-c"; then
	echo 'x - skipping cursors.c (File already exists)'
else
echo 'x - extracting cursors.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'cursors.c' &&
// show all cursors from X/cursorfont.h
X
#include "window.h"
X
/* $XConsortium: cursorfont.h,v 1.2 88/09/06 16:44:27 jim Exp $ */
/*
#define XC_num_glyphs 154
#define XC_X_cursor 0
#define XC_arrow 2
#define XC_based_arrow_down 4
#define XC_based_arrow_up 6
#define XC_boat 8
#define XC_bogosity 10
#define XC_bottom_left_corner 12
#define XC_bottom_right_corner 14
#define XC_bottom_side 16
#define XC_bottom_tee 18
#define XC_box_spiral 20
#define XC_center_ptr 22
#define XC_circle 24
#define XC_clock 26
#define XC_coffee_mug 28
#define XC_cross 30
#define XC_cross_reverse 32
#define XC_crosshair 34
#define XC_diamond_cross 36
#define XC_dot 38
#define XC_dotbox 40
#define XC_double_arrow 42
#define XC_draft_large 44
#define XC_draft_small 46
#define XC_draped_box 48
#define XC_exchange 50
#define XC_fleur 52
#define XC_gobbler 54
#define XC_gumby 56
#define XC_hand1 58
#define XC_hand2 60
#define XC_heart 62
#define XC_icon 64
#define XC_iron_cross 66
#define XC_left_ptr 68
#define XC_left_side 70
#define XC_left_tee 72
#define XC_leftbutton 74
#define XC_ll_angle 76
#define XC_lr_angle 78
#define XC_man 80
#define XC_middlebutton 82
#define XC_mouse 84
#define XC_pencil 86
#define XC_pirate 88
#define XC_plus 90
#define XC_question_arrow 92
#define XC_right_ptr 94
#define XC_right_side 96
#define XC_right_tee 98
#define XC_rightbutton 100
#define XC_rtl_logo 102
#define XC_sailboat 104
#define XC_sb_down_arrow 106
#define XC_sb_h_double_arrow 108
#define XC_sb_left_arrow 110
#define XC_sb_right_arrow 112
#define XC_sb_up_arrow 114
#define XC_sb_v_double_arrow 116
#define XC_shuttle 118
#define XC_sizing 120
#define XC_spider 122
#define XC_spraycan 124
#define XC_star 126
#define XC_target 128
#define XC_tcross 130
#define XC_top_left_arrow 132
#define XC_top_left_corner 134
#define XC_top_right_corner 136
#define XC_top_side 138
#define XC_top_tee 140
#define XC_trek 142
#define XC_ul_angle 144
#define XC_umbrella 146
#define XC_ur_angle 148
#define XC_watch 150
#define XC_xterm 152
*/
X
class curs_win : public window { 
int cursi;
public:
X  curs_win(window & parent, int w, int h, int x, int y, int ci)
X    : window(parent, w, h, x, y, 1) { 
X    Cursor curs = XCreateFontCursor(display,ci);
X    XDefineCursor(display,Win,curs);
X    cursi= ci;
X  }
X  virtual void redraw() { 
X    char cc[10]; sprintf(cc,"%d",cursi); 
X    PlaceText(cc);
X  }  
};
X
main() {
X  main_window *mw = new main_window("cursors",420,510);
X  new quit_button(*mw,50,20,0,0);
X  int x = 0, y = 30,i;
X  for (i= 0; i < 77; i++ ) { 
X    new curs_win(*mw,40,50,x,y,2*i); x+= 42; 
X    if ((i % 10) == 9) { x = 0; y+= 50; }
X  }
X  mw->main_loop();
}
SHAR_EOF
chmod 0644 cursors.c ||
echo 'restore of cursors.c failed'
Wc_c="`wc -c < 'cursors.c'`"
test 2646 -eq "$Wc_c" ||
	echo 'cursors.c: original size 2646, current size' "$Wc_c"
fi
# ============= calc.c ==============
if test -f 'calc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping calc.c (File already exists)'
else
echo 'x - extracting calc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'calc.c' &&
// calc.c : a very simple calculator, part of the grafix package
//    wolf 12/94, 
//          hex/dec/bin conversion 
//          works only with integers, no overflow check is performed
//          arithmetic and logical operations
X
#include "window.h"
#include <ctype.h>
X
static int mode = 0, // actual display mode : 0 = decimal, 1 = hex, 2 = bin
X       base = 10;    // 10       or  16
char *modestr[3]= {"dec","hex","bin"};
X
typedef void (*OP) (int&, int); // operator function
void identity(int &x,int y) { x = y; };
X
class acc_disp : public window { // display and manipulate the accumulator
X  int value, acc;
X  OP op_st; // operation stack
X  Bool init; // start entering a new number (is set after ops )
public:
X  acc_disp(window & parent, int w, int h, int x, int y) :
X    window (parent,w,h,x,y,2) { 
X      value = 0; acc = 0; op_st = identity; init = True;
X   } 
X  virtual void redraw()  {
X    char st[33]; 
X    switch (mode) {
X      case 0: 
X      case 1: sprintf(st, (base == 10) ? "%20d" : "0x%18X",value); break;
X      case 2: unsigned n = 32, x = value; // unsigned !!
X	memset(st,' ',n); st[n] = 0; 
X        do { st[--n] = (x & 1) ? '1' : '0'; x >>= 1; } while (x); 	
X    }
X    clear(); PlaceText(st); 
X  }
X  virtual void enter(char digit) { 
X    if (init) { init = False; value = 0; }
X    value = base*value + digit;
X    redraw(); 
X  }
X  void ce() { value = 0; redraw(); }
X  void ca() { value = 0; acc = 0; op_st = identity; redraw(); }
X  void operate (OP opf) { // for operations
X    (*op_st)(acc,value); value = acc; redraw();
X    op_st = opf; init = True; // enter
X  } 
};
X
acc_disp *disp;
X
class mode_button : public button {
public:
X  mode_button(window & parent, int w, int h, int x, int y) :
X  button(parent,modestr[mode],w,h,x,y) { }
X  
X  virtual void BPress_1_CB(XButtonEvent) { 
X    mode++; mode %= 3; base = (mode == 0) ? 10 : 16;
X    Name = modestr[mode]; 
X    redraw(); disp->redraw();
X  }
};
X
class digit_butt : public button {
X  char digit;
X  char nstr[2];
X public:
X  digit_butt(window & parent, char dig, int w, int h, int x, int y) :
X    button(parent,"",w,h,x,y) { 
X      digit = dig; sprintf(nstr,"%X",digit);
X      Name = nstr; 
X    }
X  virtual void BPress_1_CB(XButtonEvent) { 
X    if (mode > 0 || digit < 10 ) disp->enter(digit); 
X    else XBell(display,-80);
X  }
};
X
static void plus(int &x, int y) { x += y; }
static void minus(int &x, int y) { x -= y; }
static void mult(int &x, int y) { x *= y; }
static void divi(int &x, int y) { if (y == 0) y = 1; x /= y; }
static void divq(int &x, int y) { if (y == 0) y = 1; x %= y; }
static void eq(int &x, int y) { x = y; }
X
static void and(int &x, int y) { x &= y; }
static void or(int &x, int y) { x |= y; }
static void xor(int &x, int y) { x ^= y; }
static void shl(int &x, int y) { x <<= y; }
static void shr(int &x, int y) { x >>= y; }
X
struct op_struct {char *Name; OP opf; };
X
op_struct arith[] = { {"+",plus}, {"-",minus}, {"*",mult}, 
X		       {"/",divi}, {"%",divq}, {"=",eq} };
X
op_struct bitops[] = { {"&",and }, {"|",or   }, { "^", xor},
X		       {"<<",shl}, {">>",shr} };
X
class operator_button : public button {
X  op_struct *opp;
public:
X  operator_button(window & parent, op_struct *op, int w, int h, int x, int y) :
X  button(parent,op->Name,w,h,x,y) { opp = op; }
X  
X  virtual void BPress_1_CB(XButtonEvent) {  
X    disp->operate(opp->opf);
X  }
};
X
#include "calc.icon"
X
// derive to handle keypress events !
class calc_main : public main_window { 
public:
X  calc_main(char *name, int w, int h) : main_window(name,w,h) { 
X    set_icon(icon_bits,icon_width,icon_height);
X    selection_mask |= KeyPressMask;
X  }
X  virtual void KeyPress_CB(XKeyEvent ev) {
X    KeySym keysym = XLookupKeysym(&ev,ev.state & 1);
X    if (isxdigit(keysym & 0xff)) { // 0..F
X      char c2[] = { keysym, 0}; // keysym convert to string
X      disp->enter(strtol(c2,0,16)); // and then to int
X    } else 
X      if (keysym == 0xff0d) disp->operate(eq); // return -> =
X      else
X	for (int op=0; op < 6; op++) { // operators +-*/=%
X	  op_struct *opp = arith+op;
X	  if (keysym == opp->Name[0]) disp->operate(opp->opf);
X	}   
X  }
};
X
main(int , char *argv[]) 
{ 
X  main_window *mainw = new calc_main(argv[0], 220, 300); 
X  disp = new acc_disp(*mainw,200,20,10,10);
X
X  // first column of operators
X  new mode_button(*mainw,30,20,10,40); 
X  new instance_button <acc_disp> 
X                    (*mainw,"CA",&acc_disp::ca,disp,30,20,10,220);
X  new instance_button <acc_disp> 
X                    (*mainw,"CE",&acc_disp::ce,disp,30,20,10,250);
X  digit_butt *db[16];
X  int x = 50, y = 250, dig; 
X
X  for (dig = 0; dig < 0x10; dig++) {
X    db[dig] = new digit_butt(*mainw,dig,20,20,x,y); x+= 30;
X    if (dig % 3 == 0) { x = 50; y -= 30; }
X  }
X
X  // colum with arithmetics
X  new quit_button(*mainw,30,20, 145, 40);
X  y = 70; int op;
X  for (op=0; op < 6; op++) {
X    new operator_button(*mainw,&arith[op],30,20,145,y); y+= 30;
X  }  
X  y = 70; 
X  for (op=0; op < 5; op++) {
X    new operator_button(*mainw,&bitops[op],30,20,180,y); y+= 30;
X  }
X
X  mainw->main_loop();
}
SHAR_EOF
chmod 0644 calc.c ||
echo 'restore of calc.c failed'
Wc_c="`wc -c < 'calc.c'`"
test 5026 -eq "$Wc_c" ||
	echo 'calc.c: original size 5026, current size' "$Wc_c"
fi
# ============= dir-tree.c ==============
if test -f 'dir-tree.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dir-tree.c (File already exists)'
else
echo 'x - extracting dir-tree.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dir-tree.c' &&
// dir-tree.c 
//            wolf 10/95
// very simple demo for the Tree classes in grafix
X
#include "tree.h"
X
// #include "files.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
X
class DirTree;
X
typedef list <DirTree> Dlist;
X
class DirTree : public Tree {
X  char *path;
public:
X  DirTree(char *name, char *path) : Tree(name), path(path) {}
X  // virtual void Press_cb(XButtonEvent *ev) -> todo on button press
X  virtual void Enter_cb(window *infw) { infw->clear(); infw->PlaceText(path); }
};
X
char *help_text[] = { "help me !", 0 };
X
class Dir_main : public Tree_main {
public: 
X  Dir_main(char * WMName, int w, int h, Dlist *dll) : 
X  Tree_main(WMName,w,h, (Tlist *) dll) {
X    new help_button(*mb,"help",help_text);
X  }
X  // virtual void init() { Tree_main::init(); }
};
X
// recursively read directory tree, "dll" is linear list
// parent the parent Node 
void rec_dir(char *path, Dlist* &dll, DirTree* parent) {
X  printf("reading directory %s\n",path);
X  DIR *dirp = opendir(path);
X  if (dirp == 0) printf("can't open %s\n",path);
X  struct dirent *dp; 
X  for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X    int length = strlen(dp->d_name);
X    if (dp->d_name[length-1] != '.') { // not for . or .. file
X      int plen = strlen(path); 
X      if (path[plen-1] == '/') path[plen-1] = 0; // eliminate tail-slashes
X      char *fina = new char[length+strlen(path)+2];
X      sprintf(fina,"%s/%s",path,dp->d_name); // complete path
X      struct stat st;
X      if (!stat(fina, &st) && S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) {
X	// *** problem with symbolic links : how to exclude ???? ***
X	// printf("reading directory %s %o\n",fina,st.st_mode);
X	char *tail = strrchr(fina,'/'); // eliminate trailing path
X	if (tail == 0) tail = fina; else tail++;
X	DirTree *dt = new DirTree(tail,fina);
X	dll = dll->push(dt); // append to linar list
X	parent->children = parent->children->push(dt); // updtate parent list
X	rec_dir(fina,dll,dt);
X      }
X    }
X  }
X  closedir(dirp);
}
X
// if commandline arg given use it as search path, else use ".."
int main(int argc, char* argv[]) {
X  char *path = (argc > 1) ? argv[1] : ".."; //getenv("HOME");
X  DirTree *top = new DirTree(path,path);
X  Dlist *alldirs = new Dlist(top); // the top of the tree
X  rec_dir(path,alldirs,top);
X  Dir_main *mw = new Dir_main(argv[0],400,450,alldirs);
X  mw->init();
X  mw->main_loop();
}
SHAR_EOF
chmod 0644 dir-tree.c ||
echo 'restore of dir-tree.c failed'
Wc_c="`wc -c < 'dir-tree.c'`"
test 2455 -eq "$Wc_c" ||
	echo 'dir-tree.c: original size 2455, current size' "$Wc_c"
fi
# ============= pal-demo.c ==============
if test -f 'pal-demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping pal-demo.c (File already exists)'
else
echo 'x - extracting pal-demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pal-demo.c' &&
#include "window.h"
#include "palette.h"
X
main() {
X  main_window mw("palette",220,60);
X  palette_popup *pp = new palette_popup(100);
X  palette_popup *pp2 = new palette_popup(100);
X
X  popup_button pb(mw,pp,"popup 1",100,20,10,0); 
X  popup_button pb2(mw,pp2,"popup 2",100,20,110,0);
X  quit_button qb(mw,100,20,60,30);
X  mw.main_loop();
}
SHAR_EOF
chmod 0755 pal-demo.c ||
echo 'restore of pal-demo.c failed'
Wc_c="`wc -c < 'pal-demo.c'`"
test 336 -eq "$Wc_c" ||
	echo 'pal-demo.c: original size 336, current size' "$Wc_c"
fi
# ============= lat-demo.c ==============
if test -f 'lat-demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping lat-demo.c (File already exists)'
else
echo 'x - extracting lat-demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'lat-demo.c' &&
#include "lattice.h"
X
int nx, ny;
float *qexp,*qsin,*qigl;
X
void compute() {
X  float (*aexp)[ny] = (float (*)[ny]) qexp;
X  float (*asin)[ny] = (float (*)[ny]) qsin; 
X  float (*aigl)[ny] = (float (*)[ny]) qigl;
X  int x,y;
X  for (x = 0; x < nx; x++) { 
X    float xp = ((float) x)/nx - 0.5;  // Intervall [-0.5 .. +0.5]
X    for (y = 0; y < ny; y++) { 
X      float yp = ((float) y)/ny - 0.5;
X      float r = sqrt(SQR(xp) + SQR(yp));    
X      aexp[x][y] = exp (-10*r*r); // alle Funktionen auf 1.0 normiert
X      asin[x][y] = .25 * (1.0 + cos(15*r)); // auf 0.5 normiert
X      float rad = 1 - SQR(xp*2) - SQR(yp*3);
X      aigl[x][y] = (rad < 0) ? 0 : sqrt(rad);
X    } 
X  }
}
X
lattice_manager *lm;
X
void selexp() { lm->qptr = qexp; lm->redraw();}
void selsin() { lm->qptr = qsin; lm->redraw();}
void seligl() { lm->qptr = qigl; lm->redraw();}
X
// only needed to have an action method for the radio_menu "nx"
class main_action_window : public main_window { 
public:
X  main_action_window(char *Name, int w, int h) : main_window(Name,w,h) {}
X  virtual void action(char *menu, char *value) 
X    { nx = ny = atoi(value); 
X      compute();
X      lm->respace(nx, ny); // redraws the lattice
X      lm->redraw_clones();
X    } 
};
X
int main (int argc, char * argv[]) {
X  int ww = 450, wh = 500, bh = 20;
X  main_window * mainw = new main_action_window(argv[0], ww, wh);
X
X  nx = ny = 10;
X  qexp = new float[10000]; // [nx*ny];
X  qsin = new float[10000]; // [nx*ny];
X  qigl = new float[10000]; // [nx*ny];
X  compute();
X  menu_bar *mb = new menu_bar(*mainw,ww,bh,0,0,70,100,0);
X  lm = new lattice_manager(*mainw,ww,wh-bh,0,bh,nx,ny,qexp);
X
X  struct but_cb m_list[] = {{"gauss",selexp}, {"sin",selsin}, {"iglo",seligl}};
X  make_pulldown_menu(*mb,"menu",3,m_list);
X  char *nx_list[] = {"3","5","10","15","20","25","30","40","50","60","80",0};
X  make_radio_menu(*mb,"nx",nx_list,mainw);
X  new quit_button(*mb);
X
X  mainw->main_loop();
}
SHAR_EOF
chmod 0644 lat-demo.c ||
echo 'restore of lat-demo.c failed'
Wc_c="`wc -c < 'lat-demo.c'`"
test 1914 -eq "$Wc_c" ||
	echo 'lat-demo.c: original size 1914, current size' "$Wc_c"
fi
# ============= lat2demo.c ==============
if test -f 'lat2demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping lat2demo.c (File already exists)'
else
echo 'x - extracting lat2demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'lat2demo.c' &&
/* lat2demo.c : wolf 10/94
X   demonstrates the use of lattice_manager class
X   generates pictures of two functions inside one main window, each having
X   its own lattice-manager functionality buttons for manipulating
*/
#include "lattice.h"
X
// computes the function values as twodim. arrays for two function types
void compute(int typ, float *q, int nx, int ny) {
X  float (*qq)[ny] = (float (*)[ny]) q; // type cast from float* -> float(*)[ny]
X  int x,y;
X  for (x = 0; x < nx; x++)  
X    for (y = 0; y < ny; y++) { 
X      float r = sqrt(SQR(x-nx/2) + SQR(y-10));    
X      switch (typ) {
X      case 1:  
X	qq[x][y] = exp (-r*r/10); break;
X      case 2:
X	qq[x][y] = 0.3*(1 + sin(r)); break;
X      }
X    } 
}
X
int main (int argc, char * argv[]) {
X  lattice_manager *lm1,*lm2;
X  int ww = 905, wh = 400;
X
X  main_window *mainw = new main_window(argv[0], ww, wh);
X  
X  int nx = 20, ny = 20;
X  float *q1 = new float[nx*ny];
X  compute(1,q1,nx,ny);
X  lm1 = new lattice_manager(*mainw,ww/2-2,wh-2,0,0,nx,ny,q1);
X  new quit_button(*lm1,60,20,0,0);
X
X  float *q2 = new float[nx*ny];
X  compute(2,q2,nx,ny);
X  lm2 = new lattice_manager(*mainw,ww/2-2,wh-2,ww/2,0,nx,ny,q2);
X  lm2->body = False;  // set to grid-mode for this function initially
X
X  mainw->main_loop();
X  delete[] q1;  delete[] q2; 
}
SHAR_EOF
chmod 0644 lat2demo.c ||
echo 'restore of lat2demo.c failed'
Wc_c="`wc -c < 'lat2demo.c'`"
test 1283 -eq "$Wc_c" ||
	echo 'lat2demo.c: original size 1283, current size' "$Wc_c"
fi
# ============= one-dim.c ==============
if test -f 'one-dim.c' -a X"$1" != X"-c"; then
	echo 'x - skipping one-dim.c (File already exists)'
else
echo 'x - extracting one-dim.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'one-dim.c' &&
// pde.c 
//                     wolf 5/94
//       test of integrations of advection partial differential eq.
//       quadv1 : Smolarkievicz method
X
// #include <math.h>
// #include <stdlib.h>
#include <stdio.h>
X
// methods and externals from "solver.c"
void smolarkievicz(int i, int j);
void simple(int i, int j);
void lax_wendroff(int x1,int x2);
void diffusion(double diff, int i, int j);
extern int nx;
extern double *u, *q, dx, dt;
X
char * method_list[] = { "simple upstream", "Smolarkievicz","Lax-Wendroff",0 };
void (*method[])(int,int) = { simple, smolarkievicz, lax_wendroff };
X
#include "window.h"   
X
// !! attn :
// this strings serve as pointers to compare in the action method
// ie. they have to be passed as pointers, because no strcmp takes place
char *dt_menu = "dt", *nt_menu = "nt",
X     *breadth_menu = "breadth", *nx_menu = "nx",
X     *method_menu = "method", *diff_menu = "diff";
X
// user-defined class :
// only obligatory virtual functions are : 'draw_interior' && 'action' 
class pde_window : public coord_window {
X  int nt, breadth, nmeth; // method-index 
X  int breadth_old, nmeth_old, nx_old; // store old values to know when to reset inits
X  double dt_old, total;
X  int sx, tt;
X  int istart,iend; // Impuls Start & Ende
X  char headline[200]; 
X  double diff;
X public: 
X  int show_ratio;  
X  set_inits() { 
X    int i; istart = 5; iend = istart + breadth - 1;
X    for (i = 0; i < nx; i++) q[i]= 1e-20; // to avoid division overflow  
X    for (i = istart; i <= iend; i++) 
X      q[i] = 100.0; // initial : step function
X    tt = 0; total = 0; // total integrated time
X  };
X  
X  // integrate nt time steps   
X  integrate() { 
X    int i;
X    for (i=0; i < nt; i++) { 
X      if (diff > 0.0) diffusion(diff,0,nx);
X      (*method[nmeth]) (0, nx); 
X
X    }
X    tt += nt; total += dt*nt;
X  }
X
X  pde_window(window & parent, int w, int h, int x, int y) :
X    coord_window(parent,w,h,x,y)
X    { set_inits();
X      nx = 100; nt = 10; dt = 0.1; breadth = 10; nmeth = 1; // 
X      show_ratio = 0; diff = 0.0;
X    }
X   
X  void draw_interior() { // virtual fn must be defined : draws window content
X    sx = w_eff / nx; // to make it integer
X    
X    define_coord(0., 0. , nx, 150.);
X    draw_coords(); 
X    x_ticks((nx < 200) ? 1.0 : 5.0); 
X    y_ticks(10.0);
X    wline(0, 100.0, nx, 100.0);
X
X    if ((breadth != breadth_old) || (nx != nx_old) || (nmeth != nmeth_old)) 
X      set_inits();
X
X    breadth_old = breadth; dt_old = dt; nmeth_old = nmeth; nx_old = nx;
X
X    sprintf(headline,"'%s' with dt =%5.2f nt = %d nx = %d breadth = %d"
X	    "diff = %.2f tt = %d time = %.2f",
X	    method_list[nmeth], dt, nt, nx, breadth, diff, tt, total);  
X    
X    // printf("%s\n",headline);
X    PlaceText(headline,0,20);
X
X    // display of the theoretical pulse intervall below t axis
X    int x1,x2;
X    float pp = u[0] * total;  		 // cumulative way
X    x1 = x_window(pp + istart - 0.5) % w_eff;  // start of pulse
X    x2 = x_window(pp + iend + 0.5) % w_eff;    // end of pulse
X    if (x2 >= x1) rline(x1, -10, x2, -10); else	
X       { rline(x1, -10, w_eff, -10); rline(0, -10, x2, -10); }
X
X    // draw results
X    graph(nx,q);
X    if (show_ratio) {
X      double rat[nx]; int i;
X      for (i=0; i< nx;i++) { 
X        rat[i] = 50.0*q[(i+1) % nx]/q[i];
X        if (rat[i] > 10000) rat[i] = 0; 
X      }
X      graph(nx,rat);
X    }
X  }
X  
X  // main method "action" : called from radio_buttons of the radio_menus
X  // comparing string pointers DIRECTLY with menu names !!
X  // to find which menu was activated 
X
X  void action(char * menu, char * value) { 
X    // printf("action %s %s\n", menu,value); 
X    if (menu == dt_menu) dt = atof(value); else
X      if (menu == nt_menu) nt = atoi(value); else
X	if (menu == breadth_menu) breadth = atoi(value); else
X	  if (menu == nx_menu) nx = atoi(value); else
X	    if (menu == method_menu) {
X	      int i = 0; char *ms;
X	      do { 
X                // find method with comparing the string pointer in list
X		ms = method_list[i];
X		if (value == ms) nmeth = i; 
X		i++;
X	      } while (ms); 
X	    } else 
X	      if (menu == diff_menu) diff = atof(value);
X		else printf("error: wrong menu %s\n", menu);
X    		// nur bei Programmierfehlern !
X    redraw();
X  }
X  void data_dump() { // print state vector to file
X    FILE *fp; 
X    int i; 
X    char fname[20];
X    sprintf(fname,"data-dump.%d",tt);
X    printf("writing data dump to file '%s'\n",fname); 
X    fp = fopen(fname,"w"); 
X    fprintf(fp,"%s\n",headline);
X    for (i=0; i<nx; i++) {       
X      if (i % 8 == 0) fprintf(fp,"\n");
X      fprintf(fp,"%10.6f",q[i]);
X    }
X    fclose(fp);
X  }
};
X
extern "C" usleep(unsigned usecs); // sleep mikrosecs 
X
pde_window * pwindow;
X
void quit() { exit(0); }
void integrate() {   
X   pwindow->WatchCursor(); 
X   pwindow->integrate(); pwindow->redraw(); 
X   pwindow->ResetCursor();
}
void re_init() { pwindow->set_inits(); pwindow->redraw(); }
void data_dump() { pwindow->data_dump(); }
void toggle_ratio() { pwindow->show_ratio ^= 1; pwindow->redraw(); }
X
void animate() { 
X  int i;
X  for (i=0; i<100; i++) { integrate(); /* usleep(1000); */ } 
}
X
// derive a special class to use polling handler for running 
class one_main : public main_window {
public:
X  int *pmode; // pointer to protected variable
X  one_main(char *name, int w, int h) : main_window(name,w,h) { 
X    pmode = &polling_mode; 
X  }
X  virtual void polling_handler() { integrate(); }
};
X
int main (int argc, char * argv[]) 
{ 
X  int ww = 650, wh = 300, bh = 24;
X
X  one_main mainw(argv[0], ww, wh);
X
X  menu_bar mb(mainw, ww, bh , 0, 0, 50, 100, 0); // to place all buttons here
X				// minw = maxw : equal sized buttons
X  struct but_cb pd_list[] = { {"re-init",re_init }, {"one step", integrate},
X			      {"100 steps",animate},  {"quit", quit } };
X  button * menu = make_pulldown_menu(mb, "  menu  ", 4, pd_list); 
X  char * mhelp[] = {
X    "menu serves to select some actions :",
X    "'re-init'  : resets to starting values of integration",
X    "'one step' : integrates 'nt' time steps",
X    "'100 steps': integrates 100 * nt time steps, ",
X    "'quit'     : terminates the program", 0}; 
X
X  menu->add_help(mhelp);
X  
X  int i;
X
X  double u0;
X  int nx_max = 1000; 
X
X  q = new double[nx_max]; // global result vector
X  u = new double[nx_max]; // global velocity vector
X  u0 = 1.0;  dx = 1.0; 
X 
X  for (i=0; i < nx_max; i++) u[i] = u0;
X
X  pwindow = new pde_window (mainw, ww, wh-bh, 0, bh + 2);
X
X  // Menu zur dt-Umschaltung
X  char *dt_list[] = { "0.01","0.02","0.05","0.1","0.2","0.4","0.5",
X		      "0.6","0.7","0.8","0.9","1.0","1.1",0};
X  char *dt_help[] = { "time step value [s] for a single step of integration",
X		      "equals 'alpha', since dx = v = 1.0 is used",0};
X  make_radio_menu(mb, dt_menu, dt_list, dt_help, pwindow);
X
X  char *nt_list[] = {"1","2","3","5","10","30","100","1000","10000",0};
X  char *nt_help[] = {"number of single step to integrate,", 
X		     "befor the graph is drawn again","",0};
X  make_radio_menu(mb, nt_menu, nt_list, nt_help, pwindow);
X  
X  char *nx_list[] = {"10","20","30","50","80","100","200","300","500",0};
X  char *nx_help[] = {"number of discretization intervalls for x",
X		     "if the value is changed the integration is restarted",
X		     "automatically", 0}; 
X  make_radio_menu(mb, nx_menu, nx_list, nx_help, pwindow);
X 
X  char *breadth_list[] = {"1","2","3","4","5","7","10","20","30","50","80","100",0};
X  char *breadth_help[] = {"the breadth of the initial step function",
X			  "given in count of dx steps",
X			  "changing forces restart",0};
X  make_radio_menu(mb,breadth_menu, breadth_list, 
X		  breadth_help, pwindow);
X    
X  char *diff_list[] = { "0","0.01","0.02","0.05","0.1","0.2","0.4","0.5",
X		        "0.6","0.7","0.8","1.0","2.0",0};
X  char *diff_help[] = { "diffusion coefficient", 0};
X  make_radio_menu(mb, diff_menu, diff_list, diff_help, pwindow);
X
X  char *method_help[] = {"selection of integration method ",
X			 " * simple upstream",
X			 " * Smolarkievicz",
X			 " * Lax-Wendroff",
X			 0}; 
X  make_radio_menu(mb,method_menu,method_list, method_help, pwindow);
X   
X  new toggle_button(mb,"run",mainw.pmode); // toggles between run/stop
X
X  callback_button data(mb,"data dump",data_dump);
X  callback_button ratio(mb,"ratio",toggle_ratio);
X
X  char * help[] = {
X    "Changing of parameters with the pulldown-menues in this menue-line ",
X    "that are activated with the left mouse button","",
X    "Button 'run' starts integration, press it again to stop.","",
X    "To get explanations for the individual menues,",
X    "press the right mouse button on the field.",0};
X
X  help_button hb(mb,"help",help);
X  quit_button qb(mb);
X
X  mainw.main_loop();
}
X  
SHAR_EOF
chmod 0644 one-dim.c ||
echo 'restore of one-dim.c failed'
Wc_c="`wc -c < 'one-dim.c'`"
test 8600 -eq "$Wc_c" ||
	echo 'one-dim.c: original size 8600, current size' "$Wc_c"
fi
# ============= two-dim.c ==============
if test -f 'two-dim.c' -a X"$1" != X"-c"; then
	echo 'x - skipping two-dim.c (File already exists)'
else
echo 'x - extracting two-dim.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'two-dim.c' &&
// two-dim.c : two dimensional compution of advection equation
// using different integration methods a
// and graphic display with the lattice class
X
#include "lattice.h"
#include "smolark.h"
#include <math.h>
X
#define Pi 3.14159265358979323846
X
char * method_list[] = { "smolark", "smolark_wrap","simple",0 };
void (*method[]) (float *qp, float *up, float *vp, float dt, int nx, int ny, 
X		  int,int,int,int) = { smolark, smolark, simple };
X
char *dt_menu = "dt", *nt_menu = "nt",
X     *breadth_menu = "breadth", *nx_menu = "nx",  *ny_menu = "ny", 
X     *dir_menu = "direction", *method_menu = "method", *run_menu = "n steps";
X
class two_dim;
// to display the headline : use pixmap_window to avoid flickering
class head : public pixmap_window { 
X  two_dim  * td;
public:
X  head(window &parent,two_dim  * td, int w, int h, int x, int y);
X  virtual void draw_interior() ;
};
X				
class two_dim : public lattice_manager {
X  head * headline;
X  char headstr[200];
X  float *qp, *up, *vp; 
X  int istart,iend,jstart,jend,tt,nt,nq,breadth,nmeth;
X  int breadth_old,nmeth_old,nx_old;
X
X  float dt,total; // time step, total elapsed time
X  float xctr,yctr; // coordinates of pulse
X  int  direction; // angle of wind flow (in degrees 0..360)
X
X  float &u(int i, int j) { return *(up + ny*i + j); }
X  float &v(int i, int j) { return *(vp + ny*i + j); }
X  float &q(int i, int j) { return *(qp + ny*i + j); }
X
public:
X  char * headprint() {
X    sprintf(headstr,"%s dir = %d dt= %5.2f nt = %d tt= %d time = %7.2f",
X	    method_list[nmeth],direction,dt,nt,tt,total); return headstr;
X  }
X  void set_inits() { // set q to initial values for restart
X    int i,j; 
X    istart = nx/10; jstart = ny/10; 
X    iend = istart + breadth+1; jend = jstart + breadth+1;
X    for (i=0; i<nx; i++) for (j=0; j<ny; j++) { 
X      // initial step function computed from global (xstart, xend)
X      // step value proportional to nx/2, only for lattice-display form
X      q(i,j) = (i>istart && i<iend && j>jstart && j<jend) ? 1 : 0.1;
X    }
X    total = 0.0; // total integrated time
X    tt = 0;
X    // alpha = (direction - 90)/grd2rad; // viewpoint for lattice from the side
X    alpha = 30/grd2rad; beta = 60/grd2rad; // starting values for projektion.
X    xctr = istart; yctr = jstart;  
X  }
X  void init_uv() { // set stream field according to angle, |u*u + v*v| == 1.0
X    int i,j; 
X    float a = cos(direction/grd2rad), b = sin(direction/grd2rad);
X    for (i=0; i<nx; i++) for (j=0; j<ny; j++) {
X      u(i,j) = a; v(i,j) = b; }
X  }  
X
X  void new_arrays() { // create new arrays on the heap and initialize them   
X    qp = new float[nx*ny]; 
X    up = new float[nx*ny]; vp = new float[nx*ny];
X    init_uv();
X    set_inits();
X    qptr = qp; 
X  }
X
X  two_dim(window &parent, int w, int h, int x, int y, int nx, int ny)
X    : lattice_manager(parent, w, h-20,x, y+20, nx, ny, NULL) {
X    headline = new head(parent,this,w,20,x,y);
X    dt = 0.1; nt = 1; breadth = 5; direction = 45; 
X    new_arrays();
X    nmeth = 0; // Start with smolarkievicz as default
X    // headline->CB_info = 1;
X  }
X
X  void redraw() {
X    lattice_manager::redraw();
X    region_int->mark_rect(xctr,yctr,breadth,breadth);  
X  }
X
X  void integrate() { 
X    WatchCursor();
X    int i; for (i=0; i<nt; i++) (*method[nmeth])(qp,up,vp,dt,nx,ny,0,nx,0,ny); 
X    tt += nt; total += dt*nt;
X    xctr += u(0,0)*dt*nt; yctr += v(0,0)*dt*nt; // nur fuer konstante u,v 
X    ResetCursor();
X  }
X  
X  // main method "action" : called from radio_buttons of the radio_menus
X  // comparing string pointers DIRECTLY with menu names !!
X  // to find which menu was activated 
X
X  void action(char * menu, char * value) { 
X    //   printf("action menu = %s value = %s\n", menu,value); 
X    if (menu == dt_menu) dt = atof(value); else
X      if (menu == nt_menu) nt = atoi(value); else
X	if (menu == breadth_menu) breadth = atoi(value); else
X	  if (menu == nx_menu || menu == ny_menu) { 
X	    if (menu == nx_menu) nx = atoi(value); else ny = atoi(value);  
X	    delete qp; delete up; delete vp;
X	    new_arrays();
X	    respace(nx,ny);
X	  }
X	  else
X	    if (menu == method_menu) {
X	      int i = 0; char *ms;
X	      do { 
X		// find method with comparing the string pointer in list
X		ms = method_list[i];
X		if (value == ms) nmeth = i; 
X		i++; }  while (ms); 
X	    } else 
X	      if (menu == dir_menu) 
X		{ direction = atoi(value); init_uv(); }
X	      else
X		if (menu == run_menu)
X		  { int i,n = atoi(value);
X		    for(i=0;i<n;i++) { integrate(); redraw_all(); } 
X		    return; } 
X		else 
X		  printf("error: wrong menu %s\n", menu);
X    if ((menu == breadth_menu) || (menu == method_menu)) set_inits(); 
X    redraw_all();
X  }
X
X  void redraw_all() { 
X    headline->redraw(); redraw_clones();
X  }
X
X  // ein popup-Window mit dem aktuellen Funktionsbild erzeugen -> snapshot
X  void spawn() {
X    // das popup hat dieselbe Groesse wie das momentane und den Kopf als Name
X    float *qspawn = new float[nx*ny]; 
X    int i; // Erzeugen einer Kopie des Feldes : 
X    for (i=0; i<nx*ny; i++) qspawn[i] = qptr[i];
X    lattice_manager *snap = make_popup(headstr,qspawn);
X    main_window *pp = snap->mainw;
X    // der delete_button sollte auch noch "delete [] qspawn" ausloesen ! 
X    new delete_button (*pp,pp,100,20,0,0);
X    pp->do_popup(0,0); // realize it
X  }
X
};
X
// definition of methods follows here, since declaration of two_dim is used
head::head(window &parent, two_dim *td, int w, int h, int x, int y):
X      pixmap_window(parent,w,h,x,y,0), td(td) { }	
// compute new string and display it 
void head::draw_interior() { PlaceText( td->headprint() ); }
X	
two_dim *two;
X
void re_init() { two->set_inits(); two->redraw_all(); }
void step() { two->integrate(); two->redraw_all();}
X
void snapshot() { two->spawn(); }
X
// derive a special class to use polling handler for running 
class two_main : public main_window {
public:
X  int *pmode; // pointer to protected variable
X  two_main(char *name, int w, int h) : main_window(name,w,h) { 
X    pmode = &polling_mode; 
X  }
X  virtual void polling_handler() { step(); }
};
X
int main (int argc, char * argv[]) {
X  int ww = 560, wh = 500, bh = 20;
X  
X  two_main mainw(argv[0], ww, wh);
X  menu_bar mb(mainw,ww,bh,0,0,20,80,0);
X
X  callback_button reinit(mb,"re-init",re_init);
X  two = new two_dim(mainw,ww,wh-bh,0,bh+2,20,20);
X
X  char *dt_list[] = { "0.01","0.02","0.05","0.1","0.2","0.4","0.5",
X		      "0.6","0.7","0.8","0.9","1.0",0};
X  char *dt_help[] = { "time step value [s] for a single step of integration",
X                     "equals 'alpha', since dx = v = 1.0 is used",0};
X
X  make_radio_menu(mb, dt_menu, dt_list, dt_help, two);
X
X  char *nt_list[] = {"1","2","3","5","8","10","20","30","50","80","100",0};
X  char *nt_help[] = {"number of single step to integrate,", 
X		     "befor the graph is drawn again","",0};
X  make_radio_menu(mb, nt_menu, nt_list, nt_help, two);
X  
X  char *nx_list[] = {"10","20","30","50","80","100","200","300",0};
X  char *nx_help[] = {"number of discretization intervalls for x",
X		     "if the value is changed the integration is restarted",
X		     "automatically", 0};
X  make_radio_menu(mb, nx_menu, nx_list, nx_help, two); 
X  char *ny_list[] = {"3","5","10","15","20","30","50","80","100","200",0};
X  make_radio_menu(mb, ny_menu, ny_list, nx_help, two);
X
X  char *breadth_list[] = {"1","2","3","4","5","7","10","20","30","50","80",0};
X  char *breadth_help[] = {"the breadth of the initial step function",
X			  "given in count of dx steps",
X			  "changing forces restart",0};
X
X  make_radio_menu(mb,breadth_menu, breadth_list, 
X		  breadth_help, two);
X  char *dir_list[] = {"0","5","10","15","20","30","40","45",0};
X  char *dir_help[] = {"angle of wind direction in grd", 
X		      "0 : in x-direction, 90 : in y-direction",0};
X  make_radio_menu(mb, dir_menu, dir_list, dir_help, two);
X  
X  char *method_help[] = {"selection of integration method ",
X			 " * simple upstream",
X			 " * Smolarkievicz",
X			 0}; 
X  make_radio_menu(mb,method_menu,method_list, method_help, two);
X   
X  new toggle_button(mb,"run",mainw.pmode); // toggles between run/stop
X
X  char *run_list[] = {"5","10","20","30","50","80","100","150","200",0};
X  char *run_help[] = {"integrates the given number of time steps",0};
X  make_radio_menu(mb, run_menu, run_list, run_help, two);
X  
X  callback_button snapshot(mb,"snapshot",&snapshot); 
X  char *snap_help[] = {"'snapshot' spawnes a copy of the actual picture ",
X		       "as permanent lattice_manager window, ",
X		       "that will not be integrated further",0};    
X  snapshot.add_help(snap_help);
X
X  char * help[] = {
X    "Changing of parameters with the pulldown-menues in this menue-line ",
X    "that are activated with the left mouse button","",
X    "Button 'run' starts integration, press it again to stop.","",
X    "To get explanations for the individual menues,",
X    "press the right mouse button on the field.",0};
X
X  help_button hb(mb,"help",help);
X  quit_button qq(mb);
X
X  mainw.main_loop();
X
}
X
X
SHAR_EOF
chmod 0644 two-dim.c ||
echo 'restore of two-dim.c failed'
Wc_c="`wc -c < 'two-dim.c'`"
test 8900 -eq "$Wc_c" ||
	echo 'two-dim.c: original size 8900, current size' "$Wc_c"
fi
# ============= clock-demo.c ==============
if test -f 'clock-demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping clock-demo.c (File already exists)'
else
echo 'x - extracting clock-demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'clock-demo.c' &&
/* clock.c : wolf 6/95
X   demo for the use of clock_win 
X   display two clocks for different timezones
*/
X
#include "window.h"
#include <sys/types.h>
#include <sys/time.h>
X
clock_win *clck1, *clck2;
X
extern "C" void sleep(int);
int ticker1 = 0, ticker2;
X
class clock_main_window : public main_window {
public:
X  clock_main_window(char *Name, int w, int h) : main_window(Name,w,h) { 
X    polling_mode = True; 
X  }
X  virtual void polling_handler() {
X    if (ticker1) sleep(1); // not at first, then sleep for 1 secs
X    time_t secs =  time(0); // seconds from 1.1.1970
X    struct tm *loc = localtime(&secs); // transform to local time
X    ticker1 =  loc->tm_sec + 60*(loc->tm_min + 60*loc->tm_hour);
X    // printf(" %d\n",ticker);
X    ticker2 = ticker1 - 8*3600; // 8hrs back
X    clck1->redraw(); clck2->redraw(); 
X  }
};
X
int main(int argc, char *argv[]) {
X  main_window *mw = new clock_main_window(argv[0],100,300);
X  int y = 0;
X  clck1 = new clock_win(*mw, &ticker1,100,100,0,0); y+= 110;
X  new text_win(*mw,"GMT",80,20,10,y,1); y+= 30;
X  clck2 = new clock_win(*mw, &ticker2,100,100,0,y); y+= 110;
X  new text_win(*mw,"New York",80,20,10,y,1); y+= 30;
X  new quit_button(*mw,80,20,10,y);
X  mw->main_loop();		     
}
SHAR_EOF
chmod 0644 clock-demo.c ||
echo 'restore of clock-demo.c failed'
Wc_c="`wc -c < 'clock-demo.c'`"
test 1215 -eq "$Wc_c" ||
	echo 'clock-demo.c: original size 1215, current size' "$Wc_c"
fi
# ============= three-dim.c ==============
if test -f 'three-dim.c' -a X"$1" != X"-c"; then
	echo 'x - skipping three-dim.c (File already exists)'
else
echo 'x - extracting three-dim.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'three-dim.c' &&
// three-dim.c :                 wolf 7/95
// demo-program for the integrator and video functionality of grafix
// invokes "wave.c" (threedim wave function integrator) interactively
// may be considered as frame for hooking own applications 
// the saved files may be reviewed with program "replay"
// if a command line argument is given it is used as base-filename, 
// else the progname is used to build a name "base.video"
//
X
#include "animator.h"
X
// interface description for three-dim
// for linking with other integration sources :
// replace wave_* with your function names
X
#include "three-nxnynz.h"
X
extern void wave_init(int*); // the initialization part of the integrator
extern void wave_step(int*); // integration time step of 
extern void wave_exit();     // for cleanup
X
extern double t[NZP2][NYP2][NXP2];
X
char *three_help[] = {
X  "'three-dim' serves as reference program for binding other integration",
X  "programs (even Fortran programs) with the Grafix user interface.","",
X  "Please start the integration (with '>>') and let it run for some seconds.",
X  "It produces the output file 'three-dim.video' which is viewed with 'replay'",
X  "","The other buttons :",
X  "'rotate' lets the view rotate around z-axis, to stop press it again",
X  "'layer' selects a z-array to display","'reinit' resets all to t = 0",
X  "'>' makes one integration step","'||' stops the running integration",
X  "'spawn' opens another window to enable viewing several z-layers at once",0 };
X  
class three_integrator : public integrator {
public:
X  three_integrator(char *fina, char *video_file) :
X    integrator(fina,video_file,NXP2,NYP2,100) { // every 100 sec write video
X    d2disp *tdisp = new d2disp[NZP2]; 
X    int i, nz =  3 <? NZP2; // only max. 3 arrays to save disk space
X    for (i=0; i < nz; i++) { 
X      tdisp[i].name = new char[20]; sprintf(tdisp[i].name,"t layer %d",i);
X      tdisp[i].array.darr = (double*) t[i]; 
X      tdisp[i].gamma = 0.02; tdisp[i].z0 = 0;
X      tdisp[i].array_mode = ARRAY_NY_NX | ARRAY_DOUBLE;
X    }
X    // there might be up to 10 columns added to the menu (and saved)
X    add_column("layer", nz , tdisp); 
X    sprintf(header,"three-dim demo");
X    new help_button(*mb,"help",three_help);
X    start();
X  }
X  // the virtual functions to define, itime is the actual time in seconds
X  // to be updated from the step-function (wave_step)
X  virtual void init_solver() { wave_init(&itime); }
X  virtual void step_solver() { wave_step(&itime); }
X  virtual void exit_solver() { wave_exit(); }
};
X
X
int main(int argc, char *argv[]) {
X  // if a command line argument is given it is used as base-filename for 
X  // the video file else the progname is used
X  char *fina = (argc > 1) ? argv[1] : argv[0]; 
X  char video_file[100]; // the name of the file to save video to 
X  sprintf(video_file,"%s.video",fina); // is named eg. "three_dim.video"
X
X  new three_integrator(fina, video_file);
X
}
SHAR_EOF
chmod 0644 three-dim.c ||
echo 'restore of three-dim.c failed'
Wc_c="`wc -c < 'three-dim.c'`"
test 2910 -eq "$Wc_c" ||
	echo 'three-dim.c: original size 2910, current size' "$Wc_c"
fi
# ============= replay.c ==============
if test -f 'replay.c' -a X"$1" != X"-c"; then
	echo 'x - skipping replay.c (File already exists)'
else
echo 'x - extracting replay.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'replay.c' &&
// replay.c
//     wolf 7/95
// C++-main program with grafix-display to show stored lattice animations
// (video files)
// some arrays of one file may be visited simultaniously (spawn button)
// also different files may be visited synchron (synchron button) :
// (the program may start another image (with diff. video file) that
//  runs synchronously with the master via a pipe)
// programmer attn: the started image must not use the scrollbars !
X
#include "animator.h"
#include "files.h"
#include <unistd.h>
X
// can serve either as master or slave 
class replayer : public player, public stepper, public master, public slave {
X  Bool top_proc;
X  int istep_act;
X  int itime; // global time in seconds , read from video file
X  char *prg_name; // got from argv[0]
X  play_scrollbar *pl_scrb;
public:
X  replayer(animator *animp, char *argv0, Bool top = False) :
X  player(animp,&itime,top), master(), slave(), prg_name(argv0) {   
X    init_lat();
X    top_proc = top;
X    if (! top) step_mode = polling_mode = True; 
X    // I am a process driven from the pipe
X    seek_step(0);
X
X    if (top)  // a scrollbar only on the top window 
X      pl_scrb = new play_scrollbar(*this, width, 0, 0, 11, this, 0, 
X				   animp->nsteps, 0);
X  }
X  
X  // the 2 members for stepper : must be redefined !!
X  virtual void seek_step(int istep) { 
X    istep_act = istep; // for start_synchron
X    make_step(istep);
X  } 
X  
X  VVP stepfn; void *stepptr; 
X  // the stepfn is passed as parameter of play_mode and invoked from 
X  // the polling_handler
X
X  virtual Bool switch_play_mode(VVP step, void *vp) {
X    step_mode = ! step_mode; pmset();
X    stepfn = step; stepptr = vp;
X    return(step_mode);
X  } 
X  
X  virtual void step_handler() {  
X    if (top_proc) { 
X      if (animp->eof) { stop(); return; } else (*stepfn)(stepptr); }
X    else pstep();
X  }
X  
X  // virtual fn for slaves
X  virtual int make_step(int istep) { // read current record and display it
X    animp->seek(istep);
X    if (animp->eof) return 1; 
X    int it = animp->read_step(); 
X    if (it > 0) itime = it; // else read error or eof
X    if (animp->eof) return 1; 
X
X    static Bool reinit = False; // first call is init
X    if (reinit) 
X      lat->redraw_spawned(); 
X    else reinit = True;  // second call is reinit
X    synchronize(istep); // master fn
X    return 0;
X  }
X  
X  // create a new Unix-process running the same program with selected file
X  // ( with argument -pipe -> without the play buttons)
X  // but synchronized with the current window display via a pipe & signals
X  void start_command() { 
X    char *defname = "*.video"; char fina[100];
X    if (spipe) return; // only one possible
X    FILE *fload = open_file_interactive(defname,fina,MODE_READ);
X    if (fload == NULL) return; // aborted
X    fclose(fload);
X
X    char path[200]; // get the path of the current prog.
X    // start the new process as pipe with command -pipe
X    if (prg_name[0] == '/')  // absolute path beginning with /
X      strcpy(path,prg_name);
X    else {
X      getcwd(path,200); // concat pwd + path
X      sprintf(path+strlen(path),"/%s",prg_name);
X    }
X    printf("%s\n",path);
X
X    char command[200]; sprintf(command,"%s %s -pipe",path,fina);
X    start_synchron(command, istep_act); // master fn
X  }
X  
X  void load_file() {   
X    // it only works, if the old and new video file have the same 
X    // number of arrays !!
X    char *defname = "*.video"; char *fina = animp->wina;
X    FILE *fload = open_file_interactive(defname,fina,MODE_READ);
X    if (fload == NULL) return; 
X    fclose(animp->fvideo); 
X    animp->init_read(fload, False);
X
X    pl_scrb->adapt(animp->nsteps, 0);
X    seek_step(istep_act);
X    XStoreName(display,mainw->Win,fina); // set WM name
X  }
};
X
// nearly the quit_button class, only other string
class close_button : public button { 
public: 
X  close_button(menu_bar & parent) : button(parent, "close") {}
private:
X  void BPress_1_CB(XButtonEvent) { mainw->exit_flag = TRUE; }
};
X
// extern "C" char *getwd(char*); never use it under Linux !!!!
//  needs more than 1000 bytes !!!! -> horrible errors !!!
X
char *replay_help[] = {
X  "'replay' is used to view the saved '*.video' files from an integration run",
X  "of 'three-dim' or similiar programs.","",
X  "'rotate' lets the view rotate around z-axis, to stop press it again",
X  "To switch between arrays to display use the pulldown menues (v) lefthand.",
X  "'spawn' creates a new window to enable simultaneous viewing of several arrays",
X  "'file' loads a new video file (must have the same header size !) into the view",
X  "'synchron' starts the program as a new process to visit another file",
X  "synchronously with the current one.","",
X  "The top scrollbar controls the time selection, setting the slider (with left",
X  "mouse button) jumps immediately to the selected record.",
X  "The buttons '>' and '>>' enable stepwise and continuous viewing",
X  "(to stop press button '>>' <-> '||' again)",
X  "'<' goes stepwise back, '<<' resets to zero",0 };
X
int main(int argc, char *argv[]) {
X
X  // if argument is given : use it as filename !
X  char *name = (argc > 1) ? argv[1] : "three-dim";
X  char *full_name;
X  if (strchr(name,'.')) full_name = name; 
X  else { // if name contains no "." append ".video" 
X    full_name = new char[strlen(name) + 10];
X    sprintf(full_name,"%s.video",name);
X  } 
X  animator *animp = new animator(); 
X  animp->init_read(full_name, True); 
X  Bool top_proc = True;
X  if (argc > 2 && strcmp(argv[2],"-pipe") == 0) top_proc = False; 
X  // printf("new replayer %s %x %d\n", name, animp, itime);
X  replayer *rep = new replayer(animp, argv[0], top_proc);
X  menu_bar *mb = rep->mb; 
X  new instance_button <play_main> (*mb," spawn ",rep->spawn,rep);
X  if (top_proc) { // only the top process gets these buttons
X    new instance_button <replayer>(*mb," file ",rep->load_file,rep);
X    new instance_button <replayer> (*mb,"synchron",rep->start_command,rep);
X    new help_button (*mb," help ",replay_help);
X    new quit_button(*mb);
X  } else {
X    new close_button(*mb);
X  }
X
X  rep->main_loop();
X  rep->cleanup();
}
X
SHAR_EOF
chmod 0644 replay.c ||
echo 'restore of replay.c failed'
Wc_c="`wc -c < 'replay.c'`"
test 6038 -eq "$Wc_c" ||
	echo 'replay.c: original size 6038, current size' "$Wc_c"
fi
# ============= scrolled_demo.c ==============
if test -f 'scrolled_demo.c' -a X"$1" != X"-c"; then
	echo 'x - skipping scrolled_demo.c (File already exists)'
else
echo 'x - extracting scrolled_demo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'scrolled_demo.c' &&
// scrolled_demo.c
//    wolf 10/95
// demo of scrolled_window class and twodim_input
X
X
#include "window.h"
X
class my_virtual_window  : public virtual_window {
public:
X  my_virtual_window(scrolled_window *scr) : 
X  virtual_window(scr) {
X    for (int i= 0; i< 100; i++) 
X      new button(*this,"test",50,20, rand() % width, rand() % height);
X  }
X  virtual void redraw() {
X    line(0,0,width,height);
X  }
};
X
main() {
X  main_window *mw = new main_window("test",600,320);
X  new quit_button(*mw,80,20,0,0);
X  scrolled_window *scr = new scrolled_window(*mw,300,300,2000,300,0,20);
X  new my_virtual_window(scr);
X
X  new twodim_input(*mw,300,300,300,20,20,20);
X  // the callback cbhook is not set -> no reaction 
X  mw->main_loop();
}
X
SHAR_EOF
chmod 0644 scrolled_demo.c ||
echo 'restore of scrolled_demo.c failed'
Wc_c="`wc -c < 'scrolled_demo.c'`"
test 727 -eq "$Wc_c" ||
	echo 'scrolled_demo.c: original size 727, current size' "$Wc_c"
fi
exit 0


