//************************************************************************
//**
//**  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//**  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
//**  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
//**  A PARTICULAR PURPOSE.
//**
//**  Copyright (C) 1993, 1994 Microsoft Corporation. All Rights Reserved.
//**
//**  edit.c
//**
//**  DESCRIPTION:
//**     This file contains the code for the dialog box to enter new
//**     information for the mif.
//**
//**  HISTORY:
//**     04/28/93       created.
//**
//************************************************************************


#include "globals.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "res.h"

//*****************************************************************************
//**
//**  GetDlgItemDword();
//**
//**  DESCRIPTION:
//**     This function will read text from the ID_EDIT_BOX field and convert
//**     it to a DWORD value.  I use this since GetDlgItemInt() only returns
//**     a UINT.
//**
//**  ARGUMENTS:
//**     VOID
//**
//**  RETURNS:
//**     DWORD 
//**
//**  HISTORY:
//**     09/08/93       created.
//**
//*****************************************************************************

DWORD FNLOCAL GetDlgItemDword(
   VOID)
{
   DWORD dw;

   // Get the text that the user entered in the list box.
   //
   GetDlgItemText(ghwndMain, ID_EDIT_BOX, gszbuf, MAX_STR_LEN);

   // Convert the text to a number.
   //
   dw = (DWORD)atol(gszbuf);

   wsprintf(gszbuf, "%lu", dw);

   return(dw);
} //** GetDlgItemDword()


//************************************************************************
//**
//**  IsTrue();
//**
//**  DESCRIPTION:
//**     This funtion will translate an expression passed to it to a 
//**     boolean value.
//**
//**  ARGUMENTS:
//**     char  *szExpression
//**
//**  RETURNS:
//**     BOOL  -  FALSE if the first character of the expression is:
//**              'F', '0' or '\0'. Anything else and the expression 
//**              will evaluate to false.
//**
//**  HISTORY:
//**     04/29/93       created.
//**
//************************************************************************

BOOL FNLOCAL IsTrue(
   char  *szExpression)
{
   BOOL  f;
   char  c;

   // If the data the user entered was not of alpha or numeric 
   // origins then tell them what we actually look for.
   //
   if (isalnum(*szExpression))
   {
      // Convert the character, if it is one, 
      // to upper case for simplicity.
      //
      c = toupper(*szExpression);

      // Determine if the expression is false.
      // This can be either a 'F', '0' or a NULL.
      //
      f = !((c == 'F') || (*szExpression == '0') || (*szExpression == '\0'));
   }
   else
   {
      // Better let 'em know what we're expecting.
      //
      MessageBox(ghwndMain, 
                 "Please enter: 0, 1, TRUE or FALSE.", NULL, MB_OK);
   }

   return(f);
} //** IsTrue()


//*****************************************************************************
//**
//**  GetDlgItemBool();
//**
//**  DESCRIPTION:
//**
//**
//**  ARGUMENTS:
//**     VOID
//**
//**  RETURNS:
//**     BOOL 
//**
//**  HISTORY:
//**     09/08/93             created.
//**
//*****************************************************************************

BOOL FNLOCAL GetDlgItemBool(
   VOID)
{
   BOOL  f;

   // Get the text form the edit box.
   //
   GetDlgItemText(ghwndMain, ID_EDIT_BOX, gszbuf, MAX_STR_LEN);

   // Determine it the expression is TRUE or FALSE.
   //
   f = IsTrue(gszbuf);

   return(f);
} //** GetDlgItemBool()


//************************************************************************
//**
//**  UpdateHeaderInfo();
//**
//**  DESCRIPTION:
//**     This function will update the header information with what
//**     the user entered.
//**
//**  ARGUMENTS:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93       generalized.
//**
//************************************************************************

VOID FNLOCAL UpdateHeaderInfo(
   UINT  uEntry)   
{  
   DWORD dwNewValue;

   // Get the integer data that the user entered.
   //
   dwNewValue = GetDlgItemDword();

   // Update the appropriate entry.
   //
   switch (uEntry)
   {
      case MIF_VERSION:
         // Save the MIF format version.
         //
         gpInst[gdwCurrInst].dwVersion = dwNewValue;

         break;

      case MIF_CREATOR:
         // Save the MIF creator (manufacturer).
         //
         gpInst[gdwCurrInst].dwCreator = dwNewValue;

         break;
   }

} //** UpdateHeaderInfo()


//************************************************************************
//**
//**  UpdateInstrumentInfo();
//**
//**  DESCRIPTION:
//**     This function will update the instrument information with
//**     what the user entered.
//**
//**  ARGUMENTS:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93       updated.
//**
//************************************************************************

