/*
 * EXAMPLEC.C - Quasar SQL API example in 'C'
 *
 * LANGUAGE      : Microsoft C6.0
 * MODEL         : Small
 * ENVIRONMENT   : Microsoft Windows 3.0
 *
 * Developed by:
 *   Philip Roll
 *   Ming-Li Wang
 *
 * (C) Copyright 1991
 * Stellar Industries
 * 3335 S. Falcon Ridge Road
 * Diamond Bar  CA 91765
 *
 */

#define OEMRESOURCE
#define NOCOMM
#include    <windows.h>
#include    <memory.h>
#include    "sql.h"
#include    "examplec.h"

/*
 *
 * Define macros:
 *
 */

#define IDC_RECORD_BOX                  100
#define IDC_RECORD_STATIC               101
#define IDC_TABLE_BOX                   200
#define IDC_TABLE_STATIC                201
#define IDC_USER_BOX                    300
#define IDC_USER_STATIC                 301

#define mExampleMargin                  4

/*
 *
 * Define local variables:
 *
 */

static HANDLE   hSqlUser;
static HCURSOR  hcursorHourGlass;
static SQLCONTROL SqlControl;

static char     szExampleClass[] = "SqlExampleInC";
static char     szExampleCommit[] = "commit work;";
static char     szExampleTitle[] = "Sql Example In C";
static HANDLE   hExampleInstance;
static HWND     hwndExample;
static RECT     rectExample;
static TEXTMETRIC tmExampleTextMetrics;
static unsigned nExampleComboBoxHeight;

static char     szRecordTitle[] = " Record: ";
static char     szRecordSelectStatement[] = "select * from %s.%s;";
static HWND     hwndRecordComboBox;
static PSTR     pstrRecordRecord;
static RECT     rectRecordComboBox;
static unsigned nRecordRecordSize;

static char     szTableTitle[] = " Table: ";
static char     szTableSelectStatement[] = "select TABLE_NAME from TABLES where USER_NAME = '%s' and TABLE_NAME not like '~%%';";
static HWND     hwndTableComboBox;
static PSTR     pstrRecordTable;
static RECT     rectTableComboBox;
static unsigned nTableRecordSize;

static char     szUserTitle[] = " User: ";
static char     szUserSelectStatement[] = "select USER_NAME from USERS;";
static HWND     hwndUserComboBox;
static PSTR     pstrRecordUser;
static RECT     rectUserComboBox;
static unsigned nUserRecordSize;

/*
 *
 * Local function prototypes:
 *
 */

static void near ExampleCreate(void);
static BOOL near ExampleInitializeApplication(void);
static BOOL near ExampleInitializeInstance(int);
static void near ExampleRefresh(void);

static void near RecordComboBoxCreate(HDC);
static BOOL near RecordComboBoxRefresh(void);

static void near TableComboBoxCreate(HDC);
static BOOL near TableComboBoxRefresh(void);

static void near UserComboBoxCreate(HDC);
static BOOL near UserComboBoxRefresh(void);

/*
 *
 * Global function prototypes:
 *
 */

long FAR PASCAL ExampleWndProc(HWND, WORD, WORD, LONG);
int PASCAL      WinExample(HANDLE, HANDLE, LPSTR, int);

/*
 *
 * Quasar Example Window Creation
 *
 */

static void     near
ExampleCreate()
{
  HDC             hdcDeviceContext;

  hdcDeviceContext = GetDC(hwndExample);
  GetTextMetrics(hdcDeviceContext, &tmExampleTextMetrics);
  nExampleComboBoxHeight = 8 * GetSystemMetrics(SM_CYMENU);
  rectExample.left = 0;
  rectExample.top = GetSystemMetrics(SM_CYSCREEN) / 2;
  rectExample.right = rectExample.left + GetSystemMetrics(SM_CXSCREEN);
  UserComboBoxCreate(hdcDeviceContext);
  TableComboBoxCreate(hdcDeviceContext);
  RecordComboBoxCreate(hdcDeviceContext);
  ReleaseDC(hwndExample, hdcDeviceContext);
  rectExample.bottom = rectExample.top + rectRecordComboBox.bottom + mExampleMargin + 2;
  MoveWindow(hwndExample, rectExample.left, rectExample.top, rectExample.right - rectExample.left, rectExample.bottom - rectExample.top, FALSE);
  hSqlUser = SqlLogin(&SqlControl, "SYSTEM", "QUASAR");
  if (hSqlUser)
    ExampleRefresh();
  else
    MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
}

