/* * functions for in and output */ #include "ct1.h" #include "inout.h" #include #include #include #include #include #include "gdk/gdkprivate.h" #include #ifdef EMF #include #endif #ifdef GTK2 extern PangoFontDescription *font[7], *smallfont[7], *symbfont[7], *ssymbfont[7], *slfont[7], *boldfont[7], *textfont[7]; #else extern GdkFont *font[7],*smallfont[7],*symbfont[7],*boldfont[7],*slfont[7]; #endif static char babeloutp[4]; int save_mol (FILE * fp, int partial) /* saves the current structure to a file in native chemtool format */ { int d; int w, h; struct data *hp_b; struct dc *hp_a; struct spline *hp_sp; int mbonds = 0, mlabels = 0, msplines = 0; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif /* get true extents of drawing*/ w = 0; h = 0; hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (partial == 1 && hp_b->smarked == 0 && hp_b->tmarked == 0) { hp_b = hp_b->next; } else { if (partial) mbonds++; w = MAX (w, hp_b->x); w = MAX (w, hp_b->tx); h = MAX (h, hp_b->y); h = MAX (h, hp_b->ty); hp_b = hp_b->next; } } hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { if (partial && !hp_a->marked) { hp_a = hp_a->next; } else { if (partial) mlabels++; w = MAX (w, hp_a->x); h = MAX (h, hp_a->y); hp_a = hp_a->next; } } hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { if (partial && !hp_sp->marked) { hp_sp = hp_sp->next; } else { if (partial) msplines++; w = MAX (w, hp_sp->x0); h = MAX (h, hp_sp->y0); w = MAX (w, hp_sp->x1); h = MAX (h, hp_sp->y1); w = MAX (w, hp_sp->x2); h = MAX (h, hp_sp->y2); w = MAX (w, hp_sp->x3); h = MAX (h, hp_sp->y3); hp_sp = hp_sp->next; } } w = (int) (w * 1.1); h = (int) (h * 1.1); fprintf (fp, "Chemtool Version " VERSION "\n"); fprintf (fp, "geometry %i %i\n", w, h); hp_b = da_root.next; if (partial) fprintf (fp, "bonds %i\n", mbonds); else fprintf (fp, "bonds %i\n", hp->n); for (d = 0; d < hp->n; d++) { if (partial && !hp_b->smarked && !hp_b->tmarked) { hp_b = hp_b->next; } else { /* if (hp_b->decoration == 1) {*/ fprintf (fp, "%i %i %i %i %i %i %i\n", hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, hp_b->bond, hp_b->decoration,hp_b->color); /* }else{ fprintf (fp, "%i %i %i %i %i\n", hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, hp_b->bond); }*/ hp_b = hp_b->next; } } hp_a = dac_root.next; if (partial) fprintf (fp, "atoms %i\n", mlabels); else fprintf (fp, "atoms %i\n", hp->nc); for (d = 0; d < hp->nc; d++) { if (partial && !hp_a->marked) { hp_a = hp_a->next; } else { fprintf (fp, "%i %i %s %i %i %i %i\n", hp_a->x, hp_a->y, hp_a->c, hp_a->direct, hp_a->color,hp_a->font,hp_a->size); hp_a = hp_a->next; } } hp_sp = sp_root.next; if (partial) fprintf (fp, "splines %i\n", msplines); else fprintf (fp, "splines %i\n", hp->nsp); for (d = 0; d < hp->nsp; d++) { if (partial && !hp_sp->marked) { hp_sp = hp_sp->next; } else { fprintf (fp, "%i %i %i %i %i %i %i %i %i %i\n", hp_sp->x0, hp_sp->y0, hp_sp->x1, hp_sp->y1, hp_sp->x2, hp_sp->y2, hp_sp->x3, hp_sp->y3, hp_sp->type,hp_sp->color); hp_sp = hp_sp->next; } } if (addflag==1) { fprintf (fp,"attach %i %i\n",refx,refy); } /* fclose (fp);*/ return (0); } int load_mol (char *filename) /* loads a chemtool file, checking for correct header */ { int d, n, i; int x, y, tx, ty, x2, y2, x3, y3, b, deco, col, fnt, siz; int res; char str[255], str1[255]; FILE *fp; char version[10]; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); res = fscanf (fp, "%s %s %s", str, str1, version); if (res != 3) { fclose (fp); return (2); } if (strcmp (str, "Chemtool") || strcmp (str1, "Version")) { fclose (fp); return (2); } clear_data (); res = fscanf (fp, "%s %i %i", str, &x, &y); if (res == 3 && !strcmp (str, "geometry")) { head.width = MAX (head.width, x); head.height = MAX (head.height, y); } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && (!strcmp (str, "bonds") || !strcmp (str, "bounds"))) { /* typo in versions < 1.1.2 */ res = fgetc(fp); if (res == EOF) { fclose (fp); return (2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)) { fclose (fp); return (2); } i=sscanf (str, "%i %i %i %i %i %i %i", &x, &y, &tx, &ty, &b, &deco, &col); if (i == 7) add_struct (x, y, tx, ty, b, 0, 0, deco, col); else if (i == 6) add_struct (x, y, tx, ty, b, 0, 0, deco, 0); else add_struct (x, y, tx, ty, b, 0, 0, 0, 0); } } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && !strcmp (str, "atoms")) { res = fgetc(fp); if (res == EOF) { fclose (fp); return (2); } for (d = 0; d < n; d++) { if (!fgets(str,33+MAXCL,fp)){ fclose (fp); return (2); } i=sscanf (str, "%i %i %s %i %i %i %i", &x, &y, str, &b, &col, &fnt, &siz); if (i==7) add_char (x, y, str, b, 0, col, fnt, siz); else if (i == 6) add_char (x, y, str, b, 0, col, fnt, 3); else if (i<5) add_char (x, y, str, b, 0, 0, 0, 3); else add_char (x, y, str, b, 0, col, 0, 3); } } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && !strcmp (str, "splines")) { if (n > 0) { res = fgetc(fp); if (res == EOF) { fclose (fp); return (2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)){ fclose (fp); return (2); } i=sscanf (str, "%i %i %i %i %i %i %i %i %i %i", &x, &y, &tx, &ty, &x2, &y2, &x3, &y3, &b,&col); if (i<10) add_spline (x, y, tx, ty, x2, y2, x3, y3, b, 0, 0); else add_spline (x, y, tx, ty, x2, y2, x3, y3, b, 0, col); } } } res = fscanf (fp, "%s %i %i", str, &x,&y); if (res == 3 && !strcmp(str,"attach")){ refx=x; refy=y; addflag=1; } fclose (fp); if (atof (version) > atof (VERSION)) return (3); return (0); } int load_preview (char *filename) /* loads a chemtool file, checking for correct header */ { int d, n; int x, y, tx, ty, x2, y2, x3, y3, b, col, fnt; int res; float savedfactor; char str[255], str1[255]; FILE *fp; char version[10]; GdkRectangle update_rect; int fontsize; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); savedfactor = size_factor; res = fscanf (fp, "%s %s %s", str, str1, version); if (res != 3) { fclose (fp); return (2); } if (strcmp (str, "Chemtool") || strcmp (str1, "Version")) { fclose (fp); return (2); } res = fscanf (fp, "%s %i %i", str, &x, &y); if (res != 3) { fclose (fp); return (2); } size_factor = MIN (200. / x, 100. / y); res = fscanf (fp, "%s %i", str, &n); if (res == 2 && (!strcmp (str, "bonds") || !strcmp (str, "bounds"))) { /* typo in versions < 1.1.2 */ res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)) { fclose(fp); return(2); } res = sscanf (str, "%i %i %i %i %i %i", &x, &y, &tx, &ty, &b, &col); if (res == 6) draw_preview_bonds (x, y, tx, ty, b); } } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && !strcmp (str, "atoms")) { if (size_factor < 0.15) fontsize=0; else fontsize=1; res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,33+MAXCL,fp)){ fclose(fp); return(2); } res = sscanf (str, "%i %i %s %i %i %i", &x, &y, str, &b, &col,&fnt); if (res >= 4) Drawstring (x, y, str, b, 0,0,0,1,fontsize); } } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && !strcmp (str, "splines")) { if (n>0) { res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)){ fclose(fp); return(2); } res = sscanf (str, "%i %i %i %i %i %i %i %i %i %i", &x, &y, &tx, &ty, &x2, &y2, &x3, &y3, &b,&col); if (res >= 9) Drawspline (x, y, tx, ty, x2, y2, x3, y3, b, 0,0); } } } res = fscanf (fp, "%s %i %i", str, &xref,&yref); if (res == 3 && !strcmp(str,"attach")){ draw_preview_bonds(xref-4,yref-4,xref+4,yref+4,0); draw_preview_bonds(xref-4,yref+4,xref+4,yref-4,0); } gdk_draw_pixmap (preview_area->window, drawing_area->style-> fg_gc[GTK_WIDGET_STATE (drawing_area)], picture, 0, 0, 0, 0, 200, 100); update_rect.x = 0; update_rect.y = 0; update_rect.width = 200; update_rect.height = 100; gtk_widget_draw ((GtkWidget *) preview_area, &update_rect); size_factor = savedfactor; fclose (fp); return (0); } int add_mol (char *filename) /* loads a chemtool file and adds its contents at a given position */ { int d, n, i; int x, y, tx, ty, x2, y2, x3, y3, b, deco, col, fnt, siz; int res; int xdiff = 0, ydiff = 0; char str[255]; FILE *fp; char version[10]; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); res = fscanf (fp, "%s %s %s", str, str, version); if (res != 3 || atof (version) > atof (VERSION)) { fclose (fp); return (2); } Unmark_all(); res = fscanf (fp, "%s %i %i", str, &x, &y); if (res == 3 && !strcmp (str, "geometry")) { head.width += x; mark.w = x; head.height += y; mark.h = y; mark.flag = 1; } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && (!strcmp (str, "bonds") || !strcmp (str, "bounds"))) { res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)){ fclose(fp); return(2); } i= sscanf (str, "%i %i %i %i %i %i %i", &x, &y, &tx, &ty, &b, &deco, &col); if (i == 7) add_struct (x, y, tx, ty, b, 1, 1, deco, col); else if (i == 6) add_struct (x, y, tx, ty, b, 1, 1, deco, 0); else add_struct (x, y, tx, ty, b, 1, 1, 0, 0); } } res = fscanf (fp, "%s %i", str, &n); if (res == 2 && !strcmp (str, "atoms")) { res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,33+MAXCL,fp)) { fclose(fp); return(2); } i=sscanf (str, "%i %i %s %i %i %i %i", &x, &y, str, &b, &col, &fnt, &siz); x = x + xdiff; y = y + ydiff; if (i==7) add_char (x, y, str, b, 1, col, fnt, siz); else if (i==6) add_char (x, y, str, b, 1, col, fnt, 3); else if (i<5) add_char (x, y, str, b, 1, 0, 0, 3); else add_char (x, y, str, b, 1, col, 0, 3); } } res = fscanf (fp, "%s %i ", str, &n); if (res == 2 && !strcmp (str, "splines")) { if (n>0) { res = fgetc(fp); if (res == EOF) { fclose(fp); return(2); } for (d = 0; d < n; d++) { if (!fgets(str,80,fp)) { fclose(fp); return(2); } i=sscanf (str, "%i %i %i %i %i %i %i %i %i %i", &x, &y, &tx, &ty, &x2, &y2, &x3, &y3, &b,&col); if (i<10) add_spline (x, y, tx, ty, x2, y2, x3, y3, b, 0,0); else add_spline (x, y, tx, ty, x2, y2, x3, y3, b, 0,col); } } } res = fscanf (fp, "%s %i %i", str, &xref,&yref); if (res == 3 && !strcmp (str, "attach")) { xref=refx-xref; yref=refy-yref; partial_move (0,0,0,0,xref,yref); } fclose(fp); return (0); } int import_pdb (char *filename) { char line[255]; int i, j,m; int res; int connect = 0; double dist; double pdbxmin = 100000., pdbxmax = -100000., pdbymin = 1000000., pdbymax = -100000., pdbzmin = 100000., pdbzmax = -100000.; char code[8]; float pdbfactor = 50.; int pdboffset = 500; int at0, con[6]; FILE *fp; int *atnum=NULL; int found=0; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); /* skip to the first atom or heteroatom record */ for (i = 0;; i++) { if (fgets (line, (int)sizeof (line), fp) == NULL) { fclose (fp); return (1); } if (!strncmp (line, "END", 3) || feof (fp)) { /*premature end */ fclose (fp); return (1); } if (!strncmp (line, "ATOM", 4) || !strncmp (line, "HETATM", 6)) break; } clear_data (); FreePix(); i = -1; /* read in atom block data */ while (!feof (fp)) { if (!strncmp (line, "ATOM", 4) || !strncmp (line, "HETATM", 6)) { i++; pdbx = realloc (pdbx, (i + 1) * sizeof (double)); pdby = realloc (pdby, (i + 1) * sizeof (double)); pdbz = realloc (pdbz, (i + 1) * sizeof (double)); atjust = realloc (atjust, (i + 1) * sizeof (short)); atcode = realloc (atcode, (i + 1) * sizeof (char *)); atnum = realloc (atnum,(i+1)*sizeof(int)); atcode[i] = malloc (9 * sizeof (char)); atjust[i] = 0; res = sscanf (line, "%s %d %s %*6c %*6c %lf %lf %lf", code, &atnum[i],atcode[i], &pdbx[i], &pdby[i], &pdbz[i]); if (res < 6) { fclose (fp); return (1); } pdbxmin = MIN (pdbxmin, pdbx[i]); pdbxmax = MAX (pdbxmax, pdbx[i]); pdbymin = MIN (pdbymin, pdby[i]); pdbymax = MAX (pdbymax, pdby[i]); pdbzmin = MIN (pdbzmin, pdbz[i]); pdbzmax = MAX (pdbzmax, pdbz[i]); } else break; if (!fgets (line, (int)sizeof (line), fp)) break; } pdbn = i; nbonds = -1; while (!feof (fp)) { if (!strncmp (line, "CONECT", 6)) { connect = 1; con[0] = con[1] = con[2] = con[3] = con[4] = con[5] = 0; res = sscanf (line, "%*s %d %d %d %d %d %d %d", &at0, &con[0], &con[1], &con[2], &con[3],&con[4],&con[5]); for (i = 0; i < res; i++) { if (con[i] > 0) { found=0; for (m=0;m<=pdbn;m++){ if (atnum[m]==at0) { at0=m+1; found=1; break; } } for (m=0;m<=pdbn;m++){ if (atnum[m]==con[i]) { con[i]=m+1; found++; break; } } if (found==2){ nbonds++; bondfrom = realloc (bondfrom, (nbonds + 1) * sizeof (int)); bondto = realloc (bondto, (nbonds + 1) * sizeof (int)); bondtype = realloc (bondtype, (nbonds + 1) * sizeof (short)); bondfrom[nbonds] = at0 - 1; bondto[nbonds] = con[i] - 1; bondtype[nbonds] = 0; dist = (pdbx[at0 - 1] - pdbx[con[i] - 1]) * (pdbx[at0 - 1] - pdbx[con[i] - 1]) + (pdby[at0 - 1] - pdby[con[i] - 1]) * (pdby[at0 - 1] - pdby[con[i] - 1]) + (pdbz[at0 - 1] - pdbz[con[i] - 1]) * (pdbz[at0 - 1] - pdbz[con[i] - 1]); if (dist < 1.45 * 1.45) { if (!strncmp (atcode[at0 - 1], "C", 1) && !strncmp (atcode[con[i] - 1], "C", 1)) bondtype[nbonds] = 4; } /* fprintf(stderr,"CONECTED %d %d (%f)\n",at0,con[i],dist);*/ /* Drawline ((int) (pdbx[at0 - 1] * pdbfactor + pdboffset), (int) (pdby[at0 - 1] * pdbfactor + pdboffset), (int) (pdbx[con[i] - 1] * pdbfactor + pdboffset), (int) (pdby[con[i] - 1] * pdbfactor + pdboffset), 1);*/ } } } } else { break; } (void)fgets (line, (int)sizeof (line), fp); } fclose (fp); free (atnum); atnum=NULL; pdbxcent = (pdbxmax + pdbxmin) / 2.; pdbycent = (pdbymax + pdbymin) / 2.; pdbzcent = (pdbzmax + pdbzmin) / 2.; for (i = 0; i <= pdbn; i++) { pdbx[i] = pdbx[i] - pdbxcent; pdby[i] = pdby[i] - pdbycent; pdbz[i] = pdbz[i] - pdbzcent; } if (connect == 0) { /* if no bonds exist, i.e. there were no CONECTs */ for (i = 0; i <= pdbn; i++) { for (j = i + 1; j <= pdbn; j++) { dist = (pdbx[i] - pdbx[j]) * (pdbx[i] - pdbx[j]) + (pdby[i] - pdby[j]) * (pdby[i] - pdby[j]) + (pdbz[i] - pdbz[j]) * (pdbz[i] - pdbz[j]); if (dist < 1.58 * 1.58) { nbonds++; bondfrom = realloc (bondfrom, (nbonds + 1) * sizeof (int)); bondto = realloc (bondto, (nbonds + 1) * sizeof (int)); bondtype = realloc (bondtype, (nbonds + 1) * sizeof (short)); bondfrom[nbonds] = i; bondto[nbonds] = j; bondtype[nbonds] = 0; if (dist < 1.45 * 1.45) { if (!strncmp (atcode[i], "C", 1) && !strncmp (atcode[j], "C", 1)) bondtype[nbonds] = 4; } /* Drawline ((int) (pdbx[i] * pdbfactor + pdboffset), (int) (pdby[i] * pdbfactor + pdboffset), (int) (pdbx[j] * pdbfactor + pdboffset), (int) (pdby[j] * pdbfactor + pdboffset), 1);*/ } } } } /* CopyPlane ();*/ importflag = 1; importfactor = pdbfactor; importoffset = pdboffset; pdbrotate(0,0,0); return (0); } void pdbrotate (int nx, int ny, int nz) { double l, r, s, t, u, v, w, a, b, c, d, e, f, g, h, i; int ii, j; double x[3], xx, yy, zz; int dx, dy; double ang = 0.; GdkRectangle update_rect; if (nz != 2) { dy = nx - hp->x; dx = ny - hp->y; hp->x = nx; hp->y = ny; x[0] = (dx != 0 ? 1. : 0.); x[1] = (dy != 0 ? 1. : 0.); x[2] = (nz != 0 ? 1. : 0.); if (abs (dx) < abs (dy)) { dx = dy; x[0] = 0.; x[1] = 1.; } else { x[0] = 1.; x[1] = 0.; } ang = (float) dx / 2.; if (ang < -360.) ang = ang + 360.; if (ang > 360.) ang = ang - 360.; if (x[2] == 1) { x[0] = 0.; x[1] = 0.; } /*fprintf(stderr,"rotate %f %f %f : %f\n",x[0],x[1],x[2],ang);*/ l = sqrt (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); r = x[0] / l; s = x[1] / l; t = x[2] / l; v = sin (ang * M_PI / 180.); u = cos (ang * M_PI / 180.); w = 1.0 - u; a = u + w * r * r; b = t * v + w * r * s; c = -s * v + w * r * t; d = -t * v + w * s * r; e = u + w * s * s; f = r * v + w * s * t; g = s * v + w * t * r; h = -r * v + w * t * s; i = u + w * t * t; for (j = 0; j <= pdbn; j++) { xx = pdbx[j]; yy = pdby[j]; zz = pdbz[j]; pdbx[j] = a * xx + b * yy + c * zz; pdby[j] = d * xx + e * yy + f * zz; pdbz[j] = g * xx + h * yy + i * zz; } } FreePix (); for (ii = 0; ii <= nbonds; ii++) Drawline ((int) (pdbx[bondfrom[ii]] * importfactor + importoffset), (int) (pdby[bondfrom[ii]] * importfactor + importoffset), (int) (pdbx[bondto[ii]] * importfactor + importoffset), (int) (pdby[bondto[ii]] * importfactor + importoffset), 1, 0); gdk_draw_pixmap (drawing_area->window, drawing_area->style-> fg_gc[GTK_WIDGET_STATE (drawing_area)], picture, 0, 0, 0, 0, (gint)drawing_area->allocation.width, (gint)drawing_area->allocation.height); update_rect.x = 0; update_rect.y = 0; update_rect.width = drawing_area->allocation.width; update_rect.height = drawing_area->allocation.height; gtk_widget_draw ((GtkWidget *) drawing_area, &update_rect); } void pdbstore () { int i, j; char tmpstr[10]; for (i = 0; i <= pdbn; i++) { /* pdbx[i] = (pdbx[i] + pdbxcent) * importfactor + importoffset; pdby[i] = (pdby[i] + pdbycent) * importfactor + importoffset; pdbz[i] = (pdbz[i] + pdbzcent) * importfactor + importoffset; */ pdbx[i] = pdbx[i] * importfactor + importoffset; pdby[i] = pdby[i] * importfactor + importoffset; pdbz[i] = pdbz[i] * importfactor + importoffset; if (importflag == 1) { switch (pdbmode) { case 0: /* add all labels */ add_char ((int) (pdbx[i]), (int) (pdby[i]), atcode[i], atjust[i], 0, 0, 0, zoom_factor); break; case 1: /* add all non-H labels */ if (strncmp (atcode[i], "H", 1)) add_char ((int) (pdbx[i]), (int) (pdby[i]), atcode[i], atjust[i], 0, 0, 0, zoom_factor); break; case 3: /* only non-H without numeric identifiers */ if (!strncmp (atcode[i], "H", 1)) break; /* fall through to case 2 otherwise */ case 2: /* all labels, without the numeric part */ j = (int) strcspn (atcode[i], "1234567890"); strncpy (tmpstr, atcode[i], (size_t)j); tmpstr[j] = '\0'; add_char ((int) (pdbx[i]), (int) (pdby[i]), tmpstr, atjust[i], 0, 0, 0, zoom_factor); break; case 4: /* no labels */ default: break; } } else { /* in MDL import, add all non-C labels */ if (strncmp (atcode[i], "C", 1)) add_char ((int) (pdbx[i]), (int) (pdby[i]), atcode[i], atjust[i], 0,0,0, zoom_factor); } } for (i = 0; i <= nbonds; i++) add_struct ((int) (pdbx[bondfrom[i]]), (int) (pdby[bondfrom[i]]), (int) (pdbx[bondto[i]]), (int) (pdby[bondto[i]]), (int) bondtype[i], 0, 0, 0, 0); free (pdbx); free (pdby); free (pdbz); free (bondfrom); free (bondto); free (bondtype); free (atjust); for (i = 0; i <= pdbn; i++) free (atcode[i]); free (atcode); pdbx = NULL; pdby = NULL; pdbz = NULL; bondfrom = NULL; bondto = NULL; bondtype = NULL; atjust = NULL; atcode = NULL; importflag = 0; pdbn = 0; FreePix (); Display_Mol (); } int import_mdl_mol (char *filename, int skip) /* imports a MDL Molfile structure */ { /* int x, y, tx, ty;*/ /* the coordinates */ /* int bond = 0; */ /* Chemtool bondstyle */ float mdlfactor = 60.0; /* conversion factor .cht <-> .mol */ int mdloffset = 200; int text_direct = 0; /* Chemtool text direction */ int d, e; /* dummy variables */ int v3=0; char line[255]; char prop[41],*cfg; double pdbxmin = 100000., pdbxmax = -100000., pdbymin = 1000000., pdbymax = -100000., pdbzmin = 100000., pdbzmax = -100000.; /* the counts line, see ctfile.pdf for more information */ int a; /* number of atoms */ int b; /* number of bonds */ /* not parsed right now: */ int l; /* number of atoms list */ int f; /* obsolete */ int c; /* chiral flag, 0=not chiral, 1=chiral */ int s; /* number of stext entries */ int x_; /* number of reaction components + 1 */ int r; /* number of reactants */ int p; /* number of products */ int i; /* number of intermediates */ int m; /* number of additional properties, no longer supported and set to 999 */ char v[6]; /* ctab version, 'v2000' or 'v3000' */ /* end of counts line */ /* the atom block */ /*float xxx, yyy, zzz; */ /* the coordinates of the atom */ char aaa[3]; /* the atomic symbol */ /* not parsed right now: */ int dd; /* mass difference for isotopes */ int ccc; /* charge */ int sss; /* atom stereo parity */ int hhh; /* hydrogen count+1 */ int bbb; /* stereo care box */ int vvv; /* valence */ int HHH; /* H designator, redundant */ int rrr; /* reaction component type */ int iii; /* reaction component number */ int mmm; /* atom-atom mapping number */ int nnn; /* inversion/retention flag */ int eee; /* exact change flag */ /* end atom block */ /* the bond block */ int atom1; /* first atom number */ int atom2; /* second atom number */ int tt; /* bond type */ int ss; /* bond stereo */ int xx; /* not used */ int rr; /* bond topology, 0=eighter, 1=ring, 2=chain */ int cc; /* reaction center status */ /* end bond block */ char label[20]; /* a label defined in the .mol-file */ char aa[4],bb[4]; int res; FILE *fp; /*struct dc *hp_a; */ #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); if (skip >0 ) { d = 0; while ( d 100000 || b > 100000) { fclose(fp); return (1); } } clear_data (); pdbn = -1; /* read in atom block data */ for (d = 0; d < a; d++) { if (!fgets (line, (int)sizeof (line), fp)) { fclose(fp); return(1); } pdbn++; pdbx = realloc (pdbx, (pdbn + 1) * sizeof (double)); pdby = realloc (pdby, (pdbn + 1) * sizeof (double)); pdbz = realloc (pdbz, (pdbn + 1) * sizeof (double)); atjust = realloc (atjust, (pdbn + 1) * sizeof (short)); atcode = realloc (atcode, (pdbn + 1) * sizeof (char *)); atcode[pdbn] = malloc (9 * sizeof (char)); if (v3==0) res = sscanf (line, "%lf %lf %lf %s %i %i %i %i %i %i %i %i %i %i %i %i", &pdbx[pdbn], &pdby[pdbn], &pdbz[pdbn], atcode[pdbn], &dd, &ccc, &sss, &hhh, &bbb, &vvv, &HHH, &rrr, &iii, &mmm, &nnn, &eee); else res = sscanf (line, "M V30 %*d %s %lf %lf %lf", atcode[pdbn],&pdbx[pdbn], &pdby[pdbn], &pdbz[pdbn]); if (res <3 ) { fclose(fp); return(1); } pdbxmin = MIN (pdbxmin, pdbx[d]); pdbxmax = MAX (pdbxmax, pdbx[d]); pdbymin = MIN (pdbymin, pdby[d]); pdbymax = MAX (pdbymax, pdby[d]); pdbzmin = MIN (pdbzmin, pdbz[d]); pdbzmax = MAX (pdbzmax, pdbz[d]); atjust[pdbn] = -1; /*default to centered labels */ } if (v3==1) { if (!fgets(line,(int)sizeof(line),fp)) { fclose(fp); return(1); } if (strncmp(line,"M V30 END ATOM",14)) { fclose(fp); return(1); } if (!fgets(line,(int)sizeof(line),fp)) { fclose(fp); return(1); } if (strncmp(line,"M V30 BEGIN BOND",16)) { fclose(fp); return(1); } } nbonds = -1; /* read in bond block data */ for (d = 0; d < b; d++) { if (!fgets (line, (int)sizeof (line), fp)) { fclose(fp); return(1); } if (v3==1) { memset(prop,0,40); res = sscanf (line, "M V30 %*d %i %i %i %40c", &tt,&atom1,&atom2,prop); if (res <2) { fclose(fp); return(1); } ss = 0; if ( (cfg=strstr(prop,"CFG=")) != NULL) { res = sscanf(cfg,"CFG=%d",&ss); if (ss == 3) ss = 6; } }else{ res = sscanf (line, "%c%c%c%c%c%c %i %i %i %i %i", &aa[0],&aa[1],&aa[2], &bb[0], &bb[1], &bb[2], &tt, &ss, &xx, &rr, &cc); res = sscanf(aa,"%i",&atom1); res = sscanf(bb,"%i",&atom2); } nbonds++; bondfrom = realloc (bondfrom, (nbonds + 1) * sizeof (int)); bondto = realloc (bondto, (nbonds + 1) * sizeof (int)); bondtype = realloc (bondtype, (nbonds + 1) * sizeof (short)); bondfrom[nbonds] = atom1 - 1; bondto[nbonds] = atom2 - 1; switch (tt) { case 1: /* single */ bondtype[nbonds] = 0; if (ss == 1) /* stereo up */ bondtype[nbonds] = 5; if (ss == 2 || ss == 4) /* either */ bondtype[nbonds] = 7; if (ss == 6) /* down */ bondtype[nbonds] = 6; break; case 2: /* double */ bondtype[nbonds] = 1; break; case 3: bondtype[nbonds] = 3; break; default: bondtype[nbonds] = 0; } } if (v3 == 1) { if (!fgets (line, (int)sizeof (line), fp)) { fclose(fp); return(1); } } else { /* check for additional labels */ res = fscanf (fp, "%s %s", aaa, line); while (res >0 && !strcmp (aaa, "A")) { atom1 = atoi (line); res = fscanf (fp, "%s", label); if (res == 0) break; /* found a label "label" at atom "atom1" */ /* check for numbers, interpret as indices: */ text_direct = 0; f = (int)strlen (label); if (f == 1) text_direct = -1; /*center label if only one character */ for (e = 0; label[e] != '\0'; e++) { if (isdigit (label[e])) { /* If there's a number at the beginning, assume right- * justified text: */ if (e == 0) text_direct = -2; /* copy already processed string in auxiliary string 'line': */ strncpy (line, label, (size_t)e); /* append a '_', the number and a NULL-string: */ line[e] = '_'; line[e + 1] = label[e]; line[e + 2] = '\0'; /* append the rest of the label-string to 'line': */ strcat (line, strrchr (label, label[e + 1])); /* copy 'line' back to 'label' and add a NULL-string at the end: */ strcpy (label, line); e++; label[++f] = '\0'; } } strcpy (atcode[atom1 - 1], label); atjust[atom1 - 1] = (short)text_direct; res = fscanf (fp, "%s %s", aaa, line); } } /* check last line for "M END" */ if (strcmp(line,"END") && strcmp(line,"$$$$") ) { do { if (!fgets (line,80,fp)){ fprintf(stderr,"EOF\n"); break; } } while (strncmp (line, "M END",6) && strncmp(line,"$$$$",4) ); if (strncmp (line, "M END",6) && strncmp (line,"$$$$",4) ) { fprintf(stderr,"endless molfile???: %s\n",line); clear_data (); fclose (fp); return (2); } } fclose (fp); pdbxcent = (pdbxmax + pdbxmin) / 2.; pdbycent = (pdbymax + pdbymin) / 2.; pdbzcent = (pdbzmax + pdbzmin) / 2.; for (i = 0; i <= pdbn; i++) { pdbx[i] = pdbx[i] - pdbxcent; pdby[i] = pdby[i] - 2. * (pdby[i] - pdbycent); pdbz[i] = pdbz[i] - pdbzcent; } /* try to normalize bond lengths based on first bond */ mdlfactor = mdlfactor / sqrt ((pdbx[bondfrom[0]] - pdbx[bondto[0]]) * (pdbx[bondfrom[0]] - pdbx[bondto[0]]) + (pdby[bondfrom[0]] - pdby[bondto[0]]) * (pdby[bondfrom[0]] - pdby[bondto[0]]) + (pdbz[bondfrom[0]] - pdbz[bondto[0]]) * (pdbz[bondfrom[0]] - pdbz[bondto[0]])); for (i = 0; i <= nbonds; i++) Drawline ((int) (pdbx[bondfrom[i]] * mdlfactor + mdloffset), (int) (pdby[bondfrom[i]] * mdlfactor + mdloffset), (int) (pdbx[bondto[i]] * mdlfactor + mdloffset), (int) (pdby[bondto[i]] * mdlfactor + mdloffset), 1, 0); CopyPlane (); importflag = 2; importfactor = mdlfactor; importoffset = mdloffset; return (0); } int preview_mdl_mol (char *filename, int skip) /* imports a MDL Molfile structure into the preview widget*/ { /* int x, y, tx, ty;*/ /* the coordinates */ /* int bond = 0; */ /* Chemtool bondstyle */ float mdlfactor = 60.0; /* conversion factor .cht <-> .mol */ float previewscale; int text_direct = 0; /* Chemtool text direction */ int d, e; /* dummy variables */ GdkRectangle update_rect; int v3=0; char prop[41],*cfg; char line[255]; double pdbxmin = 100000., pdbxmax = -100000., pdbymin = 1000000., pdbymax = -100000.; /* the counts line, see ctfile.pdf for more information */ int a; /* number of atoms */ int b; /* number of bonds */ /* not parsed right now: */ int l; /* number of atoms list */ int f; /* obsolete */ int c; /* chiral flag, 0=not chiral, 1=chiral */ int s; /* number of stext entries */ int x_; /* number of reaction components + 1 */ int r; /* number of reactants */ int p; /* number of products */ int i; /* number of intermediates */ int m; /* number of additional properties, no longer supported and set to 999 */ char v[6]; /* ctab version, 'v2000' or 'v3000' */ /* end of counts line */ /* the atom block */ /*float xxx, yyy, zzz; */ /* the coordinates of the atom */ char aaa[3]; /* the atomic symbol */ /* not parsed right now: */ int dd; /* mass difference for isotopes */ int ccc; /* charge */ int sss; /* atom stereo parity */ int hhh; /* hydrogen count+1 */ int bbb; /* stereo care box */ int vvv; /* valence */ int HHH; /* H designator, redundant */ int rrr; /* reaction component type */ int iii; /* reaction component number */ int mmm; /* atom-atom mapping number */ int nnn; /* inversion/retention flag */ int eee; /* exact change flag */ /* end atom block */ /* the bond block */ int atom1; /* first atom number */ int atom2; /* second atom number */ int tt; /* bond type */ int ss; /* bond stereo */ int xx; /* not used */ int rr; /* bond topology, 0=eighter, 1=ring, 2=chain */ int cc; /* reaction center status */ /* end bond block */ char label[20]; /* a label defined in the .mol-file */ char aa[4],bb[4]; int res; FILE *fp; /*struct dc *hp_a; */ #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "r")) == NULL) return (1); if (skip >0 ) { d = 0; while ( d 100000 || b > 100000) { fclose(fp); return (1); } } clear_data (); pdbn = -1; /* read in atom block data */ for (d = 0; d < a; d++) { if (!fgets (line, (int)sizeof (line), fp)){ fclose(fp); return(1); } pdbn++; pdbx = realloc (pdbx, (pdbn + 1) * sizeof (double)); pdby = realloc (pdby, (pdbn + 1) * sizeof (double)); atjust = realloc (atjust, (pdbn + 1) * sizeof (short)); atcode = realloc (atcode, (pdbn + 1) * sizeof (char *)); atcode[pdbn] = malloc (9 * sizeof (char)); if (v3==0) res = sscanf (line, "%lf %lf %*f %s %i %i %i %i %i %i %i %i %i %i %i %i", &pdbx[pdbn], &pdby[pdbn], atcode[pdbn], &dd, &ccc, &sss, &hhh, &bbb, &vvv, &HHH, &rrr, &iii, &mmm, &nnn, &eee); else res= sscanf (line, "M V30 %*d %s %lf %lf", atcode[pdbn],&pdbx[pdbn], &pdby[pdbn]); if (res <3) { fclose(fp); return(1); } atjust[pdbn] = -1; /*default to centered labels */ } if (v3==1) { if (!fgets(line,(int)sizeof(line),fp)) { fclose(fp); return(1); } if (strncmp(line,"M V30 END ATOM",14)) { fclose(fp); return(1); } if (!fgets(line,(int)sizeof(line),fp)) { fclose(fp); return(1); } if (strncmp(line,"M V30 BEGIN BOND",16)) { fclose(fp); return(1); } } nbonds = -1; /* read in bond block data */ for (d = 0; d < b; d++) { if (!fgets (line, (int)sizeof (line), fp)) { fclose(fp); return(1); } if (v3==1) { memset(prop,0,40); res = sscanf (line, "M V30 %*d %i %i %i %40c", &tt,&atom1,&atom2,prop); ss = 0; if ( (cfg=strstr(prop,"CFG=")) != NULL) { res = sscanf(cfg,"CFG=%d",&ss); if (ss == 3) ss = 6; } }else{ res = sscanf (line, "%c%c%c%c%c%c %i %i %i %i %i", &aa[0],&aa[1],&aa[2], &bb[0], &bb[1], &bb[2], &tt, &ss, &xx, &rr, &cc); res = sscanf(aa,"%i",&atom1); res = sscanf(bb,"%i",&atom2); } nbonds++; bondfrom = realloc (bondfrom, (nbonds + 1) * sizeof (int)); bondto = realloc (bondto, (nbonds + 1) * sizeof (int)); bondtype = realloc (bondtype, (nbonds + 1) * sizeof (short)); bondfrom[nbonds] = atom1 - 1; bondto[nbonds] = atom2 - 1; switch (tt) { case 1: /* single */ bondtype[nbonds] = 0; if (ss == 1) /* stereo up */ bondtype[nbonds] = 5; if (ss == 2 || ss == 4) /* either */ bondtype[nbonds] = 7; if (ss == 6) /* down */ bondtype[nbonds] = 6; break; case 2: bondtype[nbonds] = 1; break; case 3: bondtype[nbonds] = 3; break; default: bondtype[nbonds] = 0; } } if (v3 == 1) { if (!fgets (line, (int)sizeof (line), fp)) { fclose(fp); return(1); } } else { /* check for additional labels */ res = fscanf (fp, "%s %s", aaa, line); while (res >0 && !strcmp (aaa, "A")) { atom1 = atoi (line); res = fscanf (fp, "%s", label); if (res == 0) break; /* found a label "label" at atom "atom1" */ /* check for numbers, interpret as indices: */ text_direct = 0; f = (int)strlen (label); if (f == 1) text_direct = -1; /*center label if only one character */ for (e = 0; label[e] != '\0'; e++) { if (isdigit (label[e])) { /* If there's a number at the beginning, assume right- * justified text: */ if (e == 0) text_direct = -2; /* copy already processed string in auxiliary string 'line': */ strncpy (line, label, (size_t)e); /* append a '_', the number and a NULL-string: */ line[e] = '_'; line[e + 1] = label[e]; line[e + 2] = '\0'; /* append the rest of the label-string to 'line': */ strcat (line, strrchr (label, label[e + 1])); /* copy 'line' back to 'label' and add a NULL-string at the end: */ strcpy (label, line); e++; label[++f] = '\0'; } } strcpy (atcode[atom1 - 1], label); atjust[atom1 - 1] = (short)text_direct; res = fscanf (fp, "%s %s", aaa, line); } } /* check last line for "M END" */ if (strcmp(line,"END") && strcmp(line,"$$$$") ) { do { if (!fgets (line,80,fp)){ fprintf(stderr,"EOF\n"); break; } } while (strncmp (line, "M END",6) && strncmp(line,"$$$$",4) ); if (strncmp (line, "M END",6) && strncmp (line,"$$$$",4) ) { fprintf(stderr,"endless molfile???: %s\n",line); clear_data (); fclose (fp); return (2); } } fclose (fp); /* try to normalize bond lengths based on first bond */ mdlfactor = mdlfactor / sqrt ((pdbx[bondfrom[0]] - pdbx[bondto[0]]) * (pdbx[bondfrom[0]] - pdbx[bondto[0]]) + (pdby[bondfrom[0]] - pdby[bondto[0]]) * (pdby[bondfrom[0]] - pdby[bondto[0]]) ); pdbxmin=10000.; pdbymin=10000.; pdbxmax=-10000.; pdbymax=-10000.; for (i = 0; i <= pdbn; i++) { pdbx[i] = pdbx[i]*mdlfactor; pdby[i] = pdby[i]*mdlfactor; pdbxmin = MIN (pdbxmin, pdbx[i]); pdbxmax = MAX (pdbxmax, pdbx[i]); pdbymin = MIN (pdbymin, pdby[i]); pdbymax = MAX (pdbymax, pdby[i]); } /* center molecule and scale it to fit into the effective drawing area (300x150 plus small border) */ pdbxcent = (pdbxmax + pdbxmin) / 2.; pdbycent = (pdbymax + pdbymin) / 2.; previewscale = MIN(280./(pdbxmax-pdbxmin),140./(pdbymax-pdbymin)); for (i = 0; i <= pdbn; i++) { pdbx[i] = (pdbx[i]- pdbxcent)*previewscale+140.; pdby[i] = (pdby[i]- 2. * pdby[i] + pdbycent)*previewscale+75.; } for (i = 0; i <= nbonds; i++) draw_preview_bonds ((int) pdbx[bondfrom[i]], (int) pdby[bondfrom[i]], (int) pdbx[bondto[i]], (int) pdby[bondto[i]], 0); for (i = 0; i <= pdbn; i++) if (strcmp(atcode[i],"C") && strcmp(atcode[i],"H")) Drawstring ((int)pdbx[i], (int)pdby[i], atcode[i], atjust[i], 0,0,0,1, 1); gdk_draw_pixmap (preview_area->window, drawing_area->style-> fg_gc[GTK_WIDGET_STATE (drawing_area)], picture, 0, 0, 0, 0, 200, 100); update_rect.x = 0; update_rect.y = 0; update_rect.width = 200; update_rect.height = 100; gtk_widget_draw ((GtkWidget *) preview_area, &update_rect); return (0); } int import_babel (char *filename) /* imports a foreign file via BABEL as a MDL Molfile structure */ { /* int x, y, tx, ty;*/ /* the coordinates */ /* int bond = 0; */ /* Chemtool bondstyle */ float mdlfactor = 60.0; /* conversion factor .cht <-> .mol */ int mdloffset = 200; int text_direct = 0; /* Chemtool text direction */ int d, e; /* dummy variables */ char line[255]; double pdbxmin = 100000., pdbxmax = -100000., pdbymin = 1000000., pdbymax = -100000., pdbzmin = 100000., pdbzmax = -100000.; /* the counts line, see ctfile.pdf for more information */ int a; /* number of atoms */ int b; /* number of bonds */ /* not parsed right now: */ int l; /* number of atoms list */ int f; /* obsolete */ int c; /* chiral flag, 0=not chiral, 1=chiral */ int s; /* number of stext entries */ int x_; /* number of reaction components + 1 */ int r; /* number of reactants */ int p; /* number of products */ int i; /* number of intermediates */ int m; /* number of additional properties, no longer supported and set to 999 */ char v[6]; /* ctab version, 'v2000' or 'v3000' */ /* end of counts line */ /* the atom block */ /*float xxx, yyy, zzz; */ /* the coordinates of the atom */ char aaa[3]; /* the atomic symbol */ /* not parsed right now: */ int dd; /* mass difference for isotopes */ int ccc; /* charge */ int sss; /* atom stereo parity */ int hhh; /* hydrogen count+1 */ int bbb; /* stereo care box */ int vvv; /* valence */ int HHH; /* H designator, redundant */ int rrr; /* reaction component type */ int iii; /* reaction component number */ int mmm; /* atom-atom mapping number */ int nnn; /* inversion/retention flag */ int eee; /* exact change flag */ /* end atom block */ /* the bond block */ int atom1; /* first atom number */ int atom2; /* second atom number */ int tt; /* bond type */ int ss; /* bond stereo */ int xx; /* not used */ int rr; /* bond topology, 0=eighter, 1=ring, 2=chain */ int cc; /* reaction center status */ /* end bond block */ int res; char label[20]; /* a label defined in the .mol-file */ char aa[4],bb[4]; FILE *fp; /*struct dc *hp_a; */ #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif if (!filename || !babel ) return (1); /* no filename or no input mode */ snprintf(line,255,"babel -i%s %s -omdl %s",babel,filename,babeloutp); /* fprintf(stderr,"%s\n",line);*/ /*@ignore@ splint does not recognize popen */ if ((fp = popen (line, "r")) == NULL) /*@end@*/ return (1); /* skip the first three lines (header) */ for (d = 0; d < 3; d++) { if (!fgets (line, (int)sizeof (line), fp)) { /*@ignore@*/ pclose(fp); /*@end@*/ return(1); } } /* parse the counts-line */ if (!fgets (line, (int)sizeof (line), fp)) { /*@ignore@*/ pclose(fp); /*@end@*/ return(1); } d = sscanf (line, "%c%c%c%c%c%c %i %i %i %i %i %i %i %i %i %s", &aa[0],&aa[1],&aa[2], &bb[0], &bb[1], &bb[2], &l, &f, &c, &s, &x_, &r, &p, &i, &m, v); aa[3]=bb[3]='\0'; sscanf(aa,"%i",&a); sscanf(bb,"%i",&b); if (d == 0 || a <= 0 || b < 0 || a > 100000 || b > 100000) { /*@ignore@*/ pclose(fp); /*@end@*/ return (1); } fprintf(stderr, "expecting na %d nb %d\n",a,b); clear_data (); pdbn = -1; /* read in atom block data */ for (d = 0; d < a; d++) { if (!fgets (line, (int)sizeof (line), fp)) { /*@ignore@*/ pclose(fp); /*@end@*/ return(1); } pdbn++; pdbx = realloc (pdbx, (pdbn + 1) * sizeof (double)); pdby = realloc (pdby, (pdbn + 1) * sizeof (double)); pdbz = realloc (pdbz, (pdbn + 1) * sizeof (double)); atjust = realloc (atjust, (pdbn + 1) * sizeof (short)); atcode = realloc (atcode, (pdbn + 1) * sizeof (char *)); atcode[pdbn] = malloc (9 * sizeof (char)); res = sscanf (line, "%lf %lf %lf %s %i %i %i %i %i %i %i %i %i %i %i %i", &pdbx[pdbn], &pdby[pdbn], &pdbz[pdbn], atcode[pdbn], &dd, &ccc, &sss, &hhh, &bbb, &vvv, &HHH, &rrr, &iii, &mmm, &nnn, &eee); if (res <3) { /*@ignore@*/ pclose(fp); /*@end@*/ return(1); } pdbxmin = MIN (pdbxmin, pdbx[d]); pdbxmax = MAX (pdbxmax, pdbx[d]); pdbymin = MIN (pdbymin, pdby[d]); pdbymax = MAX (pdbymax, pdby[d]); pdbzmin = MIN (pdbzmin, pdbz[d]); pdbzmax = MAX (pdbzmax, pdbz[d]); atjust[pdbn] = -1; /*default to centered labels */ } nbonds = -1; /* read in bond block data */ for (d = 0; d < b; d++) { if (!fgets (line, (int)sizeof (line), fp)) { /*@ignore@*/ pclose(fp); /*@end@*/ return(1); } res = sscanf (line, "%c%c%c%c%c%c %i %i %i %i %i", &aa[0],&aa[1],&aa[2],&bb[0],&bb[1],&bb[2], &tt, &ss, &xx, &rr, &cc); res = sscanf(aa,"%i",&atom1); res = sscanf(bb,"%i",&atom2); nbonds++; bondfrom = realloc (bondfrom, (nbonds + 1) * sizeof (int)); bondto = realloc (bondto, (nbonds + 1) * sizeof (int)); bondtype = realloc (bondtype, (nbonds + 1) * sizeof (short)); bondfrom[nbonds] = atom1 - 1; bondto[nbonds] = atom2 - 1; switch (tt) { case 1: bondtype[nbonds] = 0; if (ss == 1) bondtype[nbonds] = 5; if (ss == 6) bondtype[nbonds] = 6; break; case 2: bondtype[nbonds] = 1; break; case 3: bondtype[nbonds] = 3; break; default: bondtype[nbonds] = 0; } } /* check for additional labels */ res = fscanf (fp, "%s %s", aaa, line); while (res >0 && !strcmp (aaa, "A")) { atom1 = atoi (line); res = fscanf (fp, "%s", label); if (res <1) break; /* found a label "label" at atom "atom1" */ /* check for numbers, interpret as indices: */ text_direct = 0; f = (int)strlen (label); if (f == 1) text_direct = -1; /*center label if only one character */ for (e = 0; label[e] != '\0'; e++) { if (isdigit (label[e])) { /* If there's a number at the beginning, assume right- * justified text: */ if (e == 0) text_direct = -2; /* copy already processed string in auxiliary string 'line': */ strncpy (line, label, (size_t)e); /* append a '_', the number and a NULL-string: */ line[e] = '_'; line[e + 1] = label[e]; line[e + 2] = '\0'; /* append the rest of the label-string to 'line': */ strcat (line, strrchr (label, label[e + 1])); /* copy 'line' back to 'label' and add a NULL-string at the end: */ strcpy (label, line); e++; label[++f] = '\0'; } } strcpy (atcode[atom1 - 1], label); atjust[atom1 - 1] = (short)text_direct; res = fscanf (fp, "%s %s", aaa, line); } /* check last line for "M END" */ while (strcmp (line, "END")) { if (fscanf (fp, "%s", line) == EOF) break; if (fscanf (fp, "%s %s", aaa, line) == EOF) break; } if (strcmp (aaa, "M") || strcmp (line, "END")) { clear_data (); /*@ignore@ splint does not know pclose */ pclose (fp); /*@end@*/ return (2); } pclose (fp); pdbxcent = (pdbxmax + pdbxmin) / 2.; pdbycent = (pdbymax + pdbymin) / 2.; pdbzcent = (pdbzmax + pdbzmin) / 2.; if (pdbn <=0) return (1); /* complain if no atoms */ for (i = 0; i <= pdbn; i++) { pdbx[i] = pdbx[i] - pdbxcent; pdby[i] = pdby[i] - 2. * (pdby[i] - pdbycent); pdbz[i] = pdbz[i] - pdbzcent; } /* try to normalize bond lengths based on first bond */ mdlfactor = mdlfactor / sqrt ((pdbx[bondfrom[0]] - pdbx[bondto[0]]) * (pdbx[bondfrom[0]] - pdbx[bondto[0]]) + (pdby[bondfrom[0]] - pdby[bondto[0]]) * (pdby[bondfrom[0]] - pdby[bondto[0]]) + (pdbz[bondfrom[0]] - pdbz[bondto[0]]) * (pdbz[bondfrom[0]] - pdbz[bondto[0]])); for (i = 0; i <= nbonds; i++) Drawline ((int) (pdbx[bondfrom[i]] * mdlfactor + mdloffset), (int) (pdby[bondfrom[i]] * mdlfactor + mdloffset), (int) (pdbx[bondto[i]] * mdlfactor + mdloffset), (int) (pdby[bondto[i]] * mdlfactor + mdloffset), 1, 0); CopyPlane (); importflag = 2; importfactor = mdlfactor; importoffset = mdloffset; return (0); } int export_mdl_mol (FILE *fp, int topipe) /* exports a MDL Molfile structure */ { float factor = 76.0; /* conversion factor .cht <-> .mol */ int d, e, f; /* dummy variables */ char aaa[3]; /* the atomic symbol */ int atom1 = 0; /* first atom number */ int atom2 = 0; /* second atom number */ int tt; /* bond type */ int ss; /* bond stereo */ struct dc *hp_a; struct data *hp_b; int atoms[999][2]; /* coordinates of unique labels */ int start_already_there; int end_already_there; int is_label; int labelcount; /* number of unique atoms/labels */ int omit; /* number of decorative lines (boxes etc) */ int hcount=0; /* for explicit CH_3, CH_2, CH */ #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif /* FIXME: Write some sane stuff in the header */ fprintf (fp, "Molecule exported from chemtool\n"); fprintf (fp, "\n"); fprintf (fp, "\n"); labelcount = 0; omit = 0; atoms[0][0]=atoms[0][1]=0; /* Get coordinates of all unique bond-delimiters * and, more importantly, the number of unique atoms, * chemtool only knows the number of bonds and the * number of non-carbon atoms :( */ hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (!(mark.flag && (hp_b->smarked + hp_b->tmarked) == 0)) { if (hp_b->decoration == 1) omit++; else { /* Check for already parsed atoms on same coordinates */ start_already_there = 0; end_already_there = 0; for (f = 0; f <= labelcount; f++) { if (hp_b->x == atoms[f][0] && hp_b->y == atoms[f][1]) { start_already_there = 1; } if (hp_b->tx == atoms[f][0] && hp_b->ty == atoms[f][1]) { end_already_there = 1; } } if (!start_already_there) { atoms[labelcount][0] = hp_b->x; atoms[labelcount][1] = hp_b->y; labelcount++; } if (!end_already_there) { atoms[labelcount][0] = hp_b->tx; atoms[labelcount][1] = hp_b->ty; labelcount++; } } } hp_b = hp_b->next; } /* The counts line: */ fprintf (fp, "%3i%3i 0 0 0 0 0 0 0 0999 V2000\n", labelcount, hp->n-omit); /* Now write down the labels. * start all over */ for (d = 0; d < labelcount; d++) { /* Check for label on same position */ hp_a = dac_root.next; is_label = 0; for (e = 0; e < hp->nc; e++) { if (atoms[d][0] == hp_a->x && atoms[d][1] == hp_a->y) { is_label = 1; break; } hp_a = hp_a->next; } if (is_label) { hcount = 0; if (!strcmp(hp_a->c,"CH") || !strcmp(hp_a->c,"HC") ) { hcount=1; strcpy (aaa, "C"); } else if (!strcmp(hp_a->c,"OH") || !strcmp(hp_a->c,"HO") ) { hcount=1; strcpy (aaa, "O"); } else if (!strcmp(hp_a->c,"NH") || !strcmp(hp_a->c,"HN") ) { hcount=1; strcpy (aaa, "N"); } else if (!strcmp(hp_a->c,"SH") || !strcmp(hp_a->c,"HS") ) { hcount=1; strcpy (aaa, "S"); } else if (!strcmp(hp_a->c,"PH") || !strcmp(hp_a->c,"HP") ) { hcount=1; strcpy (aaa, "P"); } else if ((int)strlen (hp_a->c) < 4) { strcpy (aaa, hp_a->c); } else if (!strncmp(hp_a->c,"CH_3",4) || !strncmp(hp_a->c,"H_3C",4)) { hcount = 3; strcpy (aaa, "C"); } else if ( !strncmp(hp_a->c,"CH_2",4) || !strncmp(hp_a->c,"H2_C",4)) { hcount = 2; strcpy (aaa, "C"); } else if (!strncmp(hp_a->c,"NH_3",4) || !strncmp(hp_a->c,"H_3N",4)) { hcount = 3; strcpy (aaa, "N"); } else if ( !strncmp(hp_a->c,"NH_2",4) || !strncmp(hp_a->c,"H2_N",4)) { hcount = 2; strcpy (aaa, "N"); } else { fprintf(stderr,"untranslatable label %s\n",hp_a->c); strcpy (aaa, "X"); } } else { strcpy (aaa, "C"); } fprintf (fp, "%10.4f%10.4f%10.4f %-3s 0 0 0 %1d 0 0 0 0 0 0 0 0\n", (double) atoms[d][0] / factor, (double) atoms[d][1] / factor, 0.0, aaa, hcount); } /* Now for the bonds */ hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (hp_b->decoration == 0 && (!(mark.flag && (hp_b->smarked + hp_b->tmarked) == 0))) { atom1 = 0; atom2 = 0; for (e = 0; e < labelcount; e++) { if (atoms[e][0] == hp_b->x && atoms[e][1] == hp_b->y) { atom1 = e + 1; } if (atoms[e][0] == hp_b->tx && atoms[e][1] == hp_b->ty) { atom2 = e + 1; } } } /* parse the bond type */ tt = 1; ss = 0; switch (hp_b->bond) { case 1: case 2: tt = 2; /*double*/ /* 7=double or aromatic */ break; case 4: tt = 2; /* double */ break; case 3: case 18: case 19: /* FIXME: does MOL handle quadruple bonds at all ?*/ tt = 3; /* triple */ break; case 5: case 10: ss = 1; /* stereo up */ break; case 6: case 16: ss = 6; /* stereo down */ break; case 7: ss = 4; /* stereo either */ break; case 8: case 9: case 11: /* case 12: */ /* bond or not? */ case 17: tt = 0; /* assume no chemical bond */ break; case 14: case 15: tt = 1; /* 6 = single or aromatic */ break; default: tt = 1; /* single */ break; } if (tt) { fprintf (fp, "%3i%3i%3i%3i 0 0 0\n", atom1, atom2, tt, ss); } hp_b = hp_b->next; } fprintf (fp, "M END\n"); if (!topipe) fclose (fp); return 0; } int export_svg (char *filename) /* exports the current drawing to a Scaled Vector Graphics file */ { FILE *fp; int x, y, tx, ty, w, h; int x1,y1,x2,y2; float area; float factor; struct data *hp_b,*hp_bx; struct dc *hp_a; struct spline *hp_sp; struct xy_co *coord; int d, i, dd; int dy; int xbase, ybase, xside, yside, xend, yend, xlen, ylen; int shifted = 0; int unicodechar; int bond_already_tuned=0; static char svgcolor[7][8]={"#000000","#0000ff","#00ff00","#00ffff","#ff0000","#ff00ff", "#ffff00"}; #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif if ((fp = fopen (filename, "w")) == NULL) return (1); fprintf (fp, "\n"); fprintf (fp, "\n"); if (mark.flag && mark.w != 0 && mark.h != 0) { w = mark.w * size_factor - 6; h = mark.h * size_factor - 6; } else { /* get true extents of drawing*/ w = 0; h = 0; hp_b = da_root.next; for (d = 0; d < hp->n; d++) { w = MAX (w, hp_b->x); w = MAX (w, hp_b->tx); h = MAX (h, hp_b->y); h = MAX (h, hp_b->ty); hp_b = hp_b->next; } hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { w = MAX (w, hp_a->x); if (hp_a->direct > -2) w = MAX (w, hp_a->x + (int)strlen (hp_a->c) * (6 + 2 * size_factor)); h = MAX (h, hp_a->y + 8); hp_a = hp_a->next; } hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { w = MAX (w, hp_sp->x0); h = MAX (h, hp_sp->y0); w = MAX (w, hp_sp->x1); h = MAX (h, hp_sp->y1); w = MAX (w, hp_sp->x2); h = MAX (h, hp_sp->y2); w = MAX (w, hp_sp->x3); h = MAX (h, hp_sp->y3); hp_sp = hp_sp->next; } w = (int) (w * 1.1) ; h = (int) (h * 1.1) ; } fprintf (fp, "\n", w, h); fprintf (fp, "\nCreated with Chemtool 1.6.10 from file %s \n\n", filename); fprintf (fp, "\n"); hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (mark.flag && (hp_b->smarked + hp_b->tmarked) == 0) { } else { coord = bond_cut (hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, 12); x = coord->x; y = coord->y; tx = coord->tx; ty = coord->ty; if (!hp_b->bond) { fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 5) { bond_already_tuned = 0; x1 = tx - (int) (0.1 * (float) (ty - y)); y1 = ty + (int) (0.1 * (float) (tx - x)); x2 = tx + (int) (0.1 * (float) (ty - y)); y2 = ty - (int) (0.1 * (float) (tx - x)); factor=1.; hp_bx=da_root.next; for (dd = 0; dd < hp->n; dd++) { if (hp_bx->bond == 10) { if ( (abs (hp_bx->x * factor - tx) < 3 && abs (hp_bx->y * factor - ty) < 3) || (abs (hp_bx->tx * factor - tx) < 3 && abs (hp_bx->ty * factor - ty) < 3)) { coord = center_double_bond (hp_bx->x, hp_bx->y, hp_bx->tx, hp_bx->ty, db_dist); if (abs (hp_bx->x * factor - tx) < 3 && abs (hp_bx->y * factor - ty) < 3) { x1 = coord->x * factor; y1 = coord->y * factor; coord++; x2 = coord->x * factor; y2 = coord->y * factor; } else { x1 = coord->tx * factor; y1 = coord->ty * factor; coord++; x2 = coord->tx * factor; y2 = coord->ty * factor; } area = (0.5 * abs (x * (y1 - y2) + x1 * (y2 - y) + x2 * (y - y1))); if (fabs (area) < 76. * factor) { x1 = tx - (int) (0.05 * (float) (ty - y)); y1 = ty + (int) (0.05 * (float) (tx - x)); x2 = tx + (int) (0.05 * (float) (ty - y)); y2 = ty - (int) (0.05 * (float) (tx - x)); } else bond_already_tuned = 1; } /* if connected to wide end of this wedge */ } /* if adjoining bond is wide */ if (hp_bx->bond == 0 && !bond_already_tuned) { if ((abs (hp_bx->x * factor - tx) < 3 && abs (hp_bx->y * factor - ty) < 3) ||(abs (hp_bx->tx * factor - tx) < 3 && abs (hp_bx->ty * factor - ty) < 3)) /* let the wedge join smoothly alongside another bond */ { coord = intersect(x,y,x1,y1,hp_bx->x*factor,hp_bx->y*factor, hp_bx->tx*factor,hp_bx->ty*factor); coord->tx = coord->x; coord->ty = coord->y; coord = intersect(x,y,x2,y2,hp_bx->x*factor,hp_bx->y*factor, hp_bx->tx*factor,hp_bx->ty*factor); x1 = coord->tx; y1 = coord->ty; x2 = coord->x; y2 = coord->y; area = 0.5 * abs (x * (y1 - y2) + x1 * (y2 - y) + x2 * (y - y1)); if (fabs (area) > 3300. * factor || fabs(area) < 1750. * factor) { x1 = tx - (int) (0.1 * (float) (ty - y)); y1 = ty + (int) (0.1 * (float) (tx - x)); x2 = tx + (int) (0.1 * (float) (ty - y)); y2 = ty - (int) (0.1 * (float) (tx - x)); } } /* if connected to wide end of this wedge */ } /* if adjoining bond is single, and not already adjusted */ hp_bx = hp_bx->next; } /* for dd */ fprintf (fp, "color],svgcolor[hp_b->color]); fprintf (fp, " points=\"%d,%d %d,%d %d,%d\" />\n", x, y, x1,y1,x2,y2); /* fprintf (fp, " points=\"%d,%d %d,%d %d,%d\" />\n", x, y, (int) (tx - 0.08 * (ty - y)), (int) (ty + 0.08 * (tx - x)), (int) (tx + 0.08 * (ty - y)), (int) (ty - 0.08 * (tx - x))); */ } if (hp_b->bond == 6) { for (i = 0; i < 8; i++) { fprintf (fp, "\n",svgcolor[hp_b->color]); } } if (hp_b->bond == 7) { i=MAX(abs(tx-x),abs(ty-y))/10; fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 8) { fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "color],svgcolor[hp_b->color]); fprintf (fp, " points=\"%d,%d %d,%d %d,%d\" />\n", (int) (x + 0.8 * (tx - x)), (int) (y + 0.8 * (ty - y)), (int) (x + 0.8 * (tx - x) + 0.1 * (ty - y)), (int) (y + 0.8 * (ty - y) - 0.1 * (tx - x)), tx, ty); } if (hp_b->bond == 9) { int xlen = tx - x; int ylen = ty - y; float veclen = sqrt ((double)(xlen * xlen + ylen * ylen)); float scalefact=64./veclen; /* keep arrowhead size constant (64=std length)*/ int xbase = (int) (tx - 0.2 *xlen*scalefact); int ybase = (int) (ty - 0.2 *ylen*scalefact); fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "color],svgcolor[hp_b->color]); fprintf (fp, " points=\"%d,%d %d,%d %d,%d\" />\n", tx, ty,(int)(xbase + 0.1 * ylen*scalefact), (int)(ybase - 0.1 * xlen*scalefact) , (int)(xbase - 0.1 * ylen*scalefact), (int)(ybase + 0.1 * xlen*scalefact) ); /*(int) (x + 0.8 * (tx - x) + 0.1 * (ty - y)), (int) (y + 0.8 * (ty - y) - 0.1 * (tx - x)), (int) (x + 0.8 * (tx - x) - 0.1 * (ty - y)), (int) (y + 0.8 * (ty - y) + 0.1 * (tx - x)));*/ } if (hp_b->bond == 11) { fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 10) { fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 12) { fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 13) { fprintf (fp, "\n"); fprintf (fp, "\n",svgcolor[hp_b->color]); } if (hp_b->bond == 4) { coord = center_double_bond (x, y, tx, ty, db_dist); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); coord++; fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 1 || hp_b->bond == 3) { coord = multi_bonds (x, y, tx, ty, mb_dist); fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 2 || hp_b->bond == 3) { coord = multi_bonds (tx, ty, x, y, mb_dist); fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 14) { coord = multi_bonds (x, y, tx, ty, mb_dist); fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke-dasharray:4,1; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 15) { coord = multi_bonds (tx, ty, x, y, mb_dist); fprintf (fp, "\n",svgcolor[hp_b->color]); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke-dasharray:4,1; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 16) { coord = center_double_bond (x, y, tx, ty, db_dist); x = coord->x; y = coord->y; tx = coord->tx; ty = coord->ty; coord++; for (i = 0; i < 10; i++) { fprintf (fp, "x + 0.1 * i * (coord->tx - coord->x)), (int) (coord->y + 0.1 * i * (coord->ty - coord->y))); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } } if (hp_b->bond == 18) { fprintf (fp, "\n",svgcolor[hp_b->color]); coord = center_double_bond (x, y, tx, ty, db_dist+1); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); coord++; fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } if (hp_b->bond == 19) { int tmpx1,tmpx2,tmpy1,tmpy2,tmptx1,tmptx2,tmpty1,tmpty2; coord = center_double_bond (x, y, tx, ty, db_dist+1); tmpx1=coord->x; tmpy1=coord->y; tmptx1=coord->tx; tmpty1=coord->ty; coord++; tmpx2=coord->x; tmpy2=coord->y; tmptx2=coord->tx; tmpty2=coord->ty; coord = center_double_bond (tmpx1, tmpy1, tmptx1, tmpty1, db_dist-1); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); coord++; fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); coord = center_double_bond (tmpx2, tmpy2, tmptx2, tmpty2, db_dist-1); fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); coord++; fprintf (fp, "x, coord->y, coord->tx, coord->ty); fprintf (fp, "style=\"stroke-width:2; stroke:%s\" />\n",svgcolor[hp_b->color]); } } hp_b = hp_b->next; } hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { if (mark.flag && hp_a->marked == 0) { } else { if (hp_a->font == 0 ) { switch (hp_a->direct) { case Middle_Text: fprintf (fp, "x - 2, hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:middle;\" > \n\n"); break; case Left_Text: fprintf (fp, "x - 8 , hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:start;\" > \n\n"); break; case Right_Text: fprintf (fp, "x + 6, hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:end;\" > \n\n"); break; default: fprintf (stderr, "undefined text direction in svg output\n"); ;; } } else { switch (hp_a->direct) { case Middle_Text: fprintf (fp, "x - 2, hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:middle;\" > \n\n"); break; case Left_Text: fprintf (fp, "x - 8 , hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:start;\" > \n\n"); break; case Right_Text: fprintf (fp, "x + 6, hp_a->y + 8,12+hp_a->size*2,svgcolor[hp_a->color]); fprintf (fp, "text-anchor:end;\" > \n\n"); break; default: fprintf (stderr, "undefined text direction in svg output\n"); ;; } } for (i = 0; i < (int)strlen (hp_a->c); ++i) { if (hp_a->c[i] == '\\') hp_a->c[i] = ' '; if (hp_a->c[i] == '@') { unicodechar=848+hp_a->c[++i]; switch (unicodechar){ /* catch sequence mismatches with X Symbol font*/ case 915: /*C*/ case 947: /*c*/ unicodechar+=20; break; case 918: case 950: /*f*/ unicodechar+=16; break; case 919: case 951: /*g*/ unicodechar-=4; break; case 920: case 952: /*h*/ unicodechar-=1; break; case 922: /*J is vartheta*/ unicodechar=977; break; case 954: /*j is varphi*/ unicodechar=981; break; case 923: case 924: case 925: case 955: case 956: case 957: unicodechar-=1; break; case 926: /*N*/ unicodechar=78; break; case 958: /*n*/ unicodechar=118; break; case 929: /*Q*/ unicodechar=920; break; case 961: /*p*/ unicodechar=952; break; case 962: unicodechar-=1; break; case 966:/*v*/ unicodechar=982; break; case 967: /*w*/ unicodechar=969; break; case 968: unicodechar=958; break; case 969: unicodechar-=1; break; case 970: unicodechar=950; break; case 930: /*R*/ unicodechar-=1; break; case 934: /*V*/ unicodechar=962; break; case 935: /*W*/ unicodechar+=2; break; case 936: /*X*/ unicodechar=926; break; case 937: /*Y*/ unicodechar-=1; break; case 938: unicodechar=90; break; case 1031: case 775: /* bullet */ unicodechar=8226; break; default: break; } fprintf (fp, "&#%04d;", unicodechar); /*FIXME: unicode greek does not always map to X11 Symbol, e.g. F is Z not Phi */ } else if (hp_a->c[i] == '#') { fprintf (fp, "\n"); fprintf (fp, "%c", hp_a->c[++i]); fprintf (fp, "\n"); } else if (hp_a->c[i] == '|') { fprintf (fp, "\n"); fprintf (fp, "%c", hp_a->c[++i]); fprintf (fp, "\n"); } else if (hp_a->c[i] == '_') { dy=2+hp_a->size; fprintf (fp, "\n", dy, 8+hp_a->size*2); if (hp_a->c[i + 1] && hp_a->c[i + 1] == '{') { shifted = 1; i++; } if (shifted == 1) { while (hp_a->c[i + 1] && hp_a->c[i + 1] != '}') fprintf (fp, "%c", hp_a->c[++i]); shifted = 0; i++; } else { fprintf (fp, "%c", hp_a->c[++i]); } fprintf (fp, "\n\n", -dy); } else if (hp_a->c[i] == '^') { dy=-2 * (2 + hp_a->size); /* BUG FIX 1 */ fprintf (fp, "\n", dy, 8+hp_a->size*2); if (hp_a->c[i + 1] && hp_a->c[i + 1] == '{') { shifted = 1; i++; } if (shifted == 1) { while (hp_a->c[i + 1] && hp_a->c[i + 1] != '}') fprintf (fp, "%c", hp_a->c[++i]); shifted = 0; i++; } else { fprintf (fp, "%c", hp_a->c[++i]); } fprintf (fp, "\n\n", -dy); } else { #ifndef GTK2 if ((unsigned char)hp_a->c[i] >128) fprintf (fp, "&#%03d;",(unsigned char)hp_a->c[i]); else #endif fprintf (fp, "%c", hp_a->c[i]); } if (hp_a->c[i]==' ') /* protect blanks again after output */ hp_a->c[i]='\\'; } fprintf (fp, "\n\n"); } hp_a = hp_a->next; } hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { if (mark.flag == 1 && hp_sp->marked == 0) { } else { fprintf (fp, "x0, hp_sp->y0); fprintf (fp, "C %d,%d %d,%d %d,%d\"\n", hp_sp->x1, hp_sp->y1, hp_sp->x2, hp_sp->y2, hp_sp->x3, hp_sp->y3); switch (hp_sp->type) { case 0: case 1: case 2: fprintf (fp, "style=\"stroke-width:2; stroke:%s; fill:none\">\n",svgcolor[hp_sp->color]); break; ;; case -2: fprintf (fp, "style=\"stroke-width:2; stroke-dasharray:4,1; stroke:%s fill:none\">\n",svgcolor[hp_sp->color]); break; ;; case -1: fprintf (fp, "style=\"stroke-width:2; stroke:%s; fill:solid\">\n",svgcolor[hp_sp->color]); } fprintf (fp, "\n"); if (hp_sp->type > 0) { xbase = (int) (0.7 * 0.7 * 0.7 * (double) hp_sp->x3 + 3. * 0.7 * 0.7 * (1. - 0.7) * (double) hp_sp->x2 + 3. * 0.7 * (1. - 0.7) * (1. - 0.7) * (double) hp_sp->x1 + (1. - 0.7) * (1. - 0.7) * (1. - 0.7) * hp_sp->x0); ybase = (int) (0.7 * 0.7 * 0.7 * (double) hp_sp->y3 + 3. * 0.7 * 0.7 * (1. - 0.7) * (double) hp_sp->y2 + 3. * 0.7 * (1. - 0.7) * (1. - 0.7) * (double) hp_sp->y1 + (1. - 0.7) * (1. - 0.7) * (1. - 0.7) * hp_sp->y0); xlen = hp_sp->x3 - xbase; ylen = hp_sp->y3 - ybase; if (xlen != 0) xlen = (int) copysign (50., (double)xlen); if (ylen != 0) ylen = (int) copysign (50., (double)ylen); xside = (int) (xbase + 0.15 * ylen); yside = (int) (ybase - 0.15 * xlen); if (hp_sp->type == 1) { xend = (int) (xbase - 0.15 * ylen); yend = (int) (ybase + 0.15 * xlen); x = (xside - hp_sp->x0) * (xside - hp_sp->x0) + (yside - hp_sp->y0) * (yside - hp_sp->y0); tx = (xend - hp_sp->x0) * (xend - hp_sp->x0) + (yend - hp_sp->y0) * (yend - hp_sp->y0); if (tx > x) { xside = xend; yside = yend; } xend = xbase; /*on baseline */ yend = ybase; } else { xend = (int) (xbase - 0.15 * ylen); yend = (int) (ybase + 0.15 * xlen); } fprintf (fp, "color],svgcolor[hp_sp->color]); fprintf (fp, " points=\"%d,%d %d,%d, %d,%d\" />\n", hp_sp->x3, hp_sp->y3, xside, yside, xend, yend); } } hp_sp = hp_sp->next; } fprintf (fp, "\n\n"); fclose (fp); return (0); } int export_emf (char *filename) /* exports the current drawing to an ECMA Enhanced Metafile */ #ifndef EMF { char com[255]; FILE *xfile; int rval; #if 1 char tmpfile[512]; FILE *fp; int fd; #endif #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif if (figversion == 0) return (1); /* cannot export without fig2dev */ if ((int)strlen (filename)) { #if 0 snprintf (com,255, "fig2dev -L emf > %s", filename); xfile = popen (com, "w"); #else strcpy (tmpfile, "/tmp/chtXXXXXX"); /*@ignore@ splint does not recognize mkstemp */ fd = mkstemp (tmpfile); /*@end@*/ if (fd == -1) return (1); fp = fdopen (fd, "w"); rval = exfig (fp, 0); if (rval != 0) return(rval); if (fclose (fp) != 0) return(1); snprintf (com,255, "fig2dev -L emf %s> %s", tmpfile, filename); xfile = popen (com, "w"); #endif if (pclose (xfile) != 0) return (1); return (rval); } else return (1); } #else { int x, y, tx, ty, w, h; struct data *hp_b; struct dc *hp_a; struct spline *hp_sp; struct xy_co *coord; int d, i; int xbase, ybase, xside, yside, xend, yend, xlen, ylen; int shifted = 0; int ha,fzoom,xpos,chl,nsub,nsup,rval,l; int csize,fontsize,offset,savedpos; LPPOINT dummy={0}; POINT points[4]; HWND desktop = GetDesktopWindow(); HDC dc= GetDC(desktop); PCSTR description = "Created by\0chemtool 1.6.10\0"; char *tmpstring=malloc(80*sizeof(char)); HENHMETAFILE mfh; HDC metaDC ; HPEN nopen=CreatePen(PS_SOLID,0,RGB(0xff,0xff,0xff)); HPEN pen=CreatePen(PS_SOLID,1,RGB(0x00,0x00,0x00)); HPEN widepen=CreatePen(PS_SOLID,5,RGB(0x00,0x00,0x00)); HPEN dashedpen=CreatePen(PS_DASH,1,RGB(0x00,0x00,0x00)); HPEN dottedpen=CreatePen(PS_DOT,1,RGB(0x00,0x00,0x00)); HPEN whitepen=CreatePen(PS_SOLID,5,RGB(0xff,0xff,0xff)); HBRUSH fill=CreateSolidBrush(RGB(0x00,0x00,0x00)); HFONT normalfont=CreateFontA(-11,0,0,0,FW_MEDIUM,0,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT smallfont=CreateFontA(-8,0,0,0,FW_MEDIUM,0,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT italicfont=CreateFontA(11,0,12,0,FW_MEDIUM,1,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT smallitalicfont=CreateFontA(8,0,8,0,FW_MEDIUM,1,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT boldfont=CreateFontA(11,0,12,0,FW_BOLD,0,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT smallboldfont=CreateFontA(8,0,8,0,FW_BOLD,0,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT symbolfont=CreateFontA(11,0,12,0,FW_MEDIUM,0,0,0,SYMBOL_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); HFONT smallsymbolfont=CreateFontA(8,0,8,0,FW_MEDIUM,0,0,0,SYMBOL_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH| FF_DONTCARE, "Helvetica"); savedpos = 0; switch (zoom_factor) { case 0: fontsize = 8; /*8 */ fzoom = 6; /*6,4 */ break; case 1: fontsize = 10; /*6? */ fzoom = 7; /*5? */ break; case 2: fontsize = 12; /*9? */ fzoom = 8; /*7? */ break; case 3: fontsize = 16; /*12? */ fzoom = 9; /*12,10? */ break; case 4: fontsize = 18; fzoom = 10; break; default: fprintf (stderr, "no emf font parameters for zoom factor %d\n", zoom_factor); rval = 2; } fzoom=size_factor; if (mark.flag && mark.w != 0 && mark.h != 0) { x = mark.x * size_factor + 3; y = mark.y * size_factor + 3; w = mark.w * size_factor - 6; h = mark.h * size_factor - 6; } else { /* get true extents of drawing*/ x = 10000; y = 10000; w = 0; h = 0; hp_b = da_root.next; for (d = 0; d < hp->n; d++) { w = MAX (w, hp_b->x); w = MAX (w, hp_b->tx); h = MAX (h, hp_b->y); h = MAX (h, hp_b->ty); x = MIN (x, hp_b->x); x = MIN (x, hp_b->tx); y = MIN (y, hp_b->y); y = MIN (y, hp_b->ty); hp_b = hp_b->next; } hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { w = MAX (w, hp_a->x); if (hp_a->direct > -2) w = MAX (w, (hp_a->x + (int)strlen (hp_a->c) * 30)); h = MAX (h, hp_a->y + 12); x = MIN (x, hp_a->x); if (hp_a->direct < 0) x = MIN (x, (hp_a->x - (int)strlen (hp_a->c) * 30)); y = MIN (y, hp_a->y - 12); hp_a = hp_a->next; } hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { w = MAX (w, hp_sp->x0); h = MAX (h, hp_sp->y0); w = MAX (w, hp_sp->x1); h = MAX (h, hp_sp->y1); w = MAX (w, hp_sp->x2); h = MAX (h, hp_sp->y2); w = MAX (w, hp_sp->x3); h = MAX (h, hp_sp->y3); x = MIN (x, hp_sp->x0); y = MIN (y, hp_sp->y0); x = MIN (x, hp_sp->x1); y = MIN (y, hp_sp->y1); x = MIN (x, hp_sp->x2); y = MIN (y, hp_sp->y2); x = MIN (x, hp_sp->x3); y = MIN (y, hp_sp->y3); hp_sp = hp_sp->next; } x = x * size_factor/2 * 0.8; y = y * size_factor/2 * 0.8; w = (w-x) * size_factor/2 * 1.1 ; h = (h-y) * size_factor/2 * 1.1 ; } #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif metaDC = CreateEnhMetaFile (dc, filename, NULL, description); SetMapMode (dc, MM_ANISOTROPIC); SetViewportExtEx(dc,10,-10,NULL); /* invisible box for image sizing */ SelectObject(metaDC,nopen); MoveToEx(metaDC,x,h,NULL); LineTo(metaDC,w,h); LineTo(metaDC,w,y); LineTo(metaDC,x,y); LineTo(metaDC,x,h); /* now do the actual drawing */ SelectObject(metaDC,pen); SelectObject(metaDC,fill); SetTextColor(metaDC,RGB(0x00,0x00,0x00)); SetTextAlign(metaDC,TA_LEFT+TA_BASELINE); SetBkColor(metaDC,RGB(0xff,0xff,0xff)); SetBkMode(metaDC,OPAQUE); hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (mark.flag && (hp_b->smarked + hp_b->tmarked) == 0) { } else { coord = bond_cut (hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, 15); x = coord->x; y = coord->y; tx = coord->tx; ty = coord->ty; if (!hp_b->bond) { MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); } if (hp_b->bond == 5) { points[0].x=x*size_factor/2; points[0].y=y*size_factor/2; points[1].x=(int) (tx - 0.1 * (ty - y))*size_factor/2; points[1].y=(int) (ty + 0.1 * (tx - x))*size_factor/2; points[2].x=(int) (tx + 0.1 * (ty - y))*size_factor/2; points[2].y=(int) (ty - 0.1 * (tx - x))*size_factor/2; Polygon(metaDC,points,3); } if (hp_b->bond == 6) { for (i = 0; i < 10; i++) { MoveToEx(metaDC, (int) ((x + 0.1 * i * (tx - x) - 0.01 * (ty - y) * i)*size_factor/2), (int) ((y + 0.1 * i * (ty - y) + 0.01 * (tx - x) * i)*size_factor/2),dummy); LineTo(metaDC, (int) ((x + 0.1 * i * (tx - x) + 0.01 * (ty - y) * i)*size_factor/2), (int) ((y + 0.1 * i * (ty - y) - 0.01 * (tx - x) * i)*size_factor/2)); } } if (hp_b->bond == 7) { coord = multi_bonds (x, y, tx, ty, 2*mb_dist); Arc(metaDC,(int)(coord->x*size_factor/2),(int)(coord->ty*size_factor/2), (int)((x+0.25*(tx-x))*size_factor/2), (int)((y+0.25*(ty-y))*size_factor/2), (int)(coord->x*size_factor/2),(int)(coord->y*size_factor/2), (int)((x+0.25*(tx-x))*size_factor/2), (int)((y+0.25*(ty-y))*size_factor/2)); coord = multi_bonds (tx, ty, x, y, 2*mb_dist); Arc(metaDC,(int)(coord->x*size_factor/2),(int)(coord->ty*size_factor/2), (int)((x+0.5*(tx-x))*size_factor/2), (int)((y+0.5*(ty-y))*size_factor/2), (int)(coord->x*size_factor/2),(int)(coord->y*size_factor/2), (int)((x+0.5*(tx-x))*size_factor/2), (int)((y+0.5*(ty-y))*size_factor/2)); coord = multi_bonds (x, y, tx, ty, 2*mb_dist); Arc(metaDC,(int)(coord->x*size_factor/2),(int)(coord->ty*size_factor/2), (int)((x+0.75*(tx-x))*size_factor/2), (int)((y+0.75*(ty-y))*size_factor/2), (int)(coord->x*size_factor/2),(int)(coord->y*size_factor/2), (int)((x+0.75*(tx-x))*size_factor/2), (int)((y+0.75*(ty-y))*size_factor/2)); coord = multi_bonds (tx, ty, x, y, 2*mb_dist); Arc(metaDC,(int)(coord->x*size_factor/2),(int)(coord->ty*size_factor/2), (int)((x+1.*(tx-x))*size_factor/2), (int)((y+1.*(ty-y))*size_factor/2), (int)(coord->x*size_factor/2),(int)(coord->y*size_factor/2), (int)((x+1.*(tx-x))*size_factor/2), (int)((y+1.*(ty-y))*size_factor/2)); } if (hp_b->bond == 8) { MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); points[0].x=(int) (x + 0.8 * (tx - x))*size_factor/2; points[0].y=(int) (y + 0.8 * (ty - y))*size_factor/2; points[1].x=(int) (x + 0.8 * (tx - x) + 0.1 * (ty - y))*size_factor/2; points[1].y=(int) (y + 0.8 * (ty - y) - 0.1 * (tx - x))*size_factor/2; points[2].x=(int) (tx*size_factor/2); points[2].y=(int) (ty*size_factor/2); Polygon(metaDC,points,3); } if (hp_b->bond == 9) { MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); points[0].x= (int) (tx*size_factor/2); points[0].y= (int) (ty*size_factor/2); points[1].x= (int) ((x + 0.8 * (tx - x) + 0.1 * (ty - y))*size_factor/2); points[1].y= (int) ((y + 0.8 * (ty - y) - 0.1 * (tx - x))*size_factor/2); points[2].x= (int) ((x + 0.8 * (tx - x) - 0.1 * (ty - y))*size_factor/2); points[2].y= (int) ((y + 0.8 * (ty - y) + 0.1 * (tx - x))*size_factor/2); Polygon(metaDC,points,3); } if (hp_b->bond == 11) { w=calc_vector(x-tx,y-ty); Ellipse(metaDC, (x-w)*size_factor/2, (y-w)*size_factor/2, (x+w)*size_factor/2, (y+w)*size_factor/2); } if (hp_b->bond == 10) { SelectObject(metaDC,widepen); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); SelectObject(metaDC,pen); } if (hp_b->bond == 12) { SelectObject(metaDC,dottedpen); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); SelectObject(metaDC,pen); } if (hp_b->bond == 13) { SelectObject(metaDC,whitepen); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); SelectObject(metaDC,pen); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); } if (hp_b->bond == 4) { coord = center_double_bond (x, y, tx, ty, db_dist); MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); coord++; MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); } if (hp_b->bond == 1 || hp_b->bond == 3) { coord = multi_bonds (x, y, tx, ty, mb_dist); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); } if (hp_b->bond == 2 || hp_b->bond == 3) { coord = multi_bonds (tx, ty, x, y, mb_dist); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); } if (hp_b->bond == 14) { coord = multi_bonds (x, y, tx, ty, mb_dist); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); SelectObject(metaDC,dashedpen); MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); SelectObject(metaDC,pen); } if (hp_b->bond == 15) { coord = multi_bonds (tx, ty, x, y, mb_dist); MoveToEx (metaDC, x*size_factor/2,y*size_factor/2,dummy); LineTo(metaDC,tx*size_factor/2,ty*size_factor/2); SelectObject(metaDC,dashedpen); MoveToEx (metaDC, coord->x*size_factor/2,coord->y*size_factor/2,dummy); LineTo(metaDC,coord->tx*size_factor/2,coord->ty*size_factor/2); SelectObject(metaDC,pen); } if (hp_b->bond == 16) { coord = center_double_bond (x, y, tx, ty, db_dist); x = coord->x; y = coord->y; tx = coord->tx; ty = coord->ty; coord++; for (i = 0; i < 10; i++){ MoveToEx (metaDC,(int) (x+0.1*i*(tx-x)*size_factor/2), (int)(y+0.1*i*(ty-y)*size_factor/2),dummy); LineTo(metaDC, (int)(coord->x+0.1*i*(coord->tx-coord->x)*size_factor/2), (int)(coord->y+0.1*i*(coord->ty-coord->y)*size_factor/2)); } } } hp_b = hp_b->next; } ha = 9 * fzoom; ha = 9 *size_factor; hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { if (mark.flag && hp_a->marked == 0) { } else { switch (hp_a->direct) { case Middle_Text: chl = 0; SetTextAlign(metaDC,TA_CENTER+TA_BOTTOM); break; case Left_Text: chl = 9 * fzoom; SetTextAlign(metaDC,TA_LEFT+TA_BOTTOM); break; case Right_Text: chl = -9 * fzoom; SetTextAlign(metaDC,TA_RIGHT+TA_BOTTOM); break; default: fprintf (stderr, "undefined text direction in emf output\n"); rval = 3; chl=0; ;; } nsub = 0; nsup = 0; for (i = 0; i < (int)strlen (hp_a->c); ++i) if (hp_a->c[i] == '\\') hp_a->c[i] = ' '; if (!strpbrk (hp_a->c, "@_^|#")) { /*no sub- or superscripts */ xpos = hp_a->x * fzoom; csize = fontsize * fzoom * 1.4; SelectObject(metaDC,normalfont); TextOutA(metaDC,(int)((hp_a->x)*size_factor/2),(int)((hp_a->y+25)*size_factor/2), hp_a->c,(int)strlen(hp_a->c)); } else { /* special formatting needed, every character becomes a separate entity */ l = (int)strlen (hp_a->c); l = 0; for (i = 0; i < (int)strlen (hp_a->c); i++) { switch (hp_a->c[i]) { case '@': break; case '_': case '^': /* l -= .5; ??*/ break; default: l++; } } fzoom=size_factor; xpos = hp_a->x * size_factor - chl; if (hp_a->direct == Right_Text) xpos=xpos-12*(l-2); csize = fontsize * size_factor * 1.4; shifted=0; for (i = 0; i < (int)strlen (hp_a->c); i++) { offset = 0; SelectObject(metaDC,normalfont); csize = fontsize * fzoom * 1.4; if (shifted != 0) { if (hp_a->c[i] == '}') { shifted = 0; i++; if (i >= (int)strlen (hp_a->c)) break; } else { offset = shifted; } } if (hp_a->c[i] == '_') { if (chl >= 0) csize = csize / 2; offset = ha / 2; nsub = nsub + 1; if (nsub == 1) { if (nsup > 0) xpos = savedpos; else savedpos = xpos; } nsup = 0; } if (hp_a->c[i] == '^') { offset = -ha / 2; nsup = nsup + 1; if (nsup == 1) { if (nsub > 0) xpos = savedpos; else savedpos = xpos; } nsub = 0; } if (offset != 0) { SelectObject(metaDC,smallfont); /* if (chl < 0) xpos = xpos - csize / 2; else xpos = xpos - 20;*/ if (hp_a->direct==Right_Text) xpos=xpos-10; if (shifted == 0) { i++; if (hp_a->c[i] == '{') { shifted = offset; i++; } } if (i >= (int)strlen (hp_a->c)) break; if (hp_a->c[i] != '-' && hp_a->c[i] != '+') offset = offset * 2; } else { /*reset sub- and superscript counters */ nsub = 0; nsup = 0; } if (hp_a->c[i] == '@') { SelectObject(metaDC,symbolfont); if (offset !=0) SelectObject(metaDC,smallsymbolfont); i++; } if (hp_a->c[i] == '|') { SelectObject(metaDC,italicfont); if (offset!=0) SelectObject(metaDC,smallitalicfont); /* csize = csize / 2; */ i++; } if (hp_a->c[i] == '#') { SelectObject(metaDC,boldfont); if (offset!=0) SelectObject(metaDC,smallboldfont); i++; } sprintf(tmpstring,"%c",hp_a->c[i]); TextOutA(metaDC,(int)((xpos-10+abs(offset/2))/2), (int)((hp_a->y+25)*size_factor/2), tmpstring,(int)strlen(tmpstring)); xpos = xpos + 20; if (zoom_factor < 2) xpos = xpos + 10; } /*for i */ } /* normal or special formatting */ for (i = 0; i < (int)strlen (hp_a->c); ++i) if (hp_a->c[i] == ' ') hp_a->c[i] = '\\'; } /* if within current set*/ hp_a = hp_a->next; } /* for all labels */ hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { if (mark.flag == 1 && hp_sp->marked == 0) { } else { points[0].x=hp_sp->x0 *size_factor/2; points[0].y=hp_sp->y0 *size_factor/2; points[1].x=hp_sp->x1 *size_factor/2; points[1].y=hp_sp->y1 *size_factor/2; points[2].x=hp_sp->x2 *size_factor/2; points[2].y=hp_sp->y2 *size_factor/2; points[3].x=hp_sp->x3 *size_factor/2; points[3].y=hp_sp->y3 *size_factor/2; switch (hp_sp->type) { case 0: case 1: case 2: PolyBezier(metaDC,points,4); break; ;; case -2: SelectObject(metaDC,dashedpen); PolyBezier(metaDC,points,4); SelectObject(metaDC,pen); break; ;; case -1: SelectObject(metaDC,fill); PolyBezier(metaDC,points,4); SelectObject(metaDC,pen); } if (hp_sp->type > 0) { xbase = 0.7 * 0.7 * 0.7 * (double) hp_sp->x3 + 3. * 0.7 * 0.7 * (1. - 0.7) * (double) hp_sp->x2 + 3. * 0.7 * (1. - 0.7) * (1. - 0.7) * (double) hp_sp->x1 + (1. - 0.7) * (1. - 0.7) * (1. - 0.7) * hp_sp->x0; ybase = 0.7 * 0.7 * 0.7 * (double) hp_sp->y3 + 3. * 0.7 * 0.7 * (1. - 0.7) * (double) hp_sp->y2 + 3. * 0.7 * (1. - 0.7) * (1. - 0.7) * (double) hp_sp->y1 + (1. - 0.7) * (1. - 0.7) * (1. - 0.7) * hp_sp->y0; xlen = hp_sp->x3 - xbase; ylen = hp_sp->y3 - ybase; if (xlen != 0) xlen = (int) copysign (50., xlen); if (ylen != 0) ylen = (int) copysign (50., ylen); xside = xbase + 0.15 * ylen; yside = ybase - 0.15 * xlen; if (hp_sp->type == 1) { xend = xbase - 0.15 * ylen; yend = ybase + 0.15 * xlen; x = (xside - hp_sp->x0) * (xside - hp_sp->x0) + (yside - hp_sp->y0) * (yside - hp_sp->y0); tx = (xend - hp_sp->x0) * (xend - hp_sp->x0) + (yend - hp_sp->y0) * (yend - hp_sp->y0); if (tx > x) { xside = xend; yside = yend; } xend = xbase; /*on baseline */ yend = ybase; } else { xend = xbase - 0.15 * ylen; yend = ybase + 0.15 * xlen; } SelectObject(metaDC,fill); points[0].x=hp_sp->x3*size_factor/2; points[0].y=hp_sp->y3*size_factor/2; points[1].x=xside*size_factor/2; points[1].y=yside*size_factor/2; points[2].x=xend*size_factor/2; points[2].y=yend*size_factor/2; Polygon(metaDC,points,3); SelectObject(metaDC,pen); } } hp_sp = hp_sp->next; } mfh=CloseEnhMetaFile(metaDC); DeleteEnhMetaFile(mfh); DeleteDC(metaDC); return (0); } #endif int export_bitmap (char *filename) /* exports the current drawing to an X11 bitmap file */ { int x, y, w, h; struct data *hp_b; struct dc *hp_a; struct spline *hp_sp; int d; int retval; char xfile[512]; Pixmap buffer; GdkPixmap *bitmap; GdkGC *bitmapgc; if (mark.flag && mark.w != 0 && mark.h != 0) { x = mark.x * size_factor + 3; y = mark.y * size_factor + 3; w = mark.w * size_factor - 6; h = mark.h * size_factor - 6; } else { /* get true extents of drawing*/ x = 10000; y = 10000; w = 0; h = 0; hp_b = da_root.next; for (d = 0; d < hp->n; d++) { w = MAX (w, hp_b->x); w = MAX (w, hp_b->tx); h = MAX (h, hp_b->y); h = MAX (h, hp_b->ty); x = MIN (x, hp_b->x); x = MIN (x, hp_b->tx); y = MIN (y, hp_b->y); y = MIN (y, hp_b->ty); hp_b = hp_b->next; } hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { w = MAX (w, hp_a->x); if (hp_a->direct > -2) w = MAX (w, hp_a->x + (int)strlen (hp_a->c) * (6 + 2 * size_factor)); h = MAX (h, hp_a->y + 8); x = MIN (x, hp_a->x); if (hp_a->direct < 0) x = MIN (x, hp_a->x - (int)strlen (hp_a->c) * (6 + 2 * size_factor)); y = MIN (y, hp_a->y - 8); hp_a = hp_a->next; } hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { w = MAX (w, hp_sp->x0); h = MAX (h, hp_sp->y0); w = MAX (w, hp_sp->x1); h = MAX (h, hp_sp->y1); w = MAX (w, hp_sp->x2); h = MAX (h, hp_sp->y2); w = MAX (w, hp_sp->x3); h = MAX (h, hp_sp->y3); x = MIN (x, hp_sp->x0); y = MIN (y, hp_sp->y0); x = MIN (x, hp_sp->x1); y = MIN (y, hp_sp->y1); x = MIN (x, hp_sp->x2); y = MIN (y, hp_sp->y2); x = MIN (x, hp_sp->x3); y = MIN (y, hp_sp->y3); hp_sp = hp_sp->next; } x = (int) (x * size_factor * 0.9); y = (int) (y * size_factor * 0.9); w = (int) (w * size_factor * 1.1 - x); h = (int) (h * size_factor * 1.1 - y); if (x < 0) x = 0; if (y < 0) y = 0; } bitmap = gdk_pixmap_new (drawing_area->window, 1, 1, 1); bitmapgc = gdk_gc_new (bitmap); buffer = XCreatePixmap (GDK_WINDOW_XDISPLAY(picture), GDK_WINDOW_XWINDOW(picture), (unsigned int)w, (unsigned int)h, 1); XCopyPlane (GDK_WINDOW_XDISPLAY(picture), GDK_WINDOW_XWINDOW(picture), buffer, GDK_GC_XGC(bitmapgc), x, y, (unsigned int)w, (unsigned int)h, 0, 0, 1); if ((int)strlen (filename)) { snprintf (xfile,512, "%s", filename); retval = XWriteBitmapFile (GDK_DISPLAY (), xfile, buffer, (unsigned int)w, (unsigned int)h, -1, -1); gdk_pixmap_unref (bitmap); gdk_gc_unref (bitmapgc); XFreePixmap (GDK_DISPLAY (), buffer); return (retval); } return (0); } void xfig_line (FILE * fp, int x, int y, int tx, int ty) /* writes a single line bond in XFig notation */ { fprintf (fp, "%i %i %i %i %i %i %i %i %i %.3f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints); fprintf (fp, "%i %i %i %i\n", x, y, tx, ty); } void xfig_wedge (FILE * fp, int x, int y, int tx, int ty, int factor, int latex) /* writes a wedge definition in XFig notation */ { struct data *hpc; struct xy_co *coord; int d, x1, y1, x2, y2; int bond_already_tuned; float area; x1 = tx - (int) (0.1 * (float) (ty - y)); y1 = ty + (int) (0.1 * (float) (tx - x)); x2 = tx + (int) (0.1 * (float) (ty - y)); y2 = ty - (int) (0.1 * (float) (tx - x)); hpc = da_root.next; bond_already_tuned = 0; for (d = 0; d < hp->n; d++) { if (hpc->bond == 10) { if ( (abs (hpc->x * factor - tx) < 3 && abs (hpc->y * factor - ty) < 3) || (abs (hpc->tx * factor - tx) < 3 && abs (hpc->ty * factor - ty) < 3)) { coord = center_double_bond (hpc->x, hpc->y, hpc->tx, hpc->ty, db_dist); if (abs (hpc->x * factor - tx) < 3 && abs (hpc->y * factor - ty) < 3) { x1 = coord->x * factor; y1 = coord->y * factor; coord++; x2 = coord->x * factor; y2 = coord->y * factor; } else { x1 = coord->tx * factor; y1 = coord->ty * factor; coord++; x2 = coord->tx * factor; y2 = coord->ty * factor; } area = 0.5 * abs (x * (y1 - y2) + x1 * (y2 - y) + x2 * (y - y1)); if (fabs (area) < 76. * factor) { x1 = tx - (int) (0.05 * (float) (ty - y)); y1 = ty + (int) (0.05 * (float) (tx - x)); x2 = tx + (int) (0.05 * (float) (ty - y)); y2 = ty - (int) (0.05 * (float) (tx - x)); } else bond_already_tuned = 1; } } if (hpc->bond == 0 && !bond_already_tuned) { if ((abs (hpc->x * factor - tx) < 3 && abs (hpc->y * factor - ty) < 3) ||(abs (hpc->tx * factor - tx) < 3 && abs (hpc->ty * factor - ty) < 3)) /* let the wedge smooth along a another bond */ { coord = intersect(x,y,x1,y1,hpc->x*factor,hpc->y*factor, hpc->tx*factor,hpc->ty*factor); coord->tx = coord->x; coord->ty = coord->y; coord = intersect(x,y,x2,y2,hpc->x*factor,hpc->y*factor, hpc->tx*factor,hpc->ty*factor); x1 = coord->tx; y1 = coord->ty; x2 = coord->x; y2 = coord->y; area = 0.5 * abs (x * (y1 - y2) + x1 * (y2 - y) + x2 * (y - y1)); if (fabs (area) > 3300. * factor || fabs(area) < 1750. * factor) { x1 = tx - (int) (0.1 * (float) (ty - y)); y1 = ty + (int) (0.1 * (float) (tx - x)); x2 = tx + (int) (0.1 * (float) (ty - y)); y2 = ty - (int) (0.1 * (float) (tx - x)); } } } hpc = hpc->next; } if (!latex) { fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill + 21, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints + 1); fprintf (fp, "%i %i %i %i %i %i\n", x, y, x1, y1, x2, y2); } else { for (d = 0; d < 10; d++) xfig_line (fp, x, y, x1 + d * (x2 - x1) / 10, y1 + d * (y2 - y1) / 10); } } void xfig_wiggly (FILE * fp, int x, int y, int tx, int ty) /* writes a wavy bond in XFig notation */ { int arccode = 5; int arctype = 1; int direction = 1; float xlen, ylen, veclen, boxlen; int boxcorx, boxcory; int i; float center_x, center_y; int xstart, ystart, xmid, ymid, xend, yend; xlen = (float)(tx - x); ylen = (float)(ty - y); veclen = (float)calc_vector (abs (tx - x), abs (ty - y)); boxlen = 0.2 * veclen; boxcorx = (int) ((1. - xlen / veclen) * boxlen / 2); boxcory = (int) ((1. - ylen / veclen) * boxlen / 2); for (i = 0; i < 5; i++) { direction = abs (direction - 1); center_x = x + (0.2 * i + .1) * xlen; center_y = y + (0.2 * i + .1) * ylen; xstart = (int) (x + 0.2 * i * xlen); ystart = (int) (y + 0.2 * i * ylen); xmid = (int) (center_x - boxcorx * pow (-1, (double)i)); ymid = (int) (center_y - boxcory * pow (-1, (double)i)); if (x > tx) { xmid = (int) (center_x + boxcorx * pow (-1, (double)i)); ymid = (int) (center_y + boxcory * pow (-1, (double)i)); } xend = (int) (x + 0.2 * (i + 1) * xlen); yend = (int) (y + 0.2 * (i + 1) * ylen); fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %f %f %i %i %i %i %i %i\n", arccode, arctype, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, figline.cap_style, direction, figline.forward_arrow, figline.backward_arrow, center_x, center_y, xstart, ystart, xmid, ymid, xend, yend); } } void xfig_arrow (FILE * fp, int x, int y, int tx, int ty, int type, int latex) /* writes an arrow in XFig notation */ { float xlen, ylen; float headfact; int xbase, ybase, xside, yside, xend, yend; int i; float veclen; xlen = (float)(tx - x); ylen = (float)(ty - y); headfact = 0.8; xbase = x + headfact * xlen; ybase = y + headfact * ylen; if (select_char (tx,ty,1) != NULL){ veclen = (float)calc_vector(tx-x,ty-y); xbase = x+headfact*xlen-10*xlen/veclen; ybase = y+headfact*ylen-10*ylen/veclen; } xside = (int) (xbase + 0.05 * ylen); yside = (int) (ybase - 0.05 * xlen); xend = (int) (xbase - type * (0.05 * ylen)); /*type=0 (half arrow) ends on baseline, */ yend = (int) (ybase + type * (0.05 * xlen)); /*type=1 is a symmetrical arrowhead */ if (type == 1) { /* symmetrical arrow */ fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow + 1, figline.backward_arrow, figline.npoints); fprintf (fp, "%i %i %f %f %f\n", /* arrow attributes */ 1, /* arrow_type (triangle, as before) */ 1, /* arrow_style (1 == filled) */ 2.00, /* arrow_thickness (1/80inch) */ 72.00, /* arrow_width (fig units (?) ) */ 114.00 /* arrow_height (fig units) */ ); fprintf (fp, "%i %i %i %i\n", x, y, tx, ty); } else { /* half arrow */ /* the line */ fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints); fprintf (fp, "%i %i %i %i\n", x, y, tx, ty); /* and the arrowhead - a filled polyline */ if (!latex) { fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill + 21, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints + 1); fprintf (fp, "%i %i %i %i %i %i\n", tx, ty, xside, yside, xend, yend); } else { for (i = 0; i < 10; i++) xfig_line (fp, tx, ty, xend + i * (xside - xend) / 10, yend + i * (yside - yend) / 10); } } } void xfig_circle (FILE * fp, int x, int y, int tx, int ty) { int radius; float start_ang = 0.; int direction = 1; radius = calc_vector (abs (tx - x), abs (ty - y)); fprintf (fp, "1 3 %i %i %i %i %i %i %i %.4f %i %.4f %i %i %i %i %i %i %i %i\n", figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, direction, start_ang, x, y, radius, radius, tx, ty, tx, ty); } void xfig_spline (FILE * fp, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int type, int latex) /* draws a spline curve, optionally with full of half arrowhead */ { int xlen, ylen, xbase, ybase, flag; double px0, py0, px1, py1; int i; double t; double dist; int xside, yside, xend, yend; figline.npoints = 21; if (type == -2) { figline.line_style = 2; figline.style_val = 4; } if (type == -1) { figline.area_fill = 20; } /* if (type == 1)*/ /* figline.npoints = 15;*/ /* the line */ fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints); fprintf (fp, "%i %i\n", x0, y0); px0 = (double)x0; py0 = (double)y0; xbase = 0; ybase = 0; flag = 0; for (i = 0; i < figline.npoints -1 ; i++) { t = (float) i / (figline.npoints -2 ); px1 = t * t * t * (double) x3 + 3. * t * t * (1. - t) * (double) x2 + 3. * t * (1. - t) * (1. - t) * (double) x1 + (1. - t) * (1. - t) * (1. - t) * px0; py1 = t * t * t * (double) y3 + 3. * t * t * (1. - t) * (double) y2 + 3. * t * (1. - t) * (1. - t) * (double) y1 + (1. - t) * (1. - t) * (1. - t) * py0; fprintf (fp, "%i %i\n", (int) px1, (int) py1); if (type >= 0) { dist = (x3-px1) * (x3-px1) + (y3-py1) * (y3-py1) ; if (( flag == 0) && ( i == 18 || (i >= 15 && dist < 30000.) ) ) { xbase = (int)px1; ybase = (int)py1; if (dist >30000.) { xbase += (x3-xbase)/2; ybase += (y3-ybase)/2; } flag = 1; } } } figline.line_style = 0; figline.style_val = 0; figline.area_fill = -1; figline.npoints = 2; if (type <= 0) return; xlen = x3 - xbase; ylen = y3 - ybase; if (xlen != 0) xlen = (int) copysign (50., (double)xlen); if (ylen != 0) ylen = (int) copysign (50., (double)ylen); xside = (int) (xbase + 0.5 * ylen); yside = (int) (ybase - 0.5 * xlen); if (type == 1) { xend = (int) (xbase - 0.5 * ylen); yend = (int) (ybase + 0.5 * xlen); px0 = (double)((xside - x0) * (xside - x0) + (yside - y0) * (yside - y0)); px1 = (double)((xend - x0) * (xend - x0) + (yend - y0) * (yend - y0)); if (px1 > px0) { xside = xend; yside = yend; } xend = xbase; /*on baseline */ yend = ybase; } else { xend = (int) (xbase - 0.5 * ylen); yend = (int) (ybase + 0.5 * xlen); } /* add the arrowhead - a filled polyline */ if (!latex) { fprintf (fp, "%i %i %i %i %i %i %i %i %i %f %i %i %i %i %i %i\n", figline.object, figline.sub_type, figline.line_style, figline.thickness, figline.pen_color, figline.fill_color, figline.depth, figline.pen_style, figline.area_fill + 21, figline.style_val, figline.join_style, figline.cap_style, figline.radius, figline.forward_arrow, figline.backward_arrow, figline.npoints + 1); fprintf (fp, "%i %i %i %i %i %i\n", (int) x3, (int) y3, xside, yside, xend, yend); } else { for (i = 0; i < 10; i++) xfig_line (fp, x3, y3, xend + i * (xside - xend) / 10, yend + i * (yside - yend) / 10); } } int exfig (FILE * fp, int latex_flag) /* export the current molecule in the format of Brian Smith' XFig program */ { struct data *hp_b; struct dc *hp_a; struct spline *hp_sp; struct xy_co *coord; int i; float l; int d, x, y, tx, ty; int n; #ifdef GTK2 int tw; static PangoLayout *thelayout; char cc[2]; #endif int ulx, uly, lrx, lry; int ha, chl = 0; int fontsize = 12, fzoom = 10; int xpos, offset, fontshrink; int shifted = 0; int nsub, nsup, savedpos; int csize; char symbol[30]; int rval = 0; float charscale; /* scale textlength, width according to zoom factor */ int len; float step; const int myfontheight[7]={8,8,9,14,12,14,24}; #ifdef GTK2 setlocale(LC_NUMERIC,"C"); #endif savedpos = 0; switch (zoom_factor) { case 0: fontsize = 8; /*8 */ fzoom = 9; /*6,4 */ charscale = 0.5; break; case 1: fontsize = 10; /*6? */ fzoom = 9; /*5? */ charscale = 0.75; break; case 2: fontsize = 12; /*9? */ fzoom = 11; /*7? */ charscale = 1.0; break; case 3: fontsize = 16; /*12? */ fzoom = 12; /*12,10? */ charscale = 1.25; break; case 4: fontsize = 18; fzoom = 13; charscale = 1.3; break; default: charscale = 1.; fprintf (stderr, "no figfont parameters for zoom factor %d\n", zoom_factor); rval = 2; } if (!fprintf (fp, "#FIG 3.2\n")) return (1); fprintf (fp, "Portrait\n"); fprintf (fp, "Center\n"); fprintf (fp, "Metric\n"); fprintf (fp, "A4\n"); fprintf (fp, "100.00\n"); fprintf (fp, "Single\n"); fprintf (fp, "0\n"); fprintf (fp, "# generated by Chemtool " VERSION "\n"); fprintf (fp, "1200 2\n"); figline.object = 2; figline.sub_type = 1; figline.line_style = 0; figline.thickness = 2; figline.pen_color = 0; figline.fill_color = 7; figline.depth = 100; figline.pen_style = 0; figline.area_fill = -1; figline.style_val = 0.000; figline.join_style = 0; figline.cap_style = 0; figline.radius = -1; figline.forward_arrow = 0; figline.backward_arrow = 0; figline.npoints = 2; hp_b = da_root.next; for (d = 0; d < hp->n; d++) { if (mark.flag && (hp_b->smarked + hp_b->tmarked) == 0) { } else { figline.pen_color = hp_b->color; figline.fill_color = hp_b->color; coord = bond_cut (hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, 12); if(hp_b->bond==11) coord = bond_cut (hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, 0); #if 0 if(hp_b->bond==5 || hp_b->bond==6) coord = bond_cut (hp_b->x, hp_b->y, hp_b->tx, hp_b->ty, 15); #endif x = coord->x * fzoom; y = coord->y * fzoom; tx = coord->tx * fzoom; ty = coord->ty * fzoom; #if 1 if ( !use_whiteout) { i=has_label(hp_b->x,hp_b->y); if (i>=0) { int ox=x; x += (1.*fzoom*(i+1)/calc_vector(abs(tx-x),abs(ty-y))) *(tx-x); y += (1.*fzoom*(i+1)/calc_vector(abs(tx-ox),abs(ty-y))) *(ty-y); } i=has_label(hp_b->tx,hp_b->ty); if (i>=0) { int otx=tx; tx -= (1.*fzoom*(i+1)/calc_vector(abs(tx-x),abs(ty-y))) *(tx-x); ty -= (1.*fzoom*(i+1)/calc_vector(abs(otx-x),abs(ty-y))) *(ty-y); } } #endif if (!hp_b->bond) xfig_line (fp, x, y, tx, ty); if (hp_b->bond == 5) { xfig_wedge (fp, x, y, tx, ty, fzoom, latex_flag); } if (hp_b->bond == 6) { len=(int) (calc_vector(abs(tx-x),abs(ty-y))/(8.*fzoom)); if (len <8 ) len=8; step=1./len; for (i = 1; i < len; i=i+1) xfig_line (fp, (int) (x + step * i * (tx - x) - 0.01 * (ty - y) * i), (int) (y + step * i * (ty - y) + 0.01 * (tx - x) * i), (int) (x + step * i * (tx - x) + 0.01 * (ty - y) * i), (int) (y + step * i * (ty - y) - 0.01 * (tx - x) * i)); } if (hp_b->bond == 7) xfig_wiggly (fp, x, y, tx, ty); if (hp_b->bond == 8) xfig_arrow (fp, x, y, tx, ty, 0, latex_flag); if (hp_b->bond == 9) xfig_arrow (fp, x, y, tx, ty, 1, latex_flag); if (hp_b->bond == 11) xfig_circle (fp, x, y, tx, ty); if (hp_b->bond == 10) { figline.thickness = 6; /* 4 ? */ xfig_line (fp, x, y, tx, ty); figline.thickness = 2; /* 1 ? */ } if (hp_b->bond == 12) { figline.line_style = 2; figline.style_val = 4; xfig_line (fp, x, y, tx, ty); figline.line_style = 0; figline.style_val = 0; } if (hp_b->bond == 13) { figline.thickness = 6; figline.pen_color = 7; figline.depth = 85; xfig_line (fp, x + (tx - x) / 4, y + (ty - y) / 4, tx - (tx - x) / 4, ty - (ty - y) / 4); figline.thickness = 2; figline.pen_color = 0; figline.depth = 80; xfig_line (fp, x, y, tx, ty); figline.depth = 100; } if (hp_b->bond == 4) { coord = center_double_bond (x, y, tx, ty, db_dist * fzoom); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); coord++; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); } if (hp_b->bond == 1 || hp_b->bond == 3) { coord = multi_bonds (x, y, tx, ty, mb_dist * fzoom); xfig_line (fp, x, y, tx, ty); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); } if (hp_b->bond == 2 || hp_b->bond == 3) { coord = multi_bonds (tx, ty, x, y, mb_dist * fzoom); xfig_line (fp, x, y, tx, ty); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); } if (hp_b->bond == 14) { coord = multi_bonds (x, y, tx, ty, mb_dist * fzoom); xfig_line (fp, x, y, tx, ty); figline.line_style = 1; figline.style_val = 2.; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); figline.line_style = 0; figline.style_val = 0.; } if (hp_b->bond == 15) { coord = multi_bonds (tx, ty, x, y, mb_dist * fzoom); xfig_line (fp, x, y, tx, ty); figline.line_style = 1; figline.style_val = 2.; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); figline.line_style = 0; figline.style_val = 0.; } if (hp_b->bond == 16) { coord = center_double_bond (x, y, tx, ty, db_dist * fzoom); x = coord->x; y = coord->y; tx = coord->tx; ty = coord->ty; coord++; for (i = 0; i < 10; i++) xfig_line (fp, (int) (x + 0.1 * i * (tx - x)), (int) (y + 0.1 * i * (ty - y)), (int) (coord->x + 0.1 * i * (coord->tx - coord->x)), (int) (coord->y + 0.1 * i * (coord->ty - coord->y))); } if (hp_b->bond == 18) { xfig_line (fp, x, y, tx, ty); coord = center_double_bond (x, y, tx, ty, (db_dist+1) * fzoom); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); coord++; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); } if (hp_b->bond == 19) { int tmpx1,tmpx2,tmpy1,tmpy2,tmptx1,tmptx2,tmpty1,tmpty2; coord = center_double_bond (x, y, tx, ty, (db_dist+2) * fzoom); tmpx1=coord->x; tmpy1=coord->y; tmptx1=coord->tx; tmpty1=coord->ty; coord++; tmpx2=coord->x; tmpy2=coord->y; tmptx2=coord->tx; tmpty2=coord->ty; coord = center_double_bond (tmpx1,tmpy1,tmptx1,tmpty1,(db_dist-1)*fzoom); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); coord++; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); coord = center_double_bond (tmpx2,tmpy2,tmptx2,tmpty2,(db_dist-1)*fzoom); xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); coord++; xfig_line (fp, coord->x, coord->y, coord->tx, coord->ty); } /* hp_b = hp_b->next;*/ } hp_b = hp_b->next; } figtext.object = 4; figtext.sub_type = 0; figtext.color = 0; figtext.depth = 90; figtext.pen_style = 0; figtext.font = 16; /*16=helvetica*,12=courier */ figtext.font_size = fontsize; figtext.angle = 0.000; if (!latex_flag) figtext.font_flags = 4; /*6?? messes up bounding box*/ else figtext.font_flags = 6; figtext.height = 180. *charscale; figtext.length = 170. *charscale; hp_a = dac_root.next; for (d = 0; d < hp->nc; d++) { if (mark.flag && hp_a->marked == 0) { } else { fontsize=hp_a->size; if (zoom_factor <2) fontsize-= 2-zoom_factor; if (zoom_factor >2) fontsize+= zoom_factor-2; if (fontsize <0) fontsize=0; if (fontsize >6) fontsize=6; switch (fontsize) { case 0: figtext.font_size = 8; /*8 */ break; case 1: figtext.font_size = 10; /*6? */ break; case 2: figtext.font_size = 12; /*9? */ break; case 3: figtext.font_size = 16; /*12? */ break; case 4: figtext.font_size = 18; break; case 5: figtext.font_size = 20; break; case 6: figtext.font_size = 24; break; default: fprintf (stderr, "no figfont parameters for fontsize %d\n", fontsize); rval = 2; } /* fzoom = size_factor * 16. ;*/ /* 75dpi screen to 1200dpi FIG */ #ifdef GTK2 if (!thelayout) thelayout = gtk_widget_create_pango_layout(drawing_area,"X"); pango_layout_set_text(thelayout, "X", -1); pango_layout_set_font_description(thelayout,symbfont[fontsize]); pango_layout_get_pixel_size(thelayout, NULL, &ha); ha = ha/100 *fzoom; #else ha=fzoom * gdk_char_height(font[fontsize],(gchar)'X'); #endif ha=(int)(fzoom/2. * myfontheight[fontsize]); figtext.height = 180. *charscale; figtext.length = 170. *charscale; figtext.color = hp_a->color; if (hp_a->font == 0) figtext.font = 16; /* Helvetica */ else figtext.font = 0; /* Times */ figtext.sub_type = abs (hp_a->direct); switch (hp_a->direct) { case Middle_Text: chl = 0; break; case Left_Text: chl = 9 * fzoom; break; case Right_Text: chl = -9 * fzoom; break; default: fprintf (stderr, "undefined text direction in xfig output\n"); rval = 3; ;; } nsub = 0; nsup = 0; for (i = 0; i < (int)strlen (hp_a->c); ++i) if (hp_a->c[i] == '\\') hp_a->c[i] = ' '; if (!strpbrk (hp_a->c, "@_^|#")) { /*no sub- or superscripts */ xpos = hp_a->x * fzoom; csize = (int) (fontsize * fzoom /* * 1.4*/); if (chl < 0) xpos -= (int)strlen (hp_a->c) * csize; if (chl == 0) xpos -= (int)strlen (hp_a->c) * csize / 2; ulx = xpos; if (chl > 0) ulx = xpos - csize / 2; /* if (chl == 0) ulx = xpos+ csize/2; */ if (chl < 0) ulx = xpos + csize; uly = hp_a->y * fzoom - ha; lrx = xpos + (int)strlen (hp_a->c) * csize - csize / 2; if (chl == 0) lrx += csize/2; if (chl < 0) lrx = lrx + csize; lry = hp_a->y * fzoom + ha; /*whiteout box*/ if (use_whiteout == 1) fprintf (fp, " 6 %i %i %i %i\n", ulx, uly, lrx, lry); if (use_whiteout == 1 && !latex_flag) { fprintf (fp, " 2 2 0 1 7 7 95 0 20 1 0 0 5 0 0 5\n"); fprintf (fp, "%i %i\n", ulx, uly); fprintf (fp, "%i %i\n", lrx, uly); fprintf (fp, "%i %i\n", lrx, lry); fprintf (fp, "%i %i\n", ulx, lry); fprintf (fp, "%i %i\n", ulx, uly); } if (latex_flag) { int ii,jj; char latexstr[255]; jj=0; for (ii=0;ii<(int)strlen(hp_a->c);ii++){ if (hp_a->c[ii] == '°' ){ latexstr[jj++]='\0'; strcat(latexstr,"$^{\\\\circ}$"); jj += 10; continue; } if (hp_a->c[ii] == (char)169 ){ latexstr[jj++]='\0'; strcat(latexstr,"$\\\\copyright$"); jj += 12; continue; } if (hp_a->c[ii] == (char)174 ){ latexstr[jj++]='\0'; strcat(latexstr,"$\\\\textregistered$"); jj += 17; continue; } if (hp_a->c[ii] == (char)177 ){ latexstr[jj++]='\0'; strcat(latexstr,"$\\\\pm$"); jj += 5; continue; } if (hp_a->c[ii]=='%' || hp_a->c[ii]=='$') { latexstr[jj++]='\\'; latexstr[jj++]='\\'; } latexstr[jj++]=hp_a->c[ii]; } latexstr[jj]='\0'; fprintf (fp, "%i %i %i %i %i %i %d %.4f %i %f %f %i %i %s\\001\n", figtext.object, figtext.sub_type, figtext.color, figtext.depth, figtext.pen_style, figtext.font, figtext.font_size, figtext.angle, figtext.font_flags, figtext.height, figtext.length * (int)strlen (latexstr), hp_a->x * fzoom - chl, hp_a->y * fzoom + ha, latexstr); } else { //{ float tlen=0.; int xxx; int cw; #ifdef GTK2 gchar *c; c=g_convert(hp_a->c,-1,"ISO8859-1","UTF-8",NULL,NULL,NULL); if (!c) c=g_strdup(hp_a->c); #else char *c = strdup(hp_a->c); #endif for (xxx=0;xxxc);xxx++){ #ifdef GTK2 gchar *cx; cx=g_locale_to_utf8(hp_a->c,-1,NULL,NULL,NULL); if (!cx) cx = g_convert(hp_a->c,-1,"UTF-8","ISO8859-1",NULL,NULL,NULL); if (!cx) { fprintf(stderr,"invalid character cx in chemtool file\n"); return 1; } if (!thelayout) thelayout = gtk_widget_create_pango_layout(drawing_area,cx); pango_layout_set_text(thelayout, cx, -1); pango_layout_set_font_description(thelayout,font[fontsize]); pango_layout_get_pixel_size(thelayout, &cw, NULL); tlen+=1.25*cw; #else cw=gdk_char_width(font[fontsize],(gchar)hp_a->c[xxx]); tlen+=15.*cw; if (hp_a->c[xxx]==' ') tlen+=12.*cw; #endif } //fprintf(stderr,"text #%s#, len_alt %f, len_neu %f\n", //hp_a->c, figtext.length*(int)strlen(hp_a->c), tlen); //} fprintf (fp, "%i %i %i %i %i %i %d %.4f %i %f %f %i %i %s\\001\n", figtext.object, figtext.sub_type, figtext.color, figtext.depth, figtext.pen_style, figtext.font, figtext.font_size, figtext.angle, figtext.font_flags, figtext.height, // figtext.length * (int)strlen (hp_a->c), tlen, (int)(hp_a->x * fzoom - chl ), hp_a->y * fzoom + ha, c); } if (use_whiteout==1) fprintf (fp, "-6\n"); /* close block (around whiteout and label) */ } else { /* special formatting needed, every character becomes a separate entity */ figtext.sub_type = 1; /* have xfig center characters at the calculated position */ l = 0; #ifdef GTK2 if (!thelayout) thelayout = gtk_widget_create_pango_layout(drawing_area,hp_a->c); pango_layout_set_font_description(thelayout,font[fontsize]); n = (int) g_utf8_strlen(hp_a->c,-1); #else n = (int)strlen (hp_a->c); #endif for (i = 0; i < (int)strlen (hp_a->c); i++) { switch (hp_a->c[i]) { case '@': i++; if (hp_a->c[i]=='}' || hp_a->c[i]=='{' ) i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,symbfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+= tw*fzoom; #else l+=gdk_char_width(symbfont[fontsize],hp_a->c[i])*fzoom; #endif break; case '#': i++; if (hp_a->c[i]=='}' || hp_a->c[i]=='{' ) i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,boldfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+= tw*fzoom; #else l+=gdk_char_width(boldfont[fontsize],hp_a->c[i])*fzoom; #endif break; case '|': i++; if (hp_a->c[i]=='}' || hp_a->c[i]=='{' ) i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,slfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+=tw*fzoom; #else l+=gdk_char_width(slfont[fontsize],hp_a->c[i])*fzoom; #endif break; case '}': case '{': break; case '_': nsub=1; i++; if (hp_a->c[i]=='}' || hp_a->c[i]=='{' ) i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+=tw*fzoom; #else l+=gdk_char_width(smallfont[fontsize],hp_a->c[i])*fzoom; #endif break; case '^': nsup=1; i++; if (hp_a->c[i]=='}' || hp_a->c[i]=='{' ) i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+=tw*fzoom; #else l+=gdk_char_width(smallfont[fontsize],hp_a->c[i])*fzoom; #endif break; default: #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,font[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); l+=tw*fzoom; #else l+=gdk_char_width(font[fontsize],hp_a->c[i])*fzoom; #endif } } xpos = hp_a->x * fzoom ; #ifdef GTK2 cc[0]=hp_a->c[0]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,font[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= tw *fzoom*2; #else csize = gdk_char_width(font[fontsize],hp_a->c[0])*fzoom*2; #endif if (chl < 0) { xpos = hp_a->x * fzoom -l + csize/2; } if (chl == 0) xpos = hp_a->x * fzoom - l / 2; /* glue text into compound for easier editing in xfig */ ulx = xpos -csize/2; uly = hp_a->y * fzoom - ha; lrx = xpos + l ; if (chl < 0) lrx = xpos + (l - 1); lry = hp_a->y * fzoom + ha; if (nsup != 0) uly -= ha; /* height adjustment for */ if (nsub != 0) lry += ha; /* sub- and superscript */ fprintf (fp, " 6 %i %i %i %i\n", ulx, uly, lrx, lry); /*whiteout box*/ if (use_whiteout == 1 && !latex_flag) { fprintf (fp, " 2 2 0 1 7 7 95 0 20 1 0 0 5 0 0 5\n"); fprintf (fp, "%i %i\n", ulx, uly); fprintf (fp, "%i %i\n", lrx, uly); fprintf (fp, "%i %i\n", lrx, lry); fprintf (fp, "%i %i\n", ulx, lry); fprintf (fp, "%i %i\n", ulx, uly); } nsub=nsup=0; for (i = 0; i < (int)strlen (hp_a->c); i++) { offset = 0; fontshrink = 0; if (hp_a->font == 0) figtext.font = 16; /*Helvetica */ else figtext.font = 0; /* Times */ #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,font[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); /* if (cc[0]=='C') csize=161; else if (cc[0]=='H') csize=145; else */ csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(font[fontsize],hp_a->c[i])) * fzoom; #endif if (shifted != 0) { if (hp_a->c[i] == '}') { shifted = 0; offset = 0; i++; if (i >= n) break; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,font[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(font[fontsize],hp_a->c[i])) * fzoom; #endif } else { offset = shifted; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(smallfont[fontsize],hp_a->c[i])) * fzoom; #endif } } if (hp_a->c[i] == '_') { #ifdef GTK2 cc[0]=hp_a->c[i+1]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(smallfont[fontsize],hp_a->c[i+1])) * fzoom; #endif offset = ha / 2; nsub = nsub + 1; if (nsub == 1) { if (nsup > 0) xpos = savedpos; else savedpos = xpos; } nsup = 0; } if (hp_a->c[i] == '^') { offset = -ha; /* offset = -ha / 2;*/ #ifdef GTK2 cc[0]=hp_a->c[i+1]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(smallfont[fontsize],hp_a->c[i+1])) * fzoom; #endif nsup = nsup + 1; if (nsup == 1) { if (nsub > 0) xpos = savedpos; else savedpos = xpos; } nsub = 0; } if (offset != 0) { if (shifted == 0) { i++; if (hp_a->c[i] == '{') { shifted = offset; i++; #ifdef GTK2 cc[0]=hp_a->c[i]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,smallfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(smallfont[fontsize],hp_a->c[i])) * fzoom; #endif } } if (i >= (int)strlen (hp_a->c)) break; if (hp_a->c[i] != '-' && hp_a->c[i] != '+') fontshrink = 4; offset = offset * 2; /* xpos -= csize*.75;*/ xpos -= csize*.35; } else { /*reset sub- and superscript counters */ nsub = 0; nsup = 0; } if (hp_a->c[i] == '@') { figtext.font = 32; #ifdef GTK2 cc[0]=hp_a->c[i+1]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,symbfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(symbfont[fontsize],hp_a->c[i+1])) * fzoom; #endif i++; } if (hp_a->c[i] == '|') { if (figtext.font <16) figtext.font = 1; /* Times Italic */ else figtext.font = 17; /* Helvetica Oblique */ #ifdef GTK2 cc[0]=hp_a->c[i+1]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,slfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+2*gdk_char_width(slfont[fontsize],hp_a->c[i+1])) * fzoom; #endif xpos-= csize; i++; } if (hp_a->c[i] == '#') { if (figtext.font < 16) figtext.font = 2 ; /* Times Bold */ else figtext.font = 18; /* Helvetica Bold */ #ifdef GTK2 cc[0]=hp_a->c[i+1]; cc[1]='\0'; pango_layout_set_text(thelayout, cc, -1); pango_layout_set_font_description(thelayout,boldfont[fontsize]); pango_layout_get_pixel_size(thelayout, &tw, NULL); csize= 1+ tw *fzoom; #else csize = (1+gdk_char_width(boldfont[fontsize],hp_a->c[i+1])) * fzoom; #endif i++; } if (figtext.font_size-fontshrink <8) csize *=0.8; if (hp_a->c[i] == '(' || hp_a->c[i] == ')' ) xpos -= csize; if (hp_a->c[i] == 'i' || hp_a->c[i] == 'l' ) xpos -= csize; if (latex_flag) { if (figtext.font == 32 /* use TeX names for symbols */ || (unsigned char) hp_a->c[i] > 128 || hp_a->c[i]=='%' || hp_a->c[i]=='$') { switch ((unsigned char) hp_a->c[i]) { case 'a': strcpy (symbol, "$\\\\alpha$"); break; case 'b': strcpy (symbol, "$\\\\beta$"); break; case 'c': strcpy (symbol, "$\\\\chi$"); break; case 'd': strcpy (symbol, "$\\\\delta$"); break; case 'e': strcpy (symbol, "$\\\\varepsilon$"); break; case 'f': strcpy (symbol, "$\\\\phi$"); break; case 'g': strcpy (symbol, "$\\\\gamma$"); break; case 'h': strcpy (symbol, "$\\\\eta$"); break; case 'i': strcpy (symbol, "$\\\\iota$"); break; case 'j': strcpy (symbol, "$\\\\varphi$"); break; case 'k': strcpy (symbol, "$\\\\kappa$"); break; case 'l': strcpy (symbol, "$\\\\lambda$"); break; case 'm': strcpy (symbol, "$\\\\mu$"); break; case 'n': strcpy (symbol, "$\\\\nu$"); break; case 'p': strcpy (symbol, "$\\\\pi$"); break; case 'q': strcpy (symbol, "$\\\\theta$"); break; case 'r': strcpy (symbol, "$\\\\rho$"); break; case 's': strcpy (symbol, "$\\\\sigma$"); break; case 't': strcpy (symbol, "$\\\\tau$"); break; case 'u': strcpy (symbol, "$\\\\upsilon$"); break; case 'v': strcpy (symbol, "$\\\\varpi$"); break; case 'w': strcpy (symbol, "$\\\\omega$"); break; case 'x': strcpy (symbol, "$\\\\xi$"); break; case 'y': strcpy (symbol, "$\\\\psi$"); break; case 'z': strcpy (symbol, "$\\\\zeta$"); break; case 'C': strcpy (symbol, "X"); break; case 'D': strcpy (symbol, "$\\\\Delta$"); break; case 'F': strcpy (symbol, "$\\\\Phi$"); break; case 'G': strcpy (symbol, "$\\\\Gamma$"); break; case 'J': strcpy (symbol, "$\\\\vartheta$"); break; case 'L': strcpy (symbol, "$\\\\Lambda$"); break; case 'P': strcpy (symbol, "$\\\\Pi$"); break; case 'Q': strcpy (symbol, "$\\\\Theta$"); break; case 'R': strcpy (symbol, "P"); break; case 'S': strcpy (symbol, "$\\\\Sigma$"); break; case 'U': strcpy (symbol, "$\\\\Upsilon$"); break; case 'V': strcpy (symbol, "$\\\\varsigma$"); break; case 'W': strcpy (symbol, "$\\\\Omega$"); break; case 'X': strcpy (symbol, "$\\\\Xi$"); break; case 'Y': strcpy (symbol, "$\\\\Psi$"); break; case (unsigned char) 173: strcpy (symbol, "$\\\\uparrow$"); break; case (unsigned char) 175: strcpy (symbol, "$\\\\downarrow$"); break; case (unsigned char) 174: #if 0 strcpy (symbol, "$\\\\bigcirc\\\\hspace{-1.5ex}R$"); #else strcpy (symbol, "$\\\\textregistered$"); #endif break; case '%': strcpy (symbol, "\\\\%"); break; case '$': strcpy (symbol, "\\\\$"); break; case (unsigned char) 176: strcpy(symbol, "$^{\\\\circ}$"); break; case (unsigned char) 177: strcpy(symbol, "$\\\\pm$"); break; case (unsigned char) 169: strcpy(symbol, "$\\\\copyright$"); break; default: fprintf (stderr, "no translation for %d\n", (unsigned char) hp_a->c[i]); symbol[0] = hp_a->c[i]; symbol[1] = '\0'; break; } fprintf (fp, "%i %i %i %i %i %i %d %.4f %i %f %f %i %i %s \\001\n", figtext.object, figtext.sub_type, figtext.color, figtext.depth, figtext.pen_style, figtext.font, figtext.font_size - fontshrink, figtext.angle, figtext.font_flags, figtext.height, figtext.length, xpos, hp_a->y * fzoom + ha + offset, symbol); } else { fprintf (fp, "%i %i %i %i %i %i %d %.4f %i %f %f %i %i %c\\001\n", figtext.object, figtext.sub_type, figtext.color, figtext.depth, figtext.pen_style, figtext.font, figtext.font_size - fontshrink, figtext.angle, figtext.font_flags, figtext.height, figtext.length, xpos, hp_a->y * fzoom + ha + offset, hp_a->c[i]); } } else { /* not in LaTeX mode */ fprintf (fp, "%i %i %i %i %i %i %d %.4f %i %f %f %i %i %c\\001\n", figtext.object, figtext.sub_type, figtext.color, figtext.depth, figtext.pen_style, figtext.font, figtext.font_size - fontshrink, figtext.angle, figtext.font_flags, figtext.height, (double)csize*2, xpos, hp_a->y * fzoom + ha + offset, hp_a->c[i]); } if (hp_a->c[i] == '(' || hp_a->c[i] == ')' ) xpos += csize; if (hp_a->c[i] == 'l' || hp_a->c[i] == 'i' ) xpos += csize; xpos = (int)(xpos + csize *1.1) ; } /*for i */ fprintf (fp, "-6\n"); /* close this compound */ } #ifdef GTK2 n = (int) g_utf8_strlen(hp_a->c,-1); #else n = (int)strlen (hp_a->c); #endif for (i = 0; i < n; ++i) if (hp_a->c[i] == ' ') hp_a->c[i] = '\\'; } hp_a = hp_a->next; } figline.pen_color = 0; /* reset after linedrawing */ hp_sp = sp_root.next; for (d = 0; d < hp->nsp; d++) { if (mark.flag == 1 && hp_sp->marked == 0) { } else { figline.pen_color=hp_sp->color; figline.fill_color=hp_sp->color; xfig_spline (fp, hp_sp->x0 * fzoom, hp_sp->y0 * fzoom, hp_sp->x1 * fzoom, hp_sp->y1 * fzoom, hp_sp->x2 * fzoom, hp_sp->y2 * fzoom, hp_sp->x3 * fzoom, hp_sp->y3 * fzoom, hp_sp->type, latex_flag); } hp_sp = hp_sp->next; } return (rval); } int export_xfig (char *filename) /* initiate exporting of the current molecule in plain XFig format */ { FILE *xfile; int rval; if ((int)strlen (filename)) { xfile = fopen (filename, "w"); if (!xfile) return (1); rval = exfig (xfile, 0); if (fclose (xfile) != 0) { perror ("could not close fig file"); return (1); } return (rval); } return (1); } int export_latex_pic (char *filename, float scale) /* export molecule as a pictex file by writing a temporary XFig file and postprocessing that with fig2dev */ { char com[255]; FILE *xfile; int rval; if (figversion == 0) return (1); /* cannot export without fig2dev */ if ((int)strlen (filename)) { snprintf (com,255, "fig2dev -Lpictex -m %f > %s", scale, filename); xfile = popen (com, "w"); if (!xfile) return (1); rval = exfig (xfile, 1); if (pclose (xfile) != 0) return (1); return (rval); } else return (1); } int export_ps_pic (char *filename, float scale) /* export molecule as a postscript file by writing a temporary XFig file and postprocessing that with fig2dev */ { char com[255]; FILE *xfile; int rval; char *epso[4] = {" ","-A","-T","-C"}; char intl[3]; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if (figversion == 0) return (1); /* cannot export without fig2dev */ if (use_intlchars) strcpy(intl,"-j"); else strcpy(intl,""); if ((int)strlen (filename)) { if (figversion == 1) snprintf (com,255, "fig2dev %s -Lps -m %f > %s", intl, scale, filename); else if (figversion == 2) snprintf (com,255, "fig2dev %s -L eps -m %f > %s", intl, scale, filename); else snprintf (com,255, "fig2dev %s -L eps %s -m %f -g \\%s> %s", intl,epso[epsoption], scale, bghexcolor, filename); xfile = popen (com, "w"); if (!xfile) return (1); rval = exfig (xfile, 0); if (rval != 0) return (rval); rval=pclose(xfile); if (rval != 0) return (1); else return (rval); } else return (1); } int export_png_pic (char *filename, float scale) /* export molecule as a png file by writing a temporary XFig file and postprocessing that with fig2dev */ { char com[255]; FILE *xfile; int rval; char intl[3]; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if (figversion == 0) return (1); /* cannot export without fig2dev */ if (use_intlchars) strcpy(intl,"-j"); else strcpy(intl,""); if ((int)strlen (filename)) { if (figversion == 1) snprintf (com,255, "fig2dev %s -Lpng -m %f > %s", intl, scale, filename); else snprintf (com,255, "fig2dev %s -L png -S 4 -F -m %f > %s", intl, scale, filename); xfile = popen (com, "w"); if (!xfile) return (1); rval = exfig (xfile, 0); if (rval != 0) return (rval); rval=pclose(xfile); if (rval != 0) return (1); else return (rval); } else return (1); } int print_ps_pic (char *filename) /* Print molecule to a postscript printer by creating an XFig datastream and postprocessing that with fig2dev */ { char com[255]; int rval; FILE *xfile; char intl[3]; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif if (figversion == 0) return (1); /* cannot print without fig2dev */ if (use_intlchars) strcpy(intl,"-j"); else strcpy(intl,""); if (figversion == 1) snprintf (com,255, "fig2dev %s -L ps -z %s -P %s -e -m %f | %s%s", intl,paper[papersize], orientation[orient], printscale, printcommand[printcmd], queuename); else snprintf (com,255, "fig2dev %s -L ps -z %s %s -e -m %f | %s%s", intl,paper[papersize], orientation[orient], printscale, printcommand[printcmd], queuename); xfile = popen (com, "w"); if (!xfile) return (1); rval = exfig (xfile, 0); if (rval != 0) return (rval); rval=pclose(xfile); if (rval != 0) return (1); else return (rval); } int export_fw (char *filename) /* save file and postprocess it with cht */ { char com[255]; char xfile[512]; int rval; FILE *chtpipe; FILE *fp; int fd; if ((int)strlen (filename)) { strcpy (xfile, "/tmp/chtXXXXXX"); /*@ignore@ splint does not recognize mkstemp */ fd = mkstemp (xfile); /*@end@*/ if (fd == -1) return 1; snprintf (com,255, "cht %s", xfile); fp = fdopen (fd, "w"); save_mol (fp, mark.flag); fclose (fp); chtpipe = popen (com, "r"); if (!chtpipe) return (1); rval = fscanf (chtpipe, "%20s %20s %20s %64s", formula, weight, eweight, compos); rval = pclose (chtpipe); unlink (xfile); return (rval); } else return (1); } int readrc () { FILE *fp; int i; char key[20], value[100]; char line[80]; gchar *filename; char *epso[4] = { "None","EPSI","TIFFm","TIFFc" }; filename = g_malloc (PATH_MAX + 1); filename = strncat (strncpy (filename, g_get_home_dir (), PATH_MAX), "/.chemtoolrc", PATH_MAX); fp = fopen (filename, "r"); if (!fp) { g_free (filename); return 1; } else { while (!feof (fp)) { if (fgets (line, (int)sizeof (line), fp)) { i = sscanf (line, "%s %s", key, value); if (i < 2) continue; if (!strcmp (key, "orientation")) { if (!strcmp (value, "portrait")) orient = 0; else orient = 1; } if (!strcmp (key, "papersize")) { for (i = 0; i < 11; i++) if (!strcmp (value, paper[i])) papersize = i; } if (!strcmp (key, "printcommand")) { for (i = 0; i < (int)strlen (value); i++) if (value[i] == '\\') value[i] = ' '; for (i = 0; i < 2; i++) if (!strcmp (value, printcommand[i])) printcmd = i; } if (!strcmp (key, "printer")) strcpy (queuename, value); if (!strcmp (key, "printscale")) printscale = atof (value); if (!strcmp (key, "epsoption")) for (i = 0; i < 4; i++) { if (!strcmp (value, epso[i])) epsoption = i; } if (!strcmp (key, "whiteout")) use_whiteout = atoi (value); if (!strcmp (key, "intlchars")) use_intlchars = atoi (value); if (!strcmp (key, "datadir")) strcpy (datadir, value); if (!strcmp (key, "extension")) strcpy (datamask, value); if (!strcmp (key, "bondlength")){ bondlen_mm= atof(value); if (bondlen_mm != 0 && bondlen_mm != 10.668) size_factor*=bondlen_mm/10.668; } if (!strcmp (key, "double_separation")){ db_dist = atoi(value); if (db_dist <= 0 || db_dist >100) db_dist=4; mb_dist = (int) ( ( (float)db_dist )* 2.5 ); } if (!strcmp (key, "background")){ i=sscanf(value,"(%d,%d,%d)",&bgred,&bggreen,&bgblue); if (i<3) bgred=bggreen=bgblue=65535; } } } fclose (fp); g_free (filename); return 0; } } int writerc () { FILE *fp; char *pcomm[3] = { "lpr\\-P", "lp\\-d", "kprinter -d"}; char *ori[2] = { "portrait", "landscape" }; char *epso[4] = { "None","EPSI","TIFFm","TIFFc" }; gchar *filename; filename = g_malloc (PATH_MAX + 1); filename = strncat (strncpy (filename, g_get_home_dir (), PATH_MAX), "/.chemtoolrc", PATH_MAX); fp = fopen (filename, "w"); if (!fp) { g_free (filename); return 1; } else { fprintf (fp, "datadir %s\n", datadir); fprintf (fp, "extension %s\n", datamask); fprintf (fp, "papersize %s\n", paper[papersize]); fprintf (fp, "orientation %s\n", ori[orient]); fprintf (fp, "printscale %f\n", printscale); fprintf (fp, "printcommand %s\n", pcomm[printcmd]); fprintf (fp, "printer %s\n", queuename); fprintf (fp, "bondlength %6.4f\n", bondlen_mm); fprintf (fp, "double_separation %d\n", db_dist); fprintf (fp, "epsoption %s\n", epso[epsoption]); fprintf (fp, "whiteout %d\n", use_whiteout); fprintf (fp, "intlchars %d\n", use_intlchars); fprintf (fp, "background (%d,%d,%d)\n", bgred,bggreen,bgblue); fclose (fp); g_free (filename); return 0; } } void check_fig2dev () { char cmd[20]; FILE *xfile; float version; float ref=3.2; int pl; int rval; #ifdef GTK2 setlocale (LC_NUMERIC,"C"); #endif snprintf (cmd,20, "fig2dev -V"); xfile = popen (cmd, "r"); rval = fscanf (xfile, "%*s %*s %f %*s %d", &version, &pl); rval = pclose (xfile); if (rval != 0) figversion = 0; /* fig2dev not found */ else { if (version < ref || (version == ref && pl < 3)) figversion = 1; /* "old" fig2dev, needs -Lps */ else figversion = 2; /* new fig2dev, knows -L eps */ if (version > ref || (version == ref && pl >3)) figversion = 3; /* 3.2.4 can generate previews in eps file */ } } void check_babel () { char cmd[20]; char data[80]; FILE *xfile; /* float version;*/ int rval; int start=0,stop=0; int obmajor=0,obminor=0,obrel=0; babelin=-1; babelout=-1; memset(data,'\0',80); snprintf (cmd,20, "babel 2>/dev/null"); xfile = popen (cmd, "r"); if (!xfile)return; if (!fgets (data,80,xfile)){ pclose(xfile); return; } if (!strncmp(data,"Open",4)) { /* OpenBabel 1.x */ strcpy(babeloutp,"--"); sscanf(data,"%*s %*s %d.%d.%d",&obmajor,&obminor,&obrel); if (obmajor*10000+obminor*10+obrel >= 11001) { rval=pclose(xfile); snprintf(cmd,20,"babel -H"); xfile = popen (cmd, "r"); } } else if (!strncmp(data,"No output",9)) { /* OpenBabel 2.x */ strcpy(babeloutp,"--"); rval=pclose(xfile); snprintf(cmd,20,"babel -H"); xfile = popen (cmd, "r"); } else /* original babel 1.6 */ strcpy(babeloutp,"CON"); while (!feof(xfile)) { if (fgets (data,80,xfile)) { if (!strncmp(data,"Currently",9)|| !strncmp(data,"The following",13)) { start=1; break; } } } babelin=-1; inmode=NULL; intype=NULL; babelout=-1; outmode=NULL; outtype=NULL; if (start==1){ while (!feof(xfile)){ (void)fgets (data, 80, xfile); if (!strncmp(data,"Currently",9)|| !strncmp(data,"See further",11)) { stop=1; babelin--; babelout--; break; }else if (strstr(data,"Write-only")==NULL) { babelin++; inmode = realloc (inmode, (babelin + 1) * sizeof (char *)); inmode[babelin] = malloc (9 * sizeof (char)); intype = realloc (intype, (babelin + 1) * sizeof (char *)); intype[babelin] = malloc (39 * sizeof (char)); sscanf(data,"%s -- %36[a-zA-Z0-9 -]",inmode[babelin],intype[babelin]); } if (strstr(data,"Read-only")==NULL) { babelout++; outmode = realloc (outmode, (babelout + 1) * sizeof (char *)); outmode[babelout] = malloc (10 * sizeof (char)); outtype = realloc (outtype, (babelout + 1) * sizeof (char *)); outtype[babelout] = malloc (39 * sizeof (char)); sscanf(data,"%s -- %36[a-zA-Z0-9 -]",outmode[babelout],outtype[babelout]); } } } rval = pclose (xfile); if (rval != 0 && babelin <=0 ) fprintf(stderr,"Consider installing Babel/OpenBabel for file format conversions...\n"); #if 0 else { for (start=0;start<=babelin;start++) fprintf(stderr,"BABEL input %s : %s\n",inmode[start],intype[start]); for (start=0;start<=babelout;start++) fprintf(stderr,"BABEL output %s : %s\n",outmode[start],outtype[start]); } #endif } int export_sxd (char *filename) /* export molecule as a pictex file by writing a temporary XFig file and postprocessing that with fig2sxd */ { char com[255]; FILE *xfile; int rval; if (have_fig2sxd == 0) return (1); /* cannot export without fig2sxd */ if ((int)strlen (filename)) { snprintf (com,255, "fig2sxd - %s", filename); xfile = popen (com, "w"); if (!xfile) return (1); rval = exfig (xfile, 1); if (pclose (xfile) < 0) return (1); return (rval); } else return (1); } void check_fig2sxd () { char cmd[20]; FILE *xfile; char myname[10]; have_fig2sxd = 0; snprintf (cmd,20, "fig2sxd 2>&1"); xfile = popen (cmd, "r"); if (!xfile) return; fscanf (xfile, "%s", myname); pclose (xfile); if (!strncmp(myname,"fig2sxd",7)) have_fig2sxd = 1; } int export_babel (char *filename) /* export molecule by writing a temporary molfile and postprocessing that with (open)babel, adding explicit hydrogens if necessary */ { char com[255]; FILE *xfile; int rval; if ((int)strlen (filename)) { snprintf (com,255, "babel -h -imol %s -o%s %s", babeloutp, babel, filename); xfile = popen (com, "w"); if (!xfile) return (1); rval = export_mdl_mol (xfile, 1); if (pclose (xfile) < 0) return (1); return (rval); } else return (1); }