rino 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 */
|