/*
 *
 * Quasar Example Application Initialization
 *
 */

static BOOL     near
ExampleInitializeApplication()
{
  WNDCLASS        WndClass;

  memset(&WndClass, 0, sizeof(WndClass));
  WndClass.lpfnWndProc = ExampleWndProc;
  WndClass.hInstance = hExampleInstance;
  WndClass.hIcon = LoadIcon(hExampleInstance, "ExampleIcon");
  WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  WndClass.lpszMenuName = "ExampleMenu";
  WndClass.lpszClassName = szExampleClass;
  if (RegisterClass(&WndClass))
    return (TRUE);
  else
    return (FALSE);
}

/*
 *
 * Quasar Example Initialization for each instance
 *
 */

static BOOL     near
ExampleInitializeInstance(int nCmdShow)
{
  HWND            hwndTemp;

  hcursorHourGlass = LoadCursor(NULL, IDC_WAIT);
  hwndTemp = CreateWindow(szExampleClass,
                          szExampleTitle,
                          (WS_MINIMIZEBOX | WS_OVERLAPPED | WS_SYSMENU),
                          0,
                          0,
                          100,
                          100,
                          NULL,
                          NULL,
                          hExampleInstance,
                          NULL);
  if (hwndTemp) {
    ShowWindow(hwndTemp, nCmdShow);
    UpdateWindow(hwndTemp);
    return (TRUE);
  } else
    return (FALSE);
}

/*
 *
 * Re-execute all queries and load all combo boxes
 *
 */

static void     near
ExampleRefresh()
{
  if (UserComboBoxRefresh())
    if (TableComboBoxRefresh())
      RecordComboBoxRefresh();
}

/*
 *
 * Example Window Procedure:
 *
 */

long FAR        PASCAL
ExampleWndProc(HWND hwndTemp, WORD wMessage, WORD wParam, LONG lParam)
{
  HCURSOR         hcursorOld;
  PAINTSTRUCT     psPaintStructure;
  POINT           pointRecordComboBoxLeftTop;
  unsigned        nNotificationCode;

  switch (wMessage) {
    case WM_CLOSE:
    case WM_QUERYENDSESSION:
      if (hSqlUser)
        SqlLogout(hSqlUser, &SqlControl);
      if (pstrRecordRecord)
        pstrRecordRecord = (PSTR) LocalFree((HANDLE) pstrRecordRecord);
      if (pstrRecordTable)
        pstrRecordTable = (PSTR) LocalFree((HANDLE) pstrRecordTable);
      if (pstrRecordUser)
        pstrRecordUser = (PSTR) LocalFree((HANDLE) pstrRecordUser);
      break;
    case WM_COMMAND:
      switch (wParam) {
        case IDM_REFRESH:
          hcursorOld = SetCursor(hcursorHourGlass);
          RecordComboBoxRefresh();
          SetCursor(hcursorOld);
          break;
        case IDC_RECORD_BOX:
          break;
        case IDC_TABLE_BOX:
          nNotificationCode = HIWORD(lParam);
          if (nNotificationCode == CBN_SELCHANGE) {
            hcursorOld = SetCursor(hcursorHourGlass);
            RecordComboBoxRefresh();
            SetCursor(hcursorOld);
          }
          break;
        case IDC_USER_BOX:
          nNotificationCode = HIWORD(lParam);
          if (nNotificationCode == CBN_SELCHANGE) {
            hcursorOld = SetCursor(hcursorHourGlass);
            if (TableComboBoxRefresh())
              RecordComboBoxRefresh();
            SetCursor(hcursorOld);
          }
          break;
      }
      break;
    case WM_CREATE:
      hwndExample = hwndTemp;
      hcursorOld = SetCursor(hcursorHourGlass);
      ExampleCreate();
      SetCursor(hcursorOld);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    case WM_PAINT:
      pointRecordComboBoxLeftTop.x = rectRecordComboBox.left + rectExample.left;
      pointRecordComboBoxLeftTop.y = rectRecordComboBox.top + rectExample.top;
      ScreenToClient(hwndExample, &pointRecordComboBoxLeftTop);
      BeginPaint(hwndTemp, &psPaintStructure);
      TextOut(psPaintStructure.hdc, 0, mExampleMargin + 1, szUserTitle, sizeof(szUserTitle) - 1);
      TextOut(psPaintStructure.hdc, (rectExample.right - rectExample.left) / 2, mExampleMargin + 1, szTableTitle, sizeof(szTableTitle) - 1);
      TextOut(psPaintStructure.hdc, 0, pointRecordComboBoxLeftTop.y + 1, szRecordTitle, sizeof(szRecordTitle) - 1);
      EndPaint(hwndTemp, &psPaintStructure);
      break;
    case WM_SETFOCUS:
      SetFocus(hwndUserComboBox);
      break;
  }
  return (DefWindowProc(hwndTemp, wMessage, wParam, lParam));
}

