home *** CD-ROM | disk | FTP | other *** search
- // 28.7.89 avner ben - classified the alphabet datatypes
- // ┌───────┐
- // ─────────>│ AVNER │
- // ─────────>│ BEN │──────> Software Engineering Method
- // └───────┘
- // 10 Dov-Hoz st. Tel-Aviv 63416 Israel tel. 972-3-221535
-
- // The Screen NAVigator, ver 1.10 April 1990
- // Copyright (c) 1989 by Avner Ben
- // Snav is not, and never was, free software.
- // for conditions for use refer to file "copyrigh.txt"
-
- // The Screen Navigator is an object-oriented device-independent
- // character-graphics driver package, written in the C++ language,
- // distributed in the form of C++ source code.
- // For further information refer to the documentation files.
-
- // The user may not omit this text, from the beginning of the file, to
- // the line of asterisks below.
-
- /***************************************************************************/
-
- // package nucleus part 2 - source code.
- // This file defines the "computer-alphabet" object, and offers an
- // extended-ASCII implemented, as on the IBM-PC.
- // for data-structure logic, refer to file "article".
-
- // History:
- // 28.7.89 avner ben coded.
- /////// snav v1.1
- // 5.3.90 avner ben - C++ v2.0 upgrade.
- // * removed Zortech-specific strupr()
- // * removed unnecessary #include to <conio.h>
-
- // Site history (of this copy):
- // __.__.__ ____________ : __________________.
-
- #include <stdio.h>
- #include <string.h>
-
- #define SNAV1_C
- #include "snav0.hpp"
- #include "snav1.hpp"
-
- /**************** indexed access to character attribute table *****************/
-
- int ascii_pc_data[]=
- { // in-memory file to be loaded into the default alphabet when initialized.
- // all semigraphic characters in the ascii collating sequence, pc-extended.
-
- // num directions-connective wgt
- // --- ----------------------- ---
- 16,LTDIR, 3,0, // default right arrow
- 17,RTDIR, 3,0, // default left arrow
- 30,DNDIR, 0,3, // default up arrow
- 31,UPDIR, 0,3, // default down arrow
- 43,RTDIR|UPDIR|LTDIR|DNDIR,0,0, // twg cross
- 45,RTDIR|LTDIR, 0,0, // twg dash
- 60,RTDIR, 0,0, // twg left arrow
- 62,LTDIR, 0,0, // twg right arrow
- 86,UPDIR, 0,0, // twg down arrow
- 94,DNDIR, 0,0, // twg up arrow
- 124,UPDIR|DNDIR, 0,0, // twg bar
- 179,UPDIR|DNDIR, 0,1, // bar
- 180,UPDIR|LTDIR|DNDIR, 1,1, // left fork
- 181,UPDIR|LTDIR|DNDIR, 2,1, // left fork
- 182,UPDIR|LTDIR|DNDIR, 1,2, // left fork
- 183,LTDIR|DNDIR, 1,2, // right up corner
- 184,LTDIR|DNDIR, 2,1, // right up corner
- 185,UPDIR|LTDIR|DNDIR, 2,2, // left fork
- 186,UPDIR|DNDIR, 0,2, // bar
- 187,LTDIR|DNDIR, 2,2, // right up corner
- 188,UPDIR|LTDIR, 2,2, // right down corner
- 189,UPDIR|LTDIR, 1,2, // right down corner
- 190,UPDIR|LTDIR, 2,1, // right down corner
- 191,LTDIR|DNDIR, 1,1, // right up corner
- 192,RTDIR|UPDIR, 1,1, // left down corner
- 193,RTDIR|UPDIR|LTDIR, 1,1, // up fork
- 194,RTDIR|LTDIR|DNDIR, 1,1, // down fork
- 195,RTDIR|UPDIR|DNDIR, 1,1, // right fork
- 196,RTDIR|LTDIR, 1,0, // dash
- 197,RTDIR|UPDIR|LTDIR|DNDIR,1,1, // cross
- 198,RTDIR|UPDIR|DNDIR, 2,1, // right fork
- 199,RTDIR|UPDIR|DNDIR, 1,2, // right fork
- 200,RTDIR|UPDIR, 2,2, // left down corner
- 201,RTDIR|DNDIR, 2,2, // left up corner
- 202,RTDIR|UPDIR|LTDIR, 2,2, // up fork
- 203,RTDIR|LTDIR|DNDIR, 2,2, // down fork
- 204,RTDIR|UPDIR|DNDIR, 2,2, // right fork
- 205,RTDIR|LTDIR, 2,0, // dash
- 206,RTDIR|UPDIR|LTDIR|DNDIR,2,2, // cross
- 207,RTDIR|UPDIR|LTDIR, 2,1, // up fork
- 208,RTDIR|UPDIR|LTDIR, 1,2, // up fork
- 209,RTDIR|LTDIR|DNDIR, 2,1, // down fork
- 210,RTDIR|LTDIR|DNDIR, 1,2, // down fork
- 211,RTDIR|UPDIR, 1,2, // left down corner
- 212,RTDIR|UPDIR, 2,1, // left down corner
- 213,RTDIR|DNDIR, 2,1, // left up corner
- 214,RTDIR|DNDIR, 1,2, // left up corner
- 215,RTDIR|UPDIR|LTDIR|DNDIR,1,2, // cross
- 216,RTDIR|UPDIR|LTDIR|DNDIR,2,1, // cross
- 217,UPDIR|LTDIR, 1,1, // right down corner
- 218,RTDIR|DNDIR, 1,1, // left up corner
- 219,RTDIR|UPDIR|LTDIR|DNDIR,3,3, // full
- // stream terminator
- 0,NODIR, 0,0
- };
-
- // default alphabet initialized by system
- computer_alphabet *alph=
- new computer_alphabet("ASCII_PC",256,ascii_pc_data);
-
- computer_alphabet :: computer_alphabet(char *alphname, int bufsize, int *data)
- {
- name=new char[strlen(alphname)+1];
- strcpy(name,alphname);
- numchars=bufsize;
- grafc=new int[bufsize*2];
- for (int *c=grafc+(numchars-1)*2; ; c--)
- { *c=0; if (c==grafc) break; }
- for (c=&(index[15][15]); ; c--)
- { *c=0; if (c==&index[0][0]) break; }
- if (!data) return;
- for (; *data; data+=4)
- poke_c((char)*data,intersection(*(data+1)),
- weight_d(*(data+2),*(data+3)));
- }
-
- computer_alphabet :: ~computer_alphabet(void)
- { delete grafc; delete name; }
-
- void computer_alphabet :: poke_c(char c, const intersection &avdir,
- const weight_d &wgt)
- { // poke attributes in character table and index
-
- int cnum=(unsigned char)c;
- if (cnum<1 || cnum>=numchars) return; // caller's bug
- *(grafc+cnum*2)=avdir();
- *(grafc+cnum*2+1)=wgt();
- index[wgt()][avdir()]=(avdir() ? cnum : 0);// the latter is caller's bug
- }
-
- char computer_alphabet :: get_c(const intersection &avdir, weight_d wgt)
- { // retrive character by attributes, or a close match
-
- // fix caller's neglect - over-weight
- if (wgt.y() && !(avdir.intersects(hdirs)))
- wgt.replace(axis(HDIM),0);
- if (wgt.x() && !(avdir.intersects(vdirs)))
- wgt.replace(axis(VDIM),0);
- if (!(wgt()) && !(avdir()))
- return(' '); // not semigraphic
- // fix caller's neglect - under-weight
- if (!(wgt.y()) && avdir.intersects(hdirs))
- wgt.replace(axis(HDIM),
- wgt.x());
- if ((!wgt.x()) && avdir.intersects(vdirs))
- wgt.replace(axis(VDIM),wgt.y());
- int c;
- // 1. exact match
- if ((c=index[wgt()][avdir()])!=0)
- return (char)c;
- // 2. default full width
- if ((c=index[(weight_d((wgt.y()? 3:0),(wgt.x()? 3:0)))()]
- [avdir()])!=0)
- return (char)c;
- // 3. typewriter graphic - search for cross
- if (!wgt() && ((c=index[0][alldirs()])!=0))
- return (char)c;
- // 4. full weight - search for cross
- if ((wgt.y()==3 || wgt.x()==3) && ((c=index[fullwgt()][alldirs()])!=0))
- return (char)c;
- // 5. close match (nearest intersection in same weight group)
- for (int i=avdir()-1; i; i--)
- if ((c=index[wgt()][i])!=0)
- return (char)c;
- // 6. not found
- return(' ');
- }
-
- char computer_alphabet :: translate(char src, weight_d wgt)
- { // translate character to target width, as close as possible
-
- char tgt;
- if ((tgt=get_c(intersection(cdir(src)),wgt))!=0)
- return tgt;
- return src;
- }
-
- void computer_alphabet :: inverse(const axis &dim)
- { // invert the whole alphabet (e.g. latin=>semitic)
-
- for (int i=1; i<numchars-1; i++) {
- intersection avdir=(cdir((char)i)), newdir((int)NODIR);
- if (!avdir()) continue;
- for (direction dir; dir(); dir++)
- if (avdir>=dir)
- if (axis(dir)==dim) newdir+=(~dir);
- else newdir+=dir;
- poke_c( (char)i,newdir(),cweight((char)i) );
- }
- }
-
- int computer_alphabet :: list(FILE *outf)
- { // print the index (originally intended for debugging)
-
- if (!outf) return;
- int typeface[16], num_faces=0, num_semi=0;
- for (int i=0; i<=15; i++) {
- typeface[i]=0;
- for (int j=0; j<=15; j++)
- if (index[i][j])
- { typeface[i]=TRUE; num_semi++; }
- if (typeface[i]) num_faces++;
- }
- fprintf(outf,"The %s Alphabet - semigrpahic cross-reference\n",name);
- if (!num_faces)
- { fprintf(outf,"(null)\n"); return; }
- fprintf (outf,"contains %d semigraphic characters in %d weight groups\n",
- num_semi,num_faces);
- for (int w=0; w<=15; w++) {
- if (!typeface[w]) continue;
- fprintf(outf,"\n");
- fprintf(outf,"WEIGHT GROUP code %d (h:v weight distribution ",w);
- if ((weight_d(w)).y()>2) fprintf(outf,"full:");
- else fprintf(outf,"%d:",(weight_d(w)).y());
- if ((weight_d(w)).x()>2) fprintf(outf,"full)");
- else fprintf(outf,"%d)",(weight_d(w)).x());
- fprintf(outf,"\n");
- for (int d=1; d<=15; d++)
- if (index[w][d])
- fprintf(outf," %3d: %c function: %-8s (connects: %s)\n",index[w][d],
- (char)index[w][d],(intersection(d)).name(),
- (intersection(d)).names());
- }
- return i;
- }
-
- /*********************** character connectivity ******************************/
-
- boolean computer_alphabet :: ccont(char cfrm, char cto, const direction &curdir)
- { /* test if two semigraphics connect, given current direction */
-
- if (!(curdir())) return(FALSE);
- if (!(intersection(cdir(cfrm))>=curdir))
- return(FALSE); /* caller's bug */
- /* target char must point at opposite direction */
- if (intersection(cdir(cto))>=(~curdir)) {
- axis curdim(curdir);
- int widfrm=(cweight(cfrm)).width(curdim);
- int widto=(cweight(cto)).width(curdim);
- if (widfrm==widto // same width
- || widto==3 || widfrm==3) // default terminal symbol
- return(TRUE);
- }
- return(FALSE);
- }
-
- char computer_alphabet :: carrw(char *env, direction ind, weight_d wgt,
- int len, int pos, boolean directed)
- { // draw one character within an arc, context sensitive
-
- if (pos>len) pos=len; // caller's bug
- // adjust other axis to merge with char to be overlayed
- wgt.replace(~(axis(ind)),(alph->cweight(*env)).width(~(axis(ind))));
- if (pos==len) // end of arc ?
- if (len>1 || directed) {// invert connectivity
- ind.opposite();
- if (directed) // arrowhead requested
- return get_c(intersection(ind()),wgt);
- } // otherwise (not directed) - allow to "weld"
- intersection avdir(cdir(*env)); avdir+=ind;
- if (pos!=1 && pos!=len || avdir.unary())
- avdir+=(~ind); // opposite added by default
- char c=get_c(avdir,wgt); // init result
- for (direction dir; dir(); dir++) {
- if (dir!=ind && dir!=(~ind)) // vertical
- if (*(env+dir.serial())!=' '
- && ccont(c,*(env+dir.serial()),dir)) {
- if (!(avdir>=dir))
- { avdir+=dir; c=get_c(avdir,wgt); }
- } else if (avdir>=dir)
- { avdir-=dir; c=get_c(avdir,wgt); }
- }
- if (pos<len && avdir.unary()) { // arrowhead not allowed in middle
- avdir+=~(direction(avdir()));
- c=get_c(avdir,wgt);
- }
- return c;
- }
-
- char * computer_alphabet :: cearrw(char *env, direction ind, weight_d wgt,
- int len, int pos, boolean directed)
- { // draw one character within an arc, possibly modifying neighbours
-
- if (pos>len) pos=len; // caller's bug
- // adjust other axis to merge with char to be overlayed
- wgt.replace(~(axis(ind)),(alph->cweight(*env)).width(~(axis(ind))));
- if (pos==len) // end of arc ?
- if (len>1 || directed) {// invert connectivity
- ind.opposite();
- if (directed) { // arrowhead requested
- *env=get_c(intersection(ind()),wgt);
- return(env);
- }
- } // else (not directed) - allow to "weld"
- intersection avdir(cdir(*env)); avdir+=ind;
- if (pos!=1 && pos!=len || avdir.unary())
- avdir+=(~ind); // opposite added by default
- char c=get_c(avdir,wgt); // init result
- for (direction dir; dir(); dir++) {
- char *ngbr=env+dir.serial();
- if (dir!=ind && dir!=(~ind)) { // vertical
- if (*ngbr!=' ' && ccont(c,*ngbr,dir)) {
- if (!(avdir>=dir))
- { avdir+=dir; c=get_c(avdir,wgt); }
- } else if (avdir>=dir)
- { avdir-=dir; c=get_c(avdir,wgt); }
- // normalize weight
- if ((alph->cdir(*env)).unary()) {
- if (ccont(*env,*ngbr,dir)) {
- wgt.replace(axis(dir),(alph->cweight(*ngbr)).width(axis(dir)));
- c=get_c(avdir,wgt);
- }
- }
- }
- if (*ngbr!=' ' && !(avdir>=dir)) // trim neighbour
- if (cdir(*ngbr)>=~dir && (cdir(*ngbr)).type()>=J_FORK)
- *ngbr=ctrim(*ngbr,~dir);
- }
- if (pos<len && avdir.unary()) { // arrowhead not allowed in middle
- avdir+=~(direction(avdir()));
- c=get_c(avdir,wgt);
- }
- *env=c;
- return env;
- }
-
- char computer_alphabet :: ctrim(char c, const direction &dir)
- { // trim char in protruding direction, if present
-
- intersection avdir(cdir(c));
- if (!(avdir>=dir)) return(c); // not there
- avdir-=dir;
- return get_c(avdir,cweight(c));
- }
-
- char computer_alphabet :: celong(char c, const direction &dir)
- { // elongate char in missing direction, if not already present
-
- intersection avdir(cdir(c));
- if (avdir>=dir) return(c); // already there
- avdir+=dir;
- return get_c(avdir,cweight(c));
- }
-