home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / REALITY / atom / mview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  19.5 KB  |  841 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /* mview.c
  18.  * -------
  19.  *
  20.  * $Revision: 1.58 $
  21.  *
  22.  * How to Use:
  23.  * -a                use accumulation buffer
  24.  * -b color            use background color
  25.  * -d SphereDepth        use tesselation depth SphereDepth
  26.  * -f                enter fast draw
  27.  * -h                on line help
  28.  * -m display            0 - atoms, 1 - bonds, 2 -both
  29.  * -n ModelName            use molecula model, ModelName
  30.  * -p SpherePrim        use primitive SpherePrim for rendering
  31.  * -r RadiusScaleFactor        scale all atom radii with RadiusScaleFactor
  32.  * -t SphereType        use tesselation type SphereType
  33.  * -z ZoomFactor        ZoomFactor
  34.  * -A AntialiasMode        set antialias mode AntiAliasMode
  35.  *                    0 - Off
  36.  *                    1 - on
  37.  *                    2 - smoother
  38.  *                    3 - end correct
  39.  *                    4 - smoother + end correct
  40.  * -D                enter debug mode
  41.  * -H program            execute program when help is requested
  42.  * -I dir            directory to search for model files.
  43.  * -K KernelFileName        Read kernel file KernelFileName
  44.  * -P                use panel
  45.  * -R                enter roll mode
  46.  * -W x0,y0[,x1,y1]        set screen position and size
  47.  */
  48.  
  49.  
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include <ctype.h>
  53. #include <getopt.h>
  54. #include <fmclient.h>
  55. #include <math.h>
  56. #include <gl/gl.h>
  57. #include <gl/device.h>
  58. #include <sys/types.h>
  59. #include <dirent.h>
  60. #include <gl/sphere.h>
  61.  
  62. #include "mview.h"
  63. #include "geom.h"
  64. #include "panel.h"
  65. #include "fileio.h"
  66.  
  67. #define Min(a, b) (((a) > (b)) ? (b) : (a))
  68.  
  69. /*~~~~~~~~~~~~~~~~~~~~~~~~~ global variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  70.  
  71. char *ProgName;
  72. char *HelpCmd = 0;
  73.  
  74. unsigned int BackgroundColor = 0xffcc1001;
  75. char *BackgroundImageName = 0;
  76.  
  77. int hwGfxType=0;
  78. int hwMultisample = 0;
  79. int hwAccbuf = 0;
  80. int hwStereo = 0;
  81. int hwBitmapSpheres = 1;
  82. int Debug = 0;
  83. int DispAtoms = 1;
  84. int DispBonds = 0;
  85. int DispInfo = 1;
  86. int AtomAccBuf = 0;
  87. int SpinMode = 0;
  88. int RollMode = 0;
  89. int InfoAccBuf = 0;
  90. int BondAccBuf = 0;
  91. int BondSmooth = SML_OFF;
  92. int BondEndCorrect = SML_OFF;
  93. int UsePrefposition = 0;
  94. int UsePrefsize = 0;
  95. int UsePanel = 0;
  96. int UseHelp = 0;
  97. int FastDraw = 0;
  98. float ZoomFactor = 1.0;
  99. int Multisample = 0;
  100. int Stereo = 0;
  101. int Perspective = 0;
  102. int Depthcue = 0;
  103. int BitmapSpheres = 0;
  104.  
  105. int SphereType = SPH_OCT;
  106. int SphereDepth = 8;
  107. int SpherePrim = SPH_MESH;
  108. int Hemi = 0;
  109. int Orient = 0;
  110.  
  111. fmfonthandle FontScreen, FontScreen5, FontScreen8, FontScreen10;
  112. fmfontinfo FontScreenInfo, FontScreen5Info, FontScreen8Info, FontScreen10Info;
  113.  
  114. float RadScaleFactor = 1.0;
  115. float MaxRadScaleFactor = 1.0;
  116. float MinRadScaleFactor = 0.1;
  117.  
  118. int NumAtomModels = 0;
  119. int NumBondModels = 0;
  120. int NumModels = 0;
  121. char **AtomModels = 0;
  122. char **BondModels = 0;
  123. MODEL *Models = 0;
  124. char **ModelNames = 0;
  125. int ModelId = -1;
  126.  
  127. char *ModelName = 0;
  128.  
  129. int AtomModelId = -1;
  130. int BondModelId = -1;
  131.  
  132. int KernelId = -1;
  133. char **Kernels = 0;
  134. int NumKernels = 0;
  135.  
  136. char *KernelFile = 0;
  137.  
  138. /*~~~~~~~~~~~~~~~~~~~~~~~~~ static variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  139.  
  140. static char StrOption[] = "A:BDH:I:K:N:PRTW:ab:d:fhi:k:ln:p:r:st:w:z:?";
  141. static char StrUsage[] = "[-DPRhf] [-n ModelName] [-r RadiusFactor] [-b color] [-z ZoomFactor] [-W x0,y0[,x1,y1]] [-t SphereType] [-d SphereDepth] [-p SpherePrim] [-K KernelFileName] [-I directory]";
  142.  
  143. #define NUM_DIRS 10
  144. static char *Dirs[NUM_DIRS] = {
  145.     ".", 
  146.     "/usr/demos/data/atom"
  147. };
  148. static int NumDirs = 2;
  149.  
  150. static int GraphicsInitialized = 0;
  151.  
  152. extern long HelpWid;
  153.  
  154. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  155.  
  156. static void ParseArgs(int argc, char **argv);
  157. static void Usage(void);
  158. static void InitGraphics(void);
  159. static void InitFonts(void);
  160. static void InitQueue(void);
  161. static void DoEvents(void);
  162. static void InitModels(void);
  163. static void SetModelId(void);
  164. static int GetNumFiles(char *dir, char *s);
  165. static int GetFileNames(char *dir, char *s, char **file);
  166. static void AddDir(char *dir);
  167. static void SetKernelId(void);
  168. static unsigned int atox(char *);
  169. int strcmpr(char *s1, char *s2);
  170.  
  171. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  172.  
  173. void main(int argc, char **argv)
  174. {
  175.     ProgName = strdup(argv[0]);        /* program name                */
  176.     ParseArgs(argc, argv);        /* parse command line            */
  177.     InitModels();            /* initialize model names array        */
  178.     SetModelId();            /* according to the model name        */
  179.     InitKernels();            /* initialize kernel names array    */
  180.     SetKernelId();            /* according to the kernel file        */
  181.     if (KernelId != -1)            /* if a specific kernel is provided */
  182.     ReadKernel(Kernels[KernelId]);    /* ...read the kernel file        */
  183.     if (ModelId != -1)            /* if a specific model is provided  */
  184.     InitData();            /* ...initialize the data        */
  185.     InitGraphics();            /* open the windows and initialize  */
  186.     InitQueue();            /* initialize the queue            */
  187.     InitFonts();            /* initialize the fonts used        */
  188.     InitPanel();
  189.     if (UsePanel) OpenPanelWindow();
  190.     if (UsePanel) DrawPanel();        /* draw the panel            */
  191.     if (UseHelp) DoHelp(0);
  192.     OpenGeomWindow();
  193.     DefineLight();            /* define lights properties        */
  194.     DoLineSmooth();
  195.     InitSphere();            /* initialize the sphere parameters */
  196.     CalcInfo();                /* calculate teh sphere info        */
  197.     if (AtomAccBuf || BondAccBuf)    /* if specified,            */
  198.     InitAccBuf();            /* initialize the accumulation buf  */
  199.     DoReset();                /* Reset transformation matrix        */
  200.     if ((DispAtoms && AtomAccBuf) || (DispBonds && BondAccBuf))
  201.     DisplayAccScene();
  202.     else DisplayScene();
  203.     DoEvents();
  204. }
  205.  
  206. static void ParseArgs(int argc, char **argv)
  207. {
  208.     int opt;
  209.     int i;
  210.     char *tmp;
  211.  
  212.     opterr = 0;                    /* disable getopt error msgs    */
  213.     while ((opt = getopt(argc, argv, StrOption)) != EOF) {
  214.     switch(opt) {
  215.       case '?':
  216.         Usage();
  217.         DoExit(0);
  218.       case 'a':
  219.         AtomAccBuf = 1 - AtomAccBuf;
  220.         printf("AtomAccBuf=%d\n", AtomAccBuf);
  221.         break;
  222.       case 'b':
  223.         BackgroundColor = atox(optarg);
  224.         printf("BackgroundColor=%x\n", BackgroundColor);
  225.         break;
  226.       case 'd':
  227.         SphereDepth = atoi(optarg);
  228.         printf("SphereDepth=%d\n",SphereDepth);
  229.         break;
  230.       case 'f': 
  231.         FastDraw = 1 - FastDraw;
  232.         printf("FastDraw=%d\n", FastDraw);
  233.         break;
  234.       case 'h':
  235.         UseHelp = 1;
  236.         break;
  237.       case 'i': 
  238.         BackgroundImageName = strdup(optarg);
  239.         printf("BackgroundImageName=%d\n", BackgroundImageName);
  240.         break;
  241.       case 'n':
  242.         ModelName = strdup(optarg);
  243.         break;
  244.       case 'p':
  245.         printf("SpherePrim=%d\n", SpherePrim);
  246.         break;
  247.       case 'r':
  248.         RadScaleFactor = atof(optarg);
  249.         printf("RadScaleFactor=%f\n",RadScaleFactor);
  250.         break;
  251.       case 't':
  252.         SphereType = atoi(optarg);
  253.         printf("spheretesstype=%d\n",SphereType);
  254.         break;
  255.       case 'z':
  256.         ZoomFactor =  atof(optarg);
  257.         printf("ZoomFactor=%f\n",ZoomFactor);
  258.         break;
  259.       case 'A':
  260.         switch (atoi(optarg)) {
  261.           case 0:
  262.         BondSmooth = SML_OFF;
  263.         BondEndCorrect = SML_OFF;
  264.         break;
  265.           case 1:
  266.         BondSmooth = SML_ON;
  267.         BondEndCorrect = SML_OFF;
  268.         break;
  269.           case 2:
  270.         BondSmooth = SML_SMOOTHER;
  271.         BondEndCorrect = SML_OFF;
  272.         break;
  273.           case 3:
  274.         BondSmooth = SML_OFF;
  275.         BondEndCorrect = SML_END_CORRECT;
  276.         break;
  277.           case 4:
  278.         BondSmooth = SML_SMOOTHER;
  279.         BondEndCorrect = SML_END_CORRECT;
  280.         break;
  281.         }
  282.         break;
  283.       case 'B': 
  284.         BitmapSpheres ^= 1;
  285.         break;
  286.       case 'D': 
  287.         Debug = 1 - Debug;
  288.         printf("in debug mode\n");
  289.         break;
  290.  
  291.       case 'H':
  292.         HelpCmd = (char *) malloc((unsigned) (strlen(optarg) + 3));
  293.         strcpy(HelpCmd, optarg);
  294.         strcat(HelpCmd, " &");
  295.         break;
  296.  
  297.       case 'I':
  298.         AddDir(optarg);
  299.         break;
  300.       case 'K':
  301.         if ( (tmp = strrchr(optarg, '/')) != NULL) {
  302.         KernelFile = strdup(tmp + 1);
  303.         *tmp = '\0';
  304.         AddDir(optarg);
  305.         *tmp = '/';
  306.         } else {
  307.         KernelFile = strdup(optarg);
  308.         AddDir(".");
  309.         }
  310.         printf("Kernel file %s\n", optarg);
  311.         break;
  312.       case 'R':
  313.         RollMode = 1 - RollMode;
  314.         break;
  315.       case 'P':
  316.         UsePanel = 1;
  317.         break;
  318.       case 'W': /* provide x1,y1,x2,y2  or just xsize, ysize */
  319.         if (4 == sscanf(optarg, "%d,%d,%d,%d", &GeomXorigin, &GeomYorigin, 
  320.         &GeomXsize, &GeomYsize)) {
  321.         UsePrefposition = 1;
  322.         } else if (2 == sscanf(optarg, "%d,%d", &GeomXsize, &GeomYsize)) {
  323.         UsePrefsize = 1;
  324.         } else  {
  325.         Usage();
  326.         DoExit(-1);
  327.         }
  328.         break;
  329.       default:
  330.         Usage();
  331.         DoExit(-1);
  332.     }
  333.     }
  334.     if (BitmapSpheres)
  335.     Multisample = 0;
  336. }
  337.  
  338. static void Usage(void)
  339. {
  340.     fprintf(stderr, "usage: %s %s\n", ProgName, StrUsage);
  341.     fprintf(stderr, "\n\
  342. Use the -n option to specify a model name (i.e. advil).  The corresponding \n\
  343. data files are searched for in the default directories, namely '.' and \n\
  344. '/usr/demos/data/atom', and in the directories specified by the -I \n\
  345. option.\n");
  346. }
  347.  
  348. static void DoEvents(void)
  349. {
  350.     int done = 0;
  351.     long dev;
  352.     short val;
  353.     short geom_attached = 0;
  354.     short panel_attached = 0;
  355.     short help_attached = 0;
  356.     int help_window_iconified = 0;
  357.     int panel_window_iconified = 0;
  358.  
  359.     while(!done) {
  360.     if ((!GeomLeftDown && !GeomMiddleDown && !GeomRightDown && !RotMode &&
  361.     !PanelButtonDown) || qtest()) {
  362.         switch(dev = qread(&val)) {
  363.  
  364.           case INPUTCHANGE:
  365.         geom_attached = (val == GeomWid);
  366.         panel_attached = (val == PanelWid);
  367.         help_attached = (val == HelpWid);
  368.         break;
  369.  
  370.           case ESCKEY:
  371.         if (geom_attached) done = 1;
  372.         else if (panel_attached) done = 1;
  373.         else if (help_attached) DoEventsHelp(dev, val);
  374.         break;
  375.  
  376.           case REDRAW:
  377.         if (val == GeomWid)
  378.             DoEventsGeom(dev, val);
  379.         else if (val == PanelWid)
  380.             DoEventsPanel(dev, val);
  381.         else if (val == HelpWid)
  382.             DoEventsHelp(dev, val);
  383.         break;
  384.  
  385.           case WINTHAW:
  386.         if (val == GeomWid) {
  387.             if (help_window_iconified) {
  388.             InitHelpWindow();
  389.             DrawHelp();
  390.             }
  391.             if (panel_window_iconified) {
  392.             OpenPanelWindow();
  393.             DrawPanel();
  394.             }
  395.         }
  396.         break;
  397.  
  398.           case WINFREEZE:
  399.         if (val == GeomWid) {
  400.             if (PanelWid != -1) {
  401.             ClosePanelWindow();
  402.             panel_window_iconified = 1;
  403.             } else panel_window_iconified = 0;
  404.             if (HelpWid != -1) {
  405.             CloseHelpWindow();
  406.             help_window_iconified = 1;
  407.             } else help_window_iconified = 0;
  408.         }
  409.         break;
  410.  
  411.           default:
  412.         if (geom_attached)
  413.             DoEventsGeom(dev, val);
  414.         else if (UsePanel && panel_attached)
  415.             DoEventsPanel(dev, val);
  416.         }
  417.     }
  418.     if (UsePanel && panel_attached) {
  419.         DoPanel(dev, val);
  420.         if (RotMode)
  421.         DoGeom();
  422.     } else if (geom_attached)
  423.         DoGeom();
  424.     }
  425. }
  426.  
  427. static void InitFonts(void)
  428. {
  429.     fminit();
  430.  
  431.     FontScreen = fmfindfont("Screen");
  432.     FontScreen5 = fmscalefont(FontScreen, 5.0);
  433.     FontScreen8 = fmscalefont(FontScreen, 8.0);
  434.     FontScreen10 = fmscalefont(FontScreen, 10.0);
  435.  
  436.     fmgetfontinfo(FontScreen, &FontScreenInfo);
  437.     fmgetfontinfo(FontScreen5, &FontScreen5Info);
  438.     fmgetfontinfo(FontScreen8, &FontScreen8Info);
  439.     fmgetfontinfo(FontScreen10, &FontScreen10Info);
  440. }
  441.  
  442. static void InitGraphics(void)
  443. {
  444.     char gfxstr[12];
  445.     int c;
  446.     
  447.     if (Debug) foreground();
  448.     
  449.     gversion(gfxstr);
  450.     if (strstr(gfxstr, "RE"))
  451.     {
  452.     hwGfxType = RE;
  453.     Hemi = 0;
  454.     }
  455.  
  456.     if ((c = getgdesc(GD_BITS_NORM_DBL_BLUE)) <= 0) 
  457.     {
  458.     fprintf(stderr, "%s: Not enough bitplanes available.\n", ProgName);
  459.     DoExit(-1);
  460.     }
  461.     if (!(hwMultisample = getgdesc(GD_MULTISAMPLE)))
  462.     {
  463.     fprintf(stderr, "%s: No multisampling on this machine.\n", ProgName);
  464.     Multisample = 0;
  465.     }
  466.  
  467.     /* check for very low end */
  468.     if ((c <= 4) || (!(getgdesc(GD_BITS_NORM_ZBUFFER))))
  469.     SphereDepth = 4;
  470.     else if (!hwMultisample) /* mid range */
  471.     SphereDepth = 6;
  472.  
  473.     if (hwMultisample)
  474.     {
  475.     if (!BitmapSpheres)
  476.         Multisample = 1; /* come up in multisample */
  477.     AtomAccBuf = 0;
  478.     }
  479.  
  480.     if (!getgdesc(GD_FOGPIXEL))
  481.     FogType = FG_VTX_LIN;
  482.  
  483.  
  484.     if (!(hwAccbuf = (getgdesc(GD_BITS_ACBUF) >= 16)))
  485.     {
  486.     fprintf(stderr, "%s: No accumulation buffer.\n", ProgName);
  487.     } else
  488.     {
  489.     if (!Multisample)
  490.         hwAccbuf = 12;
  491.     else
  492.         hwAccbuf = 16;
  493.     }
  494.  
  495.    if (!(hwStereo = getgdesc(GD_STEREO_IN_WINDOW)))
  496.    {
  497.     fprintf(stderr, "%s: No in-the-window stereo on this machine.\n", ProgName);
  498.     fprintf(stderr, "%s: No bitmap spheres on this machine.\n", ProgName);
  499.     hwBitmapSpheres = 0;
  500.     }
  501.  
  502.     ZMin = getgdesc(GD_ZMIN);
  503.     ZMax = getgdesc(GD_ZMAX);
  504.  
  505.     noport();
  506.     winopen("mview");
  507.     GraphicsInitialized = 1;
  508. }
  509.  
  510. static void InitQueue(void)
  511. {
  512.     qdevice(LEFTMOUSE);
  513.     qdevice(MIDDLEMOUSE);
  514.     qdevice(RIGHTMOUSE);
  515.     qdevice(ESCKEY);
  516.     qdevice(INPUTCHANGE);
  517.     qdevice(REDRAW);
  518.     qdevice(LEFTARROWKEY);
  519.     qdevice(RIGHTARROWKEY);
  520.     qdevice(UPARROWKEY);
  521.     qdevice(DOWNARROWKEY);
  522.     qdevice(KEYBD);
  523.     qdevice(WINTHAW);
  524.     qdevice(WINFREEZE);
  525.  
  526.     qreset();
  527. }
  528.  
  529. void DoExit(int rc)
  530. {
  531.     int i;
  532.  
  533.     DoExitGeom();
  534.     if (GraphicsInitialized) {
  535. #ifdef USEOVERLAY
  536.     drawmode(OVERDRAW);
  537.     color(0);
  538.     clear();
  539.     drawmode(NORMALDRAW);
  540. #endif /* USEOVERLAY */
  541.     gexit();
  542.     }
  543.     if (AtomModels) {
  544.     for (i = 0; i < NumAtomModels; i++)
  545.         free(AtomModels[i]);
  546.     free(AtomModels);
  547.     }
  548.     if (BondModels) {
  549.     for (i = 0; i < NumBondModels; i++)
  550.         free(BondModels[i]);
  551.     free(BondModels);
  552.     }
  553.     if (Models) {
  554.     for (i = 0; i < NumModels; i++)
  555.         free(Models[i].name);
  556.     free(Models);
  557.     }
  558.     if (ModelNames)
  559.     free(ModelNames);
  560.     if (ModelName)
  561.     free(ModelName);
  562.  
  563.     exit(rc);
  564. }
  565.  
  566. /* utiliy functions */
  567.  
  568. int HwAccBuf(void)
  569. {
  570.     return (hwAccbuf);
  571. }
  572.  
  573. static unsigned int atox(char *s)
  574. {
  575.     unsigned int x;
  576.  
  577.     if ((isalpha(s[0])) || ((strncmp(s,"0x",2) == 0) && (s += 2))) {
  578.         sscanf(s,"%x",&x);
  579.     } else
  580.     sscanf(s,"%u",&x);
  581.     return x;
  582. }
  583.  
  584. char *get_basename(char *file)
  585. {
  586.     char *bname;
  587.  
  588.     bname = strrchr(file, '/');
  589.     if (bname) return (bname + 1);
  590.     else return (file);
  591. }
  592.  
  593. void DoHelp(long index)
  594. {
  595.     char *str;
  596.  
  597.     if (HelpCmd) {
  598.     system(HelpCmd);
  599.     return;
  600.     }
  601.     if (HelpWid == -1) {
  602.     InitHelp();
  603.     InitHelpWindow();
  604.     DrawHelp();
  605.     } else CloseHelpWindow();
  606. }
  607.  
  608. static void InitModels(void)
  609. {
  610.     char **dir_ptr;
  611.     char **model_ptr;
  612.     int i, j;
  613.     char *tmp, atom_model[100], bond_model[100];
  614.     int length;
  615.  
  616.     if (NumDirs == 0) {
  617.     fprintf(stderr, "%s: no directories to search for models found.\n", 
  618.         ProgName);
  619.     DoExit(0);
  620.     }
  621.  
  622.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  623.     NumAtomModels += GetNumFiles(*dir_ptr, "*.atoms");
  624.     }
  625.  
  626.     if (NumAtomModels == 0) {
  627.     fprintf(stderr, 
  628.         "%s: no models found in the specified directories: ", 
  629.         ProgName);
  630.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++)
  631.         fprintf(stderr, "%s, ", *dir_ptr);
  632.     fprintf(stderr, "\n");
  633.     DoExit(0);
  634.     }
  635.  
  636.     AtomModels = (char **) malloc (NumAtomModels * sizeof(char *));
  637.     model_ptr = AtomModels;
  638.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  639.     model_ptr = &model_ptr[GetFileNames(*dir_ptr, "*.atoms", model_ptr)];
  640.     }
  641.  
  642.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  643.     NumBondModels += GetNumFiles(*dir_ptr, "*.bonds");
  644.     }
  645.  
  646.     BondModels = (char **) malloc (NumBondModels * sizeof(char *));
  647.     model_ptr = BondModels;
  648.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  649.     model_ptr = &model_ptr[GetFileNames(*dir_ptr, "*.bonds", model_ptr)];
  650.     }
  651.  
  652.     Models = 
  653.     (MODEL *) malloc(Min(NumBondModels, NumAtomModels) * sizeof(MODEL));
  654.     for (i = 0; i < NumAtomModels; i++) {
  655.     tmp = get_basename(AtomModels[i]);
  656.     length = strlen(tmp) - 6;
  657.     strncpy(atom_model, tmp, length);
  658.     atom_model[length] = '\0';
  659.     for (j = 0; j < NumBondModels; j++) {
  660.         tmp = get_basename(BondModels[j]);
  661.         length = strlen(tmp) - 6;
  662.         strncpy(bond_model, tmp, length);
  663.         bond_model[length] = '\0';
  664.         if (strcmp(atom_model, bond_model) == 0) {
  665.         Models[NumModels].name = strdup(atom_model);
  666.         Models[NumModels].atom = AtomModels[i];
  667.         Models[NumModels++].bond = BondModels[j];
  668.         break;
  669.         }
  670.     }
  671.     }
  672.  
  673.     ModelNames = (char **) malloc (NumModels * sizeof(char *));
  674.     for (i = 0; i < NumModels; i++)
  675.     ModelNames[i] = Models[i].name;
  676. }
  677.  
  678. static void SetModelId(void)
  679. {
  680.     int i;
  681.  
  682.     if (ModelName) {
  683.     for (i = 0; i < NumModels; i++) {
  684.         if (strcmp(Models[i].name, ModelName) == 0) {
  685.         ModelId = i;
  686.         break;
  687.         }
  688.     }
  689.     if (i == NumModels) {
  690.         fprintf(stderr, "%s: Model %s is not available\n", 
  691.         ProgName, ModelName);
  692.     }
  693.     }
  694. }
  695.  
  696. void InitKernels(void)
  697. {
  698.     char **dir_ptr;
  699.     char **kernel_ptr;
  700.  
  701.     if (Kernels) {
  702.     free (Kernels);
  703.     NumKernels = 0;
  704.     }
  705.  
  706.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  707.     NumKernels += GetNumFiles(*dir_ptr, "*.kl");
  708.     }
  709.  
  710.     Kernels = (char **) malloc (NumKernels * sizeof(char *));
  711.     kernel_ptr = Kernels;
  712.     for (dir_ptr = Dirs; dir_ptr < &Dirs[NumDirs]; dir_ptr++) {
  713.     kernel_ptr = &kernel_ptr[GetFileNames(*dir_ptr, "*.kl", kernel_ptr)];
  714.     }
  715. }
  716.  
  717. static void SetKernelId(void)
  718. {
  719.     int i;
  720.  
  721.     if (KernelFile) {
  722.     for (i = 0; i < NumKernels; i++) {
  723.         if (strcmp(get_basename(Kernels[i]), KernelFile) == 0) {
  724.         KernelId = i;
  725.         break;
  726.         }
  727.     }
  728.     if (i == NumKernels) {
  729.         fprintf(stderr, "%s: Kernel %s is not available\n", 
  730.         ProgName, KernelFile);
  731.     }
  732.     }
  733. }
  734.  
  735. static int GetNumFiles(char *dir, char *s)
  736. {
  737.     DIR *dd;
  738.     struct dirent *dirent_p;
  739.     int i = 0;
  740.  
  741.     if (!(dd = opendir(dir))) {
  742. #ifdef GET_RID_OF_NON_FATAL_STDOUT_ERROR_MESGS
  743.     fprintf(stderr, "%s: fail to open directory %s\n", ProgName, dir);
  744. #endif
  745.     return 0;
  746.     }
  747.     while (dirent_p = readdir(dd)) {
  748.     if (strcmpr(dirent_p->d_name, s))
  749.         i++;
  750.     }
  751.     closedir(dd);
  752.     return (i);
  753. }
  754.  
  755. static int GetFileNames(char *dir, char *s, char **file)
  756. {
  757.     char *f;
  758.     DIR *dd;
  759.     struct dirent *dirent_p;
  760.     int i = 0;
  761.  
  762.     if (!(dd = opendir(dir))) {
  763. #ifdef GET_RID_OF_NON_FATAL_STDOUT_ERROR_MESGS
  764.     fprintf(stderr, "Fail to open directory %s\n", dir);
  765. #endif
  766.     return 0;
  767.     }
  768.     while (dirent_p = readdir(dd)) {
  769.     f = dirent_p->d_name;
  770.     if (strcmpr(f, s)) {
  771.         if (dir[strlen(dir)-1] != '/') {
  772.         file[i] = (char *)
  773.             malloc((strlen(f) + strlen(dir) + 2) * sizeof(char));
  774.         strcpy(file[i], dir);
  775.         strcat(file[i], "/");
  776.         } else {
  777.         file[i] = (char *)
  778.             malloc((strlen(f) + strlen(dir) + 1) * sizeof(char));
  779.         strcpy(file[i], dir);
  780.         }
  781.         strcat(file[i++], f);
  782.     }
  783.     }
  784.     closedir(dd);
  785.     return (i);
  786. }
  787.  
  788. /* strcmpr() takes two expressions as arguments. It compares the given
  789. expressions and returns 0 or 1 as they are different or equivalent
  790. respectively. The two expressions are strings. The '*' is a special
  791. character that expands to any string.
  792.  */
  793. int strcmpr(char *s1, char *s2)
  794. {
  795.     if ((s1[0] == '\0') && (s2[0] == '\0'))
  796.     return (1);
  797.  
  798.     if (s1[0] == '\0') {
  799.     if (s2[0] != '*')
  800.         return (0);
  801.     else
  802.         return (strcmpr(s1, &s2[1]));
  803.     }
  804.  
  805.     if (s2[0] == '\0') {
  806.     if (s1[0] != '*')
  807.         return (0);
  808.     else
  809.         return (strcmpr(&s1[1], s2));
  810.     }
  811.  
  812.     if ((s1[0] == s2[0]) && (s1[0] != '*') && (s2[0] != '*'))
  813.     return (strcmpr(&s1[1], &s2[1]));
  814.  
  815.     if ((s1[0] == '*') || (s2[0] == '*'))
  816.     return (
  817.         strcmpr(&s1[1], s2) ||    /* match to the empty string        */
  818.         strcmpr(&s1[1], &s2[1]) ||    /* match to one caracter        */
  819.         strcmpr(s1, &s2[1])        /* match to more than one caracter  */
  820.     );
  821.  
  822.     return (0);
  823. }
  824.  
  825. static void AddDir(char *dir)
  826. {
  827.     int i;
  828.  
  829.     if (NumDirs == NUM_DIRS) {
  830.     fprintf(stderr, "%s: no more directories are available\n", ProgName);
  831.     return;
  832.     }
  833.  
  834.     for (i = 0;  i < NumDirs;  i++)
  835.     if (strcmp(Dirs[i], dir) == 0)
  836.         return;
  837.  
  838.     Dirs[NumDirs++] = strdup(dir);
  839. }
  840.  
  841.