/*
 *
 * Create a Record ComboBox:
 *
 */

static void     near
RecordComboBoxCreate(HDC hdcDeviceContext)
{
  POINT           pointUserComboBoxLeftBottom;
  unsigned        nWidth;

  nWidth = LOWORD(GetTextExtent(hdcDeviceContext, szRecordTitle, sizeof(szRecordTitle) - 1));
  pointUserComboBoxLeftBottom.x = rectUserComboBox.left;
  pointUserComboBoxLeftBottom.y = rectUserComboBox.bottom;
  ScreenToClient(hwndExample, &pointUserComboBoxLeftBottom);
  hwndRecordComboBox = CreateWindow("ComboBox",
                                    NULL,
                                    (WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL),
                                    nWidth,
                                    pointUserComboBoxLeftBottom.y + mExampleMargin,
                                    rectExample.right - rectExample.left - nWidth - mExampleMargin,
                                    nExampleComboBoxHeight,
                                    hwndExample,
                                    IDC_RECORD_BOX,
                                    hExampleInstance,
                                    NULL);
  GetWindowRect(hwndRecordComboBox, &rectRecordComboBox);
  SendMessage(hwndRecordComboBox, WM_SETFONT, GetStockObject(SYSTEM_FIXED_FONT), 0);
}

/*
 *
 * Re-execute query for records and load record combo box
 *
 */

static BOOL     near
RecordComboBoxRefresh()
{
  char            szQuery[257];
  HANDLE          hSqlCursorRecord;
  SQLTABLE        SqlTable;
  unsigned        nTableIndex;
  unsigned        nUserIndex;
  unsigned long   lRecordPosition;

  hSqlCursorRecord = SqlCursorOpen(hSqlUser, &SqlControl);
  nTableIndex = (unsigned) SendMessage(hwndTableComboBox, CB_GETCURSEL, 0, 0);
  nUserIndex = (unsigned) SendMessage(hwndUserComboBox, CB_GETCURSEL, 0, 0);
  SendMessage(hwndTableComboBox, CB_GETLBTEXT, nTableIndex, (LONG) (LPSTR) pstrRecordTable);
  SendMessage(hwndUserComboBox, CB_GETLBTEXT, nTableIndex, (LONG) (LPSTR) pstrRecordUser);
  wsprintf(szQuery, szRecordSelectStatement, (LPSTR) pstrRecordUser, (LPSTR) pstrRecordTable);
  SqlControl.nPadding = 2;
  SqlControl.wFlags = mSqlFlagFormatPadded;
  if (SqlExecute(hSqlUser, hSqlCursorRecord, &SqlControl, szQuery)) {
    SqlDescribeTable(hSqlUser, hSqlCursorRecord, &SqlControl, &SqlTable);
    if (pstrRecordRecord)
      LocalFree((HANDLE) pstrRecordRecord);
    pstrRecordRecord = (PSTR) LocalAlloc(LPTR, SqlTable.nRecordSize);
    SqlControl.nRecordBufferSize = SqlTable.nRecordSize;
    SendMessage(hwndRecordComboBox, CB_RESETCONTENT, 0, 0);
    for (lRecordPosition = 0; lRecordPosition < SqlTable.lNumberOfRecords; lRecordPosition++) {
      if (lRecordPosition)
        SqlFetchNext(hSqlUser, hSqlCursorRecord, &SqlControl, pstrRecordRecord);
      else
        SqlFetchFirst(hSqlUser, hSqlCursorRecord, &SqlControl, pstrRecordRecord);
      if (SqlControl.nResultCode)
        MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
      SendMessage(hwndRecordComboBox, CB_ADDSTRING, 0, (LONG) (LPSTR) pstrRecordRecord);
    }
    SendMessage(hwndRecordComboBox, CB_SETCURSEL, 0, 0);
  } else
    MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
  SqlExecute(hSqlUser, hSqlCursorRecord, &SqlControl, szExampleCommit);
  SqlCursorClose(hSqlUser, hSqlCursorRecord, &SqlControl);
  return (!SqlControl.nResultCode);
}

