/* food.c */

/*
    NUT nutrition software 
    Copyright (C) 1996-2008 by Jim Jozwiak.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "food.h"
#include "meal.h"
#include "util.h"
#include "options.h"
#include "nutrient.h"
#include "abbrev.h"
#include "fdgrp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct food food_root, food_work, *new_food, recipe_root, *new_recipe, *FoodIndex[MAX_FOOD];

int DVMap[] =
{
DV_COUNT,ENERC_KCAL,
FAT,FASAT,FAMS,FAPU,OMEGA6,LA,AA,OMEGA3,ALA,EPA,DHA,CHOLE,CHOCDF,FIBTG,CHO_NONFIB,PROCNT,
VITA_IU,THIA,RIBF,NIA,PANTAC,VITB6A,FOL,VITB12,VITC,VITD,VITE,VITK,
CA,CU,FE,MG,MN,P,K,SE,NA,ZN
};

int CarbAminoMap[] =
{
31,CHOCDF,FIBTG,STARCH,SUGAR,FRUS,GALS,GLUS,LACS,MALS,SUCS,
PROCNT,ADPROT,ALA_G,ARG_G,ASP_G,CYS_G,GLU_G,GLY_G,HISTN_G,HYP,ILE_G,
LEU_G,LYS_G,MET_G,PHE_G,PRO_G,SER_G,THR_G,TRP_G,TYR_G,VAL_G
};

int MiscMap[] =
{
30,ENERC_KJ,ASH,WATER,CAFFN,THEBRN,ALC,
FLD,BETN,CHOLN,FOLAC,FOLFD,FOLDFE,RETOL,VITA_RAE,
VITB12_ADDED,VITE_ADDED,
TOCPHA,TOCPHB,TOCPHG,TOCPHD,CARTA,CARTB,CRYPX,LUT_ZEA,LYCPN,
CHOLE,PHYSTR,SITSTR,CAMD5,STID7
};

int SatMonoMap[] =
{
27,FASAT,F4D0,F6D0,F8D0,F10D0,F12D0,F13D0,F14D0,F15D0,F16D0,
F17D0,F18D0,F20D0,F22D0,F24D0,
FAMS,F14D1,F15D1,F16D1,F16D1C,F17D1,
F18D1,F18D1C,F20D1,F22D1,F22D1C,F24D1C
};

int PolyTransMap[] =
{
29,FAPU,F18D2,F18D2CN6,F18D3,F18D3CN3,F18D3CN6,F18D4,F20D2CN6,F20D3,
F20D3N3,F20D3N6,
F20D4,F20D4N6,F20D5,F21D5,F22D4,F22D5,F22D6,
FATRN,FATRNM,F16D1T,F18D1T,F22D1T,FATRNP,F18D2T,F18D2TT,F18D2I,F18D2CLA,F18D3I
};

int *ScreenMap[] =
{
DVMap,DVMap,CarbAminoMap,MiscMap,SatMonoMap,PolyTransMap
};

char *ScreenTitle[] =
{
"Daily Value Percentages","Daily Value Absolute Amounts",
"Carbohydrates and Amino Acids","Miscellaneous Nutrients",
"Saturated and Monounsaturated Fatty Acids","Polyunsaturated and Trans Fatty Acids"
};

int MaxScreen = 6;

int MaxFdGrp = FD_GRP_COUNT;

float DVBase[NUTRIENT_COUNT];

float DV[NUTRIENT_COUNT];

float NoData;

int LookupNutrNo[NUTRIENT_COUNT - DERIVED];
int LookupNut[NUTRNO_ARRAYSIZE];

int FoodCount = 0;

void initializations()
{
int c;
NoData = atof("-0");
test_signsense(&NoData);
for (c=0; c < NUTRIENT_COUNT; c++) DVBase[c] = 0;

DVBase[ENERC_KCAL] = 2000;
DVBase[PROCNT] = 50;
DVBase[FAT] = 65;
DVBase[CHOCDF] = 300;
DVBase[FIBTG] = 25;
DVBase[CHO_NONFIB] = DVBase[CHOCDF] - DVBase[FIBTG];
DVBase[CA] = 1000;
DVBase[P] = 1000;
DVBase[FE] = 18;
DVBase[NA] = 2400;
DVBase[K] = 3500;
DVBase[MG] = 400;
DVBase[ZN] = 15;
DVBase[CU] = 2;
DVBase[MN] = 2;
DVBase[SE] = 70;
DVBase[VITA_IU] = 5000;
DVBase[VITE] = 30;
DVBase[VITK] = 80;
DVBase[THIA] = 1.5;
DVBase[RIBF] = 1.7;
DVBase[NIA] = 20;
DVBase[PANTAC] = 10;
DVBase[VITB6A] = 2;
DVBase[FOL] = 400;
DVBase[VITB12] = 6;
DVBase[VITC] = 60;
DVBase[FASAT] = 20;
DVBase[CHOLE] = 300;
DVBase[VITD] = 400;
DVBase[LA] = 11.574803;
DVBase[AA] = 0.35669291;
DVBase[OMEGA6] = DVBase[LA] + DVBase[AA];
DVBase[ALA] = 2.67;
DVBase[EPA] = 1.3070866;
DVBase[DHA] = 0.92519685;
DVBase[OMEGA3] = DVBase[ALA] + DVBase[EPA] + DVBase[DHA];
DVBase[FAPU] = DVBase[OMEGA6] + DVBase[OMEGA3];
DVBase[FAMS] = 61.5 - DVBase[FASAT] - DVBase[FAPU];
for (c=0; c < NUTRNO_ARRAYSIZE; c++) LookupNut[c] = -1;
for (c=0; c < NUTRIENT_COUNT - DERIVED; c++) LookupNutrNo[c] = -1;
#include "lookup.h"
}

int order_new_food()
{
struct food *food_ptr = &food_root;
int foodnum = 0;
while (food_ptr->next != NULL && namestrcmp(new_food->name, food_ptr->next->name) >= 0)
 {
 food_ptr = food_ptr->next;
 foodnum++;
 }
new_food->next = food_ptr->next;
food_ptr->next = new_food;
return foodnum;
}

void order_new_food_already_sorted()
{
struct food *food_ptr = &food_root;
while (food_ptr->next != NULL) food_ptr = food_ptr->next;
new_food->next = NULL;
food_ptr->next = new_food;
}

int namestrcmp(char *name1, char *name2)
{
char namebuf1[61], namebuf2[61];
int count;
for (count = 0 ; count <= 60 ; count++)
 {
 if (name1[count] == ',') namebuf1[count] = '\a';
 else namebuf1[count] = name1[count]; 
 if (name2[count] == ',') namebuf2[count] = '\a';
 else namebuf2[count] = name2[count]; 
 }
return strcmp(namebuf1,namebuf2);
}

int substring_finder(char *food_name, char *substr)
{
int i;
char *token;
char substring[61];
strcpy(substring,substr);
token = strtok(substring, ", ");
while (token != NULL)
 {
 if (strstr(food_name,token) != NULL)
  {
  token = strtok(NULL,", ");
  continue;
  }
 for (i=0; i < Abbrev_Count; i++) if (strcmp(token,Abbreviations[i]) == 0) break;
 if (i == Abbrev_Count) return 0;
 if (strstr(food_name,Abbreviations[i % 2 == 0 ? i+1 : i-1]) == NULL) return 0;
 token = strtok(NULL,", ");
 }
return 1;
}

struct food *food_choice(char *screentitle, int usual)
{
struct food *food_ptr;
struct food *ptrlist[MAX_FOOD];
int count = 0, charcount, keysize, lines, junk;
char substring[61], key[61];
for ( ; ; )
 {
 key_decode(substring,key);
 if (strcmp(substring,"") == 0)
  {
  header(screentitle);
  spacer(0);
  if (strcmp(screentitle,"NUT:  Add Recipes") == 0) printf("\nType food name to add to recipe (or <enter> to quit):  ");
  else printf("\nType food name to select (or <enter> to quit):  ");
  get_string(substring,60);
  key[0] = '\0';
  key_clean();
  }
 if (substring[0] == '\0') return (struct food *) -1;
 for (charcount = 0 ; charcount < 60 ; charcount++) substring[charcount] = toupper(substring[charcount]);
 key_encode(substring,key);
 if (strncmp(substring,"THEUSUAL",8) == 0 && usual) return (struct food *) -2;
 header(screentitle);
 food_ptr = &food_root;
 keysize = strlen(key); lines = 0; count = 0;
 while ((food_ptr = food_ptr->next)) if (substring_finder(food_ptr->name,substring) && strncmp(key,food_ptr->name,keysize) == 0) ptrlist[++count] = food_ptr;
 while (count == 0)
  {
  key_clean();
  spacer(-1);
  printf("No food named \"%s\".  Try another (or <enter> to quit):  ",substring);
  get_string(substring,60);
  if (substring[0] == '\0') return (struct food *) 0;
  for (charcount = 0 ; charcount < 60 ; charcount++) substring[charcount] = toupper(substring[charcount]);
  key_encode(substring,key);
 if (strncmp(substring,"THEUSUAL",8) == 0 && usual) return (struct food *) -2;
  header(screentitle);
  food_ptr = &food_root;
  keysize = strlen(key); lines = 0; count = 0;
  while ((food_ptr = food_ptr->next)) if (substring_finder(food_ptr->name,substring) && strncmp(key,food_ptr->name,keysize) == 0) ptrlist[++count] = food_ptr;
  }
 if (count == 1) return ptrlist[1];
 if (count < 21)
  {
  for (lines = 1 ; lines <= count ; lines++) printf("%2d. %s\n",lines,ptrlist[lines]->name);
  spacer(lines - 2);
  printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
  get_string(key,60);
  junk = 0;
  if (strcmp(key,"b") == 0 || strcmp(key,"B") == 0) junk = -38;
  if (junk == -38) 
   {
   key_decode(substring,key);
   continue;
   }
  junk = atoi(key); 
  if (junk > 0 && junk <= count) 
   {
   key_encode(substring,ptrlist[junk]->name);
   return ptrlist[junk];
   }
  else return (struct food *) 0;   
  }
 if (count > 20) food_subcat(substring, key, ptrlist, count);
 }
}

void food_subcat(char *substring, char *key, struct food **ptrlist, int count)
{
char food_screen[2000];
char *fsptr[500], *thisfsptr, *bufptr, buffer[61], format[11], format100[11], tokenhead[61], junkstring[120];
char *col[10], colformat1[110], colformat2[110];
int i, l, s, subcount = 0, charcount, tokencount, nlength, tokenlength, tokenunique, headlength = 0, linecount, savelinecount = 0, tokenmax = 0, colcount;
for (linecount = 1 ; linecount <= 20 ; linecount++) fsptr[linecount] = food_screen + (61 * linecount);
for (linecount = 1 ; linecount <= count ; linecount++)
 {
 tokencount = 0;
 nlength = strlen(ptrlist[linecount]->name);
 for (charcount = 0 ; charcount <= nlength ; charcount++) if (ptrlist[linecount]->name[charcount] == ',') tokencount++;
 if (tokencount > tokenmax) tokenmax = tokencount;
 }
while (subcount < count && tokenmax > -1)
 {
 tokenmax--;
 subcount = 0;
 for (linecount = 1; subcount < count && linecount <= 20 ; linecount++)
  {
  subcount++;
  nlength = strlen(ptrlist[subcount]->name);
  thisfsptr = fsptr[linecount];
  tokencount = 0;
  for (charcount = 0 ; charcount <= nlength ; charcount++)
   {
   if (ptrlist[subcount]->name[charcount] == ',') tokencount++;
   if (tokencount == tokenmax) 
    {
    thisfsptr[charcount] = '\0';
    break;
    }
   thisfsptr[charcount] = ptrlist[subcount]->name[charcount];
   if (ptrlist[subcount]->name[charcount] == '\0') break;
   }
  if (linecount > 1 && 0 == strcmp(fsptr[linecount],fsptr[linecount-1])) linecount--;
  }
 savelinecount = --linecount;
 }
if (savelinecount > 1)
 {
 for (linecount = 1; linecount <= savelinecount ; linecount++) printf("%2d.  %s\n",linecount,fsptr[linecount]);
 spacer(savelinecount-1);
 printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
 get_string(junkstring,20);
 if (strcmp(junkstring,"b") == 0 || strcmp(junkstring,"B") == 0) 
  {
  key_take();
  return;
  }
 linecount = atoi(junkstring);
 if (linecount > 0 && linecount <= savelinecount) 
  {
  if (headlength < 1) strcpy(key,fsptr[linecount]);
  if (headlength > 0)
   {
   strcpy(key,tokenhead);
   strcat(key,fsptr[linecount]);
   }
  for (subcount = 1 ; subcount <= count ; subcount++) if (strcmp(key,ptrlist[subcount]->name) == 0) break;
  if (--subcount == count) strcat(key,",");
  }
 else
  {
  key[0] = '\0';
  substring[0] = '\0';
  }
 key_encode(substring,key);
 }
else
 {
 tokenhead[0] = '\0';
 for (tokenmax = 1 ; ; tokenmax++)
  {
  buffer[0] = '\0';
  tokenunique = 0;
  tokenlength = 0;
  for (subcount = 1 ; subcount <= count ; subcount++)
   {
   bufptr = ptrlist[subcount]->name;
   nlength = 0;
   for (tokencount = 1 ; tokencount <= tokenmax ; tokencount++)
    {
    bufptr += nlength;
    bufptr += strspn(bufptr,",");
    nlength = strcspn(bufptr,",");
    } 
   if (nlength > tokenlength) 
    {
    tokenlength = nlength;
    tokenunique++;
    strncpy(buffer,bufptr,nlength);
    buffer[nlength] = '\0';
    }
   else if (nlength < tokenlength) 
    {
    tokenunique++;
    strncpy(buffer,bufptr,nlength);
    buffer[nlength] = '\0';
    }
   else if (strncmp(buffer,bufptr,nlength) != 0)
    {
    tokenunique++;
    strncpy(buffer,bufptr,nlength);
    buffer[nlength] = '\0';
    }
   }
  if (tokenunique == 1)
   {
   strcat(buffer,",");
   strcat(tokenhead,buffer);
   }
  if (tokenunique != 1) break;
  }
 if (tokenhead[0] == '\0') savelinecount = 20;
 else savelinecount = 19; 
 headlength = strlen(tokenhead);
#ifndef DOS
 while ( savelinecount * (81 / (tokenlength + 5 ) ) < tokenunique )
#else
 while ( savelinecount * (80 / (tokenlength + 5 ) ) < tokenunique )
#endif
  {
  buffer[0] = '\0';
  tokenunique = 0 ;
  tokenlength--;
  for (subcount = 1 ; subcount <= count ; subcount++)
   {
   bufptr = ptrlist[subcount]->name + headlength;
   nlength = strcspn(bufptr,",");
   while (*(bufptr + nlength - 1) == ' ') nlength--;
   if (nlength > tokenlength) nlength = tokenlength;
   if (strncmp(buffer,bufptr,nlength) != 0)
    {
    tokenunique++;
    strncpy(buffer,bufptr,nlength);
    buffer[nlength] = '\0';
    }
   }
  }
 for (linecount = 0 ; linecount <= (tokenunique+2) ; linecount++) fsptr[linecount] = food_screen + ((tokenlength+1) * linecount);
 food_screen[0] = '\0';
 linecount = 0;
 for (subcount = 1 ; subcount <= count ; subcount++)
  { 
  bufptr = ptrlist[subcount]->name + headlength;
  nlength = (strcspn(bufptr,","));
  if (nlength > tokenlength) nlength = tokenlength;
  while (*(bufptr + nlength - 1) == ' ') nlength--;
  strncpy(fsptr[linecount + 1],bufptr,nlength);
  thisfsptr = fsptr[linecount + 1];
  thisfsptr[nlength] = '\0';
  if (strncmp(fsptr[linecount],fsptr[linecount + 1],nlength) != 0) linecount++;
  }
 sprintf(format,"%%2d. %%-%ds",tokenlength);
 sprintf(format100,"%%3d. %%-%ds",tokenlength);
 strcpy(colformat1,format);
 strcpy(colformat2,format);
 colcount = (linecount % savelinecount == 0 ? 0 : 1) + (linecount / savelinecount);
 if (colcount > 7)
  {
  spacer(-1);
  printf("Too many foods meet criterion.  Press <enter> to continue...");
  i = get_int();
  key_take();
  return;
  } 
 if (colcount < 8)
  {
  for (i = 2 ; i <= colcount ; i++)
   {
   if (i != colcount) strcat(colformat1," ");
   strcat(colformat2," ");
   if ((i * savelinecount) < 100 || tokenunique < 100)
    {
    if (i != colcount) strcat(colformat1,format);
    strcat(colformat2,format);
    }
   else 
    {
    if (i != colcount) strcat(colformat1,format100);
    strcat(colformat2,format100);
    }
   }
  strcat(colformat1,"\n");
  strcat(colformat2,"\n");
  col[colcount - 1] = colformat1;
  col[colcount] = colformat2;
  if (headlength > 0 ) printf("%-s\n",tokenhead);
  if ( linecount < savelinecount ) savelinecount = linecount;
  l = linecount ; s = savelinecount;
  for (i = 1 ; i <= savelinecount ; i++)
   {
   if      (i+(1*s)>l) printf(col[1],i,fsptr[i]);
   else if (i+(2*s)>l) printf(col[2],i,fsptr[i],i+s,fsptr[i+s]);
   else if (i+(3*s)>l) printf(col[3],i,fsptr[i],i+s,fsptr[i+s],i+(2*s),fsptr[i+(2*s)]);
   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)]);
   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)]);
   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)]);
   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)]);
   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)]);
   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)]);
   }
  spacer(savelinecount < 19 ? savelinecount : 19);
  printf("Type number of food category (\"b\" to go back, <enter> to quit):  ");
  get_string(junkstring,20);
  if (strcmp(junkstring,"b") == 0 || strcmp(junkstring,"B") == 0) 
   {
   key_take();
   return;
   }
  i = atoi(junkstring);
  if (i > 0 && i <= linecount)
   {
   if (headlength > 0)
    {
    strcpy(key,tokenhead);
    strcat(key,fsptr[i]);
    }
   else strcpy(key,fsptr[i]);
   }
  else
   {
   key[0] = '\0';
   substring[0] = '\0';
   }
  key_encode(substring,key);
  }
 }
}

void food_show(struct food *food_ptr, float *ratio)
{
char servingstring[62];
int count;
printf("%-60s   Grams  %8.2f\n",food_ptr->name,food_ptr->grams * *ratio);
printf("Serving:  %-50s   Ounces  %7.2f\n",format_serving(servingstring,ratio,food_ptr),*ratio * food_ptr->grams / GRAMS_IN_OUNCE);
printf("          %-50s   Water    %6.2f%%\n"," ",food_ptr->nutrient[WATER] > 0 ? food_ptr->nutrient[WATER] : 0.0);
if ( ! options.custom && options.screen == 0 ) printf("Percentages of \"Daily Values\" in this serving:                 Refuse   %3d%%\n\n",food_ptr->refuse);
if ( options.custom && options.screen == 0 )     printf("Percentages of customized DV in this serving:                  Refuse   %3d%%\n\n",food_ptr->refuse);
if ( options.screen > 0 )                 printf("Nutrients in this serving:                                     Refuse   %3d%%\n\n",food_ptr->refuse);
for (count = 0; count < NUTRIENT_COUNT; count++) food_work.nutrient[count] = *ratio * food_ptr->nutrient[count] * food_ptr->grams / 100; 
food_display(stdout);
spacer(20);
}

struct food *food_number(int i)
{
return FoodIndex[i];
}

int find_ndbno(int ndbno)
{
struct food *food_ptr = &food_root;
while (food_ptr->next != NULL)
 {
 food_ptr = food_ptr->next;
 if (food_ptr->ndb_no == ndbno) return food_ptr->food_no;
 }
return -1;
}

struct food *find_ndbno_ptr(int ndbno)
{
struct food *food_ptr = &food_root;
while (food_ptr->next != NULL)
 {
 food_ptr = food_ptr->next;
 if (food_ptr->ndb_no == ndbno) return food_ptr;
 }
return NULL;
}

void make_food_index()
{
struct food *food_ptr = &food_root;
FoodCount = 0;
while (food_ptr->next != NULL)
 {
 food_ptr = food_ptr->next;
 food_ptr->food_no = FoodCount;
 FoodIndex[FoodCount++] = food_ptr;
 }
}

int modify_food_index(int foodnum, struct food *food_ptr)
{
int count;
for (count = FoodCount; count > foodnum; count--) FoodIndex[count] = FoodIndex[count-1];
FoodIndex[foodnum] = food_ptr;
FoodCount++;
food_ptr = &food_root;
for (count = 0; count < FoodCount; count++)
 {
 food_ptr = food_ptr->next;
 food_ptr->food_no = count;
 }
return foodnum;
}

void clear_work()
{
int count;
for (count = 0; count < NUTRIENT_COUNT; count++) food_work.nutrient[count] = NoData;
food_work.grams = 0;
food_work.refuse = 0;
}

void food_display(FILE *fp)
{
int i, n6;
float pctfat = 0, pctcarb = 0, pctprot = 0;
float p3, p6, h3, h6, o;
char carbprotfat[9];
if (food_work.nutrient[ENERC_KCAL] > 0.05)
 {
 pctcarb = 100 * food_work.nutrient[CHO_KCAL] / food_work.nutrient[ENERC_KCAL];
 pctprot = 100 * food_work.nutrient[PROT_KCAL] / food_work.nutrient[ENERC_KCAL]; 
 pctfat = 100 * food_work.nutrient[FAT_KCAL] / food_work.nutrient[ENERC_KCAL];
 if (test_for_negative_zero(&pctcarb)) pctcarb = 0;
 if (test_for_negative_zero(&pctprot)) pctprot = 0;
 if (test_for_negative_zero(&pctfat)) pctfat = 0;
 }
else
 {
 pctcarb = 0; pctprot = 0; pctfat = 0;
 }
sprintf(carbprotfat,"%1.0f/%1.0f/%1.0f",pctcarb,pctprot,pctfat);
switch (options.screen)
 {
 case 1 :
 food_display_line(fp,ScreenMap[options.screen][1],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][14],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][17],0,1,0,0);
 fprintf(fp,"Carb/Prot/Fat    %8s  ",carbprotfat);
 food_display_line(fp,ScreenMap[options.screen][15],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][16],0,1,0,0);
 fprintf(fp,"\n");
 food_display_line(fp,ScreenMap[options.screen][2],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][18],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][30],0,1,0,0);
 for (i = 3; i < 6 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,1);
  food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],0,0,0,2);
 food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
 for (i = 7; i < 9 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
  food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],0,0,0,2);
 food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
 for (i = 10; i < 12 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
  food_display_line(fp,ScreenMap[options.screen][i+16],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+28],0,1,0,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],0,0,0,4);
 food_display_line(fp,ScreenMap[options.screen][i+16],0,1,0,0);
 food_display_line(fp,ScreenMap[options.screen][13],0,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][13+16],0,0,0,0);
 p3 = 902 * food_work.nutrient[SHORT3] / food_work.nutrient[ENERC_KCAL];
 p6 = 902 * food_work.nutrient[SHORT6] / food_work.nutrient[ENERC_KCAL];
 h3 = 902 * food_work.nutrient[LONG3] / food_work.nutrient[ENERC_KCAL];
 h6 = 902 * food_work.nutrient[LONG6] / food_work.nutrient[ENERC_KCAL];
 o  = 902 * food_work.nutrient[FAT] * options.fattyacidfactor / food_work.nutrient[ENERC_KCAL] - food_work.nutrient[SHORT6] - food_work.nutrient[LONG6] - food_work.nutrient[SHORT3] - food_work.nutrient[LONG3];
 n6 = (int) n6hufa(p3,p6,h3,h6,o,food_work.nutrient[ENERC_KCAL]);
 fprintf(fp,"Omega-6/3 Balance %2d/%2d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
/*
 if (options.n6hufa == 0 || (options.n6hufa < 90 && options.n6hufa > 15)) fprintf(fp,"Omega-6/3 Balance %2d/%2d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
 else fprintf(fp,"\n");
*/
 break;
 case 2 :
 fprintf(fp,"%-27s","Carbohydrates");
 fprintf(fp,"%-27s\n\n","Amino Acids");
 for (i = 1; i < 5 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+10],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+21],0,1,0,0);
  }
 for (i = 5; i < 11 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,1);
  food_display_line(fp,ScreenMap[options.screen][i+10],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+21],0,1,0,0);
  }
 fprintf(fp,"%-27s"," ");
 food_display_line(fp,ScreenMap[options.screen][i+10],0,1,0,0);
 fprintf(fp,"\n\n");
 break;
 case 3 :
 fprintf(fp,"Miscellaneous Nutrients\n\n");
 for (i = 1; i < 11 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+10],0,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+20],0,1,0,0);
  }
 fprintf(fp,"\n\n\n");
 break;
 case 4 :
 food_display_line(fp,ScreenMap[options.screen][1],0,0,1,0);
 fprintf(fp,"Saturated and Monounsaturated Fatty Acids\n");
 food_display_line(fp,ScreenMap[options.screen][2],0,1,1,0);
 for (i = 3; i < 15 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,1,0);
  food_display_line(fp,ScreenMap[options.screen][i+13],0,1,1,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],0,1,1,0);
 break;
 case 5 :
 fprintf(fp,"%-27s","Polyunsaturated and Trans Fatty Acids\n\n");
 for (i = 1; i < 10 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],0,0,1,0);
  food_display_line(fp,ScreenMap[options.screen][i+9],0,0,1,0);
  food_display_line(fp,ScreenMap[options.screen][i+18],0,1,1,0);
  }
 for (i = 10; i < 12 ; i++)
  {
  fprintf(fp,"%-54s"," ");
  food_display_line(fp,ScreenMap[options.screen][i+18],0,1,1,0);
  }
 fprintf(fp,"\n\n");
 break;
 default :
 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);
 else fprintf(fp,"Calories(%4.0f)    %5s     ",DV[ScreenMap[options.screen][1]],"(nd)");
 if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][14]])) fprintf(fp,"%-14s   %5.0f%%     ",Nutrient[ScreenMap[options.screen][14]],dv_cho());
 else fprintf(fp,"%-14s    %5s     ",Nutrient[ScreenMap[options.screen][14]],"(nd)");
 if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][17]])) fprintf(fp,"%-14s   %5.0f%%\n",Nutrient[ScreenMap[options.screen][17]],dv_pro());
 else fprintf(fp,"%-14s    %5s\n",Nutrient[ScreenMap[options.screen][17]],"(nd)");
 fprintf(fp,"Carb/Prot/Fat  %8s     ",carbprotfat);
 food_display_line(fp,ScreenMap[options.screen][15],1,0,0,0);
 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]]);
 else fprintf(fp,"%-15s   %5s\n",Nutrient[ScreenMap[options.screen][16]],"(nd)");
 fprintf(fp,"\n");
 if (! test_for_negative_zero(&food_work.nutrient[ScreenMap[options.screen][2]])) fprintf(fp,"%-14s   %5.0f%%     ",Nutrient[ScreenMap[options.screen][2]],dv_fat());
 else fprintf(fp,"%-14s    %5s     ",Nutrient[ScreenMap[options.screen][2]],"(nd)");
 food_display_line(fp,ScreenMap[options.screen][18],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][30],1,1,0,0);
 food_display_line(fp,ScreenMap[options.screen][3],1,0,0,1);
 food_display_line(fp,ScreenMap[options.screen][19],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][31],1,1,0,0);
 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);
 else fprintf(fp," %-13s    %5s     ",Nutrient[ScreenMap[options.screen][4]],"(nd)");
 food_display_line(fp,ScreenMap[options.screen][20],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][32],1,1,0,0);
 food_display_line(fp,ScreenMap[options.screen][5],1,0,0,1);
 food_display_line(fp,ScreenMap[options.screen][21],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][33],1,1,0,0);
 food_display_line(fp,ScreenMap[options.screen][6],1,0,0,2);
 food_display_line(fp,ScreenMap[options.screen][22],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][34],1,1,0,0);
 for (i = 7; i < 9 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
  food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],1,0,0,2);
 food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
 for (i = 10; i < 12 ; i++)
  {
  food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
  food_display_line(fp,ScreenMap[options.screen][i+16],1,0,0,0);
  food_display_line(fp,ScreenMap[options.screen][i+28],1,1,0,0);
  }
 food_display_line(fp,ScreenMap[options.screen][i],1,0,0,4);
 food_display_line(fp,ScreenMap[options.screen][i+16],1,1,0,0);
 food_display_line(fp,ScreenMap[options.screen][13],1,0,0,0);
 food_display_line(fp,ScreenMap[options.screen][13+16],1,0,0,0);
 p3 = 902 * food_work.nutrient[SHORT3] / food_work.nutrient[ENERC_KCAL];
 p6 = 902 * food_work.nutrient[SHORT6] / food_work.nutrient[ENERC_KCAL];
 h3 = 902 * food_work.nutrient[LONG3] / food_work.nutrient[ENERC_KCAL];
 h6 = 902 * food_work.nutrient[LONG6] / food_work.nutrient[ENERC_KCAL];
 o  = 902 * food_work.nutrient[FAT] * options.fattyacidfactor / food_work.nutrient[ENERC_KCAL] - food_work.nutrient[SHORT6] - food_work.nutrient[LONG6] - food_work.nutrient[SHORT3] - food_work.nutrient[LONG3];
 n6 = (int) n6hufa(p3,p6,h3,h6,o,food_work.nutrient[ENERC_KCAL]);               
