/* -*- Mode: C -*-
 *
 * $Header: /home/gene/library/website/docsrc/sdkskel/src/RCS/log.c,v 395.1 2008/04/20 17:25:51 gene Exp $
 *
 * Copyright (c) 2006 Gene Michael Stover.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "this.h"

/*
 */
char *LOG_pathname = "C:/temp/log.txt";

/*
 * Return file pointer or NULL if we can't open the file.
 */
FILE *
LOG_Open ()
{
  FILE *fp = NULL;

  if (access (LOG_pathname, 0) == 0) {
    fp = fopen (LOG_pathname, "a");
    if (fp != NULL) setbuf (fp, NULL);
  }
  return fp;
}

void
LOG_AviError (DWORD error, char moo[], char file[], int line)
{
  char *errstr, tmp[50];
  FILE *fp;

  switch (error) {
  case AVIERR_NOCOMPRESSOR: errstr = "AVIERR_NOCOMPRESSOR"; break;
  case AVIERR_MEMORY: errstr = "AVIERR_MEMORY"; break;
  case AVIERR_UNSUPPORTED: errstr = "AVIERR_UNSUPPORTED"; break;
  default:
    sprintf (tmp, "AVIERR(%lu)", (unsigned long) error);
    errstr = tmp;
  }
  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n%s:%d: %s: %s", file, line, moo, errstr);
    fclose (fp);
  }
}

void
LOG_Error (DWORD error, char moo[], char file[], int line)
{
  /*
   * This implementation is copied from
   * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/retrieving_the_last_error_code.asp.
   * I made some small changes, like using the "error" argument
   * instead of GetLastError.
   */
  char *lpMsgBuf;
  static char fmt[] = "\n%s:%d: %s failed (%lu): %s";
  int sz;
  char *str;
  FILE *fp;

  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                  NULL, error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
                  &lpMsgBuf, 0, NULL);
  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, fmt, file, line, moo, error, lpMsgBuf);
    fclose (fp);
  }
  /*
   * In this size computation, we assume that the maximum space
   * required by line is95 & by error is 9.
   */
  sz = strlen (fmt) + strlen (file) + 9 + strlen (moo) + 9 +
    strlen (lpMsgBuf);
  str = (char *) malloc (sz + 1);
  sprintf (str, fmt, file, line, moo, (unsigned long) error, lpMsgBuf);
  assert (strlen (str) < sz);
  MessageBoxA (NULL, str, TEXT("Error"), MB_OK); 
  free (str);
}

/*
 */
void
LOG_LastError (char moo[], char file[], int line)
{
  LOG_Error (GetLastError (), moo, file, line);
}

/*
 */
void
LOG_Trace (char file[], int line)
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d trace)", file, line);
    fclose (fp);
  } else {
    /*
     * We could not open the file.  This isn't an error.  It means
     * we shouldn't log anything.
     */
  }
}

/*
 */
void
LOG_TraceEntry (char file[], int line, char moo[])
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d %s entry)", file, line, moo);
    fclose (fp);
  } else {
    /*
     * We could not open the file.  This isn't an error.  It means
     * we shouldn't log anything.
     */
  }
}

/*
 */
void
LOG_TraceExit (char file[], int line, char moo[])
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d %s exit)", file, line, moo);
    fclose (fp);
  } else {
    /*
     * We could not open the file.  This isn't an error.  It means
     * we shouldn't log anything.
     */
  }
}

/*
 */
void
LOG_TraceMoo (char file[], int line, char moo[])
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d %s)", file, line, moo);
    fclose (fp);
  } else {
    /*
     * We could not open the file.  This isn't an error.  It means
     * we shouldn't log anything.
     */
  }
}

/*
 */
void
LOG_TraceMsgMapNotFound (char file[], int line, WindowMessage msg)
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d MsgMapNotFound");
    fflush (fp);
    LOG_TraceWindowMessage (file, line, msg);
    fprintf (fp, ")");
    fclose (fp);
  }
}

/*
 */
void
LOG_TraceWindowClass (char file[], int line, HWND wnd)
{
  FILE *fp;
  char classname[256];

  fp = LOG_Open ();
  if (fp != NULL) {
    GetClassName (wnd, classname, sizeof classname);
    fprintf (fp, "\n(\"%s\" %d windowclass \"%s\")", file, line, classname);
    fclose (fp);
  }
}

/*
 */
