Extending Cogent Prolog with Windows GUI Elements
-------------------------------------------------

Cogent Prolog is distributed as a compact Prolog engine that is easily
extensible to allow direct communication from Prolog to any facilities
available from C/C++.  This is done by defining your own extended predicates
in C/C++ and linking them into a custom version of the Prolog engine.
(You can also embed a Prolog engine, custom or otherwise, in C/C++ or
any language that can access a Windows DLL, such as Visual Basic.)

Because the 3.0 release is relatively new, we do not have a large library
of such extensions built up, but there are many examples.  All of the DOS-
specific extensions (such as mouse and full screen access) to the DOS
version are implemented using the Logic Server API and distributed in
source form so they can be easily extended and/or modified.

So, while Cogent doesn't come with many extended predicates giving the
Prolog programmer access to Windows capabilities, it does come with
a few that can be easily augmented to provide exactly the degree of
Windows programming capability you would like.  (There are many design
issues here, all related to whether you want the Prolog program to
provide simple menu and dialog support that is easy to use, or provide
full access to the rich complexities of Windows, and whether you want
to recreate an event-drive Prolog programming style, or preserve the
more traditional command-driven style of program.  This is the primary
reason we haven't provided much here.)

Implementing interfaces such as this is not difficult.  For example,
under contract to one of our customers we implemented a full programming
interface to a DOS GUI package, from Prolog.  The work took about
two weeks and lets the Prolog programmer develop and manipulate the
DOS GUI purely from Prolog.  This was all done using the Logic Server
API that is available to all our customers.  (The source code for that
interface is available on an as-is basis.)

Attached to the end of this message is the sample code for implementing
three Windows-specific extended predicates in Cogent Prolog.  We will
be adding many more, but doubt that our provided extensions will ever
be exactly what any one customer needs.

(The Windows version of Cogent does have a full IDE for developing Prolog
programs, but it uses the normal Prolog listener environment for running
the code.  The IDE is an example of an extended environment, it uses
the Logic Server API to capture the Prolog I/O streams and map them to
scrolling text windows.  The same Cogent interpreter, written in Prolog,
that runs under DOS, runs under Windows using the custom engine.)

//-----------------------------------------------------------
// Sample Extended Windows Predicates
// Microsoft Foundation Classes version
// (these predicates could be implemented using the SDK or
// any other GUI library, such as OWL or Zinc or XVT.)
//

#include "stdafx.h"
#include "cpeng.hpp"

TF __export p_msgbox(ENGid);
TF __export p_tfmsgbox(ENGid);
TF __export p_consult(ENGid);

// Provide mapping between Prolog predicate names and C functions
// This example defines msgbox/1, tfmsgbox/1, and consult/0.
PRED_INIT winPreds[] =
{
        {"msgbox", 1, p_msgbox},
        {"tfmsgbox", 1, p_tfmsgbox},
        {"consult", 0, p_consult},
        {NULL, 0, NULL}
};

// Put up a simple message box.
TF __export p_msgbox(ENGid eid)
{
        char msg[120];
        //Map the Prolog argument into a C string for display
        cpGetParm(eid, 1, cSTR, msg);
        AfxMessageBox(msg);
        return(TRUE);
}

// Put up a YESNO message box, allowing user to cause predicate to
// succeed or fail.
TF __export p_tfmsgbox(ENGid eid)
{
        char msg[120];
        cpGetParm(eid, 1, cSTR, msg);
        if (IDYES == AfxMessageBox(msg, MB_YESNO))
                return TRUE;
        else
                return FALSE;
}

// Use the Windows file open dialog box to let the user select a file
// to consult, and consult it.
TF __export p_consult(ENGid eid)
{
   CString sFile;
   TERM t;
   char buf[120];

   CFileDialog fileDlg(TRUE, ".pro", NULL,
                       OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
                       "Prolog Source (*.pro)|*.pro|All (*.*)|*.*||");

   if (fileDlg.DoModal() != IDOK) return(FALSE);
   sFile = fileDlg.GetPathName();
   // construct a Prolog query to consult the file
   sprintf(buf, "consult('%s')", (const char *)sFile);
   cpStrToTerm(eid, &t, buf);
   cpCall(eid, &t);
   return(TRUE);
}