fprintf(fp,"Omega-6/3 Balance %2d/%2d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
/*
 if (options.n6hufa == 0 || (options.n6hufa < 90 && options.n6hufa > 15)) fprintf(fp,"Omega-6/3 Balance %2d/%2d\n",n6 == 0 ? 0 : n6,n6 == 0 ? 0 : 100-n6);
 else fprintf(fp,"\n");
*/
 break;
 }
}

void food_display_line(FILE *fp, int nut, int dv, int eol, int precision, int indent)
{
int flags;
flags = 100 * dv + 10 * eol + precision;
switch (indent)
 {
 case 1  : fprintf(fp," %-13s",Nutrient[nut]);
           break;
 case 2  : fprintf(fp,"  %-12s",Nutrient[nut]);
           break;
 case 4  : fprintf(fp,"    %-10s",Nutrient[nut]);
           break;
 default : fprintf(fp,"%-14s",Nutrient[nut]);
           break;
 }

switch (flags)
 {
 case   0 :
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s ",food_work.nutrient[nut],Unit[nut]);
  else fprintf(fp,"%9s%-3s ","(nd)"," ");
  break;
 case   1 :
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s ",food_work.nutrient[nut],Unit[nut]);
  else fprintf(fp,"%9s%-3s ","(nd)"," ");
  break;
 case  10 :
#ifndef DOS
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
  else fprintf(fp,"%9s%-3s\n","(nd)"," ");
#else
  if (nut != VITE && nut != VITK && nut != ILE_G)
   {
   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%7.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
   else fprintf(fp,"%8s%-3s\n","(nd)"," ");
   }
  else
   {
   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.1f %-3s\n",food_work.nutrient[nut],Unit[nut]);
   else fprintf(fp,"%9s%-3s\n","(nd)"," ");
   }
#endif
  break;
 case  11 :
#ifndef DOS
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
  else fprintf(fp,"%9s%-3s\n","(nd)"," ");
#else
  if (nut != F4D0 && nut != F18D2CN6 && nut != F20D2CN6 && nut != F20D3 && nut != F20D4 && nut != F20D5 && nut != F22D4 && nut != F24D0)
   {
   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%7.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
   else fprintf(fp,"%8s%-3s\n","(nd)"," ");
   }
  else
   {
   if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"%8.2f %-3s\n",food_work.nutrient[nut],Unit[nut]);
   else fprintf(fp,"%9s%-3s\n","(nd)"," ");
   }
#endif
  break;
 case 110 :
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"   %5.0f%%\n",food_work.nutrient[nut]/DV[nut]*100);
  else fprintf(fp,"     %4s\n","(nd)");
  break;
 default :
  if (! test_for_negative_zero(&food_work.nutrient[nut])) fprintf(fp,"   %5.0f%%     ",food_work.nutrient[nut]/DV[nut]*100);
  else fprintf(fp,"    %5s     ","(nd)");
  break;
 }
}