void
LOG_TraceWindowMessage (char file[], int line, WindowMessage msg)
{
  FILE *fp;
  char *p, str[20];

  fp = LOG_Open ();
  if (fp != NULL) {
    switch (msg) {
#define Entry(msg) case msg: p = #msg; break

      Entry (WM_NULL);
      Entry (WM_CREATE);
      Entry (WM_DESTROY);
      Entry (WM_MOVE);
      Entry (WM_SIZE);
      Entry (WM_ACTIVATE);
      Entry (WM_SETFOCUS);
      Entry (WM_KILLFOCUS);
      Entry (WM_ENABLE);
      Entry (WM_SETREDRAW);
      Entry (WM_SETTEXT);
      Entry (WM_GETTEXT);
      Entry (WM_GETTEXTLENGTH);
      Entry (WM_PAINT);
      Entry (WM_CLOSE);
#ifndef _WIN32_WCE
      Entry (WM_QUERYENDSESSION);
      Entry (WM_QUERYOPEN);
      Entry (WM_ENDSESSION);
#endif
      Entry (WM_QUIT);
      Entry (WM_ERASEBKGND);
      Entry (WM_SYSCOLORCHANGE);
      Entry (WM_SHOWWINDOW);
      Entry (WM_WININICHANGE);
#if(WINVER >= 0x0400)
      /* Entry (WM_SETTINGCHANGE); */
#endif /* WINVER >= 0x0400 */

      Entry (WM_DEVMODECHANGE);
      Entry (WM_ACTIVATEAPP);
      Entry (WM_FONTCHANGE);
      Entry (WM_TIMECHANGE);
      Entry (WM_CANCELMODE);
      Entry (WM_SETCURSOR);
      Entry (WM_MOUSEACTIVATE);
      Entry (WM_CHILDACTIVATE);
      Entry (WM_QUEUESYNC);

      Entry (WM_GETMINMAXINFO);

      Entry (WM_PAINTICON);
      Entry (WM_ICONERASEBKGND);
      Entry (WM_NEXTDLGCTL);
      Entry (WM_SPOOLERSTATUS);
      Entry (WM_DRAWITEM);
      Entry (WM_MEASUREITEM);
      Entry (WM_DELETEITEM);
      Entry (WM_VKEYTOITEM);
      Entry (WM_CHARTOITEM);
      Entry (WM_SETFONT);
      Entry (WM_GETFONT);
      Entry (WM_SETHOTKEY);
      Entry (WM_GETHOTKEY);
      Entry (WM_QUERYDRAGICON);
      Entry (WM_COMPAREITEM);
#if(WINVER >= 0x0500)
#ifndef _WIN32_WCE
      Entry (WM_GETOBJECT);
#endif
#endif /* WINVER >= 0x0500 */
      Entry (WM_COMPACTING);
      Entry (WM_COMMNOTIFY);
      Entry (WM_WINDOWPOSCHANGING);
      Entry (WM_WINDOWPOSCHANGED);
      Entry (WM_POWER);
      Entry (WM_COPYDATA);
      Entry (WM_CANCELJOURNAL);

#if(WINVER >= 0x0400)
      Entry (WM_NOTIFY);
      Entry (WM_INPUTLANGCHANGEREQUEST);
      Entry (WM_INPUTLANGCHANGE);
      Entry (WM_TCARD);
      Entry (WM_HELP);
      Entry (WM_USERCHANGED);
      Entry (WM_NOTIFYFORMAT);
      Entry (WM_CONTEXTMENU);
      Entry (WM_STYLECHANGING);
      Entry (WM_STYLECHANGED);
      Entry (WM_DISPLAYCHANGE);
      Entry (WM_GETICON);
      Entry (WM_SETICON);
#endif /* WINVER >= 0x0400 */

      Entry (WM_NCCREATE);
      Entry (WM_NCDESTROY);
      Entry (WM_NCCALCSIZE);
      Entry (WM_NCHITTEST);
      Entry (WM_NCPAINT);
      Entry (WM_NCACTIVATE);
      Entry (WM_GETDLGCODE);
#ifndef _WIN32_WCE
      Entry (WM_SYNCPAINT);
#endif
      Entry (WM_NCMOUSEMOVE);
      Entry (WM_NCLBUTTONDOWN);
      Entry (WM_NCLBUTTONUP);
      Entry (WM_NCLBUTTONDBLCLK);
      Entry (WM_NCRBUTTONDOWN);
      Entry (WM_NCRBUTTONUP);
      Entry (WM_NCRBUTTONDBLCLK);
      Entry (WM_NCMBUTTONDOWN);
      Entry (WM_NCMBUTTONUP);
      Entry (WM_NCMBUTTONDBLCLK);

#if(_WIN32_WINNT >= 0x0500)
      Entry (WM_NCXBUTTONDOWN);
      Entry (WM_NCXBUTTONUP);
      Entry (WM_NCXBUTTONDBLCLK);
#endif /* _WIN32_WINNT >= 0x0500 */

#if(_WIN32_WINNT >= 0x0501)
      Entry (WM_INPUT);
#endif /* _WIN32_WINNT >= 0x0501 */

      Entry (WM_KEYFIRST);
      /* Entry (WM_KEYDOWN); */
      Entry (WM_KEYUP);
      Entry (WM_CHAR);
      Entry (WM_DEADCHAR);
      Entry (WM_SYSKEYDOWN);
      Entry (WM_SYSKEYUP);
      Entry (WM_SYSCHAR);
      Entry (WM_SYSDEADCHAR);
#if(_WIN32_WINNT >= 0x0501)
      Entry (WM_UNICHAR);
      Entry (WM_KEYLAST);
      Entry (UNICODE_NOCHAR);
#else
      Entry (WM_KEYLAST);
#endif /* _WIN32_WINNT >= 0x0501 */

#if(WINVER >= 0x0400)
      Entry (WM_IME_STARTCOMPOSITION);
      Entry (WM_IME_ENDCOMPOSITION);
      Entry (WM_IME_COMPOSITION);
      /* Entry (WM_IME_KEYLAST); */
#endif /* WINVER >= 0x0400 */

      Entry (WM_INITDIALOG);
      Entry (WM_COMMAND);
      Entry (WM_SYSCOMMAND);
      Entry (WM_TIMER);
      Entry (WM_HSCROLL);
      Entry (WM_VSCROLL);
      Entry (WM_INITMENU);
      Entry (WM_INITMENUPOPUP);
      Entry (WM_MENUSELECT);
      Entry (WM_MENUCHAR);
      Entry (WM_ENTERIDLE);
#if(WINVER >= 0x0500)
#ifndef _WIN32_WCE
      Entry (WM_MENURBUTTONUP);
      Entry (WM_MENUDRAG);
      Entry (WM_MENUGETOBJECT);
      Entry (WM_UNINITMENUPOPUP);
      Entry (WM_MENUCOMMAND);

#ifndef _WIN32_WCE
#if(_WIN32_WINNT >= 0x0500)
      Entry (WM_CHANGEUISTATE);
      Entry (WM_UPDATEUISTATE);
      Entry (WM_QUERYUISTATE);

      /*
       * LOWORD(wParam) values in WM_*UISTATE*
       */
      Entry (UIS_SET);
      Entry (UIS_CLEAR);
      Entry (UIS_INITIALIZE);

      /*
       * HIWORD(wParam) values in WM_*UISTATE*
       */
      Entry (UISF_HIDEFOCUS);
      Entry (UISF_HIDEACCEL);
#if(_WIN32_WINNT >= 0x0501)
      Entry (UISF_ACTIVE);
#endif /* _WIN32_WINNT >= 0x0501 */
#endif /* _WIN32_WINNT >= 0x0500 */
#endif

#endif
#endif /* WINVER >= 0x0500 */

      Entry (WM_CTLCOLORMSGBOX);
      Entry (WM_CTLCOLOREDIT);
      Entry (WM_CTLCOLORLISTBOX);
      Entry (WM_CTLCOLORBTN);
      Entry (WM_CTLCOLORDLG);
      Entry (WM_CTLCOLORSCROLLBAR);
      Entry (WM_CTLCOLORSTATIC);
      Entry (MN_GETHMENU);

      /* Entry (WM_MOUSEFIRST); */
      Entry (WM_MOUSEMOVE);
      Entry (WM_LBUTTONDOWN);
      Entry (WM_LBUTTONUP);
      Entry (WM_LBUTTONDBLCLK);
      Entry (WM_RBUTTONDOWN);
      Entry (WM_RBUTTONUP);
      Entry (WM_RBUTTONDBLCLK);
      Entry (WM_MBUTTONDOWN);
      Entry (WM_MBUTTONUP);
      Entry (WM_MBUTTONDBLCLK);
#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
      Entry (WM_MOUSEWHEEL);
#endif
#if (_WIN32_WINNT >= 0x0500)
      Entry (WM_XBUTTONDOWN);
      Entry (WM_XBUTTONUP);
      Entry (WM_XBUTTONDBLCLK);
#endif
      Entry (WM_PARENTNOTIFY);
      Entry (WM_ENTERMENULOOP);
      Entry (WM_EXITMENULOOP);

#if(WINVER >= 0x0400)
      Entry (WM_NEXTMENU);
      Entry (WM_SIZING);
      Entry (WM_CAPTURECHANGED);
      Entry (WM_MOVING);
#endif /* WINVER >= 0x0400 */

#if(WINVER >= 0x0400)
      Entry (WM_POWERBROADCAST);
#endif /* WINVER >= 0x0400 */

#if(WINVER >= 0x0400)
      Entry (WM_DEVICECHANGE);
#endif /* WINVER >= 0x0400 */

      Entry (WM_MDICREATE);
      Entry (WM_MDIDESTROY);
      Entry (WM_MDIACTIVATE);
      Entry (WM_MDIRESTORE);
      Entry (WM_MDINEXT);
      Entry (WM_MDIMAXIMIZE);
      Entry (WM_MDITILE);
      Entry (WM_MDICASCADE);
      Entry (WM_MDIICONARRANGE);
      Entry (WM_MDIGETACTIVE);

      Entry (WM_MDISETMENU);
      Entry (WM_ENTERSIZEMOVE);
      Entry (WM_EXITSIZEMOVE);
      Entry (WM_DROPFILES);
      Entry (WM_MDIREFRESHMENU);

#if(WINVER >= 0x0400)
      Entry (WM_IME_SETCONTEXT);
      Entry (WM_IME_NOTIFY);
      Entry (WM_IME_CONTROL);
      Entry (WM_IME_COMPOSITIONFULL);
      Entry (WM_IME_SELECT);
      Entry (WM_IME_CHAR);
#endif /* WINVER >= 0x0400 */
#if(WINVER >= 0x0500)
      Entry (WM_IME_REQUEST);
#endif /* WINVER >= 0x0500 */
#if(WINVER >= 0x0400)
      Entry (WM_IME_KEYDOWN);
      Entry (WM_IME_KEYUP);
#endif /* WINVER >= 0x0400 */

#if((_WIN32_WINNT >= 0x0400) || (WINVER >= 0x0500))
      Entry (WM_MOUSEHOVER);
      Entry (WM_MOUSELEAVE);
#endif
#if(WINVER >= 0x0500)
      Entry (WM_NCMOUSEHOVER);
      Entry (WM_NCMOUSELEAVE);
#endif /* WINVER >= 0x0500 */

#if(_WIN32_WINNT >= 0x0501)
      Entry (WM_WTSSESSION_CHANGE);

      Entry (WM_TABLET_FIRST);
      Entry (WM_TABLET_LAST);
#endif /* _WIN32_WINNT >= 0x0501 */

      Entry (WM_CUT);
      Entry (WM_COPY);
      Entry (WM_PASTE);
      Entry (WM_CLEAR);
      Entry (WM_UNDO);
      Entry (WM_RENDERFORMAT);
      Entry (WM_RENDERALLFORMATS);
      Entry (WM_DESTROYCLIPBOARD);
      Entry (WM_DRAWCLIPBOARD);
      Entry (WM_PAINTCLIPBOARD);
      Entry (WM_VSCROLLCLIPBOARD);
      Entry (WM_SIZECLIPBOARD);
      Entry (WM_ASKCBFORMATNAME);
      Entry (WM_CHANGECBCHAIN);
      Entry (WM_HSCROLLCLIPBOARD);
      Entry (WM_QUERYNEWPALETTE);
      Entry (WM_PALETTEISCHANGING);
      Entry (WM_PALETTECHANGED);
      Entry (WM_HOTKEY);

#if(WINVER >= 0x0400)
      Entry (WM_PRINT);
      Entry (WM_PRINTCLIENT);
#endif /* WINVER >= 0x0400 */

#if(_WIN32_WINNT >= 0x0500)
      Entry (WM_APPCOMMAND);
#endif /* _WIN32_WINNT >= 0x0500 */

#if(_WIN32_WINNT >= 0x0501)
      Entry (WM_THEMECHANGED);
#endif /* _WIN32_WINNT >= 0x0501 */


#if(WINVER >= 0x0400)

      Entry (WM_HANDHELDFIRST);
      Entry (WM_HANDHELDLAST);

      Entry (WM_AFXFIRST);
      Entry (WM_AFXLAST);
#endif /* WINVER >= 0x0400 */

      Entry (WM_PENWINFIRST);
      Entry (WM_PENWINLAST);


#if(WINVER >= 0x0400)
      Entry (WM_APP);
#endif /* WINVER >= 0x0400 */

      /*
       * NOTE: All Message Numbers below 0x0400 are RESERVED.
       *
       * Private Window Messages Start Here:
       */
      Entry (WM_USER);

    default: sprintf (str, "#x%04X", msg); p = str;
    }
    fprintf (fp, "\n(\"%s\" %d WindowMessage %s)", file, line, p);
    fclose (fp);
  }
}

/*
 */
void
LOG_TraceXmalloc (char file[], int line, int sz)
{
  FILE *fp;

  fp = LOG_Open ();
  if (fp != NULL) {
    fprintf (fp, "\n(\"%s\" %d xmalloc %d)", file, line, sz);
    fclose (fp);
  } else {
    /*
     * We could not open the file.  This isn't an error.  It means
     * we shouldn't log anything.
     */
  }
}

/* --- end of file --- */
