pure-data/src/g_canvas.h

/* Copyright (c) 1997-1999 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */

/* this file defines the structure for "glists" and related structures and
functions.  "Glists" and "canvases" and "graphs" used to be different
structures until being unified in version 0.35.

A glist occupies its own window if the "gl_havewindow" flag is set.  Its
appearance on its "parent", also called "owner", (if it has one) is as a graph
if "gl_isgraph" is set, and otherwise as a text box.

A glist is "root" if it has no owner, i.e., a document window.  In this
case "gl_havewindow" is always set.

Note that "gl_havewindow" being set only means the canvas is visible in the
case that the GUI is up; the flag may be set before the GUI starts up or
after it has been shut down.  In this case if we later start the GUI up we
check this flag and repeat a canvas_vis() call to make it truly visible.  This
is uncomfortable - it seems like we're overloading this flag in a confusing
way and need a rethink.

If a glist has a window it may still not be "mapped."  Miniaturized
windows aren't mapped, for example, but a window is also not mapped
immediately upon creation.  In either case gl_havewindow is true but
gl_mapped is false.

We maintain a list of root windows, so that we can traverse the whole
collection of everything in a Pd process.

Closing a non-root window makes it invisible; closing a root destroys it.

A glist that's just a text object on its parent is always "toplevel."  An
embedded glist can switch back and forth to appear as a toplevel by double-
clicking on it.  Single-clicking a text box makes the toplevel become visible
and raises the window it's in.

If a glist shows up as a graph on its parent, the graph is blanked while the
glist has its own window, even if miniaturized.

*/

/* NOTE: this file describes Pd implementation details which may change
in future releases.  The public (stable) API is in m_pd.h. */

#ifndef G_CANVAS_H
#define G_CANVAS_H

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif

/* --------------------- geometry ---------------------------- */
#define IOWIDTH
#define IHEIGHT
#define OHEIGHT
#define IOMIDDLE
#define GLIST_DEFGRAPHWIDTH
#define GLIST_DEFGRAPHHEIGHT

#define GLIST_DEFCANVASXLOC
#ifdef __APPLE__
#define GLIST_DEFCANVASYLOC
#else
#define GLIST_DEFCANVASYLOC
#endif

/* ----------------------- data ------------------------------- */

t_updateheader;

    /* types to support glists grabbing mouse motion or keys from parent */
t_glistmotionfn;
t_glistkeyfn;

EXTERN_STRUCT _rtext;
#define t_rtext

EXTERN_STRUCT _pdstruct;
#define t_pdstruct

EXTERN_STRUCT _guiconnect;
#define t_guiconnect

EXTERN_STRUCT _tscalar;
#define t_tscalar

EXTERN_STRUCT _canvasenvironment;
#define t_canvasenvironment

EXTERN_STRUCT _fielddesc;
#define t_fielddesc

t_selection;

    /* this structure is instantiated whenever a glist becomes visible. */
t_editor;

#define MA_NONE
#define MA_MOVE
#define MA_CONNECT
#define MA_REGION
#define MA_PASSOUT
#define MA_DRAGTEXT
#define MA_RESIZE

/* editor structure for "garrays".  We don't bother to delete and regenerate
this structure when the "garray" becomes invisible or visible, although we
could do so if the structure gets big (like the "editor" above.) */

t_arrayvis;

/* the t_tick structure describes where to draw x and y "ticks" for a glist */

t_tick;

/* the t_glist structure, which describes a list of elements that live on an
area of a window.

*/

struct _glist
{};

#define gl_gobj
#define gl_pd

/* a data structure to describe a field in a pure datum */

#define DT_FLOAT
#define DT_SYMBOL
#define DT_TEXT
#define DT_ARRAY

t_dataslot;

t_template;

struct _array
{};

    /* structure for traversing all the connections in a glist */
t_linetraverser;

struct _instancecanvas  /* per-instance stuff for canvases */
{};