/*
 *
 * Create a Table ComboBox:
 *
 */

static void     near
TableComboBoxCreate(HDC hdcDeviceContext)
{
  unsigned        nWidth;

  nWidth = LOWORD(GetTextExtent(hdcDeviceContext, szTableTitle, sizeof(szTableTitle) - 1));
  hwndTableComboBox = CreateWindow("ComboBox",
                                   NULL,
                                   (WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL),
                                   nWidth + (rectExample.right - rectExample.left) / 2,
                                   mExampleMargin,
                                   (rectExample.right - rectExample.left) / 2 - nWidth - mExampleMargin,
                                   nExampleComboBoxHeight,
                                   hwndExample,
                                   IDC_TABLE_BOX,
                                   hExampleInstance,
                                   NULL);
  GetWindowRect(hwndTableComboBox, &rectTableComboBox);
  SendMessage(hwndTableComboBox, WM_SETFONT, GetStockObject(SYSTEM_FIXED_FONT), 0);
}

/*
 *
 * Re-execute query for tables and load table combo box
 *
 */

static BOOL     near
TableComboBoxRefresh()
{
  char            szQuery[257];
  HANDLE          hSqlCursorTable;
  SQLTABLE        SqlTable;
  unsigned        nUserIndex;
  unsigned long   lRecordPosition;

  hSqlCursorTable = SqlCursorOpen(hSqlUser, &SqlControl);
  nUserIndex = (unsigned) SendMessage(hwndUserComboBox, CB_GETCURSEL, 0, 0);
  SendMessage(hwndUserComboBox, CB_GETLBTEXT, nUserIndex, (LONG) (LPSTR) pstrRecordUser);
  wsprintf(szQuery, szTableSelectStatement, (LPSTR) pstrRecordUser);
  SqlControl.wFlags = mSqlFlagFormatString;
  if (SqlExecute(hSqlUser, hSqlCursorTable, &SqlControl, szQuery)) {
    SqlDescribeTable(hSqlUser, hSqlCursorTable, &SqlControl, &SqlTable);
    if (pstrRecordTable)
      LocalFree((HANDLE) pstrRecordTable);
    pstrRecordTable = (PSTR) LocalAlloc(LPTR, SqlTable.nRecordSize);
    SqlControl.nRecordBufferSize = SqlTable.nRecordSize;
    SendMessage(hwndTableComboBox, CB_RESETCONTENT, 0, 0);
    for (lRecordPosition = 0; lRecordPosition < SqlTable.lNumberOfRecords; lRecordPosition++) {
      if (lRecordPosition)
        SqlFetchNext(hSqlUser, hSqlCursorTable, &SqlControl, pstrRecordTable);
      else
        SqlFetchFirst(hSqlUser, hSqlCursorTable, &SqlControl, pstrRecordTable);
      if (SqlControl.nResultCode)
        MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
      SendMessage(hwndTableComboBox, CB_ADDSTRING, 0, (LONG) (LPSTR) pstrRecordTable);
    }
    SendMessage(hwndTableComboBox, CB_SETCURSEL, 0, 0);
  } else
    MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
  SqlCursorClose(hSqlUser, hSqlCursorTable, &SqlControl);
  return (!SqlControl.nResultCode);
}

