home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga Shareware Floppies / ma01.dms / ma01.adf / wasp / src / wriff.c < prev    next >
C/C++ Source or Header  |  1992-01-01  |  16KB  |  772 lines

  1. /* wasp - Copyright 1991 by Steven Reiz
  2.  * see COPYING and wasp.c for further info
  3.  * wriff.c, 4/12/90 - 30/1/91,
  4.  * 5/5/91 - 2/6/91, 23/6/91, 30/6/91 - 8/7/91, 16/11/91,
  5.  * 8/12/91, 31/12/91 - 1/1/92
  6.  */
  7.  
  8. static char *sourcefile=__FILE__;
  9.  
  10. #include "wasp.h"
  11. #define WRIFFMAIN
  12. #include "wriff.h"
  13.  
  14. static int ticolors;
  15. static int mmap_size_known=1;
  16.  
  17.  
  18. void
  19. write_iff(void)
  20. {
  21.     long t;
  22.  
  23.     err=0; err2=0;
  24.     wriff_init();
  25.     decide_mode();
  26.     compute_nregs();
  27.     wrl(id('F', 'O', 'R', 'M'));
  28.     wrl(0L); /* size of the form ilbm, will be patched later */
  29.     wrl(id('I', 'L', 'B', 'M'));
  30.     write_header();
  31.     write_cmap();
  32.     write_mmap();
  33.     write_body();
  34.     write_cmap();
  35.     write_mmap();
  36.     write_body();
  37.     t=cseek_out(0L, 2);
  38.     cseek_out(4L, 0);
  39.     wrl(t-8L);
  40.     printe("IFF file written; %ld bytes, error: %ld, error2: %ld\n", t, err, err2);
  41. }
  42.  
  43.  
  44. void
  45. wriff_init(void)
  46. {
  47.     slicedo=0;
  48.     counts=NULL1;
  49.     cm=NULL1;
  50.     curcm=NULL1;
  51.     wf2rgbweight=NULL1;
  52.     cmrgb=NULL1;
  53.     newcol=NULL1;
  54.     error=NULL1;
  55.     error2=NULL1;
  56.     nrestricted=0;
  57.     restrict_changes= -1;
  58. }
  59.  
  60.  
  61. void
  62. decide_mode(void)
  63. {
  64.     float sx, sy, st;
  65.  
  66.     if (directrgb>=0) {
  67.     if (directrgb%3)
  68.         error1(E0_FATAL, E1_IFF_RGB, E2_OPTION, E3_WRONG_NR_PLANES, (int)directrgb);
  69.     nplanes=directrgb;
  70.     printe("IFF output; direct rgb, %d planes\n", nplanes);
  71.     return;
  72.     }
  73.     if ((xmode!=UNSET || ymode!=UNSET) && asc)
  74.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ASC);
  75.     if (xmode!=UNSET && hires!=HIRES_OK)
  76.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_NOHIRES);
  77.     count_pixels(0, (int)ysz-1, 1);
  78.     ticolors=icolors=count_colors(1L);
  79.     if (hires==HIRES_MAYBE)
  80.         hires=(icolors<=16 ? HIRES_OK : HIRES_NOT);
  81.     if (asc && (xsz>scrw || ysz>scrh)) {
  82.         sx=(float)scrw/(float)xsz;
  83.         sy=(float)scrh/(float)ysz;
  84.         if (sy<sx)
  85.             st=sy;
  86.         else
  87.             st=sx;
  88.         ymode=LACE;
  89.         sy=st*2.0;
  90.         if (hires==HIRES_OK) {
  91.             xmode=HIRES;
  92.             sx=st*2.0;
  93.         } else {
  94.             sx=st;
  95.             if (sy>1.0) {
  96.                 sx=sx/sy;
  97.                 sy=1.0;
  98.             }
  99.         }
  100.         if (sx!=sy || sx<1.0) {
  101.             scalef(1, sy);
  102.             scalef(0, sx);
  103.         }
  104.     }
  105.     if (xmode==UNSET) {
  106.         if (icolors<=32)
  107.             xmode=LORES;
  108.         else
  109.             xmode=HAM;
  110.     }
  111.     slicedo=sliced;
  112.     if (ymode==UNSET)
  113.         ymode=NOLACE;
  114.     if (ymode==LACE && (ysz&1))
  115.     do_enlarge((int)xsz, (int)ysz+1);
  116.     if (distrmeth2!=DISTRMETH_UNSET && xmode!=HAM)
  117.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ITMETH);
  118.     if (!inoperation && distrmeth==DISTRMETH_UNSET) {
  119.         if (xmode==EHB)
  120.             distrmeth=DEF_EHB_DISTRMETH;
  121.         else
  122.             distrmeth=DEF_DISTRMETH;
  123.     }
  124.     if (countmeth==COUNTMETH_UNSET)
  125.     countmeth=(xmode==HAM ? DEF_HAM_COUNTMETH : DEF_COUNTMETH);
  126.     if (xmode==EHB && !is_ehb_distr())
  127.     error1(E0_FATAL, E1_IFF, E2_OPTION, E3_EHB_METH, dmethnam(distrmeth));
  128.     printe("IFF output; xmode: %s%s, ymode: %s, cmeth: %s, dmeth: %s",
  129.      mmapnam((int)sliced), xmodenam(xmode), ymodenam(ymode),
  130.      cmethnam(countmeth), dmethnam(distrmeth));
  131.     if (distrmeth2!=DISTRMETH_UNSET)
  132.     printe(", dmeth2: %s", dmethnam(distrmeth2));
  133.     pute('\n');
  134. }
  135.  
  136.  
  137. int
  138. is_ehb_distr(void)
  139. {
  140.     return (distrmeth==DISTRMETH_EHB || distrmeth==DISTRMETH_MUE ? 1 : 0);
  141. }
  142.  
  143.  
  144. void
  145. compute_nregs(void)
  146. {
  147.     if (directrgb>=0)
  148.     return;
  149.     switch (xmode) {
  150.     case HAM:   nregs=16; nplanes=6; break;
  151.     case EHB:   nregs=64; nplanes=6; break;
  152.     case LORES: nregs=32; nplanes=5; break;
  153.     case HIRES: nregs=16; nplanes=4; break;
  154.     }
  155.     if (slicedo) {
  156.         cm=Malloc((ymode==LACE && sliced!=SLICED_DYN ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short));
  157.     curcm=cm;
  158.         goto compute_npixvals;
  159.     }
  160.     count_pixels(0, (int)ysz-1, 0);
  161.     icolors=count_colors(1L);
  162.     if (icolors>nregs && threshold>1) {
  163.         icolors=count_colors(threshold);
  164.         if (icolors<nregs) {
  165.             u_long mint, curt, maxt;
  166.  
  167.             printe("%d colors occur at least %ld times, trying to complete to %d\n",
  168.              icolors, threshold, nregs);
  169.             mint=1;
  170.             maxt=threshold;
  171.             while (maxt>mint+1) {
  172.                 curt=(mint+maxt)/2;
  173.                 icolors=count_colors(curt);
  174.                 if (icolors<nregs)
  175.                     maxt=curt-1;
  176.                 else
  177.                     mint=curt;
  178.             }
  179.             threshold=(mint+maxt)/2;
  180.             icolors=count_colors(threshold);
  181.             printe("%d colors occur at least %ld times\n", icolors, threshold);
  182.         }
  183.     }
  184.     if (xmode==LORES || xmode==HIRES) {
  185.         if (icolors<nregs)
  186.             nplanes=ceillog2((u_long)icolors);
  187.         else
  188.             nplanes=ceillog2((u_long)nregs);
  189.         nregs=1<<nplanes;
  190.     }
  191.     cm=Malloc(nregs*sizeof(u_short));
  192.     curcm=cm;
  193. compute_npixvals:
  194.     if (distrmeth2!=DISTRMETH_UNSET) {
  195.     cm0=Malloc(nregs*sizeof(u_short));
  196.     cmprev=Malloc(nregs*sizeof(u_short));
  197.     }
  198.     npixvals=1<<nplanes;
  199.     printe("%d colors", ticolors);
  200.     if (icolors!=ticolors)
  201.         printe(", counting %d colors", icolors);
  202.     printe(", %d color registers, %d planes", nregs, nplanes);
  203.     if (nregs-icolors>0)
  204.         printe(", %d registers wasted", nregs-icolors);
  205.     pute('\n');
  206.     if (nregs<2 || xsz<2 || ysz<2)
  207.     error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_2SIMPLE);
  208.     assert(nplanes>0 && nplanes<=MAXNPLANES);
  209.     assert(nregs<=MAXNREGS);
  210. }
  211.  
  212.  
  213. void
  214. write_header(void)
  215. {
  216.     struct bmhd_t {
  217.         u_short w, h;
  218.         short x, y;
  219.         u_char nplanes, masking, compression, pad;
  220.         u_short transpcol;
  221.         u_char xaspect, yaspect;
  222.         short pagew, pageh;
  223.     } bmhd;
  224.     u_long viewmodes;
  225.  
  226.     wrl(id('B', 'M', 'H', 'D'));
  227.     wrl((long)sizeof(bmhd));
  228.     bmhd.w=xsz;
  229.     bmhd.h=ysz;
  230.     bmhd.x=bmhd.y=0;
  231.     bmhd.nplanes=nplanes;
  232.     bmhd.masking=0;
  233.     bmhd.compression=compression;
  234.     bmhd.pad=0;
  235.     bmhd.transpcol=0;
  236.     bmhd.yaspect=11;
  237.     if (xmode==HIRES && ymode==NOLACE)
  238.         bmhd.xaspect=5;
  239.     else if (xmode!=HIRES && ymode==LACE)
  240.         bmhd.xaspect=20;
  241.     else
  242.         bmhd.xaspect=10;
  243.     bmhd.pagew=bmhd.w;
  244.     bmhd.pageh=bmhd.h;
  245.     cwrite(&bmhd, sizeof(bmhd));
  246.     if (directrgb>=0)
  247.     return;
  248.     wrl(id('C', 'A', 'M', 'G'));
  249.     wrl(4L);
  250.     viewmodes=0;
  251.     if (xmode==HIRES)
  252.         viewmodes|=VM_HIRES;
  253.     else if (xmode==HAM)
  254.         viewmodes|=VM_HAM;
  255.     else if (xmode==EHB)
  256.         viewmodes|=VM_EHB;
  257.     if (ymode==LACE)
  258.         viewmodes|=VM_LACE;
  259.     wrl(viewmodes);
  260. }
  261.  
  262.  
  263. void
  264. write_cmap(void)
  265. {
  266.     u_char *cmbuf;
  267.     long t;
  268.     short i, j, nr;
  269.     static long pos= -1;
  270.  
  271.     if (directrgb>=0)
  272.     return;
  273.     if (xmode==EHB)
  274.         nr=nregs/2;
  275.     else
  276.         nr=nregs;
  277.     t=nr*3;
  278.     if (pos== -1) {
  279.         wrl(id('C', 'M', 'A', 'P'));
  280.         wrl(t);
  281.         pos=cseek_out(0L, 1);
  282.     } else
  283.         cseek_out(pos, 0);
  284.     cmbuf=Malloc(t);
  285.     for (i=0, j=0; i<nr; ++i) {
  286.         cmbuf[j++]=(cm[i]&0x0f00)>>4;
  287.         cmbuf[j++]= cm[i]&0x00f0;
  288.         cmbuf[j++]=(cm[i]&0x000f)<<4;
  289.     }
  290.     cwrite(cmbuf, (int)t);
  291.     free(cmbuf);
  292. }
  293.  
  294.  
  295. void
  296. write_mmap(void)
  297. {
  298.     long t;
  299.     static long pos= -1;
  300.  
  301.     if (!slicedo)
  302.         return;
  303.     if (xmode==EHB)
  304.         error0(E0_FATAL, E1_IFF, E2_EHB, E3_SLICED_EHB);
  305.     t=(ymode==LACE && sliced!=SLICED_DYN ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short);
  306.     if (pos== -1) {
  307.         pos=cseek_out(0L, 2);
  308.         switch (sliced) {
  309.         case SLICED_SHAM: {
  310.             short ver;
  311.  
  312.             wrl(id('S', 'H', 'A', 'M'));
  313.             wrl(t+2);
  314.             ver=0;
  315.             cwrite(&ver, 2);
  316.             cwrite(cm, (int)t);
  317.         } break;
  318.         case SLICED_DYN:
  319.             wrl(id('C', 'T', 'B', 'L'));
  320.             wrl(t);
  321.             cwrite(cm, (int)t);
  322.         break;
  323.         case SLICED_PCHG:
  324.             mmap_size_known=0;
  325.         break;
  326.         default:
  327.             assert(0);
  328.         break;
  329.         }
  330.     } else {
  331.         switch (sliced) {
  332.         case SLICED_SHAM:
  333.             cseek_out(pos+10, 0);
  334.             cwrite(cm, (int)t);
  335.         break;
  336.         case SLICED_DYN:
  337.             cseek_out(pos+8, 0);
  338.             cwrite(cm, (int)t);
  339.         break;
  340.         case SLICED_PCHG:
  341.             cseek_out(pos, 0);
  342.             write_1pchg();
  343.         break;
  344.         }
  345.         if (nrestricted)
  346.             printe("restricting per line changes to %d made %lu changes unsatisfiable\n",
  347.              restrict_changes, nrestricted);
  348.     }
  349. }
  350.  
  351.  
  352. void
  353. write_1pchg(void)
  354. {
  355.     short Compression, Flags, StartLine, LineCount;
  356.     short ChangedLines, MinReg, MaxReg, MaxChanges;
  357.     long TotalChanges;
  358.     int firstchange, lastchange, nmaps, linemask_size, changes_size;
  359.     u_short *cmptr, *cmptr2, *cmend;
  360.     u_long *linemask;
  361.     u_short *changes, *changesp, *changesp2;
  362.     short i;
  363.     int mapnum, regnum, nchanges, nchanges32;
  364.     long linemask_index;
  365.  
  366.     assert(nregs<=32);
  367.     nmaps=(ymode==LACE ? (ysz+1)/2 : ysz);
  368.     /* compute firstchange, the mapnr of the first map different
  369.      * from the first map
  370.      */
  371.     cmptr=cm;
  372.     for (firstchange=0; firstchange<nmaps; ++firstchange) {
  373.         cmptr2=cm;
  374.         i=nregs-1;
  375.         do {
  376.             if (*cmptr++ != *cmptr2++)
  377.                 goto firstchange_found;
  378.         } while (--i>=0);
  379.     }
  380. firstchange_found:
  381.     if (firstchange>=nmaps)
  382.         return;
  383.     /* compute lastchange, the mapnr of the last map different
  384.      * from the last map, +1
  385.      */
  386.     cmend=cm+nregs*nmaps;
  387.     cmptr=cmend;
  388.     for (lastchange=nmaps-1; lastchange>=0; --lastchange) {
  389.         cmptr2=cmend;
  390.         i=nregs-1;
  391.         do {
  392.             if (*--cmptr != *--cmptr2)
  393.                 goto lastchange_found;
  394.         } while (--i>=0);
  395.     }
  396. lastchange_found:
  397.     ++lastchange;
  398.     /* fill in some of the header fields, allocate the linemask */
  399.     Compression=PCHG_COMP_NONE;
  400.     Flags=PCHGF_12BIT;
  401.     StartLine=(ymode==LACE ? 2*firstchange : firstchange);
  402.     LineCount=(ymode==LACE ? 2*lastchange : lastchange)-StartLine+1;
  403.     linemask_size=(LineCount+31)/32*4;
  404.     linemask=Calloc(linemask_size);
  405.     /* compute the other header fields, fill linemask */
  406.     ChangedLines=0;
  407.     MinReg=nregs-1;
  408.     MaxReg=0;
  409.     MaxChanges=0;
  410.     TotalChanges=0;
  411.     cmptr=cm+firstchange*nregs;
  412.     for (mapnum=firstchange; mapnum<=lastchange; ++mapnum) {
  413.         cmptr2=cmptr-nregs;
  414.         nchanges=0;
  415.         for (regnum=0; regnum<nregs; ++regnum) {
  416.             if (cmptr[regnum]!=cmptr2[regnum]) {
  417.                 ++nchanges;
  418.                 if (regnum<MinReg)
  419.                     MinReg=regnum;
  420.                 if (regnum>MaxReg)
  421.                     MaxReg=regnum;
  422.             }
  423.         }
  424.         if (nchanges) {
  425.             ++ChangedLines;
  426.             if (nchanges>MaxChanges)
  427.                 MaxChanges=nchanges;
  428.             TotalChanges+=nchanges;
  429.             linemask_index=mapnum-firstchange;
  430.             if (ymode==LACE)
  431.                 linemask_index<<=1;
  432.             linemask[linemask_index>>5]|=1L<<(31-(linemask_index & 0x1f));
  433.         }
  434.         cmptr+=nregs;
  435.     }
  436.     /* allocate the changes */
  437.     changes_size=(int)ChangedLines*2+TotalChanges*2;
  438.     changes=Malloc(changes_size);
  439.     /* fill changes */
  440.     cmptr=cm+firstchange*nregs;
  441.     changesp=changes;
  442.     for (mapnum=firstchange; mapnum<=lastchange; ++mapnum) {
  443.         cmptr2=cmptr-nregs;
  444.         nchanges=0;
  445.         nchanges32=0;
  446.         changesp2=changesp+1;
  447.         for (regnum=0; regnum<nregs; ++regnum) {
  448.             if (cmptr[regnum]!=cmptr2[regnum]) {
  449.                 if (regnum<16)
  450.                     ++nchanges;
  451.                 else
  452.                     ++nchanges32;
  453.                 *changesp2++ =(regnum<<12)|cmptr[regnum];
  454.             }
  455.         }
  456.         if (nchanges+nchanges32) {
  457.             *changesp=(nchanges<<8)|nchanges32;    /* BYTEORDER */
  458.             changesp=changesp2;
  459.         }
  460.         cmptr+=nregs;
  461.     }
  462.     assert(changesp==(u_short *)((long)changes+changes_size));
  463.     /* write the chunk */
  464.     wrl(id('P', 'C', 'H', 'G'));
  465.     wrl(20L+(long)linemask_size+(long)changes_size);
  466.     wrs(Compression);
  467.     wrs(Flags);
  468.     wrs(StartLine);
  469.     wrs(LineCount);
  470.     wrs(ChangedLines);
  471.     wrs(MinReg);
  472.     wrs(MaxReg);
  473.     wrs(MaxChanges);
  474.     wrl(TotalChanges);
  475.     cwrite(linemask, linemask_size);
  476.     cwrite(changes, changes_size);
  477.     /* deallocate data */
  478.     free(linemask);
  479.     free(changes);
  480. }
  481.  
  482.  
  483. void
  484. write_body(void)
  485. {
  486.     static long tmpnum= -1;
  487.     static long pos;
  488.  
  489.     if (tmpnum== -1) {
  490.         if (mmap_size_known) {
  491.             pos=cseek_out(0L, 2);
  492.             write_1body();
  493.             tmpnum= -2;
  494.         } else {
  495.             cout_tmp();
  496.             write_1body();
  497.             cout_default(&tmpnum, &pos); /* pos used as dummy here */
  498.         }
  499.     } else {
  500.         long endpos;
  501.  
  502.         if (!mmap_size_known) {
  503.             pos=cseek_out(0L, 2);
  504.             ctmp_move(tmpnum);
  505.         }
  506.         endpos=cseek_out(0L, 2);
  507.         cseek_out(pos+4, 0);
  508.         wrl(endpos-pos-8);
  509.     }
  510. }
  511.  
  512.  
  513. void
  514. write_1body(void)
  515. {
  516.     int y, step;
  517.     void (*outfunc)(int);
  518.  
  519.     if (directrgb<0)
  520.     fillconv();
  521.     if (xmode==HAM)
  522.     assert(nplanes==6);
  523.     if (!inoperation) {
  524.         wrl(id('B', 'O', 'D', 'Y'));
  525.         wrl(0L);
  526.     }
  527.     bytesperrow=(xsz+15)/16*2;
  528.     noutrows=MAXOUTBUFSZ/(bytesperrow*nplanes);
  529.     if (noutrows==0)
  530.         noutrows=1;
  531.     outbufsz=noutrows*bytesperrow*nplanes;
  532.     outrows=Malloc(outbufsz);
  533.     if (compression)
  534.     outcrows=Malloc(outbufsz*3/2);
  535.     body_size=0;
  536.     curcm=cm;
  537.     if (xmode==HAM) {
  538.     fill_prgbtab();
  539.         outfunc=ham_row_out;
  540.     } else
  541.         outfunc=row_out;
  542.     if (directrgb>=0) {
  543.     nzero=nplanes/3-4;
  544.     if (nzero<0)
  545.         nzero=0;
  546.     ncolor=nplanes/3;
  547.     if (ncolor>4)
  548.         ncolor=4;
  549.     init_counter(0, (int)ysz, 10, "writing RGB IFF");
  550.     for (y=0; y<ysz; ++y)
  551.         rgb_row_out(y);
  552.     } else if (slicedo) {
  553.         if (ymode==LACE && sliced!=SLICED_DYN)
  554.             step=2;
  555.         else
  556.             step=1;
  557.     init_counter(0, (int)ysz, 5, "writing multimap IFF");
  558.         for (y=0; y<ysz; y+=step) {
  559.             if (y==ysz-1)
  560.                 step=1;
  561.             count_pixels(y, y+step-1, 0);
  562.             icolors=count_colors(threshold);
  563.             if (icolors<nregs && threshold>1)
  564.                     printe("in row %d (and %d) only %d colors occur at least %ld times\n",
  565.                      y, y+step-1, icolors, threshold);
  566.             compute_distr(y, y+step-1);
  567.             outfunc(y);
  568.             if (step==2)
  569.                 outfunc(y+1);
  570.             curcm+=nregs;
  571.         }
  572.     } else {
  573.         compute_distr(0, (int)ysz-1);
  574.     init_counter(0, (int)ysz, 10, "writing IFF");
  575.         for (y=0; y<ysz; ++y)
  576.             outfunc(y);
  577.     }
  578.     if (!inoperation)
  579.         (void)next_row(1); /* to flush the row buffer */
  580.     erase_counter(NULL);
  581. }
  582.  
  583.  
  584. void
  585. fillconv(void)
  586. {
  587.     short i, j, k;
  588.     u_char *p;
  589.  
  590.     conv=Malloc(npixvals*8*MAXNPLANES);
  591.     p=conv;
  592.     for (i=0; i<npixvals; ++i) {
  593.         for (j=128; j; j>>=1) {
  594.             for (k=0; k<nplanes; ++k) {
  595.                 if (i&(1<<k))
  596.                     *p++ =j;
  597.                 else
  598.                     *p++ =0;
  599.             }
  600.             p+=MAXNPLANES-nplanes;
  601.         }
  602.     }
  603. }
  604.  
  605.  
  606. int
  607. cmpcolregs(short *p1, short *p2)
  608. {
  609.     short c1, c2, i;
  610.  
  611.     c1= *p1;
  612.     c2= *p2;
  613.     i=((c1>>8) + ((c1&0x00f0)>>4) + (c1&0x000f))
  614.     - ((c2>>8) + ((c2&0x00f0)>>4) + (c2&0x000f));
  615.     if (i)
  616.         return (int)i;
  617.     i=(c1>>8)-(c2>>8);
  618.     if (i)
  619.         return (int)i;
  620.     i=((c1&0x00f0)>>4)-((c2&0x00f0)>>4);
  621.     if (i)
  622.         return (int)i;
  623.     i=(c1&0x000f)-(c2&0x000f);
  624.     return (int)i;
  625. }
  626.  
  627.  
  628. void
  629. sort_cm(void)
  630. {
  631.     qsort((char *)curcm, (int)nregs, sizeof(u_short),
  632.      (int (*)(void *, void *))cmpcolregs);
  633. }
  634.  
  635.  
  636. static char *qm="?";
  637.  
  638. static char *sliceds[]={
  639.     "ok",
  640.     "not",
  641.     "maybe",
  642.     NULL
  643. };
  644.  
  645. char *
  646. slicednam(int i)
  647. {
  648.     if (i<0 || i>2)
  649.         return qm;
  650.     return sliceds[i];
  651. }
  652.  
  653.  
  654. static char *xmodes[]={
  655.     "unset",
  656.     "hires",
  657.     "lores",
  658.     "ehb",
  659.     "ham",
  660.     NULL
  661. };
  662.  
  663. char *
  664. xmodenam(int i)
  665. {
  666.     if (i<0 || i>4)
  667.         return qm;
  668.     return xmodes[i];
  669. }
  670.  
  671.  
  672. static char *ymodes[]={
  673.     "unset",
  674.     "lace",
  675.     "nolace",
  676.     NULL
  677. };
  678.  
  679. char *
  680. ymodenam(int i)
  681. {
  682.     if (i<0 || i>2)
  683.         return qm;
  684.     return ymodes[i];
  685. }
  686.  
  687.  
  688. /* should be in same order as DISTRMETH_ defines in wasp.h */
  689. static char *dmeths[]={
  690.     "unset",
  691.     "mu",
  692.     "wf",
  693.     "ehb",
  694.     "mue",
  695.     "hs",
  696.     "con",
  697.     NULL
  698. };
  699.  
  700. char *
  701. dmethnam(int i)
  702. {
  703.     if (i<0 || i>6)
  704.         return qm;
  705.     return dmeths[i];
  706. }
  707.  
  708. int
  709. dmethnum(char *s)
  710. {
  711.     int i;
  712.  
  713.     for (i=1; dmeths[i]; ++i)
  714.         if (!strcmp(s, dmeths[i]))
  715.             return i;
  716.     return -1;
  717. }
  718.  
  719.  
  720. /* should be in same order as COUNTMETH_ defines in wasp.h */
  721. static char *cmeths[]={
  722.     "unset",
  723.     "all1",
  724.     "alldif",
  725.     "allfdif",
  726.     "j1",
  727.     "j21",
  728.     "jdif",
  729.     "jdifsh",
  730.     "jfdif",
  731.     "jfdifsh",
  732.     "hmgs",
  733.     "hmcubic",
  734.     "hm",
  735.     NULL
  736. };
  737.  
  738. char *
  739. cmethnam(int i)
  740. {
  741.     if (i<0 || i>12)
  742.         return qm;
  743.     return cmeths[i];
  744. }
  745.  
  746. int
  747. cmethnum(char *s)
  748. {
  749.     int i;
  750.  
  751.     for (i=1; cmeths[i]; ++i)
  752.         if (!strcmp(s, cmeths[i]))
  753.             return i;
  754.     return -1;
  755. }
  756.  
  757.  
  758. static char *mmaps[]={
  759.     "",
  760.     "sliced ",
  761.     "dynamic ",
  762.     "multipalette ",
  763.     NULL
  764. };
  765.  
  766. char *
  767. mmapnam(int i)
  768. {
  769.     assert(i>=0 && i<4);
  770.     return mmaps[i];
  771. }
  772.