Programming in XPCE/Prolog: Section D.1

## D.1 Basic predicates

This section describes the basic interface predicates. These predicates reside in the library module `pce', which is loaded when Prolog is started with PCE loaded on top of it.

new(?Reference, +TermDescription)
  Create a XPCE object from TermDescription and either unify an integer reference (e.g. @2535252) with Reference or give the new object the provided atomic reference (e.g. @my_diagram). The argument TermDescription is a complex term of the form Functor(...InitArg...) . Functor denotes the class from which to create an object and InitArg are the initialisation arguments for the object creation. Each InitArg is translated to a XPCE data object using the following rules:

  - atom
    Atoms are translated into XPCE name objects. This is a loss-less transformation.
  - integer
    Prolog integers are translated into XPCE int data-types. The range of XPCE int is half that of Prolog (i.e. ±2^30 on a 32-bit machine).
  - `Class(+InitArg...)`
    Creates an instance of class Class using InitArg.
  - `new(+TermDescription)`
    Same as plain InitArg, but an atom is translated to an instance of the named class. E.g. the term `new(chain)` is translated to an empty chain object rather then the atom `chain`.
  - `new(?Reference, +TermDescription)`
    Same as new/2 , handling Reference the same as the predicate new/2.
  - `prolog(Term)`
    Pass Term as an unmodified Prolog term.

  Below we illustrate the use of embedded new/2 terms in InitArg to get access to the reference of in-line created objects. The examples are functionally equivalent.

      1 ?- new(@icon_viewer, dialog('Icon Viewer 1')),
           new(P, picture),
           send(P, below, @icon_viewer),
           new(TI, text_item(name, '',
                     and(message(P, display, @arg1),
                         message(@arg1, recogniser,
                                 new(move_gesture))))),
           send(TI, type, bitmap),
           send(@icon_viewer, append, TI),
           send(@icon_viewer, open).

      2 ?- D = @icon_viewer,
           new(D, dialog('Icon Viewer 1')),
           send(new(P, picture), below, D),
           send(D, append,
                new(TI, text_item(name, '',
                          and(message(P, display, @arg1),
                              message(@arg1, recogniser,
                                      new(move_gesture)))))),
           send(TI, type, bitmap),
           send(D, open).

  Using new/2 with a variable reference argument is equivalent to invoking `Class`<-`instance: InitArgs ...'. The arguments needed to instantiate a class are defined by the `->`initialise method of this class. See also section 3.3.1.

send(+Receiver, +Selector(+Argument...))
send(+Receiver, +Selector, +Argument...)
  Invoke a send-method on the Receiver. Receiver is processed as the InitArgs described with new/2. This implies that a complex term is translated into an object before the method is invoked. An atom is translated into an XPCE name object. Selector is a Prolog atom which is translated into a XPCE name object. The Arguments are processed as the InitArgs described with new/2.

  The predicate send/[2-12] fails with an error message if one of the arguments cannot be translated or there is a type-error or an argument-error. The method itself may also produce error messages. This predicate only succeeds if the requested method was executed successfully.

  Trailing arguments that can handle @default (indicated by square brackets in the type declaration) may be omitted.

  If the method accepts many arguments of which most are default, using the named argument convention may be preferred. For example:

      ...,
      send(Graphical, graphics_state, colour := red),
      ...,

  The first form using `Selector(Argument...)` is the principal form. The second is translated by the XPCE/Prolog macro-layer and available for compatibility and style-preference.

get(+Receiver, +Selector(+Argument...), -Result)
get(+Receiver, +Selector, +Argument..., -Result)
  Invoke a get-method on Receiver. Receiver, Selector and Argument... are processed as with send/[2-12]. If the method fails, this predicate fails too. Otherwise the XPCE result of invoking the method is unified with Result.

  If the return value is a XPCE integer, real object or name object, it is unified with a Prolog integer, float or atom. Otherwise if the Prolog return argument is a variable or a term @/1 it is unified with the object reference. Otherwise the Prolog argument should be a compound term. Its functor will be compared with the class-name of the XPCE return value. The arguments will be unified in the same manner with the term-description arguments as declared with the class. Examples:

      1 ?- get(@pce, user, User).
      User = fred
      2 ?- get(@display, size, Size).
      Size = @474573
      3 ?- get(@display, size, size(W, H)).
      W = 1152, H = 900

  It is not advised to use the latter construct for other objects than elementary objects such as point, area, size, string, etc..

