/* ------------------------------------------------------------------------- */
/*   "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);
}

