6 * o Cursor motion is less than optimal (but who cares at 9600),
9 * cc -O fontedit.c -o fontedit
12 * Copyright (c) 1987 by Greg Franks.
14 * Permission is granted to do anything you want with this program
15 * except claim that you wrote it.
20 * Nov 21, 1987 - Fixed man page to say "Fontedit" instead of "Top"
21 * Nov 22, 1987 - Added BSD Compatible ioctl, turned cursor on/off
24 * $DragonFly: src/usr.sbin/pcvt/fontedit/Attic/fontedit.c,v 1.2 2004/02/10 02:59:42 rob Exp $
30 #include <sys/termio.h>
33 #include <sys/ioctl.h>
35 #if defined (__NetBSD__) || defined (__DragonFly__)
36 #include <sys/termios.h>
37 #include <sys/ioctl.h>
38 #endif /* __NetBSD__ || __DragonFly__ */
42 #define CURSORON "\033[?25h"
43 #define CURSOROFF "\033[?25l"
49 typedef enum { false, true } bool;
51 #define KEY_FIND 0x0100
52 #define KEY_INSERT 0x0101
53 #define KEY_REMOVE 0x0102
54 #define KEY_SELECT 0x0103
55 #define KEY_PREV 0x0104
56 #define KEY_NEXT 0x0105
61 #define KEY_F10 0x010a
62 #define KEY_F11 0x010b
63 #define KEY_F12 0x010c
64 #define KEY_F13 0x010d
65 #define KEY_F14 0x010e
66 #define KEY_HELP 0x010f
68 #define KEY_F17 0x0111
69 #define KEY_F18 0x0112
70 #define KEY_F19 0x0113
71 #define KEY_F20 0x0114
73 #define KEY_DOWN 0x0116
74 #define KEY_RIGHT 0x0117
75 #define KEY_LEFT 0x0118
78 * Position of main drawing screen.
85 * Position of the DRCS table.
98 bool display_table[MAX_ROWS][MAX_COLS];
100 #define TOTAL_ENTRIES (128 - 32)
101 #define SIXELS_PER_CHAR 16
103 char font_table[TOTAL_ENTRIES][SIXELS_PER_CHAR];
104 unsigned int current_entry;
107 struct termio old_stty, new_stty;
110 struct sgttyb old_stty, new_stty;
112 #if defined (__NetBSD__) || defined (__DragonFly__)
113 struct termios old_stty, new_stty;
114 #endif /* __NetBSD__ || __DragonFly__ */
115 FILE * font_file = (FILE *)0;
127 printf("%s\n",CURSORON);
130 ioctl( 0, TCSETA, &old_stty );
133 ioctl( 0, TIOCSETP, &old_stty );
135 #if defined (__NetBSD__) || defined (__DragonFly__)
136 ioctl( 0, TIOCSETA, &old_stty );
137 #endif /* __NetBSD__ || __DragonFly__ */
145 * Grab input/output file and call main command processor.
152 void command(), init_restore(), clear_screen();
153 void save_table(), get_table(), extract_entry();
156 fprintf( stderr, "usage: fontedit filename\n" );
160 printf( "Press HELP for help\n" );
161 printf( "\033P1;1;2{ @\033\\" ); /* Clear font buffer */
163 sleep( 1 ); /* Let terminal catch up */
164 /* otherwise we get frogs */
166 if ( ( font_file = fopen( argv[1], "r" ) ) == (FILE *)0 ) {
167 if ( ( font_file = fopen( argv[1], "w" ) ) == (FILE *)0 ) {
168 fprintf( stderr, "Cannot create file %s \n", argv[1] );
174 if ( ( font_file = fopen( argv[1], "r" ) ) != (FILE *)0 ) {
175 get_table( font_file );
179 if ( ( font_file = fopen( argv[1], "r+" ) ) == (FILE *)0 ) {
180 fprintf( stderr, "Cannot open %s for writing\n", argv[1] );
184 printf("%s\n",CURSOROFF);
187 ioctl( 0, TCGETA, &old_stty );
190 ioctl( 0, TIOCGETP, &old_stty );
192 #if defined (__NetBSD__) || defined (__DragonFly__)
193 ioctl( 0, TIOCGETA, &old_stty );
194 #endif /* __NetBSD__ || __DragonFly__ */
195 signal( SIGINT, (void *) interrupt );
198 new_stty.c_lflag &= ~ICANON;
199 new_stty.c_cc[VMIN] = 1;
200 ioctl( 0, TCSETA, &new_stty );
202 #if defined (__NetBSD__) || defined (__DragonFly__)
203 new_stty.c_lflag &= ~ICANON;
204 new_stty.c_lflag &= ~ECHO;
205 new_stty.c_cc[VMIN] = 1;
206 ioctl( 0, TIOCSETA, &new_stty );
207 #endif /* __NetBSD__ || __DragonFly__ */
209 new_stty.sg_flags |= CBREAK;
210 new_stty.sg_flags &= ~ECHO;
211 ioctl( 0, TIOCSETP, &new_stty );
214 extract_entry( current_entry );
218 ioctl( 0, TCSETA, &old_stty );
221 ioctl( 0, TIOCSETP, &old_stty );
223 #if defined (__NetBSD__) || defined (__DragonFly__)
224 ioctl( 0, TIOCSETA, &old_stty );
225 #endif /* __NetBSD__ || __DragonFly__ */
228 /* Overwrite the old file. */
230 fseek( font_file, 0L, 0 );
231 save_table( font_file );
234 printf("%s\n",CURSORON);
242 * Process a function key.
244 * The user cannot fill in slots 0 or 95 (space and del respecitively).
251 register int row, col;
253 bool change, error, override;
255 void build_entry(), extract_entry(), send_entry(), print_entry();
256 void highlight(), draw_current(), init_restore(), help();
263 highlight( row, col, true );
267 highlight( row, col, false ); /* turn cursor off */
270 move ( ERROR_ROW, ERROR_COL );
271 printf( "\033[K" ); /* Clear error message */
272 move ( ERROR_ROW+1, ERROR_COL );
273 printf( "\033[K" ); /* Clear error message */
281 case KEY_FIND: /* update DRCS */
282 if ( !change && !override ) {
283 warning( "No changes to save" );
287 build_entry( current_entry );
288 send_entry( current_entry );
289 print_entry( current_entry, true );
294 case KEY_F6: /* Turn on pixel */
296 display_table[row][col] = true;
297 highlight( row, col, false );
298 col = ( col + 1 ) % MAX_COLS;
300 row = ( row + 1 ) % MAX_ROWS;
303 case KEY_F7: /* Turn off pixel */
305 display_table[row][col] = false;
306 highlight( row, col, false );
307 col = ( col + 1 ) % MAX_COLS;
309 row = ( row + 1 ) % MAX_ROWS;
312 case KEY_INSERT: /* Insert a blank row */
314 for ( j = 0; j < MAX_COLS; ++j ) {
315 for ( i = MAX_ROWS - 1; i > row; --i ) {
316 display_table[i][j] = display_table[i-1][j];
318 display_table[row][j] = false;
323 case KEY_REMOVE: /* Remove a row */
325 for ( j = 0; j < MAX_COLS; ++j ) {
326 for ( i = row; i < MAX_ROWS - 1; ++i ) {
327 display_table[i][j] = display_table[i+1][j];
329 display_table[MAX_ROWS-1][j] = false;
334 case KEY_F13: /* Clear buffer */
335 if ( change && !override ) {
336 warning( "Changes not saved" );
340 for ( j = 0; j < MAX_COLS; ++j ) {
341 for ( i = 0; i < MAX_ROWS; ++i ) {
342 display_table[i][j] = false;
349 case KEY_SELECT: /* Select font from DRCS */
350 if ( change && !override ) {
351 warning( "Changes not saved" );
355 extract_entry( current_entry );
360 case KEY_PREV: /* Move to prev entry in DRCS */
361 if ( change && !override ) {
362 warning( "Changes not saved" );
366 print_entry( current_entry, false );
367 current_entry = current_entry - 1;
368 if ( current_entry == 0 )
369 current_entry = TOTAL_ENTRIES - 2;
370 print_entry( current_entry, true );
374 case KEY_NEXT: /* Move to next entry in DRCS */
375 if ( change && !override ) {
376 warning( "Changes not saved" );
380 print_entry( current_entry, false );
381 current_entry = current_entry + 1;
382 if ( current_entry == TOTAL_ENTRIES - 1 )
384 print_entry( current_entry, true );
388 case KEY_UP: /* UP one row. */
394 case KEY_DOWN: /* Guess. */
395 row = ( row + 1 ) % MAX_ROWS;
399 col = ( col + 1 ) % MAX_COLS;
408 case KEY_HELP: /* Display helpful info */
415 case '\004': /* All done! */
418 case '\f': /* Redraw display */
422 default: /* user is a klutzy typist */
423 move ( ERROR_ROW, ERROR_COL );
424 printf( "Unknown key: " );
427 } else if ( c < 0x0100 ) {
430 printf( "0x%04x", c );
436 highlight( row, col, true ); /* turn cursor on */
442 char *key_table[] = {
443 "\033[1~", /* Find */
444 "\033[2~", /* Insert */
445 "\033[3~", /* Remove */
446 "\033[4~", /* Select */
447 "\033[5~", /* Prev */
448 "\033[6~", /* Next */
472 * Convert VT220 escape sequence into something more reasonable.
483 for ( i = 0; i < 10; ++i ) {
485 if ( i == 0 && *p != '\033' )
486 return( (int)*p ); /* Not an escape sequence */
487 if ( *p != '\033' && *p < 0x0020 )
488 return( (int)*p ); /* Control character */
489 *++p = '\0'; /* Null terminate */
490 for ( j = 0; key_table[j]; ++j ) {
491 if ( strcmp( s, key_table[j] ) == 0 ) {
492 return( j | 0x0100 );
503 * Emit nulls so that the terminal can catch up.
510 for ( i = 0; i < 20; ++i )
519 * refresh the main display table.
525 register int row, col;
528 void draw_current(), clear_screen(), print_entry();
532 for ( col = 0; col < MAX_COLS; ++col ) {
533 move( ROW_OFFSET - 2, col * 3 + COL_OFFSET + 1 );
536 move( ROW_OFFSET - 1, COL_OFFSET );
537 printf( "+--+--+--+--+--+--+--+--+" );
538 move( ROW_OFFSET + MAX_ROWS * 2, COL_OFFSET );
539 printf( "+--+--+--+--+--+--+--+--+" );
541 for ( row = 0; row < MAX_ROWS; ++row ) {
542 if ( row != 0 && row != 7 ) {
543 move( row * 2 + ROW_OFFSET, COL_OFFSET - 2 );
544 printf( "%d|", row );
545 move( row * 2 + ROW_OFFSET + 1, COL_OFFSET - 1 );
547 move( row * 2 + ROW_OFFSET, COL_OFFSET + MAX_COLS * 3 );
549 move( row * 2 + ROW_OFFSET + 1, COL_OFFSET + MAX_COLS * 3 );
552 move( row * 2 + ROW_OFFSET, COL_OFFSET - 2 );
553 printf( "%d*", row );
554 move( row * 2 + ROW_OFFSET + 1, COL_OFFSET - 1 );
556 move( row * 2 + ROW_OFFSET, COL_OFFSET + MAX_COLS * 3 );
558 move( row * 2 + ROW_OFFSET + 1, COL_OFFSET + MAX_COLS * 3 );
564 move( TABLE_ROW - 1, TABLE_COL - 1 );
565 printf( "+-+-+-+-+-+-+-+-+-+-+-+-+" );
566 move( TABLE_ROW + 8 * 2 - 1, TABLE_COL - 1 );
567 printf( "+-+-+-+-+-+-+-+-+-+-+-+-+" );
568 for ( i = 0; i < 8; ++i ) {
569 move ( TABLE_ROW + i * 2, TABLE_COL - 1 );
571 move ( TABLE_ROW + i * 2 + 1, TABLE_COL - 1 );
573 move ( TABLE_ROW + i * 2, TABLE_COL + 12 * 2 - 1);
575 move ( TABLE_ROW + i * 2 + 1, TABLE_COL +12 * 2 - 1);
578 for ( i = 0; i < TOTAL_ENTRIES; ++i )
579 print_entry( i, (i == current_entry) ? true : false );
586 * Draw the complete current entry.
592 register int row, col;
594 printf( "\033)0" ); /* Special graphics in G1 */
595 printf( "\016" ); /* Lock in G1 (SO) */
597 for ( row = 0; row < MAX_ROWS; ++row ) {
598 for ( col = 0; col < MAX_COLS; ++col ) {
599 if ( display_table[row][col] ) {
600 move( row * 2 + ROW_OFFSET, col * 3 + COL_OFFSET );
601 printf( "\141\141\141" );
602 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
603 printf( "\141\141\141" );
605 move( row * 2 + ROW_OFFSET, col * 3 + COL_OFFSET );
606 printf( " " ); /* erase splat */
607 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
608 printf( " " ); /* erase splat */
613 printf( "\017" ); /* Lock in G0 (SI) */
621 * Draw the cursor in the main display area.
625 highlight( row, col, on )
626 unsigned int row, col;
630 printf( "\033)0" ); /* Special graphics in G1 */
631 printf( "\016" ); /* Lock in G1 (SO) */
633 printf( "\033[7m" ); /* Reverse video cursor */
636 if ( display_table[row][col] ) {
637 move( row * 2 + ROW_OFFSET, col * 3 + COL_OFFSET );
638 printf( "\141\141\141" );
639 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
640 printf( "\141\141\141" );
642 move( row * 2 + ROW_OFFSET, col * 3 + COL_OFFSET );
643 printf( " " ); /* erase splat */
644 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
645 printf( " " ); /* erase splat */
648 printf( "\017" ); /* Lock in G0 (SI) */
649 printf( "\033[0m" ); /* normal video */
650 printf( "\b" ); /* Back up one spot */
663 printf( "\033[H\033[J" ); /* Clear screen. */
676 printf( "\033[%d;%df", y, x );
683 * Convert the bit pattern used in the main display area into something
684 * that the vt220 can digest - namely sixels...
688 build_entry( entry_no )
689 unsigned int entry_no;
691 register int row, col;
692 register unsigned int mask;
694 for ( col = 0; col < 8; ++col ) {
696 /* Top set of sixels */
699 for ( row = 5; row >= 0; --row ) {
701 if ( display_table[row][col] )
704 font_table[entry_no][col] = mask + 077;
706 /* Bottom set of sixels */
709 for ( row = 9; row >= 6; --row ) {
711 if ( display_table[row][col] )
714 font_table[entry_no][col+8] = mask + 077;
723 * convert sixel representation into an array of bits.
727 extract_entry( entry_no )
728 unsigned int entry_no;
730 register int row, col;
731 register unsigned int mask;
733 for ( col = 0; col < 8; ++col ) {
735 /* Top set of sixels */
737 mask = font_table[entry_no][col];
741 mask = 0; /* Bogus entry */
743 for ( row = 0; row <= 5; ++row ) {
744 display_table[row][col] = (bool)(mask & 0x0001);
748 /* Bottom set of sixels */
750 mask = font_table[entry_no][col+8];
756 for ( row = 6; row <= 9; ++row ) {
757 display_table[row][col] = (bool)(mask & 0x0001);
768 * Emit the stuff used by the VT220 to load a character into the
769 * DRCS. We could, of course, send more than one entry at a time...
773 send_entry( entry_no )
776 register char *fp = font_table[entry_no];
778 printf( "\033P1;%d;1;0;0;0{ @%c%c%c%c%c%c%c%c/%c%c%c%c%c%c%c%c\033\\",
780 fp[ 0], fp[ 1], fp[ 2], fp[ 3], fp[ 4], fp[ 5], fp[ 6], fp[ 7],
781 fp[ 8], fp[ 9], fp[10], fp[11], fp[12], fp[13], fp[14], fp[15] );
788 * The terminal normally has G0 in GL. We don't want to change
789 * this, nor do we want to use GR. Sooooo send out the necessary
790 * magic for shifting in G2 temporarily for the character that we
795 print_entry( entry_no, highlight )
796 register unsigned int entry_no;
803 x = entry_no >> 3 & 0x1f;
804 entry_no += 32; /* Map up to G set */
806 move( y * 2 + TABLE_ROW, x * 2 + TABLE_COL );
811 printf( "\033* @" ); /* select DRCS into G2 */
812 printf( "\033N" ); /* select single shift */
813 printf( "%c", entry_no ); /* Draw the character */
827 save_table( font_file )
833 for ( i = 0; i < TOTAL_ENTRIES; ++i ) {
835 fprintf( font_file, "\033P1;%d;1;0;0;0{ @%c%c%c%c%c%c%c%c/%c%c%c%c%c%c%c%c\033\\\n",
837 fp[ 0], fp[ 1], fp[ 2], fp[ 3], fp[ 4], fp[ 5], fp[ 6], fp[ 7],
838 fp[ 8], fp[ 9], fp[10], fp[11], fp[12], fp[13], fp[14], fp[15] );
846 * Extract font table entries from a file
850 get_table( font_file )
859 while( fgets( s, 255, font_file ) ) {
860 if ( strncmp( s, "\033P1;", 4 ) != 0 )
861 continue; /* Bogus line */
863 if ( sscanf( p, "%d", &i ) != 1 )
864 continue; /* Illegal entry number */
866 if ( i <= 0 || TOTAL_ENTRIES <= i )
867 continue; /* Bogues entry */
871 while ( *p && *p != '@' )
872 ++p; /* Skip to font definition */
874 continue; /* Skip @ */
876 for ( j = 0; *p && *p != '\033' && j < 16; ++j, ++p ) {
891 * Print out help information.
897 printf( "Font editor\n\n" );
898 printf( "F6 - Pixel on\n" );
899 printf( "F7 - Pixel off\n" );
900 printf( "F13 - Clear display area\n" );
901 printf( "HELP - This screen\n" );
902 printf( "FIND - Update font table\n" );
903 printf( "INSERT - Insert a blank row\n" );
904 printf( "REMOVE - Remove a row\n" );
905 printf( "SELECT - Select current font table entry\n" );
906 printf( "PREV - Move to previous font table entry\n" );
907 printf( "NEXT - Move to next font table entry\n" );
908 printf( "^D - Exit\n" );
909 printf( "\n\n\n\nPress any key to continue\n" );
916 * Issue a warning to the regarding the current status.
923 move( ERROR_ROW, ERROR_COL );
924 printf( "Warning: %s!\n", s );
925 move( ERROR_ROW+1, ERROR_COL );
926 printf( " Reissue command to override\n" );