free(+Reference)
  Send `->`free to Reference if it is a valid reference. Defined as

      free(Ref) :- object(Ref), !, send(Ref, free).
      free(_).

  This definition implies free/1 only fails if the object may not be freed (see `object`->`protect').

send_class(+Reference, +Class, +Selector(+Arg...))
get_class(+Reference, +Class, +Selector(+Arg...), -Result)
send_super(+Reference, +Selector(+Arg...))
get_super(+Reference, +Selector(+Arg...), -Result)
send_super(+Reference, +Selector, +Arg...)
get_super(+Reference, +Selector, +Arg..., -Result)
  The predicates send_class/3 and get_class/4 invoke methods on a super-class of the class Reference belongs to. In most cases methods access the immediate super-class and this is the function of send_super/[2-12] and get_super/[3-13].

  The *_super calls are macro-expanded to send_class/3 or get_class/4. They must appear within a XPCE class definition. Though not enforced, using any of these predicates or macros outside the context of a method-definition should be considered illegal. See chapter 7 for further discussion on defining classes and methods.

object(+Reference)
  Succeeds if Reference is a term of the form @/1 and the argument is a valid object reference. Fails silently otherwise. Note that the form @Integer is only save to test whether or not an object has already been freed as a side-effect of freeing another object. Consider the following example:

      1 ?- new(P, point(100,100)).
      P = @235636/point
      2 ?- free(@235636).
      3 ?- object(@235636).           ---> fail
      4 ?- new(S, size(50,50)).
      S = @235636/size

  If `->`free is invoked on an object that has no references, its memory will be reclaimed immediately. As long as the memory has not been reused object/1 is guaranteed to fail. If the memory is reused for storing a new object object/1 will succeed, but point to another object than expected. Finally, the memory may be reused by a non-object data structure. In this case object/1 only applies heuristics to detect whether the memory holds an object. See also section 12 and section 10.3.3

object(+Reference, -TermDescription)
  Unify object description with the argument. Normally only used for debugging purposes. Equivalent to:

      object(Ref, Term) :-
              object(Ref),
              get_object(Ref, self, Term).

pce_global(+Reference, :Create)
  Define exception handler for undefined global (named) reference. When XPCE refers to a non-existing named reference an exception is raised. The standard handler for this exception will scan the pce_global/2 database and execute the Create action. Create is either a term of the form new(+TermDescription) or another term. In the first case TermDescription is transformed into a XPCE object as the second argument of new/2. In the latter case, Reference is appended to the list of arguments of the term and the term is called as a Prolog goal:

      :- pce_global(@succeed, new(and)).
      :- pce_global(@event_receiver,
                    new(@event?receiver)).
      :- pce_global(@select_recogniser,
                    make_select_recogniser).

      make_select_recogniser(R) :-
              new(G, handler_group),
              send_list(G, append,
                [ click_gesture(left, '', single,
                        message(@event_receiver?device,
                                selection, @event_receiver))
                , click_gesture(left, s, single,
                        message(@event_receiver,
                                toggle_selected))
                ]).

  See section 6 for more examples.

pce_open(+Object, +Mode, -Stream)
  The predicate pce_open/3 opens an XPCE object as a Prolog stream. Using this stream, the normal Prolog I/O predicates for reading from, or writing to the object can be used.

  This predicate works on any object that implements the *as_file methods. Currently this is only implemented for class text_buffer. See `text_buffer`<-`read_as_file', `text_buffer`<-`size_as_file', `text_buffer `->`truncate_as_file' and `text_buffer`->`write_as_file'.

  The stream handle is discarded using Prolog's close/1 predicate. For example, to write to a view, one could use:

      ...
      pce_open(View, append, Stream),
      format(Stream, 'Hello World~n', []),
      close(View),
      ...

  See also `text_buffer`->`format'. Reading from a stream is used by the PceEmacs editor to verify the syntax of an entered clause.

pce_catch_error(+ErrorIds, +Goal)
  This predicates allows the application to handle errors occuring while Goal is called. ErrorIds is either an atom representing the id of XPCE error or a chain of such id's. If one of the given errors occurrs the goal will silently fail and `@pce`<-`last_error' holds the id of the trapped error. Any other error that occurs during the execution of Goal will be handled by XPCE's normal error handling mechanism. See section 10.8.

### D.1.1 Portable declaration of required library predicates

Different Prolog implementations to which XPCE has been connected provide a different library structure and offers different means for accessing library predicates. For this reason, XPCE introduced the require/1 directive. This directive is the preferred way to import library predicates. Below is a typical declaration of an XPCE/Prolog module:

    :- module(mymodule, [myapp/0]).
    :- use_module(library(pce)).
    :- require([ member/2,
                 send_list/3
               ]).

require(:ListOfNameArity)
  Defines that this module requires the named predicates. It is the task of the Prolog system to make sure the module can make calls to the named predicates and this predicate has the `commonly accepted semantics'. This predicate is built-in for SICStus and SWI-Prolog. It is defined in the module library(pce) for ProWindows-3/Quintus. This is the reason why library(pce) should always be imported explicitely.

  Note the command Pce/PceInsertRequireDirective in PceEmacs Prolog mode, which automatically determines the required require-directive for the current module-file.

auto_call(:Goal)
  Acts like call/1, but dynamically loads the predicate required by Goal if this predicate is not defined. On systems not having autoloading, the definition is:

      auto_call(Goal) :-
              strip_module(Goal, Module, Predicate),
              functor(Predicate, Name, Arity),
              require(Module:[Name/Arity]),
              Goal.