void order_new_recipe()
{
struct food *food_ptr = &recipe_root;
while (food_ptr->next != NULL) food_ptr = food_ptr->next;
new_recipe->next = NULL;
food_ptr->next = new_recipe;
}

void modify_recipe_food(int num, char *qty)
{
struct food *m, *recipe_ptr = &recipe_root;
int count = 0;
float newqty;
while (recipe_ptr->next != NULL)
 {
 count++;
 if (count == num)
  {
  newqty = evaluate_qty(food_number(recipe_ptr->next->food_no),qty);
  if (newqty == 0)
   {
   m = recipe_ptr->next;
   recipe_ptr->next = recipe_ptr->next->next;
   free(m);
   }
  else recipe_ptr->next->grams = newqty;
  return;
  }
 recipe_ptr = recipe_ptr->next;
 }
}

void modify_label_food(int num, char *command)
{
struct food *m = NULL, *pm = NULL, *am = NULL, *po = NULL, *ao = NULL, *recipe_ptr = &recipe_root;
int count = 0;
int action;
action = evaluate_action(command);
if (num == action) return;
while (recipe_ptr->next != NULL)
 {
 count++;
 if (count == action && action > 0 && num > action)
  {
  ao = recipe_ptr;
  po = recipe_ptr->next;
  }
 if (count == action && action > 0 && num < action)
  {
  ao = recipe_ptr->next;
  if (recipe_ptr->next != NULL) po = recipe_ptr->next->next;
  else po = NULL;
  }
 if (count == num)
  {
  m = recipe_ptr->next;
  pm = recipe_ptr->next->next;
  am = recipe_ptr;
  if (action == 0)
   {
   recipe_ptr->next = recipe_ptr->next->next;
   free(m);
   return;
   }
  if (action < 0)
   {
   if (action == -1 && m->refuse >= 0) m->refuse++;
   if (action == -1 && m->refuse <  0) m->refuse = 1;
   if (action == -2 && m->refuse <= 0) m->refuse--;
   if (action == -2 && m->refuse >  0) m->refuse = -1;
   if (action == -3 && m->refuse <  0) m->refuse++;
   if (action == -3 && m->refuse >  0) m->refuse--;
   return;
   }
  }
 recipe_ptr = recipe_ptr->next;
 }
if (num > count || action > count) return;
am->next = pm;
ao->next = m;
m->next = po;
}

