X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fmolecule.c;h=58be5ceb90b1ea4cb0adc0eaa31a9b25093b4361;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=a787b0117445be7debcd0d59ce67488246c9aef4;hpb=447db08c956099b3b183886729108bf5b364c4b8;p=xscreensaver diff --git a/hacks/glx/molecule.c b/hacks/glx/molecule.c index a787b011..58be5ceb 100644 --- a/hacks/glx/molecule.c +++ b/hacks/glx/molecule.c @@ -1,4 +1,4 @@ -/* molecule, Copyright (c) 2001-2005 Jamie Zawinski +/* molecule, Copyright (c) 2001-2006 Jamie Zawinski * Draws molecules, based on coordinates from PDB (Protein Data Base) files. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -12,48 +12,29 @@ /* Documentation on the PDB file format: - http://www.rcsb.org/pdb/docs/format/pdbguide2.2/guide2.2_frame.html + http://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29 + http://www.wwpdb.org/docs.html + http://www.wwpdb.org/documentation/format32/v3.2.html + http://www.wwpdb.org/documentation/format32/sect9.html + http://www.rcsb.org/pdb/file_formats/pdb/pdbguide2.2/guide2.2_frame.html Good source of PDB files: http://www.sci.ouc.bc.ca/chem/molecule/molecule.html + http://www.umass.edu/microbio/rasmol/whereget.htm + http://www.wwpdb.org/docs.html */ -#include -#include -#include -#include -#include - -#define PROGCLASS "Molecule" -#define HACK_INIT init_molecule -#define HACK_DRAW draw_molecule -#define HACK_RESHAPE reshape_molecule -#define HACK_HANDLE_EVENT molecule_handle_event -#define EVENT_MASK PointerMotionMask -#define molecule_opts xlockmore_opts - -#define DEF_TIMEOUT "20" -#define DEF_SPIN "XYZ" -#define DEF_WANDER "False" -#define DEF_LABELS "True" -#define DEF_TITLES "True" -#define DEF_ATOMS "True" -#define DEF_BONDS "True" -#define DEF_SHELLS "False" -#define DEF_BBOX "False" -#define DEF_SHELL_ALPHA "0.3" -#define DEF_MOLECULE "(default)" -#define DEF_VERBOSE "False" - #define DEFAULTS "*delay: 10000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ - "*atomFont: -*-times-bold-r-normal-*-240-*\n" \ - "*titleFont: -*-times-bold-r-normal-*-180-*\n" \ + "*atomFont: -*-helvetica-medium-r-normal-*-180-*\n" \ + "*atomFont2: -*-helvetica-bold-r-normal-*-80-*\n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ "*noLabelThreshold: 30 \n" \ "*wireframeThreshold: 150 \n" \ - +# define refresh_molecule 0 +# define release_molecule 0 #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) @@ -67,14 +48,26 @@ #ifdef USE_GL /* whole file */ -#include +#include +#include +#include #include -#include -#include -#include -#define SPHERE_SLICES 24 /* how densely to render spheres */ -#define SPHERE_STACKS 12 +#define DEF_TIMEOUT "20" +#define DEF_SPIN "XYZ" +#define DEF_WANDER "False" +#define DEF_LABELS "True" +#define DEF_TITLES "True" +#define DEF_ATOMS "True" +#define DEF_BONDS "True" +#define DEF_ESHELLS "True" +#define DEF_BBOX "False" +#define DEF_SHELL_ALPHA "0.3" +#define DEF_MOLECULE "(default)" +#define DEF_VERBOSE "False" + +#define SPHERE_SLICES 48 /* how densely to render spheres */ +#define SPHERE_STACKS 24 #define SMOOTH_TUBE /* whether to have smooth or faceted tubes */ @@ -84,10 +77,9 @@ # define TUBE_FACES 8 #endif -static int scale_down; -#define SPHERE_SLICES_2 7 -#define SPHERE_STACKS_2 4 -#define TUBE_FACES_2 3 +#define SPHERE_SLICES_2 14 +#define SPHERE_STACKS_2 8 +#define TUBE_FACES_2 6 # ifdef __GNUC__ @@ -112,16 +104,16 @@ typedef struct { /* These are the traditional colors used to render these atoms, and their approximate size in angstroms. */ -static atom_data all_atom_data[] = { - { "H", 1.17, 0, "White", "Grey70", { 0, }}, - { "C", 1.75, 0, "Grey60", "White", { 0, }}, - { "CA", 1.80, 0, "Blue", "LightBlue", { 0, }}, - { "N", 1.55, 0, "LightSteelBlue3", "SlateBlue1", { 0, }}, - { "O", 1.40, 0, "Red", "LightPink", { 0, }}, - { "P", 1.28, 0, "MediumPurple", "PaleVioletRed", { 0, }}, - { "S", 1.80, 0, "Yellow4", "Yellow1", { 0, }}, - { "bond", 0, 0, "Grey70", "Yellow1", { 0, }}, - { "*", 1.40, 0, "Green4", "LightGreen", { 0, }} +static const atom_data all_atom_data[] = { + { "H", 1.17, 0.40, "#FFFFFF", "#000000", { 0, }}, + { "C", 1.75, 0.58, "#999999", "#FFFFFF", { 0, }}, + { "CA", 1.80, 0.60, "#0000FF", "#ADD8E6", { 0, }}, + { "N", 1.55, 0.52, "#A2B5CD", "#EE99FF", { 0, }}, + { "O", 1.40, 0.47, "#FF0000", "#FFB6C1", { 0, }}, + { "P", 1.28, 0.43, "#9370DB", "#DB7093", { 0, }}, + { "S", 1.80, 0.60, "#8B8B00", "#FFFF00", { 0, }}, + { "bond", 0, 0, "#B3B3B3", "#FFFF00", { 0, }}, + { "*", 1.40, 0.47, "#008B00", "#90EE90", { 0, }} }; @@ -129,7 +121,7 @@ typedef struct { int id; /* sequence number in the PDB file */ const char *label; /* The atom name */ GLfloat x, y, z; /* position in 3-space (angstroms) */ - atom_data *data; /* computed: which style of atom this is */ + const atom_data *data; /* computed: which style of atom this is */ } molecule_atom; typedef struct { @@ -168,10 +160,15 @@ typedef struct { GLuint molecule_dlist; GLuint shell_dlist; - XFontStruct *xfont1, *xfont2; - GLuint font1_dlist, font2_dlist; + XFontStruct *xfont1, *xfont2, *xfont3; + GLuint font1_dlist, font2_dlist, font3_dlist; int polygon_count; + time_t draw_time; + int draw_tick; + + int scale_down; + } molecule_configuration; @@ -225,7 +222,7 @@ static argtype vars[] = { {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, {&do_atoms, "atoms", "Atoms", DEF_ATOMS, t_Bool}, {&do_bonds, "bonds", "Bonds", DEF_BONDS, t_Bool}, - {&do_shells, "eshells", "EShells", DEF_SHELLS, t_Bool}, + {&do_shells, "eshells", "EShells", DEF_ESHELLS, t_Bool}, {&do_labels, "labels", "Labels", DEF_LABELS, t_Bool}, {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, {&do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool}, @@ -233,7 +230,7 @@ static argtype vars[] = { {&verbose_p, "verbose", "Verbose", DEF_VERBOSE, t_Bool}, }; -ModeSpecOpt molecule_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt molecule_opts = {countof(opts), opts, countof(vars), vars, NULL}; @@ -241,10 +238,11 @@ ModeSpecOpt molecule_opts = {countof(opts), opts, countof(vars), vars, NULL}; /* shapes */ static int -sphere (GLfloat x, GLfloat y, GLfloat z, GLfloat diameter, Bool wire) +sphere (molecule_configuration *mc, + GLfloat x, GLfloat y, GLfloat z, GLfloat diameter, Bool wire) { - int stacks = (scale_down ? SPHERE_STACKS_2 : SPHERE_STACKS); - int slices = (scale_down ? SPHERE_SLICES_2 : SPHERE_SLICES); + int stacks = (mc->scale_down ? SPHERE_STACKS_2 : SPHERE_STACKS); + int slices = (mc->scale_down ? SPHERE_SLICES_2 : SPHERE_SLICES); glPushMatrix (); glTranslatef (x, y, z); @@ -261,15 +259,16 @@ load_fonts (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; load_font (mi->dpy, "atomFont", &mc->xfont1, &mc->font1_dlist); - load_font (mi->dpy, "titleFont", &mc->xfont2, &mc->font2_dlist); + load_font (mi->dpy, "atomFont2", &mc->xfont2, &mc->font2_dlist); + load_font (mi->dpy, "titleFont", &mc->xfont3, &mc->font3_dlist); } -static atom_data * +static const atom_data * get_atom_data (const char *atom_name) { int i; - atom_data *d = 0; + const atom_data *d = 0; char *n = strdup (atom_name); char *n2 = n; int L; @@ -292,21 +291,31 @@ get_atom_data (const char *atom_name) static void -set_atom_color (ModeInfo *mi, molecule_atom *a, Bool font_p, GLfloat alpha) +set_atom_color (ModeInfo *mi, const molecule_atom *a, + Bool font_p, GLfloat alpha) { - atom_data *d; - GLfloat *gl_color; + const atom_data *d; + GLfloat gl_color[4]; if (a) d = a->data; else + d = get_atom_data ("bond"); + + if (font_p) { - static atom_data *def_data = 0; - if (!def_data) def_data = get_atom_data ("bond"); - d = def_data; + gl_color[0] = d->gl_color[4]; + gl_color[1] = d->gl_color[5]; + gl_color[2] = d->gl_color[6]; + gl_color[3] = d->gl_color[7]; + } + else + { + gl_color[0] = d->gl_color[0]; + gl_color[1] = d->gl_color[1]; + gl_color[2] = d->gl_color[2]; + gl_color[3] = d->gl_color[3]; } - - gl_color = (!font_p ? d->gl_color : (d->gl_color + 4)); if (gl_color[3] == 0) { @@ -326,6 +335,16 @@ set_atom_color (ModeInfo *mi, molecule_atom *a, Bool font_p, GLfloat alpha) gl_color[3] = alpha; + /* If we're not drawing atoms, and the color is black, use white instead. + This is a kludge so that H can have black text over its white ball, + but the text still shows up if balls are off. + */ + if (font_p && !do_atoms && + gl_color[0] == 0 && gl_color[1] == 0 && gl_color[2] == 0) + { + gl_color[0] = gl_color[1] = gl_color[2] = 1; + } + if (font_p) glColor4f (gl_color[0], gl_color[1], gl_color[2], gl_color[3]); else @@ -334,25 +353,10 @@ set_atom_color (ModeInfo *mi, molecule_atom *a, Bool font_p, GLfloat alpha) static GLfloat -atom_size (molecule_atom *a) +atom_size (const molecule_atom *a) { if (do_bonds) - { - if (a->data->size2 == 0) - { - /* let the molecules have the same relative sizes, but scale - them to a smaller range, so that the bond-tubes are - actually visible... - */ - GLfloat bot = 0.4; - GLfloat top = 0.6; - GLfloat min = 1.17; - GLfloat max = 1.80; - GLfloat ratio = (a->data->size - min) / (max - min); - a->data->size2 = bot + (ratio * (top - bot)); - } - return a->data->size2; - } + return a->data->size2; else return a->data->size; } @@ -426,8 +430,8 @@ molecule_bounding_box (ModeInfo *mi, static void draw_bounding_box (ModeInfo *mi) { - static GLfloat c1[4] = { 0.2, 0.2, 0.4, 1.0 }; - static GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat c1[4] = { 0.2, 0.2, 0.4, 1.0 }; + static const GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 }; int wire = MI_IS_WIREFRAME(mi); GLfloat x1, y1, z1, x2, y2, z2; molecule_bounding_box (mi, &x1, &y1, &z1, &x2, &y2, &z2); @@ -508,14 +512,14 @@ ensure_bounding_box_visible (ModeInfo *mi) mc->molecule_size = size; - scale_down = 0; + mc->scale_down = 0; if (size > max_size) { GLfloat scale = max_size / size; glScalef (scale, scale, scale); - scale_down = scale < 0.3; + mc->scale_down = scale < 0.3; } glTranslatef (-(x1 + w/2), @@ -563,9 +567,9 @@ build_molecule (ModeInfo *mi, Bool transparent_p) if (do_bonds) for (i = 0; i < m->nbonds; i++) { - molecule_bond *b = &m->bonds[i]; - molecule_atom *from = get_atom (m->atoms, m->natoms, b->from); - molecule_atom *to = get_atom (m->atoms, m->natoms, b->to); + const molecule_bond *b = &m->bonds[i]; + const molecule_atom *from = get_atom (m->atoms, m->natoms, b->from); + const molecule_atom *to = get_atom (m->atoms, m->natoms, b->to); if (wire) { @@ -577,7 +581,7 @@ build_molecule (ModeInfo *mi, Bool transparent_p) } else { - int faces = (scale_down ? TUBE_FACES_2 : TUBE_FACES); + int faces = (mc->scale_down ? TUBE_FACES_2 : TUBE_FACES); # ifdef SMOOTH_TUBE int smooth = True; # else @@ -588,21 +592,20 @@ build_molecule (ModeInfo *mi, Bool transparent_p) if (thickness > 0.3) thickness = 0.3; - tube (from->x, from->y, from->z, - to->x, to->y, to->z, - thickness, cap_size, - faces, smooth, (!do_atoms || do_shells), wire); - polys += faces; + polys += tube (from->x, from->y, from->z, + to->x, to->y, to->z, + thickness, cap_size, + faces, smooth, (!do_atoms || do_shells), wire); } } if (!wire && do_atoms) for (i = 0; i < m->natoms; i++) { - molecule_atom *a = &m->atoms[i]; + const molecule_atom *a = &m->atoms[i]; GLfloat size = atom_size (a); set_atom_color (mi, a, False, alpha); - polys += sphere (a->x, a->y, a->z, size, wire); + polys += sphere (mc, a->x, a->y, a->z, size, wire); } if (do_bbox && !transparent_p) @@ -665,6 +668,14 @@ push_bond (molecule *m, int from, int to) } +static void +parse_error (const char *file, int lineno, const char *line) +{ + fprintf (stderr, "%s: %s: parse error, line %d: %s\n", + progname, file, lineno, line); + exit (1); +} + /* This function is crap. */ @@ -735,6 +746,15 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) !strncmp (s, "MTRIX3", 6) || !strncmp (s, "SHEET ", 6) || !strncmp (s, "CISPEP", 6) || +/* + !strncmp (s, "SEQADV", 6) || + !strncmp (s, "SITE ", 5) || + !strncmp (s, "FTNOTE", 6) || + !strncmp (s, "MODEL ", 5) || + !strncmp (s, "ENDMDL", 6) || + !strncmp (s, "SPRSDE", 6) || + !strncmp (s, "MODRES", 6) || + */ !strncmp (s, "GENERATED BY", 12) || !strncmp (s, "TER ", 4) || !strncmp (s, "END ", 4) || @@ -746,12 +766,26 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) else if (!strncmp (s, "ATOM ", 7)) { int id; + const char *end = strchr (s, '\n'); + int L = end - s; char *name = (char *) calloc (1, 4); GLfloat x = -999, y = -999, z = -999; - sscanf (s+7, " %d ", &id); + if (1 != sscanf (s+7, " %d ", &id)) + parse_error (filename, line, s); + /* Use the "atom name" field if that is all that is available. */ strncpy (name, s+12, 3); + + /* But prefer the "element" field. */ + if (L > 77 && !isspace(s[77])) { + /* fprintf(stderr, " \"%s\" -> ", name); */ + name[0] = s[76]; + name[1] = s[77]; + name[2] = 0; + /* fprintf(stderr, "\"%s\"\n", name); */ + } + while (isspace(*name)) name++; ss = name + strlen(name)-1; while (isspace(*ss) && ss > name) @@ -762,7 +796,9 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) *ss = tolower(*ss); ss++; } - sscanf (s + 32, " %f %f %f ", &x, &y, &z); + if (3 != sscanf (s + 32, " %f %f %f ", &x, &y, &z)) + parse_error (filename, line, s); + /* fprintf (stderr, "%s: %s: %d: atom: %d \"%s\" %9.4f %9.4f %9.4f\n", progname, filename, line, @@ -776,14 +812,16 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) char *name = (char *) calloc (1, 4); GLfloat x = -999, y = -999, z = -999; - sscanf (s+7, " %d ", &id); + if (1 != sscanf (s+7, " %d ", &id)) + parse_error (filename, line, s); strncpy (name, s+12, 3); while (isspace(*name)) name++; ss = name + strlen(name)-1; while (isspace(*ss) && ss > name) *ss-- = 0; - sscanf (s + 30, " %f %f %f ", &x, &y, &z); + if (3 != sscanf (s + 30, " %f %f %f ", &x, &y, &z)) + parse_error (filename, line, s); /* fprintf (stderr, "%s: %s: %d: atom: %d \"%s\" %9.4f %9.4f %9.4f\n", progname, filename, line, @@ -1129,7 +1167,7 @@ load_molecules (ModeInfo *mi) /* Window management, etc */ -void +ENTRYPOINT void reshape_molecule (ModeInfo *mi, int width, int height) { GLfloat h = (GLfloat) height / (GLfloat) width; @@ -1153,10 +1191,10 @@ reshape_molecule (ModeInfo *mi, int width, int height) static void gl_init (ModeInfo *mi) { - static GLfloat pos[4] = {1.0, 0.4, 0.9, 0.0}; - static GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; - static GLfloat dif[4] = {0.8, 0.8, 0.8, 1.0}; - static GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + static const GLfloat pos[4] = {1.0, 0.4, 0.9, 0.0}; + static const GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; + static const GLfloat dif[4] = {0.8, 0.8, 0.8, 1.0}; + static const GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, pos); glLightfv(GL_LIGHT0, GL_AMBIENT, amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); @@ -1169,15 +1207,15 @@ startup_blurb (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; const char *s = "Constructing molecules..."; - print_gl_string (mi->dpy, mc->xfont2, mc->font2_dlist, + print_gl_string (mi->dpy, mc->xfont3, mc->font3_dlist, mi->xgwa.width, mi->xgwa.height, 10, mi->xgwa.height - 10, - s); + s, False); glFinish(); glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); } -Bool +ENTRYPOINT Bool molecule_handle_event (ModeInfo *mi, XEvent *event) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; @@ -1199,7 +1237,9 @@ molecule_handle_event (ModeInfo *mi, XEvent *event) } else if (event->xany.type == ButtonPress && (event->xbutton.button == Button4 || - event->xbutton.button == Button5)) + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) { gltrackball_mousewheel (mc->trackball, event->xbutton.button, 10, !!event->xbutton.state); @@ -1232,7 +1272,7 @@ molecule_handle_event (ModeInfo *mi, XEvent *event) } -void +ENTRYPOINT void init_molecule (ModeInfo *mi) { molecule_configuration *mc; @@ -1271,6 +1311,7 @@ init_molecule (ModeInfo *mi) if (*s == 'x' || *s == 'X') spinx = True; else if (*s == 'y' || *s == 'Y') spiny = True; else if (*s == 'z' || *s == 'Z') spinz = True; + else if (*s == '0') ; else { fprintf (stderr, @@ -1303,9 +1344,9 @@ init_molecule (ModeInfo *mi) load_molecules (mi); mc->which = random() % mc->nmolecules; - mc->no_label_threshold = get_float_resource ("noLabelThreshold", + mc->no_label_threshold = get_float_resource (mi->dpy, "noLabelThreshold", "NoLabelThreshold"); - mc->wireframe_threshold = get_float_resource ("wireframeThreshold", + mc->wireframe_threshold = get_float_resource (mi->dpy, "wireframeThreshold", "WireframeThreshold"); mc->mode = 0; @@ -1318,12 +1359,14 @@ init_molecule (ModeInfo *mi) This can't be a part of the display list because of the games we play with the translation matrix. */ -void +static void draw_labels (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; int wire = MI_IS_WIREFRAME(mi); molecule *m = &mc->molecules[mc->which]; + XFontStruct *xfont = (mc->scale_down ? mc->xfont2 : mc->xfont1); + GLuint font_dlist = (mc->scale_down ? mc->font2_dlist : mc->font1_dlist); int i, j; if (!do_labels) @@ -1383,12 +1426,13 @@ draw_labels (ModeInfo *mi) /* Before drawing the string, shift the origin to center the text over the origin of the sphere. */ glBitmap (0, 0, 0, 0, - -string_width (mc->xfont1, a->label) / 2, - -mc->xfont1->descent, + -string_width (xfont, a->label, 0) / 2, + -xfont->descent, NULL); for (j = 0; j < strlen(a->label); j++) - glCallList (mc->font1_dlist + (int)(a->label[j])); + + glCallList (font_dlist + (int)(a->label[j])); glPopMatrix(); } @@ -1484,10 +1528,9 @@ pick_new_molecule (ModeInfo *mi, time_t last) } -void +ENTRYPOINT void draw_molecule (ModeInfo *mi) { - static time_t last = 0; time_t now = time ((time_t *) 0); GLfloat speed = 4.0; /* speed at which the zoom out/in happens */ @@ -1498,28 +1541,29 @@ draw_molecule (ModeInfo *mi) if (!mc->glx_context) return; - if (last == 0) + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mc->glx_context)); + + if (mc->draw_time == 0) { - pick_new_molecule (mi, last); - last = now; + pick_new_molecule (mi, mc->draw_time); + mc->draw_time = now; } else if (mc->mode == 0) { - static int tick = 0; - if (tick++ > 10) + if (mc->draw_tick++ > 10) { time_t now = time((time_t *) 0); - if (last == 0) last = now; - tick = 0; + if (mc->draw_time == 0) mc->draw_time = now; + mc->draw_tick = 0; if (!mc->button_down_p && mc->nmolecules > 1 && - last + timeout <= now) + mc->draw_time + timeout <= now) { /* randomize molecules every -timeout seconds */ mc->mode = 1; /* go out */ mc->mode_tick = 10 * speed; - last = now; + mc->draw_time = now; } } } @@ -1529,8 +1573,8 @@ draw_molecule (ModeInfo *mi) { mc->mode_tick = 10 * speed; mc->mode = 2; /* go in */ - pick_new_molecule (mi, last); - last = now; + pick_new_molecule (mi, mc->draw_time); + mc->draw_time = now; } } else if (mc->mode == 2) /* in */ @@ -1583,10 +1627,10 @@ draw_molecule (ModeInfo *mi) if (do_titles && m->label && *m->label) { set_atom_color (mi, 0, True, 1); - print_gl_string (mi->dpy, mc->xfont2, mc->font2_dlist, + print_gl_string (mi->dpy, mc->xfont3, mc->font3_dlist, mi->xgwa.width, mi->xgwa.height, 10, mi->xgwa.height - 10, - m->label); + m->label, False); } } glPopMatrix(); @@ -1619,4 +1663,6 @@ draw_molecule (ModeInfo *mi) glXSwapBuffers(dpy, window); } +XSCREENSAVER_MODULE ("Molecule", molecule) + #endif /* USE_GL */