Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : * Copyright (c) 2024 IUPAC and InChI Trust
4 : : */
5 : :
6 : :
7 : : /*
8 : : SortAndPrintINChI and misc. processing (display, tests, error treatment, etc.)
9 : :
10 : : */
11 : :
12 : : #include <stdlib.h>
13 : : #include <string.h>
14 : : #include <stdarg.h>
15 : : #include <errno.h>
16 : : #include <limits.h>
17 : : #include <math.h>
18 : : #include <ctype.h>
19 : :
20 : : #include "mode.h"
21 : :
22 : : #ifndef COMPILE_ANSI_ONLY
23 : : #include <conio.h>
24 : : #endif
25 : :
26 : : #include "ichimain.h"
27 : : #include "ichi_io.h"
28 : : #include "mol_fmt.h"
29 : : #include "ichicant.h"
30 : : #include "inchi_api.h"
31 : : #include "readinch.h"
32 : : #ifdef TARGET_LIB_FOR_WINCHI
33 : : #include "../../../IChI_lib/src/ichi_lib.h"
34 : : #include "inchi_api.h"
35 : : #else
36 : : #include "inchi_gui.h"
37 : : #endif
38 : : #include "readinch.h"
39 : :
40 : : #include "bcf_s.h"
41 : :
42 : : #ifdef TARGET_LIB_FOR_WINCHI
43 : :
44 : : void( *FWPRINT )
45 : : ( const char * format, va_list argptr ) = NULL;
46 : : void( *FWPUSH )
47 : : ( const char *s );
48 : : void( *DRAWDATA )
49 : : ( struct DrawData * pDrawData ) = NULL;
50 : : int( *DRAWDATA_EXISTS )
51 : : ( int nComponent, int nType, int bReconnected ) = NULL;
52 : : struct DrawData * ( *GET_DRAWDATA )
53 : : ( int nComponent, int nType, int bReconnected ) = NULL;
54 : : #endif
55 : :
56 : : /* Local */
57 : : int GetProcessingWarningsOneInChI( INChI *pINChI,
58 : : INP_ATOM_DATA *inp_norm_data,
59 : : char *pStrErrStruct,
60 : : int bNoWarnings);
61 : :
62 : :
63 : :
64 : : /****************************************************************************
65 : : Main InChI serialization procedure
66 : : ****************************************************************************/
67 : 122 : int SortAndPrintINChI( CANON_GLOBALS *pCG,
68 : : INCHI_IOSTREAM *out_file,
69 : : INCHI_IOS_STRING *strbuf,
70 : : INCHI_IOSTREAM *log_file,
71 : : INPUT_PARMS *ip,
72 : : ORIG_ATOM_DATA *orig_inp_data,
73 : : ORIG_ATOM_DATA *prep_inp_data,
74 : : COMP_ATOM_DATA composite_norm_data[INCHI_NUM][TAUT_NUM + 1],
75 : : ORIG_STRUCT *pOrigStruct,
76 : : int num_components[INCHI_NUM],
77 : : int num_non_taut[INCHI_NUM],
78 : : int num_taut[INCHI_NUM],
79 : : INCHI_MODE bTautFlags[INCHI_NUM],
80 : : INCHI_MODE bTautFlagsDone[INCHI_NUM],
81 : : NORM_CANON_FLAGS *pncFlags,
82 : : long num_inp,
83 : : PINChI2 *pINChI[INCHI_NUM],
84 : : PINChI_Aux2 *pINChI_Aux[INCHI_NUM],
85 : : int *pSortPrintINChIFlags,
86 : : unsigned char save_opt_bits )
87 : : {
88 : : INCHI_SORT *pINChISort[INCHI_NUM][TAUT_NUM];
89 : : int j, i, k, k1, ret, ret2, iINChI, max_num_components; /* djb-rwth: ignoring LLVM warning: variable used */
90 : : int INCHI_basic_or_INCHI_reconnected;
91 : : /* djb-rwth: removing redundant variables */
92 : 122 : int bDisconnectedCoord = ( 0 != ( bTautFlagsDone[0] & TG_FLAG_DISCONNECT_COORD_DONE ) );
93 : : int bINChIOutputOptions0, bCurOption, bINChIOutputOptionsCur, bEmbedReconnected;
94 : : static const char szAnnHdr[] = "InChI ANNOTATED CONTENTS";
95 : : #ifdef TARGET_LIB_FOR_WINCHI
96 : : int ikflag = 0;
97 : : out_file->type = INCHI_IOS_TYPE_STRING;
98 : : #endif
99 : :
100 : : /*
101 : : Note:
102 : :
103 : : pINChI[INCHI_BAS] refers to either disconnected or original structure;
104 : : num_components[INCHI_BAS] > 0 if there was input structure
105 : : pINChI[INCHI_REC] refers to the reconnected structure,
106 : : and only if the input structure has been disconnected, that is,
107 : : num_components[INCHI_REC] > 0
108 : : */
109 : :
110 : 122 : ret = 1;
111 : :
112 [ + + ]: 366 : for (i = 0; i < INCHI_NUM; i++)
113 : : {
114 [ + + ]: 732 : for (k = 0; k < TAUT_NUM; k++)
115 : : {
116 : 488 : bTautFlags[i] |= pncFlags->bTautFlags[i][k];
117 : 488 : bTautFlagsDone[i] |= pncFlags->bTautFlagsDone[i][k];
118 : : }
119 : : }
120 : :
121 : : /* djb-rwth: removing redundant code */
122 : :
123 : 122 : max_num_components = 0;
124 [ + + ]: 366 : for (j = 0; j < INCHI_NUM; j++)
125 : : {
126 [ + + ]: 244 : if (max_num_components < num_components[j])
127 : : {
128 : 122 : max_num_components = num_components[j];
129 : : }
130 : : }
131 [ - + ]: 122 : if (max_num_components <= 0)
132 : : {
133 : 0 : max_num_components = 1;
134 : : }
135 : :
136 [ + + ]: 366 : for (j = 0, i = 0; j < INCHI_NUM; j++)
137 : : {
138 [ + + ]: 244 : if (num_components[j])
139 : : {
140 [ + + ]: 366 : for (k1 = 0; k1 < TAUT_NUM; k1++)
141 : : {
142 : 244 : pINChISort[j][k1] =
143 : 244 : (INCHI_SORT *) inchi_calloc( max_num_components,
144 : : sizeof( pINChISort[0][0][0] ) );
145 : 244 : i += !pINChISort[j][k1]; /* number of failed allocatons */
146 : : }
147 : : }
148 : : else
149 : : {
150 [ + + ]: 366 : for (k1 = 0; k1 < TAUT_NUM; k1++)
151 : : {
152 : 244 : pINChISort[j][k1] = NULL; /* keep BC happy */
153 : : }
154 : : }
155 : : }
156 : :
157 [ - + ]: 122 : if (i)
158 : : {
159 : 0 : ret = CT_OUT_OF_RAM;
160 : 0 : goto exit_function;
161 : : }
162 : :
163 [ + + ]: 366 : for (j = 0; j < INCHI_NUM; j++)
164 : : {
165 [ + + ]: 244 : if (!num_components[j])
166 : : {
167 : 122 : continue;
168 : : }
169 : 122 : iINChI = j;
170 : :
171 : : #if ( OUTPUT_CONNECTED_METAL_ONLY == 1 ) /* test: output connected as the only one INChI */
172 : : if (INCHI_BAS == j && num_components[INCHI_REC])
173 : : {
174 : : j = INCHI_REC;
175 : : }
176 : : #endif
177 : :
178 : : /* j = INCHI_BAS; <- for debug only */
179 : : /* for only normal or disconnected coord compounds */
180 : : /* (j=0=INCHI_BAS => normal or disconnected, j=1=INCHI_REC => reconnected */
181 : :
182 [ + + ]: 366 : for (k1 = 0; k1 < TAUT_NUM; k1++)
183 : : {
184 [ + + ]: 566 : for (i = 0; i < num_components[j]; i++)
185 : : {
186 [ + + ]: 966 : for (k = 0; k < TAUT_NUM; k++)
187 : : {
188 : 644 : pINChISort[j][k1][i].pINChI[k] = pINChI[j][i][k];
189 : 644 : pINChISort[j][k1][i].pINChI_Aux[k] = pINChI_Aux[j][i][k];
190 : : }
191 : 322 : pINChISort[j][k1][i].ord_number = i;
192 : : }
193 : : }
194 : :
195 : : /* Sort component INChIs */
196 [ + + ]: 366 : for (k1 = 0; k1 < TAUT_NUM; k1++)
197 : : {
198 [ + + - ]: 244 : switch (k1)
199 : : {
200 : 122 : case TAUT_NON:
201 : 122 : qsort( pINChISort[j][k1],
202 : 122 : num_components[j],
203 : : sizeof( pINChISort[0][0][0] ),
204 : : CompINChINonTaut2 );
205 : 122 : break;
206 : 122 : case TAUT_YES:
207 : 122 : qsort( pINChISort[j][k1],
208 : 122 : num_components[j],
209 : : sizeof( pINChISort[0][0][0] ),
210 : : CompINChITaut2 );
211 : 122 : break;
212 : : }
213 : : }
214 : :
215 : : #ifndef COMPILE_ANSI_ONLY
216 : : /* Find equivalent and wINChI display order;
217 : : use requested in ip->bCompareComponents comparison */
218 : :
219 : : ret = SaveEquComponentsInfoAndSortOrder( iINChI, pINChISort[j],
220 : : num_components,
221 : : orig_inp_data, prep_inp_data,
222 : : #if ( FIX_DALKE_BUGS == 1 )
223 : : composite_norm_data ? composite_norm_data[j] : NULL,
224 : : #else
225 : : composite_norm_data[j],
226 : : #endif
227 : : ip->bCompareComponents );
228 : : if (RETURNED_ERROR( ret ))
229 : : {
230 : : ret = 0;
231 : : goto exit_function;
232 : : }
233 : : else
234 : : {
235 : : ret = 1;
236 : : }
237 : : #endif
238 : : } /* j */
239 : :
240 [ - + ]: 122 : if (!( ip->bINChIOutputOptions & INCHI_OUT_PRINT_OPTIONS ))
241 : : {
242 : : /* Prepare InChI from the structures obtained by
243 : : reversing InChI for returning to the caller */
244 [ # # ]: 0 : for (j = 0; j < INCHI_NUM; j++)
245 : : {
246 [ # # ]: 0 : if (!num_components[j])
247 : : {
248 : 0 : continue;
249 : : }
250 : :
251 : : /* pINChI[iINCHI][iComponent][bTaut] */
252 : : /* j = disconnected/connected */
253 : : /* k1 = sort order for Mobile or Fixed H */
254 : :
255 : 0 : k1 = TAUT_YES; /* in Mobile H order */
256 : : /* store components in Mobile H order */
257 : :
258 [ # # # # ]: 0 : for (i = 0; i < num_components[j] && i < max_num_components; i++) /* djb-rwth: fixing undefined index value / buffer overflow */
259 : : {
260 : :
261 [ # # ]: 0 : if (pINChISort[j][k1][i].pINChI[TAUT_NON] &&
262 [ # # ]: 0 : !pINChISort[j][k1][i].pINChI[TAUT_YES])
263 : : {
264 : : /* make sure Mobile-H is always present */
265 [ # # ]: 0 : for (k = 0; k < TAUT_NUM; k++)
266 : : {
267 [ # # ]: 0 : pINChI[j][i][k] = pINChISort[j][k1][i].pINChI[ALT_TAUT( k )];
268 [ # # ]: 0 : pINChI_Aux[j][i][k] = pINChISort[j][k1][i].pINChI_Aux[ALT_TAUT( k )];
269 : : }
270 : : }
271 : : else
272 : : {
273 [ # # ]: 0 : for (k = 0; k < TAUT_NUM; k++)
274 : : {
275 : 0 : pINChI[j][i][k] = pINChISort[j][k1][i].pINChI[k];
276 : 0 : pINChI_Aux[j][i][k] = pINChISort[j][k1][i].pINChI_Aux[k];
277 : : }
278 : : }
279 : : }
280 : : }
281 : : }
282 : : else
283 : : {
284 : : /* Print InChI string(s) */
285 : 122 : bINChIOutputOptions0 = ip->bINChIOutputOptions & ~INCHI_OUT_PRINT_OPTIONS;
286 : 122 : bEmbedReconnected = ip->bINChIOutputOptions & INCHI_OUT_EMBED_REC;
287 : :
288 [ + + ]: 366 : for (i = 1; i <= 2; i++)
289 : : {
290 : 244 : bCurOption = INCHI_OUT_PLAIN_TEXT;
291 [ + + ]: 244 : if (i == 2)
292 : : {
293 : 122 : bCurOption = INCHI_OUT_PLAIN_TEXT_COMMENTS;
294 : : /* continue; */
295 : : }
296 [ + + ]: 244 : if (!( ip->bINChIOutputOptions & bCurOption ))
297 : : {
298 : 122 : continue;
299 : : }
300 : :
301 : 122 : bINChIOutputOptionsCur = bINChIOutputOptions0 | bCurOption;
302 [ + - ]: 122 : if (i == 1)
303 : : {
304 : : /* output INChI */
305 : 122 : bINChIOutputOptionsCur |= bEmbedReconnected;
306 : : }
307 [ # # ]: 0 : else if (i == 2)
308 : : {
309 : : /* output annotation */
310 : 0 : inchi_ios_print( out_file, "\n==== %s ====\n", szAnnHdr );
311 : : ITRACE_( "\n==== %s ====\n", szAnnHdr );
312 : 0 : bINChIOutputOptionsCur |= bEmbedReconnected;
313 : 0 : bINChIOutputOptionsCur &= ~INCHI_OUT_TABBED_OUTPUT;
314 : : }
315 : : else
316 : : {
317 : 0 : continue;
318 : : }
319 : :
320 : : #if 0 /*^^^#ifdef TARGET_LIB_FOR_WINCHI*/
321 : : inchi_ios_free_str( out_file );
322 : : #endif
323 : :
324 : 122 : INCHI_basic_or_INCHI_reconnected = INCHI_BAS;
325 : :
326 : 122 : ret2 = OutputINChI2( pCG,
327 : : strbuf,
328 : : pINChISort,
329 : : INCHI_basic_or_INCHI_reconnected,
330 : : orig_inp_data,
331 : : pOrigStruct,
332 : : ip,
333 : : bDisconnectedCoord,
334 : : OUT_TN,
335 : : bINChIOutputOptionsCur,
336 : : num_components,
337 : : num_non_taut,
338 : : num_taut,
339 : : out_file,
340 : : log_file,
341 : : num_inp,
342 : : pSortPrintINChIFlags,
343 : : save_opt_bits );
344 : :
345 : 122 : ret &= ret2;
346 : :
347 : : #ifdef TARGET_LIB_FOR_WINCHI
348 : : /* always calculate InChIKey */
349 : : winchi_calc_inchikey( ret, &ikflag, ip, out_file, log_file );
350 : : /*push_to_winchi_text_window( out_file );
351 : : inchi_ios_flush( out_file );*/
352 : :
353 : : #endif
354 : :
355 [ - + ]: 122 : if (!ret)
356 : : {
357 : 0 : break;
358 : : }
359 : : } /* i */
360 : : }
361 : :
362 : :
363 : 122 : exit_function:
364 : :
365 [ + + ]: 366 : for (j = 0; j < INCHI_NUM; j++)
366 : : {
367 [ + + ]: 732 : for (k1 = 0; k1 < TAUT_NUM; k1++) /* djb-rwth: removing redundant code */
368 : : {
369 [ + + ]: 488 : if (pINChISort[j][k1])
370 : : {
371 [ + - ]: 244 : inchi_free( pINChISort[j][k1] );
372 : : }
373 : : }
374 : : }
375 : :
376 : :
377 [ + - ]: 122 : ret = ret ? 0 : _IS_FATAL;
378 : :
379 : 122 : return ret;
380 : : }
381 : :
382 : :
383 : : /****************************************************************************
384 : : Specific to winchi-1 calculation of InChIKey
385 : : ****************************************************************************/
386 : 0 : void winchi_calc_inchikey( int ret,
387 : : int *ikflag,
388 : : INPUT_PARMS *ip,
389 : : INCHI_IOSTREAM *out_file,
390 : : INCHI_IOSTREAM *log_file )
391 : : {
392 : : char ik_string[256]; /* Resulting InChIKey string */
393 : 0 : int ik_ret = 0; /* InChIKey-calc result code */
394 : 0 : int xhash1 = 0, xhash2 = 0;
395 : : char szXtra1[256], szXtra2[256];
396 : 0 : size_t slen = out_file->s.nUsedLength;
397 : 0 : char *buf = NULL;
398 : :
399 : 0 : ( *ikflag )++;
400 [ # # ]: 0 : if (*ikflag != 1)
401 : : {
402 : 0 : return;
403 : : }
404 : :
405 [ # # ]: 0 : if (ret == 0)
406 : : {
407 : 0 : inchi_ios_flush( out_file );
408 : 0 : return;
409 : : }
410 : :
411 : 0 : extract_inchi_substring( &buf, out_file->s.pStr, slen );
412 : :
413 : : /* Calculate and print InChIKey */
414 [ # # ]: 0 : if (NULL != buf)
415 : : {
416 : 0 : xhash1 = xhash2 = 0;
417 [ # # ]: 0 : if (( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1 ) ||
418 [ # # ]: 0 : ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ))
419 : : {
420 : 0 : xhash1 = 1;
421 : : }
422 [ # # ]: 0 : if (( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2 ) ||
423 [ # # ]: 0 : ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ))
424 : : {
425 : 0 : xhash2 = 1;
426 : : }
427 : 0 : ik_ret = GetINCHIKeyFromINCHI( buf, xhash1, xhash2, ik_string, szXtra1, szXtra2 );
428 [ # # ]: 0 : inchi_free( buf );
429 : : }
430 : : else
431 : : {
432 : 0 : ik_ret = 3;
433 : : }
434 : :
435 [ # # ]: 0 : if (ik_ret == INCHIKEY_OK)
436 : : {
437 : : /* NB: correctly treat tabbed output with InChIKey & hash extensions */
438 : 0 : char csep = '\n';
439 [ # # ]: 0 : if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)
440 : : {
441 : 0 : csep = '\t';
442 : : }
443 : 0 : inchi_ios_print( out_file, "InChIKey=%-s", ik_string );
444 [ # # ]: 0 : if (xhash1)
445 : : {
446 : 0 : inchi_ios_print( out_file, "%cXHash1=%-s", csep, szXtra1 );
447 : : }
448 [ # # ]: 0 : if (xhash2)
449 : : {
450 : 0 : inchi_ios_print( out_file, "%cXHash2=%-s", csep, szXtra2 );
451 : : }
452 : 0 : inchi_ios_print( out_file, "\n" );
453 : : }
454 : : else
455 : : {
456 : 0 : inchi_ios_print( log_file, "Warning (Could not compute InChIKey)\n" ); /*: ", num_inp);*/
457 : : }
458 : : /*inchi_ios_flush(out_file);*/
459 : :
460 : 0 : return;
461 : : }
462 : :
463 : :
464 : : #ifndef COMPILE_ANSI_ONLY /* { */
465 : :
466 : :
467 : : /****************************************************************************/
468 : : int SaveEquComponentsInfoAndSortOrder( int iINChI,
469 : : INCHI_SORT *pINChISort[TAUT_NUM],
470 : : int *num_components,
471 : : ORIG_ATOM_DATA *orig_inp_data,
472 : : ORIG_ATOM_DATA *prep_inp_data,
473 : : COMP_ATOM_DATA composite_norm_data[TAUT_NUM + 1],
474 : : int bCompareComponents )
475 : : {
476 : : int nRet = 0, i, k, nNumDeleted;
477 : : int bCompareIsotopic, bCompareTaut, bCompareAlt;
478 : : ORIG_ATOM_DATA *inp_data = NULL;
479 : :
480 : : /* Equivalent components and sorting order */
481 : : /* bCompareComponents: bit = 1 => compare */
482 : : /* bit = 2 => compare non-isotopic */
483 : : /* bit = 4 => compare non-tautomeric */
484 : :
485 : : if (num_components[iINChI] <= 1)
486 : : {
487 : : return 0;
488 : : }
489 : :
490 : : #ifdef TARGET_LIB_FOR_WINCHI
491 : : if (!DRAWDATA)
492 : : return 0;
493 : : #endif
494 : :
495 : : if (!( bCompareComponents & CMP_COMPONENTS ))
496 : : {
497 : : return 0;
498 : : }
499 : :
500 : : bCompareIsotopic = !( bCompareComponents & CMP_COMPONENTS_NONISO );
501 : :
502 : : bCompareTaut = ( bCompareComponents & CMP_COMPONENTS_NONTAUT )
503 : : ? TAUT_NON
504 : : : TAUT_YES;
505 : :
506 : : bCompareAlt = ALT_TAUT( bCompareTaut );
507 : :
508 : : if (num_components[iINChI] > 1)
509 : : {
510 : : if (prep_inp_data[iINChI].bSavedInINCHI_LIB[iINChI] &&
511 : : prep_inp_data[iINChI].bPreprocessed[iINChI])
512 : : {
513 : : inp_data = prep_inp_data + iINChI;
514 : : }
515 : : else if (orig_inp_data->bSavedInINCHI_LIB[iINChI] &&
516 : : !orig_inp_data->bPreprocessed[iINChI])
517 : : {
518 : : inp_data = orig_inp_data;
519 : : }
520 : : else
521 : : {
522 : : inp_data = NULL;
523 : : }
524 : :
525 : : if (inp_data && !inp_data->nEquLabels &&
526 : : !prep_inp_data[iINChI].nSortedOrder)
527 : : {
528 : : int i1, i2, nSet;
529 : : AT_NUMB nAtNo;
530 : : AT_NUMB nNumAtoms = (AT_NUMB) inp_data->num_inp_atoms;
531 : :
532 : : if (( prep_inp_data[iINChI].nSortedOrder =
533 : : (AT_NUMB *) inchi_calloc( (long long)num_components[iINChI] + 1,
534 : : sizeof( prep_inp_data[0].nSortedOrder[0] ) ) )) /* djb-rwth: cast operator added */
535 : : {
536 : : inp_data->nNumEquSets = 0;
537 : :
538 : : for (i1 = 0, nSet = 0; i1 < num_components[iINChI]; i1 = i2)
539 : : {
540 : : nNumDeleted =
541 : : ( pINChISort[bCompareTaut][i1].pINChI[bCompareTaut] &&
542 : : pINChISort[bCompareTaut][i1].pINChI[bCompareTaut]->bDeleted );
543 : :
544 : : for (i2 = i1 + 1; i2 < num_components[iINChI]; i2++)
545 : : {
546 : : /* isotopic/non-isotopic comparison does not separate equivalent components */
547 : : if (CompINChI2( pINChISort[bCompareTaut] + i1,
548 : : pINChISort[bCompareTaut] + i2,
549 : : bCompareTaut, bCompareIsotopic ))
550 : : {
551 : : break;
552 : : }
553 : : else
554 : : {
555 : : nNumDeleted +=
556 : : ( pINChISort[bCompareTaut][i2].pINChI[bCompareTaut] &&
557 : : pINChISort[bCompareTaut][i2].pINChI[bCompareTaut]->bDeleted );
558 : : }
559 : : }
560 : :
561 : : if (i2 - i1 - nNumDeleted > 1)
562 : : {
563 : : if (inp_data->nEquLabels ||
564 : : ( inp_data->nEquLabels =
565 : : (AT_NUMB *) inchi_calloc( (long long)inp_data->num_inp_atoms + 1,
566 : : sizeof( inp_data->nEquLabels[0] ) ) )) /* djb-rwth: cast operator added */
567 : : {
568 : : nSet++;
569 : : /* found i2-i1 equivalent components && */
570 : : /* memory has been allocated */
571 : : for (i = i1; i < i2; i++)
572 : : {
573 : : INChI_Aux *pINChI_Aux;
574 : : int aux_test;
575 : :
576 : : if (pINChISort[bCompareTaut][i].pINChI[bCompareTaut] &&
577 : : pINChISort[bCompareTaut][i].pINChI[bCompareTaut]->bDeleted)
578 : : continue;
579 : :
580 : : aux_test =
581 : : ( pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut] &&
582 : : pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut]->nNumberOfAtoms );
583 : :
584 : : pINChI_Aux =
585 : : aux_test ? pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut]
586 : : : ( pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt] &&
587 : : pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt]->nNumberOfAtoms )
588 : : ? pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt]
589 : : : (INChI_Aux *) NULL;
590 : :
591 : : if (pINChI_Aux && pINChI_Aux->nOrigAtNosInCanonOrd)
592 : : {
593 : : for (k = 0; k < pINChI_Aux->nNumberOfAtoms; k++)
594 : : {
595 : : if (( nAtNo = pINChI_Aux->nOrigAtNosInCanonOrd[k] ) &&
596 : : nAtNo <= nNumAtoms)
597 : : {
598 : : inp_data->nEquLabels[nAtNo - 1] = nSet;
599 : : }
600 : : }
601 : : }
602 : : }
603 : : }
604 : : else
605 : : {
606 : : return CT_OUT_OF_RAM;
607 : : }
608 : : }
609 : : }
610 : :
611 : : nRet |= nSet ? 1 : 0;
612 : : }
613 : : else
614 : : {
615 : : return CT_OUT_OF_RAM;
616 : : }
617 : :
618 : : inp_data->nNumEquSets = nSet;
619 : : /* output order */
620 : : prep_inp_data[iINChI].nSortedOrder[0] = 0;
621 : : for (i1 = 0; i1 < num_components[iINChI]; i1++)
622 : : {
623 : : prep_inp_data[iINChI].nSortedOrder[i1 + 1] =
624 : : pINChISort[TAUT_YES][i1].ord_number + 1;
625 : : }
626 : :
627 : : #ifdef TARGET_LIB_FOR_WINCHI /* { */
628 : : if (DRAWDATA && GET_DRAWDATA &&
629 : : inp_data->nNumEquSets > 0 &&
630 : : inp_data->nEquLabels)
631 : : {
632 : : int nType = inp_data->bPreprocessed[iINChI]
633 : : ? COMPONENT_ORIGINAL_PREPROCESSED
634 : : : COMPONENT_ORIGINAL;
635 : :
636 : : struct DrawData *pDrawData = GET_DRAWDATA( 0, nType, iINChI );
637 : : if (pDrawData &&
638 : : pDrawData->pWindowData &&
639 : : !pDrawData->pWindowData->nEquLabels)
640 : : {
641 : : /* copy equivalence data from inp_data */
642 : : /* to pDrawData->pWindowData */
643 : : if (inp_data->nEquLabels &&
644 : : ( pDrawData->pWindowData->nEquLabels =
645 : : (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
646 : : sizeof( inp_data->nEquLabels[0] ) ) ))
647 : : {
648 : : memcpy( pDrawData->pWindowData->nEquLabels,
649 : : inp_data->nEquLabels,
650 : : inp_data->num_inp_atoms *
651 : : sizeof( inp_data->nEquLabels[0] ) );
652 : : pDrawData->pWindowData->nNumEquSets =
653 : : inp_data->nNumEquSets;
654 : : pDrawData->pWindowData->nCurEquLabel = 0;
655 : : }
656 : : }
657 : : }
658 : :
659 : : #endif /* } TARGET_LIB_FOR_WINCHI */
660 : : }
661 : : }
662 : :
663 : : return nRet;
664 : : }
665 : :
666 : :
667 : : /****************************************************************************/
668 : : int DisplayTheWholeCompositeStructure( struct tagCANON_GLOBALS *pCG,
669 : : struct tagINCHI_CLOCK *ic,
670 : : INPUT_PARMS *ip,
671 : : struct tagStructData *sd,
672 : : long num_inp,
673 : : int iINChI,
674 : : PINChI2 *pINChI2,
675 : : PINChI_Aux2 *pINChI_Aux2,
676 : : ORIG_ATOM_DATA *orig_inp_data,
677 : : ORIG_ATOM_DATA *prep_inp_data,
678 : : COMP_ATOM_DATA composite_norm_data[TAUT_NUM + 1] )
679 : : {
680 : : ORIG_ATOM_DATA *inp_data = NULL;
681 : : int jj, j, k, err = 0, nNumIntermediateTaut = 0, bDisplayTaut;
682 : : char szTitle[256];
683 : : int nNumTautComponents, m;
684 : : int bCompareIsotopic = !( ip->bCompareComponents & CMP_COMPONENTS_NONISO );
685 : : int bCompareTaut = ( ip->bCompareComponents & CMP_COMPONENTS_NONTAUT ) ? TAUT_NON : TAUT_YES;
686 : :
687 : : if (ip->bCompareComponents & CMP_COMPONENTS)
688 : : {
689 : : if (prep_inp_data[iINChI].bSavedInINCHI_LIB[iINChI] && prep_inp_data[iINChI].bPreprocessed[iINChI])
690 : : {
691 : : inp_data = prep_inp_data + iINChI;
692 : : }
693 : : else if (orig_inp_data->bSavedInINCHI_LIB[iINChI] && !orig_inp_data->bPreprocessed[iINChI])
694 : : {
695 : : inp_data = orig_inp_data;
696 : : }
697 : : }
698 : :
699 : : /**************************************************************************
700 : : * display from one up to 4 structure pictures-results for all components *
701 : : * Enable buttons: *
702 : : * BN (non-tautomeric non-isotopic): inp_norm_data[0]->bExists *
703 : : * TN (tautomeric non-isotopic): inp_norm_data[1]->bExists *
704 : : * BI (non-tautomeric isotopic): inp_norm_data[0]->bExists && *
705 : : * inp_norm_data[0]->bHasIsotopicLayer *
706 : : * TI (tautomeric isotopic): inp_norm_data[1]->bExists && *
707 : : * inp_norm_data[1]->bHasIsotopicLayer *
708 : : **************************************************************************/
709 : :
710 : : for ( jj = 0;
711 : : ip->bDisplayCompositeResults && !sd->bUserQuitComponentDisplay && jj <= TAUT_INI;
712 : : jj++)
713 : : {
714 : : j = ( jj == 0 )
715 : : ? TAUT_NON : ( jj == 1 ) ? TAUT_INI : ( jj == 2 ) ? TAUT_YES : -1;
716 : :
717 : : if (j < 0)
718 : : {
719 : : continue;
720 : : }
721 : :
722 : : if (composite_norm_data[j].bExists &&
723 : : composite_norm_data[j].num_components > 1)
724 : : {
725 : :
726 : : bDisplayTaut = ( !( ip->nMode & REQ_MODE_BASIC ) && !j ) ? -1 : j;
727 : : nNumTautComponents = 0;
728 : : if (bDisplayTaut)
729 : : {
730 : : /* find whether the structure is actually tautomeric */
731 : : for (m = 0; m < composite_norm_data[TAUT_YES].num_components; m++)
732 : : {
733 : : if (!pINChI2[m][TAUT_YES])
734 : : {
735 : : continue;
736 : : }
737 : : if (pINChI2[m][TAUT_YES]->bDeleted ||
738 : : pINChI2[m][TAUT_YES]->lenTautomer > 0)
739 : : {
740 : : nNumTautComponents++;
741 : : }
742 : : }
743 : : }
744 : :
745 : : for (k = 0;
746 : : k <= composite_norm_data[j].bHasIsotopicLayer && !sd->bUserQuitComponentDisplay;
747 : : k++)
748 : : {
749 : : /* added number of components, added another format */
750 : : /* for a single component case - DCh */
751 : : int bMobileH = ( bDisplayTaut > 0 && nNumTautComponents );
752 : : sprintf(szTitle, "%s Structure #%ld%s%s.%s%s%s%s%s",
753 : : j == TAUT_INI ? "Preprocessed" : "Result for", num_inp,
754 : : bMobileH ? ", mobile H" :
755 : : bDisplayTaut == 0 ? ", fixed H" : "",
756 : : /*j? ", mobile H":", fixed H",*/
757 : : k ? ", isotopic" : "",
758 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue),
759 : : iINChI ? " (Reconnected)" : "");
760 : : #ifndef TARGET_LIB_FOR_WINCHI
761 : : /****** Display composite Result structure **************/
762 : : nNumIntermediateTaut += ( j == TAUT_INI );
763 : : /* display TAUT_INI (preprocessed) only once */
764 : : if (j != TAUT_INI || nNumIntermediateTaut == 1)
765 : : {
766 : : err =
767 : : DisplayCompositeStructure( pCG,
768 : : composite_norm_data,
769 : : orig_inp_data->polymer,
770 : : j == TAUT_INI ? 1 : k,
771 : : /* bIsotopic*/
772 : : j, /*tautomeric*/
773 : : j == TAUT_INI ? NULL
774 : : : pINChI2,
775 : : j == TAUT_INI ? NULL
776 : : : pINChI_Aux2,
777 : : ip->bAbcNumbers,
778 : : &ip->dp,
779 : : ip->nMode,
780 : : szTitle );
781 : : }
782 : : if ((sd->bUserQuitComponentDisplay = ( err == ESC_KEY ))) /* djb-rwth: addressing LLVM warning */
783 : : {
784 : : break;
785 : : }
786 : :
787 : : if (inp_data &&
788 : : inp_data->nEquLabels &&
789 : : inp_data->nNumEquSets &&
790 : : !sd->bUserQuitComponentDisplay &&
791 : : ( ( j == bCompareTaut || (bCompareTaut && j == TAUT_INI) ) ||
792 : : (bCompareTaut && !composite_norm_data[bCompareTaut].bExists) ) &&
793 : : ( k == bCompareIsotopic || (bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer) ) /* djb-rwth: addressing LLVM warnings */
794 : : ) /* djb-rwth: addressing LLVM warning */
795 : : {
796 : : AT_NUMB nEquSet;
797 : : int bDisplaySaved = ip->bDisplay;
798 : :
799 : : /****** Display Equ Sets of composite Result structure **************/
800 : : for (nEquSet = 1;
801 : : nEquSet <= inp_data->nNumEquSets;
802 : : nEquSet++)
803 : : {
804 : : sprintf(szTitle, "Equ set %d of %d, %s Structure #%ld%s%s.%s%s%s%s%s",
805 : : nEquSet, inp_data->nNumEquSets,
806 : : j == TAUT_INI ? "Preprocessed" : "Result for",
807 : : num_inp,
808 : : (bDisplayTaut > 0 && nNumTautComponents) ? ", mobile H" : bDisplayTaut == 0 ? ", fixed H" : "",
809 : : /*j? ", mobile H":", fixed H",*/
810 : : k ? ", isotopic" : "",
811 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
812 : : ip->dp.nEquLabels = inp_data->nEquLabels;
813 : : ip->dp.nCurEquLabel = nEquSet;
814 : : ip->dp.nNumEquSets = inp_data->nNumEquSets;
815 : : ip->bDisplay = 1; /* force display if it was not requested */
816 : : err = DisplayCompositeStructure( pCG,
817 : : composite_norm_data,
818 : : inp_data->polymer,
819 : : k, j,
820 : : pINChI2, pINChI_Aux2,
821 : : ip->bAbcNumbers,
822 : : &ip->dp,
823 : : ip->nMode,
824 : : szTitle );
825 : : ip->dp.nEquLabels = NULL;
826 : : ip->dp.nCurEquLabel = 0;
827 : : ip->dp.nNumEquSets = 0;
828 : : ip->bDisplay = bDisplaySaved; /* restore display option */
829 : :
830 : : if ((sd->bUserQuitComponentDisplay = ( err == ESC_KEY ))) /* djb-rwth: addressing LLVM warning */
831 : : {
832 : : break;
833 : : }
834 : : }
835 : : }
836 : : #else
837 : : if (DRAWDATA && j <= TAUT_YES)
838 : : {
839 : : struct DrawData vDrawData;
840 : : vDrawData.pWindowData =
841 : : CreateWinDataComposite_( pCG,
842 : : composite_norm_data,
843 : : k,
844 : : j,
845 : : pINChI2,
846 : : pINChI_Aux2,
847 : : ip->bAbcNumbers,
848 : : &ip->dp,
849 : : ip->nMode );
850 : :
851 : : /* vDrawData.pWindowData = CreateWinData_( composite_norm_data[j].at, composite_norm_data[j].num_at,
852 : : k, j, pINChI[i], pINChI_Aux[i],ip->bAbcNumbers, &ip->dp, ip->nMode ); */
853 : :
854 : : if (vDrawData.pWindowData != NULL)
855 : : {
856 : : int nType;
857 : : vDrawData.nComponent = 0;
858 : : if (j == 0)
859 : : nType = ( k == 0 ) ? COMPONENT_BN : COMPONENT_BI;
860 : : else
861 : : nType = ( k == 0 ) ? COMPONENT_TN : COMPONENT_TI;
862 : : vDrawData.nType = nType;
863 : : vDrawData.bReconnected = iINChI; /* 0=>main; 1=>reconnected */
864 : : vDrawData.szTitle = inchi__strdup( szTitle );
865 : : vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
866 : : if (inp_data && inp_data->nEquLabels &&
867 : : inp_data->nNumEquSets &&
868 : : ( j == bCompareTaut || bCompareTaut && !composite_norm_data[bCompareTaut].bExists ) &&
869 : : ( k == bCompareIsotopic || bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer ) &&
870 : : ( vDrawData.pWindowData->nEquLabels = (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
871 : : sizeof( inp_data->nEquLabels[0] ) ) ))
872 : : {
873 : : memcpy( vDrawData.pWindowData->nEquLabels, inp_data->nEquLabels,
874 : : inp_data->num_inp_atoms * sizeof( inp_data->nEquLabels[0] ) );
875 : : vDrawData.pWindowData->nNumEquSets = inp_data->nNumEquSets;
876 : : vDrawData.pWindowData->nCurEquLabel = 0;
877 : : }
878 : : DRAWDATA( &vDrawData );
879 : : }
880 : : }
881 : : else if (DRAWDATA && GET_DRAWDATA && j == TAUT_INI)
882 : : {
883 : : struct DrawData vDrawData;
884 : : struct DrawData *pDrawData;
885 : :
886 : : if (!( ip->bCompareComponents & CMP_COMPONENTS ) ||
887 : : ( ip->bCompareComponents & CMP_COMPONENTS_NONTAUT ) ||
888 : : !k != !composite_norm_data[j].bHasIsotopicLayer)
889 : : {
890 : :
891 : : continue;
892 : : }
893 : : vDrawData.pWindowData =
894 : : CreateWinDataComposite_( pCG,
895 : : composite_norm_data,
896 : : 1 /*k*/,
897 : : j,
898 : : NULL,
899 : : NULL,
900 : : ip->bAbcNumbers,
901 : : &ip->dp,
902 : : ip->nMode );
903 : :
904 : :
905 : :
906 : : if (vDrawData.pWindowData != NULL)
907 : : {
908 : : int nType = COMPONENT_ORIGINAL_PREPROCESSED;
909 : : pDrawData = GET_DRAWDATA( 0, nType, iINChI );
910 : : if (pDrawData)
911 : : {
912 : : FreeDrawData( pDrawData );
913 : : pDrawData->pWindowData = vDrawData.pWindowData;
914 : : vDrawData.pWindowData = NULL;
915 : : }
916 : : else
917 : : {
918 : : pDrawData = &vDrawData;
919 : : }
920 : :
921 : : /* vDrawData.pWindowData = CreateWinData_( composite_norm_data[j].at, composite_norm_data[j].num_at,
922 : : k, j, pINChI[i], pINChI_Aux[i],ip->bAbcNumbers, &ip->dp, ip->nMode ); */
923 : :
924 : : pDrawData->nComponent = 0;
925 : : pDrawData->nType = nType;
926 : : pDrawData->bReconnected = iINChI; /* 0=>main; 1=>reconnected */
927 : : pDrawData->szTitle = inchi__strdup( szTitle );
928 : : pDrawData->pWindowData->szTitle = inchi__strdup( szTitle );
929 : : if (inp_data && inp_data->nEquLabels &&
930 : : inp_data->nNumEquSets &&
931 : : /*(j == bCompareTaut || bCompareTaut && !composite_norm_data[bCompareTaut].bExists) &&*/
932 : : /*(k == bCompareIsotopic || bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer) &&*/
933 : : ( pDrawData->pWindowData->nEquLabels = (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
934 : : sizeof( inp_data->nEquLabels[0] ) ) ))
935 : : {
936 : : memcpy( pDrawData->pWindowData->nEquLabels,
937 : : inp_data->nEquLabels,
938 : : inp_data->num_inp_atoms * sizeof( inp_data->nEquLabels[0] ) );
939 : : pDrawData->pWindowData->nNumEquSets = inp_data->nNumEquSets;
940 : : pDrawData->pWindowData->nCurEquLabel = 0;
941 : : }
942 : : if (pDrawData == &vDrawData)
943 : : {
944 : : DRAWDATA( pDrawData ); /* there was no prepocessed structure */
945 : : }
946 : : }
947 : : }
948 : :
949 : : #endif /* #ifndef TARGET_LIB_FOR_WINCHI */
950 : : }
951 : : }
952 : : }
953 : :
954 : : return err;
955 : : }
956 : :
957 : :
958 : : /****************************************************************************/
959 : : int DisplayTheWholeStructure( struct tagCANON_GLOBALS *pCG,
960 : : struct tagINCHI_CLOCK *ic,
961 : : STRUCT_DATA *sd,
962 : : INPUT_PARMS *ip,
963 : : char *szTitle,
964 : : INCHI_IOSTREAM *inp_file,
965 : : INCHI_IOSTREAM *log_file,
966 : : ORIG_ATOM_DATA *orig_inp_data,
967 : : long num_inp,
968 : : int iINChI,
969 : : int bShowStruct,
970 : : int bINCHI_LIB_Flag )
971 : : {
972 : :
973 : : int bDisplayEqu = 0;
974 : :
975 : : #ifndef TARGET_LIB_FOR_WINCHI
976 : :
977 : : /* Displaying equivalent input structures when disconnection has been done: */
978 : : /* in case of TARGET_LIB_FOR_WINCHI equivalence info is always unknown here and bOriginalReconnected=0 */
979 : :
980 : : int bOriginalReconnected = iINChI < 0 &&
981 : : orig_inp_data && orig_inp_data->nEquLabels &&
982 : : ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) &&
983 : : ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD );
984 : :
985 : : const char *lpszType =
986 : : bOriginalReconnected ? " (Reconnected)"
987 : : : ( iINChI < 0 ) ? ""
988 : : : ( iINChI == INCHI_BAS ) ? " (Preprocessed)"
989 : : : ( iINChI == INCHI_REC ) ? " (Reconnected)"
990 : : : ""; /* djb-rwth: ignoring LLVM warning: variable used */
991 : :
992 : : int err = 0; /* djb-rwth: ignoring LLVM warning: variable used */
993 : :
994 : : /* Display the original structure */
995 : :
996 : : bDisplayEqu = bShowStruct && ip->bDisplay &&
997 : : ip->dp.nEquLabels && 0 < ip->dp.nCurEquLabel && ip->dp.nCurEquLabel <= ip->dp.nNumEquSets;
998 : : #else
999 : : if (!DRAWDATA || !DRAWDATA_EXISTS)
1000 : : return 0;
1001 : : #endif
1002 : :
1003 : :
1004 : : #if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY)
1005 : : /* Ask the user whether to process the input structure or quit*/
1006 : : if (ip->bDisplay && inp_file->f != stdin)
1007 : : {
1008 : : if (user_quit( ic, bDisplayEqu ? "Enter=Display identical components, Esc=Stop ?"
1009 : : : "Enter=Display, Esc=Stop ?",
1010 : : ip->ulDisplTime ))
1011 : : {
1012 : : sd->bUserQuit = 1;
1013 : : goto exit_function;
1014 : : }
1015 : : }
1016 : : #endif
1017 : :
1018 : : /*
1019 : : * Display the whole input structure in console app
1020 : : */
1021 : :
1022 : : /* #ifndef TARGET_LIB_FOR_WINCHI */
1023 : :
1024 : : #if ( !defined( TARGET_LIB_FOR_WINCHI ) && !defined(TARGET_EXE_STANDALONE) )
1025 : : if (bShowStruct && ip->bDisplay)
1026 : : {
1027 : : if (bDisplayEqu)
1028 : : {
1029 : : sprintf( szTitle, " Equ Set %d of %d, Input Structure #%ld.%s%s%s%s%s",
1030 : : ip->dp.nCurEquLabel, ip->dp.nNumEquSets,
1031 : : num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), lpszType );
1032 : : }
1033 : : else
1034 : : {
1035 : : sprintf( szTitle, "Input Structure #%ld.%s%s%s%s%s", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), lpszType );
1036 : : }
1037 : : err = DisplayStructure( orig_inp_data->at, orig_inp_data->num_inp_atoms,
1038 : : orig_inp_data->polymer,
1039 : : 0, 1, 0, NULL, 1/*isotopic*/, 0/*taut*/, NULL, NULL,
1040 : : ip->bAbcNumbers, &ip->dp, ip->nMode, szTitle );
1041 : : sd->bUserQuitComponent = ( err == ESC_KEY );
1042 : : if (!err)
1043 : : {
1044 : : inchi_fprintf( stderr, "Cannot display the structure\n" );
1045 : : }
1046 : : }
1047 : : if (!bDisplayEqu)
1048 : : {
1049 : : /* console output progress report */
1050 : : if (ip->bDisplay && !sd->bUserQuitComponent)
1051 : : {
1052 : : if (iINChI == 1)
1053 : : {
1054 : : if (ip->bDisplay)
1055 : : inchi_ios_eprint( log_file, "Processing (rec) structure #%ld.%s%s%s%s...\n", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1056 : : else
1057 : : inchi_fprintf( stderr, "Processing (rec) structure #%ld.%s%s%s%s...\r", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1058 : : }
1059 : : else
1060 : : {
1061 : : if (ip->bDisplay)
1062 : : inchi_ios_eprint( log_file, "Processing structure #%ld.%s%s%s%s...\n", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1063 : : else
1064 : : inchi_fprintf( stderr, "Processing structure #%ld.%s%s%s%s...\r", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1065 : : }
1066 : : }
1067 : : }
1068 : : #endif
1069 : :
1070 : :
1071 : : /*
1072 : : * Store the whole input structure in GUI application
1073 : : */
1074 : :
1075 : : #ifdef TARGET_LIB_FOR_WINCHI
1076 : : if (ip->bDisplay && bINCHI_LIB_Flag)
1077 : : #else
1078 : : if (( ip->bDisplay || ( ip->bCompareComponents & CMP_COMPONENTS ) ) && bINCHI_LIB_Flag)
1079 : : #endif
1080 : :
1081 : : {
1082 : : int bBit, k, bReconnected, nComponent, bPreprocessed;
1083 : :
1084 : : for (bBit = 1, k = 0; k < 8; k++, bBit <<= 1)
1085 : : {
1086 : : /******************************************************************************
1087 : : * bReconnected = k%2 (0 or 1)
1088 : : * nComponent = k/4 (0 or 1)
1089 : : * bPreprocessed = (k/2)%2 (0 or 1)
1090 : : ******************************************************************************/
1091 : : if (!( bINCHI_LIB_Flag & bBit ))
1092 : : {
1093 : : continue;
1094 : : }
1095 : :
1096 : : bReconnected = k % 2;
1097 : : nComponent = k / 4;
1098 : : bPreprocessed = ( ( k / 2 ) % 2 );
1099 : :
1100 : : sprintf(szTitle, "%s Structure #%ld.%s%s%s%s",
1101 : : bPreprocessed ? "Preprocessed" : bReconnected ? "Reconnected" : "Input",
1102 : : num_inp,
1103 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));
1104 : :
1105 : : #ifdef TARGET_LIB_FOR_WINCHI
1106 : : if (DRAWDATA && DRAWDATA_EXISTS)
1107 : : {
1108 : : struct DrawData vDrawData;
1109 : : int nType = bPreprocessed ? COMPONENT_ORIGINAL_PREPROCESSED : COMPONENT_ORIGINAL;
1110 : : if (DRAWDATA_EXISTS( nComponent, bPreprocessed, bReconnected ))
1111 : : {
1112 : : /*
1113 : : TEMPORARILY DISABLED TO MAKE WINCHI TREAT SOME POLYMERS
1114 : : sd->nErrorType = _IS_FATAL;
1115 : : sd->nErrorCode = CT_UNKNOWN_ERR;
1116 : : return -1;
1117 : : */
1118 : : }
1119 : : vDrawData.pWindowData = CreateWinData_( pCG,
1120 : : orig_inp_data->at,
1121 : : orig_inp_data->num_inp_atoms,
1122 : : 0,
1123 : : 1 /* bAdd_DT_to_num_H */,
1124 : : 0,
1125 : : NULL,
1126 : : 1,
1127 : : 0,
1128 : : NULL,
1129 : : NULL,
1130 : : ip->bAbcNumbers,
1131 : : &ip->dp,
1132 : : ip->nMode );
1133 : : if (vDrawData.pWindowData != NULL)
1134 : : {
1135 : : vDrawData.nComponent = nComponent;
1136 : : vDrawData.nType = nType; /* COMPONENT_ORIGINAL or COMPONENT_ORIGINAL_PREPROCESSED */
1137 : : vDrawData.bReconnected = bReconnected; /* 0=>main; 1=>reconnected */
1138 : : vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
1139 : : vDrawData.szTitle = inchi__strdup( szTitle );
1140 : : DRAWDATA( &vDrawData );
1141 : : if (!nComponent)
1142 : : {
1143 : : /* keep track of saved INCHI_LIB data */
1144 : : orig_inp_data->bSavedInINCHI_LIB[bReconnected] ++;
1145 : : orig_inp_data->bPreprocessed[bReconnected] = bPreprocessed;
1146 : : }
1147 : : }
1148 : : }
1149 : : #else
1150 : : if (!nComponent && orig_inp_data) /* djb-rwth: fixing a NULL pointer dereference */
1151 : : {
1152 : : /* keep track of saved INCHI_LIB data */
1153 : : orig_inp_data->bSavedInINCHI_LIB[bReconnected] ++;
1154 : : orig_inp_data->bPreprocessed[bReconnected] = bPreprocessed;
1155 : : }
1156 : : #endif
1157 : : }
1158 : : }
1159 : :
1160 : : exit_function:
1161 : :
1162 : : return sd->bUserQuit;
1163 : : }
1164 : :
1165 : : #else
1166 : : /* dummies */
1167 : :
1168 : : /****************************************************************************/
1169 : 0 : int DisplayTheWholeStructure( struct tagCANON_GLOBALS *pCG,
1170 : : struct tagINCHI_CLOCK *ic,
1171 : : STRUCT_DATA *sd,
1172 : : INPUT_PARMS *ip,
1173 : : char *szTitle,
1174 : : INCHI_IOSTREAM *inp_file,
1175 : : INCHI_IOSTREAM *log_file,
1176 : : ORIG_ATOM_DATA *orig_inp_data,
1177 : : long num_inp,
1178 : : int iINChI,
1179 : : int bShowStruct,
1180 : : int bINCHI_LIB_Flag )
1181 : : {
1182 : 0 : return 0;
1183 : : }
1184 : :
1185 : :
1186 : : /****************************************************************************/
1187 : 0 : int DisplayStructure( struct tagCANON_GLOBALS *pCG,
1188 : : inp_ATOM *at,
1189 : : int num_at,
1190 : : OAD_Polymer *polymer,
1191 : : int num_removed_H,
1192 : : int bAdd_DT_to_num_H,
1193 : : int nNumRemovedProtons,
1194 : : NUM_H *nNumRemovedProtonsIsotopic,
1195 : : int bIsotopic,
1196 : : int j /*bTautomeric*/,
1197 : : INChI **cur_INChI,
1198 : : INChI_Aux **cur_INChI_Aux,
1199 : : int bAbcNumbers,
1200 : : DRAW_PARMS *dp,
1201 : : INCHI_MODE nMode,
1202 : : char *szTitle )
1203 : : {
1204 : 0 : return 0;
1205 : : }
1206 : :
1207 : :
1208 : :
1209 : :
1210 : : #endif /* }COMPILE_ANSI_ONLY */
1211 : :
1212 : :
1213 : : #ifndef TARGET_API_LIB
1214 : :
1215 : :
1216 : : /****************************************************************************/
1217 : : void SplitTime( unsigned long ulTotalTime,
1218 : : int *hours, int *minutes,
1219 : : int *seconds, int *mseconds )
1220 : : {
1221 : :
1222 : : *mseconds = (int) ( ulTotalTime % 1000 );
1223 : : ulTotalTime /= 1000;
1224 : : *seconds = (int) ( ulTotalTime % 60 );
1225 : : ulTotalTime /= 60;
1226 : : *minutes = (int) ( ulTotalTime % 60 );
1227 : : ulTotalTime /= 60;
1228 : : *hours = (int) ( ulTotalTime );
1229 : : }
1230 : : #endif
1231 : :
1232 : :
1233 : : /****************************************************************************
1234 : : Check if structure is chiral
1235 : : ****************************************************************************/
1236 : 8 : int bIsStructChiral( PINChI2 *pINChI2[INCHI_NUM], int num_components[] )
1237 : : {
1238 : : int i, j, k;
1239 : : INChI *pINChI;
1240 : : INChI_Stereo *Stereo;
1241 : :
1242 [ + + ]: 10 : for (j = 0; j < INCHI_NUM; j++)
1243 : : {
1244 : : /* disconnected / reconnected */
1245 [ + + ]: 9 : if (!num_components[j])
1246 : : {
1247 : 1 : continue;
1248 : : }
1249 : :
1250 [ + + ]: 9 : for (i = 0; i < num_components[j]; i++)
1251 : : {
1252 : : /* i-th component */
1253 [ + + ]: 17 : for (k = 0; k < TAUT_NUM; k++)
1254 : : {
1255 : : /* mobile/immobile H */
1256 [ + + ]: 16 : if (( pINChI = pINChI2[j][i][k] ) &&
1257 [ + - ]: 8 : !pINChI->bDeleted &&
1258 [ + - ]: 8 : pINChI->nNumberOfAtoms > 0)
1259 : : {
1260 : :
1261 [ + - ]: 8 : if (( Stereo = pINChI->Stereo ) &&
1262 [ + - ]: 8 : Stereo->t_parity &&
1263 [ + + ]: 8 : Stereo->nNumberOfStereoCenters > 0 &&
1264 [ + - ]: 7 : Stereo->nCompInv2Abs)
1265 : : {
1266 : 7 : return 1; /* inversion changed stereo */
1267 : : }
1268 [ - + ]: 1 : if (( Stereo = pINChI->StereoIsotopic ) &&
1269 [ # # ]: 0 : Stereo->t_parity &&
1270 [ # # ]: 0 : Stereo->nNumberOfStereoCenters > 0 &&
1271 [ # # ]: 0 : Stereo->nCompInv2Abs)
1272 : : {
1273 : 0 : return 1; /* inversion changed stereo */
1274 : : }
1275 : : }
1276 : : }
1277 : : }
1278 : : }
1279 : :
1280 : 1 : return 0;
1281 : : }
1282 : :
1283 : :
1284 : : /****************************************************************************
1285 : : Release InChI work memory
1286 : : ****************************************************************************/
1287 : 122 : void FreeAllINChIArrays( PINChI2 *pINChI[INCHI_NUM],
1288 : : PINChI_Aux2 *pINChI_Aux[INCHI_NUM],
1289 : : int num_components[INCHI_NUM] )
1290 : : {
1291 : : int k;
1292 [ + + ]: 366 : for (k = 0; k < INCHI_NUM; k++)
1293 : : {
1294 : 244 : int nk = num_components[k];
1295 : :
1296 : 244 : FreeINChIArrays( pINChI[k], pINChI_Aux[k], num_components[k] );
1297 : :
1298 : 244 : num_components[k] = 0;
1299 : :
1300 [ + + ]: 244 : if (nk && /* added check for nk: 2013-12-15 IPl */
1301 [ + - ]: 122 : pINChI[k])
1302 : : {
1303 [ + - ]: 122 : inchi_free( pINChI[k] );
1304 : 122 : pINChI[k] = NULL;
1305 : : }
1306 : :
1307 [ + + ]: 244 : if (nk && /* added check for nk: 2013-12-15 IPl */
1308 [ + - ]: 122 : pINChI_Aux[k])
1309 : : {
1310 [ + - ]: 122 : inchi_free( pINChI_Aux[k] );
1311 : 122 : pINChI_Aux[k] = NULL;
1312 : : }
1313 : : }
1314 : :
1315 : 122 : return;
1316 : : }
1317 : :
1318 : :
1319 : : /****************************************************************************
1320 : : Release InChI work memory
1321 : : ****************************************************************************/
1322 : 244 : void FreeINChIArrays( PINChI2 *pINChI, PINChI_Aux2 *pINChI_Aux, int num_components )
1323 : : {
1324 : : int i, k;
1325 : : /* Release allocated memory */
1326 [ + + ]: 244 : if (pINChI)
1327 : : {
1328 [ + + ]: 283 : for (i = 0; i < num_components; i++)
1329 : : {
1330 [ + + ]: 483 : for (k = 0; k < TAUT_NUM; k++)
1331 : : {
1332 : 322 : Free_INChI( &pINChI[i][k] );
1333 : : }
1334 : : }
1335 : : }
1336 [ + + ]: 244 : if (pINChI_Aux)
1337 : : {
1338 [ + + ]: 283 : for (i = 0; i < num_components; i++)
1339 : : {
1340 [ + + ]: 483 : for (k = 0; k < TAUT_NUM; k++)
1341 : : {
1342 : 322 : Free_INChI_Aux( &pINChI_Aux[i][k] );
1343 : : }
1344 : : }
1345 : : }
1346 : 244 : }
1347 : :
1348 : :
1349 : : /****************************************************************************
1350 : : Treat errors returned by CreateOneComponentINChI( ... )
1351 : : ****************************************************************************/
1352 : 0 : int TreatErrorsInCreateOneComponentINChI( STRUCT_DATA *sd,
1353 : : INPUT_PARMS *ip,
1354 : : ORIG_ATOM_DATA *orig_inp_data,
1355 : : int i, long num_inp,
1356 : : INCHI_IOSTREAM *inp_file,
1357 : : INCHI_IOSTREAM *log_file,
1358 : : INCHI_IOSTREAM *out_file,
1359 : : INCHI_IOSTREAM *prb_file )
1360 : : {
1361 [ # # ]: 0 : if (sd->nErrorCode)
1362 : : {
1363 : 0 : AddErrorMessage( sd->pStrErrStruct, ErrMsg( sd->nErrorCode ) );
1364 : 0 : inchi_ios_eprint( log_file,
1365 : : "Error %d (%s) structure #%ld component %d.%s%s%s%s\n",
1366 : 0 : sd->nErrorCode, sd->pStrErrStruct,
1367 [ # # # # : 0 : num_inp, i + 1, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
# # # # #
# # # # #
# # # # #
# # # #
# ]
1368 [ # # ]: 0 : sd->nErrorType = ( sd->nErrorCode == CT_OUT_OF_RAM || sd->nErrorCode == CT_USER_QUIT_ERR )
1369 : : ? _IS_FATAL
1370 [ # # ]: 0 : : _IS_ERROR;
1371 : :
1372 : : #ifdef TARGET_LIB_FOR_WINCHI
1373 : : if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
1374 : : ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
1375 : : {
1376 : : sd->nErrorType = ProcessStructError( out_file, log_file,
1377 : : sd->pStrErrStruct, sd->nErrorType,
1378 : : num_inp, ip );
1379 : : /* Save the problem structure */
1380 : : if (prb_file->f &&
1381 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd &&
1382 : : !ip->bSaveAllGoodStructsAsProblem)
1383 : : {
1384 : : MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, num_inp );
1385 : : }
1386 : : }
1387 : : else
1388 : : {
1389 : : /* Save the problem structure */
1390 : : if (sd->nErrorCode &&
1391 : : prb_file->f &&
1392 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd &&
1393 : : !ip->bSaveAllGoodStructsAsProblem)
1394 : : {
1395 : : MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, num_inp );
1396 : : }
1397 : : }
1398 : : #endif
1399 : : }
1400 : :
1401 : : /* #ifndef TARGET_API_LIB */
1402 : : #if ( !defined( TARGET_API_LIB ) && !defined(TARGET_EXE_STANDALONE) )
1403 : : /* print the logfile record */
1404 : : if (log_file->f && log_file->f != stderr && ( sd->ulStructTime >= 1000 || sd->nErrorCode ))
1405 : : {
1406 : : fprintf( log_file->f, "%10lu msec structure #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1407 : : sd->ulStructTime, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1408 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1409 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1410 : : }
1411 : : #endif
1412 : :
1413 : 0 : return sd->nErrorType;
1414 : : }
1415 : :
1416 : :
1417 : : /****************************************************************************/
1418 : 122 : int TreatCreateINChIWarning( STRUCT_DATA *sd,
1419 : : INPUT_PARMS *ip,
1420 : : ORIG_ATOM_DATA *orig_inp_data,
1421 : : long num_inp,
1422 : : INCHI_IOSTREAM *inp_file,
1423 : : INCHI_IOSTREAM *log_file,
1424 : : INCHI_IOSTREAM *out_file,
1425 : : INCHI_IOSTREAM *prb_file )
1426 : : {
1427 : :
1428 : : #if ( bRELEASE_VERSION == 0 && (EXTR_FLAGS || EXTR_MASK) )
1429 : : if (EXTR_MASK ? ( ( sd->bExtract & EXTR_MASK ) == EXTR_FLAGS )
1430 : : : ( sd->bExtract & EXTR_FLAGS )
1431 : : )
1432 : : {
1433 : : char szMsg[64];
1434 : : sprintf( szMsg, "ExtractStruct.code=0x%X", sd->bExtract );
1435 : : if (!ip->bNoWarnings)
1436 : : {
1437 : : WarningMessage( sd->pStrErrStruct, szMsg );
1438 : : }
1439 : : }
1440 : : #endif
1441 : :
1442 [ + - + + ]: 122 : if (!sd->nErrorCode && sd->pStrErrStruct[0])
1443 : : {
1444 : 100 : inchi_ios_eprint( log_file, "Warning (%s) structure #%ld.%s%s%s%s\n",
1445 [ - + - - : 125 : sd->pStrErrStruct, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
- + - - -
+ - - - -
- - - + -
- - + -
- ]
1446 : 25 : sd->nErrorType = _IS_WARNING;
1447 : :
1448 : : #ifdef TARGET_LIB_FOR_WINCHI
1449 : : if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
1450 : : ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
1451 : : {
1452 : : sd->nErrorType = ProcessStructError( out_file,
1453 : : log_file,
1454 : : sd->pStrErrStruct,
1455 : : sd->nErrorType,
1456 : : num_inp,
1457 : : ip );
1458 : : }
1459 : : #endif
1460 : : /* save the structure as a problem structure if requested */
1461 [ - + - - ]: 25 : if (ip->bSaveWarningStructsAsProblem && !ip->bSaveAllGoodStructsAsProblem &&
1462 [ # # # # : 0 : prb_file->f && 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd)
# # ]
1463 : : { /* djb-rwth: addressing coverity ID #499545 -- return values handled properly */
1464 : 0 : MolfileSaveCopy( inp_file,
1465 : : sd->fPtrStart,
1466 : : sd->fPtrEnd,
1467 : : prb_file->f,
1468 : : num_inp );
1469 : : }
1470 : :
1471 : : #if ( bRELEASE_VERSION == 0 )
1472 : : /* otherwise extract the structure as a problem structure if requested */
1473 : : else
1474 : : if (( EXTR_MASK ? ( ( sd->bExtract & EXTR_MASK ) == EXTR_FLAGS ) : ( sd->bExtract & EXTR_FLAGS ) )
1475 : : && !ip->bSaveAllGoodStructsAsProblem &&
1476 : : prb_file->f &&
1477 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd)
1478 : : {
1479 : : MolfileSaveCopy( inp_file->f,
1480 : : sd->fPtrStart,
1481 : : sd->fPtrEnd,
1482 : : prb_file->f,
1483 : : num_inp );
1484 : : }
1485 : : #endif
1486 : : }
1487 : :
1488 : : #if ( bRELEASE_VERSION != 1 && bOUTPUT_ONE_STRUCT_TIME == 1 )
1489 : : #ifndef TARGET_API_LIB
1490 : : if (log_file && log_file != stderr)
1491 : : {
1492 : : fprintf( log_file, "%10lu msec structure %1dD #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1493 : : sd->ulStructTime, orig_inp_data->num_dimensions, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1494 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1495 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1496 : : }
1497 : : #else
1498 : : if (log_file)
1499 : : {
1500 : : inchi_ios_eprint( log_file, "%10lu msec structure %1dD #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1501 : : sd->ulStructTime, orig_inp_data->num_dimensions, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1502 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1503 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1504 : : }
1505 : : #endif
1506 : : #endif
1507 : :
1508 : 122 : return sd->nErrorType;
1509 : : }
1510 : :
1511 : :
1512 : : /****************************************************************************
1513 : : Treat errors/warnings
1514 : : ****************************************************************************/
1515 : 161 : int GetProcessingWarningsOneComponentInChI( INChI *cur_INChI[],
1516 : : INP_ATOM_DATA **inp_norm_data,
1517 : : STRUCT_DATA *sd,
1518 : : int bNoWarnings )
1519 : : {
1520 : 161 : int i, ret = 0;
1521 [ + + ]: 483 : for (i = 0; i < TAUT_NUM; i++)
1522 : : {
1523 [ + + + - ]: 322 : if (cur_INChI[i] && cur_INChI[i]->nNumberOfAtoms > 0)
1524 : : {
1525 : 161 : ret |= GetProcessingWarningsOneInChI( cur_INChI[i],
1526 : 161 : inp_norm_data[i],
1527 : 161 : sd->pStrErrStruct,
1528 : : bNoWarnings );
1529 : : }
1530 : : }
1531 : :
1532 : 161 : return ret;
1533 : : }
1534 : :
1535 : :
1536 : : /****************************************************************************
1537 : : Treat errors/warnings
1538 : : ****************************************************************************/
1539 : 161 : int GetProcessingWarningsOneInChI( INChI *pINChI,
1540 : : INP_ATOM_DATA *inp_norm_data,
1541 : : char *pStrErrStruct,
1542 : : int bNoWarnings )
1543 : : {
1544 : : int j;
1545 : : int nAmbiguousStereoAtoms, nAmbiguousStereoBonds;
1546 : 161 : nAmbiguousStereoAtoms = 0;
1547 : 161 : nAmbiguousStereoBonds = 0;
1548 : :
1549 [ + - ]: 161 : if (inp_norm_data->at)
1550 : : {
1551 [ + + ]: 971 : for (j = 0; j < pINChI->nNumberOfAtoms; j++)
1552 : : {
1553 [ - + ]: 810 : if (inp_norm_data->at[j].bAmbiguousStereo & ( AMBIGUOUS_STEREO_ATOM | AMBIGUOUS_STEREO_ATOM_ISO ))
1554 : : {
1555 : 0 : nAmbiguousStereoAtoms++;
1556 : : }
1557 [ - + ]: 810 : if (inp_norm_data->at[j].bAmbiguousStereo & ( AMBIGUOUS_STEREO_BOND | AMBIGUOUS_STEREO_BOND_ISO ))
1558 : : {
1559 : 0 : nAmbiguousStereoBonds++;
1560 : : }
1561 : : }
1562 [ - + ]: 161 : if (nAmbiguousStereoAtoms)
1563 : : {
1564 [ # # ]: 0 : if (!bNoWarnings)
1565 : : {
1566 : 0 : WarningMessage( pStrErrStruct, "Ambiguous stereo:" );
1567 : 0 : WarningMessage( pStrErrStruct, "center(s)" );
1568 : : }
1569 : : }
1570 [ - + ]: 161 : if (nAmbiguousStereoBonds)
1571 : : {
1572 [ # # ]: 0 : if (!bNoWarnings)
1573 : : {
1574 : 0 : WarningMessage( pStrErrStruct, "Ambiguous stereo:" );
1575 : 0 : WarningMessage( pStrErrStruct, "bond(s)" );
1576 : : }
1577 : : }
1578 : : }
1579 : :
1580 [ + - - + ]: 161 : return ( nAmbiguousStereoAtoms || nAmbiguousStereoBonds );
1581 : : }
|