home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / vt220fontedit / fontedit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-01-31  |  17.3 KB  |  896 lines

  1. /*
  2.  * fontedit
  3.  *    Fonteditor for VT220
  4.  *
  5.  *  BUGS:
  6.  *    o Cursor motion is less than optimal (but who cares at 9600),
  7.  *
  8.  *  COMPILE:
  9.  *    cc -O fontedit.c -o fontedit
  10.  *      (use Makefile)
  11.  *
  12.  *    Copyright (c) 1987 by Greg Franks.
  13.  *
  14.  *    Permission is granted to do anything you want with this program
  15.  *    except claim that you wrote it.
  16.  *
  17.  *
  18.  *      REVISION HISTORY:
  19.  *
  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
  22.  *                     - eap@bucsf.bu.edu
  23.  */
  24.  
  25. #include <stdio.h>
  26. #ifdef SYSV
  27. #include <sys/termio.h>
  28. #endif SYSV
  29. #ifdef BSD
  30. #include <sys/ioctl.h>
  31. #endif BSD
  32. #include <signal.h>
  33.  
  34. #ifdef CURFIX
  35. #define CURSORON  "\033[?25h"
  36. #define CURSOROFF "\033[?25l"
  37. #endif CURFIX
  38.  
  39. #define    MAX_ROWS    10
  40. #define    MAX_COLS    8
  41.  
  42. typedef enum { false, true } bool;
  43.  
  44. #define    KEY_FIND     0x0100
  45. #define    KEY_INSERT     0x0101
  46. #define    KEY_REMOVE     0x0102
  47. #define    KEY_SELECT     0x0103
  48. #define    KEY_PREV     0x0104
  49. #define    KEY_NEXT     0x0105
  50. #define    KEY_F6        0X0106
  51. #define    KEY_F7        0x0107
  52. #define    KEY_F8        0x0108
  53. #define    KEY_F9        0x0109
  54. #define    KEY_F10        0x010a
  55. #define    KEY_F11        0x010b
  56. #define    KEY_F12        0x010c
  57. #define    KEY_F13        0x010d
  58. #define    KEY_F14        0x010e
  59. #define    KEY_HELP    0x010f
  60. #define    KEY_DO        0x0110
  61. #define    KEY_F17        0x0111
  62. #define    KEY_F18        0x0112
  63. #define    KEY_F19        0x0113
  64. #define    KEY_F20        0x0114
  65. #define    KEY_UP         0x0115
  66. #define    KEY_DOWN     0x0116
  67. #define    KEY_RIGHT     0x0117
  68. #define    KEY_LEFT     0x0118
  69.  
  70. /*
  71.  * Position of main drawing screen.
  72.  */
  73.  
  74. #define    ROW_OFFSET    3
  75. #define COL_OFFSET    10
  76.  
  77. /* 
  78.  * Position of the DRCS table.
  79.  */
  80.  
  81. #define    TABLE_ROW    4
  82. #define    TABLE_COL    50
  83.  
  84. /*
  85.  *
  86.  */
  87.  
  88. #define    ERROR_ROW    20
  89. #define ERROR_COL    40
  90.  
  91. bool    display_table[MAX_ROWS][MAX_COLS];
  92.  
  93. #define    TOTAL_ENTRIES    (128 - 32)
  94. #define    SIXELS_PER_CHAR    16
  95.  
  96. char    font_table[TOTAL_ENTRIES][SIXELS_PER_CHAR];
  97. unsigned int    current_entry;
  98.  
  99. #ifdef SYSV
  100. struct termio old_stty, new_stty;
  101. #endif SYSV
  102. #ifdef BSD
  103. struct sgttyb old_stty, new_stty;
  104. #endif BSD
  105.  
  106. FILE * font_file = (FILE *)0;
  107.  
  108.  
  109. /*
  110.  * Interrupt
  111.  *    Exit gracefully.
  112.  */
  113.  
  114. interrupt()
  115. {
  116.     void clear_screen();
  117. #ifdef CURFIX
  118.         printf("%s\n",CURSORON);   
  119. #endif CURFIX   
  120. #ifdef SYSV
  121.     ioctl( 0, TCSETA, &old_stty );
  122. #endif SYSV
  123. #ifdef BSD
  124.         ioctl( 0, TIOCSETP, &old_stty );
  125. #endif BSD
  126.     clear_screen();
  127.     exit( 0 );
  128. }
  129.  
  130.  
  131. /*
  132.  * Main
  133.  *    Grab input/output file and call main command processor.
  134.  */
  135.     
  136. main( argc, argv )
  137. int argc;
  138. char *argv[];
  139. {
  140.     void command(), init_restore(), clear_screen();
  141.     void save_table(), get_table(), extract_entry();
  142.  
  143.     if ( argc != 2 ) {
  144.         fprintf( stderr, "useage: fontedit filename\n" );
  145.         exit( 1 );
  146.     }
  147.  
  148.     printf( "Press HELP for help\n" );
  149.     printf( "\033P1;1;2{ @\033\\" );    /* Clear font buffer    */
  150.     fflush( stdout );
  151.     sleep( 1 );            /* Let terminal catch up    */
  152.                     /* otherwise we get frogs    */
  153.  
  154.     if ( ( font_file = fopen( argv[1], "r" ) ) != (FILE *)0 ) {
  155.         get_table( font_file );
  156.         fclose( font_file );
  157.     }
  158.  
  159.     if ( ( font_file = fopen( argv[1], "r+" ) ) == (FILE *)0 ) {
  160.         fprintf( stderr, "Cannot open %s for writing\n", argv[1] );
  161.         exit( 1 );
  162.     }
  163. #ifdef CURFIX
  164.         printf("%s\n",CURSOROFF);
  165. #endif CURFIX
  166. #ifdef SYSV
  167.     ioctl( 0, TCGETA, &old_stty );
  168. #endif SYSV
  169. #ifdef BSD
  170.         ioctl( 0, TIOCGETP, &old_stty );
  171. #endif BSD
  172.     signal( SIGINT, interrupt );
  173.  
  174.     new_stty = old_stty;
  175. #ifdef SYSV
  176.     new_stty.c_lflag &= ~ICANON;
  177.     new_stty.c_cc[VMIN] = 1;
  178.     ioctl( 0, TCSETA, &new_stty );
  179. #endif SYSV
  180. #ifdef BSD
  181.     new_stty.sg_flags |= CBREAK;               
  182.         new_stty.sg_flags &= ~ECHO;
  183.     ioctl( 0, TIOCSETP, &new_stty );
  184. #endif BSD
  185.     current_entry = 1;
  186.     extract_entry( current_entry );
  187.     init_restore();
  188.     command();
  189. #ifdef SYSV
  190.     ioctl( 0, TCSETA, &old_stty );
  191. #endif SYSV
  192. #ifdef BSD
  193.     ioctl( 0, TIOCSETP, &old_stty );
  194. #endif BSD
  195.     clear_screen();
  196.  
  197.     /* Overwrite the old file. */
  198.  
  199.     fseek( font_file, 0L, 0 );
  200.     save_table( font_file );
  201.     fclose( font_file );
  202. #ifdef CURFIX
  203.         printf("%s\n",CURSORON);
  204. #endif CURFIX
  205. }
  206.  
  207.  
  208.  
  209. /*
  210.  * Command
  211.  *    Process a function key. 
  212.  *
  213.  *    The user cannot fill in slots 0 or 95 (space and del respecitively).
  214.  */
  215.  
  216. void
  217. command()
  218. {
  219.     register int c;
  220.     register int row, col;
  221.     register int i, j;
  222.     bool change, error, override;
  223.  
  224.     void build_entry(), extract_entry(), send_entry(), print_entry();
  225.     void highlight(), draw_current(), init_restore(), help();
  226.     void warning();
  227.  
  228.     change = false;
  229.     error = false;
  230.     override = false;
  231.     row = 0; col = 0;
  232.     highlight( row, col, true );
  233.  
  234.     for ( ;; ) {
  235.         c = get_key();
  236.         highlight( row, col, false );    /* turn cursor off    */
  237.  
  238.         if ( error ) {
  239.             move ( ERROR_ROW, ERROR_COL );
  240.             printf( "\033[K" );        /* Clear error message    */
  241.             move ( ERROR_ROW+1, ERROR_COL );
  242.             printf( "\033[K" );        /* Clear error message    */
  243.             error = false;
  244.         } else {
  245.             override = false;
  246.         }
  247.  
  248.         switch ( c ) {
  249.  
  250.         case KEY_FIND:        /* update DRCS     */
  251.             if ( !change && !override ) {
  252.                 warning( "No changes to save" );
  253.                 override = true;
  254.                 error = true;
  255.             } else {
  256.                 build_entry( current_entry );
  257.                 send_entry( current_entry );
  258.                 print_entry( current_entry, true );
  259.                 change = false;
  260.             }
  261.             break;
  262.  
  263.         case KEY_F6:        /* Turn on pixel    */
  264.             change = true;
  265.             display_table[row][col] = true;
  266.             highlight( row, col, false );
  267.             col = ( col + 1 ) % MAX_COLS;
  268.             if ( col == 0 )
  269.                 row = ( row + 1 ) % MAX_ROWS;
  270.             break;
  271.  
  272.         case KEY_F7:        /* Turn off pixel    */
  273.             change = true;
  274.             display_table[row][col] = false;
  275.             highlight( row, col, false );
  276.             col = ( col + 1 ) % MAX_COLS;
  277.             if ( col == 0 )
  278.                 row = ( row + 1 ) % MAX_ROWS;
  279.             break;
  280.  
  281.         case KEY_INSERT:    /* Insert a blank row    */
  282.             change = true;
  283.             for ( j = 0; j < MAX_COLS; ++j ) {
  284.                 for ( i = MAX_ROWS - 1; i > row; --i ) {
  285.                     display_table[i][j] = display_table[i-1][j];
  286.                 }
  287.                 display_table[row][j] = false;
  288.             }
  289.             draw_current();
  290.             break;
  291.     
  292.         case KEY_REMOVE:    /* Remove a row    */
  293.             change = true;
  294.             for ( j = 0; j < MAX_COLS; ++j ) {
  295.                 for ( i = row; i < MAX_ROWS - 1; ++i ) {
  296.                     display_table[i][j] = display_table[i+1][j];
  297.                 }
  298.                 display_table[MAX_ROWS-1][j] = false;
  299.             }
  300.             draw_current();
  301.             break;
  302.  
  303.         case KEY_F13:        /* Clear buffer    */
  304.             if ( change && !override ) {
  305.                 warning( "Changes not saved" );
  306.                 error = true;
  307.                 override = true;
  308.             } else {
  309.                 for ( j = 0; j < MAX_COLS; ++j ) {
  310.                     for ( i = 0; i < MAX_ROWS; ++i ) {
  311.                         display_table[i][j] = false;
  312.                     }
  313.                 }
  314.                 draw_current();
  315.             }
  316.             break;
  317.  
  318.         case KEY_SELECT:    /* Select font from DRCS    */
  319.             if ( change && !override ) {
  320.                 warning( "Changes not saved" );
  321.                 error = true;
  322.                 override = true;
  323.             } else { 
  324.                 extract_entry( current_entry );
  325.                 draw_current();
  326.             }
  327.             break;
  328.  
  329.         case KEY_PREV:        /* Move to prev entry in DRCS    */
  330.             if ( change && !override ) {
  331.                 warning( "Changes not saved" );
  332.                 override = true;
  333.                 error = true;
  334.             } else {
  335.                 print_entry( current_entry, false );
  336.                 current_entry = current_entry - 1;
  337.                 if ( current_entry == 0 ) 
  338.                     current_entry = TOTAL_ENTRIES - 2;
  339.                 print_entry( current_entry, true );
  340.             }
  341.             break;
  342.  
  343.         case KEY_NEXT:        /* Move to next entry in DRCS    */
  344.             if ( change && !override ) {
  345.                 warning( "Changes not saved" );
  346.                 override = true;
  347.                 error = true;
  348.             } else {
  349.                 print_entry( current_entry, false );
  350.                 current_entry = current_entry + 1;
  351.                 if ( current_entry  == TOTAL_ENTRIES - 1 )
  352.                     current_entry = 1;
  353.                 print_entry( current_entry, true );
  354.             }
  355.             break;
  356.  
  357.         case KEY_UP:        /* UP one row.            */
  358.             if ( row == 0 )
  359.                 row = MAX_ROWS;
  360.             row = row - 1;
  361.             break;
  362.  
  363.         case KEY_DOWN:        /* Guess.            */
  364.             row = ( row + 1 ) % MAX_ROWS;
  365.             break;
  366.  
  367.         case KEY_RIGHT:
  368.             col = ( col + 1 ) % MAX_COLS;
  369.             break;
  370.  
  371.         case KEY_LEFT:
  372.             if ( col == 0 ) 
  373.                 col = MAX_COLS;
  374.             col = col - 1;
  375.             break;
  376.  
  377.         case KEY_HELP:        /* Display helpful info        */
  378.             clear_screen();
  379.             help();
  380.             c = getchar();
  381.             init_restore();
  382.             break;
  383.  
  384.         case '\004':        /* All done!            */
  385.             return;
  386.  
  387.         case '\f':        /* Redraw display        */
  388.             init_restore();
  389.             break;
  390.  
  391.         default:        /* user is a klutzy  typist    */
  392.             move ( ERROR_ROW, ERROR_COL );
  393.             printf( "Unknown key: " );
  394.             if ( c < 0x20 ) {
  395.                 printf( "^%c", c );
  396.             } else if ( c < 0x0100 ) {
  397.                 printf( "%c", c );
  398.             } else {
  399.                 printf( "0x%04x", c );
  400.             }
  401.             fflush( stdout );
  402.             error = true;
  403.         }
  404.  
  405.         highlight( row, col, true );    /* turn cursor on    */
  406.     }
  407. }
  408.  
  409.  
  410.  
  411. char *key_table[]    = {
  412.     "\033[1~",        /* Find        */
  413.     "\033[2~",        /* Insert    */
  414.     "\033[3~",        /* Remove    */
  415.     "\033[4~",        /* Select    */
  416.     "\033[5~",        /* Prev        */
  417.     "\033[6~",        /* Next        */
  418.     "\033[17~",
  419.     "\033[18~",
  420.     "\033[19~",
  421.     "\033[20~",
  422.     "\033[21~",
  423.     "\033[23~",
  424.     "\033[24~",
  425.     "\033[25~",
  426.     "\033[26~",
  427.     "\033[28~",
  428.     "\033[29~",
  429.     "\033[31~",
  430.     "\033[32~",
  431.     "\033[33~",
  432.     "\033[34~",
  433.     "\033[A",
  434.     "\033[B",
  435.     "\033[C",
  436.     "\033[D",
  437.     (char *)0 };
  438.  
  439. /*
  440.  * get_key
  441.  *    Convert VT220 escape sequence into something more reasonable.
  442.  */
  443.  
  444. int
  445. get_key()
  446. {
  447.     register char    *p;
  448.     char    s[10];
  449.     register int i, j;
  450.  
  451.     p = s;
  452.     for ( i = 0; i < 10; ++i ) {
  453.         *p = getchar();
  454.         if ( i == 0 && *p != '\033' )
  455.             return( (int)*p );    /* Not an escape sequence */
  456.         if ( *p != '\033' && *p < 0x0020 )
  457.             return( (int)*p );    /* Control character    */
  458.         *++p = '\0';            /* Null terminate    */
  459.         for ( j = 0; key_table[j]; ++j ) {
  460.             if ( strcmp( s, key_table[j] ) == 0 )
  461.                 return( j | 0x0100 );
  462.         }
  463.     }
  464.     return( -1 );
  465. }
  466.  
  467.  
  468.  
  469. /*
  470.  * pad
  471.  *    Emit nulls so that the terminal can catch up.
  472.  */
  473.  
  474. pad()
  475. {
  476.     int i;
  477.  
  478.     for ( i = 0; i < 20; ++i )
  479.         putchar( '\000' );
  480.     fflush( stdout );
  481. }
  482.  
  483.  
  484.  
  485. /*
  486.  * init_restore
  487.  *    refresh the main display table.
  488.  */
  489.  
  490. void
  491. init_restore()
  492. {
  493.     register int row, col;
  494.     register int i;
  495.     
  496.     void  draw_current(), clear_screen(), print_entry();
  497.  
  498.     clear_screen();
  499.  
  500.     for ( col = 0; col < MAX_COLS; ++col ) {
  501.         move( ROW_OFFSET - 2, col * 3 + COL_OFFSET + 1 );
  502.         printf( "%d", col );
  503.     }
  504.     move( ROW_OFFSET - 1, COL_OFFSET );
  505.     printf( "+--+--+--+--+--+--+--+--+" );
  506.     move( ROW_OFFSET + MAX_ROWS * 2, COL_OFFSET );
  507.     printf( "+--+--+--+--+--+--+--+--+" );
  508.  
  509.     for ( row = 0; row < MAX_ROWS; ++row ) {
  510.         if ( row != 0 && row != 7 )  {
  511.             move( row * 2 + ROW_OFFSET, COL_OFFSET - 2 );
  512.             printf( "%d|", row );
  513.             move( row * 2 + ROW_OFFSET + 1, COL_OFFSET - 1 );
  514.             printf( "|" );
  515.             move( row * 2 + ROW_OFFSET, COL_OFFSET + MAX_COLS * 3 );
  516.             printf( "|" );
  517.             move( row * 2 + ROW_OFFSET + 1, COL_OFFSET + MAX_COLS * 3 );
  518.             printf( "|" );
  519.         } else {
  520.             move( row * 2 + ROW_OFFSET, COL_OFFSET - 2 );
  521.             printf( "%d*", row );
  522.             move( row * 2 + ROW_OFFSET + 1, COL_OFFSET - 1 );
  523.             printf( "*" );
  524.             move( row * 2 + ROW_OFFSET, COL_OFFSET + MAX_COLS * 3 );
  525.             printf( "*" );
  526.             move( row * 2 + ROW_OFFSET + 1, COL_OFFSET + MAX_COLS * 3 );
  527.             printf( "*" );
  528.         }
  529.     }
  530.     draw_current();
  531.  
  532.     move( TABLE_ROW - 1, TABLE_COL - 1 );
  533.     printf( "+-+-+-+-+-+-+-+-+-+-+-+-+" );
  534.     move( TABLE_ROW + 8 * 2 - 1, TABLE_COL - 1 );
  535.     printf( "+-+-+-+-+-+-+-+-+-+-+-+-+" );
  536.     for ( i = 0; i < 8; ++i ) {
  537.         move ( TABLE_ROW + i * 2, TABLE_COL - 1 );
  538.         printf( "|" );
  539.         move ( TABLE_ROW + i * 2 + 1, TABLE_COL - 1 );
  540.         printf( "+" );
  541.         move ( TABLE_ROW + i * 2, TABLE_COL + 12 * 2 - 1);
  542.         printf( "|" );
  543.         move ( TABLE_ROW + i * 2 + 1, TABLE_COL +12 * 2 - 1);
  544.         printf( "+" );
  545.     }    
  546.     for ( i = 0; i < TOTAL_ENTRIES; ++i )
  547.         print_entry( i, (i == current_entry) ? true : false );
  548. }
  549.  
  550.  
  551.  
  552. /*
  553.  * draw_current
  554.  *    Draw the complete current entry.
  555.  */
  556.  
  557. void
  558. draw_current()
  559. {
  560.     register int row, col;
  561.  
  562.     printf( "\033)0" );        /* Special graphics in G1    */
  563.     printf( "\016" );        /* Lock in G1 (SO)        */
  564.  
  565.     for ( row = 0; row < MAX_ROWS; ++row ) {
  566.         for ( col = 0; col < MAX_COLS; ++col ) {
  567.             if ( display_table[row][col] ) {
  568.                 move( row * 2 + ROW_OFFSET,     col * 3 + COL_OFFSET );
  569.                 printf( "\141\141\141" );
  570.                 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
  571.                 printf( "\141\141\141" );
  572.             } else {
  573.                 move( row * 2 + ROW_OFFSET,     col * 3 + COL_OFFSET );
  574.                 printf( "   " );     /* erase splat    */
  575.                 move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
  576.                 printf( "   " );     /* erase splat    */
  577.             }
  578.         }
  579.         pad();
  580.     }
  581.     printf( "\017" );        /* Lock in G0 (SI)    */
  582.     fflush( stdout );
  583. }
  584.  
  585.  
  586.  
  587. /*
  588.  * highlight
  589.  *    Draw the cursor in the main display area.
  590.  */
  591.  
  592. void
  593. highlight( row, col, on )
  594. unsigned int row, col;
  595. bool on;
  596. {
  597.  
  598.     printf( "\033)0" );        /* Special graphics in G1    */
  599.     printf( "\016" );        /* Lock in G1 (SO)        */
  600.     if ( on ) {
  601.         printf( "\033[7m" );    /* Reverse video cursor        */
  602.     }
  603.  
  604.     if ( display_table[row][col] ) {
  605.         move( row * 2 + ROW_OFFSET,     col * 3 + COL_OFFSET );
  606.         printf( "\141\141\141" );
  607.         move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
  608.         printf( "\141\141\141" );
  609.     } else {
  610.         move( row * 2 + ROW_OFFSET,     col * 3 + COL_OFFSET );
  611.         printf( "   " );     /* erase splat    */
  612.         move( row * 2 + ROW_OFFSET + 1, col * 3 + COL_OFFSET );
  613.         printf( "   " );     /* erase splat    */
  614.     }
  615.     pad();
  616.     printf( "\017" );        /* Lock in G0 (SI)    */
  617.     printf( "\033[0m" );        /* normal video        */
  618.     printf( "\b" );            /* Back up one spot    */
  619.     fflush( stdout );
  620. }
  621.  
  622.  
  623.  
  624. /*
  625.  * Clear_screen
  626.  */
  627.  
  628. void
  629. clear_screen()
  630. {
  631.     printf( "\033[H\033[J" );        /* Clear screen.    */
  632.     fflush( stdout );
  633. }
  634.  
  635.  
  636.  
  637. /*
  638.  * move
  639.  */
  640.  
  641. move( y, x )
  642. int y, x;
  643. {
  644.     printf( "\033[%d;%df", y, x );
  645. }
  646.  
  647.  
  648.  
  649. /*
  650.  * Build_entry
  651.  *    Convert the bit pattern used in the main display area into something
  652.  *    that the vt220 can digest - namely sixels...
  653.  */
  654.  
  655. void
  656. build_entry( entry_no )
  657. unsigned int entry_no;
  658. {
  659.     register int row, col;
  660.     register unsigned int mask;
  661.  
  662.     for ( col = 0; col < 8; ++col ) {
  663.  
  664.         /* Top set of sixels    */
  665.  
  666.         mask = 0;
  667.         for ( row = 5; row >= 0; --row ) {
  668.             mask = mask << 1;
  669.             if ( display_table[row][col] )
  670.                 mask |= 1;
  671.         }
  672.         font_table[entry_no][col] = mask + 077;
  673.  
  674.         /*  Bottom set of sixels    */
  675.  
  676.         mask = 0;
  677.         for ( row = 9; row >= 6; --row ) {
  678.             mask = mask << 1;
  679.             if ( display_table[row][col] )
  680.                 mask |= 1;
  681.         }
  682.         font_table[entry_no][col+8] = mask + 077;
  683.     }
  684.         
  685. }
  686.  
  687.  
  688.  
  689. /*
  690.  * Extract_engry
  691.  *    convert sixel representation into an array of bits.
  692.  */
  693.  
  694. void
  695. extract_entry( entry_no )
  696. unsigned int entry_no;
  697. {
  698.     register int row, col;
  699.     register unsigned int mask;
  700.  
  701.     for ( col = 0; col < 8; ++col ) {
  702.  
  703.         /* Top set of sixels    */
  704.  
  705.         mask = font_table[entry_no][col];
  706.         if ( mask >= 077 ) 
  707.             mask -= 077;
  708.         else
  709.             mask = 0;        /* Bogus entry    */
  710.  
  711.         for ( row = 0; row <= 5; ++row ) {
  712.             display_table[row][col] = (bool)(mask & 0x0001);
  713.             mask = mask >> 1;
  714.         }
  715.  
  716.         /*  Bottom set of sixels    */
  717.  
  718.         mask = font_table[entry_no][col+8];
  719.         if ( mask >= 077 )
  720.             mask -= 077;
  721.         else
  722.             mask = 0;
  723.  
  724.         for ( row = 6; row <= 9; ++row ) {
  725.             display_table[row][col] = (bool)(mask & 0x0001);
  726.             mask = mask >> 1;
  727.         }
  728.     }
  729.         
  730. }
  731.  
  732.  
  733.  
  734. /*
  735.  * Send_entry
  736.  *    Emit the stuff used by the VT220 to load a character into the
  737.  *    DRCS.  We could, of course, send more than one entry at a time...
  738.  */
  739.  
  740. void
  741. send_entry( entry_no )
  742. int entry_no;
  743. {
  744.     register char *fp    = font_table[entry_no];
  745.  
  746.     printf( "\033P1;%d;1;0;0;0{ @%c%c%c%c%c%c%c%c/%c%c%c%c%c%c%c%c\033\\", 
  747.         entry_no,
  748.         fp[ 0], fp[ 1], fp[ 2], fp[ 3], fp[ 4], fp[ 5], fp[ 6], fp[ 7],
  749.         fp[ 8], fp[ 9], fp[10], fp[11], fp[12], fp[13], fp[14], fp[15] );
  750. }
  751.  
  752.  
  753.  
  754. /*
  755.  * Print_entry
  756.  *    The terminal normally has G0 in GL.  We don't want to change
  757.  *    this, nor do we want to use GR.  Sooooo send out the necessary
  758.  *    magic for shifting in G2 temporarily for the character that we
  759.  *    want to display.
  760.  */
  761.  
  762. void
  763. print_entry( entry_no, highlight )
  764. register unsigned int entry_no;
  765. bool highlight;
  766. {
  767.  
  768.     register int y, x;
  769.  
  770.     y = entry_no & 0x07;
  771.     x = entry_no >> 3 & 0x1f;
  772.     entry_no += 32;            /* Map up to G set    */
  773.  
  774.     move( y * 2 + TABLE_ROW, x * 2 + TABLE_COL );
  775.  
  776.     if ( highlight )
  777.         printf( "\033[7m" );
  778.  
  779.     printf( "\033* @" );        /* select DRCS into G2    */
  780.     printf( "\033N" );        /* select single shift    */
  781.     printf( "%c", entry_no );    /* Draw the character    */
  782.  
  783.     if ( highlight )
  784.         printf( "\033[0m" );
  785. }
  786.  
  787.  
  788.  
  789. /*
  790.  * Save_table
  791.  *    Save a font table
  792.  */
  793.  
  794. void
  795. save_table( font_file )
  796. FILE *font_file;
  797. {
  798.     register char *fp;
  799.     register int i;
  800.  
  801.     for ( i = 0; i < TOTAL_ENTRIES; ++i ) {
  802.         fp = font_table[i];
  803.         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", 
  804.             i, 
  805.             fp[ 0], fp[ 1], fp[ 2], fp[ 3], fp[ 4], fp[ 5], fp[ 6], fp[ 7],
  806.             fp[ 8], fp[ 9], fp[10], fp[11], fp[12], fp[13], fp[14], fp[15] );
  807.     }
  808. }
  809.  
  810.  
  811.  
  812. /*
  813.  * Get_table
  814.  *    Extract font table entries from a file
  815.  */
  816.  
  817. void
  818. get_table( font_file )
  819. FILE *font_file;
  820. {
  821.     char    s[256];
  822.     register char    *p;
  823.     char    *fp;
  824.     int i;
  825.     register int j;
  826.  
  827.     while( fgets( s, 255, font_file ) ) {
  828.         if ( strncmp( s, "\033P1;", 4 ) !=  0 ) 
  829.             continue;    /* Bogus line    */
  830.         p = &s[4];
  831.         if ( sscanf( p, "%d", &i ) != 1 ) 
  832.             continue;    /* Illegal entry number    */
  833.  
  834.         if ( i <= 0 || TOTAL_ENTRIES <= i )
  835.             continue;    /* Bogues entry    */
  836.  
  837.         fp = font_table[i];
  838.  
  839.         while ( *p && *p != '@' )
  840.             ++p;        /* Skip to font definition */
  841.         if ( ! *p++ ) 
  842.             continue;    /* Skip @    */
  843.  
  844.         for ( j = 0; *p && *p != '\033' && j < 16; ++j, ++p ) {
  845.             if ( *p == '/' ) {
  846.                 j = 8; 
  847.                 ++p;
  848.             }
  849.             fp[j] = *p;
  850.         }
  851.         send_entry( i );
  852.     }
  853. }
  854.  
  855.  
  856.  
  857. /*
  858.  * Help
  859.  *    Print out help information.
  860.  */
  861.  
  862. void
  863. help()
  864. {
  865.     printf( "Font editor\n\n" );
  866.     printf( "F6     - Pixel on\n" );
  867.     printf( "F7     - Pixel off\n" );
  868.     printf( "F13    - Clear display area\n" );
  869.     printf( "HELP   - This screen\n" );
  870.     printf( "FIND   - Update font table\n" );
  871.     printf( "INSERT - Insert a blank row\n" );
  872.     printf( "REMOVE - Remove a row\n" );
  873.     printf( "SELECT - Select current font table entry\n" );
  874.     printf( "PREV   - Move to previous font table entry\n" );
  875.     printf( "NEXT   - Move to next font table entry\n" );
  876.     printf( "^D     - Exit\n" );
  877.     printf( "\n\n\n\nPress any key to continue\n" );
  878. }
  879.  
  880.  
  881.  
  882. /*
  883.  * Warning
  884.  *    Issue a warning to the regarding the current status.
  885.  */
  886.  
  887. void
  888. warning( s )
  889. char *s;
  890. {
  891.     move( ERROR_ROW, ERROR_COL );
  892.     printf( "Warning: %s!\n", s );
  893.     move( ERROR_ROW+1, ERROR_COL );
  894.     printf( "         Reissue command to override\n" );
  895. }
  896.