Using SQLA DBTools with Watcom C/C++ under Windows

This is based on a query made by someone on how to create a database using the DBTools library for Sybase SQL Anywhere.

This is fairly crude and is meant only as a sample.

// mkdb.c
#define _SQL_OS_WINDOWS
#define WIN
#include <windows.h>
#include "dbtools.h"
#include <windowsx.h>

HWND DlgWnd; // puke! (A global)

// process any waiting window messages
static void DoMessages(void)
{
    MSG msg;
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        if (!IsDialogMessage(DlgWnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

// error message callback
short _callback __export error_cb(char const *msg)
{
    if (msg != NULL)
    {
        return MessageBox(DlgWnd, msg, "Error", MB_OK | MB_ICONSTOP);
    }

    return 0;
}

// status message callback
short _callback __export msg_cb(char const *msg)
{
    if (msg != NULL)
    {
        HWND editWnd = GetDlgItem(DlgWnd, 100);
        Edit_SetSel(editWnd, -1, -1);
        Edit_ReplaceSel(editWnd, msg);
        Edit_SetSel(editWnd, -1, -1);
        Edit_ReplaceSel(editWnd, "\r\n");
        Edit_SetSel(editWnd, -1, -1);

        DoMessages();
    }
    return 0;
}

// a basic dialog proc for a application based on a dialog box
BOOL CALLBACK __export MyDlgProc(HWND dlg, UINT msg, WPARAM wparm, LPARAM
                                 lparm)
{
    switch (msg)
    {
      case WM_INITDIALOG:
        return TRUE;

      case WM_COMMAND:
        switch (wparm)
        {
          case IDCANCEL:
            DestroyWindow(dlg);
            return TRUE;
        }
        break;

      case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    return FALSE;
}

// show a failure
static void show_fail(char const *func, int result)
{
    char msgbuf[100];
    sprintf(msgbuf, "%s failed, error code %d", func, result);
    MessageBox(DlgWnd, msgbuf, "MKDB", MB_OK | MB_ICONSTOP);
}

int PASCAL WinMain(HINSTANCE inst, HINSTANCE pinst, LPSTR cmdline, int
                   cmdshow)
{
    a_create_db dbc;
    a_dbtools_info dbi;
    DLGPROC dlgProc = (DLGPROC)MakeProcInstance((FARPROC)MyDlgProc, inst);
    int result;
    MSG msg;

    // show the dialog box
    DlgWnd = CreateDialog(inst, "MYDIALOG", NULL, dlgProc);
    if (DlgWnd == NULL)
    {
        MessageBox(0, "Could not create dialog", 0, MB_OK | MB_ICONSTOP);
        return 4;
    }
    ShowWindow(DlgWnd, cmdshow);
    UpdateWindow(DlgWnd);

    // initialize DBTools
    memset(&dbi, 0, sizeof(dbi));
    dbi.errorrtn = (MSG_CALLBACK)MakeProcInstance((FARPROC)error_cb, inst);
    result = DBToolsInit(&dbi);
    if (result != 0)
    {
        show_fail("DBToolsInit", result);
        return 1;
    }

    // setup for create
    dbc.version = DB_TOOLS_VERSION_NUMBER;
    dbc.dbname = "h:\\play\\jan98\\testdb.db";
    dbc.logname = "h:\\play\\jan98\\testdb.log";
    dbc.startline = NULL;
    dbc.page_size = 512;
    dbc.default_collation = "850";
    dbc.errorrtn = dbi.errorrtn;
    dbc.msgrtn = (MSG_CALLBACK)MakeProcInstance((FARPROC)msg_cb, inst);
    dbc.database_version = 0;
    dbc.verbose = VB_NORMAL; // or VB_QUIET, VB_VERBOSE
    dbc.blank_pad = NO_BLANK_PADDING; // or BLANK_PADDING
    dbc.respect_case = 0; // 1 for case sensitive
    dbc.encrypt = 0;
    dbc.debug = 0;
    dbc.dbo_avail = 1;
    dbc.mirrorname_present = 0;
    dbc.dbo_username = "DBO";
    dbc.mirrorname = NULL;

    // create the database: this takes a while and updates the dialog box
    result = DBCreate(&dbc);
    if (result != 0)
    {
        show_fail("DBCreate", result);
        return 2;
    }

    // clean up and resources
    result = DBToolsFini(&dbi);
    if (result != 0)
    {
        show_fail("DBToolsFini", result);
        return 3;
    }

    // keep the dialog up until closed
    EnableWindow(GetDlgItem(DlgWnd, IDCANCEL), 1);
    while (GetMessage(&msg, 0, 0, 0))
    {
        if (!IsDialogMessage(DlgWnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    // release the proc instances
    FreeProcInstance((FARPROC)dlgProc);
    FreeProcInstance((FARPROC)dbc.errorrtn);
    FreeProcInstance((FARPROC)dbc.msgrtn);

    return 0;
}

and the resources:

// mkdb.rc
#include <windows.h>

MYDIALOG DIALOG 18, 18, 186, 138
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME
CAPTION "MKDB"
FONT 8, "Helv"
BEGIN
	LTEXT "Progress log", -1, 3, 3, 48, 8
	CONTROL "", 100, "EDIT", ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_GROUP | WS_TABSTOP, 4, 15, 177, 106
	CONTROL "Close", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_GROUP | WS_TABSTOP, 139, 123, 40, 12
END

To build this:

wrc -bt=windows -r mkdb.rc
wcl -bt=window -l=windows -ml -zWs -d2 -i=j:\sqlany50\h mkdb.c j:dbtoolsw.lib /"op res=mkdb.res"