home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Appls / dpv / choose.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  8.6 KB  |  434 lines  |  [TEXT/????]

  1. /* Application to choose ditroff special character names
  2.    for glyphs in a given font.
  3.    Usage: choose [-f  glyphfont] [-s size] [-c columns]
  4.    Mac defaults: -f Symbol -s 24 -c 8
  5.    X defaults: -f '*-symbol-*--24-*' -c 8
  6.  
  7.    TO DO:
  8.        - start with font choosing dialog on Mac
  9.     - more object-like file interface (pretend we're editing
  10.       a table object)
  11.     - more syntax checking on input
  12.     - check for duplicate names?
  13. */
  14.  
  15. #define CHARWIDTHBUG        /* wcharwidth(i) == 0 for all i >= 128 */
  16.  
  17. #include <stdwin.h>
  18. #include <tools.h>
  19.  
  20. /* Number of possible characters per font -- limited by char = 8 bit */
  21. #define NGLYPHS 256
  22.  
  23. /* Table of names for each char -- 3rd is terminating zero */
  24. char namelist[NGLYPHS][3];
  25.  
  26. /* Random global variables */
  27. char *progname= "choose";    /* Program name for error messages */
  28. WINDOW *win;            /* Where it all happens */
  29. int selected= -1;        /* Glyph currently selected, -1 if none */
  30. bool changed;            /* Set if any changes made */
  31. char *filename;            /* Namelist file name */
  32.  
  33. /* Variables controlling the window lay-out */
  34. char *glyphfont, *namefont;    /* Fonts used for ditto */
  35. int glyphsize, namesize;    /* Point sizes used for glyph and name */
  36. int firstglyph, lastglyph;    /* First and last glyphs */
  37. int ncols, nrows;        /* Matrix dimensions */
  38. int colwidth, rowheight;    /* Cell dimensions */
  39.  
  40. /* Parse the command line */
  41.  
  42. parse(argc, argv)
  43.     int argc;
  44.     char **argv;
  45. {
  46.     if (argc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
  47.         progname= strrchr(argv[0], '/');
  48.         if (progname == NULL)
  49.             progname= argv[0];
  50.         else
  51.             progname++;
  52.     }
  53.     
  54.     for (;;) {
  55.         int c= getopt(argc, argv, "c:f:s:");
  56.         if (c == EOF)
  57.             break;
  58.         switch (c) {
  59.         case 'c':
  60.             ncols= atoi(optarg);
  61.             break;
  62.         case 'f':
  63.             glyphfont= optarg;
  64.             break;
  65.         case 's':
  66.             glyphsize= atoi(optarg);
  67.             break;
  68.         default:
  69.             usage();
  70.             /*NOTREACHED*/
  71.         }
  72.     }
  73.     
  74.     if (optind < argc)
  75.         filename= argv[optind++];
  76.     
  77.     if (optind < argc)
  78.         usage();
  79. }
  80.  
  81. /* Print usage message and exit */
  82.  
  83. usage()
  84. {
  85.     wdone();
  86.     fprintf(stderr, "usage: %s [-c columns] [-f font] [-s size]\n",
  87.         progname);
  88.     exit(2);
  89. }
  90.  
  91. /* Initialize the control variables */
  92.  
  93. setup()
  94. {
  95.     /* Fill in defaults */
  96.     if (ncols <= 0)
  97.         ncols= 8;
  98.     if (glyphfont == NULL || *glyphfont == EOS) {
  99. #ifdef macintosh
  100.         glyphfont= "Symbol";
  101. #else
  102. #ifdef X11R2
  103.         glyphfont= "symbol22";
  104. #else
  105.         glyphfont= "*-symbol-*--24-*";
  106. #endif
  107. #endif
  108.     }
  109.     
  110.     if (glyphsize <= 0)
  111.         glyphsize= 24;
  112.     if (namefont == NULL || *namefont == EOS) {
  113. #ifdef machintosh
  114.         namefont= "Courier";
  115. #else
  116. #ifdef X11R2
  117.         namefont= "courier12f";
  118. #else
  119.         namefont= "*-courier-*--12-*";
  120. #endif
  121. #endif
  122.     }
  123.     if (namesize <= 0)
  124.         namesize= 10;
  125.     
  126.     /* Find first and last existing character */
  127.     firstglyph= 0;
  128.     lastglyph= NGLYPHS-1;
  129.     wsetfont(glyphfont);
  130.     wsetsize(glyphsize);
  131.     while (firstglyph < lastglyph && wcharwidth(firstglyph) == 0)
  132.         ++firstglyph;
  133.     firstglyph= (firstglyph/ncols) * ncols;
  134. #ifndef CHARWIDTHBUG
  135.     while (lastglyph > firstglyph && wcharwidth(lastglyph) == 0)
  136.         --lastglyph;
  137.     lastglyph= (lastglyph/ncols + 1) * ncols - 1;
  138. #endif
  139.     
  140.     /* Compute remaining variables */
  141.     nrows= (lastglyph - firstglyph + ncols) / ncols;
  142.     colwidth= 2*wcharwidth('M');
  143.     rowheight= wlineheight();
  144.     wsetfont(namefont);
  145.     wsetsize(namesize);
  146.     rowheight += 4 + wlineheight();
  147.     {
  148.         int cw= wtextwidth("MM  MM", -1) + 4;
  149.         if (colwidth < cw)
  150.             colwidth= cw;
  151.     }
  152. }
  153.  
  154. /* Draw procedure */
  155.  
  156. void
  157. drawproc(win, left, top, right, bottom)
  158.     WINDOW *win;
  159.     int left, top, right, bottom;
  160. {
  161.     int i;
  162.     
  163.     /* Draw vertical grid lines */
  164.     for (i= 1; i < ncols; ++i)
  165.         wdrawline(i*colwidth-1, 0, i*colwidth-1, nrows*rowheight);
  166.     
  167.     /* Draw horizontal grid lines */
  168.     for (i= 1; i < nrows; ++i)
  169.         wdrawline(0, i*rowheight-1, ncols*colwidth, i*rowheight-1);
  170.     
  171.     /* Draw glyph cells */
  172.     for (i= firstglyph; i <= lastglyph; ++i) {
  173.         int h, v, h2, v2;
  174.         int glyphwidth;
  175.         cellbounds(i, &h, &v, &h2, &v2);
  176.         if (v >= bottom)
  177.             break;
  178.         if (!intersects(h, v, h2, v2, left, top, right, bottom))
  179.             continue;
  180.         wsetfont(glyphfont);
  181.         wsetsize(glyphsize);
  182.         glyphwidth= wcharwidth(i);
  183. #ifndef CHARWIDTHBUG
  184.         if (glyphwidth == 0)
  185.             continue;
  186. #endif
  187.         wdrawchar(h + (colwidth-glyphwidth) / 2, v+2, i);
  188.         wsetfont(namefont);
  189.         wsetsize(namesize);
  190.         {
  191.             char buf[10];
  192.             sprintf(buf, "%02X", i);
  193.             wdrawtext(h+2, v2 - 2 - wlineheight(), buf, -1);
  194.         }
  195.         if (namelist[i][0] != EOS) {
  196.             int namewidth;
  197.             namewidth= wtextwidth(namelist[i], -1);
  198.             wdrawtext(h + colwidth - namewidth - 2,
  199.                 v2 - 2 - wlineheight(),
  200.                 namelist[i], -1);
  201.         }
  202.         if (i == selected)
  203.             winvert(h+1, v+1, h2-2, v2-2);
  204.     }
  205. }
  206.     
  207. /* Main program */
  208.  
  209. main(argc, argv)
  210.     int argc;
  211.     char **argv;
  212. {
  213.     winitargs(&argc, &argv);
  214.     parse(argc, argv);
  215.     setup();
  216.     readnamelist();
  217.     wsetdefwinsize(colwidth*ncols, 0);
  218.     win= wopen(glyphfont, drawproc);
  219.     if (win == NULL) {
  220.         wdone();
  221.         fprintf(stderr, "%s: can't create window\n", progname);
  222.     }
  223.     wsetdocsize(win, colwidth*ncols, rowheight*nrows);
  224.     eventloop();
  225.     /*NOTREACHED*/
  226. }
  227.  
  228. /* Event loop.  Never returns. */
  229.  
  230. eventloop() {
  231.     for (;;) {
  232.         EVENT e;
  233.         wgetevent(&e);
  234.         switch (e.type) {
  235.         
  236.         case WE_MOUSE_DOWN:
  237.         case WE_MOUSE_MOVE:
  238.         case WE_MOUSE_UP:
  239.             do_select(&e);
  240.             break;
  241.         
  242.         case WE_CHAR:
  243.             do_char(e.u.character);
  244.             break;
  245.         
  246.         case WE_COMMAND:
  247.             switch (e.u.command) {
  248.             case WC_CLOSE:
  249.             case WC_CANCEL:
  250.         close_it:
  251.                 if (changed) {
  252.                     int ok;
  253.                     ok= waskync("Save changes?", 1);
  254.                     if (ok > 0) {
  255.                         if (!writenamelist())
  256.                             ok= -1;
  257.                     }
  258.                     if (ok < 0)
  259.                         continue;
  260.                 }
  261.                 wclose(win);
  262.                 wdone();
  263.                 exit(0);
  264.                 /*NOTREACHED*/
  265.             case WC_BACKSPACE:
  266.                 do_char('\b');
  267.                 break;
  268.             }
  269.             break;
  270.         
  271.         case WE_CLOSE:
  272.             goto close_it;
  273.  
  274.         }
  275.     }
  276.     /*NOTREACHED*/
  277. }
  278.  
  279. /* Handle mouse events */
  280.  
  281. do_select(ep)
  282.     EVENT *ep;
  283. {
  284.     int left, top, right, bottom;
  285.     int col= ep->u.where.h / colwidth;
  286.     int row= ep->u.where.v / rowheight;
  287.     int i= firstglyph + col + ncols*row;
  288.     wsetfont(glyphfont);
  289.     wsetsize(glyphsize);
  290.     if (ep->u.where.h < 0 || ep->u.where.v < 0 ||
  291.         col >= ncols || row >= nrows ||
  292.         i < firstglyph || i > lastglyph ||
  293.         wcharwidth(i) == 0)
  294.         i= -1;
  295.     if (i != selected) {
  296.         wbegindrawing(win);
  297.         if (selected >= 0) {
  298.             cellbounds(selected, &left, &top, &right, &bottom);
  299.             winvert(left+1, top+1, right-2, bottom-2);
  300.         }
  301.         selected= i;
  302.         if (selected >= 0) {
  303.             cellbounds(selected, &left, &top, &right, &bottom);
  304.             winvert(left+1, top+1, right-2, bottom-2);
  305.         }
  306.         wenddrawing(win);
  307.     }
  308.     /* Must do this here because wshow may have no effect
  309.        while the mouse is down. */
  310.     if (selected >= 0) {
  311.         cellbounds(selected, &left, &top, &right, &bottom);
  312.         wshow(win, left, top, right, bottom);
  313.     }
  314.         
  315. }
  316.  
  317. /* Handle character events and backspace */
  318.  
  319. do_char(c)
  320.     int c;
  321. {
  322.     int n;
  323.     int left, top, right, bottom;
  324.     if (selected < 0) {
  325.         wfleep();
  326.         return;
  327.     }
  328.     if (c == '\b') {
  329.         n= 0;
  330.     }
  331.     else {
  332.         n= strlen(namelist[selected]) % 2;
  333.         namelist[selected][n++]= c;
  334.     }
  335.     namelist[selected][n]= EOS;
  336.     wsetfont(namefont);
  337.     wsetsize(namesize);
  338.     cellbounds(selected, &left, &top, &right, &bottom);
  339.     wshow(win, left, top, right, bottom);
  340.     wchange(win,
  341.         right - 3*wcharwidth('m'), bottom - 2 - wlineheight(),
  342.         right-2, bottom-2);
  343.     changed= TRUE;
  344. }
  345.  
  346. /* Subroutine to find a glyph's cell */
  347.  
  348. cellbounds(i, pleft, ptop, pright, pbottom)
  349.     int i;
  350.     int *pleft, *ptop, *pright, *pbottom;
  351. {
  352.     int row= (i - firstglyph) / ncols;
  353.     int col= (i - firstglyph) % ncols;
  354.     *pleft= col*colwidth;
  355.     *pright= *pleft + colwidth;
  356.     *ptop= row * rowheight;
  357.     *pbottom= *ptop + rowheight;
  358. }
  359.  
  360. /* Predicate for rectangle intersection */
  361.  
  362. bool
  363. intersects(l1, t1, r1, b1, l2, t2, r2, b2)
  364. {
  365.     if (l1 >= r2 || r1 <= l2)
  366.         return FALSE;
  367.     if (t1 >= b2 || b1 <= t2)
  368.         return FALSE;
  369.     return TRUE;
  370. }
  371.  
  372. /* Read the namelist */
  373.  
  374. bool
  375. readnamelist()
  376. {
  377.     FILE *fp;
  378.     char buf[256];
  379.     if (filename == NULL) {
  380.         buf[0]= EOS;
  381.         if (!waskfile("Read file:", buf, sizeof buf, FALSE))
  382.             return FALSE;
  383.         filename= strdup(buf);
  384.     }
  385.     fp= fopen(filename, "r");
  386.     if (fp == NULL) {
  387.         char buf[256];
  388.         sprintf(buf, "Can't read file %s", filename);
  389.         wmessage(buf);
  390.         return FALSE;
  391.     }
  392.     while (fgets(buf, sizeof buf, fp) != NULL) {
  393.         int glyph;
  394.         char name[256];
  395.         if (sscanf(buf, "%s - 0x%x", name, &glyph) == 2 ||
  396.             sscanf(buf, "%s 0x%x", name, &glyph) == 2) {
  397.             if (glyph >= 0 && glyph < NGLYPHS)
  398.                 strncpy(namelist[glyph], name, 2);
  399.         }
  400.     }
  401.     fclose(fp);
  402. }
  403.  
  404. /* Write the namelist */
  405.  
  406. bool
  407. writenamelist()
  408. {
  409.     char name[256];
  410.     FILE *fp;
  411.     int i;
  412.     if (filename == NULL)
  413.         name[0]= EOS;
  414.     else
  415.         strcpy(name, filename);
  416.     if (!waskfile("Write to file:", name, sizeof name, TRUE))
  417.         return FALSE;
  418.     filename= strdup(name);
  419.     fp= fopen(filename, "w");
  420.     if (fp == NULL) {
  421.         sprintf(name, "Can't create file %s", filename);
  422.         wmessage(name);
  423.         filename= NULL;
  424.         return FALSE;
  425.     }
  426.     for (i= 0; i < NGLYPHS; ++i) {
  427.         if (namelist[i][0] != EOS)
  428.             fprintf(fp, "%-2s - 0x%02X\n", namelist[i], i);
  429.     }
  430.     fclose(fp);
  431.     changed= FALSE;
  432.     return TRUE;
  433. }
  434.