1 /* food.c */
2 
3 /*
4     NUT nutrition software
5     Copyright (C) 1996-2014 by Jim Jozwiak.
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21 
22 #include "util.h"
23 #include "options.h"
24 #include "nutrient.h"
25 #include "abbrev.h"
26 #include "fdgrp.h"
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 
31 struct food food_root, food_work, *new_food, recipe_root, *new_recipe, *FoodIndex[MAX_FOOD];
32 
33 int DVMap[] =
34 {
35 DV_COUNT,ENERC_KCAL,
36 FAT,FASAT,FAMS,FAPU,OMEGA6,LA,AA,OMEGA3,ALA,EPA,DHA,CHOLE,CHOCDF,FIBTG,CHO_NONFIB,PROCNT,
37 VITA_IU,THIA,RIBF,NIA,PANTAC,VITB6A,FOL,VITB12,VITC,VITD,VITE,VITK1,
38 CA,CU,FE,MG,MN,P,K,SE,NA,ZN
39 };
40 
41 int CarbAminoMap[] =
42 {
43 CARBAMINO_COUNT,CHOCDF,FIBTG,STARCH,SUGAR,FRUS,GALS,GLUS,LACS,MALS,SUCS,
44 PROCNT,ADPROT,ALA_G,ARG_G,ASP_G,CYS_G,GLU_G,GLY_G,HISTN_G,HYP,ILE_G,
45 LEU_G,LYS_G,MET_G,PHE_G,PRO_G,SER_G,THR_G,TRP_G,TYR_G,VAL_G
46 };
47 
48 int MiscMap[] =
49 {
50 MISC_COUNT,ENERC_KJ,ASH,WATER,CAFFN,THEBRN,ALC,
51 FLD,BETN,CHOLN,FOLAC,FOLFD,FOLDFE,RETOL,VITA_RAE,
52 ERGCAL,CHOCAL,VITD_BOTH,
53 VITB12_ADDED,VITE_ADDED,
54 VITK1D,MK4,
55 TOCPHA,TOCPHB,TOCPHG,TOCPHD,TOCTRA,TOCTRB,TOCTRG,TOCTRD,CARTA,CARTB,CRYPX,LUT_ZEA,LYCPN,
56 CHOLE,PHYSTR,SITSTR,CAMD5,STID7
57 };
58 
59 int SatMonoMap[] =
60 {
61 SATMONO_COUNT,FASAT,F4D0,F6D0,F8D0,F10D0,F12D0,F13D0,F14D0,F15D0,F16D0,
62 F17D0,F18D0,F20D0,F22D0,F24D0,
63 FAMS,F14D1,F15D1,F16D1,F16D1C,F17D1,
64 F18D1,F18D1C,F20D1,F22D1,F22D1C,F24D1C
65 };
66 
67 int PolyTransMap[] =
68 {
69 POLYTRANS_COUNT,FAPU,F18D2,F18D2CN6,
70 F18D3,F18D3CN3,F18D3CN6,F18D4,F20D2CN6,F20D3,
71 F20D3N3,F20D3N6,
72 F20D4,F20D4N6,F20D5,F21D5,F22D4,F22D5,F22D6,
73 FATRN,FATRNM,F16D1T,F18D1T,F18D1TN7,F22D1T,
74 FATRNP,F18D2T,F18D2TT,F18D2I,F18D2CLA,F18D3I
75 };
76 
77 int *ScreenMap[] =
78 {
79 DVMap,DVMap,CarbAminoMap,MiscMap,SatMonoMap,PolyTransMap
80 };
81 
82 char *ScreenTitle[] =
83 {
84 "Daily Value Percentages","Daily Value Absolute Amounts",
85 "Carbohydrates and Amino Acids","Miscellaneous Nutrients",
86 "Saturated and Monounsaturated Fatty Acids","Polyunsaturated and Trans Fatty Acids"
87 };
88 
89 int MaxFdGrp = FD_GRP_COUNT;
90 
91 float DVBase[NUTRIENT_COUNT];
92 
93 float DV[NUTRIENT_COUNT];
94 
95 int DVnotOK;
96 
97 float NoData;
98 
99 int LookupNutrNo[NUTRIENT_COUNT - DERIVED];
100 int LookupNut[NUTRNO_ARRAYSIZE];
101 
102 int FoodCount = 0;
103 
initializations()104 void initializations()
105 {
106 int c;
107 NoData = atof("-0");
108 test_signsense(&NoData);
109 initialize_options();
110 for (c=0; c < NUTRIENT_COUNT; c++) DVBase[c] = 0;
111 
112 DVBase[ENERC_KCAL] = 2000;
113 DVBase[PROCNT] = 50;
114 DVBase[FAT] = 65;
115 DVBase[CHOCDF] = 300;
116 DVBase[FIBTG] = 25;
117 DVBase[CHO_NONFIB] = DVBase[CHOCDF] - DVBase[FIBTG];
118 DVBase[CA] = 1000;
119 DVBase[P] = 1000;
120 DVBase[FE] = 18;
121 DVBase[NA] = 2400;
122 DVBase[K] = 3500;
123 DVBase[MG] = 400;
124 DVBase[ZN] = 15;
125 DVBase[CU] = 2;
126 DVBase[MN] = 2;
127 DVBase[SE] = 70;
128 DVBase[VITA_IU] = 5000;
129 DVBase[VITE] = 30;
130 DVBase[VITK1] = 80;
131 DVBase[THIA] = 1.5;
132 DVBase[RIBF] = 1.7;
133 DVBase[NIA] = 20;
134 DVBase[PANTAC] = 10;
135 DVBase[VITB6A] = 2;
136 DVBase[FOL] = 400;
137 DVBase[VITB12] = 6;
138 DVBase[VITC] = 60;
139 DVBase[FASAT] = 20;
140 DVBase[CHOLE] = 300;
141 DVBase[VITD] = 400;
142 DVBase[FAPU] = 8.9;
143 DVBase[AA] = 0.2;
144 DVBase[ALA] = 3.8;
145 DVBase[EPA] = 0.1;
146 DVBase[DHA] = 0.1;
147 DVBase[LA] = DVBase[FAPU] - DVBase[AA] - DVBase[ALA] - DVBase[EPA] - DVBase[DHA];
148 DVBase[OMEGA3] = DVBase[ALA] + DVBase[EPA] + DVBase[DHA];
149 DVBase[OMEGA6] = DVBase[LA] + DVBase[AA];
150 DVBase[FAMS] = 61.5 - DVBase[FASAT] - DVBase[FAPU];
151 for (c=0; c < NUTRNO_ARRAYSIZE; c++) LookupNut[c] = -1;
152 for (c=0; c < NUTRIENT_COUNT - DERIVED; c++) LookupNutrNo[c] = -1;
153 #include "lookup.h"
154 }
155 
order_new_food()156 int order_new_food()
157 {
158 struct food *food_ptr = &food_root;
159 int foodnum = 0;
160 while (food_ptr->next != NULL && namestrcmp(new_food->name, food_ptr->next->name) >= 0)
161  {
162  food_ptr = food_ptr->next;
163  foodnum++;
164  }
165 new_food->next = food_ptr->next;
166 food_ptr->next = new_food;
167 return foodnum;
168 }
169 
namestrcmp(char * name1,char * name2)170 int namestrcmp(char *name1, char *name2)
171 {
172 char namebuf1[61], namebuf2[61];
173 int count;
174 for (count = 0 ; count <= 60 ; count++)
175  {
176  if (name1[count] == ',') namebuf1[count] = '\a';
177  else namebuf1[count] = name1[count];
178  if (name2[count] == ',') namebuf2[count] = '\a';
179  else namebuf2[count] = name2[count];
180  }
181 return strcmp(namebuf1,namebuf2);
182 }
183 
substring_finder(char * food_name,char * substr)184 int substring_finder(char *food_name, char *substr)
185 {
186 int i;
187 char *token;
188 char substring[61];
189 strcpy(substring,substr);
190 token = strtok(substring, ", ");
191 while (token != NULL)
192  {
193  if (strstr(food_name,token) != NULL)
194   {
195   token = strtok(NULL,", ");
196   continue;
197   }
198  for (i=0; i < Abbrev_Count; i++) if (strcmp(token,Abbreviations[i]) == 0) break;
199  if (i == Abbrev_Count) return 0;
200  if (strstr(food_name,Abbreviations[i % 2 == 0 ? i+1 : i-1]) == NULL) return 0;
201  token = strtok(NULL,", ");
202  }
203 return 1;
204 }
205 
food_choice(char * screentitle,int usual)206 struct food *food_choice(char *screentitle, int usual)
207 {
208 struct food *food_ptr;
209 struct food *ptrlist[MAX_FOOD];
210 int count = 0, charcount, keysize, lines, junk;
211 char substring[61], key[61];
212 for ( ; ; )
213  {
214  key_decode(substring,key);
215  if (strcmp(substring,"") == 0)
216   {
217   header(screentitle);
218   spacer(0);
219   if (strcmp(screentitle,"NUT:  Add Recipes") == 0) printf("\nType food name to add to recipe (or <enter> to quit):  ");
220   else printf("\nType food name to select (or <enter> to quit):  ");
221   get_string(substring,60);
222   key[0] = '\0';
223   key_clean();
224   }
225  if (substring[0] == '\0') return (struct food *) -1;
226  for (charcount = 0 ; charcount < 60 ; charcount++) substring[charcount] = toupper(substring[charcount]);
227  key_encode(substring,key);
228  if (strncmp(substring,"THEUSUAL",8) == 0 && usual) return (struct food *) -2;
229  if (strncmp(substring,"PCF ",4) == 0 && usual) return (struct food *) -3;
230  header(screentitle);
231  food_ptr = &food_root;
232  keysize = strlen(key); lines = 0; count = 0;
233  while ((food_ptr = food_ptr->next)) if (substring_finder(food_ptr->name,substring) && strncmp(key,food_ptr->name,keysize) == 0) ptrlist[++count] = food_ptr;
234  while (count == 0)
235   {
236   key_clean();
237   spacer(-1);
238   printf("No food named \"%s\".  Try another (or <enter> to quit):  ",substring);
239   get_string(substring,60);
240   if (substring[0] == '\0') return (struct food *) 0;
241   for (charcount = 0 ; charcount < 60 ; charcount++) substring[charcount] = toupper(substring[charcount]);
242   key_encode(substring,key);
243   if (strncmp(substring,"THEUSUAL",8) == 0 && usual) return (struct food *) -2;
244   if (strncmp(substring,"PCF ",4) == 0 && usual) return (struct food *) -3;
245   header(screentitle);
246   food_ptr = &food_root;
247   keysize = strlen(key); lines = 0; count = 0;
248   while ((food_ptr = food_ptr->next)) if (substring_finder(food_ptr->name,substring) && strncmp(key,food_ptr->name,keysize) == 0) ptrlist[++count] = food_ptr;
249   }
250  if (count == 1) return ptrlist[1];
251  if (count < 21)
252   {
253   for (lines = 1 ; lines <= count ; lines++) printf("%2d. %s\n",lines,ptrlist[lines]->name);
254   spacer(lines - 2);
255   printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
256   get_string(key,60);
257   junk = 0;
258   if (strcmp(key,"b") == 0 || strcmp(key,"B") == 0) junk = -38;
259   if (junk == -38)
260    {
261    key_decode(substring,key);
262    continue;
263    }
264   junk = atoi(key);
265   if (junk > 0 && junk <= count)
266    {
267    key_encode(substring,ptrlist[junk]->name);
268    return ptrlist[junk];
269    }
270   else return (struct food *) 0;
271   }
272  if (count > 20) food_subcat(substring, key, ptrlist, count);
273  }
274 }
275 
food_subcat(char * substring,char * key,struct food ** ptrlist,int count)276 void food_subcat(char *substring, char *key, struct food **ptrlist, int count)
277 {
278 char food_screen[2000];
279 char *fsptr[500], *thisfsptr, *bufptr, buffer[61], format[11], format100[11], tokenhead[61], junkstring[120];
280 char *col[10], colformat1[110], colformat2[110];
281 int i, l, s, subcount = 0, charcount, tokencount, nlength, tokenlength, tokenunique, headlength = 0, linecount, savelinecount = 0, tokenmax = 0, colcount;
282 for (linecount = 1 ; linecount <= 20 ; linecount++) fsptr[linecount] = food_screen + (61 * linecount);
283 for (linecount = 1 ; linecount <= count ; linecount++)
284  {
285  tokencount = 0;
286  nlength = strlen(ptrlist[linecount]->name);
287  for (charcount = 0 ; charcount <= nlength ; charcount++) if (ptrlist[linecount]->name[charcount] == ',') tokencount++;
288  if (tokencount > tokenmax) tokenmax = tokencount;
289  }
290 while (subcount < count && tokenmax > -1)
291  {
292  tokenmax--;
293  subcount = 0;
294  for (linecount = 1; subcount < count && linecount <= 20 ; linecount++)
295   {
296   subcount++;
297   nlength = strlen(ptrlist[subcount]->name);
298   thisfsptr = fsptr[linecount];
299   tokencount = 0;
300   for (charcount = 0 ; charcount <= nlength ; charcount++)
301    {
302    if (ptrlist[subcount]->name[charcount] == ',') tokencount++;
303    if (tokencount == tokenmax)
304     {
305     thisfsptr[charcount] = '\0';
306     break;
307     }
308    thisfsptr[charcount] = ptrlist[subcount]->name[charcount];
309    if (ptrlist[subcount]->name[charcount] == '\0') break;
310    }
311   if (linecount > 1 && 0 == strcmp(fsptr[linecount],fsptr[linecount-1])) linecount--;
312   }
313  savelinecount = --linecount;
314  }
315 if (savelinecount > 1)
316  {
317  for (linecount = 1; linecount <= savelinecount ; linecount++) printf("%2d.  %s\n",linecount,fsptr[linecount]);
318  spacer(savelinecount-1);
319  printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
320  get_string(junkstring,20);
321  if (strcmp(junkstring,"b") == 0 || strcmp(junkstring,"B") == 0)
322   {
323   key_take();
324   return;
325   }
326  linecount = atoi(junkstring);
327  if (linecount > 0 && linecount <= savelinecount)
328   {
329   if (headlength < 1) strcpy(key,fsptr[linecount]);
330   if (headlength > 0)
331    {
332    strcpy(key,tokenhead);
333    strcat(key,fsptr[linecount]);
334    }
335   for (subcount = 1 ; subcount <= count ; subcount++) if (strcmp(key,ptrlist[subcount]->name) == 0) break;
336   if (--subcount == count) strcat(key,",");
337   }
338  else
339   {
340   key[0] = '\0';
341   substring[0] = '\0';
342   }
343  key_encode(substring,key);
344  }
345 else
346  {
347  tokenhead[0] = '\0';
348  for (tokenmax = 1 ; ; tokenmax++)
349   {
350   buffer[0] = '\0';
351   tokenunique = 0;
352   tokenlength = 0;
353   for (subcount = 1 ; subcount <= count ; subcount++)
354    {
355    bufptr = ptrlist[subcount]->name;
356    nlength = 0;
357    for (tokencount = 1 ; tokencount <= tokenmax ; tokencount++)
358     {
359     bufptr += nlength;
360     bufptr += strspn(bufptr,",");
361     nlength = strcspn(bufptr,",");
362     }
363    if (nlength > tokenlength)
364     {
365     tokenlength = nlength;
366     tokenunique++;
367     strncpy(buffer,bufptr,nlength);
368     buffer[nlength] = '\0';
369     }
370    else if (nlength < tokenlength)
371     {
372     tokenunique++;
373     strncpy(buffer,bufptr,nlength);
374     buffer[nlength] = '\0';
375     }
376    else if (strncmp(buffer,bufptr,nlength) != 0)
377     {
378     tokenunique++;
379     strncpy(buffer,bufptr,nlength);
380     buffer[nlength] = '\0';
381     }
382    }
383   if (tokenunique == 1)
384    {
385    strcat(buffer,",");
386    strcat(tokenhead,buffer);
387    }
388   if (tokenunique != 1) break;
389   }
390  if (tokenhead[0] == '\0') savelinecount = 20;
391  else savelinecount = 19;
392  headlength = strlen(tokenhead);
393 #ifndef DOS
394  while ( savelinecount * (81 / (tokenlength + 5 ) ) < tokenunique )
395 #else
396  while ( savelinecount * (80 / (tokenlength + 5 ) ) < tokenunique )
397 #endif
398   {
399   buffer[0] = '\0';
400   tokenunique = 0 ;
401   tokenlength--;
402   for (subcount = 1 ; subcount <= count ; subcount++)
403    {
404    bufptr = ptrlist[subcount]->name + headlength;
405    nlength = strcspn(bufptr,",");
406    while (*(bufptr + nlength - 1) == ' ') nlength--;
407    if (nlength > tokenlength) nlength = tokenlength;
408    if (strncmp(buffer,bufptr,nlength) != 0)
409     {
410     tokenunique++;
411     strncpy(buffer,bufptr,nlength);
412     buffer[nlength] = '\0';
413     }
414    }
415   }
416  for (linecount = 0 ; linecount <= (tokenunique+2) ; linecount++) fsptr[linecount] = food_screen + ((tokenlength+1) * linecount);
417  food_screen[0] = '\0';
418  linecount = 0;
419  for (subcount = 1 ; subcount <= count ; subcount++)
420   {
421   bufptr = ptrlist[subcount]->name + headlength;
422   nlength = (strcspn(bufptr,","));
423   if (nlength > tokenlength) nlength = tokenlength;
424   while (*(bufptr + nlength - 1) == ' ') nlength--;
425   strncpy(fsptr[linecount + 1],bufptr,nlength);
426   thisfsptr = fsptr[linecount + 1];
427   thisfsptr[nlength] = '\0';
428   if (strncmp(fsptr[linecount],fsptr[linecount + 1],nlength) != 0) linecount++;
429   }
430  sprintf(format,"%%2d. %%-%ds",tokenlength);
431  sprintf(format100,"%%3d. %%-%ds",tokenlength);
432  strcpy(colformat1,format);
433  strcpy(colformat2,format);
434  colcount = (linecount % savelinecount == 0 ? 0 : 1) + (linecount / savelinecount);
435  if (colcount > 7)
436   {
437   spacer(-1);
438   printf("Too many foods meet criterion.  Press <enter> to continue...");
439   i = get_int();
440   key_take();
441   return;
442   }
443  if (colcount < 8)
444   {
445   for (i = 2 ; i <= colcount ; i++)
446    {
447    if (i != colcount) strcat(colformat1," ");
448    strcat(colformat2," ");
449    if ((i * savelinecount) < 100 || tokenunique < 100)
450     {
451     if (i != colcount) strcat(colformat1,format);
452     strcat(colformat2,format);
453     }
454    else
455     {
456     if (i != colcount) strcat(colformat1,format100);
457     strcat(colformat2,format100);
458     }
459    }
460   strcat(colformat1,"\n");
461   strcat(colformat2,"\n");
462   col[colcount - 1] = colformat1;
463   col[colcount] = colformat2;
464   if (headlength > 0 ) printf("%-s\n",tokenhead);
465   if ( linecount < savelinecount ) savelinecount = linecount;
466   l = linecount ; s = savelinecount;
467   for (i = 1 ; i <= savelinecount ; i++)
468    {
469    if      (i+(1*s)>l) printf(col[1],i,fsptr[i]);
470    else if (i+(2*s)>l) printf(col[2],i,fsptr[i],i+s,fsptr[i+s]);
471    else if (i+(3*s)>l) printf(col[3],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)]);
472    else if (i+(4*s)>l) printf(col[4],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)]);
473    else if (i+(5*s)>l) printf(col[5],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)],i+(4*s),fsptr[i+(4*s)]);
474    else if (i+(6*s)>l) printf(col[6],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)],i+(4*s),fsptr[i+(4*s)],i+(5*s),fsptr[i+(5*s)]);
475    else if (i+(7*s)>l) printf(col[7],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)],i+(4*s),fsptr[i+(4*s)],i+(5*s),fsptr[i+(5*s)],i+(6*s),fsptr[i+(6*s)]);
476    else if (i+(8*s)>l) printf(col[8],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)],i+(4*s),fsptr[i+(4*s)],i+(5*s),fsptr[i+(5*s)],i+(6*s),fsptr[i+(6*s)],i+(7*s),fsptr[i+(7*s)]);
477    else if (i+(9*s)>l) printf(col[9],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)],i+(3*s),fsptr[i+(3*s)],i+(4*s),fsptr[i+(4*s)],i+(5*s),fsptr[i+(5*s)],i+(6*s),fsptr[i+(6*s)],i+(7*s),fsptr[i+(7*s)],i+(8*s),fsptr[i+(8*s)]);
478    }
479   spacer(savelinecount < 19 ? savelinecount : 19);
480   printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
481   get_string(junkstring,20);
482   if (strcmp(junkstring,"b") == 0 || strcmp(junkstring,"B") == 0)
483    {
484    key_take();
485    return;
486    }
487   i = atoi(junkstring);
488   if (i > 0 && i <= linecount)
489    {
490    if (headlength > 0)
491     {
492     strcpy(key,tokenhead);
493     strcat(key,fsptr[i]);
494     }
495    else strcpy(key,fsptr[i]);
496    }
497   else
498    {
499    key[0] = '\0';
500    substring[0] = '\0';
501    }
502   key_encode(substring,key);
503   }
504  }
505 }
506 
food_show(struct food * food_ptr,float * ratio)507 void food_show(struct food *food_ptr, float *ratio)
508 {
509 char servingstring[62];
510 int count;
511 printf("%-60s   Grams  %8.2f\n",food_ptr->name,food_ptr->grams * *ratio);
512 printf("Serving:  %-50s   Ounces  %7.2f\n",format_serving(servingstring,ratio,food_ptr),*ratio * food_ptr->grams / GRAMS_IN_OUNCE);
513 printf("          %-50s   Water    %6.2f%%\n"," ",food_ptr->nutrient[WATER] > 0 ? food_ptr->nutrient[WATER] : 0.0);
514 if ( ! options.custom && options.screen == 0 ) printf("Percentages of \"Daily Values\" in this serving:                 Refuse   %3d%%\n\n",food_ptr->refuse);
515 if ( options.custom && options.screen == 0 )     printf("Percentages of customized DV in this serving:                  Refuse   %3d%%\n\n",food_ptr->refuse);
516 if ( options.screen > 0 )                 printf("Nutrients in this serving:                                     Refuse   %3d%%\n\n",food_ptr->refuse);
517 for (count = 0; count < NUTRIENT_COUNT; count++) food_work.nutrient[count] = *ratio * food_ptr->nutrient[count] * food_ptr->grams / 100;
518 food_display(stdout);
519 spacer(20);
520 }
521 
food_number(int i)522 struct food *food_number(int i)
523 {
524 return FoodIndex[i];
525 }
526 
find_ndbno(int ndbno)527 int find_ndbno(int ndbno)
528 {
529 struct food *food_ptr = &food_root;
530 while (food_ptr->next != NULL)
531  {
532  food_ptr = food_ptr->next;
533  if (food_ptr->ndb_no == ndbno) return food_ptr->food_no;
534  }
535 return -1;
536 }
537 
find_ndbno_ptr(int ndbno)538 struct food *find_ndbno_ptr(int ndbno)
539 {
540 struct food *food_ptr = &food_root;
541 while (food_ptr->next != NULL)
542  {
543  food_ptr = food_ptr->next;
544  if (food_ptr->ndb_no == ndbno) return food_ptr;
545  }
546 return NULL;
547 }
548 
make_food_index()549 void make_food_index()
550 {
551 struct food *food_ptr = &food_root;
552 FoodCount = 0;
553 while (food_ptr->next != NULL)
554  {
555  food_ptr = food_ptr->next;
556  food_ptr->food_no = FoodCount;
557  FoodIndex[FoodCount++] = food_ptr;
558  }
559 }
560 
modify_food_index(int foodnum,struct food * food_ptr)561 int modify_food_index(int foodnum, struct food *food_ptr)
562 {
563 int count;
564 for (count = FoodCount; count > foodnum; count--) FoodIndex[count] = FoodIndex[count-1];
565 FoodIndex[foodnum] = food_ptr;
566 FoodCount++;
567 food_ptr = &food_root;
568 for (count = 0; count < FoodCount; count++)
569  {
570  food_ptr = food_ptr->next;
571  food_ptr->food_no = count;
572  }
573 return foodnum;
574 }
575 
clear_work()576 void clear_work()
577 {
578 int count;
579 for (count = 0; count < NUTRIENT_COUNT; count++) food_work.nutrient[count] = NoData;
580 food_work.grams = 0;
581 food_work.refuse = 0;
582 }
583 
food_display(FILE * fp)584 void food_display(FILE *fp)
585 {
586 int i, n6;
587 float pctfat = 0, pctcarb = 0, pctprot = 0;
588 float p3, p6, h3, h6, o;
589 char protcarbfat[30];
590 if (food_work.nutrient[ENERC_KCAL] > 0.05)
591  {
592  pctcarb = 100 * food_work.nutrient[CHO_KCAL] / food_work.nutrient[ENERC_KCAL];
593  pctprot = 100 * food_work.nutrient[PROT_KCAL] / food_work.nutrient[ENERC_KCAL];
594  pctfat = 100 * food_work.nutrient[FAT_KCAL] / food_work.nutrient[ENERC_KCAL];
595  if (test_for_negative_zero(&pctcarb)) pctcarb = 0;
596  if (test_for_negative_zero(&pctprot)) pctprot = 0;
597  if (test_for_negative_zero(&pctfat)) pctfat = 0;
598  }
599 else
600  {
601  pctcarb = 0; pctprot = 0; pctfat = 0;
602  }
603 sprintf(protcarbfat,"%1.0f/%1.0f/%1.0f",pctprot,pctcarb,pctfat);
604 switch (options.screen)
605  {
606  case 1 :
607  food_display_line(fp,ScreenMap[options.screen][1],0,0,0,0);
608  food_display_line(fp,ScreenMap[options.screen][14],0,0,0,0);
609  food_display_line(fp,ScreenMap[options.screen][17],0,1,0,0);
610  fprintf(fp,"Prot/Carb/Fat    %8s  ",protcarbfat);
611  food_display_line(fp,ScreenMap[options.screen][15],0,0,0,0);
612  food_display_line(fp,ScreenMap[options.screen][16],0,1,0,0);
613  fprintf(fp,"\n");
614  food_display_line(fp,ScreenMap[options.screen][2],0,0,0,0);
615  food_display_line(fp,ScreenMap[options.screen][18],0,0,0,0);
616  food_display_line(fp,ScreenMap[options.screen][30],0,1,0,0);
617  for (i = 3; i < 6 ; i++)
618   {
619   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,1);
620   food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
621   food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
622   }
623  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,2);
624  food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
625  food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
626  for (i = 7; i < 9 ; i++)
627   {
628   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
629   food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
630   food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
631   }
632  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,2);
633  food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
634  food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
635  for (i = 10; i < 12 ; i++)
636   {
637   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
638   food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
639   food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
640   }
641  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
642  food_display_line(fp,ScreenMap[options.screen][i+16],0,1,0,0);
643  food_display_line(fp,ScreenMap[options.screen][13],0,0,0,0);
644  food_display_line(fp,ScreenMap[options.screen][13+16],0,0,0,0);
645  p3 = 900 * food_work.nutrient[SHORT3] / food_work.nutrient[ENERC_KCAL];
646  p6 = 900 * food_work.nutrient[SHORT6] / food_work.nutrient[ENERC_KCAL];
647  h3 = 900 * food_work.nutrient[LONG3] / food_work.nutrient[ENERC_KCAL];
648  h6 = 900 * food_work.nutrient[LONG6] / food_work.nutrient[ENERC_KCAL];
649  o  = 900 * (food_work.nutrient[FASAT] + food_work.nutrient[FAMS] + food_work.nutrient[FAPU] - food_work.nutrient[SHORT6] - food_work.nutrient[LONG6] - food_work.nutrient[SHORT3] - food_work.nutrient[LONG3]) / food_work.nutrient[ENERC_KCAL];
650  n6 = (int) n6hufa(p3,p6,h3,h6,o,food_work.nutrient[ENERC_KCAL]);
651  fprintf(fp,"Omega-6/3 Balance %2d/%1d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
652  break;
653  case 2 :
654  fprintf(fp,"%-27s","Carbohydrates");
655  fprintf(fp,"%-27s\n\n","Amino Acids");
656  for (i = 1; i < 5 ; i++)
657   {
658   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,0);
659   food_display_line(fp,ScreenMap[options.screen][i+10],0,0,0,0);
660   food_display_line(fp,ScreenMap[options.screen][i+21],0,1,0,0);
661   }
662  for (i = 5; i < 11 ; i++)
663   {
664   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,1);
665   food_display_line(fp,ScreenMap[options.screen][i+10],0,0,0,0);
666   food_display_line(fp,ScreenMap[options.screen][i+21],0,1,0,0);
667   }
668  fprintf(fp,"%-27s"," ");
669  food_display_line(fp,ScreenMap[options.screen][i+10],0,1,0,0);
670  fprintf(fp,"\n\n");
671  break;
672  case 3 :
673  fprintf(fp,"Miscellaneous Nutrients\n\n");
674  for (i = 1; i < 14 ; i++)
675   {
676   food_display_line(fp,ScreenMap[options.screen][i],0,0,0,0);
677   food_display_line(fp,ScreenMap[options.screen][i+13],0,0,0,0);
678   food_display_line(fp,ScreenMap[options.screen][i+26],0,1,0,0);
679   }
680  break;
681  case 4 :
682  food_display_line(fp,ScreenMap[options.screen][1],0,0,1,0);
683  fprintf(fp,"Saturated and Monounsaturated Fatty Acids\n");
684  food_display_line(fp,ScreenMap[options.screen][2],0,1,1,0);
685  for (i = 3; i < 15 ; i++)
686   {
687   food_display_line(fp,ScreenMap[options.screen][i],0,0,1,0);
688   food_display_line(fp,ScreenMap[options.screen][i+13],0,1,1,0);
689   }
690  food_display_line(fp,ScreenMap[options.screen][i],0,1,1,0);
691  break;
692  case 5 :
693  fprintf(fp,"%-27s","Polyunsaturated and Trans Fatty Acids\n\n");
694  for (i = 1; i < 10 ; i++)
695   {
696   food_display_line(fp,ScreenMap[options.screen][i],0,0,1,0);
697   food_display_line(fp,ScreenMap[options.screen][i+9],0,0,1,0);
698   food_display_line(fp,ScreenMap[options.screen][i+18],0,1,1,0);
699   }
700  for (i = 10; i < 13 ; i++)
701   {
702   fprintf(fp,"%-54s"," ");
703   food_display_line(fp,ScreenMap[options.screen][i+18],0,1,1,0);
704   }
705  fprintf(fp,"\n");
706  break;
707  default :
708  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][1]])) fprintf(fp,"Calories(%4.0f)   %5.0f%%     ",DV[ScreenMap[options.screen][1]],food_work.nutrient[ScreenMap[options.screen][1]]/DV[ScreenMap[options.screen][1]]*100);
709  else fprintf(fp,"Calories(%4.0f)    %5s     ",DV[ScreenMap[options.screen][1]],"(nd)");
710  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][14]])) fprintf(fp,"%-14s   %5.0f%%     ",Nutrient[ScreenMap[options.screen][14]],food_work.nutrient[ScreenMap[options.screen][14]]/DV[ScreenMap[options.screen][14]] *100);
711  else fprintf(fp,"%-14s    %5s     ",Nutrient[ScreenMap[options.screen][14]],"(nd)");
712  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][17]])) fprintf(fp,"%-14s   %5.0f%%\n",Nutrient[ScreenMap[options.screen][17]],food_work.nutrient[ScreenMap[options.screen][17]]/DV[ScreenMap[options.screen][17]] *100);
713  else fprintf(fp,"%-14s    %5s\n",Nutrient[ScreenMap[options.screen][17]],"(nd)");
714  fprintf(fp,"Prot/Carb/Fat  %8s     ",protcarbfat);
715  food_display_line(fp,ScreenMap[options.screen][15],1,0,0,0);
716  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][16]])) fprintf(fp,"%-15s  %5.0f%-1s\n",Nutrient[ScreenMap[options.screen][16]],food_work.nutrient[ScreenMap[options.screen][16]],Unit[ScreenMap[options.screen][16]]);
717  else fprintf(fp,"%-15s   %5s\n",Nutrient[ScreenMap[options.screen][16]],"(nd)");
718  fprintf(fp,"\n");
719  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][2]])) fprintf(fp,"%-14s   %5.0f%%     ",Nutrient[ScreenMap[options.screen][2]],food_work.nutrient[ScreenMap[options.screen][2]]/DV[ScreenMap[options.screen][2]] *100);
720  else fprintf(fp,"%-14s    %5s     ",Nutrient[ScreenMap[options.screen][2]],"(nd)");
721  food_display_line(fp,ScreenMap[options.screen][18],1,0,0,0);
722  food_display_line(fp,ScreenMap[options.screen][30],1,1,0,0);
723  food_display_line(fp,ScreenMap[options.screen][3],1,0,0,1);
724  food_display_line(fp,ScreenMap[options.screen][19],1,0,0,0);
725  food_display_line(fp,ScreenMap[options.screen][31],1,1,0,0);
726  if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][4]])) fprintf(fp," %-13s   %5.0f%%     ",Nutrient[ScreenMap[options.screen][4]],food_work.nutrient[ScreenMap[options.screen][4]]/DV[FAMS]*100);
727  else fprintf(fp," %-13s    %5s     ",Nutrient[ScreenMap[options.screen][4]],"(nd)");
728  food_display_line(fp,ScreenMap[options.screen][20],1,0,0,0);
729  food_display_line(fp,ScreenMap[options.screen][32],1,1,0,0);
730  food_display_line(fp,ScreenMap[options.screen][5],1,0,0,1);
731  food_display_line(fp,ScreenMap[options.screen][21],1,0,0,0);
732  food_display_line(fp,ScreenMap[options.screen][33],1,1,0,0);
733  food_display_line(fp,ScreenMap[options.screen][6],1,0,0,2);
734  food_display_line(fp,ScreenMap[options.screen][22],1,0,0,0);
735  food_display_line(fp,ScreenMap[options.screen][34],1,1,0,0);
736  for (i = 7; i < 9 ; i++)
737   {
738   food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
739   food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
740   food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
741   }
742  food_display_line(fp,ScreenMap[options.screen][i],1,0,0,2);
743  food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
744  food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
745  for (i = 10; i < 12 ; i++)
746   {
747   food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
748   food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
749   food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
750   }
751  food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
752  food_display_line(fp,ScreenMap[options.screen][i+16],1,1,0,0);
753  food_display_line(fp,ScreenMap[options.screen][13],1,0,0,0);
754  food_display_line(fp,ScreenMap[options.screen][13+16],1,0,0,0);
755  p3 = 900 * food_work.nutrient[SHORT3] / food_work.nutrient[ENERC_KCAL];
756  p6 = 900 * food_work.nutrient[SHORT6] / food_work.nutrient[ENERC_KCAL];
757  h3 = 900 * food_work.nutrient[LONG3] / food_work.nutrient[ENERC_KCAL];
758  h6 = 900 * food_work.nutrient[LONG6] / food_work.nutrient[ENERC_KCAL];
759  o  = 900 * (food_work.nutrient[FASAT] + food_work.nutrient[FAMS] + food_work.nutrient[FAPU] - food_work.nutrient[SHORT6] - food_work.nutrient[LONG6] - food_work.nutrient[SHORT3] - food_work.nutrient[LONG3]) / food_work.nutrient[ENERC_KCAL];
760  n6 = (int) n6hufa(p3,p6,h3,h6,o,food_work.nutrient[ENERC_KCAL]);
761 fprintf(fp,"Omega-6/3 Balance %2d/%1d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
762  break;
763  }
764 }
765 
food_display_line(FILE * fp,int nut,int dv,int eol,int precision,int indent)766 void food_display_line(FILE *fp, int nut, int dv, int eol, int precision, int indent)
767 {
768 int flags;
769 flags = 100 * dv + 10 * eol + precision;
770 switch (indent)
771  {
772  case 1  : fprintf(fp," %-13s",Nutrient[nut]);
773            break;
774  case 2  : fprintf(fp,"  %-12s",Nutrient[nut]);
775            break;
776  case 4  : fprintf(fp,"    %-10s",Nutrient[nut]);
777            break;
778  default : fprintf(fp,"%-14s",Nutrient[nut]);
779            break;
780  }
781 
782 switch (flags)
783  {
784  case   0 :
785   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s ",food_work.nutrient[nut],Unit[nut]);
786   else fprintf(fp,"%9s%-3s ","(nd)"," ");
787   break;
788  case   1 :
789   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s ",food_work.nutrient[nut],Unit[nut]);
790   else fprintf(fp,"%9s%-3s ","(nd)"," ");
791   break;
792  case  10 :
793 #ifndef DOS
794   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
795   else fprintf(fp,"%9s%-3s\n","(nd)"," ");
796 #else
797   if (nut != VITE && nut != VITK1 && nut != ILE_G && nut != TOCPHG)
798    {
799    if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%7.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
800    else fprintf(fp,"%8s%-3s\n","(nd)"," ");
801    }
802   else
803    {
804    if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
805    else fprintf(fp,"%9s%-3s\n","(nd)"," ");
806    }
807 #endif
808   break;
809  case  11 :
810 #ifndef DOS
811   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
812   else fprintf(fp,"%9s%-3s\n","(nd)"," ");
813 #else
814   if (nut != F4D0 && nut != F18D2CN6 && nut != F20D2CN6 && nut != F20D3 && nut != F20D4 && nut != F20D5 && nut != F22D4 && nut != F24D0)
815    {
816    if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%7.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
817    else fprintf(fp,"%8s%-3s\n","(nd)"," ");
818    }
819   else
820    {
821    if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
822    else fprintf(fp,"%9s%-3s\n","(nd)"," ");
823    }
824 #endif
825   break;
826  case 110 :
827   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"   %5.0f%%\n",food_work.nutrient[nut]/DV[nut]*100);
828   else fprintf(fp,"     %4s\n","(nd)");
829   break;
830  default :
831   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"   %5.0f%%     ",food_work.nutrient[nut]/DV[nut]*100);
832   else fprintf(fp,"    %5s     ","(nd)");
833   break;
834  }
835 }
836 
order_new_recipe()837 void order_new_recipe()
838 {
839 struct food *food_ptr = &recipe_root;
840 while (food_ptr->next != NULL) food_ptr = food_ptr->next;
841 new_recipe->next = NULL;
842 food_ptr->next = new_recipe;
843 }
844 
modify_recipe_food(int num,char * qty)845 void modify_recipe_food(int num, char *qty)
846 {
847 struct food *m, *recipe_ptr = &recipe_root;
848 int count = 0;
849 float newqty;
850 while (recipe_ptr->next != NULL)
851  {
852  count++;
853  if (count == num)
854   {
855   newqty = evaluate_qty(food_number(recipe_ptr->next->food_no),qty);
856   if (newqty == 0)
857    {
858    m = recipe_ptr->next;
859    recipe_ptr->next = recipe_ptr->next->next;
860    free(m);
861    }
862   else recipe_ptr->next->grams = newqty;
863   return;
864   }
865  recipe_ptr = recipe_ptr->next;
866  }
867 }
868 
modify_label_food(int num,char * command)869 void modify_label_food(int num, char *command)
870 {
871 struct food *m = NULL, *pm = NULL, *am = NULL, *po = NULL, *ao = NULL, *recipe_ptr = &recipe_root;
872 int count = 0;
873 int action;
874 action = evaluate_action(command);
875 if (num == action) return;
876 while (recipe_ptr->next != NULL)
877  {
878  count++;
879  if (count == action && action > 0 && num > action)
880   {
881   ao = recipe_ptr;
882   po = recipe_ptr->next;
883   }
884  if (count == action && action > 0 && num < action)
885   {
886   ao = recipe_ptr->next;
887   if (recipe_ptr->next != NULL) po = recipe_ptr->next->next;
888   else po = NULL;
889   }
890  if (count == num)
891   {
892   m = recipe_ptr->next;
893   pm = recipe_ptr->next->next;
894   am = recipe_ptr;
895   if (action == 0)
896    {
897    recipe_ptr->next = recipe_ptr->next->next;
898    free(m);
899    return;
900    }
901   if (action < 0)
902    {
903    if (action == -1 && m->refuse >= 0) m->refuse++;
904    if (action == -1 && m->refuse <  0) m->refuse = 1;
905    if (action == -2 && m->refuse <= 0) m->refuse--;
906    if (action == -2 && m->refuse >  0) m->refuse = -1;
907    if (action == -3 && m->refuse <  0) m->refuse++;
908    if (action == -3 && m->refuse >  0) m->refuse--;
909    return;
910    }
911   }
912  recipe_ptr = recipe_ptr->next;
913  }
914 if (num > count || action > count) return;
915 am->next = pm;
916 ao->next = m;
917 m->next = po;
918 }
919 
compute_derived_fields(struct food * food_ptr)920 void compute_derived_fields(struct food *food_ptr)
921 {
922 float ratio, realcal, alcCalFactor = 6.93;
923 if (!test_for_negative_zero(&food_ptr->nutrient[VITE_ADDED]) || !test_for_negative_zero(&food_ptr->nutrient[TOCPHA])) food_ptr->nutrient[VITE] = (food_ptr->nutrient[VITE_ADDED] / 0.45) + ((food_ptr->nutrient[TOCPHA] - food_ptr->nutrient[VITE_ADDED]) / 0.67);
924 if (test_for_negative_zero(&food_ptr->nutrient[VITE_ADDED]) && test_for_negative_zero(&food_ptr->nutrient[TOCPHA])) food_ptr->nutrient[VITE] = NoData;
925 food_ptr->nutrient[LA] = food_ptr->nutrient[F18D2CN6] > 0 ? food_ptr->nutrient[F18D2CN6] : food_ptr->nutrient[F18D2] - food_ptr->nutrient[F18D2T] - food_ptr->nutrient[F18D2TT] - food_ptr->nutrient[F18D2I] - food_ptr->nutrient[F18D2CLA];
926 if (food_ptr->nutrient[LA] == 0 && test_for_negative_zero(&food_ptr->nutrient[F18D2])) food_ptr->nutrient[LA] = NoData;
927 if (food_ptr->nutrient[LA] < 0) food_ptr->nutrient[LA] = 0;
928 food_ptr->nutrient[SHORT6] = food_ptr->nutrient[LA];
929 food_ptr->nutrient[SHORT6] += food_ptr->nutrient[F18D3CN6];
930 food_ptr->nutrient[ALA] = food_ptr->nutrient[F18D3CN3] > 0 ? food_ptr->nutrient[F18D3CN3] : food_ptr->nutrient[F18D3] - food_ptr->nutrient[F18D3CN6] - food_ptr->nutrient[F18D3I];
931 if (food_ptr->nutrient[ALA] == 0 && test_for_negative_zero(&food_ptr->nutrient[F18D3])) food_ptr->nutrient[ALA] = NoData;
932 if (food_ptr->nutrient[ALA] < 0) food_ptr->nutrient[ALA] = 0;
933 food_ptr->nutrient[SHORT3] = food_ptr->nutrient[ALA];
934 food_ptr->nutrient[SHORT3] += food_ptr->nutrient[F18D4];
935 food_ptr->nutrient[LONG6] = food_ptr->nutrient[F20D2CN6];
936 food_ptr->nutrient[LONG3] = food_ptr->nutrient[F20D5];
937 if (food_ptr->nutrient[F20D3N3] > 0) food_ptr->nutrient[LONG3] += food_ptr->nutrient[F20D3N3];
938 if (food_ptr->nutrient[F20D3N6] > 0) food_ptr->nutrient[LONG6] += food_ptr->nutrient[F20D3N6];
939 if (food_ptr->nutrient[F20D3N3] == 0 && food_ptr->nutrient[F20D3N6] == 0) food_ptr->nutrient[LONG6] += food_ptr->nutrient[F20D3];
940 food_ptr->nutrient[AA] = food_ptr->nutrient[F20D4];
941 if (food_ptr->nutrient[F20D4N6] > 0) food_ptr->nutrient[AA] = food_ptr->nutrient[F20D4N6];
942 food_ptr->nutrient[LONG6] += food_ptr->nutrient[AA];
943 food_ptr->nutrient[LONG3] += food_ptr->nutrient[F22D5];
944 food_ptr->nutrient[LONG6] += food_ptr->nutrient[F22D4];
945 food_ptr->nutrient[LONG3] += food_ptr->nutrient[F21D5];
946 food_ptr->nutrient[EPA] = food_ptr->nutrient[F20D5];
947 food_ptr->nutrient[DHA] = food_ptr->nutrient[F22D6];
948 food_ptr->nutrient[LONG3] += food_ptr->nutrient[F22D6];
949 if (food_ptr->nutrient[SHORT3] == 0 && test_for_negative_zero(&food_ptr->nutrient[ALA]) && test_for_negative_zero(&food_ptr->nutrient[F18D4])) food_ptr->nutrient[SHORT3] = NoData;
950 if (food_ptr->nutrient[LONG3] == 0 && test_for_negative_zero(&food_ptr->nutrient[EPA]) && test_for_negative_zero(&food_ptr->nutrient[F22D5]) && test_for_negative_zero(&food_ptr->nutrient[DHA])) food_ptr->nutrient[LONG3] = NoData;
951 if (food_ptr->nutrient[SHORT6] == 0 && test_for_negative_zero(&food_ptr->nutrient[LA]) && test_for_negative_zero(&food_ptr->nutrient[F18D3CN6])) food_ptr->nutrient[SHORT6] = NoData;
952 if (food_ptr->nutrient[LONG6] == 0 && test_for_negative_zero(&food_ptr->nutrient[F20D2CN6]) && test_for_negative_zero(&food_ptr->nutrient[F20D3]) && test_for_negative_zero(&food_ptr->nutrient[F20D3N6]) && test_for_negative_zero(&food_ptr->nutrient[AA])) food_ptr->nutrient[LONG6] = NoData;
953 food_ptr->nutrient[OMEGA6] = food_ptr->nutrient[SHORT6] + food_ptr->nutrient[LONG6];
954 if (food_ptr->nutrient[OMEGA6] == 0 && test_for_negative_zero(&food_ptr->nutrient[SHORT6]) && test_for_negative_zero(&food_ptr->nutrient[LONG6])) food_ptr->nutrient[OMEGA6] = NoData;
955 food_ptr->nutrient[OMEGA3] = food_ptr->nutrient[SHORT3] + food_ptr->nutrient[LONG3];
956 if (food_ptr->nutrient[OMEGA3] == 0 && test_for_negative_zero(&food_ptr->nutrient[SHORT3]) && test_for_negative_zero(&food_ptr->nutrient[LONG3])) food_ptr->nutrient[OMEGA3] = NoData;
957 
958 if ( food_ptr->prot_cal_factor == 0 && food_ptr->fat_cal_factor == 0 && food_ptr->cho_cal_factor == 0 && food_ptr->nutrient[ENERC_KCAL] > 0)
959  {
960  food_ptr->prot_cal_factor = 4;
961  food_ptr->fat_cal_factor = 9;
962  food_ptr->cho_cal_factor = 4;
963  food_ptr->nutrient[PROT_KCAL] = food_ptr->prot_cal_factor * food_ptr->nutrient[PROCNT];
964  food_ptr->nutrient[FAT_KCAL] = food_ptr->fat_cal_factor * food_ptr->nutrient[FAT];
965  food_ptr->nutrient[CHO_KCAL] = food_ptr->cho_cal_factor * food_ptr->nutrient[CHOCDF];
966  realcal = food_ptr->nutrient[ENERC_KCAL] - (food_ptr->nutrient[ALC] * alcCalFactor);
967  ratio = realcal / (food_ptr->nutrient[PROT_KCAL] + food_ptr->nutrient[FAT_KCAL] + food_ptr->nutrient[CHO_KCAL]);
968  food_ptr->prot_cal_factor *= ratio;
969  food_ptr->fat_cal_factor *= ratio;
970  food_ptr->cho_cal_factor *= ratio;
971  }
972 food_ptr->nutrient[PROT_KCAL] = food_ptr->prot_cal_factor * food_ptr->nutrient[PROCNT];
973 food_ptr->nutrient[FAT_KCAL] = food_ptr->fat_cal_factor * food_ptr->nutrient[FAT];
974 food_ptr->nutrient[CHO_KCAL] = food_ptr->cho_cal_factor * food_ptr->nutrient[CHOCDF];
975 if (!test_for_negative_zero(&food_ptr->nutrient[CHOCDF]))
976  {
977  food_ptr->nutrient[CHO_NONFIB] = food_ptr->nutrient[CHOCDF] - food_ptr->nutrient[FIBTG];
978  if (food_ptr->nutrient[CHO_NONFIB] < 0) food_ptr->nutrient[CHO_NONFIB] = 0;
979  }
980 }
981 
format_serving(char * buffer,float * ratio,struct food * food_ptr)982 char *format_serving(char *buffer, float *ratio, struct food *food_ptr)
983 {
984 sprintf(buffer,"%1.3g",food_ptr->qty * *ratio);
985 strncat(buffer," ",50);
986 strncat(buffer,food_ptr->unit,50);
987 buffer[49] = '\0';
988 return buffer;
989 }
990 
load_foodwork(int max,struct meal * meal_ptr_origin)991 struct meal *load_foodwork(int max, struct meal *meal_ptr_origin)
992 {
993 int meals = 0, meal = 0, count = 0;
994 char meal_date[9];
995 struct meal *meal_ptr = meal_ptr_origin;
996 clear_work();
997 if (max == 0) max = meal_count(meal_ptr);
998 clear_work();
999 while (meal_ptr->next != NULL && meals <= max)
1000  {
1001  meal_ptr = meal_ptr->next;
1002  if (strcmp(meal_date,meal_ptr->meal_date) != 0 || meal != meal_ptr->meal)
1003   {
1004   strcpy(meal_date,meal_ptr->meal_date);
1005   meal = meal_ptr->meal;
1006   meals++;
1007   }
1008  if (meals > max) break;
1009  for (count = 1; count <= *ScreenMap[options.screen] ; count++) if (! test_for_negative_zero(&FoodIndex[meal_ptr->food_no]->nutrient[ScreenMap[options.screen][count]])) food_work.nutrient[ScreenMap[options.screen][count]] = food_work.nutrient[ScreenMap[options.screen][count]] + ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[ScreenMap[options.screen][count]]) / (float) max);
1010  if (options.screen < 2)
1011   {
1012   food_work.nutrient[FAT_KCAL] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[FAT_KCAL]) / (float) max);
1013   food_work.nutrient[PROT_KCAL] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[PROT_KCAL]) / (float) max);
1014   food_work.nutrient[CHO_KCAL] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[CHO_KCAL]) / (float) max);
1015   food_work.nutrient[SHORT3] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[SHORT3]) / (float) max);
1016   food_work.nutrient[LONG3] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[LONG3]) / (float) max);
1017   food_work.nutrient[SHORT6] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[SHORT6]) / (float) max);
1018   food_work.nutrient[LONG6] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[LONG6]) / (float) max);
1019   food_work.nutrient[ALC] += ((options.mealsperday * meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[ALC]) / (float) max);
1020   }
1021  }
1022 return meal_ptr;
1023 }
1024 
n6hufa(float p3,float p6,float h3,float h6,float o,float c)1025 float n6hufa(float p3, float p6, float h3, float h6, float o, float c)
1026 {
1027 float pc6 = .0441, pc3 = .0555, co = 5, ks = .175, hc6 = .7, hc3 = 3;
1028 float hi3 = .005;
1029 /* float hi6 = .04; */
1030 float answer;
1031 /*
1032 printf("%f %f %f %f %f\n",p3,p6,h3,h6,o);
1033 exit(0);
1034 */
1035 /* if (p3 == 0 && p6 == 0 && h3 == 0 && h6 == 0) return 0; */
1036 if (p3 < 0.00000001 && p6 < 0.00000001 && h3 < 0.00000001 && h6 < 0.00000001) return 0;
1037 /* if (c == 0) return 0; */
1038 if (c < 0.00000001) return 0;
1039 answer = 100 / (1 + pc6/p6 * (1 + p3/pc3 + h3/hi3 + o/co + p6/ks)) + 100 / (1 + hc6/h6 * (1 + h3/hc3));
1040 if (answer <= 90 && answer >= 15) return answer;
1041 if (answer > 90) return 90;
1042 else return 15;
1043 }
1044