/* ------------------------------------------------------------------------- */
/*   "infoclues": A small utility to convert (simple) UHS-format hints into  */
/*                an Inform include file which runs an "Invisiclues"-style   */
/*                menu (with submenus) of hints                              */
/*                                                                           */
/*   (C) Copyright Graham Nelson, 1994, 1995                                 */
/*                                                                           */
/*   For use with Inform 5                                                   */
/* ------------------------------------------------------------------------- */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct menu_item_s
{   char t[256];
} menu_item;

typedef struct menu_s
{   char name[32];
   char title[256];
   menu_item items[32];
   int menu_size;
} menu;

typedef struct subj_s
{   char name[256];
} subj;

FILE *ifp;
FILE *ofp;

char *process(char *s)
{   int i;
   for (i=0; s[i]!=0; i++)
   {   if (s[i]=='\"') s[i]='~';
       if ((s[i]=='\\')||(s[i]=='@')) s[i]='?';
   }
   i=0; while (s[i]==' ') i++; return(s+i);
}

int max_size = 12, max_width = 72;

menu main_menu, sub_menu, next_menu;

void compile_menu(menu *M)
{   int i, flag=0;

   if (M->menu_size > max_size+1)
   {   sprintf(next_menu.name, "%sN", M->name);
       sprintf(next_menu.title, "%s (2)", M->title);
       next_menu.menu_size = 0;
       for (i=max_size; i<M->menu_size; i++, next_menu.menu_size++)
           next_menu.items[i-max_size] = M->items[i];
       M->menu_size = max_size+1;
       sprintf(M->items[max_size].t, ">> To next page");
       flag=1;
       fprintf(ofp, "[ %s_Info i;\n", next_menu.name);
       fprintf(ofp, "  menu_item=menu_item+%d; i=%s_Info(menu_item);\n",
           max_size, M->name);
       fprintf(ofp, "  menu_item=menu_item-%d; return i;\n", max_size);
       fprintf(ofp, "];\n\n");
   }

   for (i=0; i<M->menu_size; i++)
   {   process(M->items[i].t);
       if (strlen(M->items[i].t) > max_width)
           sprintf(M->items[i].t + max_width-4, " ...");
   }

   fprintf(ofp, "[ %s_Menu;\n", M->name);
   fprintf(ofp, "  DoMenu(\"^\\\n");
   for (i=0; i<M->menu_size; i++)
       fprintf(ofp, "          ^     %s\\\n", M->items[i].t);
       fprintf(ofp, "          ^\", #r$%s_TR, #r$%s_Info%s);\n",
           M->name, M->name, (flag==0)?"":"X");
   fprintf(ofp, "];\n\n");

   fprintf(ofp, "[ %s_TR;\n", M->name);
   fprintf(ofp,
 "  if (menu_item==0) { item_name=\"%s\"; item_width=%d; return %d; }\n",
       M->title, strlen(M->title)/2, M->menu_size);
   for (i=0; i<M->menu_size; i++)
       fprintf(ofp,
       "  if (menu_item==%d) { item_name=\"%s\"; item_width=%d; }\n",
          i+1, M->items[i].t, strlen(M->items[i].t)/2);

   fprintf(ofp, "];\n\n");

   if (flag==1)
   {
       fprintf(ofp, "[ %s_InfoX;\n", M->name);
       fprintf(ofp, "  if (menu_item == %d) { %sN_Menu(); return 2; }\n",
           M->menu_size, M->name);
       fprintf(ofp, "  return %s_Info(menu_item);\n", M->name);
       fprintf(ofp, "];\n\n");
       compile_menu(&next_menu);
   }
}

subj the_subjects[64];

void prologue(void)
{
   fprintf(ofp, "!  Clues file generated automatically from UHS source\n\n");
   fprintf(ofp, "[ GiveHint hint flag keypress;\n");
   fprintf(ofp,
"  if (flag==1) print \"(Press H for another hint, or SPACE to return.)^^\";");
   fprintf(ofp, "  print_paddr hint;\n");
   fprintf(ofp, "  new_line; new_line;\n");
   fprintf(ofp, "  @read_char 1 0 0 keypress;\n");
   fprintf(ofp, "  if (keypress == 'H' or 'h') rfalse;\n");
   fprintf(ofp, "  rtrue;\n");
   fprintf(ofp, "];\n\n");
}