void compute_derived_fields(struct food *food_ptr)
{
float ratio, realcal, alcCalFactor = 6.93;;
food_ptr->nutrient[VITE] = 1.5 * food_ptr->nutrient[TOCPHA];
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];
if (food_ptr->nutrient[LA] == 0 && test_for_negative_zero(&food_ptr->nutrient[F18D2])) food_ptr->nutrient[LA] = NoData;
if (food_ptr->nutrient[LA] < 0) food_ptr->nutrient[LA] = 0;
food_ptr->nutrient[SHORT6] = food_ptr->nutrient[LA];
food_ptr->nutrient[SHORT6] += food_ptr->nutrient[F18D3CN6];
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];
if (food_ptr->nutrient[ALA] == 0 && test_for_negative_zero(&food_ptr->nutrient[F18D3])) food_ptr->nutrient[ALA] = NoData;
if (food_ptr->nutrient[ALA] < 0) food_ptr->nutrient[ALA] = 0;
food_ptr->nutrient[SHORT3] = food_ptr->nutrient[ALA];
food_ptr->nutrient[SHORT3] += food_ptr->nutrient[F18D4];
food_ptr->nutrient[LONG6] = food_ptr->nutrient[F20D2CN6];
if (food_ptr->nutrient[F20D3N3] > 0) food_ptr->nutrient[LONG3] += food_ptr->nutrient[F20D3N3];
if (food_ptr->nutrient[F20D3N6] > 0) food_ptr->nutrient[LONG6] += food_ptr->nutrient[F20D3N6];
if (food_ptr->nutrient[F20D3N3] == 0 && food_ptr->nutrient[F20D3N6] == 0) food_ptr->nutrient[LONG6] += food_ptr->nutrient[F20D3];
food_ptr->nutrient[AA] = food_ptr->nutrient[F20D4];
if (food_ptr->nutrient[F20D4N6] > 0) food_ptr->nutrient[AA] = food_ptr->nutrient[F20D4N6];
food_ptr->nutrient[LONG6] += food_ptr->nutrient[AA];
food_ptr->nutrient[EPA] = food_ptr->nutrient[F20D5];
food_ptr->nutrient[LONG3] = food_ptr->nutrient[F20D5];
food_ptr->nutrient[LONG3] += food_ptr->nutrient[F22D5];
food_ptr->nutrient[DHA] = food_ptr->nutrient[F22D6];
food_ptr->nutrient[LONG3] += food_ptr->nutrient[F22D6];
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;
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;
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;
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;
food_ptr->nutrient[OMEGA6] = food_ptr->nutrient[SHORT6] + food_ptr->nutrient[LONG6];
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;
food_ptr->nutrient[OMEGA3] = food_ptr->nutrient[SHORT3] + food_ptr->nutrient[LONG3];
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;

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)
 {
 food_ptr->prot_cal_factor = 4;
 food_ptr->fat_cal_factor = 9;
 food_ptr->cho_cal_factor = 4;
 food_ptr->nutrient[PROT_KCAL] = food_ptr->prot_cal_factor * food_ptr->nutrient[PROCNT];
 food_ptr->nutrient[FAT_KCAL] = food_ptr->fat_cal_factor * food_ptr->nutrient[FAT];
 food_ptr->nutrient[CHO_KCAL] = food_ptr->cho_cal_factor * food_ptr->nutrient[CHOCDF];
 realcal = food_ptr->nutrient[ENERC_KCAL] - (food_ptr->nutrient[ALC] * alcCalFactor);
 ratio = realcal / (food_ptr->nutrient[PROT_KCAL] + food_ptr->nutrient[FAT_KCAL] + food_ptr->nutrient[CHO_KCAL]);
 food_ptr->prot_cal_factor *= ratio;
 food_ptr->fat_cal_factor *= ratio;
 food_ptr->cho_cal_factor *= ratio;
 }
