
#include "includes.h"
#include "installergui_data.h"

/********************************************************************
 *
 *  DESCRIPTION
 *
 */

/********************************************************************
 *
 *  STATIC
 *
 */

static void __asm __saveds askoptions_hookfun(register __a2 APTR, register __a1 APTR *);

static const struct Hook askoptions_hook = { { NULL, NULL }, (VOID *) askoptions_hookfun, NULL, NULL };

/********************************************************************
 *
 *  EXTERN
 *
 */

/********************************************************************
 *
 *  PUBLIC
 *
 */

/********************************************************************
 *
 *  CODE
 *
 */

long __asm igui_AskOptions(register __a0 APTR application,
                           register __a1 struct FunctionEnvironment *localenv)
{
  #ifdef DEBUG
  DEBUG_MAKRO
  #endif

  {
    struct Application *app = (struct Application *) application;

    // the return value of this function
    long retval = localenv->fe_Default;

    // for later use
    APTR innergroup,

         // the new object
         obj = GroupObject,
                 Child, TextObject,
                   MUIA_Frame, MUIV_Frame_None,
                   MUIA_Text_Contents, localenv->fe_Prompt,
                   MUIA_Text_SetMin, TRUE,
                   MUIA_Text_PreParse, "\33c",
                 End,
                 Child, innergroup = GroupObject,
                   MUIA_Group_Horiz, TRUE,
                   Child, HVSpace,
                     // here we will put the checkbox buttons later
                 End,
               End;



    // if DEFAULT equals -1 (means "all" choices on) then just set
    // only the choices, which have relates nodes
    if (retval == -1)
    {
      struct Node *node = (struct Node *) &(localenv->fe_Choices);

      retval = 0;
      while (node = sav_GetSucc(node)) { retval |= (1 << node->ln_Pri); }
    }

    if (!obj) { app->app_Error = GUIERROR_NO_GUI_OBJECT; }
    else
    {
      // no dynamically create the labels and the checkboxs an
      // put them together into the inner group!
      if (DoMethod(innergroup, MUIM_Group_InitChange))
      {
        int i,j;
        char *label;
        APTR checkbox;
        struct Node *choicenode = sav_GetHead((struct List *) &(localenv->fe_Choices));
        long num_choices = sav_ListLen((struct List *) &(localenv->fe_Choices)),
             columns = num_choices/10 + 1,
             rows = num_choices/columns,
             choice_id;

        // care for odd number of choices!
        if (num_choices > (rows * columns)) { rows++; }

        // go!
        for (j=1; j<=columns; j++)
        {
          APTR choicelist = GroupObject,
                              MUIA_Group_Columns, 2,
                              Child, HVSpace,
                              Child, HVSpace,
                            End;

          if (choicelist && DoMethod(choicelist, MUIM_Group_InitChange))
          {
            for (i=1; (i<=rows) && choicenode; i++)
            {
              // the node ln_Name holds the name, ln_Pri holds the related bit-number
              label = choicenode->ln_Name;
              choice_id = choicenode->ln_Pri;
              choicenode = sav_GetSucc(choicenode);

              DoMethod(choicelist, OM_ADDMEMBER, Label(label));
              DoMethod(choicelist, OM_ADDMEMBER, checkbox = CheckMark(retval & (1<<choice_id)), FALSE);

              // the hook
              if (checkbox)
              {
                SetAttrs(checkbox, MUIA_UserData, choice_id, TAG_DONE);
                DoMethod(checkbox, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
                         MUIV_Notify_Self, 3, MUIM_CallHook, &askoptions_hook, &retval);
              }
            }
            DoMethod(choicelist, OM_ADDMEMBER, HVSpace);
            DoMethod(choicelist, OM_ADDMEMBER, HVSpace);
            DoMethod(choicelist, MUIM_Group_ExitChange);
          }

          DoMethod(innergroup, OM_ADDMEMBER, choicelist);
        }

        // unteren space einfügen und fertig
        DoMethod(innergroup, OM_ADDMEMBER, HVSpace);
        DoMethod(innergroup, MUIM_Group_ExitChange);
      }

      // add the content to the gui!
      guistuff_NewContent(app, obj);

      //
      igui_WaitApp(app);
    }

    igui_EmptyPanel(app);
    return(retval);
  }
}

/********************************************************************/

static void __asm __saveds askoptions_hookfun(register __a2 APTR obj, register __a1 APTR *data)
{
  // data[0] holds the address of the "retval"

  long bitnum;
  GetAttr(MUIA_UserData, obj, (APTR) &bitnum);
  *((ULONG *) data[0]) = sav_BitChange(*((ULONG *) data[0]), bitnum);
}