/*
 *
 * Create a User ComboBox:
 *
 */

static void     near
UserComboBoxCreate(HDC hdcDeviceContext)
{
  unsigned        nWidth;

  nWidth = LOWORD(GetTextExtent(hdcDeviceContext, szUserTitle, sizeof(szUserTitle) - 1));
  hwndUserComboBox = CreateWindow("ComboBox",
                                  NULL,
                                  (WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL),
                                  nWidth,
                                  mExampleMargin,
                                  (rectExample.right - rectExample.left) / 2 - nWidth - mExampleMargin,
                                  nExampleComboBoxHeight,
                                  hwndExample,
                                  IDC_USER_BOX,
                                  hExampleInstance,
                                  NULL);
  GetWindowRect(hwndUserComboBox, &rectUserComboBox);
  SendMessage(hwndUserComboBox, WM_SETFONT, GetStockObject(SYSTEM_FIXED_FONT), 0);
}

/*
 *
 * Re-execute query for users and load user combo box
 *
 */

static BOOL     near
UserComboBoxRefresh()
{
  HANDLE          hSqlCursorUser;
  SQLTABLE        SqlTable;
  unsigned long   lRecordPosition;

  hSqlCursorUser = SqlCursorOpen(hSqlUser, &SqlControl);
  SqlControl.wFlags = mSqlFlagFormatString;
  if (SqlExecute(hSqlUser, hSqlCursorUser, &SqlControl, szUserSelectStatement)) {
    SqlDescribeTable(hSqlUser, hSqlCursorUser, &SqlControl, &SqlTable);
    if (pstrRecordUser)
      LocalFree((HANDLE) pstrRecordUser);
    pstrRecordUser = (PSTR) LocalAlloc(LPTR, SqlTable.nRecordSize);
    SqlControl.nRecordBufferSize = SqlTable.nRecordSize;
    SendMessage(hwndUserComboBox, CB_RESETCONTENT, 0, 0);
    for (lRecordPosition = 0; lRecordPosition < SqlTable.lNumberOfRecords; lRecordPosition++) {
      if (lRecordPosition)
        SqlFetchNext(hSqlUser, hSqlCursorUser, &SqlControl, pstrRecordUser);
      else
        SqlFetchFirst(hSqlUser, hSqlCursorUser, &SqlControl, pstrRecordUser);
      if (SqlControl.nResultCode)
        MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
      SendMessage(hwndUserComboBox, CB_ADDSTRING, 0, (LONG) (LPSTR) pstrRecordUser);
    }
    SendMessage(hwndUserComboBox, CB_SETCURSEL, 0, 0);
  } else
    MessageBox(hwndExample, SqlControl.szErrorMessage, szExampleTitle, MB_OK | MB_ICONSTOP);
  SqlCursorClose(hSqlUser, hSqlCursorUser, &SqlControl);
  return (!SqlControl.nResultCode);
}

/*
 *
 * Example Window Program:
 *
 */

int             PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpstrCmdLine, int nCmdShow)
{
  MSG             msgMessage;

  lpstrCmdLine = lpstrCmdLine;
  hExampleInstance = hInstance;
  if (!SqlGetStatus(0, 0, NULL, NULL)) {
    MessageBox(GetFocus(), "The Dba is not running!", szExampleTitle, MB_OK | MB_ICONSTOP);
    return (0);
  }
  if (!hPrevInstance && !ExampleInitializeApplication())
    return (0);
  if (!ExampleInitializeInstance(nCmdShow))
    return (0);
  while (GetMessage(&msgMessage, NULL, 0, 0)) {
    TranslateMessage(&msgMessage);
    DispatchMessage(&msgMessage);
  }
  return (0);
}