food_ptr->nutrient[PROT_KCAL] = food_ptr->prot_cal_factor * food_ptr->nutrient[PROCNT];
food_ptr->nutrient[FAT_KCAL] = food_ptr->fat_cal_factor * food_ptr->nutrient[FAT];
food_ptr->nutrient[CHO_KCAL] = food_ptr->cho_cal_factor * food_ptr->nutrient[CHOCDF];
food_ptr->nutrient[CHO_NONFIB] = food_ptr->nutrient[CHOCDF] - food_ptr->nutrient[FIBTG];
if (food_ptr->nutrient[CHO_NONFIB] < 0) food_ptr->nutrient[CHO_NONFIB] = 0;
}

float dv_fat()
{
float targetpct, totalcal, totaldv, imaginarydv, diff;
targetpct = food_work.nutrient[ENERC_KCAL] / DV[ENERC_KCAL];
if (options.pccarb == 0 && options.pcprotein == 0)
 {
 totalcal = food_work.nutrient[PROCNT] * options.protcalpergm + food_work.nutrient[CHOCDF] * options.carbcalpergm + food_work.nutrient[FAT] * options.fatcalpergm;
 totaldv = DV[PROCNT] * options.protcalpergm + DV[CHOCDF] * options.carbcalpergm + DV[FAT] * options.fatcalpergm;
 imaginarydv = totalcal / targetpct;
 diff = (totaldv - imaginarydv) / options.fatcalpergm;
 if (DV[FAT] > diff) return food_work.nutrient[FAT] / (DV[FAT] - diff) * 100;
 else return food_work.nutrient[FAT] / DV[FAT] * 100;
 }
else return diff = 100 * food_work.nutrient[FAT_KCAL] / (DV[ENERC_KCAL] * (1 - (options.pccarb > 0 ? options.pccarb / 100 : DV[CHOCDF] * options.carbcalpergm / DV[ENERC_KCAL]) - (options.pcprotein > 0 ? options.pcprotein / 100 : DV[PROCNT] * options.protcalpergm / DV[ENERC_KCAL])));
}