VOID FNLOCAL UpdateInstrumentInfo(
   UINT  uEntry)
{
   DWORD cbTextLength;
   LPSTR psz;

   // Update the instrument information structure accordingly.
   //
   switch (uEntry)
   {
      case INST_MANUFACT:
      case INST_PRODUCT:

         // Get the length of the entered text.    
         //
         cbTextLength = SendMessage(HWND_EDIT_BOX, WM_GETTEXTLENGTH, 0, 0L) + 1;

         // Allocate a new buffer for the name.
         //
         psz = AllocPtr(GHND, cbTextLength + 1);   
         if (NULL == psz)
         {
            // We could not allocate memory for the new name.
            //
            NotifyUser(MIFERR_NOMEM);
            break;
         }

         // Get the name entered into the buffer.
         //
         GetDlgItemText(ghwndMain, ID_EDIT_BOX, psz, (UINT)cbTextLength + 1); 

         // Which string did they edit?
         //
         if (INST_MANUFACT == uEntry)
         {
            // Free the old name.
            //
            FreePtr(&gpInst[gdwCurrInst].pszManufactASCII);
         
            // Save the new name in our instrument structure.
            //
            gpInst[gdwCurrInst].pszManufactASCII = psz;
         }
         else
         {
            // Free the old name.
            //
            FreePtr(&gpInst[gdwCurrInst].pszProductASCII);
         
            // Save the new name in our instrument structure.
            //
            gpInst[gdwCurrInst].pszProductASCII = psz;
         }

         break;

      case INST_MID:
         // Save the manufacturer ID.
         //
         gpInst[gdwCurrInst].dwManufactID = GetDlgItemDword();
         
         break;

      case INST_PID:
         // Save the product ID.
         //
         gpInst[gdwCurrInst].dwProductID = GetDlgItemDword();

         break;

      case INST_REV:
         // Save the revision
         //
         gpInst[gdwCurrInst].dwRevision = GetDlgItemDword();

         break;
   }

} //** UpdateInstrumentInfo()


//************************************************************************
//**
//**  UpdateInstCaps();
//**
//**  DESCRIPTION:
//**     This function will update the instrument capabilities 
//**     information with what the user entered.
//**
//**  ARGUMENTS:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93             added a few things.
//**
//************************************************************************

VOID FNLOCAL UpdateInstCaps(
   UINT  uEntry)
{
   BOOL  f;

   // Update the instrument caps struct accordingly.
   //
   switch (uEntry)
   {
      case CAPS_BASECHANL:
         // Save the new base channel.
         //
         gpInst[gdwCurrInst].dwBasicChannel = GetDlgItemDword();

         break;

      case CAPS_NUMCHANL:
         // Save the new number of channels.
         //
         gpInst[gdwCurrInst].cNumChannels =  GetDlgItemDword();

         break;

      case CAPS_INSTPOLY:
         // Save the instrument's polyphony.
         //
         gpInst[gdwCurrInst].cInstPoly = GetDlgItemDword();

         break;

      case CAPS_CHANLPOLY:
         // Save the channel polyphony.
         //
         gpInst[gdwCurrInst].cChannelPoly = GetDlgItemDword();

         break;
      
      case CAPS_GENERAL:
         // Did the user enter a TRUE or FALSE expression?
         //
         f = GetDlgItemBool();

         // Is the instrument General MIDI compliant?
         //
         if (f)
            gpInst[gdwCurrInst].fdwFlags |= MIFINSTCAPS_F_GENERAL_MIDI;
         else
            gpInst[gdwCurrInst].fdwFlags &= ~MIFINSTCAPS_F_GENERAL_MIDI;

         break;

      case CAPS_SYSEX:
         // Did the user enter a TRUE or FALSE expression?
         //
         f = GetDlgItemBool();

         // Does the instrument support system exclusive messages?
         //
         if (f)
            gpInst[gdwCurrInst].fdwFlags |= MIFINSTCAPS_F_SYSTEMEXCLUSIVE;
         else
            gpInst[gdwCurrInst].fdwFlags &= ~MIFINSTCAPS_F_SYSTEMEXCLUSIVE;

         break;
   }

} //** UpdateInstCaps()

//************************************************************************
//**
//**  UpdateChannelType();
//**
//**  DESCRIPTION:
//**     This function will update the channel type information with 
//**     what user entered.
//**
//**  ARGUMENTS:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93             added a few things.
//**
//************************************************************************

VOID FNLOCAL UpdateChannelType(
   UINT  uEntry)
{
   BOOL  f;
   UINT  c;

   // Get the text the user entered.
   //
   GetDlgItemText(ghwndMain, ID_EDIT_BOX, gszbuf, MAX_STR_LEN);

   // Do we know about this channel type?
   //
   for ( c = 0, f = FALSE;
         !f && (NUM_CHANNELS_DEFINED > c);
         c++)
   {
      // Is it in our array?
      //
      if (0 == lstrcmpi(gszChannelTypes[c], gszbuf))
      {
         // We found it.
         //
         f = TRUE;

         // Save the type index.
         //
         CURR_CHANNEL_TYPE(uEntry) = c;
      }
   }
} //** UpdateChannelType()


