rino 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/ext/extconf.rb +1 -24
- data/ext/libinchi.so +0 -0
- data/ext/src/aux2atom.h +120 -39
- data/ext/src/comdef.h +3 -3
- data/ext/src/dispstru.c +2547 -0
- data/ext/src/dispstru.h +73 -0
- data/ext/src/extr_ct.h +5 -2
- data/ext/src/ichi.h +27 -11
- data/ext/src/ichi_bns.c +1800 -254
- data/ext/src/ichi_bns.h +205 -4
- data/ext/src/ichican2.c +197 -86
- data/ext/src/ichicano.c +8 -13
- data/ext/src/ichicano.h +2 -2
- data/ext/src/ichicans.c +11 -6
- data/ext/src/ichicant.h +2 -2
- data/ext/src/ichicomn.h +2 -2
- data/ext/src/ichicomp.h +19 -4
- data/ext/src/ichidrp.h +9 -5
- data/ext/src/ichierr.h +5 -3
- data/ext/src/ichiisot.c +2 -2
- data/ext/src/ichimain.c +461 -0
- data/ext/src/ichimain.h +23 -15
- data/ext/src/ichimak2.c +6 -6
- data/ext/src/ichimake.c +843 -42
- data/ext/src/ichimake.h +4 -2
- data/ext/src/ichimap1.c +5 -5
- data/ext/src/ichimap2.c +2 -2
- data/ext/src/ichimap4.c +34 -21
- data/ext/src/ichinorm.c +11 -5
- data/ext/src/ichinorm.h +3 -2
- data/ext/src/ichiparm.c +2 -2
- data/ext/src/ichiparm.h +232 -30
- data/ext/src/ichiprt1.c +35 -11
- data/ext/src/ichiprt2.c +78 -7
- data/ext/src/ichiprt3.c +300 -120
- data/ext/src/ichiqueu.c +17 -2
- data/ext/src/ichiread.c +6932 -0
- data/ext/src/ichiring.c +3 -2
- data/ext/src/ichiring.h +2 -2
- data/ext/src/ichirvr1.c +4891 -0
- data/ext/src/ichirvr2.c +6344 -0
- data/ext/src/ichirvr3.c +5499 -0
- data/ext/src/ichirvr4.c +3177 -0
- data/ext/src/ichirvr5.c +1166 -0
- data/ext/src/ichirvr6.c +1287 -0
- data/ext/src/ichirvr7.c +2319 -0
- data/ext/src/ichirvrs.h +882 -0
- data/ext/src/ichisize.h +2 -2
- data/ext/src/ichisort.c +5 -5
- data/ext/src/ichister.c +281 -86
- data/ext/src/ichister.h +9 -3
- data/ext/src/ichitaut.c +208 -9
- data/ext/src/ichitaut.h +13 -11
- data/ext/src/ichitime.h +16 -2
- data/ext/src/inchicmp.h +107 -0
- data/ext/src/inpdef.h +6 -3
- data/ext/src/libinchi_wrap.c +912 -0
- data/ext/src/lreadmol.h +34 -31
- data/ext/src/mode.h +244 -7
- data/ext/src/mol2atom.c +1060 -0
- data/ext/src/mol2atom.h +31 -0
- data/ext/src/readinch.c +239 -0
- data/ext/src/readmol.c +28 -0
- data/ext/src/{e_readmol.h → readmol.h} +7 -9
- data/ext/src/runichi.c +251 -177
- data/ext/src/strutil.c +444 -238
- data/ext/src/strutil.h +150 -11
- data/ext/src/util.c +176 -118
- data/ext/src/util.h +15 -3
- data/lib/rino.rb +71 -3
- data/test/test.rb +33 -4
- metadata +22 -34
- data/ext/ruby_inchi_main.so +0 -0
- data/ext/src/e_0dstereo.c +0 -3014
- data/ext/src/e_0dstereo.h +0 -31
- data/ext/src/e_comdef.h +0 -57
- data/ext/src/e_ctl_data.h +0 -147
- data/ext/src/e_ichi_io.c +0 -498
- data/ext/src/e_ichi_io.h +0 -40
- data/ext/src/e_ichi_parms.c +0 -37
- data/ext/src/e_ichi_parms.h +0 -41
- data/ext/src/e_ichicomp.h +0 -50
- data/ext/src/e_ichierr.h +0 -40
- data/ext/src/e_ichimain.c +0 -593
- data/ext/src/e_ichisize.h +0 -43
- data/ext/src/e_inchi_atom.c +0 -75
- data/ext/src/e_inchi_atom.h +0 -33
- data/ext/src/e_inpdef.h +0 -41
- data/ext/src/e_mode.h +0 -706
- data/ext/src/e_mol2atom.c +0 -649
- data/ext/src/e_readinch.c +0 -58
- data/ext/src/e_readmol.c +0 -54
- data/ext/src/e_readstru.c +0 -251
- data/ext/src/e_readstru.h +0 -33
- data/ext/src/e_util.c +0 -284
- data/ext/src/e_util.h +0 -61
- data/ext/src/ichilnct.c +0 -286
- data/ext/src/inchi_api.h +0 -670
- data/ext/src/inchi_dll.c +0 -1480
- data/ext/src/inchi_dll.h +0 -34
- data/ext/src/inchi_dll_main.c +0 -23
- data/ext/src/inchi_dll_main.h +0 -31
- data/ext/src/ruby_inchi_main.c +0 -558
data/Rakefile
CHANGED
data/ext/extconf.rb
CHANGED
@@ -1,26 +1,3 @@
|
|
1
|
-
# =================================
|
2
|
-
# Rino - The InChI Toolkit for Ruby
|
3
|
-
# =================================
|
4
|
-
#
|
5
|
-
# Project Info: http://rino.rubyforge.org
|
6
|
-
#
|
7
|
-
# Copyright (C) 2006 Richard L. Apodaca
|
8
|
-
#
|
9
|
-
# This library is free software; you can redistribute it and/or
|
10
|
-
# modify it under the terms of the GNU Lesser General Public
|
11
|
-
# License version 2.1 as published by the Free Software
|
12
|
-
# Foundation.
|
13
|
-
#
|
14
|
-
# This library is distributed in the hope that it will be useful,
|
15
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17
|
-
# Lesser General Public License for more details.
|
18
|
-
#
|
19
|
-
# You should have received a copy of the GNU Lesser General Public
|
20
|
-
# License along with this library; if not, write to the Free
|
21
|
-
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
|
22
|
-
# Boston, MA 02111-1301, USA.
|
23
|
-
|
24
1
|
require 'mkmf'
|
25
2
|
|
26
|
-
create_makefile(
|
3
|
+
create_makefile('libinchi', 'src')
|
data/ext/libinchi.so
ADDED
Binary file
|
data/ext/src/aux2atom.h
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
* International Union of Pure and Applied Chemistry (IUPAC)
|
3
3
|
* International Chemical Identifier (InChI)
|
4
4
|
* Version 1
|
5
|
-
* Software version 1.
|
6
|
-
*
|
5
|
+
* Software version 1.01
|
6
|
+
* July 21, 2006
|
7
7
|
* Developed at NIST
|
8
8
|
*/
|
9
9
|
|
@@ -80,8 +80,10 @@ int str_fgetc( INCHI_FILE *f )
|
|
80
80
|
/*******************************************************************/
|
81
81
|
char *str_fgets( char *szLine, int len, INCHI_FILE *f )
|
82
82
|
{
|
83
|
-
int length=0, c;
|
84
|
-
len
|
83
|
+
int length=0, c=0;
|
84
|
+
if ( -- len < 0 ) {
|
85
|
+
return NULL;
|
86
|
+
}
|
85
87
|
while ( length < len && EOF != (c = str_fgetc( f )) ) {
|
86
88
|
szLine[length++] = (char)c;
|
87
89
|
if ( c == '\n' )
|
@@ -150,13 +152,13 @@ S_SHORT *is_in_the_slist( S_SHORT *pathAtom, S_SHORT nNextAtom, int nPathLen )
|
|
150
152
|
/************************************************/
|
151
153
|
int is_element_a_metal( char szEl[] )
|
152
154
|
{
|
153
|
-
static char szMetals[] = "K;V;Y;W;U;"
|
155
|
+
static const char szMetals[] = "K;V;Y;W;U;"
|
154
156
|
"Li;Be;Na;Mg;Al;Ca;Sc;Ti;Cr;Mn;Fe;Co;Ni;Cu;Zn;Ga;Rb;Sr;Zr;"
|
155
157
|
"Nb;Mo;Tc;Ru;Rh;Pd;Ag;Cd;In;Sn;Sb;Cs;Ba;La;Ce;Pr;Nd;Pm;Sm;"
|
156
158
|
"Eu;Gd;Tb;Dy;Ho;Er;Tm;Yb;Lu;Hf;Ta;Re;Os;Ir;Pt;Au;Hg;Tl;Pb;"
|
157
159
|
"Bi;Po;Fr;Ra;Ac;Th;Pa;Np;Pu;Am;Cm;Bk;Cf;Es;Fm;Md;No;Lr;Rf;";
|
158
|
-
int len = strlen(szEl);
|
159
|
-
char *p;
|
160
|
+
const int len = strlen(szEl);
|
161
|
+
const char *p;
|
160
162
|
|
161
163
|
if ( 0 < len && len <= 2 &&
|
162
164
|
isalpha( UCINT szEl[0] ) && isupper( szEl[0] ) &&
|
@@ -172,8 +174,10 @@ int is_element_a_metal( char szEl[] )
|
|
172
174
|
/*******************************************************************/
|
173
175
|
char *str_fgetsTab( char *szLine, int len, INCHI_FILE *f )
|
174
176
|
{
|
175
|
-
int length=0, c;
|
176
|
-
len
|
177
|
+
int length=0, c=0;
|
178
|
+
if ( --len < 0 ) {
|
179
|
+
return NULL;
|
180
|
+
}
|
177
181
|
while ( length < len && EOF != (c = str_fgetc( f )) ) {
|
178
182
|
if ( c == '\t' )
|
179
183
|
c = '\n';
|
@@ -422,16 +426,16 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
422
426
|
inchi_Atom *atom = NULL;
|
423
427
|
MOL_COORD *pszCoord = NULL;
|
424
428
|
INCHI_MODE InpAtomFlags = 0; /* 0 or FLAG_INP_AT_NONCHIRAL or FLAG_INP_AT_CHIRAL */
|
425
|
-
static char szIsoH[] = "hdt";
|
429
|
+
static const char szIsoH[] = "hdt";
|
426
430
|
/* plain tags */
|
427
|
-
static char sStructHdrPln[] = "Structure:";
|
428
|
-
static char sStructHdrPlnNoLblVal[] = " is missing";
|
431
|
+
static const char sStructHdrPln[] = "Structure:";
|
432
|
+
static const char sStructHdrPlnNoLblVal[] = " is missing";
|
429
433
|
static char sStructHdrPlnAuxStart[64] =""; /*"$1.1Beta/";*/
|
430
434
|
static int lenStructHdrPlnAuxStart = 0;
|
431
|
-
static char sStructHdrPlnRevAt[] = "/rA:";
|
432
|
-
static char sStructHdrPlnRevBn[] = "/rB:";
|
433
|
-
static char sStructHdrPlnRevXYZ[] = "/rC:";
|
434
|
-
char *sToken;
|
435
|
+
static const char sStructHdrPlnRevAt[] = "/rA:";
|
436
|
+
static const char sStructHdrPlnRevBn[] = "/rB:";
|
437
|
+
static const char sStructHdrPlnRevXYZ[] = "/rC:";
|
438
|
+
const char *sToken;
|
435
439
|
int lToken;
|
436
440
|
if ( !lenStructHdrPlnAuxStart ) {
|
437
441
|
lenStructHdrPlnAuxStart = sprintf( sStructHdrPlnAuxStart, "AuxInfo=" );
|
@@ -632,7 +636,7 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
632
636
|
#else
|
633
637
|
atom[i].el_number = get_periodic_table_number( atom[i].elname );
|
634
638
|
#endif
|
635
|
-
/* bonds' valence */
|
639
|
+
/* bonds' valence + number of non-isotopic H */
|
636
640
|
if ( isdigit( UCINT *p ) ) {
|
637
641
|
AT_BONDS_VAL(atom,i) = (char)strtol( p, &q, 10 );
|
638
642
|
if ( !AT_BONDS_VAL(atom,i) )
|
@@ -1098,7 +1102,7 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
1098
1102
|
}
|
1099
1103
|
chem_bonds_valence += n2;
|
1100
1104
|
*err |= 32; /* Unrecognized aromatic bond(s) replaced with single */
|
1101
|
-
MOLFILE_ERR_SET (*err, 0, "Atom has more than 3 aromatic bonds");
|
1105
|
+
MOLFILE_ERR_SET (*err, 0, "Atom has 1 or more than 3 aromatic bonds");
|
1102
1106
|
break;
|
1103
1107
|
}
|
1104
1108
|
}
|
@@ -1124,6 +1128,38 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
1124
1128
|
}
|
1125
1129
|
}
|
1126
1130
|
#else
|
1131
|
+
/* added 2006-07-19 to process aromatic bonds same way as from molfile */
|
1132
|
+
if ( n2 && !valence ) {
|
1133
|
+
int num_H = NUMH(atom, a1); /* only isotopic */
|
1134
|
+
int chem_valence = chem_bonds_valence;
|
1135
|
+
int bUnusualValenceArom =
|
1136
|
+
detect_unusual_el_valence( (int)atom[a1].el_number, atom[a1].charge,
|
1137
|
+
atom[a1].radical, chem_valence,
|
1138
|
+
num_H, atom[a1].valence );
|
1139
|
+
int bUnusualValenceNoArom =
|
1140
|
+
detect_unusual_el_valence( (int)atom[a1].el_number, atom[a1].charge,
|
1141
|
+
atom[a1].radical, chem_valence-1,
|
1142
|
+
num_H, atom[a1].valence );
|
1143
|
+
#if ( CHECK_AROMBOND2ALT == 1 )
|
1144
|
+
if ( bUnusualValenceArom && !bUnusualValenceNoArom && 0 == nBondsValToMetal( atom, a1) )
|
1145
|
+
#else
|
1146
|
+
if ( bUnusualValenceArom && !bUnusualValenceNoArom )
|
1147
|
+
#endif
|
1148
|
+
{
|
1149
|
+
/* typically NH in 5-member aromatic ring */
|
1150
|
+
chem_bonds_valence --;
|
1151
|
+
}
|
1152
|
+
} else
|
1153
|
+
if ( n2 && valence ) {
|
1154
|
+
/* atom has aromatic bonds AND the chemical valence is known */
|
1155
|
+
int num_H = NUMH(atom, a1);
|
1156
|
+
int chem_valence = chem_bonds_valence + num_H;
|
1157
|
+
if ( valence == chem_valence-1 ) {
|
1158
|
+
/* typically NH in 5-member aromatic ring */
|
1159
|
+
chem_bonds_valence --;
|
1160
|
+
}
|
1161
|
+
}
|
1162
|
+
|
1127
1163
|
atom[a1].chem_bonds_valence = chem_bonds_valence;
|
1128
1164
|
atom[a1].num_H = get_num_H( atom[a1].elname, atom[a1].num_H, atom[a1].num_iso_H, atom[a1].charge, atom[a1].radical,
|
1129
1165
|
atom[a1].chem_bonds_valence,
|
@@ -1179,7 +1215,7 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
1179
1215
|
atom_stereo0D[i].type = INCHI_StereoType_None;
|
1180
1216
|
atom_stereo0D[i].central_atom = NO_ATOM;
|
1181
1217
|
atom_stereo0D[i].neighbor[0] =
|
1182
|
-
atom_stereo0D[i].neighbor[
|
1218
|
+
atom_stereo0D[i].neighbor[3] = -1;
|
1183
1219
|
*err |= 64; /* Error in cumulene stereo */
|
1184
1220
|
MOLFILE_ERR_SET (*err, 0, "0D stereobond not recognized");
|
1185
1221
|
break;
|
@@ -1252,7 +1288,7 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
1252
1288
|
atom_stereo0D[i].type = INCHI_StereoType_None;
|
1253
1289
|
atom_stereo0D[i].central_atom = NO_ATOM;
|
1254
1290
|
atom_stereo0D[i].neighbor[0] =
|
1255
|
-
atom_stereo0D[i].neighbor[
|
1291
|
+
atom_stereo0D[i].neighbor[3] = -1;
|
1256
1292
|
*err |= 64; /* Error in cumulene stereo */
|
1257
1293
|
MOLFILE_ERR_SET (*err, 0, "Cumulene stereo not recognized (0D)");
|
1258
1294
|
|
@@ -1315,6 +1351,12 @@ int INChITo_Atom(INPUT_FILE *inp_molfile, MOL_COORD **szCoord,
|
|
1315
1351
|
}
|
1316
1352
|
#if( defined(INCHI_LIBRARY) || defined(INCHI_MAIN) )
|
1317
1353
|
#else
|
1354
|
+
#if( FIX_READ_AUX_MEM_LEAK == 1 )
|
1355
|
+
/* 2005-08-04 avoid memory leak */
|
1356
|
+
if ( atom_stereo0D && !(stereo0D && *stereo0D == atom_stereo0D) ) {
|
1357
|
+
FreeInchi_Stereo0D( &atom_stereo0D );
|
1358
|
+
}
|
1359
|
+
#endif
|
1318
1360
|
if ( szCoord ) {
|
1319
1361
|
*szCoord = pszCoord;
|
1320
1362
|
pszCoord = NULL;
|
@@ -1378,22 +1420,26 @@ bypass_end_of_INChI_plain:
|
|
1378
1420
|
/***********************************************************/
|
1379
1421
|
if ( nInputType == INPUT_INCHI_XML ) {
|
1380
1422
|
/* xml tags */
|
1381
|
-
static char sStructHdrXml[] = "<structure";
|
1382
|
-
static char sStructHdrXmlEnd[] = "</structure";
|
1383
|
-
static char sStructHdrXmlNumber[] = "number=\"";
|
1384
|
-
static char sStructHdrXmlIdName[] = "id.name=\"";
|
1385
|
-
static char sStructHdrXmlIdValue[] = "id.value=\"";
|
1386
|
-
|
1387
|
-
static char
|
1388
|
-
|
1389
|
-
static char
|
1390
|
-
|
1391
|
-
static char
|
1392
|
-
static char
|
1393
|
-
static char
|
1394
|
-
static char
|
1395
|
-
static char
|
1396
|
-
static char
|
1423
|
+
static const char sStructHdrXml[] = "<structure";
|
1424
|
+
static const char sStructHdrXmlEnd[] = "</structure";
|
1425
|
+
static const char sStructHdrXmlNumber[] = "number=\"";
|
1426
|
+
static const char sStructHdrXmlIdName[] = "id.name=\"";
|
1427
|
+
static const char sStructHdrXmlIdValue[] = "id.value=\"";
|
1428
|
+
#if( SPECIAL_BUILD == 1 )
|
1429
|
+
static const char sStructMsgXmlErr[] = "<message type=\"error (no MoChI)\" value=\"";
|
1430
|
+
#else
|
1431
|
+
static const char sStructMsgXmlErr[] = "<message type=\"error (no InChI)\" value=\"";
|
1432
|
+
#endif
|
1433
|
+
static const char sStructMsgXmlErrFatal[] = "<message type=\"fatal (aborted)\" value=\"";
|
1434
|
+
static const char sStructRevXmlRevHdr[] = "<reversibility>";
|
1435
|
+
static const char sStructRevXmlRevAt[] = "<atoms>";
|
1436
|
+
static const char sStructRevXmlRevAtEnd[] = "</atoms>";
|
1437
|
+
static const char sStructRevXmlRevBn[] = "<bonds>";
|
1438
|
+
static const char sStructRevXmlRevBnEnd[] = "</bonds>";
|
1439
|
+
static const char sStructRevXmlRevXYZ[] = "<xyz>";
|
1440
|
+
static const char sStructRevXmlRevXYZEnd[]= "</xyz>";
|
1441
|
+
static const char sStructAuxXml[] = "<identifier.auxiliary-info";
|
1442
|
+
static const char sStructAuxXmlEnd[] = "</identifier.auxiliary-info";
|
1397
1443
|
int bInTheAuxInfo = 0;
|
1398
1444
|
|
1399
1445
|
while ( 0 < (res = my_fgets( szLine, sizeof(szLine)-1, inp_molfile, &bTooLongLine ) ) ) {
|
@@ -2090,7 +2136,7 @@ bypass_end_of_INChI_plain:
|
|
2090
2136
|
}
|
2091
2137
|
chem_bonds_valence += n2;
|
2092
2138
|
*err |= 32; /* Unrecognized aromatic bond(s) replaced with single */
|
2093
|
-
MOLFILE_ERR_SET (*err, 0, "Atom has more than 3 aromatic bonds");
|
2139
|
+
MOLFILE_ERR_SET (*err, 0, "Atom has 1 or more than 3 aromatic bonds");
|
2094
2140
|
break;
|
2095
2141
|
}
|
2096
2142
|
}
|
@@ -2117,6 +2163,38 @@ bypass_end_of_INChI_plain:
|
|
2117
2163
|
}
|
2118
2164
|
}
|
2119
2165
|
#else
|
2166
|
+
/* added 2006-07-19 to process aromatic bonds same way as from molfile */
|
2167
|
+
if ( n2 && !valence ) {
|
2168
|
+
int num_H = NUMH(atom, a1); /* only isotopic */
|
2169
|
+
int chem_valence = chem_bonds_valence;
|
2170
|
+
int bUnusualValenceArom =
|
2171
|
+
detect_unusual_el_valence( (int)atom[a1].el_number, atom[a1].charge,
|
2172
|
+
atom[a1].radical, chem_valence,
|
2173
|
+
num_H, atom[a1].valence );
|
2174
|
+
int bUnusualValenceNoArom =
|
2175
|
+
detect_unusual_el_valence( (int)atom[a1].el_number, atom[a1].charge,
|
2176
|
+
atom[a1].radical, chem_valence-1,
|
2177
|
+
num_H, atom[a1].valence );
|
2178
|
+
#if ( CHECK_AROMBOND2ALT == 1 )
|
2179
|
+
if ( bUnusualValenceArom && !bUnusualValenceNoArom && 0 == nBondsValToMetal( atom, a1) )
|
2180
|
+
#else
|
2181
|
+
if ( bUnusualValenceArom && !bUnusualValenceNoArom )
|
2182
|
+
#endif
|
2183
|
+
{
|
2184
|
+
/* typically NH in 5-member aromatic ring */
|
2185
|
+
chem_bonds_valence --;
|
2186
|
+
}
|
2187
|
+
} else
|
2188
|
+
if ( n2 && valence ) {
|
2189
|
+
/* atom has aromatic bonds AND the chemical valence is known */
|
2190
|
+
int num_H = NUMH(atom, a1);
|
2191
|
+
int chem_valence = chem_bonds_valence + num_H;
|
2192
|
+
if ( valence == chem_valence-1 ) {
|
2193
|
+
/* typically NH in 5-member aromatic ring */
|
2194
|
+
chem_bonds_valence --;
|
2195
|
+
}
|
2196
|
+
}
|
2197
|
+
|
2120
2198
|
atom[a1].chem_bonds_valence = chem_bonds_valence;
|
2121
2199
|
atom[a1].num_H = get_num_H( atom[a1].elname, atom[a1].num_H, atom[a1].num_iso_H, atom[a1].charge, atom[a1].radical,
|
2122
2200
|
atom[a1].chem_bonds_valence,
|
@@ -2172,7 +2250,7 @@ bypass_end_of_INChI_plain:
|
|
2172
2250
|
atom_stereo0D[i].type = INCHI_StereoType_None;
|
2173
2251
|
atom_stereo0D[i].central_atom = NO_ATOM;
|
2174
2252
|
atom_stereo0D[i].neighbor[0] =
|
2175
|
-
atom_stereo0D[i].neighbor[
|
2253
|
+
atom_stereo0D[i].neighbor[3] = -1;
|
2176
2254
|
*err |= 64; /* Error in cumulene stereo */
|
2177
2255
|
MOLFILE_ERR_SET (*err, 0, "0D stereobond not recognized");
|
2178
2256
|
break;
|
@@ -2245,7 +2323,7 @@ bypass_end_of_INChI_plain:
|
|
2245
2323
|
atom_stereo0D[i].type = INCHI_StereoType_None;
|
2246
2324
|
atom_stereo0D[i].central_atom = NO_ATOM;
|
2247
2325
|
atom_stereo0D[i].neighbor[0] =
|
2248
|
-
atom_stereo0D[i].neighbor[
|
2326
|
+
atom_stereo0D[i].neighbor[3] = -1;
|
2249
2327
|
*err |= 64; /* Error in cumulene stereo */
|
2250
2328
|
MOLFILE_ERR_SET (*err, 0, "Cumulene stereo not recognized (0D)");
|
2251
2329
|
|
@@ -2766,6 +2844,9 @@ int Extract0DParities( inp_ATOM *at, int nNumAtoms, inchi_Stereo0D *stereo0D,
|
|
2766
2844
|
break;
|
2767
2845
|
}
|
2768
2846
|
}
|
2847
|
+
/* take care of Unknown stereobonds: */
|
2848
|
+
/* copy their Unknown stereo descriptors to at->bond_stereo (2005-03-01) */
|
2849
|
+
FixUnkn0DStereoBonds(at, nNumAtoms);
|
2769
2850
|
|
2770
2851
|
#ifdef INCHI_LIBRARY
|
2771
2852
|
|
data/ext/src/comdef.h
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
* International Union of Pure and Applied Chemistry (IUPAC)
|
3
3
|
* International Chemical Identifier (InChI)
|
4
4
|
* Version 1
|
5
|
-
* Software version 1.
|
6
|
-
*
|
5
|
+
* Software version 1.01
|
6
|
+
* July 21, 2006
|
7
7
|
* Developed at NIST
|
8
8
|
*/
|
9
9
|
|
@@ -23,7 +23,7 @@
|
|
23
23
|
#define ATOM_INFO_LEN 36 /* inf_ATOM output string ^123Al^+2H12..(+)/999/999/999/999: 32 chars */
|
24
24
|
#define MAXVAL 20 /* max number of bonds per atom */
|
25
25
|
#define MAX_STEREO_BONDS 3 /* max number of stereogenic bonds per atom */
|
26
|
-
#define NUM_H_ISOTOPES 3 /* number of hydrogen isotopes */
|
26
|
+
#define NUM_H_ISOTOPES 3 /* number of hydrogen isotopes: protium, deuterium, tritium */
|
27
27
|
#define ATW_H 1 /* hydrogen atomic weight */
|
28
28
|
|
29
29
|
/* input bond type definition */
|
data/ext/src/dispstru.c
ADDED
@@ -0,0 +1,2547 @@
|
|
1
|
+
/*
|
2
|
+
* International Union of Pure and Applied Chemistry (IUPAC)
|
3
|
+
* International Chemical Identifier (InChI)
|
4
|
+
* Version 1
|
5
|
+
* Software version 1.01
|
6
|
+
* July 21, 2006
|
7
|
+
* Developed at NIST
|
8
|
+
*/
|
9
|
+
|
10
|
+
/* Draw input atom -- Win32 specific */
|
11
|
+
|
12
|
+
#include "mode.h"
|
13
|
+
|
14
|
+
#ifndef INCHI_ANSI_ONLY /* { */
|
15
|
+
|
16
|
+
#ifdef WIN32 /* { */
|
17
|
+
#include <windows.h>
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <math.h>
|
20
|
+
|
21
|
+
#include "inpdef.h"
|
22
|
+
#include "util.h"
|
23
|
+
#include "dispstru.h"
|
24
|
+
#include "extr_ct.h"
|
25
|
+
#include "ichicomp.h"
|
26
|
+
|
27
|
+
/* Font size */
|
28
|
+
#define FONT_NAME "Arial" /* "MS Sans Serif"; */
|
29
|
+
/* rgb colors */
|
30
|
+
#define CLR_BLUE RGB( 0, 0, 255)
|
31
|
+
#define CLR_GREEN RGB( 0, 128, 0)
|
32
|
+
#define CLR_RED RGB(255, 0, 0)
|
33
|
+
#define CLR_PINK RGB(255, 128, 128)
|
34
|
+
#define CLR_CYAN RGB( 0, 255, 255)
|
35
|
+
#define CLR_LTGREEN RGB(128 ,255, 128)
|
36
|
+
#define CLR_LTPURPLE RGB(255 ,0xCC, 255)
|
37
|
+
#define CLR_YELLOW RGB(255, 255, 0)
|
38
|
+
#define CLR_BLACK RGB( 0, 0, 0)
|
39
|
+
#define CLR_LTGRAY RGB(0xCC, 0xCC, 0xCC)
|
40
|
+
#define CLR_MAGENTA RGB(255,0,255)
|
41
|
+
#define CLR_WHITE RGB(255, 255, 255)
|
42
|
+
|
43
|
+
/* local prototypes */
|
44
|
+
HWND GetConsoleHwnd(void);
|
45
|
+
|
46
|
+
#define MY_TIMER_ID 1
|
47
|
+
|
48
|
+
typedef struct Box {
|
49
|
+
int xhigh, xlow;
|
50
|
+
int yhigh, ylow;
|
51
|
+
} BOX;
|
52
|
+
|
53
|
+
|
54
|
+
/* local prototypes */
|
55
|
+
int DrawBond( HDC pDC, int x1, int y1, int x2, int y2, int b_type, int b_stereo, int b_parity, int bInvertBonds, COLORREF clrPen, int nPenWidth );
|
56
|
+
int DrawBondStereo( HDC pDC, int x1, int y1, int x2, int y2, int b_stereo, int b_highlight, int bInvertBonds, COLORREF clrPen, int nPenWidth );
|
57
|
+
int DrawBondNoStereo( HDC pDC, int x1, int y1, int x2, int y2, int b_type, int b_highlight, COLORREF clrPen, int nPenWidth );
|
58
|
+
int DrawBondParity( HDC pDC, int x1, int y1, int x2, int y2, int parity_mark );
|
59
|
+
void DrawLine( HDC, int, int, int, int );
|
60
|
+
void DrawPenColorFilledPolygon( HDC pDC, const POINT* pnt, int num );
|
61
|
+
int DrawTextColorDot( HDC pDC );
|
62
|
+
int DrawString( HDC pDC, char *st1, int shift, int x, int y );
|
63
|
+
int DrawPreparedString( HDC pDC, char *st1, int shift, int x, int y, int bHighlightTheAtom );
|
64
|
+
int DrawColorString( HDC pDC, const char *st, int xs, int ys, int bHighlightTheAtom );
|
65
|
+
/* structure drawing */
|
66
|
+
int DrawStructure( HDC pDC, inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at, int xoff, int yoff, COLORREF clrPen, int nPenWidth );
|
67
|
+
/* all drawing, including text strings and table */
|
68
|
+
int DrawTheInputStructure( inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at,
|
69
|
+
HDC pDC, int tx_off, int ty_off, int xoff, int yoff,
|
70
|
+
int width_pix, int height_pix, int bDraw, int bOrigAtom, COLORREF clrPen, int nPenWidth );
|
71
|
+
/* calculate sizes, run drawing */
|
72
|
+
int CreateInputStructPicture( HDC hDC, MY_WINDOW_DATA *pWinData, RECT *rc, int bPrint, AT_NUMB nNewEquLabel );
|
73
|
+
|
74
|
+
void FreeWinData( MY_WINDOW_DATA* pWinData );
|
75
|
+
void InpStructureMarkEquComponents( MY_WINDOW_DATA *pWinData, AT_NUMB nNewEquLabel,
|
76
|
+
inp_ATOM *at0, inp_ATOM *at1, inf_ATOM *inf_at, int num_at );
|
77
|
+
int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC );
|
78
|
+
|
79
|
+
/* window procedure */
|
80
|
+
LRESULT CALLBACK WndProcDisplayInputStructure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
81
|
+
|
82
|
+
/* main drawing function: create window, save drawing parameters in the window */
|
83
|
+
int DisplayInputStructure( char *szOutputString, inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at, DRAW_PARMS *dp /*, int bTaut, unsigned long ulDisplTime, long *rcPict, int nFontSize*/ );
|
84
|
+
|
85
|
+
|
86
|
+
int GetFontHeight( HDC );
|
87
|
+
int GetFontAscent( HDC );
|
88
|
+
int GetFontDescent( HDC pDC );
|
89
|
+
int GetFontAveWidth( HDC );
|
90
|
+
int GetStringWidth( HDC pDC, char *pString );
|
91
|
+
int GetOneCharInStringWidth( HDC pDC, const char *pString );
|
92
|
+
int MoveHydrogenAtomToTheLeft( char *s, int start, int H );
|
93
|
+
|
94
|
+
int nRound( double X );
|
95
|
+
double RoundDouble(double X);
|
96
|
+
void roundoff_coord( double dx1, double dx2, int *new_ix1, int *new_ix2 );
|
97
|
+
BOOL ReallySetForegroundWindow(HWND hWnd);
|
98
|
+
HWND GetConsoleHwnd(void);
|
99
|
+
|
100
|
+
|
101
|
+
/*********************************************************************/
|
102
|
+
char szWindowClassName[] = "INChI_DrawStructWnd";
|
103
|
+
|
104
|
+
/*********************************************************************/
|
105
|
+
|
106
|
+
void PrintFileName( const char *fmt, FILE *output_file, const char *szFname )
|
107
|
+
{
|
108
|
+
char szBuf[_MAX_PATH];
|
109
|
+
long lBufLen = sizeof(szBuf);
|
110
|
+
long lReqBufLen;
|
111
|
+
char *pName;
|
112
|
+
const char *p;
|
113
|
+
|
114
|
+
lReqBufLen = GetFullPathName( szFname, lBufLen, szBuf, &pName );
|
115
|
+
|
116
|
+
if ( lReqBufLen && lReqBufLen < lBufLen ) {
|
117
|
+
p = szBuf;
|
118
|
+
} else {
|
119
|
+
p = szFname;
|
120
|
+
}
|
121
|
+
fprintf( output_file, fmt, p );
|
122
|
+
}
|
123
|
+
|
124
|
+
/*********************************************************************/
|
125
|
+
BOOL ReallySetForegroundWindow(HWND hWnd)
|
126
|
+
{
|
127
|
+
BOOL retVal = FALSE;
|
128
|
+
HWND hForegroundWnd;
|
129
|
+
if ( hWnd && IsWindow(hWnd) && (hForegroundWnd = GetForegroundWindow()) ) {
|
130
|
+
DWORD dwWindowThreadProcessId = GetWindowThreadProcessId(hForegroundWnd, NULL);
|
131
|
+
DWORD dwCurrentThreadId = GetCurrentThreadId();
|
132
|
+
AttachThreadInput(dwWindowThreadProcessId, dwCurrentThreadId, TRUE);
|
133
|
+
retVal = SetForegroundWindow(hWnd);
|
134
|
+
AttachThreadInput(dwWindowThreadProcessId, dwCurrentThreadId, FALSE);
|
135
|
+
}
|
136
|
+
return retVal;
|
137
|
+
}
|
138
|
+
/*********************************************************************/
|
139
|
+
HWND GetConsoleHwnd(void)
|
140
|
+
{
|
141
|
+
#define MY_BUFSIZE 1024 /* Buffer size for console window titles. */
|
142
|
+
HWND hwndFound; /* This is what is returned to the caller. */
|
143
|
+
char pszNewWindowTitle[MY_BUFSIZE]; /* Contains fabricated */
|
144
|
+
/* WindowTitle. */
|
145
|
+
char pszOldWindowTitle[MY_BUFSIZE]; /* Contains original */
|
146
|
+
/* WindowTitle. */
|
147
|
+
|
148
|
+
/* Fetch current window title. */
|
149
|
+
|
150
|
+
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
|
151
|
+
|
152
|
+
/* Format a "unique" NewWindowTitle. */
|
153
|
+
|
154
|
+
wsprintf(pszNewWindowTitle,"InChITmpWnd%ul/%ul",
|
155
|
+
(unsigned long)GetTickCount(),
|
156
|
+
(unsigned long)GetCurrentProcessId());
|
157
|
+
|
158
|
+
/* Change current window title. */
|
159
|
+
SetConsoleTitle(pszNewWindowTitle);
|
160
|
+
|
161
|
+
/* Ensure window title has been updated. */
|
162
|
+
|
163
|
+
Sleep(40);
|
164
|
+
|
165
|
+
/* Look for NewWindowTitle. */
|
166
|
+
|
167
|
+
hwndFound=FindWindow(NULL, pszNewWindowTitle);
|
168
|
+
|
169
|
+
/* download INChI packages
|
170
|
+
ShellExecute(hwndFound, "open", "http://www.iupac.org/inchi", "", "C:\\", SW_SHOWNORMAL);
|
171
|
+
*/
|
172
|
+
|
173
|
+
/* Restore original window title. */
|
174
|
+
|
175
|
+
SetConsoleTitle(pszOldWindowTitle);
|
176
|
+
|
177
|
+
return(hwndFound);
|
178
|
+
}
|
179
|
+
/****************************************************************************/
|
180
|
+
int GetFontHeight( HDC pDC )
|
181
|
+
{
|
182
|
+
TEXTMETRIC TextMetric;
|
183
|
+
|
184
|
+
GetTextMetrics( pDC, &TextMetric );
|
185
|
+
|
186
|
+
return TextMetric.tmHeight;
|
187
|
+
}
|
188
|
+
/****************************************************************************/
|
189
|
+
int GetFontAscent( HDC pDC )
|
190
|
+
{
|
191
|
+
TEXTMETRIC TextMetric;
|
192
|
+
|
193
|
+
GetTextMetrics( pDC, &TextMetric );
|
194
|
+
|
195
|
+
return TextMetric.tmAscent;
|
196
|
+
}
|
197
|
+
/****************************************************************************/
|
198
|
+
int GetFontDescent( HDC pDC )
|
199
|
+
{
|
200
|
+
TEXTMETRIC TextMetric;
|
201
|
+
|
202
|
+
GetTextMetrics( pDC, &TextMetric );
|
203
|
+
|
204
|
+
return TextMetric.tmDescent;
|
205
|
+
}
|
206
|
+
|
207
|
+
/****************************************************************************/
|
208
|
+
int GetFontAveWidth( HDC pDC)
|
209
|
+
{
|
210
|
+
TEXTMETRIC TextMetric;
|
211
|
+
|
212
|
+
GetTextMetrics( pDC, &TextMetric );
|
213
|
+
|
214
|
+
return TextMetric.tmAveCharWidth;
|
215
|
+
}
|
216
|
+
/****************************************************************************/
|
217
|
+
int GetSubstringWidth( HDC pDC, int len, char *pString)
|
218
|
+
{
|
219
|
+
SIZE Size;
|
220
|
+
int widthABC, i;
|
221
|
+
ABC abc;
|
222
|
+
GetTextExtentPoint32( pDC, pString, len, &Size );
|
223
|
+
for ( i = widthABC = 0; i < len; i ++ ) {
|
224
|
+
if ( GetCharABCWidths( pDC, /* handle to DC */
|
225
|
+
(int)pString[i], /* first character in range */
|
226
|
+
(int)pString[i], /* last character in range */
|
227
|
+
&abc ) /* array of character widths */
|
228
|
+
) {
|
229
|
+
widthABC += (int)abc.abcB + abs(abc.abcA) + abs(abc.abcC);
|
230
|
+
} else {
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
if ( widthABC > Size.cx ) {
|
235
|
+
return (widthABC + 2*Size.cx)/3; /* hunch */
|
236
|
+
}
|
237
|
+
return Size.cx;
|
238
|
+
}
|
239
|
+
/****************************************************************************/
|
240
|
+
void GetTextSize( HDC pDC, int len, char *pString, int *width, int *height )
|
241
|
+
{
|
242
|
+
SIZE Size;
|
243
|
+
|
244
|
+
GetTextExtentPoint32( pDC, pString, len, &Size );
|
245
|
+
*width = Size.cx;
|
246
|
+
*height = Size.cy;
|
247
|
+
}
|
248
|
+
/****************************************************************************/
|
249
|
+
void GetVertTextSize( HDC pDC, int len, char *pString, int *width, int *height )
|
250
|
+
{
|
251
|
+
SIZE Size;
|
252
|
+
TEXTMETRIC TextMetric;
|
253
|
+
int i;
|
254
|
+
GetTextMetrics( pDC, &TextMetric );
|
255
|
+
*height = len * TextMetric.tmHeight;
|
256
|
+
*width = 0;
|
257
|
+
for ( i = 0; i < len; i ++ ) {
|
258
|
+
GetTextExtentPoint32( pDC, &pString[i], 1, &Size );
|
259
|
+
*width = inchi_max( *width, (int)Size.cx );
|
260
|
+
}
|
261
|
+
}
|
262
|
+
/****************************************************************************/
|
263
|
+
BOOL TextOutVert(
|
264
|
+
HDC pDC, /* handle to DC */
|
265
|
+
int nXStart, /* x-coordinate of starting position */
|
266
|
+
int nYStart, /* y-coordinate of starting position */
|
267
|
+
LPCTSTR lpString, /* character string */
|
268
|
+
int cbString, /* number of characters */
|
269
|
+
int cell_width /* width for center alignment */
|
270
|
+
) {
|
271
|
+
TEXTMETRIC TextMetric;
|
272
|
+
int i, dy, ret, char_width;
|
273
|
+
GetTextMetrics( pDC, &TextMetric );
|
274
|
+
dy = TextMetric.tmHeight;
|
275
|
+
for ( i = 0, ret = 1; ret && i < cbString; nYStart += dy, i ++ ) {
|
276
|
+
char_width = GetOneCharInStringWidth( pDC, lpString+i );
|
277
|
+
ret = TextOut( pDC, nXStart+(cell_width-char_width)/2, nYStart, lpString+i, 1 );
|
278
|
+
}
|
279
|
+
return ret;
|
280
|
+
}
|
281
|
+
/****************************************************************************/
|
282
|
+
BOOL TextOutHoriz(
|
283
|
+
HDC pDC, /* handle to DC */
|
284
|
+
int nXStart, /* x-coordinate of starting position */
|
285
|
+
int nYStart, /* y-coordinate of starting position */
|
286
|
+
LPCTSTR lpString, /* character string */
|
287
|
+
int cbString, /* number of characters */
|
288
|
+
int cell_width
|
289
|
+
) {
|
290
|
+
int dX = (cell_width && cbString == 1)? (cell_width - GetOneCharInStringWidth( pDC, lpString ))/2:0;
|
291
|
+
return TextOut( pDC, nXStart+dX, nYStart, lpString, cbString );
|
292
|
+
}
|
293
|
+
/****************************************************************************/
|
294
|
+
int GetStringWidth( HDC pDC, char *pString)
|
295
|
+
{
|
296
|
+
SIZE Size;
|
297
|
+
|
298
|
+
GetTextExtentPoint32( pDC, pString, strlen( pString ), &Size );
|
299
|
+
return Size.cx;
|
300
|
+
}
|
301
|
+
|
302
|
+
/****************************************************************************/
|
303
|
+
int GetOneCharInStringWidth( HDC pDC, const char *pString)
|
304
|
+
{
|
305
|
+
SIZE Size;
|
306
|
+
GetTextExtentPoint32( pDC, pString, 1, &Size );
|
307
|
+
|
308
|
+
return Size.cx;
|
309
|
+
}
|
310
|
+
|
311
|
+
|
312
|
+
/****************************************************************************/
|
313
|
+
int DrawStructure( HDC pDC, inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at, int xoff, int yoff, COLORREF clrPen, int nPenWidth )
|
314
|
+
{
|
315
|
+
int i, next, k;
|
316
|
+
int j, r, shift, b_parity=0, bDraw;
|
317
|
+
char str[64], *atname; /*str[sizeof(st->str[0])+1]; */
|
318
|
+
inf_ATOM *inf_at = inf_at_data? inf_at_data->at : NULL;
|
319
|
+
int bUseInvFlags = (!inf_at_data)? 0 : inf_at_data->pStereoFlags? 1 : 2;
|
320
|
+
int bInvertBonds = 0;
|
321
|
+
/*
|
322
|
+
int bInvertBonds = inf_at_data && (inf_at_data->StereoFlags & INF_STEREO_INV);
|
323
|
+
*/
|
324
|
+
/* draw all straight lines (bonds) */
|
325
|
+
|
326
|
+
for ( i = 0; i < num_at; i ++ ) {
|
327
|
+
/* draw atom #i. */
|
328
|
+
for ( j = 0; j < at[i].valence; j++ ) {
|
329
|
+
next = at[i].neighbor[j];
|
330
|
+
bDraw = 1;
|
331
|
+
/* normally draw bonds if next > i; exception: disconnected terminal hydrogen atoms */
|
332
|
+
if ( next < i ) {
|
333
|
+
/* check if it is a disconnected terminal atom. Disconnected atoms */
|
334
|
+
/* have bonds to the rest of the structure; the bond from the rest */
|
335
|
+
/* of the structure to the removed terminal atom has been removed. */
|
336
|
+
for ( r = 0; r < at[next].valence; r ++ ) {
|
337
|
+
if ( at[next].neighbor[r] == i ) {
|
338
|
+
bDraw = 0;
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
}
|
342
|
+
}
|
343
|
+
if ( bDraw ) {
|
344
|
+
/* at[i].bond_stereo[j] is negative if the pointing wedge */
|
345
|
+
/* of a stereo bond is at the at[next] atom */
|
346
|
+
if ( inf_at ) {
|
347
|
+
for ( k =0, b_parity = 0; k < MAX_STEREO_BONDS && inf_at[i].cStereoBondParity[k]; k ++ ) {
|
348
|
+
if ( inf_at[i].cStereoBondNumber[k] == j ) {
|
349
|
+
b_parity = inf_at[i].cStereoBondParity[k];
|
350
|
+
if ( inf_at[i].cStereoBondWarning[k] ) {
|
351
|
+
b_parity = -b_parity;
|
352
|
+
}
|
353
|
+
break;
|
354
|
+
}
|
355
|
+
}
|
356
|
+
}
|
357
|
+
switch( bUseInvFlags ) {
|
358
|
+
case 1:
|
359
|
+
if ( at[i].component <= inf_at_data->num_components ) {
|
360
|
+
bInvertBonds = (0 != (inf_at_data->pStereoFlags[at[i].component] & INF_STEREO_INV));
|
361
|
+
} else {
|
362
|
+
bInvertBonds = 0;
|
363
|
+
}
|
364
|
+
break;
|
365
|
+
case 2:
|
366
|
+
bInvertBonds = 0 != (inf_at_data->StereoFlags & INF_STEREO_INV);
|
367
|
+
break;
|
368
|
+
}
|
369
|
+
DrawBond( pDC, nRound(at[i].x+xoff), nRound(at[i].y+yoff),
|
370
|
+
nRound(at[next].x+xoff), nRound(at[next].y+yoff),
|
371
|
+
at[i].bond_type[j], at[i].bond_stereo[j], b_parity, bInvertBonds, clrPen, nPenWidth);
|
372
|
+
}
|
373
|
+
}
|
374
|
+
}
|
375
|
+
/* write all strings (heteroatoms + H) */
|
376
|
+
if ( inf_at ) {
|
377
|
+
for ( i = 0; i < num_at; i++ ) {
|
378
|
+
strcpy( str, inf_at[i].at_string );
|
379
|
+
DrawPreparedString( pDC, str, -inf_at[i].DrawingLabelLeftShift, nRound(at[i].x+xoff), nRound(at[i].y+yoff), inf_at[i].cHighlightTheAtom );
|
380
|
+
}
|
381
|
+
} else {
|
382
|
+
/* version which does not use inf_at */
|
383
|
+
for ( i = 0; i < num_at; i++ ) {
|
384
|
+
|
385
|
+
/* the direction of the shift: */
|
386
|
+
shift = at[i].bDrawingLabelLeftShift;
|
387
|
+
/* input structure before normalizing: */
|
388
|
+
/* terminal H atoms have not been disconnected; */
|
389
|
+
/* isotopic H atoms numbers have not been added to num_H */
|
390
|
+
atname = at[i].elname;
|
391
|
+
j = 0;
|
392
|
+
k = 0;
|
393
|
+
if ( at[i].iso_atw_diff && (!atname[0] || isupper(UCINT atname[0])) ) {
|
394
|
+
int atw = get_atw_from_elnum( (int)at[i].el_number );
|
395
|
+
if ( atw ) {
|
396
|
+
k += sprintf( str+k, "^%d", atw+at[i].iso_atw_diff-(at[i].iso_atw_diff>0));
|
397
|
+
} else {
|
398
|
+
k += sprintf( str+k, "^+%d", at[i].iso_atw_diff-(at[i].iso_atw_diff>0));
|
399
|
+
}
|
400
|
+
}
|
401
|
+
/* obsolete section, this never happens for now */
|
402
|
+
if ( atname[0] && atname[0] < ' ' && atname[1] ) {
|
403
|
+
/* special encoding. The 1st byte contains the 1st delimiter; next delimiters are '/'. */
|
404
|
+
/* this allows to draw up to 5 numbers from 1..255 range. */
|
405
|
+
int t;
|
406
|
+
int ch = ' ' + atname[0]; /* delimiter */
|
407
|
+
k += sprintf( str+k, "%u", (unsigned)(unsigned char)atname[1]);
|
408
|
+
for ( t = 2; t < sizeof(at->elname); t ++ ) {
|
409
|
+
if ( atname[t] ) {
|
410
|
+
if ( t == 3 )
|
411
|
+
ch = ','; /* comma after 2nd number to separate tautomer group info */
|
412
|
+
if ( ch != '/' && ch != ',' )
|
413
|
+
k += sprintf( str+k, "(%c)%u", ch, (unsigned)(unsigned char)atname[t]);
|
414
|
+
else
|
415
|
+
k += sprintf( str+k, "%c%u", ch, (unsigned)(unsigned char)atname[t]);
|
416
|
+
|
417
|
+
ch = '/';
|
418
|
+
}
|
419
|
+
}
|
420
|
+
} else {
|
421
|
+
/* this is the main section to display hydrogen atoms, charges, radicals */
|
422
|
+
strncpy( str+k, atname+j, sizeof(at->elname)-j );
|
423
|
+
str[sizeof(at->elname)+k-j] = '\0';
|
424
|
+
k = strlen( str );
|
425
|
+
if ( at[i].num_H ) {
|
426
|
+
strcat( str, "H" );
|
427
|
+
k ++;
|
428
|
+
if ( at[i].num_H > 1 ) {
|
429
|
+
k += sprintf( str+k, "%d", (int)at[i].num_H );
|
430
|
+
}
|
431
|
+
}
|
432
|
+
for ( j = 0; j < NUM_H_ISOTOPES; j ++ ) {
|
433
|
+
if ( at[i].num_iso_H[j] ) {
|
434
|
+
if ( j == 0 || j !=1 && j != 2 ) {
|
435
|
+
k += sprintf( str+k, "^%dH", j+1 );
|
436
|
+
} else {
|
437
|
+
k += sprintf( str+k, j == 1? "D" : "T" );
|
438
|
+
}
|
439
|
+
if ( at[i].num_iso_H[j] > 1 ) {
|
440
|
+
k += sprintf( str+k, "%d", (int)at[i].num_iso_H[j] );
|
441
|
+
}
|
442
|
+
}
|
443
|
+
}
|
444
|
+
if ( abs(at[i].charge) > 1 )
|
445
|
+
sprintf( str+k, "%+d", at[i].charge );
|
446
|
+
else
|
447
|
+
if ( abs(at[i].charge) == 1 )
|
448
|
+
strcat( str, at[i].charge>0? "+" : "-" );
|
449
|
+
if ( at[i].radical )
|
450
|
+
strcat( str, at[i].radical==RADICAL_SINGLET? ":" :
|
451
|
+
at[i].radical==RADICAL_DOUBLET? "." :
|
452
|
+
at[i].radical==RADICAL_TRIPLET? "^^" : "?");
|
453
|
+
k = strlen(str);
|
454
|
+
sprintf( str+k, "/%d", i+1 ); /* atom ordering number, 1,2,... */
|
455
|
+
}
|
456
|
+
|
457
|
+
DrawString( pDC, str, shift, nRound(at[i].x+xoff), nRound(at[i].y+yoff) );
|
458
|
+
}
|
459
|
+
}
|
460
|
+
return ( 1 );
|
461
|
+
}
|
462
|
+
|
463
|
+
/****************************************************************************/
|
464
|
+
int DrawBond( HDC pDC, int x1, int y1, int x2, int y2, int b_type, int b_stereo, int b_parity, int bInvertBonds, COLORREF clrPen, int nPenWidth )
|
465
|
+
{
|
466
|
+
int abs_value_of_stereo = abs( b_stereo );
|
467
|
+
int bond_parity_mark = b_type & BOND_MARK_PARITY;
|
468
|
+
int bond_highlight = b_type & BOND_MARK_HIGHLIGHT;
|
469
|
+
int ret;
|
470
|
+
b_type ^= (bond_parity_mark | bond_highlight);
|
471
|
+
|
472
|
+
if ( !b_stereo ||
|
473
|
+
/* => no stereo */
|
474
|
+
b_type== BOND_TYPE_DOUBLE && abs_value_of_stereo!=STEREO_DBLE_EITHER ||
|
475
|
+
/* => ignore unknown double bond stereo */
|
476
|
+
b_type >= BOND_TYPE_TRIPLE ||
|
477
|
+
/* => ignore bond stereo in case of triple bonds */
|
478
|
+
b_type==BOND_TYPE_SINGLE && !(abs_value_of_stereo==STEREO_SNGL_UP ||
|
479
|
+
abs_value_of_stereo==STEREO_SNGL_EITHER ||
|
480
|
+
abs_value_of_stereo==STEREO_SNGL_DOWN)
|
481
|
+
/* => ignore unknown single bond stereo */ ) {
|
482
|
+
/*if ( b_type || !abs_value_of_stereo || (abs_value_of_stereo != 1 && abs_value_of_stereo != 4 && abs_value_of_stereo != 6) ) */
|
483
|
+
ret = DrawBondNoStereo( pDC, x1, y1, x2, y2, b_type, 0!=bond_highlight, clrPen, nPenWidth );
|
484
|
+
} else {
|
485
|
+
ret = DrawBondStereo( pDC, x1, y1, x2, y2, b_stereo, 0!=bond_highlight, bInvertBonds, clrPen, nPenWidth );
|
486
|
+
}
|
487
|
+
if ( b_parity /* bond_parity_mark*/ ) {
|
488
|
+
DrawBondParity( pDC, x1, y1, x2, y2, b_parity );
|
489
|
+
}
|
490
|
+
return ret;
|
491
|
+
}
|
492
|
+
/****************************************************************************/
|
493
|
+
double RoundDouble(double X)
|
494
|
+
{
|
495
|
+
return ((X)>0.0? floor((X)+0.5):-floor(0.4999999-(X)));
|
496
|
+
}
|
497
|
+
/****************************************************************************/
|
498
|
+
int nRound( double X )
|
499
|
+
{
|
500
|
+
return (int)RoundDouble( X );
|
501
|
+
}
|
502
|
+
/****************************************************************************/
|
503
|
+
void roundoff_coord( double dx1, double dx2, int *new_ix1, int *new_ix2 )
|
504
|
+
{
|
505
|
+
int new_x1;
|
506
|
+
int new_x2;
|
507
|
+
int diff = (int) RoundDouble(dx2-dx1);
|
508
|
+
|
509
|
+
if ( dx1 >= dx2 ) {
|
510
|
+
new_x1 = (int) RoundDouble(dx1);
|
511
|
+
new_x2 = new_x1 + diff;
|
512
|
+
} else {
|
513
|
+
new_x2 = (int) RoundDouble(dx2);
|
514
|
+
new_x1 = new_x2 - diff;
|
515
|
+
}
|
516
|
+
if ( new_ix1 )
|
517
|
+
*new_ix1 = new_x1;
|
518
|
+
if ( new_ix2 )
|
519
|
+
*new_ix2 = new_x2;
|
520
|
+
}
|
521
|
+
/****************************************************************************/
|
522
|
+
void DrawPenColorFilledPolygon( HDC pDC, const POINT* pnt, int num )
|
523
|
+
{
|
524
|
+
LOGPEN LogPen;
|
525
|
+
HPEN penNew=(HPEN)GetStockObject(BLACK_PEN);
|
526
|
+
HPEN penOld=(HPEN)SelectObject(pDC, penNew); /* get current pen */
|
527
|
+
HBRUSH brushNew, brushOld;
|
528
|
+
int ret;
|
529
|
+
ret = GetObject( penOld, sizeof(LogPen), &LogPen );
|
530
|
+
SelectObject(pDC, penOld);
|
531
|
+
/* do not need to delete stock object penNew */
|
532
|
+
if ( ret ) {
|
533
|
+
if ( brushNew = CreateSolidBrush(LogPen.lopnColor) ) {
|
534
|
+
brushOld = (HBRUSH)SelectObject( pDC, brushNew );
|
535
|
+
Polygon( pDC, pnt, num );
|
536
|
+
SelectObject( pDC, brushOld);
|
537
|
+
DeleteObject( brushNew );
|
538
|
+
}
|
539
|
+
}
|
540
|
+
}
|
541
|
+
/****************************************************************************/
|
542
|
+
int DrawTextColorDot( HDC pDC )
|
543
|
+
{
|
544
|
+
COLORREF clrColor = GetTextColor( pDC );
|
545
|
+
int width = GetSubstringWidth( pDC, 1, ".");
|
546
|
+
HPEN penNew = CreatePen(PS_SOLID, 0, clrColor);
|
547
|
+
HBRUSH brushNew = CreateSolidBrush(clrColor);
|
548
|
+
/*int hfont = GetFontHeight( pDC ); */
|
549
|
+
POINT pt;
|
550
|
+
int bSuccess = 0;
|
551
|
+
int nVertShift;
|
552
|
+
int nTextAlign = (TA_BOTTOM | TA_TOP | TA_BASELINE) & GetTextAlign( pDC );
|
553
|
+
if ( TA_BASELINE == nTextAlign ) {
|
554
|
+
nVertShift = 0;
|
555
|
+
} else
|
556
|
+
if ( TA_BOTTOM == nTextAlign ) {
|
557
|
+
nVertShift = -GetFontDescent( pDC );
|
558
|
+
} else
|
559
|
+
if ( TA_TOP == nTextAlign ) {
|
560
|
+
nVertShift = GetFontHeight( pDC ); /*GetFontAscent( pDC ); */
|
561
|
+
} else {
|
562
|
+
nVertShift = GetFontHeight( pDC );
|
563
|
+
}
|
564
|
+
if ( width % 2 ) {
|
565
|
+
width ++;
|
566
|
+
}
|
567
|
+
|
568
|
+
GetCurrentPositionEx( pDC, &pt );
|
569
|
+
if ( penNew && brushNew ) {
|
570
|
+
HPEN penOld = (HPEN) SelectObject( pDC, penNew );
|
571
|
+
HBRUSH brushOld = (HBRUSH)SelectObject( pDC, brushNew );
|
572
|
+
bSuccess = Ellipse( pDC, pt.x+width/2, pt.y - (3*width)/2+nVertShift, pt.x + (3*width)/2, pt.y-width/2+nVertShift );
|
573
|
+
SelectObject( pDC, penOld );
|
574
|
+
SelectObject( pDC, brushOld );
|
575
|
+
if ( bSuccess ) {
|
576
|
+
MoveToEx( pDC, pt.x+(3*width)/2, pt.y, NULL );
|
577
|
+
}
|
578
|
+
}
|
579
|
+
if ( penNew )
|
580
|
+
DeleteObject( penNew );
|
581
|
+
if ( brushNew )
|
582
|
+
DeleteObject( brushNew );
|
583
|
+
return bSuccess;
|
584
|
+
}
|
585
|
+
/****************************************************************************/
|
586
|
+
int DrawBondStereo( HDC pDC, int x1, int y1, int x2, int y2, int b_stereo, int b_highlight, int bInvertBonds, COLORREF clrPen, int nPenWidth )
|
587
|
+
{
|
588
|
+
double lambda, mult, ax1, ay1, bond_sep, bond_width, bond_step, dx, dy, dx1, dy1;
|
589
|
+
int ix, ix1, iy, iy1, ix21, ix22, iy21, iy22;
|
590
|
+
int i, n;
|
591
|
+
int hfont = GetFontHeight( pDC );
|
592
|
+
HPEN hHighlightPen=0, hOldPen = 0;
|
593
|
+
COLORREF clrHighlight = CLR_MAGENTA;
|
594
|
+
|
595
|
+
|
596
|
+
POINT pnt[4];
|
597
|
+
|
598
|
+
if ( b_highlight ) {
|
599
|
+
hHighlightPen = CreatePen( PS_SOLID, nPenWidth, clrHighlight );
|
600
|
+
if ( !hHighlightPen )
|
601
|
+
hHighlightPen = (HPEN)GetStockObject( BLACK_PEN ); /*should not fail */
|
602
|
+
hOldPen = (HPEN)SelectObject( pDC, hHighlightPen );
|
603
|
+
}
|
604
|
+
/* the wedge (pointed) end is at (x1, y1) unless b_stereo is negative */
|
605
|
+
if ( b_stereo < 0 ) {
|
606
|
+
i = x1;
|
607
|
+
x1 = x2;
|
608
|
+
x2 = i;
|
609
|
+
i = y1;
|
610
|
+
y1 = y2;
|
611
|
+
y2 = i;
|
612
|
+
b_stereo = -b_stereo; /* 1=Up (solid triangle), 6=Down (Dashed triangle), 4=Either (zigzag triangle) */
|
613
|
+
}
|
614
|
+
if ( bInvertBonds ) {
|
615
|
+
switch ( b_stereo ) {
|
616
|
+
case STEREO_SNGL_UP:
|
617
|
+
b_stereo = STEREO_SNGL_DOWN;
|
618
|
+
break;
|
619
|
+
case STEREO_SNGL_DOWN:
|
620
|
+
b_stereo = STEREO_SNGL_UP;
|
621
|
+
break;
|
622
|
+
}
|
623
|
+
}
|
624
|
+
|
625
|
+
dx = x2 - x1;
|
626
|
+
dy = y2 - y1;
|
627
|
+
lambda = dx*dx + dy*dy;
|
628
|
+
if ( lambda == 0.0 )
|
629
|
+
return 0;
|
630
|
+
lambda = sqrt( lambda ); /* bond length */
|
631
|
+
|
632
|
+
bond_width = hfont / 6.0;
|
633
|
+
if ( bond_width < 2.0 )
|
634
|
+
bond_width = 2.0; /* half-width */
|
635
|
+
/* from x1 to x2 */
|
636
|
+
bond_width = inchi_min( bond_width, lambda / 8.0 );
|
637
|
+
bond_width = floor( 2.0*bond_width + 0.5 )/2; /* half of actual bond width */
|
638
|
+
|
639
|
+
bond_step = hfont / 4.0;
|
640
|
+
bond_step = inchi_min( bond_step, lambda/6.0 );
|
641
|
+
bond_step = inchi_max( bond_step, 3 );
|
642
|
+
|
643
|
+
if ( b_stereo == 3 ) {
|
644
|
+
bond_width *= 2.0; /* otherwise looks strange */
|
645
|
+
}
|
646
|
+
|
647
|
+
ax1 = -bond_width * dy / lambda;
|
648
|
+
ay1 = bond_width * dx / lambda;
|
649
|
+
|
650
|
+
switch( b_stereo ) {
|
651
|
+
|
652
|
+
case STEREO_SNGL_UP: /* Up */
|
653
|
+
roundoff_coord( x2 - ax1, x2 + ax1, &ix, &ix1 );
|
654
|
+
roundoff_coord( y2 - ay1, y2 + ay1, &iy, &iy1 );
|
655
|
+
pnt[0].x = x1;
|
656
|
+
pnt[0].y = y1;
|
657
|
+
|
658
|
+
pnt[1].x = ix1;
|
659
|
+
pnt[1].y = iy1;
|
660
|
+
|
661
|
+
pnt[2].x = ix;
|
662
|
+
pnt[2].y = iy;
|
663
|
+
|
664
|
+
DrawPenColorFilledPolygon( pDC, pnt, 3 );
|
665
|
+
break;
|
666
|
+
case STEREO_DBLE_EITHER: /* cis or trans double bond */
|
667
|
+
roundoff_coord( x2 - ax1, x2 + ax1, &ix21, &ix22 );
|
668
|
+
roundoff_coord( y2 - ay1, y2 + ay1, &iy21, &iy22 );
|
669
|
+
|
670
|
+
roundoff_coord( x1 - ax1, x1 + ax1, &ix, &ix1 );
|
671
|
+
roundoff_coord( y1 - ay1, y1 + ay1, &iy, &iy1 );
|
672
|
+
|
673
|
+
DrawLine( pDC, ix21, iy21, ix1, iy1 );
|
674
|
+
DrawLine( pDC, ix22, iy22, ix, iy );
|
675
|
+
|
676
|
+
break;
|
677
|
+
|
678
|
+
case STEREO_SNGL_EITHER: /* either */
|
679
|
+
|
680
|
+
n = (int)floor( lambda / bond_step );
|
681
|
+
n = inchi_max( n, 4 );
|
682
|
+
dx = dy = 0.0;
|
683
|
+
ix = iy = 0;
|
684
|
+
for ( i = 1; i <= 3*n/2; i ++ ) {
|
685
|
+
|
686
|
+
mult = (double)i/(double)n/1.5;
|
687
|
+
dx1 = (x2-x1)*mult;
|
688
|
+
dy1 = (y2-y1)*mult;
|
689
|
+
if ( i % 2 ) {
|
690
|
+
dx1 += ax1*mult;
|
691
|
+
dy1 += ay1*mult;
|
692
|
+
} else {
|
693
|
+
dx1 -= ax1*mult+ax1/bond_width;
|
694
|
+
dy1 -= ay1*mult+ay1/bond_width;
|
695
|
+
}
|
696
|
+
|
697
|
+
roundoff_coord( dx, dx1, NULL, &ix1 );
|
698
|
+
roundoff_coord( dy, dy1, NULL, &iy1 );
|
699
|
+
|
700
|
+
/*line( win, x1 + ix, y1 + iy, x1 + ix1, y1 + iy1 ); */
|
701
|
+
DrawLine( pDC, x1 + ix, y1 + iy, x1 + ix1, y1 + iy1 );
|
702
|
+
dx = dx1;
|
703
|
+
dy = dy1;
|
704
|
+
ix = ix1;
|
705
|
+
iy = iy1;
|
706
|
+
/*line( win, x1 + ( int ) dx, y1 + ( int ) dy, x1 + ( int ) dx1, y1 + ( int ) dy1 ); */
|
707
|
+
}
|
708
|
+
break;
|
709
|
+
|
710
|
+
case STEREO_SNGL_DOWN: /* Down */
|
711
|
+
|
712
|
+
n = (int)floor( lambda / bond_step );
|
713
|
+
n = inchi_max( n, 4 );
|
714
|
+
|
715
|
+
for ( i = 0; i <= n; i ++ ) {
|
716
|
+
mult = (double)i/(double)n;
|
717
|
+
|
718
|
+
dx = dx1 = (x2-x1)*mult; /* x1,y1 offset */
|
719
|
+
dy = dy1 = (y2-y1)*mult;
|
720
|
+
|
721
|
+
mult = (double)(i)/(double)(n);
|
722
|
+
|
723
|
+
bond_sep = ax1*mult;
|
724
|
+
dx += bond_sep;
|
725
|
+
dx1 -= bond_sep+ax1/bond_width;
|
726
|
+
|
727
|
+
bond_sep = ay1*mult;
|
728
|
+
dy += bond_sep;
|
729
|
+
dy1 -= bond_sep+ay1/bond_width;
|
730
|
+
|
731
|
+
roundoff_coord( dx, dx1, &ix, &ix1 );
|
732
|
+
roundoff_coord( dy, dy1, &iy, &iy1 );
|
733
|
+
|
734
|
+
DrawLine( pDC, x1 + ix, y1 + iy, x1 + ix1, y1 + iy1 );
|
735
|
+
}
|
736
|
+
break;
|
737
|
+
}
|
738
|
+
/* cleanup */
|
739
|
+
if ( hOldPen )
|
740
|
+
SelectObject( pDC, hOldPen );
|
741
|
+
if ( hHighlightPen )
|
742
|
+
DeleteObject( hHighlightPen );
|
743
|
+
|
744
|
+
return 0;
|
745
|
+
}
|
746
|
+
/****************************************************************************/
|
747
|
+
int DrawBondParity( HDC pDC, int x1, int y1, int x2, int y2, int parity_mark0 )
|
748
|
+
{
|
749
|
+
/* int hfont = GetFontHeight( pDC ); */
|
750
|
+
int xs, ys, width, height, parity_mark;
|
751
|
+
char *p;
|
752
|
+
COLORREF clrTextOld;
|
753
|
+
|
754
|
+
if ( parity_mark0 < 0 ) {
|
755
|
+
parity_mark = -parity_mark0;
|
756
|
+
clrTextOld = SetTextColor( pDC, CLR_RED );
|
757
|
+
} else {
|
758
|
+
parity_mark = parity_mark0;
|
759
|
+
}
|
760
|
+
|
761
|
+
if ( parity_mark == BOND_MARK_ODD ) p = "(-)"; else
|
762
|
+
if ( parity_mark == BOND_MARK_EVEN ) p = "(+)"; else
|
763
|
+
if ( parity_mark == BOND_MARK_UNDF ) p = "(?)"; else
|
764
|
+
if ( parity_mark == BOND_MARK_UNKN ) p = "(u)"; else
|
765
|
+
if ( parity_mark == BOND_MARK_ERR ) p = "(!)"; else return 0;
|
766
|
+
|
767
|
+
if ( abs( x2-x1 ) > 10 * abs(y2 - y1) ) {
|
768
|
+
/* almost horizontal bond; draw parity closer (1:2) to the right end */
|
769
|
+
if ( x2 < x1 ) {
|
770
|
+
int tmp;
|
771
|
+
tmp = x2;
|
772
|
+
x2 = x1;
|
773
|
+
x1 = tmp;
|
774
|
+
tmp = y2;
|
775
|
+
y2 = y1;
|
776
|
+
y1 = tmp;
|
777
|
+
}
|
778
|
+
xs = 2*x1 + (4*(x2-x1))/3; /* 2/3 shift */
|
779
|
+
ys = 2*y1 + (4*(y2-y1))/3; /* 2/3 shift */
|
780
|
+
} else {
|
781
|
+
xs = x1 + x2; /* middle */
|
782
|
+
ys = y1 + y2; /* middle */
|
783
|
+
}
|
784
|
+
GetTextSize( pDC, strlen(p), p, &width, &height );
|
785
|
+
/*
|
786
|
+
width = GetFontAveWidth( pDC);
|
787
|
+
height = GetFontAscent( pDC );
|
788
|
+
*/
|
789
|
+
xs = (xs - width )/2;
|
790
|
+
ys = (ys - height )/2;
|
791
|
+
|
792
|
+
TextOut( pDC, xs, ys, p, 3 );
|
793
|
+
|
794
|
+
if ( parity_mark0 < 0 ) {
|
795
|
+
SetTextColor( pDC, clrTextOld );
|
796
|
+
}
|
797
|
+
|
798
|
+
return 0;
|
799
|
+
}
|
800
|
+
/****************************************************************************/
|
801
|
+
int DrawBondNoStereo( HDC pDC, int x1, int y1, int x2, int y2, int b_type, int b_highlight, COLORREF clrPen, int nPenWidth )
|
802
|
+
{
|
803
|
+
double lambda, ax1, ax2, ay1, ay2, bond_sep;
|
804
|
+
int hfont = GetFontHeight( pDC );
|
805
|
+
int ret = 0;
|
806
|
+
HPEN hSolidPen=0, hDashedPen=0, hLongDashedPen=0, hHighlightPen = 0, hOldPen=0;
|
807
|
+
char c=0, r=0, l=0, bDashed=1, bLongDashed=0, i;
|
808
|
+
COLORREF clr = clrPen;
|
809
|
+
|
810
|
+
switch( b_type ) { /* c=center, l=left, r=right */
|
811
|
+
case 0:
|
812
|
+
c = 'D';
|
813
|
+
b_highlight = 1;
|
814
|
+
break;
|
815
|
+
case BOND_SINGLE: /* S=solid, D=dashed, L=long dashed(Green) */
|
816
|
+
c = 'S';
|
817
|
+
bDashed = 0;
|
818
|
+
break;
|
819
|
+
case BOND_DOUBLE:
|
820
|
+
l = r = 'S';
|
821
|
+
bDashed = 0;
|
822
|
+
break;
|
823
|
+
case BOND_TRIPLE:
|
824
|
+
l = r = c = 'S';
|
825
|
+
bDashed = 0;
|
826
|
+
break;
|
827
|
+
case BOND_TAUTOM:
|
828
|
+
l = r = 'D';
|
829
|
+
break;
|
830
|
+
case BOND_ALTERN: /* 1 or 2 */
|
831
|
+
l = 'S';
|
832
|
+
r = 'D';
|
833
|
+
break;
|
834
|
+
case BOND_ALT12NS: /* 1 or 2, non-stereo */
|
835
|
+
l = 'L';
|
836
|
+
r = 'D';
|
837
|
+
bLongDashed = 1;
|
838
|
+
break;
|
839
|
+
case BOND_ALT_13: /* 1 or 3 */
|
840
|
+
l = 'S';
|
841
|
+
c = r = 'D';
|
842
|
+
break;
|
843
|
+
case BOND_ALT_23: /* 2 or 3 */
|
844
|
+
l = c = 'S';
|
845
|
+
r = 'D';
|
846
|
+
break;
|
847
|
+
case BOND_ALT_123: /* 1 or 2 or 3 */
|
848
|
+
c = 'S';
|
849
|
+
l = r = 'D';
|
850
|
+
break;
|
851
|
+
default:
|
852
|
+
c = 'D';
|
853
|
+
break;
|
854
|
+
}
|
855
|
+
if ( bLongDashed ) {
|
856
|
+
clr = CLR_GREEN;
|
857
|
+
}
|
858
|
+
/* -- debug --
|
859
|
+
if ( c && l && r ) {
|
860
|
+
int stop = 1;
|
861
|
+
}
|
862
|
+
*/
|
863
|
+
if ( b_highlight ) {
|
864
|
+
clr = CLR_MAGENTA;
|
865
|
+
if ( c=='S' || l == 'S' || r == 'S' ) {
|
866
|
+
hHighlightPen = CreatePen( PS_SOLID, nPenWidth, clr );
|
867
|
+
if ( !hHighlightPen )
|
868
|
+
hHighlightPen = (HPEN)GetStockObject( BLACK_PEN ); /*should not fail */
|
869
|
+
hOldPen = (HPEN)SelectObject( pDC, hHighlightPen );
|
870
|
+
}
|
871
|
+
}
|
872
|
+
|
873
|
+
if ( bDashed ) {
|
874
|
+
hDashedPen = CreatePen( PS_DOT, 1, clr );
|
875
|
+
if ( !hDashedPen )
|
876
|
+
hDashedPen = (HPEN)GetStockObject( BLACK_PEN ); /*should not fail */
|
877
|
+
}
|
878
|
+
if ( bLongDashed ) {
|
879
|
+
hLongDashedPen = CreatePen( PS_DASH, 1, clr );
|
880
|
+
if ( !hLongDashedPen )
|
881
|
+
hLongDashedPen = (HPEN)GetStockObject( BLACK_PEN ); /*should not fail */
|
882
|
+
}
|
883
|
+
|
884
|
+
/* draw lines between the atoms */
|
885
|
+
if ( c == 'S' ) {
|
886
|
+
DrawLine( pDC, x1, y1, x2, y2 );
|
887
|
+
} else
|
888
|
+
if ( c == 'D' ) {
|
889
|
+
hSolidPen = (HPEN)SelectObject( pDC, hDashedPen );
|
890
|
+
DrawLine( pDC, x1, y1, x2, y2 );
|
891
|
+
hDashedPen = (HPEN)SelectObject( pDC, hSolidPen );
|
892
|
+
} else
|
893
|
+
if ( c == 'L' ) {
|
894
|
+
hSolidPen = (HPEN)SelectObject( pDC, hLongDashedPen );
|
895
|
+
DrawLine( pDC, x1, y1, x2, y2 );
|
896
|
+
hLongDashedPen = (HPEN)SelectObject( pDC, hSolidPen );
|
897
|
+
}
|
898
|
+
|
899
|
+
/* draw lines parallel to line between bonds */
|
900
|
+
if ( l || r ) {
|
901
|
+
|
902
|
+
if ( b_type == BOND_DOUBLE ) {
|
903
|
+
bond_sep = hfont / 12.0;
|
904
|
+
if( ( x1 == x2 ) || ( y1 == y2 ) ) {
|
905
|
+
if ( bond_sep < 1.0 ) bond_sep = 1.0;
|
906
|
+
} else {
|
907
|
+
if ( bond_sep < 2.0 ) bond_sep = 2.0;
|
908
|
+
}
|
909
|
+
} else {
|
910
|
+
bond_sep = hfont / 6.0;
|
911
|
+
if( ( x1 == x2 ) || ( y1 == y2 ) ) {
|
912
|
+
if ( bond_sep < 2.0 ) bond_sep = 2.0;
|
913
|
+
} else {
|
914
|
+
if ( bond_sep < 4.0 ) bond_sep = 4.0;
|
915
|
+
}
|
916
|
+
}
|
917
|
+
|
918
|
+
lambda = ( ( double ) ( x2 - x1 ) ) * ( x2 - x1 ) +
|
919
|
+
( ( double ) ( y2 - y1 ) ) * ( y2 - y1 );
|
920
|
+
|
921
|
+
if ( lambda > 0.0 )
|
922
|
+
lambda = bond_sep / sqrt( lambda );
|
923
|
+
else {
|
924
|
+
ret = 1;
|
925
|
+
goto exit_function;
|
926
|
+
}
|
927
|
+
for ( i = 0; i < 2; i ++, lambda = -lambda ) {
|
928
|
+
c = i? r : l;
|
929
|
+
ax1 = lambda * ( y1 - y2 ) + x1;
|
930
|
+
ay1 = lambda * ( x2 - x1 ) + y1;
|
931
|
+
ax2 = lambda * ( y1 - y2 ) + x2;
|
932
|
+
ay2 = lambda * ( x2 - x1 ) + y2;
|
933
|
+
|
934
|
+
if ( c == 'S' ) {
|
935
|
+
DrawLine( pDC, ( int ) ax1, ( int ) ay1, ( int ) ax2, ( int ) ay2 );
|
936
|
+
} else
|
937
|
+
if ( c == 'D' ) {
|
938
|
+
hSolidPen = (HPEN)SelectObject( pDC, hDashedPen );
|
939
|
+
DrawLine( pDC, ( int ) ax1, ( int ) ay1, ( int ) ax2, ( int ) ay2 );
|
940
|
+
hDashedPen = (HPEN)SelectObject( pDC, hSolidPen );
|
941
|
+
} else
|
942
|
+
if ( c == 'L' ) {
|
943
|
+
hSolidPen = (HPEN)SelectObject( pDC, hLongDashedPen );
|
944
|
+
DrawLine( pDC, x1, y1, x2, y2 );
|
945
|
+
hLongDashedPen = (HPEN)SelectObject( pDC, hSolidPen );
|
946
|
+
}
|
947
|
+
}
|
948
|
+
|
949
|
+
}
|
950
|
+
|
951
|
+
exit_function:
|
952
|
+
/* make sure DC has its initial pen */
|
953
|
+
if ( hSolidPen )
|
954
|
+
SelectObject( pDC, hSolidPen );
|
955
|
+
if ( hOldPen )
|
956
|
+
SelectObject( pDC, hOldPen );
|
957
|
+
/* delete all newly created pens */
|
958
|
+
if ( hDashedPen )
|
959
|
+
DeleteObject( hDashedPen );
|
960
|
+
if ( hLongDashedPen )
|
961
|
+
DeleteObject( hLongDashedPen );
|
962
|
+
if ( hHighlightPen )
|
963
|
+
DeleteObject( hHighlightPen );
|
964
|
+
|
965
|
+
return ( ret );
|
966
|
+
}
|
967
|
+
/****************************************************************************/
|
968
|
+
int MoveHydrogenAtomToTheLeft( char *s, int start, int H )
|
969
|
+
{
|
970
|
+
int len, c, num_alpha;
|
971
|
+
char szBuffer[16];
|
972
|
+
char *pH = strchr( s+start, H );
|
973
|
+
for ( pH = s+start, num_alpha = 0; (c= UCINT*pH) && c != H && c != '/'; pH ++ ) {
|
974
|
+
num_alpha = isalpha( c );
|
975
|
+
}
|
976
|
+
if ( c == H && num_alpha ) { /* do not search beyond the first slash */
|
977
|
+
for ( len = 1; pH[len] && isdigit( UCINT pH[len] ); len ++ )
|
978
|
+
;
|
979
|
+
if ( len >= (int)sizeof(szBuffer) )
|
980
|
+
return start; /* too long string */
|
981
|
+
memcpy( szBuffer, pH, len );
|
982
|
+
memmove( s+len, s, pH - s );
|
983
|
+
memmove( s, szBuffer, len );
|
984
|
+
return start+len; /* (pH-s)+i; */
|
985
|
+
}
|
986
|
+
return start;
|
987
|
+
}
|
988
|
+
/****************************************************************************/
|
989
|
+
int MyTextOutABC( const char *p, int iFst, int iLst, HDC pDC )
|
990
|
+
{
|
991
|
+
ABC abc;
|
992
|
+
POINT pt;
|
993
|
+
if ( iFst > iLst || iFst < 0 || iLst < 0 )
|
994
|
+
return 0;
|
995
|
+
GetCurrentPositionEx( pDC, &pt );
|
996
|
+
if ( GetCharABCWidths(
|
997
|
+
pDC, /* handle to DC */
|
998
|
+
(int)p[iFst], /* first character in range */
|
999
|
+
(int)p[iFst], /* last character in range */
|
1000
|
+
&abc /* array of character widths */
|
1001
|
+
) && abc.abcA < 0 ) {
|
1002
|
+
pt.x -= abc.abcA;
|
1003
|
+
MoveToEx( pDC, pt.x, pt.y, NULL );
|
1004
|
+
}
|
1005
|
+
TextOut( pDC, pt.x, pt.y, p+iFst, iLst-iFst+1 );
|
1006
|
+
if ( GetCharABCWidths(
|
1007
|
+
pDC, /* handle to DC */
|
1008
|
+
(int)p[iLst], /* first character in range */
|
1009
|
+
(int)p[iLst], /* last character in range */
|
1010
|
+
&abc /* array of character widths */
|
1011
|
+
) && abc.abcC < 0 ) {
|
1012
|
+
GetCurrentPositionEx( pDC, &pt );
|
1013
|
+
pt.x -= abc.abcC;
|
1014
|
+
MoveToEx( pDC, pt.x, pt.y, NULL );
|
1015
|
+
}
|
1016
|
+
return 1;
|
1017
|
+
}
|
1018
|
+
/****************************************************************************/
|
1019
|
+
int DrawColorString( HDC pDC, const char *st, int xs, int ys, int bHighlightTheAtom )
|
1020
|
+
{
|
1021
|
+
int afont = GetFontAscent( pDC );
|
1022
|
+
COLORREF clrBk = CLR_WHITE;
|
1023
|
+
int nNumSlash = 0;
|
1024
|
+
COLORREF OrigBkColor = CLR_WHITE;
|
1025
|
+
COLORREF OrigTxColor = GetTextColor( pDC );
|
1026
|
+
COLORREF NewBkColor;
|
1027
|
+
int bWritingAtomStringColored = 0;
|
1028
|
+
/* Draw the string character by character. */
|
1029
|
+
/* For each character within the first part of the string */
|
1030
|
+
/* make a decision if it is a subscript or a superscript */
|
1031
|
+
/* The first part ends with '/'=start of the canonical number or '(' = start of the parity mark */
|
1032
|
+
/* The superscript first character is ^ or + or - or . (. initiates double shift) */
|
1033
|
+
/* The the superscript ends with not the first character and not a digit or the end of the first part */
|
1034
|
+
/* The first character of a subscript (if it is not in the superscript) is a digit */
|
1035
|
+
/* The subscript ends a non-digit */
|
1036
|
+
const char *p=st;
|
1037
|
+
UINT uPrevTextAlign = SetTextAlign( pDC, TA_UPDATECP);
|
1038
|
+
POINT pt, pt0;
|
1039
|
+
int i, i0, len, bSuperscript, bSubscript, bWritingAtomString, nShift, nShift2;
|
1040
|
+
int bNewBkColor, bMoveToEx, bBypassCurrentChar;
|
1041
|
+
nShift = afont/2;
|
1042
|
+
nShift2 = nShift/2;
|
1043
|
+
if ( bHighlightTheAtom ) {
|
1044
|
+
clrBk = SetBkColor( pDC, CLR_LTPURPLE );
|
1045
|
+
} else
|
1046
|
+
if ( strchr(st, '~') ) {
|
1047
|
+
clrBk = SetBkColor( pDC, CLR_CYAN );
|
1048
|
+
} /* else { == for debugging ==
|
1049
|
+
clrBk = SetBkColor( pDC, CLR_LTGRAY );
|
1050
|
+
} */
|
1051
|
+
if ( st[0] == '!' ) {
|
1052
|
+
OrigTxColor = SetTextColor( pDC, CLR_RED );
|
1053
|
+
bWritingAtomStringColored = 1;
|
1054
|
+
p ++;
|
1055
|
+
}
|
1056
|
+
bSuperscript = bSubscript = 0;
|
1057
|
+
bWritingAtomString = 1;
|
1058
|
+
MoveToEx( pDC, xs, ys, NULL );
|
1059
|
+
for ( i = i0 = 0, len = strlen( p ); i < len; i ++ ) {
|
1060
|
+
bNewBkColor = 0;
|
1061
|
+
bMoveToEx = 0;
|
1062
|
+
if ( bWritingAtomString ) {
|
1063
|
+
GetCurrentPositionEx( pDC, &pt );
|
1064
|
+
pt0 = pt;
|
1065
|
+
if ( !p[i] || p[i] == '/' || p[i] == '(' ) {
|
1066
|
+
bWritingAtomString = 0;
|
1067
|
+
if ( bSuperscript ) {
|
1068
|
+
while( bSuperscript > 1 ) {
|
1069
|
+
pt.y += nShift2;
|
1070
|
+
bSuperscript --;
|
1071
|
+
}
|
1072
|
+
pt.y += nShift;
|
1073
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1074
|
+
bMoveToEx = 1;
|
1075
|
+
bSuperscript = 0;
|
1076
|
+
}
|
1077
|
+
if ( bSubscript ) {
|
1078
|
+
pt.y -= nShift;
|
1079
|
+
bMoveToEx = 1;
|
1080
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1081
|
+
bSubscript = 0;
|
1082
|
+
}
|
1083
|
+
} else {
|
1084
|
+
/* turn Superscript off */
|
1085
|
+
if ( bSuperscript == 2 && p[i] != '.' ) {
|
1086
|
+
pt.y += nShift2;
|
1087
|
+
bMoveToEx = 1;
|
1088
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1089
|
+
bSuperscript -= 1;
|
1090
|
+
}
|
1091
|
+
if ( bSuperscript && !isdigit((int)(unsigned char)p[i]) && p[i] != '+' && p[i] != '-' && p[i] != '.' ) {
|
1092
|
+
while( bSuperscript > 1 ) {
|
1093
|
+
pt.y += nShift2;
|
1094
|
+
bSuperscript --;
|
1095
|
+
}
|
1096
|
+
pt.y += nShift;
|
1097
|
+
bMoveToEx = 1;
|
1098
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1099
|
+
bSuperscript = 0;
|
1100
|
+
}
|
1101
|
+
/* turn Subscript off */
|
1102
|
+
if ( bSubscript && !isdigit((int)(unsigned char)p[i] ) ) {
|
1103
|
+
pt.y -= nShift;
|
1104
|
+
bMoveToEx = 1;
|
1105
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1106
|
+
bSubscript = 0;
|
1107
|
+
}
|
1108
|
+
/* turn Subscript on after non-space and non-digit */
|
1109
|
+
if ( !bSuperscript && !bSubscript && ( i && p[i-1] != ' ' && !isdigit((int)(unsigned char)p[i-1]) && isdigit((int)(unsigned char)p[i])) ) {
|
1110
|
+
pt.y += nShift;
|
1111
|
+
bMoveToEx = 1;
|
1112
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1113
|
+
bSubscript = 1;
|
1114
|
+
}
|
1115
|
+
/* turn Superscript on */
|
1116
|
+
if ( !bSuperscript && !bSubscript &&
|
1117
|
+
(p[i] == '^' || p[i] == '.' ||
|
1118
|
+
(p[i] == '+' || p[i] == '-') && (i && p[i-1]!=' ' ) ) ) {
|
1119
|
+
pt.y -= nShift;
|
1120
|
+
bSuperscript += 1;
|
1121
|
+
if ( p[i] == '.' ) {
|
1122
|
+
bSuperscript += 1; /* special case */
|
1123
|
+
pt.y -= nShift2;
|
1124
|
+
}
|
1125
|
+
bMoveToEx = 1;
|
1126
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1127
|
+
if ( p[i] == '^' ) {
|
1128
|
+
goto output_the_string;
|
1129
|
+
continue; /* leading superscript: isotopic mass */
|
1130
|
+
}
|
1131
|
+
}
|
1132
|
+
if ( bSuperscript == 1 && !bSubscript && p[i] == '.' ) {
|
1133
|
+
pt.y -= nShift2;
|
1134
|
+
bSuperscript += 1;
|
1135
|
+
bMoveToEx = 1;
|
1136
|
+
/* MoveToEx( pDC, pt.x, pt.y, NULL ); */
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
}
|
1140
|
+
}
|
1141
|
+
if ( p[i] == '/' ) {
|
1142
|
+
nNumSlash ++;
|
1143
|
+
if ( nNumSlash == 1 ) {
|
1144
|
+
OrigBkColor = GetBkColor( pDC );
|
1145
|
+
bNewBkColor ++;
|
1146
|
+
NewBkColor = CLR_YELLOW;
|
1147
|
+
/* OrigBkColor = SetBkColor( pDC, CLR_YELLOW);*/ /* CLR_CYAN ); */
|
1148
|
+
}
|
1149
|
+
if ( nNumSlash == 3 ) {
|
1150
|
+
bNewBkColor ++;
|
1151
|
+
NewBkColor = CLR_CYAN;
|
1152
|
+
/* SetBkColor( pDC, CLR_CYAN ); */
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
#ifdef DISPLAY_DEBUG_DATA
|
1156
|
+
else if ( nNumSlash && p[i] == '`' ) {
|
1157
|
+
bNewBkColor ++;
|
1158
|
+
NewBkColor = CLR_LTPURPLE;
|
1159
|
+
/* SetBkColor( pDC, CLR_LTPURPLE );*/ /* DebugData */
|
1160
|
+
}
|
1161
|
+
#endif
|
1162
|
+
/* output one character; special treatment for '.' */
|
1163
|
+
output_the_string:
|
1164
|
+
bBypassCurrentChar = ( p[i] == '.' && bSuperscript || p[i] == '^' );
|
1165
|
+
if ( bBypassCurrentChar || bNewBkColor || bMoveToEx ) {
|
1166
|
+
/* output the accumulated string */
|
1167
|
+
int iLast = i-(bBypassCurrentChar || bMoveToEx);
|
1168
|
+
/*
|
1169
|
+
int k;
|
1170
|
+
for ( k = i0; k <= iLast; k ++ ) {
|
1171
|
+
MyTextOutABC( p, k, k, pDC );
|
1172
|
+
}
|
1173
|
+
*/
|
1174
|
+
MyTextOutABC( p, i0, iLast, pDC ); /* including iLast */
|
1175
|
+
i0 = i+1-bMoveToEx;
|
1176
|
+
if ( p[i0] == '^' )
|
1177
|
+
i0 ++;
|
1178
|
+
if ( bMoveToEx ) {
|
1179
|
+
int dx = pt.x - pt0.x;
|
1180
|
+
int dy = pt.y - pt0.y;
|
1181
|
+
GetCurrentPositionEx( pDC, &pt );
|
1182
|
+
pt.x += dx;
|
1183
|
+
pt.y += dy;
|
1184
|
+
MoveToEx( pDC, pt.x, pt.y, NULL );
|
1185
|
+
}
|
1186
|
+
if ( bNewBkColor ) {
|
1187
|
+
SetBkColor( pDC, NewBkColor);
|
1188
|
+
}
|
1189
|
+
if ( p[i] == '.' && bSuperscript ) {
|
1190
|
+
if ( !DrawTextColorDot( pDC ) ) {
|
1191
|
+
TextOut( pDC, xs, ys, p+i, 1 );
|
1192
|
+
}
|
1193
|
+
}
|
1194
|
+
}
|
1195
|
+
/*
|
1196
|
+
if ( p[i] != '.' || !bSuperscript || !DrawTextColorDot( pDC ) ) {
|
1197
|
+
TextOut( pDC, xs, ys, p+i, 1 );
|
1198
|
+
}
|
1199
|
+
*/
|
1200
|
+
}
|
1201
|
+
MyTextOutABC( p, i0, i-1, pDC ); /* output the rest of the string */
|
1202
|
+
|
1203
|
+
SetTextAlign( pDC, uPrevTextAlign);
|
1204
|
+
if ( nNumSlash ) {
|
1205
|
+
SetBkColor( pDC, OrigBkColor );
|
1206
|
+
}
|
1207
|
+
if ( bHighlightTheAtom || strchr(st, '~') ) {
|
1208
|
+
SetBkColor( pDC, clrBk );
|
1209
|
+
}
|
1210
|
+
if ( bWritingAtomStringColored ) {
|
1211
|
+
SetTextColor( pDC, OrigTxColor );
|
1212
|
+
bWritingAtomStringColored = 0;
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
return ( 1 );
|
1216
|
+
}
|
1217
|
+
/****************************************************************************/
|
1218
|
+
int DrawPreparedString( HDC pDC, char *st1, int shift, int x, int y, int bHighlightTheAtom )
|
1219
|
+
{
|
1220
|
+
DrawColorString( pDC, st1, x+shift, y-GetFontAscent( pDC )/2, bHighlightTheAtom );
|
1221
|
+
return 1;
|
1222
|
+
}
|
1223
|
+
/****************************************************************************/
|
1224
|
+
int DrawString( HDC pDC, char *st1, int shift, int x, int y )
|
1225
|
+
{
|
1226
|
+
char st[256];
|
1227
|
+
int xs, ys, l, k;
|
1228
|
+
/* int hfont = GetFontHeight( pDC ); */
|
1229
|
+
int afont = GetFontAscent( pDC );
|
1230
|
+
/* COLORREF clrBk; */
|
1231
|
+
/* int nNumSlash = 0; */
|
1232
|
+
/* COLORREF OrigBkColor; */
|
1233
|
+
|
1234
|
+
strncpy( st, st1, sizeof(st)-1 );
|
1235
|
+
st[sizeof(st)-1] = '\0';
|
1236
|
+
|
1237
|
+
l = GetStringWidth( pDC, st );
|
1238
|
+
|
1239
|
+
/* Default values */
|
1240
|
+
xs = x - l / 2;
|
1241
|
+
ys = y - afont / 2;
|
1242
|
+
|
1243
|
+
/* Single element */
|
1244
|
+
|
1245
|
+
if( strlen( st ) == 1 ) goto draw;
|
1246
|
+
|
1247
|
+
/* Changing order for right/left connection */
|
1248
|
+
|
1249
|
+
if( shift ) {
|
1250
|
+
int start = 0;
|
1251
|
+
start = MoveHydrogenAtomToTheLeft( st, start, 'T' );
|
1252
|
+
start = MoveHydrogenAtomToTheLeft( st, start, 'D' );
|
1253
|
+
start = MoveHydrogenAtomToTheLeft( st, start, 'H' );
|
1254
|
+
/* determine the position */
|
1255
|
+
|
1256
|
+
if( ( strlen( st ) == 2 ) && islower( st[1] ) ) goto draw;
|
1257
|
+
|
1258
|
+
k = GetStringWidth( pDC, st );
|
1259
|
+
k -= GetOneCharInStringWidth( pDC, ( st + strlen( st ) - 1 ) ) / 2;
|
1260
|
+
xs = x - k;
|
1261
|
+
} else {
|
1262
|
+
|
1263
|
+
/* determine the position */
|
1264
|
+
|
1265
|
+
k = GetOneCharInStringWidth( pDC, st );
|
1266
|
+
xs = x - k / 2;
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
draw:
|
1270
|
+
DrawColorString( pDC, st, xs, ys, 0 );
|
1271
|
+
return ( 1 );
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
/****************************************************************************/
|
1275
|
+
void DrawLine( HDC pDC, int x1, int y1, int x2, int y2 )
|
1276
|
+
{
|
1277
|
+
MoveToEx( pDC, x1, y1, NULL );
|
1278
|
+
LineTo( pDC, x2, y2 );
|
1279
|
+
}
|
1280
|
+
/****************************************************************************/
|
1281
|
+
int nGetNumLegendOptions( inf_ATOM *inf_at, int num_at )
|
1282
|
+
{
|
1283
|
+
int i, n, nmax=0;
|
1284
|
+
char *p;
|
1285
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1286
|
+
for ( n = 0, p = inf_at[i].at_string; p = strchr( p, '/' ); p ++, n++ )
|
1287
|
+
;
|
1288
|
+
nmax = inchi_max( nmax, n );
|
1289
|
+
}
|
1290
|
+
return nmax;
|
1291
|
+
}
|
1292
|
+
/****************************************************************************/
|
1293
|
+
int DrawTheInputStructure( inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at,
|
1294
|
+
HDC pDC, int tx_off, int ty_off, int xoff, int yoff,
|
1295
|
+
int width_pix, int height_pix, int bDraw, int bOrigAtom, COLORREF clrPen, int nPenWidth )
|
1296
|
+
{
|
1297
|
+
int RetVal;
|
1298
|
+
char *NoRoom = "Window is too small";
|
1299
|
+
#ifdef INCHI_LIB
|
1300
|
+
static char PressEnter[] = "";
|
1301
|
+
#else
|
1302
|
+
static char PressEnter[] = "Press Enter to continue.";
|
1303
|
+
#endif
|
1304
|
+
static char Legend[] = "Legend:";
|
1305
|
+
char **Str;
|
1306
|
+
int num_str;
|
1307
|
+
inf_ATOM *inf_at = inf_at_data? inf_at_data->at : NULL;
|
1308
|
+
static char LastString[256];
|
1309
|
+
static char *LastStr[] = { "Atom / Atom Id", " / Non-stereo class", " / Mobile group id", " / Mobile group class", "" };
|
1310
|
+
static char *StrOrig[] = {PressEnter, Legend, "Atom / Input atom number"};
|
1311
|
+
static char *StrInfo[] = {PressEnter, Legend, LastString};
|
1312
|
+
|
1313
|
+
int nFontHeight, nFontAveWidth, afont, i, x, y, n_opt;
|
1314
|
+
COLORREF rgbColor;
|
1315
|
+
|
1316
|
+
RetVal = 0;
|
1317
|
+
nFontHeight = GetFontHeight( pDC );
|
1318
|
+
nFontAveWidth = GetFontAveWidth( pDC );
|
1319
|
+
afont = GetFontAscent( pDC );
|
1320
|
+
|
1321
|
+
|
1322
|
+
if ( bDraw ) {
|
1323
|
+
/* drawing */
|
1324
|
+
DrawStructure( pDC, at, inf_at_data, num_at, xoff, yoff, clrPen, nPenWidth );
|
1325
|
+
/* draw the message and legend: */
|
1326
|
+
if ( !inf_at || bOrigAtom ) {
|
1327
|
+
Str = StrOrig;
|
1328
|
+
num_str = sizeof(StrOrig)/sizeof(StrOrig[0]);
|
1329
|
+
} else {
|
1330
|
+
n_opt = nGetNumLegendOptions( inf_at, num_at );
|
1331
|
+
Str = StrInfo;
|
1332
|
+
num_str = sizeof(StrInfo)/sizeof(StrInfo[0]);
|
1333
|
+
for ( i = 0, LastString[0] = '\0'; i < n_opt && LastStr[i][0]; i ++ ) {
|
1334
|
+
strcat(LastString, LastStr[i]);
|
1335
|
+
}
|
1336
|
+
}
|
1337
|
+
rgbColor = SetBkColor( pDC, CLR_CYAN );
|
1338
|
+
x = nFontAveWidth;
|
1339
|
+
y = nFontHeight/5;
|
1340
|
+
for ( i = 0; i < num_str; i ++ ) {
|
1341
|
+
if ( i+1 < num_str ) {
|
1342
|
+
TextOut( pDC, x+tx_off, y+ty_off, Str[i], strlen(Str[i]) );
|
1343
|
+
x += GetStringWidth( pDC, Str[i] )+2*nFontAveWidth;
|
1344
|
+
if ( i == 0 ) {
|
1345
|
+
SetBkColor( pDC, rgbColor );
|
1346
|
+
rgbColor = SetTextColor( pDC, CLR_BLUE /*CLR_RED*/ );
|
1347
|
+
} else
|
1348
|
+
if ( i == 1 ) {
|
1349
|
+
SetTextColor( pDC, rgbColor );
|
1350
|
+
}
|
1351
|
+
} else {
|
1352
|
+
DrawString( pDC, Str[i], 0, x+tx_off, y+afont/2+ty_off );
|
1353
|
+
}
|
1354
|
+
}
|
1355
|
+
} else {
|
1356
|
+
rgbColor = SetTextColor( pDC, CLR_RED );
|
1357
|
+
TextOut( pDC, nFontAveWidth+tx_off, nFontHeight/5+ty_off, NoRoom, strlen(NoRoom) );
|
1358
|
+
rgbColor = SetTextColor( pDC, rgbColor );
|
1359
|
+
}
|
1360
|
+
return RetVal;
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
|
1364
|
+
/****************************************************************************/
|
1365
|
+
typedef struct tagTableParms {
|
1366
|
+
int thdrHeight;
|
1367
|
+
int thdrWidth;
|
1368
|
+
int tcellHeight;
|
1369
|
+
int tcellWidth;
|
1370
|
+
int tblHeight;
|
1371
|
+
int tblWidth;
|
1372
|
+
int tblRows;
|
1373
|
+
int tblCols;
|
1374
|
+
int xtblOffs;
|
1375
|
+
int ytblOffs;
|
1376
|
+
} TBL_PARMS;
|
1377
|
+
/****************************************************************************/
|
1378
|
+
void CalcTblParms( HDC hMemoryDC, TBL_PARMS *tp, TBL_DRAW_PARMS *tdp,
|
1379
|
+
int *xStructOffs, int *yStructOffs, int *xStructSize, int *yStructSize, int yoffs1)
|
1380
|
+
{
|
1381
|
+
int i, j, n, w, h;
|
1382
|
+
tp->tblCols = tdp->bDrawTbl;
|
1383
|
+
tp->tblRows = 0;
|
1384
|
+
for ( i = 0; i < tp->tblCols; i ++ ) {
|
1385
|
+
(tdp->nOrientation? GetVertTextSize:GetTextSize)( hMemoryDC, strlen(tdp->ReqShownFoundTxt[i]), tdp->ReqShownFoundTxt[i], &w, &h );
|
1386
|
+
tp->thdrHeight=inchi_max(h, tp->thdrHeight);
|
1387
|
+
tp->thdrWidth =inchi_max(w, tp->thdrWidth );
|
1388
|
+
|
1389
|
+
for ( j = 0, n = 0; j < TDP_NUM_PAR; j ++ ) {
|
1390
|
+
if ( tdp->ReqShownFound[i][j] >= ' ' ) {
|
1391
|
+
GetTextSize( hMemoryDC, 1, &tdp->ReqShownFound[i][j], &w, &h );
|
1392
|
+
tp->tcellHeight=inchi_max(h, tp->tcellHeight);
|
1393
|
+
tp->tcellWidth =inchi_max(w, tp->tcellWidth );
|
1394
|
+
n ++; /* number of types of requested or found or shown features (type: B/T, I/N, S) */
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
tp->tblRows = inchi_max(tp->tblRows, n);
|
1398
|
+
}
|
1399
|
+
if ( tdp->nOrientation ) { /* here are tp->tblCols columns and tp->tblRows rows. */
|
1400
|
+
tp->tblHeight = tp->thdrHeight + (2*tp->tblRows+2)*tp->tcellHeight; /* empty lines above the header and around each cell */
|
1401
|
+
tp->thdrWidth = tp->tcellWidth = inchi_max( tp->tcellWidth, tp->thdrWidth );
|
1402
|
+
tp->tblWidth = (2*tp->tblCols+1) * tp->tcellWidth; /* add empty columns around each column */
|
1403
|
+
*xStructOffs += tp->tblWidth; /* draw on the left margine */
|
1404
|
+
/* *yStructSize -= tp->tblHeight; */
|
1405
|
+
*xStructSize -= tp->tblWidth;
|
1406
|
+
tp->xtblOffs = 0;
|
1407
|
+
tp->ytblOffs = yoffs1;
|
1408
|
+
} else { /* Do not believe your eyes: here are tp->tblCols rows and tp->tblRows columns. */
|
1409
|
+
tp->thdrHeight = tp->tcellHeight = inchi_max(tp->thdrHeight, tp->tcellHeight);
|
1410
|
+
tp->tblWidth = tp->thdrWidth + (2*tp->tblRows+2)*tp->tcellWidth;
|
1411
|
+
tp->tblHeight = (2*tp->tblCols+1)*tp->tcellHeight;
|
1412
|
+
/* draw the table on the left margine */
|
1413
|
+
*xStructOffs += tp->tblWidth;
|
1414
|
+
*xStructSize -= tp->tblWidth;
|
1415
|
+
/* *xStructSize -= tp->tblWidth; */
|
1416
|
+
tp->xtblOffs = 0;
|
1417
|
+
tp->ytblOffs = yoffs1;
|
1418
|
+
}
|
1419
|
+
}
|
1420
|
+
/****************************************************************************/
|
1421
|
+
int DrawTheTable( HDC hDC, TBL_PARMS *tp, TBL_DRAW_PARMS *tdp, int x_offs, int y_offs )
|
1422
|
+
{
|
1423
|
+
int i, j, ret;
|
1424
|
+
int dx = tp->tcellWidth/2;
|
1425
|
+
int dy = tp->tcellHeight/2;
|
1426
|
+
int x1, y1, x2, y2;
|
1427
|
+
/* draw frame around the table */
|
1428
|
+
ret = Rectangle( hDC, tp->xtblOffs+dx+x_offs, tp->ytblOffs+dy+y_offs, tp->xtblOffs+tp->tblWidth-dx+x_offs, tp->ytblOffs+tp->tblHeight-dy+y_offs);
|
1429
|
+
/* draw lines between labeled rows or columns */
|
1430
|
+
for ( i = 1; i < tp->tblCols; i ++ ) {
|
1431
|
+
if ( tdp->nOrientation ) {
|
1432
|
+
/* parallel to vertical columns */
|
1433
|
+
x1 = x2 = tp->xtblOffs+dx + 2 * i * tp->tcellWidth;
|
1434
|
+
y1 = tp->ytblOffs+dy;
|
1435
|
+
y2 = tp->ytblOffs+tp->tblHeight-dy;
|
1436
|
+
} else {
|
1437
|
+
/* parallel to horizontal rows */
|
1438
|
+
x1 = tp->xtblOffs+dx;
|
1439
|
+
x2 = tp->xtblOffs+tp->tblWidth-dx;
|
1440
|
+
y1 = y2 = tp->ytblOffs+dy + 2 * i * tp->tcellHeight;
|
1441
|
+
}
|
1442
|
+
DrawLine( hDC, x1+x_offs, y1+y_offs, x2+x_offs, y2+y_offs );
|
1443
|
+
}
|
1444
|
+
/* draw lines between requested/Shown/Found types */
|
1445
|
+
for ( i = 0; i < tp->tblRows; i ++ ) {
|
1446
|
+
if ( tdp->nOrientation ) {
|
1447
|
+
/* perpendicular to vertical columns */
|
1448
|
+
x1 = tp->xtblOffs+dx;
|
1449
|
+
x2 = tp->xtblOffs+tp->tblWidth-dx;
|
1450
|
+
y1 = y2 = tp->ytblOffs + tp->thdrHeight + tp->tcellHeight + 2 * i * tp->tcellHeight + dy;
|
1451
|
+
} else {
|
1452
|
+
/* perpendicular to horizontal rows */
|
1453
|
+
x1 = x2 = tp->xtblOffs + tp->thdrWidth + tp->tcellWidth + 2 * i * tp->tcellWidth + dx;
|
1454
|
+
y1 = tp->ytblOffs+dy;
|
1455
|
+
y2 = tp->ytblOffs+tp->tblHeight-dy;
|
1456
|
+
}
|
1457
|
+
DrawLine( hDC, x1+x_offs, y1+y_offs, x2+x_offs, y2+y_offs );
|
1458
|
+
}
|
1459
|
+
/* draw the text */
|
1460
|
+
for ( i = 0; i < tp->tblCols; i ++ ) {
|
1461
|
+
if ( tdp->nOrientation ) {
|
1462
|
+
/* vertical column */
|
1463
|
+
x1 = tp->xtblOffs + (2 * i + 1) * tp->tcellWidth;
|
1464
|
+
y1 = tp->ytblOffs + tp->tcellHeight;
|
1465
|
+
} else {
|
1466
|
+
/* horizontal row */
|
1467
|
+
x1 = tp->xtblOffs + tp->tcellWidth;
|
1468
|
+
y1 = tp->ytblOffs + tp->tcellHeight + 2 * i * tp->tcellHeight;
|
1469
|
+
}
|
1470
|
+
(tdp->nOrientation? TextOutVert:TextOutHoriz)( hDC, x1+x_offs, y1+y_offs, tdp->ReqShownFoundTxt[i], strlen(tdp->ReqShownFoundTxt[i]), tp->tcellWidth );
|
1471
|
+
|
1472
|
+
for ( j = 0; j < tp->tblRows; j ++ ) {
|
1473
|
+
if ( tdp->ReqShownFound[i][j] >= ' ' ) {
|
1474
|
+
if ( tdp->nOrientation ) {
|
1475
|
+
/* vertical column */
|
1476
|
+
y1 = tp->ytblOffs + tp->thdrHeight + (2*j + 2) * tp->tcellHeight;
|
1477
|
+
} else {
|
1478
|
+
/* horizontal row */
|
1479
|
+
x1 = tp->xtblOffs + tp->thdrWidth + (2*j + 2) * tp->tcellWidth;
|
1480
|
+
}
|
1481
|
+
(tdp->nOrientation? TextOutVert:TextOutHoriz)( hDC, x1+x_offs, y1+y_offs, &tdp->ReqShownFound[i][j], 1, tp->tcellWidth );
|
1482
|
+
}
|
1483
|
+
}
|
1484
|
+
}
|
1485
|
+
|
1486
|
+
|
1487
|
+
return 0;
|
1488
|
+
}
|
1489
|
+
/****************************************************************************/
|
1490
|
+
void GetStructSizes( HDC hDC, inf_ATOM *inf_at, inp_ATOM *at0, inp_ATOM *at1, int num_at, int *xoffs1, int *xoffs2, INT_DRAW_PARMS *idp)
|
1491
|
+
{
|
1492
|
+
int i, j, k, num_bonds;
|
1493
|
+
double xmin, xmax, ymin, ymax;
|
1494
|
+
double x2, x, y2, y, dist;
|
1495
|
+
char *str;
|
1496
|
+
int len, cur_len, half_char_width;
|
1497
|
+
int Left_shift, Right_shift, Other_shift;
|
1498
|
+
char cLeftChar, cRightChar;
|
1499
|
+
int max_left_label_width_pix;
|
1500
|
+
int max_right_label_width_pix;
|
1501
|
+
|
1502
|
+
if ( idp ) {
|
1503
|
+
if ( !inf_at ) {
|
1504
|
+
idp->max_left_label_width_pix = *xoffs1;
|
1505
|
+
idp->max_right_label_width_pix = *xoffs2;
|
1506
|
+
} else {
|
1507
|
+
idp->max_left_label_width_pix = idp->max_right_label_width_pix = 0;
|
1508
|
+
}
|
1509
|
+
} else {
|
1510
|
+
if ( !inf_at ) {
|
1511
|
+
max_left_label_width_pix = *xoffs1;
|
1512
|
+
max_right_label_width_pix = *xoffs2;
|
1513
|
+
} else {
|
1514
|
+
max_left_label_width_pix = max_right_label_width_pix = 0;
|
1515
|
+
}
|
1516
|
+
}
|
1517
|
+
|
1518
|
+
xmin=xmax=at0[0].x;
|
1519
|
+
ymin=ymax=at0[0].y;
|
1520
|
+
|
1521
|
+
for ( num_bonds = 0, i=0; i < num_at; i ++ ) {
|
1522
|
+
|
1523
|
+
x = at0[i].x;
|
1524
|
+
y = at0[i].y;
|
1525
|
+
Left_shift = Right_shift = Other_shift = 0;
|
1526
|
+
|
1527
|
+
for ( j = 0; j < at0[i].valence; j ++ ) {
|
1528
|
+
k = at0[i].neighbor[j];
|
1529
|
+
x2 = at0[k].x;
|
1530
|
+
y2 = at0[k].y;
|
1531
|
+
dist = sqrt( (x-x2)*(x-x2)+(y-y2)*(y-y2) );
|
1532
|
+
if ( x < x2 - 0.2*dist )
|
1533
|
+
Left_shift ++;
|
1534
|
+
else
|
1535
|
+
if ( x > x2 + 0.1*dist )
|
1536
|
+
Right_shift ++;
|
1537
|
+
else
|
1538
|
+
Other_shift ++;
|
1539
|
+
}
|
1540
|
+
|
1541
|
+
if ( inf_at ) {
|
1542
|
+
len = 0;
|
1543
|
+
str = inf_at[i].at_string;
|
1544
|
+
do {
|
1545
|
+
if ( cur_len=strcspn(str, "^") ) {
|
1546
|
+
if ( !len ) {
|
1547
|
+
cLeftChar = str[0];
|
1548
|
+
}
|
1549
|
+
cRightChar = str[cur_len-1];
|
1550
|
+
len += GetSubstringWidth( hDC, cur_len, str);
|
1551
|
+
}
|
1552
|
+
str += cur_len+1;
|
1553
|
+
} while ( str[0] );
|
1554
|
+
inf_at[i].DrawingLabelLength = len;
|
1555
|
+
if ( Left_shift && !Right_shift ) {
|
1556
|
+
/* Atom label should be to the left from the vertex */
|
1557
|
+
half_char_width = len? GetOneCharInStringWidth( hDC, &cRightChar )/2:0;
|
1558
|
+
inf_at[i].DrawingLabelLeftShift = len - half_char_width;
|
1559
|
+
if ( idp ) {
|
1560
|
+
idp->max_left_label_width_pix = inchi_max( idp->max_left_label_width_pix, inf_at[i].DrawingLabelLeftShift);
|
1561
|
+
idp->max_right_label_width_pix = inchi_max(idp->max_right_label_width_pix, half_char_width);
|
1562
|
+
} else {
|
1563
|
+
max_left_label_width_pix = inchi_max(max_left_label_width_pix, inf_at[i].DrawingLabelLeftShift);
|
1564
|
+
max_right_label_width_pix = inchi_max(max_right_label_width_pix, half_char_width);
|
1565
|
+
}
|
1566
|
+
/* convert NH2 to H2N, etc. */
|
1567
|
+
len = 0;
|
1568
|
+
str = inf_at[i].at_string;
|
1569
|
+
len = MoveHydrogenAtomToTheLeft( str, len, 'T' );
|
1570
|
+
len = MoveHydrogenAtomToTheLeft( str, len, 'D' );
|
1571
|
+
len = MoveHydrogenAtomToTheLeft( str, len, 'H' );
|
1572
|
+
} else {
|
1573
|
+
/* Atom label should be to the right from the vertex */
|
1574
|
+
half_char_width = len? GetOneCharInStringWidth( hDC, &cLeftChar )/2:0;
|
1575
|
+
inf_at[i].DrawingLabelLeftShift = half_char_width;
|
1576
|
+
if ( idp ) {
|
1577
|
+
idp->max_left_label_width_pix = inchi_max( idp->max_left_label_width_pix, half_char_width);
|
1578
|
+
idp->max_right_label_width_pix = inchi_max( idp->max_right_label_width_pix,
|
1579
|
+
inf_at[i].DrawingLabelLength
|
1580
|
+
- inf_at[i].DrawingLabelLeftShift);
|
1581
|
+
} else {
|
1582
|
+
max_left_label_width_pix = inchi_max( max_left_label_width_pix, half_char_width);
|
1583
|
+
max_right_label_width_pix = inchi_max( max_right_label_width_pix,
|
1584
|
+
inf_at[i].DrawingLabelLength
|
1585
|
+
- inf_at[i].DrawingLabelLeftShift);
|
1586
|
+
}
|
1587
|
+
}
|
1588
|
+
} else {
|
1589
|
+
at1[i].bDrawingLabelLeftShift = ( Left_shift && !Right_shift );
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
xmin = inchi_min( xmin, x );
|
1593
|
+
xmax = inchi_max( xmax, x );
|
1594
|
+
ymin = inchi_min( ymin, y );
|
1595
|
+
ymax = inchi_max( ymax, y );
|
1596
|
+
}
|
1597
|
+
if ( idp ) {
|
1598
|
+
idp->xmin = xmin;
|
1599
|
+
idp->xmax = xmax;
|
1600
|
+
idp->ymin = ymin;
|
1601
|
+
idp->ymax = ymax;
|
1602
|
+
if ( inf_at ) {
|
1603
|
+
*xoffs1 = idp->max_left_label_width_pix;
|
1604
|
+
*xoffs2 = idp->max_right_label_width_pix;
|
1605
|
+
}
|
1606
|
+
} else
|
1607
|
+
if ( inf_at ) {
|
1608
|
+
*xoffs1 = max_left_label_width_pix;
|
1609
|
+
*xoffs2 = max_right_label_width_pix;
|
1610
|
+
}
|
1611
|
+
|
1612
|
+
}
|
1613
|
+
/****************************************************************************/
|
1614
|
+
void ResizeAtomForDrawing( inf_ATOM *inf_at, inp_ATOM *at0, inp_ATOM *at1, int num_at,
|
1615
|
+
INT_DRAW_PARMS *idp, int width, int height, int nFontWidth, int *xoffs1, int *xoffs2,
|
1616
|
+
int *draw_width, int *draw_height, int *xdraw_offs, int *ydraw_offs )
|
1617
|
+
{
|
1618
|
+
int i;
|
1619
|
+
double xmin = idp->xmin;
|
1620
|
+
double xmax = idp->xmax;
|
1621
|
+
double ymin = idp->ymin;
|
1622
|
+
double ymax = idp->ymax;
|
1623
|
+
double dx = 0.0, dy = 0.0, new_dx;
|
1624
|
+
double coeff=0.0, xShift=0.0, yShift=0.0;
|
1625
|
+
double coeffx = 0.0, coeffy = 0.0, new_coeffx;
|
1626
|
+
|
1627
|
+
|
1628
|
+
if ( xmax > xmin || ymax > ymin ) {
|
1629
|
+
|
1630
|
+
dx = xmax-xmin;
|
1631
|
+
dy = ymax-ymin;
|
1632
|
+
|
1633
|
+
if ( width > 0 && height > 0 ) {
|
1634
|
+
coeffx = dx > 0.0? (double)width/dx : 0.0;
|
1635
|
+
coeffy = dy > 0.0? (double)height/dy : 0.0;
|
1636
|
+
|
1637
|
+
if ( coeffx > 0.0 && coeffy > 0.0 )
|
1638
|
+
coeff = inchi_min( coeffx, coeffy );
|
1639
|
+
else
|
1640
|
+
coeff = inchi_max( coeffx, coeffy );
|
1641
|
+
}
|
1642
|
+
if ( coeffx == 0.0 ) {
|
1643
|
+
xShift = width/2.0;
|
1644
|
+
}
|
1645
|
+
if ( coeffy == 0.0 ) {
|
1646
|
+
yShift = height/2.0;
|
1647
|
+
}
|
1648
|
+
|
1649
|
+
} else {
|
1650
|
+
coeff = 0.0;
|
1651
|
+
xShift = width/2.0;
|
1652
|
+
yShift = height/2.0;
|
1653
|
+
}
|
1654
|
+
|
1655
|
+
|
1656
|
+
/* set screen coordinates for drawing */
|
1657
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1658
|
+
at1[i].y = (ymax - at0[i].y)*coeff+yShift; /* screen y axis is directed down */
|
1659
|
+
at1[i].x = (at0[i].x-xmin)*coeff+xShift;
|
1660
|
+
}
|
1661
|
+
/* horizontal screen coordinates rescale if x dimension determines struct. size */
|
1662
|
+
if ( coeffx > 0.0 && coeffy > 0.0 && inf_at ) {
|
1663
|
+
double new_xmin = 1.0e32;
|
1664
|
+
double new_xmax = -1.0e32;
|
1665
|
+
double dx1, dx2;
|
1666
|
+
int nPass=0;
|
1667
|
+
int new_width = width + idp->max_left_label_width_pix + idp->max_right_label_width_pix;
|
1668
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1669
|
+
dx1 = at1[i].x - inf_at[i].DrawingLabelLeftShift;
|
1670
|
+
dx2 = dx1 + inf_at[i].DrawingLabelLength;
|
1671
|
+
new_xmin = inchi_min( new_xmin, dx1 );
|
1672
|
+
new_xmax = inchi_max( new_xmax, dx2 );
|
1673
|
+
}
|
1674
|
+
new_dx = new_xmax - new_xmin;
|
1675
|
+
if ( coeffx > coeffy && new_dx < (double)new_width )
|
1676
|
+
goto done;
|
1677
|
+
if ( new_dx < (double)new_width && new_dx > (double)(new_width-2*nFontWidth) )
|
1678
|
+
goto done;
|
1679
|
+
again:
|
1680
|
+
new_dx += nFontWidth; /* precaution */
|
1681
|
+
new_coeffx = coeffx + ((double)new_width-new_dx)/dx;
|
1682
|
+
if ( coeffy > 0.0 )
|
1683
|
+
coeff = inchi_min(new_coeffx, coeffy);
|
1684
|
+
else
|
1685
|
+
coeff = new_coeffx;
|
1686
|
+
|
1687
|
+
new_xmin = 1.0e32;
|
1688
|
+
new_xmax = -1.0e32;
|
1689
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1690
|
+
dy = at1[i].y = (ymax - at0[i].y)*coeff+yShift; /* screen y axis is directed down */
|
1691
|
+
dx = at1[i].x = (at0[i].x-xmin)*coeff+xShift;
|
1692
|
+
dx1 = dx - inf_at[i].DrawingLabelLeftShift;
|
1693
|
+
dx2 = dx1 + inf_at[i].DrawingLabelLength;
|
1694
|
+
new_xmin = inchi_min( new_xmin, dx1 );
|
1695
|
+
new_xmax = inchi_max( new_xmax, dx2 );
|
1696
|
+
}
|
1697
|
+
new_dx = new_xmax - new_xmin;
|
1698
|
+
if ( new_dx > new_width && nPass++ < 3 ) {
|
1699
|
+
coeffx = new_coeffx;
|
1700
|
+
goto again;
|
1701
|
+
}
|
1702
|
+
done:
|
1703
|
+
*xoffs1 = -nRound( new_xmin );
|
1704
|
+
*xoffs2 = nRound( new_xmax - (xmax-xmin)*coeff );
|
1705
|
+
*draw_width = nRound( (xmax-xmin)*coeff ); /* nRound( new_dx ); */
|
1706
|
+
*draw_height = nRound( (ymax-ymin)*coeff );
|
1707
|
+
} else {
|
1708
|
+
*draw_width = nRound( (xmax-xmin)*coeff );
|
1709
|
+
*draw_height = nRound( (ymax-ymin)*coeff );
|
1710
|
+
}
|
1711
|
+
*xdraw_offs = nRound(xShift);
|
1712
|
+
*ydraw_offs = nRound(yShift);
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
/******************************************************************************/
|
1716
|
+
void InpStructureMarkEquComponents( MY_WINDOW_DATA *pWinData, AT_NUMB nNewEquLabel,
|
1717
|
+
inp_ATOM *at0, inp_ATOM *at1, inf_ATOM *inf_at, int num_at )
|
1718
|
+
{
|
1719
|
+
int bHighlight = 0;
|
1720
|
+
AT_NUMB *nEquLabels = pWinData->nEquLabels;
|
1721
|
+
/* highlight equivalent components */
|
1722
|
+
int i, neigh, j, ni, nj, nh;
|
1723
|
+
if ( nNewEquLabel ) {
|
1724
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1725
|
+
ni = (int)at0[i].orig_at_number-1;
|
1726
|
+
if ( 0 <= ni && ni < num_at ) {
|
1727
|
+
if ( nNewEquLabel == nEquLabels[ni] ||
|
1728
|
+
1==at0[i].el_number && 1==at0[i].chem_bonds_valence &&
|
1729
|
+
0<=(nh=(int)at0[at0[i].neighbor[0]].orig_at_number-1) &&
|
1730
|
+
nh < num_at && nNewEquLabel == nEquLabels[nh] ) {
|
1731
|
+
inf_at[i].cHighlightTheAtom = 1; /* highlight the atom */
|
1732
|
+
bHighlight |= 1;
|
1733
|
+
for ( j = 0; j < at0[i].valence; j ++ ) {
|
1734
|
+
neigh = (int)at0[i].neighbor[j];
|
1735
|
+
if ( neigh < num_at &&
|
1736
|
+
0 <= (nj = (int)at0[neigh].orig_at_number-1) &&
|
1737
|
+
nj < num_at &&
|
1738
|
+
(
|
1739
|
+
/* highlighted atom */
|
1740
|
+
( nNewEquLabel == nEquLabels[nj] ) ||
|
1741
|
+
/* terminal H */
|
1742
|
+
( 1==at0[neigh].el_number && 1 == at0[neigh].chem_bonds_valence)
|
1743
|
+
)
|
1744
|
+
) {
|
1745
|
+
at0[i].bond_type[j] |= BOND_MARK_HIGHLIGHT; /* highlight the bond */
|
1746
|
+
at1[i].bond_type[j] |= BOND_MARK_HIGHLIGHT; /* highlight the bond */
|
1747
|
+
}
|
1748
|
+
}
|
1749
|
+
} else
|
1750
|
+
if ( inf_at[i].cHighlightTheAtom ) {
|
1751
|
+
inf_at[i].cHighlightTheAtom = 0;
|
1752
|
+
for ( j = 0; j < at0[i].valence; j ++ ) {
|
1753
|
+
at0[i].bond_type[j] &= ~BOND_MARK_HIGHLIGHT; /* remove highlight from the bond */
|
1754
|
+
at1[i].bond_type[j] &= ~BOND_MARK_HIGHLIGHT; /* remove highlight from the bond */
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
}
|
1758
|
+
}
|
1759
|
+
}
|
1760
|
+
} else {
|
1761
|
+
for ( i = 0; i < num_at; i ++ ) {
|
1762
|
+
ni = (int)at0[i].orig_at_number-1;
|
1763
|
+
if ( 0 <= ni && ni < num_at ) {
|
1764
|
+
if ( inf_at[i].cHighlightTheAtom ) {
|
1765
|
+
inf_at[i].cHighlightTheAtom = 0;
|
1766
|
+
for ( j = 0; j < at0[i].valence; j ++ ) {
|
1767
|
+
at0[i].bond_type[j] &= ~BOND_MARK_HIGHLIGHT; /* remove highlight from the bond */
|
1768
|
+
at1[i].bond_type[j] &= ~BOND_MARK_HIGHLIGHT; /* remove highlight from the bond */
|
1769
|
+
}
|
1770
|
+
|
1771
|
+
}
|
1772
|
+
|
1773
|
+
}
|
1774
|
+
}
|
1775
|
+
}
|
1776
|
+
if ( !bHighlight ) {
|
1777
|
+
nNewEquLabel = 0;
|
1778
|
+
}
|
1779
|
+
pWinData->nCurEquLabel = nNewEquLabel;
|
1780
|
+
pWinData->bHighlight = bHighlight;
|
1781
|
+
}
|
1782
|
+
/****************************************************************************/
|
1783
|
+
int CreateInputStructPicture( HDC hDC, MY_WINDOW_DATA *pWinData, RECT *rc, int bPrint, AT_NUMB nNewEquLabel )
|
1784
|
+
{
|
1785
|
+
int ErrCode = 1, Res, width=0, height=0, yoffs0=0, xoffs1=0, yoffs1=0, xoffs2, yoffs2;
|
1786
|
+
int xDim, yDim, w, h, xs, ys;
|
1787
|
+
|
1788
|
+
HDC hMemoryDC = NULL;
|
1789
|
+
HBITMAP hBitmap = NULL, hOldBitmap=NULL;
|
1790
|
+
HPEN Pen = 0, OldPen = 0;
|
1791
|
+
LOGFONT MyLogFont;
|
1792
|
+
HFONT Font = 0, OldFont = 0;
|
1793
|
+
char *FaceName = FONT_NAME;
|
1794
|
+
int bDrawTbl = 0;
|
1795
|
+
int bStereoFlags = 0;
|
1796
|
+
|
1797
|
+
int win_top = rc->top;
|
1798
|
+
int win_left = rc->left;
|
1799
|
+
|
1800
|
+
int win_width = rc->right - rc->left;
|
1801
|
+
int win_height = rc->bottom - rc->top;
|
1802
|
+
|
1803
|
+
int bm_top = rc->top;
|
1804
|
+
int bm_left = rc->left;
|
1805
|
+
|
1806
|
+
int bm_width = rc->right - rc->left;
|
1807
|
+
int bm_height = rc->bottom - rc->top;
|
1808
|
+
|
1809
|
+
TBL_PARMS tp;
|
1810
|
+
|
1811
|
+
int num_at = 0;
|
1812
|
+
int bOrigAtom = 0;
|
1813
|
+
int nFontSize = 10;
|
1814
|
+
inp_ATOM *at0 = NULL;
|
1815
|
+
inp_ATOM *at1 = NULL;
|
1816
|
+
inf_ATOM *inf_at = NULL;
|
1817
|
+
INT_DRAW_PARMS *idp = NULL;
|
1818
|
+
TBL_DRAW_PARMS *tdp = NULL;
|
1819
|
+
INT_DRAW_PARMS idp_print;
|
1820
|
+
|
1821
|
+
/* structure + headers rect: offsets, width, height */
|
1822
|
+
int xStructOffs=0, yStructOffs=0, xStructSize, yStructSize;
|
1823
|
+
|
1824
|
+
int nFontHeight=0;
|
1825
|
+
int nFontWidth=0;
|
1826
|
+
int nPenWidth = 1;
|
1827
|
+
COLORREF clrPen = CLR_BLUE;
|
1828
|
+
int afont;
|
1829
|
+
|
1830
|
+
/*bPrint = 1;*/ /* test */
|
1831
|
+
|
1832
|
+
if ( pWinData ) {
|
1833
|
+
num_at = pWinData->num_at;
|
1834
|
+
bOrigAtom = pWinData->bOrigAtom;
|
1835
|
+
nFontSize = pWinData->nFontSize;
|
1836
|
+
at0 = pWinData->at0;
|
1837
|
+
at1 = pWinData->at1;
|
1838
|
+
inf_at = pWinData->inf_at_data.at;
|
1839
|
+
idp = &pWinData->idp;
|
1840
|
+
tdp = &pWinData->tdp;
|
1841
|
+
bStereoFlags = pWinData->inf_at_data.StereoFlags;
|
1842
|
+
if ( bPrint ) {
|
1843
|
+
idp = &idp_print;
|
1844
|
+
memset( idp, 0, sizeof(idp[0]) );
|
1845
|
+
}
|
1846
|
+
|
1847
|
+
if ( pWinData->nCurEquLabel != nNewEquLabel &&
|
1848
|
+
pWinData->nEquLabels &&
|
1849
|
+
nNewEquLabel <= pWinData->nNumEquSets && at0 && at1 && inf_at && num_at ) {
|
1850
|
+
InpStructureMarkEquComponents( pWinData, nNewEquLabel, at0, at1, inf_at, num_at );
|
1851
|
+
}
|
1852
|
+
}
|
1853
|
+
|
1854
|
+
|
1855
|
+
xDim = xStructSize = win_width;
|
1856
|
+
yDim = yStructSize = win_height;
|
1857
|
+
if ( !bPrint ) {
|
1858
|
+
/* create bitmap: drawing on a bitmap reduces screen flicker */
|
1859
|
+
if ( !(hMemoryDC = CreateCompatibleDC(hDC)) ||
|
1860
|
+
!(hBitmap = CreateCompatibleBitmap(hDC, xDim, yDim )) ||
|
1861
|
+
!(hOldBitmap = (HBITMAP) SelectObject(hMemoryDC, hBitmap)) ||
|
1862
|
+
!PatBlt( hMemoryDC, 0, 0, xDim, yDim, PATCOPY )) {
|
1863
|
+
ErrCode = 0;
|
1864
|
+
goto _end;
|
1865
|
+
}
|
1866
|
+
bm_top = 0;
|
1867
|
+
bm_left = 0;
|
1868
|
+
bm_height = win_height - win_top;
|
1869
|
+
bm_width = win_width - win_left;
|
1870
|
+
} else {
|
1871
|
+
hMemoryDC = hDC;
|
1872
|
+
}
|
1873
|
+
|
1874
|
+
if ( pWinData ) {
|
1875
|
+
/* create drawing tools: font */
|
1876
|
+
memset( &MyLogFont, 0, sizeof( LOGFONT ) );
|
1877
|
+
if ( nFontSize < 0 ) {
|
1878
|
+
int iLogPixsY = GetDeviceCaps(hDC, LOGPIXELSY);
|
1879
|
+
nFontSize = -MulDiv(iLogPixsY, -nFontSize, 72);
|
1880
|
+
}
|
1881
|
+
nPenWidth = bPrint? inchi_max(abs(nFontSize)/10,1):1;
|
1882
|
+
clrPen = bPrint? CLR_BLACK : CLR_BLUE;
|
1883
|
+
MyLogFont.lfHeight = nFontSize;
|
1884
|
+
MyLogFont.lfWeight = FW_NORMAL;
|
1885
|
+
/* MyLogFont.lfItalic = 1; */ /* test MyTextOutABC() */
|
1886
|
+
strncpy( MyLogFont.lfFaceName, FaceName, LF_FACESIZE );
|
1887
|
+
Font = CreateFontIndirect( &MyLogFont ); /* black */
|
1888
|
+
|
1889
|
+
/* create drawing tools: pen */
|
1890
|
+
Pen = CreatePen( PS_SOLID, nPenWidth, clrPen );
|
1891
|
+
|
1892
|
+
/* select drawing tools into the bitmap */
|
1893
|
+
OldFont = (HFONT)SelectObject( hMemoryDC, Font );
|
1894
|
+
OldPen = (HPEN) SelectObject( hMemoryDC, Pen );
|
1895
|
+
|
1896
|
+
/* find sizes */
|
1897
|
+
|
1898
|
+
nFontHeight = GetFontHeight( hMemoryDC );
|
1899
|
+
nFontWidth = GetFontAveWidth( hMemoryDC );
|
1900
|
+
afont = GetFontAscent( hMemoryDC );
|
1901
|
+
|
1902
|
+
/* offsets within the (0, 0, xStructSize, yStructSize) rectangle */
|
1903
|
+
xoffs1 = xoffs2 = 16*nFontWidth; /* define structure atom coordinate margins here */
|
1904
|
+
yoffs0 = (bPrint && pWinData->szTitle && pWinData->szTitle[0] )? (3*nFontHeight)/2 : 0; /* 1.5 or 0 lines at the top */
|
1905
|
+
yoffs1 = (5*nFontHeight)/2; /* 2.5 lines at the top */
|
1906
|
+
yoffs2 = (5*nFontHeight)/2; /* 2.5 lines at the bottom */
|
1907
|
+
|
1908
|
+
/***********************************************/
|
1909
|
+
/* Calculate structure size */
|
1910
|
+
/***********************************************/
|
1911
|
+
if ( idp->bInit ) {
|
1912
|
+
/* structure sizes are known */
|
1913
|
+
xoffs1 = idp->max_left_label_width_pix;
|
1914
|
+
xoffs2 = idp->max_right_label_width_pix;
|
1915
|
+
} else {
|
1916
|
+
GetStructSizes( hMemoryDC, inf_at, at0, at1, num_at, &xoffs1, &xoffs2, idp);
|
1917
|
+
idp->bInit = 1;
|
1918
|
+
}
|
1919
|
+
|
1920
|
+
/***********************************************/
|
1921
|
+
/* Calculate requested/Shown/Found table sizes */
|
1922
|
+
/***********************************************/
|
1923
|
+
|
1924
|
+
memset( &tp, 0, sizeof(tp) );
|
1925
|
+
#ifdef INCHI_LIB
|
1926
|
+
bDrawTbl = 0;
|
1927
|
+
#else
|
1928
|
+
bDrawTbl = tdp && tdp->bDrawTbl;
|
1929
|
+
/*bDrawTbl = 0;*/
|
1930
|
+
#endif
|
1931
|
+
if ( bDrawTbl ) {
|
1932
|
+
double dx = idp->xmax - idp->xmin;
|
1933
|
+
double dy = idp->ymax - idp->ymin;
|
1934
|
+
int nOrientation_tmp = tdp->nOrientation;
|
1935
|
+
if ( dx > 0.0 && dy > 0.0 ) {
|
1936
|
+
int xStructOffs_tmp0=xStructOffs, yStructOffs_tmp0=yStructOffs;
|
1937
|
+
int xStructSize_tmp0=xStructSize, yStructSize_tmp0=yStructSize;
|
1938
|
+
int twidth0;
|
1939
|
+
/*
|
1940
|
+
int xStructOffs_tmp1=xStructOffs, yStructOffs_tmp1=yStructOffs;
|
1941
|
+
int xStructSize_tmp1=xStructSize, yStructSize_tmp1=yStructSize;
|
1942
|
+
int twidth1;
|
1943
|
+
*/
|
1944
|
+
tdp->nOrientation = 0;
|
1945
|
+
CalcTblParms( hMemoryDC, &tp, tdp,
|
1946
|
+
&xStructOffs_tmp0, &yStructOffs_tmp0, &xStructSize_tmp0, &yStructSize_tmp0, yoffs0+yoffs1);
|
1947
|
+
twidth0 = tp.tblWidth;
|
1948
|
+
xStructSize_tmp0 -= xoffs1 + xoffs2;
|
1949
|
+
yStructSize_tmp0 -= yoffs1 + yoffs2;
|
1950
|
+
/*
|
1951
|
+
memset( &tp, 0, sizeof(tp) );
|
1952
|
+
tdp->nOrientation = 0;
|
1953
|
+
CalcTblParms( hMemoryDC, &tp, tdp,
|
1954
|
+
&xStructOffs_tmp1, &yStructOffs_tmp1, &xStructSize_tmp1, &yStructSize_tmp1, yoffs1);
|
1955
|
+
twidth1 = tp.tblWidth;
|
1956
|
+
xStructSize_tmp1 -= xoffs1 + xoffs2;
|
1957
|
+
yStructSize_tmp1 -= yoffs1 + yoffs2;
|
1958
|
+
*/
|
1959
|
+
if ( xStructSize_tmp0 > 0 && yStructSize_tmp0 > 0 ) {
|
1960
|
+
nOrientation_tmp = ( (double)yStructSize_tmp0/(double)xStructSize_tmp0 > dy / dx );
|
1961
|
+
}
|
1962
|
+
}
|
1963
|
+
tdp->nOrientation = nOrientation_tmp;
|
1964
|
+
memset( &tp, 0, sizeof(tp) );
|
1965
|
+
CalcTblParms( hMemoryDC, &tp, tdp,
|
1966
|
+
&xStructOffs, &yStructOffs, &xStructSize, &yStructSize, yoffs0+yoffs1);
|
1967
|
+
} else {
|
1968
|
+
xStructSize -= 2*nFontWidth; /* drawing area sizes */
|
1969
|
+
yStructSize -= nFontHeight;
|
1970
|
+
xStructOffs += nFontWidth; /* drawing area offsets */
|
1971
|
+
yStructOffs += nFontHeight/2;
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
width = xStructSize - xoffs1 - xoffs2; /* drawing structre area sizes */
|
1975
|
+
height = yStructSize - yoffs0 - yoffs1 - yoffs2;
|
1976
|
+
ResizeAtomForDrawing( inf_at, at0, at1, num_at, idp, width, height, nFontWidth, &xoffs1, &xoffs2, &w, &h, &xs, &ys );
|
1977
|
+
|
1978
|
+
/* At this point xStructOffs = the left margin for the drawing */
|
1979
|
+
|
1980
|
+
if ( 2*xs+xoffs1+xoffs2+w < win_width - xStructOffs ) { /*compare 2*x-coordinate of the center */
|
1981
|
+
xStructOffs += (win_width - (xStructOffs+xoffs1+xoffs2+w))/2-xs;
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
}
|
1985
|
+
|
1986
|
+
/* draw */
|
1987
|
+
if ( bPrint ) {
|
1988
|
+
; /*PatBlt( hMemoryDC, 0, 0, xDim+win_left, yDim+win_top, PATCOPY ); */
|
1989
|
+
} else {
|
1990
|
+
PatBlt( hMemoryDC, 0, 0, xDim, yDim, PATCOPY );
|
1991
|
+
}
|
1992
|
+
|
1993
|
+
if ( pWinData ) {
|
1994
|
+
char str[128]="";
|
1995
|
+
|
1996
|
+
/* exact rectangle around the structure drawing */
|
1997
|
+
/*Rectangle( hMemoryDC, xStructOffs+xs-1, yStructOffs+ys+yoffs1-afont-1, xStructOffs+xs+xoffs1+xoffs2+w+1, yStructOffs+ys+yoffs1+nFontHeight+h+1); */
|
1998
|
+
Res = DrawTheInputStructure( at1, &pWinData->inf_at_data, num_at, hMemoryDC,
|
1999
|
+
bm_left, /* text output offsets */
|
2000
|
+
bm_top+yoffs0,
|
2001
|
+
bm_left + xoffs1+xStructOffs, /* structure offsets */
|
2002
|
+
bm_top + +yoffs0+yoffs1+yStructOffs,
|
2003
|
+
xDim-xoffs1, /* structure width */
|
2004
|
+
yDim-yoffs0-yoffs1, /* structure height */
|
2005
|
+
( width >= 0 && height >= 0 ), bOrigAtom, clrPen, nPenWidth );
|
2006
|
+
if( Res == -1 ){
|
2007
|
+
ErrCode = 0;
|
2008
|
+
goto _end;
|
2009
|
+
}
|
2010
|
+
if ( bDrawTbl || bStereoFlags || pWinData->inf_at_data.szRemovedProtons[0] ) {
|
2011
|
+
/*
|
2012
|
+
if ( bDrawTbl ) {
|
2013
|
+
char *str = "Abbreviations: Tautomeric, Isotopic, Stereo";
|
2014
|
+
DrawTheTable( hMemoryDC, &tp, tdp, bPrint?win_left:0, bPrint?win_top:0 );
|
2015
|
+
TextOut( hMemoryDC, nFontWidth+(bPrint?win_left:0), win_height - nFontHeight+(bPrint?win_top:0), str, strlen(str) );
|
2016
|
+
}
|
2017
|
+
*/
|
2018
|
+
if ( bStereoFlags ) {
|
2019
|
+
switch ( bStereoFlags & INF_STEREO_ABS_REL_RAC ) {
|
2020
|
+
case INF_STEREO_ABS:
|
2021
|
+
strcat( str, "Absolute" );
|
2022
|
+
break;
|
2023
|
+
case INF_STEREO_REL:
|
2024
|
+
strcat( str, "Relative" );
|
2025
|
+
break;
|
2026
|
+
case INF_STEREO_RAC:
|
2027
|
+
strcat( str, "Racemic mixture" );
|
2028
|
+
break;
|
2029
|
+
}
|
2030
|
+
if ( str[0] ) {
|
2031
|
+
strcat( str, " stereo" );
|
2032
|
+
switch( bStereoFlags & INF_STEREO_NORM_INV ) {
|
2033
|
+
case INF_STEREO_NORM:
|
2034
|
+
strcat( str, " (normal)" );
|
2035
|
+
break;
|
2036
|
+
case INF_STEREO_INV:
|
2037
|
+
strcat( str, " (inverted)" );
|
2038
|
+
break;
|
2039
|
+
case INF_STEREO_NORM_INV:
|
2040
|
+
strcat( str, " (normal and inverted)" );
|
2041
|
+
break;
|
2042
|
+
}
|
2043
|
+
}
|
2044
|
+
}
|
2045
|
+
if ( bDrawTbl ) {
|
2046
|
+
int bTaut=0, bIso=0, bSter=0;
|
2047
|
+
if ( str[0] ) {
|
2048
|
+
strcat( str, "; ");
|
2049
|
+
}
|
2050
|
+
bTaut = (NULL != memchr(tdp->ReqShownFound[ilSHOWN], 'T', TDP_NUM_PAR));
|
2051
|
+
bIso = (NULL != memchr(tdp->ReqShownFound[ilSHOWN], 'I', TDP_NUM_PAR));
|
2052
|
+
bSter = (NULL != memchr(tdp->ReqShownFound[ilSHOWN], 'S', TDP_NUM_PAR)) ||
|
2053
|
+
(NULL != memchr(tdp->ReqShownFound[ilSHOWN], 's', TDP_NUM_PAR));
|
2054
|
+
strcat( str, "Abbreviation" );
|
2055
|
+
if ( bTaut+bIso+bSter > 1 ) {
|
2056
|
+
strcat( str, "s:");
|
2057
|
+
} else {
|
2058
|
+
strcat( str, ":" );
|
2059
|
+
}
|
2060
|
+
if ( bTaut ) strcat( str, " Mobile H" );
|
2061
|
+
if ( bIso ) strcat( str, " Isotopic" );
|
2062
|
+
if ( bSter ) strcat( str, " Stereo" );
|
2063
|
+
DrawTheTable( hMemoryDC, &tp, tdp, bm_left, bm_top);
|
2064
|
+
}
|
2065
|
+
if ( pWinData->inf_at_data.szRemovedProtons[0] ) {
|
2066
|
+
if ( str[0] ) strcat( str, "; ");
|
2067
|
+
strcat( str, pWinData->inf_at_data.szRemovedProtons );
|
2068
|
+
}
|
2069
|
+
/*TextOut( hMemoryDC, nFontWidth+bm_left, bm_height - nFontHeight +bm_top, str, strlen(str) );*/
|
2070
|
+
/*DrawColorString( hMemoryDC, str, nFontWidth+bm_left, bm_height - nFontHeight +bm_top, 0 );*/
|
2071
|
+
}
|
2072
|
+
if ( pWinData->bHighlight ) {
|
2073
|
+
/* draw highlighted (identical) components description */
|
2074
|
+
char *p1 = " Highlighted ";
|
2075
|
+
char *p2 = " components are identical";
|
2076
|
+
int x = bm_left + nFontWidth;
|
2077
|
+
int y = bm_top + bm_height - nFontHeight;
|
2078
|
+
COLORREF clrBk;
|
2079
|
+
UINT uPrevTextAlign;
|
2080
|
+
POINT pt;
|
2081
|
+
/* save current position */
|
2082
|
+
GetCurrentPositionEx( hMemoryDC, &pt );
|
2083
|
+
/* move to the starting point */
|
2084
|
+
MoveToEx( hMemoryDC, x, y, NULL );
|
2085
|
+
/* set text aligh that do not require coordinates in TextOut() */
|
2086
|
+
uPrevTextAlign = SetTextAlign( hMemoryDC, TA_UPDATECP);
|
2087
|
+
/* set highlighted background color */
|
2088
|
+
clrBk = SetBkColor( hMemoryDC, CLR_LTPURPLE );
|
2089
|
+
/* output the 1st word */
|
2090
|
+
TextOut( hMemoryDC, 0, 0, p1, strlen(p1) );
|
2091
|
+
/* restore text background */
|
2092
|
+
SetBkColor( hMemoryDC, clrBk );
|
2093
|
+
/* output the rest of the text as normal text */
|
2094
|
+
TextOut( hMemoryDC, 0, 0, p2, strlen(p2) );
|
2095
|
+
|
2096
|
+
if ( str[0] ) {
|
2097
|
+
POINT pt2;
|
2098
|
+
TextOut( hMemoryDC, 0, 0, ";", 1 );
|
2099
|
+
GetCurrentPositionEx( hMemoryDC, &pt2 );
|
2100
|
+
DrawColorString( hMemoryDC, str, pt2.x+2*nFontWidth, pt2.y, 0 );
|
2101
|
+
}
|
2102
|
+
/* restore text align */
|
2103
|
+
SetTextAlign( hMemoryDC, uPrevTextAlign);
|
2104
|
+
/* restore current position */
|
2105
|
+
MoveToEx( hMemoryDC, pt.x, pt.y, NULL );
|
2106
|
+
} else
|
2107
|
+
if ( str[0] ) {
|
2108
|
+
DrawColorString( hMemoryDC, str, nFontWidth+bm_left, bm_height - nFontHeight +bm_top, 0 );
|
2109
|
+
}
|
2110
|
+
if ( yoffs0 > 0 && bPrint && pWinData->szTitle && pWinData->szTitle[0] ) {
|
2111
|
+
/* print window title */
|
2112
|
+
char *p1 = pWinData->szTitle;
|
2113
|
+
int x = bm_left + 3*nFontWidth;
|
2114
|
+
int y = bm_top + yoffs0 - (3*nFontHeight)/2;
|
2115
|
+
UINT uPrevTextAlign;
|
2116
|
+
POINT pt;
|
2117
|
+
/* save current position */
|
2118
|
+
GetCurrentPositionEx( hMemoryDC, &pt );
|
2119
|
+
/* move to the starting point */
|
2120
|
+
MoveToEx( hMemoryDC, x, y, NULL );
|
2121
|
+
/* set text aligh that do not require coordinates in TextOut() */
|
2122
|
+
uPrevTextAlign = SetTextAlign( hMemoryDC, TA_UPDATECP);
|
2123
|
+
/* output the text */
|
2124
|
+
TextOut( hMemoryDC, 0, 0, p1, strlen(p1) );
|
2125
|
+
/* restore text align */
|
2126
|
+
SetTextAlign( hMemoryDC, uPrevTextAlign);
|
2127
|
+
/* restore current position */
|
2128
|
+
MoveToEx( hMemoryDC, pt.x, pt.y, NULL );
|
2129
|
+
}
|
2130
|
+
}
|
2131
|
+
|
2132
|
+
if ( !bPrint ) {
|
2133
|
+
/* copy bitmap onto the window */
|
2134
|
+
ErrCode = BitBlt(
|
2135
|
+
hDC, /* handle to the destination device context */
|
2136
|
+
win_left, /* x-coordinate of destination rectangle's upper-left corner */
|
2137
|
+
win_top, /* y-coordinate of destination rectangle's upper-left corner */
|
2138
|
+
xDim, /* width of destination rectangle */
|
2139
|
+
yDim, /* height of destination rectangle */
|
2140
|
+
hMemoryDC, /* handle to source device context */
|
2141
|
+
bm_left, /* x-coordinate of source rectangle's upper-left corner */
|
2142
|
+
bm_top, /* y-coordinate of source rectangle's upper-left corner */
|
2143
|
+
SRCCOPY /* raster operation code */
|
2144
|
+
);
|
2145
|
+
}
|
2146
|
+
|
2147
|
+
if ( pWinData ) {
|
2148
|
+
|
2149
|
+
/* remove drawing tools */
|
2150
|
+
if( Pen ){
|
2151
|
+
SelectObject( hMemoryDC, OldPen );
|
2152
|
+
DeleteObject( Pen );
|
2153
|
+
}
|
2154
|
+
if( Font ){
|
2155
|
+
SelectObject( hMemoryDC, OldFont );
|
2156
|
+
DeleteObject( Font );
|
2157
|
+
}
|
2158
|
+
|
2159
|
+
}
|
2160
|
+
_end:
|
2161
|
+
if ( !bPrint ) {
|
2162
|
+
if( hBitmap ) {
|
2163
|
+
if ( hOldBitmap )
|
2164
|
+
SelectObject(hMemoryDC, hOldBitmap);
|
2165
|
+
DeleteObject( hBitmap );
|
2166
|
+
}
|
2167
|
+
if( hMemoryDC && hMemoryDC != hDC )
|
2168
|
+
DeleteDC(hMemoryDC);
|
2169
|
+
}
|
2170
|
+
return ErrCode;
|
2171
|
+
}
|
2172
|
+
|
2173
|
+
/*********************************************************************
|
2174
|
+
|
2175
|
+
FUNCTION: WndProcDisplayCanonStructure(HWND, unsigned, WORD, LONG)
|
2176
|
+
|
2177
|
+
PURPOSE: Processes messages for the main window.
|
2178
|
+
|
2179
|
+
MESSAGES:
|
2180
|
+
|
2181
|
+
WM_COMMAND - process the application menu
|
2182
|
+
WM_PAINT - Paint the main window
|
2183
|
+
WM_DESTROY - post a quit message and return
|
2184
|
+
WM_DISPLAYCHANGE - message sent to Plug & Play systems when the display changes
|
2185
|
+
WM_RBUTTONDOWN - Right mouse click -- put up context menu here if appropriate
|
2186
|
+
WM_NCRBUTTONUP - User has clicked the right button on the application's system menu
|
2187
|
+
|
2188
|
+
********************************************************************/
|
2189
|
+
LRESULT CALLBACK WndProcDisplayInputStructure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
2190
|
+
{
|
2191
|
+
int wmId, wmEvent;
|
2192
|
+
PAINTSTRUCT ps;
|
2193
|
+
HDC hdc;
|
2194
|
+
MY_WINDOW_DATA *pWinData;
|
2195
|
+
RECT rc;
|
2196
|
+
|
2197
|
+
#define IS_WIN95 0
|
2198
|
+
|
2199
|
+
switch (message) {
|
2200
|
+
|
2201
|
+
case WM_COMMAND:
|
2202
|
+
wmId = LOWORD(wParam); /* Remember, these are... */
|
2203
|
+
wmEvent = HIWORD(wParam); /* ...different for Win32! */
|
2204
|
+
break;
|
2205
|
+
|
2206
|
+
case WM_CLOSE:
|
2207
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2208
|
+
pWinData->bEsc = 1;
|
2209
|
+
goto close_window;
|
2210
|
+
|
2211
|
+
case WM_RBUTTONUP: /* RightClick in the window client area */
|
2212
|
+
case WM_LBUTTONUP: /* LeftClick in the window client area */
|
2213
|
+
/* stop the timer */
|
2214
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2215
|
+
if ( pWinData->nTimerId ) {
|
2216
|
+
KillTimer( hWnd, pWinData->nTimerId );
|
2217
|
+
pWinData->nTimerId = 0;
|
2218
|
+
pWinData->bUserIntervened = 1;
|
2219
|
+
}
|
2220
|
+
/*InvalidateRect( hWnd, NULL, 0 ); */
|
2221
|
+
break;
|
2222
|
+
|
2223
|
+
case WM_CHAR:
|
2224
|
+
|
2225
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2226
|
+
if ( pWinData->nTimerId ) {
|
2227
|
+
KillTimer( hWnd, pWinData->nTimerId );
|
2228
|
+
pWinData->nTimerId = 0;
|
2229
|
+
pWinData->bUserIntervened = 1;
|
2230
|
+
}
|
2231
|
+
if ( wParam == '\r' || wParam == 27 ) {
|
2232
|
+
pWinData->bEsc = (wParam == 27);
|
2233
|
+
goto close_window;
|
2234
|
+
}
|
2235
|
+
|
2236
|
+
break;
|
2237
|
+
|
2238
|
+
case WM_ERASEBKGND:
|
2239
|
+
return TRUE; /* to prevent flicker do not let Windows erase background */
|
2240
|
+
|
2241
|
+
case WM_SIZE:
|
2242
|
+
case WM_MOVE:
|
2243
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2244
|
+
if ( pWinData->nTimerId ) {
|
2245
|
+
KillTimer( hWnd, pWinData->nTimerId );
|
2246
|
+
pWinData->nTimerId = 0;
|
2247
|
+
pWinData->bUserIntervened = 1;
|
2248
|
+
}
|
2249
|
+
break;
|
2250
|
+
|
2251
|
+
case WM_DISPLAYCHANGE: /* Only comes through on plug'n'play systems */
|
2252
|
+
{
|
2253
|
+
SIZE szScreen;
|
2254
|
+
BOOL fChanged = (BOOL)wParam;
|
2255
|
+
|
2256
|
+
szScreen.cx = LOWORD(lParam);
|
2257
|
+
szScreen.cy = HIWORD(lParam);
|
2258
|
+
|
2259
|
+
if (fChanged) {
|
2260
|
+
/* The display 'has' changed. szScreen reflects the */
|
2261
|
+
/* new size. */
|
2262
|
+
; /*MessageBox (GetFocus(), "Display Changed", szWindowClassName, 0); */
|
2263
|
+
} else {
|
2264
|
+
/* The display 'is' changing. szScreen reflects the */
|
2265
|
+
/* original size. */
|
2266
|
+
MessageBeep(0);
|
2267
|
+
}
|
2268
|
+
}
|
2269
|
+
break;
|
2270
|
+
|
2271
|
+
case WM_TIMER:
|
2272
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2273
|
+
if ( wParam == pWinData->nTimerId ) {
|
2274
|
+
KillTimer( hWnd, pWinData->nTimerId );
|
2275
|
+
pWinData->nTimerId = 0;
|
2276
|
+
goto close_window;
|
2277
|
+
}
|
2278
|
+
break;
|
2279
|
+
/*
|
2280
|
+
case WM_SHOWWINDOW:
|
2281
|
+
break;
|
2282
|
+
*/
|
2283
|
+
case WM_PAINT:
|
2284
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2285
|
+
GetClientRect( hWnd, &rc );
|
2286
|
+
hdc = BeginPaint (hWnd, &ps);
|
2287
|
+
/* the drawing code is here */
|
2288
|
+
/*
|
2289
|
+
rc.top = 30;
|
2290
|
+
rc.left= 50;
|
2291
|
+
*/
|
2292
|
+
CreateInputStructPicture( hdc, pWinData, &rc, 0, pWinData->nNewEquLabel );
|
2293
|
+
EndPaint (hWnd, &ps);
|
2294
|
+
/* start the timer if requested */
|
2295
|
+
if ( !pWinData->nTimerId && !pWinData->bUserIntervened && pWinData->ulDisplTime ) {
|
2296
|
+
pWinData->nTimerId = SetTimer(
|
2297
|
+
hWnd, /* handle to window */
|
2298
|
+
MY_TIMER_ID, /* timer identifier */
|
2299
|
+
pWinData->ulDisplTime, /* time-out value */
|
2300
|
+
NULL /* ptr to the timer procedure */
|
2301
|
+
);
|
2302
|
+
}
|
2303
|
+
break;
|
2304
|
+
|
2305
|
+
case WM_DESTROY:
|
2306
|
+
/* Tell WinHelp we don't need it any more... */
|
2307
|
+
/* WinHelp (hWnd, APPNAME".HLP", HELP_QUIT,(DWORD)0); */
|
2308
|
+
/*PostQuitMessage(0); */
|
2309
|
+
return (DefWindowProc(hWnd, message, wParam, lParam));
|
2310
|
+
break;
|
2311
|
+
|
2312
|
+
default:
|
2313
|
+
return (DefWindowProc(hWnd, message, wParam, lParam));
|
2314
|
+
}
|
2315
|
+
goto exit_function;
|
2316
|
+
|
2317
|
+
close_window:
|
2318
|
+
|
2319
|
+
pWinData = (MY_WINDOW_DATA *)GetWindowLong( hWnd, GWL_USERDATA );
|
2320
|
+
GetWindowRect( hWnd, &pWinData->rc );
|
2321
|
+
ReallySetForegroundWindow(GetConsoleHwnd());
|
2322
|
+
DestroyWindow( hWnd );
|
2323
|
+
|
2324
|
+
|
2325
|
+
exit_function:
|
2326
|
+
|
2327
|
+
return (0);
|
2328
|
+
}
|
2329
|
+
/**********************************************************************************************/
|
2330
|
+
void FreeWinData( MY_WINDOW_DATA* pWinData )
|
2331
|
+
{
|
2332
|
+
if ( pWinData ) {
|
2333
|
+
if ( pWinData->at0 ) {
|
2334
|
+
inchi_free( pWinData->at0 );
|
2335
|
+
pWinData->at0 = NULL;
|
2336
|
+
}
|
2337
|
+
if ( pWinData->at1 ) {
|
2338
|
+
inchi_free( pWinData->at1 );
|
2339
|
+
pWinData->at1 = NULL;
|
2340
|
+
}
|
2341
|
+
FreeInfoAtomData( &pWinData->inf_at_data );
|
2342
|
+
|
2343
|
+
if ( pWinData->nEquLabels ) {
|
2344
|
+
inchi_free( pWinData->nEquLabels );
|
2345
|
+
pWinData->nEquLabels = NULL;
|
2346
|
+
pWinData->nNumEquSets = 0;
|
2347
|
+
}
|
2348
|
+
|
2349
|
+
if ( pWinData->szTitle ) {
|
2350
|
+
inchi_free(pWinData->szTitle);
|
2351
|
+
pWinData->szTitle = NULL;
|
2352
|
+
}
|
2353
|
+
}
|
2354
|
+
}
|
2355
|
+
#ifndef INCHI_LIB
|
2356
|
+
/**********************************************************************************************/
|
2357
|
+
int DisplayInputStructure( char *szOutputString, inp_ATOM *at, INF_ATOM_DATA *inf_at_data, int num_at, DRAW_PARMS *dp )
|
2358
|
+
{
|
2359
|
+
#define IS_WIN95 0
|
2360
|
+
HWND hWnd = NULL;
|
2361
|
+
WNDCLASS wc;
|
2362
|
+
HINSTANCE hInstance = 0;
|
2363
|
+
RECT rc, rc2, rc3;
|
2364
|
+
MSG msg;
|
2365
|
+
MY_WINDOW_DATA WinData;
|
2366
|
+
int ret, ret2, ret3, bRectVisible;
|
2367
|
+
HDC hDesktopDC;
|
2368
|
+
inf_ATOM *inf_at = inf_at_data? inf_at_data->at : NULL;
|
2369
|
+
/*WINDOWPLACEMENT wndpl = {sizeof(WINDOWPLACEMENT),}; */ /*set wndpl.length */
|
2370
|
+
/* get console application window handle */
|
2371
|
+
HWND hConsoleWnd = GetConsoleHwnd();
|
2372
|
+
HWND hDesktopWnd = GetDesktopWindow();
|
2373
|
+
int bSetForeground = (hConsoleWnd == GetForegroundWindow());
|
2374
|
+
|
2375
|
+
/*printf("hConsoleWnd = %ld, hDesktopWnd = %ld\n", (long)hConsoleWnd, (long)hDesktopWnd ); */
|
2376
|
+
|
2377
|
+
if ( !hConsoleWnd || !hDesktopWnd )
|
2378
|
+
return (FALSE); /* failed */
|
2379
|
+
if ( !IsWindowVisible(hConsoleWnd) )
|
2380
|
+
return (FALSE); /* failed */
|
2381
|
+
|
2382
|
+
|
2383
|
+
/* we will create graphics window of the same size and position as our console window */
|
2384
|
+
/* to do that we need to get console app window size and position. */
|
2385
|
+
ret = GetWindowRect( hConsoleWnd, &rc );
|
2386
|
+
/*printf( "ConsoleWnd: ret=%d, rc=%ld %ld %ld %ld\n", ret, rc.left, rc.top, rc.right, rc.bottom); */
|
2387
|
+
/* full screen: "ConsoleWnd: ret=1, rc=-32000 -32000 -31840 -31976" */
|
2388
|
+
|
2389
|
+
ret2 = GetWindowRect( hDesktopWnd, &rc2 );
|
2390
|
+
/*printf( "DesktopWnd: ret=%d, rc2=%ld %ld %ld %ld\n", ret, rc2.left, rc2.top, rc2.right, rc2.bottom); */
|
2391
|
+
/* full screen: "DesktopWnd: ret=1, rc2=0 0 1280 1024" */
|
2392
|
+
|
2393
|
+
if ( !(hDesktopDC = GetWindowDC(hDesktopWnd) ) )
|
2394
|
+
return (FALSE);
|
2395
|
+
bRectVisible = RectVisible( hDesktopDC, &rc );
|
2396
|
+
/*printf( "Console rect visible=%d\n", bRectVisible); */
|
2397
|
+
/* full screen: "Console rect visible=1" */
|
2398
|
+
|
2399
|
+
/*ret3 = GetClipBox(hDesktopDC, &rc3); */
|
2400
|
+
/*printf( "DesktopClip: ret=%d, rc3=%ld %ld %ld %ld\n", ret3, rc3.left, rc3.top, rc3.right, rc3.bottom); */
|
2401
|
+
/* full screen: "DesktopClip: ret=3, rc3=0 0 0 0", 3=COMPLEXREGION */
|
2402
|
+
|
2403
|
+
ret3 = ReleaseDC( hDesktopWnd, hDesktopDC );
|
2404
|
+
if ( !bRectVisible )
|
2405
|
+
return (FALSE); /* usually happens in MS-DOS full-screen mode, but the API call may fail and return TRUE */
|
2406
|
+
|
2407
|
+
if ( !IntersectRect(&rc3, &rc2, &rc) ) {
|
2408
|
+
/*printf( "Console rect invisible\n", bRectVisible); */
|
2409
|
+
/* full screen: "Console rect invisible" */
|
2410
|
+
return (FALSE); /* usually happens in MS-DOS full-screen mode */
|
2411
|
+
}
|
2412
|
+
|
2413
|
+
hInstance = GetModuleHandle (NULL); /* or =(HINSTANCE)GetWindowLong(hConsoleWnd, GWL_HINSTANCE); */
|
2414
|
+
if ( !dp->pdp->rcPict[2] || !dp->pdp->rcPict[3] ) {
|
2415
|
+
dp->pdp->rcPict[0] = rc.left;
|
2416
|
+
dp->pdp->rcPict[1] = rc.top;
|
2417
|
+
dp->pdp->rcPict[2] = rc.right-rc.left;
|
2418
|
+
dp->pdp->rcPict[3] = rc.bottom-rc.top;
|
2419
|
+
}
|
2420
|
+
|
2421
|
+
/* Fill in window class structure with parameters that describe */
|
2422
|
+
/* the main window. */
|
2423
|
+
wc.style = CS_HREDRAW | CS_VREDRAW;
|
2424
|
+
wc.lpfnWndProc = (WNDPROC)WndProcDisplayInputStructure; /* window procedure */
|
2425
|
+
wc.cbClsExtra = 0;
|
2426
|
+
wc.cbWndExtra = 0;
|
2427
|
+
wc.hInstance = hInstance;
|
2428
|
+
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
|
2429
|
+
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
2430
|
+
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); /*(COLOR_WINDOW+1); */
|
2431
|
+
wc.lpszMenuName = NULL;
|
2432
|
+
wc.lpszClassName = szWindowClassName;
|
2433
|
+
/* Register the window class and return success/failure code. */
|
2434
|
+
if ( !RegisterClass(&wc) )
|
2435
|
+
return FALSE;
|
2436
|
+
|
2437
|
+
hWnd = CreateWindow(szWindowClassName, szOutputString, WS_OVERLAPPEDWINDOW,
|
2438
|
+
dp->pdp->rcPict[0], dp->pdp->rcPict[1], dp->pdp->rcPict[2], dp->pdp->rcPict[3],
|
2439
|
+
/*rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, */
|
2440
|
+
hConsoleWnd, NULL, hInstance, NULL);
|
2441
|
+
|
2442
|
+
if (!hWnd) {
|
2443
|
+
/* avoid nasty messages about exception 0x5 in Windows dlls. */
|
2444
|
+
UnregisterClass(szWindowClassName, /* address of class name string */
|
2445
|
+
hInstance /* handle of application instance */
|
2446
|
+
);
|
2447
|
+
return (FALSE);
|
2448
|
+
}
|
2449
|
+
|
2450
|
+
/* provide window procedure with the pointer to the chemical structure */
|
2451
|
+
memset( &WinData, 0, sizeof(WinData) );
|
2452
|
+
WinData.at0 =(inp_ATOM *)inchi_calloc(num_at+1, sizeof(WinData.at0[0]));
|
2453
|
+
WinData.at1 =(inp_ATOM *)inchi_calloc(num_at+1, sizeof(WinData.at1[0]));
|
2454
|
+
|
2455
|
+
if ( dp->nEquLabels && dp->nNumEquSets ) {
|
2456
|
+
WinData.nEquLabels = (AT_NUMB *)inchi_calloc( num_at+1, sizeof(WinData.nEquLabels[0]));
|
2457
|
+
WinData.nNumEquSets = dp->nNumEquSets;
|
2458
|
+
WinData.nCurEquLabel = 0;
|
2459
|
+
WinData.nNewEquLabel = dp->nCurEquLabel;
|
2460
|
+
}
|
2461
|
+
|
2462
|
+
WinData.nFontSize = dp->sdp.nFontSize;
|
2463
|
+
WinData.szTitle = NULL;
|
2464
|
+
/*WinData.szTitle = _strdup(szOutputString);*/ /* for testing INCHI_LIB printing */
|
2465
|
+
if ( inf_at ) {
|
2466
|
+
DuplicateInfoAtomData( &WinData.inf_at_data, inf_at_data);
|
2467
|
+
}
|
2468
|
+
if ( !WinData.at0 || !WinData.at1 || inf_at && !WinData.inf_at_data.at
|
2469
|
+
|| dp->nEquLabels && dp->nNumEquSets && !WinData.nEquLabels
|
2470
|
+
) {
|
2471
|
+
FreeWinData( &WinData );
|
2472
|
+
} else {
|
2473
|
+
memcpy( WinData.at0, at, sizeof(at[0])*num_at );
|
2474
|
+
if ( inf_at )
|
2475
|
+
memcpy( WinData.inf_at_data.at, inf_at, sizeof(inf_at[0])*num_at );
|
2476
|
+
if ( WinData.nEquLabels ) {
|
2477
|
+
memcpy( WinData.nEquLabels, dp->nEquLabels, num_at*sizeof(WinData.nEquLabels[0]));
|
2478
|
+
}
|
2479
|
+
|
2480
|
+
memcpy( WinData.at1, WinData.at0, sizeof(at[0])*num_at );
|
2481
|
+
|
2482
|
+
WinData.num_at = num_at;
|
2483
|
+
WinData.bOrigAtom = dp->sdp.bOrigAtom;
|
2484
|
+
WinData.nTimerId = 0;
|
2485
|
+
WinData.ulDisplTime = dp->sdp.ulDisplTime;
|
2486
|
+
if ( dp->sdp.tdp ) {
|
2487
|
+
WinData.tdp = *dp->sdp.tdp;
|
2488
|
+
}
|
2489
|
+
}
|
2490
|
+
|
2491
|
+
SetWindowLong( hWnd, GWL_USERDATA, (long)&WinData );
|
2492
|
+
|
2493
|
+
ShowWindow(hWnd, SW_SHOWNORMAL /*SW_SHOW*/);
|
2494
|
+
UpdateWindow(hWnd);
|
2495
|
+
|
2496
|
+
|
2497
|
+
/* Message Loop for Display Canon Struct Window */
|
2498
|
+
while( IsWindow(hWnd) ) {
|
2499
|
+
if ( PeekMessage(
|
2500
|
+
&msg, /* pointer to structure for message */
|
2501
|
+
hWnd, /* or NULL,*/ /* handle to window */
|
2502
|
+
0, /* UINT wMsgFilterMin, */ /* first message */
|
2503
|
+
0, /* UINT wMsgFilterMax, */ /* last message */
|
2504
|
+
PM_REMOVE /* UINT wRemoveMsg */ /* removal flags */
|
2505
|
+
) ) {
|
2506
|
+
TranslateMessage( &msg );
|
2507
|
+
DispatchMessage( &msg );
|
2508
|
+
} else {
|
2509
|
+
if ( bSetForeground ) {
|
2510
|
+
ReallySetForegroundWindow( hWnd );
|
2511
|
+
bSetForeground = 0;
|
2512
|
+
}
|
2513
|
+
SleepEx( 10L, TRUE ); /* provides a nice behavior of the app */
|
2514
|
+
}
|
2515
|
+
}
|
2516
|
+
/* deallocate memory */
|
2517
|
+
FreeWinData( &WinData );
|
2518
|
+
/* show console window on the top upon closing hWnd */
|
2519
|
+
ReallySetForegroundWindow( hConsoleWnd );
|
2520
|
+
/* avoid nasty messages about exception 0x5 in Windows dlls. */
|
2521
|
+
UnregisterClass(szWindowClassName, /* address of class name string */
|
2522
|
+
hInstance /* handle of application instance */
|
2523
|
+
);
|
2524
|
+
/* Save window size and position */
|
2525
|
+
if ( WinData.rc.bottom > WinData.rc.top && WinData.rc.right > WinData.rc.left ) {
|
2526
|
+
dp->pdp->rcPict[0] = WinData.rc.left;
|
2527
|
+
dp->pdp->rcPict[1] = WinData.rc.top;
|
2528
|
+
dp->pdp->rcPict[2] = WinData.rc.right-WinData.rc.left;
|
2529
|
+
dp->pdp->rcPict[3] = WinData.rc.bottom-WinData.rc.top;
|
2530
|
+
}
|
2531
|
+
if ( WinData.bEsc ) {
|
2532
|
+
dp->rdp.bEsc = 1;
|
2533
|
+
}
|
2534
|
+
return WinData.bEsc? 27:1;
|
2535
|
+
|
2536
|
+
}
|
2537
|
+
#endif
|
2538
|
+
/****************************************************************************/
|
2539
|
+
void MySleep( unsigned long ms )
|
2540
|
+
{
|
2541
|
+
Sleep( ms );
|
2542
|
+
}
|
2543
|
+
|
2544
|
+
#endif /* } _WIN32 */
|
2545
|
+
#else
|
2546
|
+
int dummyDispStru_c; /* make translation unit non-empty for ANSI-C compatibility */
|
2547
|
+
#endif /* } INCHI_ANSI_ONLY */
|