/* MAKFNT - Font editor A Christopher Hall fecit */ #include #include #define DEBUG 0 /* Debug assembly switches */ #define DEBUG1 0 /* Command invocations: */ #define XRIGHT 4 /* Cursor right */ #define XLEFT 19 /* Cursor left */ #define XUP 5 /* Cursor up */ #define XDOWN 24 /* Cursor down */ #define XTAB 9 /* Tab */ #define XBTAB 21 /* Back-tab */ #define XUPTAB 15 /* Up-tab */ #define XDNTAB 16 /* Down-tab */ #define XBLINE '4' /* Move to start of line */ #define XELINE '6' /* Move to end of line */ #define XHOME '1' /* Move cursor home */ #define XRETRN 13 /* Carriage return */ #define XRUB 127 /* Rub out blot before cursor */ #define XEEOL 10 /* Erase to end of line */ #define XREWRT '5' /* Re-write the screen */ #define XSAVEC '0' /* Save defined character */ #define XRCALL '.' /* Recall saved character */ #define XKILL 11 /* Kill (delete) saved character */ #define XINROW '9' /* Insert row */ #define XDLROW '-' /* Delete row */ #define XINCOL '7' /* Insert column */ #define XDLCOL '8' /* Delete column */ #define XERASE ',' /* Erase current character */ #define XSTHGT '3' /* Set new height */ #define XFREAD 18 /* Read font file */ #define XFWRIT 6 /* Write font file */ #define XFAPP 1 /* Append font file */ #define XSTINC '2' /* Set new direction increment */ #define XFLIPV 22 /* Flip character vertically */ #define XFLIPH 2 /* Flip character horizontally */ #define XEXIT 3 /* Exit editor */ /* Screen manipulation sequences: */ #define CLEAR "\033[H\033[J" /* Clear the screen and move home */ #define CUP "\033[A" /* Move cursor up */ #define CDOWN "\033[B" /* Move cursor down */ #define CRIGHT "\033[C" /* Move cursor right */ #define CLEFT "\010" /* Move cursor left */ #define CEOL "\033[K" /* Clear from cursor to end of line */ /* Program parameters: */ #define EOF 0 /* End-of-file return value */ #define CHEIGHT 24 /* Maximum height a character will be */ #define CWIDTH 53 /* Ditto, width */ #define TOTCHR 100 /* Number of characters which can be defined */ #define MSGMGN 55 /* Column to start outputting messages */ int i,j; /* Scratch counters */ int row,col; /* Current row, column position */ int hr,hc; /* Home row, column, for CRLF's */ char charac[CHEIGHT+1][CWIDTH+1]; /* Character array */ int height; /* Height of current character */ char cmd; /* Command the user typed */ char chr; /* Single character */ char *ptr; /* General-purpose pointer */ int right; /* Farthest right the user has made a mark */ char inspac; /* Number of spaces to put between chars */ char inlins; /* Number of lines to put between lines */ char incdir; /* Direction of increment after type-in */ int cmask[6]; /* 2**(n+1), given n */ char string[400]; /* String of terminal type-in */ char filspc[20]; /* Name of input file */ int iobuf[BUFSIZ]; /* Buffer area for file I/O */ int finx; /* Index of latest character to save */ char *fptr; /* Pointer to freespace */ char frenam[TOTCHR]; /* Names of characters saved in freespace */ char *freptr[TOTCHR]; /* Pointers ditto */ char frelen[TOTCHR]; /* Lengths ditto */ char frespc[10000]; /* Space to save finished characters */ char clfflg; /* Flag: clear freespace when reading font */ main(argc,argv) char **argv; { initw(cmask,"1,2,4,8,16,32,64"); clrfre(); /* Clear out and init freespace */ right = 0; /* Init rightmost high water mark */ height = 12; /* Set a good default height */ drawfnc(); /* Draw the default fence; init row,col */ poshom(); /* Home the cursor */ incdir = 4; /* Set typein increment to "right" */ hc = 1; /* Set CRLF's column to be left margin */ while(1) { switch(cmd = readchr()) { /* Read a command and dispatch */ case XEXIT: /* Quit */ typstg(CLEAR); exit(); case XUP: /* Cursor up */ if (--row < 1) poscur((row=height),col); else typstg(CUP); /* Else just move up */ break; case XRETRN: /* Carriage return */ if (hr) { row = hr; if (++col > CWIDTH) col = 1; } else { col = hc; if (++row > height) row = 1; } poscur(row,col); break; case XDOWN: /* Cursor down */ if (++row > height) poscur((row=1),col); else typstg(CDOWN); /* Else just move down */ break; case XRIGHT: /* Cursor right */ if (++col > CWIDTH) poscur(row,(col=1)); else typstg(CRIGHT); break; case XLEFT: /* Cursor left */ if (--col < 1) poscur(row,(col=right+1)); else typstg(CLEFT); break; case XEEOL: /* Erase to end of line */ for (i=col; i<=right; i++) charac[row][i] = 0; typstg(CEOL); break; case XFREAD: /* Read a font file */ clfflg = 1; /* Tell readfnt to clear freespace; fall */ case XFAPP: /* Append font to current one */ readfnt(); drawfnc(); /* Re-draw the screen */ rewrite(); break; case XFWRIT: /* Write file */ wrtfil(); drawfnc(); /* Re-draw the screen */ rewrite(); break; case XKILL: /* Delete saved letter */ dellet(); rewrite(); break; case XBLINE: /* Move to beginning of line */ poscur(row,col=1); break; case XTAB: /* Goto next mark/blank change (or vva) */ chr = charac[row][col++]; /* Get what's at the cursor */ i = col; /* Save starting column position */ for (; col= CWIDTH) col = 1; poscur(row,col); break; case XBTAB: /* Move to previous mark change */ chr = charac[row][--col]; /* Get what's at cursor */ for (; col>1; col--) if (charac[row][col] != chr) break; if (col++ <= 1) col = 1; poscur(row,col); break; case XDNTAB: /* Down-tab */ chr = charac[row++][col]; /* Get what's at the cursor */ i = row; /* Save starting row position */ for (; row<=height; row++) if (charac[row][col] != chr) break; if (row > height) /* If none move to top */ if ((row = 5 + (i & ~3)) > height) row = 1; poscur(row,col); break; case XUPTAB: /* Up-tab */ chr = charac[--row][col]; /* Get what's at cursor */ for (; row>1; row--) if (charac[row][col] != chr) break; if (row++ <= 1) row = 1; poscur(row,col); break; case XELINE: /* Move to last mark on line */ for (col=CWIDTH; col>1; col--) if (charac[row][col]) break; poscur(row,++col); break; case XHOME: /* Move cursor home */ poscur((row=1),(col=1)); break; case XERASE: /* Erase complete character */ if (!verify(0)) { /* Verify answer; if not, */ poscur(row,col); /* Put the cursor back */ break; /* And forget the command */ } clrchr(); /* Erase the character array */ rewrite(); /* Remove character from screen */ poshom(); /* Move the cursor home */ break; case XREWRT: /* Re-write screen */ drawfnc(); rewrite(); break; case XSTINC: /* Set direction of increment */ query("Type new direction"); switch (chr = readchr()) { case XRIGHT: /* Right, left */ case XLEFT: incdir = chr; hr = 0; hc = col; break; case XUP: /* Up, down */ case XDOWN: incdir = chr; hr = row; hc = 0; break; case XRETRN: /* CR == right the default way */ incdir = 4; hr = 0; hc = 1; break; default: /* Anything else is an error */ typchr('\007'); } query(CEOL); /* Clear the query line */ poscur(row,col); /* Put the cursor back in the text */ break; case XSTHGT: /* Set height of character */ query("Type new height: "); i = getnum(); /* Get the new height and re-draw */ if (!verify(0)) { /* Verify answer; if not, */ query(CEOL); /* Clear the query line */ poscur(row,col); /* Put the cursor back */ break; /* And forget the command */ } height = i; /* Else make the change permanent */ clrchr(); drawfnc(); rewrite(); poshom(); /* Move the cursor home */ break; case XRUB: /* Erase character before cursor */ if (col > 1) { charac[row][--col] = 0; typstg("\010 \010"); } break; case XSAVEC: /* Encode and save character */ encode(); /* Find what to save it as and do so */ rewrite(); /* Rewrite the screen */ break; case XRCALL: /* Decode a saved character */ decode(); /* Ask for and decode the character */ rewrite(); /* Display it */ break; case XINCOL: /* Insert a blank column at cursor */ for (i=1; i<=height; i++) for (j=right+1; j>col; j--) charac[i][j] = charac[i][j-1]; for (i=1; i<=height; i++) charac[i][col] = 0; right++; /* Bump rightmost high-water mark */ rewrite(); break; case XDLCOL: /* Delete the column at the cursor */ for (i=1; i<=height; i++) for (j=col; j<=right; j++) charac[i][j] = charac[i][j+1]; rewrite(); break; case XINROW: /* Insert a blank row at cursor */ for (i=height; i>row; i--) for (j=1; j<=right; j++) charac[i][j] = charac[i-1][j]; for (j=1; j<=right; j++) charac[row][j] = 0; rewrite(); break; case XDLROW: /* Delete the row at the cursor */ for (i=row; i ' ') { /* If printing, make mark */ charac[row][col++] = 1; /* At cursor location */ typchr('X'); /* And on screen */ if (incdir != 4) adjpos(); /* Adjust if inc is not "right" */ } else typchr('\007'); /* Else beep for unknown command */ } /* End switching */ if ((i = col-1) >= right) { /* If moved to a new right position */ /* Save new high water mark */ if (charac[row-1][col] || charac[row+1][col]) right = col; else if (charac[row][i]) right = i; typwid(); /* Display the width */ poscur(row,col); /* Position back in the character */ } } /* End while (1) */ } /* ADJPOS - Here if incdir is not 4. If it is, the cursor, after typein or erase, should be positioned to the right of the character typed. If not, the cursor should be above, below, or to the left of the character. */ adjpos() { col--; /* Move column back */ if (incdir == 5) row--; /* Position above */ else if (incdir == 19) col--; /* To the left */ else if (incdir == 24) row++; /* Below */ poscur(row,col); /* Position in the right direction */ } /* QUERY - Position the the query line and output the given text */ query(stg) char *stg; { poscur(3,MSGMGN); typstg(stg); } /* TYPWID - Display the width of the character */ typwid() { poscur(2,MSGMGN); sprintf(string,"Width: %d ",right); typstg(string); } /* REWRITE - Rewrite the entire screen */ rewrite() { int rrow,rcol; for (rrow=1; rrow<=height; rrow++) { poscur(rrow,1); typstg(CEOL); /* Clear to end of line */ for (rcol=1; rcol<=right; rcol++) typchr((charac[rrow][rcol]) ? 'X' : ' '); } if (*filspc) { poscur(1,MSGMGN); /* Display the filespec */ typstg(filspc); /* If there is one */ } typwid(); /* Display the character's width */ tydchrs(); /* Say which characters have been defined */ poscur(row,col); /* Put the cursor back */ } /* CLRCHR - Erase the charac[][] character definition array */ clrchr() { int i,j; for (i=0; i<=height; i++) for (j=0; j<=right; j++) charac[i][j] = 0; right = 0; /* Clear rightmost high-water mark */ } /* DELLET - Delete saved character */ dellet() { int f; query("Delete: "); chr = readche(); /* Get the answer */ if (!verify(chr)) return; /* Get, verify answer; return if not v'ed */ for (f=0; f