void g_editor_newpdinstance(void);
void g_template_newpdinstance(void);
void g_editor_freepdinstance(void);
void g_template_freepdinstance(void);

#define THISGUI

/* function types used to define graphical behavior for gobjs, a bit like X
widgets.  We don't use Pd methods because Pd's typechecking can't specify the
types of pointer arguments.  Also it's more convenient this way, since
every "patchable" object can just get the "text" behaviors. */

        /* Call this to get a gobj's bounding rectangle in pixels */
t_getrectfn;
        /* and this to displace a gobj: */
t_displacefn;
        /* change color to show selection: */
t_selectfn;
        /* change appearance to show activation/deactivation: */
t_activatefn;
        /* warn a gobj it's about to be deleted */
t_deletefn;
        /*  making visible or invisible */
t_visfn;
        /* field a mouse click (when not in "edit" mode) */
t_clickfn;
        /* ... and later, resizing; getting/setting font or color... */

struct _widgetbehavior
{};

/* -------- behaviors for scalars defined by objects in template --------- */
/* these are set by "drawing commands" in g_template.c which add appearance to
scalars, which live in some other window.  If the scalar is just included
in a canvas the "parent" is a misnomer.  There is also a text scalar object
which really does draw the scalar on the parent window; see g_scalar.c. */

/* note how the click function wants the whole scalar, not the "data", so
doesn't work on array elements... LATER reconsider this */

        /* bounding rectangle: */
t_parentgetrectfn;
        /* displace it */
t_parentdisplacefn;
        /* change color to show selection */
t_parentselectfn;
        /* change appearance to show activation/deactivation: */
t_parentactivatefn;
        /*  making visible or invisible */
t_parentvisfn;
        /*  field a mouse click */
t_parentclickfn;

struct _parentwidgetbehavior
{};

    /* cursor definitions; used as return value for t_parentclickfn */
#define CURSOR_RUNMODE_NOTHING
#define CURSOR_RUNMODE_CLICKME
#define CURSOR_RUNMODE_THICKEN
#define CURSOR_RUNMODE_ADDPOINT
#define CURSOR_EDITMODE_NOTHING
#define CURSOR_EDITMODE_CONNECT
#define CURSOR_EDITMODE_DISCONNECT
#define CURSOR_EDITMODE_RESIZE
EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);

extern t_canvas *canvas_whichfind;  /* last canvas we did a find in */
extern t_class *vinlet_class, *voutlet_class;
extern int glist_valid;         /* incremented when pointers might be stale */

#define PLOTSTYLE_POINTS
#define PLOTSTYLE_POLY
#define PLOTSTYLE_BEZ

/* ------------------- functions on any gobj ----------------------------- */
EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1,
    int *x2, int *y2);
EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy);
EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state);
EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state);
EXTERN void gobj_delete(t_gobj *x, t_glist *owner);
EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag);
EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
    int xpix, int ypix, int shift, int alt, int dbl, int doit);
EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist);

/* -------------------- functions on glists --------------------- */
EXTERN void glist_init(t_glist *x);
EXTERN void glist_add(t_glist *x, t_gobj *g);

EXTERN void glist_clear(t_glist *x);
EXTERN t_canvas *glist_getcanvas(t_glist *x);
EXTERN int glist_isselected(t_glist *x, t_gobj *y);
EXTERN void glist_select(t_glist *x, t_gobj *y);
EXTERN void glist_deselect(t_glist *x, t_gobj *y);
EXTERN void glist_noselect(t_glist *x);
EXTERN void glist_selectall(t_glist *x);
EXTERN void glist_delete(t_glist *x, t_gobj *y);
EXTERN void glist_retext(t_glist *x, t_text *y);
EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
    t_glistkeyfn keyfn, int xpos, int ypos);
EXTERN int glist_isvisible(t_glist *x);
EXTERN int glist_istoplevel(t_glist *x);
EXTERN t_glist *glist_findgraph(t_glist *x);
EXTERN int glist_getfont(t_glist *x);
EXTERN int glist_fontwidth(t_glist *x);
EXTERN int glist_fontheight(t_glist *x);
EXTERN int glist_getzoom(t_glist *x);
EXTERN void glist_sort(t_glist *canvas);
EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format);
EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format);

