/* -*- Mode: C -*-
 *
 * $Header: /home/gene/library/website/docsrc/sdkskel/src/RCS/gwp.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"

/*
 */
static char *S_moduleName = "com.cybertiggyr.gene.sdkskel.gwp";

/*
 * Data for each window.  Each window of a given class
 * holds a pointer to the exact same Data object.
 */
typedef struct {
  char *magic;                          /* Copy of S_moduleName */
  char *classname;
  MsgMap *map;
  WNDPROC default_wndproc;
} Data;

/*
 */
static int
S_CmpData (const void *va, const void *vb)
{
  Data *da, *db;

  da = (Data *) va;
  db = (Data *) vb;
  return strcmp (da->classname, db->classname);
}

/*
 * Table which maps class names to message maps.
 * Sorted by class name so we can use "bsearch" to
 * find entries in it.
 */
static Data *S_classinfo = NULL;
static int S_classinfo_count = 0; /* number of elements alloced & used */

/*
 */
Boolean
GWP_RegisterClass (WNDCLASS *wndclass, MsgMap *map, WNDPROC default_wndproc)
{
  Boolean is_good = FALSE;
  size_t sz;

  ++S_classinfo_count;
  sz = S_classinfo_count * (sizeof *S_classinfo);
  S_classinfo = (Data *) xrealloc (S_classinfo, sz);
  S_classinfo[S_classinfo_count-1].magic = S_moduleName;
  S_classinfo[S_classinfo_count-1].classname = (char *) wndclass->lpszClassName;
  S_classinfo[S_classinfo_count-1].map = map;
  S_classinfo[S_classinfo_count-1].default_wndproc = default_wndproc;
  qsort (S_classinfo, S_classinfo_count, sizeof *S_classinfo,
         (int (*) (const void *, const void *)) &S_CmpData);
  is_good = RegisterClass (wndclass);
  if (!is_good) {
    LOG_LastError ("RegisterClass", __FILE__, __LINE__);
  }
  return is_good;
}

/*
 */
static int
S_GetClassName (HWND wnd, char classname[256])
{
  int rc = 0, i;

  i = GetClassName (wnd, classname, 256);
  if (0 < i && i < 256) {
    /* good */
  } else {
    LOG_LastError ("GetClassName", __FILE__, __LINE__);
    printf ("\n%s:%d:", __FILE__, __LINE__);
    printf (" GetClassName returnd %d. ", i);
    printf (" Expected a positive number less than 256.");
    rc = 3;
  }
  return rc;
}

/*
 */
static Data *
S_FindClassInfo (char classname[])
{
  Data key;

  key.classname = classname;
  return bsearch (&key, S_classinfo, S_classinfo_count, sizeof *S_classinfo,
                  (int (*) (const void *, const void *)) &S_CmpData);
}

/*
 */
static Data *
S_GetData (HWND wnd)
{
  char classname[256];

  S_GetClassName (wnd, classname);
  return S_FindClassInfo (classname);
}

/*
 */
LRESULT CALLBACK
GWP_WindowProc0 (HWND wnd, WindowMessage msg, WPARAM wparam, LPARAM lparam,
                 MsgMap *map, WNDPROC default_wndproc)
{
  LRESULT rc = 0;
  WNDPROC fn;

  fn = MSGMAP_Find (msg, map);
  if (fn != NULL) {
    /* We found a specific handler for the message. */
  } else {
    /* No specific handler, so use the default Window Procedure. */
    fn = default_wndproc;
  }
  return (*fn) (wnd, msg, wparam, lparam);
}

/*
 */
LRESULT CALLBACK
GWP_WindowProc (HWND wnd, WindowMessage msg, WPARAM wparam, LPARAM lparam)
{
  LRESULT rc = 0;
  Data *x;
  WNDPROC fn;

  x = S_GetData (wnd);
  if (x != NULL) {
    rc = GWP_WindowProc0 (wnd, msg, wparam, lparam, x->map,
                          x->default_wndproc);
  } else {
    rc = 3;
  }
  return rc;
}

/* --- end of file --- */