void epilogue(void)
{   int i; menu *M=&main_menu;
   fprintf(ofp, "[ Main_Info;\n");
   for (i=0; i<M->menu_size; i++)
       fprintf(ofp,
       "  if (menu_item == %d) Subj%d_Menu();\n", i+1, i+1);
   fprintf(ofp, "  return 2;\n\n");
   fprintf(ofp, "];\n\n");
   compile_menu(M);
}

char hintbuff[2048];
int in_sr_flag=0;
void finish_subject(void)
{   if (in_sr_flag!=1) return; in_sr_flag=0;
   fprintf(ofp, "];\n\n");
}
int in_hint_flag=0;
void finish_hint(void)
{   if (in_hint_flag!=1) return;
   if (strlen(hintbuff)!=0)
   {   fprintf(ofp, "  \"%s\";\n", process(hintbuff)); hintbuff[0]=0; }
   in_hint_flag=0;
   fprintf(ofp, "  }\n");
}

int main(int argc, char **argv)
{   char buffer[256], fw[256]; int hints=0, i, j, k, given;
   printf("Infoclues 1: Generates clues-menu Inform code from UHS source\n");

   if (argc!=3) { printf("Syntax is: infoclues fromfile tofile\n"); exit(1); }

   ifp = fopen(argv[1], "r");
   if (ifp==NULL) { printf("Input file won't open\n"); exit(1); }
   ofp = fopen(argv[2], "w");
   if (ofp==NULL) { printf("Output file won't open\n"); exit(1); }

   prologue();

   main_menu.menu_size = 0; strcpy(main_menu.title, "Clues");
   strcpy(main_menu.name, "Main");

   hintbuff[0]=0;

   while (feof(ifp)==0)
   {   if (fgets(buffer,256,ifp)==0) goto RunOut;
       for (i=0; buffer[i]==' '; i++) ;
       for (j=i; buffer[j]!=' ' && buffer[j]!=0; j++) fw[j-i]=buffer[j];
       fw[j-i]=0; while (buffer[j]==' ') j++;
       for (k=0; buffer[k]!=0; k++)
           if (buffer[k]=='\n') buffer[k]=0;

       if ((fw[0]=='[') && (fw[strlen(fw)-1]==']'))
       {   if (strcmp(fw, "[subject]")==0)
           {   strcpy(main_menu.items[main_menu.menu_size++].t, buffer+j);
               if (in_sr_flag==1)
               {   finish_hint(); finish_subject(); compile_menu(&sub_menu);
               }
               in_sr_flag=1;
               fprintf(ofp, "[ Subj%d_Info;\n", main_menu.menu_size);
               sub_menu.menu_size = 0; strcpy(sub_menu.title, buffer+j);
               sprintf(sub_menu.name, "Subj%d", main_menu.menu_size);
           }
           else
           {   strcpy(sub_menu.items[sub_menu.menu_size++].t, buffer+j);
               hints++; finish_hint();
               fprintf(ofp, "  if (menu_item==%d) {\n", sub_menu.menu_size);
               in_hint_flag=1; given=0;
           }
       }
       else if (strcmp(fw, ">>")==0)
       {   if (strlen(hintbuff)!=0)
           {   fprintf(ofp, "  if (GiveHint(\"%s\"%s)==1) return 2;\n",
                   process(hintbuff), (given++==0)?",1":"");
           }
           strcpy(hintbuff, buffer+j);
       }
       else
       {   sprintf(hintbuff+strlen(hintbuff), " %s", buffer+i);
       }
   }

   RunOut:

   fclose(ifp);

   if (in_sr_flag==1)
   {   finish_hint(); finish_subject(); compile_menu(&sub_menu);
   }
   epilogue();

   fclose(ofp);

   printf("Completed: %d subjects, %d hints\n",
          main_menu.menu_size, hints);
   return(0);
}