float dv_cho()
{
if (options.pccarb > 0) return food_work.nutrient[CHO_KCAL] / DV[ENERC_KCAL] / options.pccarb * 10000;
else return food_work.nutrient[CHOCDF] / DV[CHOCDF] * 100;
}

float dv_pro()
{
if (options.pcprotein > 0) return food_work.nutrient[PROT_KCAL] / DV[ENERC_KCAL] / options.pcprotein * 10000;
else return food_work.nutrient[PROCNT] / DV[PROCNT] * 100;
}

char *format_serving(char *buffer, float *ratio, struct food *food_ptr)
{
sprintf(buffer,"%1.3g",food_ptr->qty * *ratio);
strncat(buffer," ",50);
strncat(buffer,food_ptr->unit,50);
buffer[49] = '\0';
return buffer;
}

float n6hufa(float p3, float p6, float h3, float h6, float o, float c)
{
float pc6 = .0441, pc3 = .0555, co = 5, ks = .175, hc6 = .7, hc3 = 3;
float hi3 = .005;
/* float hi6 = .04; */
float answer;
/*
printf("%f %f %f %f %f\n",p3,p6,h3,h6,o);
exit(0);
*/  
if (p3 == 0 && p6 == 0 && h3 == 0 && h6 == 0 && o == 0) return 0;
if (c == 0) return 0;
answer = 100 / (1 + pc6/p6 * (1 + p3/pc3 + h3/hi3 + o/co + p6/ks)) + 100 / (1 + hc6/h6 * (1 + h3/hc3));
if (answer <= 90 && answer >= 15) return answer;
if (answer > 90) return 90;
else return 15;
}