EXTERN t_float glist_pixelstox(t_glist *x, t_float xpix);
EXTERN t_float glist_pixelstoy(t_glist *x, t_float ypix);
EXTERN t_float glist_xtopixels(t_glist *x, t_float xval);
EXTERN t_float glist_ytopixels(t_glist *x, t_float yval);
EXTERN t_float glist_dpixtodx(t_glist *x, t_float dxpix);
EXTERN t_float glist_dpixtody(t_glist *x, t_float dypix);

EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval);
EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv);
EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym,
    t_float x1, t_float y1, t_float x2, t_float y2,
    t_float px1, t_float py1, t_float px2, t_float py2);
EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name,
    t_floatarg size, t_floatarg saveit, t_floatarg newgraph);
EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething);
EXTERN int glist_isgraph(t_glist *x);
EXTERN void glist_redraw(t_glist *x);
EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
    const char *tag, int x1, int y1, int x2, int y2);
EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, const char *tag);
EXTERN void canvas_create_editor(t_glist *x);
EXTERN void canvas_destroy_editor(t_glist *x);
void canvas_deletelinesforio(t_canvas *x, t_text *text,
    t_inlet *inp, t_outlet *outp);

t_rtext *glist_textedfor(t_glist *gl);
void glist_settexted(t_glist *gl, t_rtext *x);

/* -------------------- functions on texts ------------------------- */
EXTERN void text_setto(t_text *x, t_glist *glist, const char *buf, int bufsize);
EXTERN void text_drawborder(t_text *x, t_glist *glist, const char *tag,
    int firsttime);
EXTERN void text_eraseborder(t_text *x, t_glist *glist, const char *tag);
EXTERN int text_xpix(t_text *x, t_glist *glist);
EXTERN int text_ypix(t_text *x, t_glist *glist);
extern const t_widgetbehavior text_widgetbehavior;

/* -------------------- functions on rtexts ------------------------- */
#define RTEXT_DOWN
#define RTEXT_DRAG
#define RTEXT_DBL
#define RTEXT_SHIFT

EXTERN t_rtext *glist_getrtext(t_glist *gl, t_text *who);
EXTERN t_rtext *glist_getforscalar(t_glist *gl, t_scalar *sc, t_word *words,
    t_gobj *drawtext);
EXTERN void rtext_draw(t_rtext *x);
EXTERN void rtext_erase(t_rtext *x);
EXTERN int rtext_height(t_rtext *x);
EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
EXTERN void rtext_select(t_rtext *x, int state);
EXTERN void rtext_activate(t_rtext *x, int state);
EXTERN void rtext_free(t_rtext *x);
EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
EXTERN void rtext_retext(t_rtext *x);
EXTERN int rtext_width(t_rtext *x);
EXTERN const char *rtext_gettag(t_rtext *x);
EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
EXTERN void rtext_getseltext(t_rtext *x, char **buf, int *bufsize);
EXTERN t_text *rtext_getowner(t_rtext *x);
EXTERN t_glist *rtext_getglist(t_rtext *x);
EXTERN void rtext_unmouse(t_rtext *x);
EXTERN void rtext_untype(t_rtext *x);
EXTERN void rtext_getrect(t_rtext *x, int *x1p, int *y1p, int *x2p, int *y2p);
EXTERN void rtext_retextforscalar(t_rtext *x, char *buf, int len,
    int xpix, int ypix);
EXTERN int rtext_hit(t_rtext *x, int xpix, int ypix,
    int *x1p, int *y1p, int *x2p, int *y2p);
t_rtext *rtext_findhit(t_glist *gl, int xpix, int ypix,
    t_text **text, t_scalar **scalar, t_word **words, t_gobj **drawtext);

/* -------------------- functions on canvases ------------------------ */
EXTERN t_class *canvas_class;

EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv);
EXTERN t_symbol *canvas_makebindsym(t_symbol *s);
EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text);
EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text);
EXTERN void canvas_stowconnections(t_canvas *x);
EXTERN void canvas_restoreconnections(t_canvas *x);
EXTERN void canvas_redraw(t_canvas *x);
EXTERN void canvas_closebang(t_canvas *x);
EXTERN void canvas_initbang(t_canvas *x);

EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym);
EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip);
EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym);
EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op);
EXTERN void canvas_redrawallfortemplate(t_template *tmpl, int action);
EXTERN void canvas_redrawallfortemplatecanvas(t_canvas *x, int action);
EXTERN void canvas_setcurrent(t_canvas *x);
EXTERN void canvas_unsetcurrent(t_canvas *x);
EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
EXTERN void canvas_dirty(t_canvas *x, t_floatarg n);
t_canvasapply;

EXTERN void canvas_resortinlets(t_canvas *x);
EXTERN void canvas_resortoutlets(t_canvas *x);
EXTERN void canvas_free(t_canvas *x);
EXTERN void canvas_updatewindowlist(void);
EXTERN void canvas_editmode(t_canvas *x, t_floatarg state);
EXTERN int canvas_isabstraction(const t_canvas *x);
EXTERN int canvas_istable(const t_canvas *x);
EXTERN int canvas_showtext(const t_canvas *x);
EXTERN void canvas_vis(t_canvas *x, t_floatarg f);
EXTERN t_canvasenvironment *canvas_getenv(const t_canvas *x);
EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir);
EXTERN void canvas_loadbang(t_canvas *x);
EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
    int *x1p, int *y1p, int *x2p, int *y2p);
EXTERN int canvas_setdeleting(t_canvas *x, int flag);

#define LB_LOAD
#define LB_INIT
#define LB_CLOSE

t_undofn;        /* a function that does UNDO/REDO */
#define UNDO_FREE
#define UNDO_UNDO
#define UNDO_REDO
EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
    const char *name);
EXTERN void canvas_noundo(t_canvas *x);
EXTERN int canvas_getindex(t_canvas *x, t_gobj *y);

EXTERN void canvas_connect(t_canvas *x,
    t_floatarg fwhoout, t_floatarg foutno, t_floatarg fwhoin, t_floatarg finno);
EXTERN void canvas_disconnect(t_canvas *x,
    t_float index1, t_float outno, t_float index2, t_float inno);
EXTERN int canvas_isconnected (t_canvas *x,
    t_text *ob1, int n1, t_text *ob2, int n2);
EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy);

EXTERN t_glist *pd_checkglist(t_pd *x);
t_canvas_path_iterator;
EXTERN int canvas_path_iterate(const t_canvas *x, t_canvas_path_iterator fun,
    void *user_data);

/* check string for untitled canvas filename prefix */
#define UNTITLED_STRNCMP(s)

/* ---- functions on canvasses as objects  --------------------- */

EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x);
EXTERN t_outconnect *linetraverser_next(t_linetraverser *t);
EXTERN void linetraverser_skipobject(t_linetraverser *t);

/* --------- functions on garrays (graphical arrays) -------------------- */

EXTERN t_template *garray_template(t_garray *x);

/* -------------------- arrays --------------------- */
#define GRAPH_ARRAY_SAVE
#define GRAPH_ARRAY_PLOTSTYLE
#define GRAPH_ARRAY_SAVESIZE

EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl,
    t_floatarg f, t_floatarg flags);
EXTERN t_array *array_new(t_symbol *templatesym, int length,
    t_gpointer *parent);
EXTERN void array_resize(t_array *x, int n);
EXTERN void array_free(t_array *x);
EXTERN void array_redraw(t_array *a, t_glist *glist);
EXTERN void array_resize_and_redraw(t_array *array, t_glist *glist, int n);