//************************************************************************
//**
//**  UpdatePatchMap();
//**
//**  DESCRIPTION:
//**     This function will update the patch map information.
//**
//**  ARGUMENTS:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93             added a few things.
//**
//************************************************************************

VOID FNLOCAL UpdatePatchMap(
   UINT  uEntry)
{
   UINT  uPatch;

   // Get the new patch.
   //
   uPatch = GetDlgItemInt(ghwndMain, ID_EDIT_BOX, NULL, FALSE);

   // Get the new patch map that the user enterd.
   //
   CURR_PATCH_MAP(uEntry) = (BYTE)uPatch;

} //** UpdatePatchMap()


//*****************************************************************************
//**
//**  UpdateKeyMap();
//**
//**  DESCRIPTION:
//**     UINT  uEntry   -  The item in the list box that we are editing.
//**
//**  ARGUMENTS:
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     09/08/93            created.
//**
//*****************************************************************************

VOID FNLOCAL UpdateKeyMap(
   UINT  uEntry)
{
   UINT  c;
   UINT  uChannel;

   // Get the channel that we are editing.
   // This is not the actual channel number but the
   // drum channel.  So we need to go through the and
   // find the xth drum channel in our channel list,
   // where x is equal to uChannel.
   //
   uChannel = (UINT)SendMessage(HWND_DRUM_CHANNELS, CB_GETCURSEL, 0, 0L);

   // Since the combo-box entries are 0 based we need
   // to increment our channel number by 1.
   //
   uChannel++;

   // Find the actual channel number that this is for.
   //
   for ( c = 0;
         (0 != uChannel) && (c < MAX_CHANNELS);
         c++)
   {
      // If we find a drum channel then decrement the channel 
      // index.
      //
      if (DRUM_CHANNEL == CURR_CHANNEL_TYPE(c))
         uChannel--;
   }

   // We now have our channel number in c, and
   // the actual key that we are changing in uEntry.
   //
   CURR_KEY_MAP(c, uEntry) = (BYTE)GetDlgItemInt(ghwndMain, 
                                                 ID_EDIT_BOX, 
                                                 NULL, 
                                                 FALSE);
   
} //** UpdateKeyMap()

//************************************************************************
//**
//**  UpdateInstrument();
//**
//**  DESCRIPTION:
//**     This function will update the mif file acording to the changes
//**     made by the user.
//**
//**  ARGUMENTS:
//**     VOID
//**
//**  RETURNS:
//**     VOID 
//**
//**  HISTORY:
//**     04/29/93       created.
//**     09/08/93       updated.
//**
//************************************************************************

VOID FNLOCAL UpdateInstrument(
   VOID)
{
   UINT  uEntry;

   // Disable the redrawing of the list box until we're done.
   //
   SendMessage(HWND_LIST_BOX, WM_SETREDRAW, FALSE, 0L);

   // Which entry are we editing?
   //
   uEntry = (UINT)SendMessage(HWND_LIST_BOX, LB_GETCURSEL, 0, 0L);

   // What section of the MIF are we editing?
   //
   switch (guCurrSelection)
   {
      case MIF_HEADER_INFO:
         // Update the header information.
         //
         UpdateHeaderInfo(uEntry);

         break;

      case MIF_INSTRUMENT_INFO:
         // Update the instrument information.
         //
         UpdateInstrumentInfo(uEntry);

         break;

      case MIF_INSTRUMENT_CAPS:
         // Update the midi capabilities information.
         //
         UpdateInstCaps(uEntry);

         break;

      case MIF_CHANNEL_TYPE:
         // Update the channel type.
         //
         UpdateChannelType(uEntry);

         break;

      case MIF_PATCH_MAPS:
         // Update the patch map.
         //
         UpdatePatchMap(uEntry);

         break;

      case MIF_KEY_MAPS:
         // Update the appropriate key map.
         //
         UpdateKeyMap(uEntry);
         
         break;
   }

   // Clear the current items from the list box.
   //
   SendMessage(HWND_LIST_BOX, LB_RESETCONTENT, 0, 0L);

   // Update the section.
   //
   UpdateListBox();

   // Set the current selection to the one we changed.
   //
   SetFocus(HWND_LIST_BOX);
   SendMessage(HWND_LIST_BOX, LB_SETCURSEL, uEntry, 0L);

   // Enable the redrawing of the list box and invalidate 
   // it so that it does a re-draw.
   //
   SendMessage(HWND_LIST_BOX, WM_SETREDRAW, (WPARAM)TRUE, 0L);
   InvalidateRect(ghwndMain, NULL, FALSE);

} //** UpdateInstrument()

                     

