rino 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Rakefile +1 -1
  2. data/ext/extconf.rb +1 -24
  3. data/ext/libinchi.so +0 -0
  4. data/ext/src/aux2atom.h +120 -39
  5. data/ext/src/comdef.h +3 -3
  6. data/ext/src/dispstru.c +2547 -0
  7. data/ext/src/dispstru.h +73 -0
  8. data/ext/src/extr_ct.h +5 -2
  9. data/ext/src/ichi.h +27 -11
  10. data/ext/src/ichi_bns.c +1800 -254
  11. data/ext/src/ichi_bns.h +205 -4
  12. data/ext/src/ichican2.c +197 -86
  13. data/ext/src/ichicano.c +8 -13
  14. data/ext/src/ichicano.h +2 -2
  15. data/ext/src/ichicans.c +11 -6
  16. data/ext/src/ichicant.h +2 -2
  17. data/ext/src/ichicomn.h +2 -2
  18. data/ext/src/ichicomp.h +19 -4
  19. data/ext/src/ichidrp.h +9 -5
  20. data/ext/src/ichierr.h +5 -3
  21. data/ext/src/ichiisot.c +2 -2
  22. data/ext/src/ichimain.c +461 -0
  23. data/ext/src/ichimain.h +23 -15
  24. data/ext/src/ichimak2.c +6 -6
  25. data/ext/src/ichimake.c +843 -42
  26. data/ext/src/ichimake.h +4 -2
  27. data/ext/src/ichimap1.c +5 -5
  28. data/ext/src/ichimap2.c +2 -2
  29. data/ext/src/ichimap4.c +34 -21
  30. data/ext/src/ichinorm.c +11 -5
  31. data/ext/src/ichinorm.h +3 -2
  32. data/ext/src/ichiparm.c +2 -2
  33. data/ext/src/ichiparm.h +232 -30
  34. data/ext/src/ichiprt1.c +35 -11
  35. data/ext/src/ichiprt2.c +78 -7
  36. data/ext/src/ichiprt3.c +300 -120
  37. data/ext/src/ichiqueu.c +17 -2
  38. data/ext/src/ichiread.c +6932 -0
  39. data/ext/src/ichiring.c +3 -2
  40. data/ext/src/ichiring.h +2 -2
  41. data/ext/src/ichirvr1.c +4891 -0
  42. data/ext/src/ichirvr2.c +6344 -0
  43. data/ext/src/ichirvr3.c +5499 -0
  44. data/ext/src/ichirvr4.c +3177 -0
  45. data/ext/src/ichirvr5.c +1166 -0
  46. data/ext/src/ichirvr6.c +1287 -0
  47. data/ext/src/ichirvr7.c +2319 -0
  48. data/ext/src/ichirvrs.h +882 -0
  49. data/ext/src/ichisize.h +2 -2
  50. data/ext/src/ichisort.c +5 -5
  51. data/ext/src/ichister.c +281 -86
  52. data/ext/src/ichister.h +9 -3
  53. data/ext/src/ichitaut.c +208 -9
  54. data/ext/src/ichitaut.h +13 -11
  55. data/ext/src/ichitime.h +16 -2
  56. data/ext/src/inchicmp.h +107 -0
  57. data/ext/src/inpdef.h +6 -3
  58. data/ext/src/libinchi_wrap.c +912 -0
  59. data/ext/src/lreadmol.h +34 -31
  60. data/ext/src/mode.h +244 -7
  61. data/ext/src/mol2atom.c +1060 -0
  62. data/ext/src/mol2atom.h +31 -0
  63. data/ext/src/readinch.c +239 -0
  64. data/ext/src/readmol.c +28 -0
  65. data/ext/src/{e_readmol.h → readmol.h} +7 -9
  66. data/ext/src/runichi.c +251 -177
  67. data/ext/src/strutil.c +444 -238
  68. data/ext/src/strutil.h +150 -11
  69. data/ext/src/util.c +176 -118
  70. data/ext/src/util.h +15 -3
  71. data/lib/rino.rb +71 -3
  72. data/test/test.rb +33 -4
  73. metadata +22 -34
  74. data/ext/ruby_inchi_main.so +0 -0
  75. data/ext/src/e_0dstereo.c +0 -3014
  76. data/ext/src/e_0dstereo.h +0 -31
  77. data/ext/src/e_comdef.h +0 -57
  78. data/ext/src/e_ctl_data.h +0 -147
  79. data/ext/src/e_ichi_io.c +0 -498
  80. data/ext/src/e_ichi_io.h +0 -40
  81. data/ext/src/e_ichi_parms.c +0 -37
  82. data/ext/src/e_ichi_parms.h +0 -41
  83. data/ext/src/e_ichicomp.h +0 -50
  84. data/ext/src/e_ichierr.h +0 -40
  85. data/ext/src/e_ichimain.c +0 -593
  86. data/ext/src/e_ichisize.h +0 -43
  87. data/ext/src/e_inchi_atom.c +0 -75
  88. data/ext/src/e_inchi_atom.h +0 -33
  89. data/ext/src/e_inpdef.h +0 -41
  90. data/ext/src/e_mode.h +0 -706
  91. data/ext/src/e_mol2atom.c +0 -649
  92. data/ext/src/e_readinch.c +0 -58
  93. data/ext/src/e_readmol.c +0 -54
  94. data/ext/src/e_readstru.c +0 -251
  95. data/ext/src/e_readstru.h +0 -33
  96. data/ext/src/e_util.c +0 -284
  97. data/ext/src/e_util.h +0 -61
  98. data/ext/src/ichilnct.c +0 -286
  99. data/ext/src/inchi_api.h +0 -670
  100. data/ext/src/inchi_dll.c +0 -1480
  101. data/ext/src/inchi_dll.h +0 -34
  102. data/ext/src/inchi_dll_main.c +0 -23
  103. data/ext/src/inchi_dll_main.h +0 -31
  104. data/ext/src/ruby_inchi_main.c +0 -558
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ require 'rake/testtask'
26
26
  require 'rake/rdoctask'
27
27
  require 'rake/gempackagetask'
28
28
 
29
- PKG_VERSION = "0.1.0"
29
+ PKG_VERSION = "0.2.0"
30
30
 
31
31
  PKG_FILES = FileList[
32
32
  "Rakefile", "README",
@@ -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("ruby_inchi_main", "src")
3
+ create_makefile('libinchi', 'src')
Binary file
@@ -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.00
6
- * April 13, 2005
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[4] = -1;
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[4] = -1;
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
- static char sStructMsgXmlErr[] = "<message type=\"error (no InChI)\" value=\"";
1387
- static char sStructMsgXmlErrFatal[] = "<message type=\"fatal (aborted)\" value=\"";
1388
- static char sStructRevXmlRevHdr[] = "<reversibility>";
1389
- static char sStructRevXmlRevAt[] = "<atoms>";
1390
- static char sStructRevXmlRevAtEnd[] = "</atoms>";
1391
- static char sStructRevXmlRevBn[] = "<bonds>";
1392
- static char sStructRevXmlRevBnEnd[] = "</bonds>";
1393
- static char sStructRevXmlRevXYZ[] = "<xyz>";
1394
- static char sStructRevXmlRevXYZEnd[]= "</xyz>";
1395
- static char sStructAuxXml[] = "<identifier.auxiliary-info";
1396
- static char sStructAuxXmlEnd[] = "</identifier.auxiliary-info";
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[4] = -1;
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[4] = -1;
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
 
@@ -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.00
6
- * April 13, 2005
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 */
@@ -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 */