/* --------------------- gpointers and stubs ---------------- */
EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a);
EXTERN void gstub_cutoff(t_gstub *gs);
EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x);
EXTERN void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w);

/* --------------------- scalars ------------------------- */
EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp);
EXTERN void word_initvec(t_word *wp, t_template *tmpl, t_gpointer *gp, long n);
EXTERN void word_restore(t_word *wp, t_template *tmpl,
    int argc, t_atom *argv);
EXTERN t_scalar *scalar_new(t_glist *owner,
    t_symbol *templatesym);
EXTERN void word_free(t_word *wp, t_template *tmpl);
EXTERN void word_freevec(t_word *wp, t_template *tmpl, long n);
EXTERN void scalar_getbasexy(t_scalar *x, t_float *basex, t_float *basey);
EXTERN void scalar_redraw(t_scalar *x, t_glist *glist);
EXTERN void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
    int amarrayelement);
EXTERN int canvas_readscalar(t_glist *x, int natoms, t_atom *vec,
    int *p_nextmsg, int selectit);
EXTERN void scalar_addrtexts(t_scalar *y, t_glist *gl);
EXTERN int scalar_click(t_gobj *z, struct _glist *owner,
    int xpix, int ypix, int shift, int alt, int dbl, int doit);

EXTERN int scalar_doclick(t_word *data, t_template *template, t_scalar *sc,
    t_array *ap, struct _glist *owner,
    t_float xloc, t_float yloc, int xpix, int ypix,
    int shift, int alt, int dbl, int doit);

/* ------helper routines for "garrays" and "plots" -------------- */
EXTERN void array_getcoordinate(t_glist *glist,
    char *elem, int xonset, int yonset, int wonset, int indx,
    t_float basex, t_float basey, t_float xinc,
    t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
    t_float *xp, t_float *yp, t_float *wp);

EXTERN int array_getfields(t_symbol *elemtemplatesym,
    t_canvas **elemtemplatecanvasp,
    t_template **elemtemplatep, int *elemsizep,
    t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
    int *xonsetp, int *yonsetp, int *wonsetp);

/* --------------------- templates ------------------------- */
EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv);
EXTERN void template_free(t_template *x);
EXTERN int template_match(t_template *x1, t_template *x2);
EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset,
    int *p_type, t_symbol **p_arraytype);
EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp,
    int loud);
EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp,
    t_float f, int loud);
EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
    t_word *wp, int loud);
EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
    t_word *wp, t_symbol *s, int loud);
void template_notifyforscalar(t_template *template, t_glist *owner,
    t_scalar *sc, t_symbol *s, int argc, t_atom *argv);

EXTERN t_template *gtemplate_get(t_pdstruct *x);
EXTERN t_template *glist_findtemplate(t_glist *gl);
EXTERN t_template *template_findbyname(t_symbol *s);
EXTERN t_canvas *template_findcanvas(t_template *tmpl);
EXTERN void template_notify(t_template *tmpl,
    t_symbol *s, int argc, t_atom *argv);

EXTERN t_float fielddesc_getcoord(t_fielddesc *f, t_template *tmpl,
    t_word *wp, int loud);
EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl,
    t_word *wp, t_float pix, int loud);
EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, t_float val);
EXTERN t_float fielddesc_cvtfromcoord(t_fielddesc *f, t_float coord);

EXTERN int drawtext_gettype(t_gobj *z, t_template *template, int *onsetp);
EXTERN t_template *drawtext_gettemplate(t_gobj *z);

/* ----------------------- guiconnects, g_guiconnect.c --------- */
EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);

/* ------------- IEMGUI routines used in other g_ files ---------------- */
EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
EXTERN t_symbol *iemgui_put_in_braces(t_symbol *s);

/*-------------  g_clone.c ------------- */
EXTERN t_class *clone_class;

/*-------------  d_ugen.c ------------- */
EXTERN void signal_setborrowed(t_signal *sig, t_signal *sig2);
EXTERN void signal_makereusable(t_signal *sig);


#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif

#endif // G_CANVAS_H