2017-08-18 20:15:12 +02:00
|
|
|
|
/* grTCairo1.c
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*
|
|
|
|
|
|
* Copyright (C) 2003 Open Circuit Design, Inc., for MultiGiG Ltd.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This file contains primitive functions for OpenGL running under
|
|
|
|
|
|
* an X window system in a Tcl/Tk interpreter environment
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
#include <GL/gl.h>
|
|
|
|
|
|
#include <GL/glx.h>
|
|
|
|
|
|
*/
|
2017-08-30 22:34:42 +02:00
|
|
|
|
#include <cairo/cairo-xlib.h>
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
|
|
|
|
#include "utils/main.h"
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
|
#include "utils/malloc.h"
|
|
|
|
|
|
#include "utils/magsgtty.h"
|
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
|
#include "windows/windows.h"
|
|
|
|
|
|
#include "graphics/graphics.h"
|
|
|
|
|
|
#include "graphics/graphicsInt.h"
|
|
|
|
|
|
#include "textio/textio.h"
|
|
|
|
|
|
#include "textio/txcommands.h"
|
|
|
|
|
|
#include "utils/signals.h"
|
|
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
|
#include "drc/drc.h"
|
|
|
|
|
|
#include "utils/macros.h"
|
2017-08-18 20:15:12 +02:00
|
|
|
|
//#include "graphics/grTCairoInt.h"
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#include "graphics/grTCairoInt.h"
|
|
|
|
|
|
#include "utils/paths.h"
|
|
|
|
|
|
#include "graphics/grTkCommon.h"
|
|
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
uint8_t **grTCairoStipples;
|
|
|
|
|
|
HashTable grTCairoWindowTable;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
//GLXContext grXcontext;
|
|
|
|
|
|
cairo_surface_t *grCairoSurface;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
cairo_t *grCairoContext;
|
|
|
|
|
|
XVisualInfo *grVisualInfo;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
//TCairo_CURRENT tcairoCurrent= {(Tk_Font)0, 0, 0, 0, 0,
|
2017-08-04 20:25:41 +02:00
|
|
|
|
// (Tk_Window)0, (Window)0, (MagWindow *)NULL};
|
|
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
TCAIRO_CURRENT tcairoCurrent = {(Tk_Font)0, 0, 0, 0, 0,
|
|
|
|
|
|
(Tk_Window)0, (Window)0, (MagWindow *)NULL
|
|
|
|
|
|
};
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
/* This is kind of a long story, and very kludgy, but the following
|
|
|
|
|
|
* things need to be defined as externals because of the way lint
|
|
|
|
|
|
* libraries are made by taking this module and changing all procedures
|
|
|
|
|
|
* names "Xxxx" to "Grxxx". The change is only done at the declaration
|
|
|
|
|
|
* of the procedure, so we need these declarations to handle uses
|
|
|
|
|
|
* of those names, which don't get modified. Check out the Makefile
|
|
|
|
|
|
* for details on this.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2017-08-09 20:55:30 +02:00
|
|
|
|
extern void GrTCairoClose(), GrTCairoFlush();
|
|
|
|
|
|
extern void GrTCairoDelete(), GrTCairoConfigure(), GrTCairoRaise(), GrTCairoLower();
|
|
|
|
|
|
extern void GrTCairoLock(), GrTCairoUnlock(), GrTCairoIconUpdate();
|
|
|
|
|
|
extern bool GrTCairoInit();
|
|
|
|
|
|
extern bool GrTCairoEventPending(), GrTCairoCreate(), grtcairoGetCursorPos();
|
|
|
|
|
|
extern int GrTCairoWindowId();
|
|
|
|
|
|
extern char *GrTkWindowName();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-09 20:55:30 +02:00
|
|
|
|
extern void tcairoSetProjection();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* grtcairoSetWMandC:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* This is a local routine that resets the value of the current
|
|
|
|
|
|
* write alpha (mask) and color, if necessary.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Errors: None.
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
grtcairoSetWMandC (mask, c)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int mask; /* New value for write mask */
|
|
|
|
|
|
int c; /* New value for current color */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
static int oldColor = -1;
|
|
|
|
|
|
static int oldMask = -1;
|
|
|
|
|
|
|
|
|
|
|
|
int lr, lb, lg;
|
2017-08-09 20:55:30 +02:00
|
|
|
|
//GLfloat fr, fb, fg;
|
|
|
|
|
|
//GLfloat aval; /* Alpha default value was 0.75 */
|
|
|
|
|
|
float fr, fb, fg, aval;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
if (mask == -65) mask = 127; /* All planes */
|
|
|
|
|
|
if (mask == oldMask && c == oldColor) return;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
//GR_TCairo_FLUSH_BATCH();
|
2017-08-09 20:55:30 +02:00
|
|
|
|
GR_TCAIRO_FLUSH_BATCH();
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
GrGetColor(c, &lr, &lb, &lg);
|
|
|
|
|
|
|
2017-08-09 20:55:30 +02:00
|
|
|
|
fr = ((float)lr / 255);
|
|
|
|
|
|
fg = ((float)lg / 255);
|
|
|
|
|
|
fb = ((float)lb / 255);
|
|
|
|
|
|
aval = ((float)mask / 127.0);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
if (mask == 127)
|
|
|
|
|
|
{
|
|
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
|
aval = 1.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//Calculate a "supercolor", outside of the normal color range,
|
|
|
|
|
|
//but which results in the desired color after a blend with
|
|
|
|
|
|
//the background color.
|
|
|
|
|
|
|
|
|
|
|
|
fr = fr * 2 - 0.8;
|
|
|
|
|
|
fg = fg * 2 - 0.8;
|
|
|
|
|
|
fb = fb * 2 - 0.8;
|
|
|
|
|
|
|
|
|
|
|
|
aval = (GLfloat)mask / 127.0; // mask translates to alpha in
|
|
|
|
|
|
//the OpenGL version.
|
|
|
|
|
|
|
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//glColor4f(fr, fb, fg, aval);
|
|
|
|
|
|
|
|
|
|
|
|
cairo_set_source_rgba(grCairoContext, fr, fg, fb, aval);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
oldColor = c;
|
|
|
|
|
|
oldMask = mask;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* grtcairoSetLineStyle:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* This local routine sets the current line style.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* A new line style is output to the display.
|
|
|
|
|
|
*
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-30 22:34:42 +02:00
|
|
|
|
grtcairoSetLineStyle (style)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int style; /* New stipple pattern for lines. */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-11 21:42:32 +02:00
|
|
|
|
// unimplemented for cairo
|
|
|
|
|
|
/*
|
2017-08-07 20:17:12 +02:00
|
|
|
|
static int oldStyle = -1;
|
|
|
|
|
|
GLushort glstyle;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
style &= 0xFF;
|
|
|
|
|
|
if (style == oldStyle) return;
|
|
|
|
|
|
oldStyle = style;
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GR_TCairo_FLUSH_BATCH();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
switch (style) {
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case 0xFF:
|
|
|
|
|
|
case 0x00:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
glDisable(GL_LINE_STIPPLE);
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
default:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
glstyle = style | (style << 8);
|
|
|
|
|
|
glEnable(GL_LINE_STIPPLE);
|
|
|
|
|
|
glLineStipple(1, glstyle);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-11 21:42:32 +02:00
|
|
|
|
*/
|
2017-08-30 22:34:42 +02:00
|
|
|
|
;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* grtcairoSetSPattern:
|
|
|
|
|
|
* tcairoSetSPattern associates a stipple pattern with a given
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* stipple number. This is a local routine called from
|
|
|
|
|
|
* grStyle.c .
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects: None.
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
cairo_pattern_t **stipplePatterns;
|
2017-08-11 21:18:32 +02:00
|
|
|
|
|
2017-08-04 20:25:41 +02:00
|
|
|
|
void
|
2017-08-30 22:34:42 +02:00
|
|
|
|
grtcairoSetSPattern (sttable, numstipples)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int **sttable; /* The table of patterns */
|
|
|
|
|
|
int numstipples; /* Number of stipples */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int i, j, k, n;
|
2017-08-15 21:19:13 +02:00
|
|
|
|
uint8_t *pdata;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
stipplePatterns = (cairo_pattern_t **)mallocMagic(sizeof(cairo_pattern_t *) * numstipples);
|
2017-08-11 21:18:32 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
grTCairoStipples = (uint8_t **)mallocMagic(numstipples * sizeof(uint8_t *));
|
2017-08-07 20:17:12 +02:00
|
|
|
|
for (k = 0; k < numstipples; k++)
|
|
|
|
|
|
{
|
2017-08-15 21:19:13 +02:00
|
|
|
|
pdata = (uint8_t *)mallocMagic(128 * sizeof(uint8_t));
|
2017-08-07 20:17:12 +02:00
|
|
|
|
n = 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* expand magic's default 8x8 stipple to OpenGL's 32x32 */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
|
|
for (j = 0; j < 4; j++) {
|
2017-08-15 21:19:13 +02:00
|
|
|
|
pdata[n++] = (uint8_t)sttable[k][i % 8];
|
2017-08-30 22:34:42 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-11 21:42:32 +02:00
|
|
|
|
grTCairoStipples[k] = pdata;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
stipplePatterns[k] = cairo_pattern_create_for_surface(cairo_image_surface_create_for_data(pdata, CAIRO_FORMAT_A1, 32, 32,
|
|
|
|
|
|
cairo_format_stride_for_width(CAIRO_FORMAT_A1, 32)));
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* grtcairoSetStipple:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* This routine sets the Xs current stipple number.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* The current clipmask in the X is set to stipple,
|
|
|
|
|
|
* if it wasn't that already.
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-30 22:34:42 +02:00
|
|
|
|
grtcairoSetStipple (stipple)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int stipple; /* The stipple number to be used. */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
static int oldStip = -1;
|
|
|
|
|
|
if (stipple == oldStip) return;
|
|
|
|
|
|
oldStip = stipple;
|
2017-08-11 21:42:32 +02:00
|
|
|
|
GR_TCAIRO_FLUSH_BATCH();
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (stipple == 0 || stipple > grNumStipples) {
|
2017-08-11 21:18:32 +02:00
|
|
|
|
//glDisable(GL_POLYGON_STIPPLE);
|
|
|
|
|
|
cairo_set_source_rgb(grCairoContext, 0, 0, 0);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
} else {
|
2017-08-30 22:34:42 +02:00
|
|
|
|
if (stipplePatterns[stipple] == (cairo_pattern_t *)NULL) MainExit(1);
|
2017-08-11 21:18:32 +02:00
|
|
|
|
//glEnable(GL_POLYGON_STIPPLE);
|
2017-08-18 20:15:12 +02:00
|
|
|
|
//glPolygonStipple(grTCairoStipples[stipple]);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
cairo_pattern_set_extend(stipplePatterns[stipple], CAIRO_EXTEND_REPEAT);
|
|
|
|
|
|
cairo_pattern_set_filter(stipplePatterns[stipple], CAIRO_FILTER_NEAREST);
|
|
|
|
|
|
cairo_set_source(grCairoContext, stipplePatterns[stipple]);
|
|
|
|
|
|
cairo_mask_surface(grCairoContext, grCairoSurface, 0.0, 0.0);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoInit:
|
|
|
|
|
|
* GrTCairoInit initializes the graphics display and clears its screen.
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Files must have been previously opened with GrSetDisplay();
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: TRUE if successful.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Notes: When 3D rendering is compiled in, we search for a double-buffered
|
|
|
|
|
|
* configuration first, because it generates the smoothest graphics,
|
2017-08-07 20:17:12 +02:00
|
|
|
|
* and fall back on a single-buffered configuration if necessary.
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* For normal, 2D-only rendering, we look for a single-buffered
|
|
|
|
|
|
* configuration first because we don't use the back buffer, so a
|
|
|
|
|
|
* double-buffered configuration just wastes space.
|
|
|
|
|
|
*------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
GrTCairoInit ()
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
bool rstatus;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
/*
|
|
|
|
|
|
#ifdef THREE_D
|
|
|
|
|
|
static int attributeList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
|
|
|
|
|
#else
|
|
|
|
|
|
static int attributeList[] = { GLX_RGBA, None, None };
|
|
|
|
|
|
#endif
|
|
|
|
|
|
*/
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
tcairoCurrent.window = Tk_MainWindow(magicinterp); // XDefaultRootWindow(grXdpy) ??
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (tcairoCurrent.window == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
TxError("No Top-Level Tk window available. . . is Tk running?\n");
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
tcairoCurrent.windowid = Tk_WindowId(tcairoCurrent.window);
|
|
|
|
|
|
grXdpy = Tk_Display(tcairoCurrent.window);
|
|
|
|
|
|
tcairoCurrent.depth = Tk_Depth(tcairoCurrent.window);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grXscrn = DefaultScreen(grXdpy);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
//grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList);
|
|
|
|
|
|
XVisualInfo grtemplate;
|
|
|
|
|
|
int gritems;
|
|
|
|
|
|
grtemplate.screen = grXscrn;
|
|
|
|
|
|
grtemplate.depth = 0;
|
|
|
|
|
|
grVisualInfo = XGetVisualInfo(grXdpy, VisualScreenMask, &grtemplate, &gritems);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (!grVisualInfo)
|
|
|
|
|
|
{
|
2017-08-30 22:34:42 +02:00
|
|
|
|
TxError("No suitable visual!\n");
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
/*
|
|
|
|
|
|
// Try for a double-buffered configuration
|
|
|
|
|
|
#ifdef THREE_D
|
2017-08-07 20:17:12 +02:00
|
|
|
|
attributeList[1] = None;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
#else
|
2017-08-07 20:17:12 +02:00
|
|
|
|
attributeList[1] = GLX_DOUBLEBUFFER;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
#endif
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList);
|
|
|
|
|
|
if (!grVisualInfo)
|
|
|
|
|
|
{
|
2017-08-30 22:34:42 +02:00
|
|
|
|
TxError("No suitable visual!\n");
|
|
|
|
|
|
return FALSE;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
2017-08-30 22:34:42 +02:00
|
|
|
|
*/
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
2017-08-30 22:34:42 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grXscrn = grVisualInfo->screen;
|
|
|
|
|
|
tcairoCurrent.depth = grVisualInfo->depth;
|
|
|
|
|
|
|
|
|
|
|
|
/* TRUE = Direct rendering, FALSE = Indirect rendering */
|
|
|
|
|
|
/* (note that direct rendering may not be able to deal with pixmaps) */
|
|
|
|
|
|
//grXcontext = glXCreateContext(grXdpy, grVisualInfo, NULL, GL_FALSE);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
|
|
|
|
|
|
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grCairoContext = cairo_create(grCairoSurface);
|
|
|
|
|
|
|
|
|
|
|
|
/* Basic GL parameters */
|
|
|
|
|
|
/*
|
|
|
|
|
|
glLineWidth(1.0);
|
|
|
|
|
|
glShadeModel (GL_FLAT);
|
|
|
|
|
|
glPixelStorei(GL_PACK_LSB_FIRST, TRUE);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*/
|
2017-08-07 20:17:12 +02:00
|
|
|
|
cairo_set_line_width(grCairoContext, 1.0);
|
|
|
|
|
|
cairo_set_source_rgb(grCairoContext, 0, 0, 0);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* OpenGL sets its own names for colormap and dstyle file types */
|
|
|
|
|
|
grCMapType = "OpenGL";
|
|
|
|
|
|
grDStyleType = "OpenGL";
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Globally-accessed variables */
|
|
|
|
|
|
grNumBitPlanes = tcairoCurrent.depth;
|
|
|
|
|
|
grBitPlaneMask = (1 << tcairoCurrent.depth) - 1;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
HashInit(&grTCairoWindowTable, 8, HT_WORDKEYS);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
return grTkLoadFont();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoClose:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoClose ()
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (grXdpy == NULL) return;
|
|
|
|
|
|
if (grVisualInfo != NULL) XFree(grVisualInfo);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grTkFreeFonts();
|
|
|
|
|
|
/* Pop down Tk window but let Tcl/Tk */
|
|
|
|
|
|
/* do XCloseDisplay() */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoFlush:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Flush output to display.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Flushing is done automatically the next time input is read,
|
|
|
|
|
|
* so this procedure should not be used very often.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects: None.
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoFlush ()
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-30 22:34:42 +02:00
|
|
|
|
GR_TCAIRO_FLUSH_BATCH();
|
|
|
|
|
|
//glFlush();
|
|
|
|
|
|
//glFinish();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//static GLXPixmap glpmap = None;
|
|
|
|
|
|
Pixmap cairopmap = (Pixmap)NULL;
|
|
|
|
|
|
|
|
|
|
|
|
#define glTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n))
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
* Set the OpenGL viewport (projection matrix) for a window
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
tcairoSetProjection(llx, lly, width, height)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int llx, lly, width, height;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (tcairoCurrent.mw->w_flags & WIND_OFFSCREEN)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
if (glpmap != None) glXDestroyGLXPixmap(grXdpy, glpmap);
|
|
|
|
|
|
glpmap = glXCreateGLXPixmap(grXdpy, grVisualInfo,
|
2017-08-18 20:15:12 +02:00
|
|
|
|
(Pixmap)tcairoCurrent.windowid);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
glXMakeCurrent(grXdpy, (GLXDrawable)glpmap, grXcontext);
|
|
|
|
|
|
*/
|
|
|
|
|
|
cairopmap = XCreatePixmap(grXdpy, grXscrn, width, height, tcairoCurrent.depth);
|
|
|
|
|
|
grCairoSurface = cairo_xlib_surface_create(grXdpy, cairopmap, grVisualInfo->visual, width, height);
|
|
|
|
|
|
}
|
2017-08-07 20:38:50 +02:00
|
|
|
|
else {
|
2017-08-18 20:15:12 +02:00
|
|
|
|
//glXMakeCurrent(grXdpy, (GLXDrawable)tcairoCurrent.windowid, grXcontext);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
|
2017-08-07 20:38:50 +02:00
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
// #ifndef Cairo_SERVER_SIDE_ONLY
|
|
|
|
|
|
// For batch-processing lines and rectangles
|
|
|
|
|
|
// glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
|
// #endif
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Because this tends to result in thick lines, it has been moved */
|
|
|
|
|
|
/* the line drawing routine so it can be enabled for individual */
|
|
|
|
|
|
/* lines. */
|
|
|
|
|
|
/* glEnable(GL_LINE_SMOOTH); */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Force draw to front buffer (in case of double-buffered config) */
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glDrawBuffer(GL_FRONT);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glMatrixMode(GL_PROJECTION);
|
|
|
|
|
|
//glLoadIdentity();
|
2017-08-31 20:11:17 +02:00
|
|
|
|
cairo_identity_matrix(grCairoContext);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
//glViewport((GLsizei)llx, (GLsizei)lly, (GLsizei) width, (GLsizei) height);
|
2017-08-07 21:37:14 +02:00
|
|
|
|
// cairo equivalent??
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* scale to fit window */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-30 22:34:42 +02:00
|
|
|
|
#ifdef CAIRO_INVERT_Y
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glScalef(1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1), 1.0);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
//cairo_scale(grCairoContext, 1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1));
|
|
|
|
|
|
cairo_scale(grCairoContext, width, -height);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#else
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glScalef(1.0 / (float)(width >> 1), 1.0 / (float)(height >> 1), 1.0);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
cairo_scale(grCairoContext, width, height);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* magic origin maps to window center; move to window origin */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glTranslated(-(GLsizei)(width >> 1), -(GLsizei)(height >> 1), 0);
|
2017-08-30 22:34:42 +02:00
|
|
|
|
cairo_translate(grCairoContext, -(int)(width >> 1), -(int)(height >> 1));
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Remaining transformations are done on the modelview matrix */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 21:37:14 +02:00
|
|
|
|
//glMatrixMode(GL_MODELVIEW);
|
|
|
|
|
|
//glLoadIdentity();
|
2017-08-31 20:11:17 +02:00
|
|
|
|
cairo_identity_matrix(grCairoContext);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ---------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* TCairoEventProc ---
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*
|
|
|
|
|
|
* Tk Event Handler
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Calls functions in response to X11 events.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ---------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
TCairoEventProc(clientData, xevent)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
ClientData clientData;
|
|
|
|
|
|
XEvent *xevent;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
TxInputEvent *event;
|
|
|
|
|
|
HashEntry *entry;
|
|
|
|
|
|
Tk_Window tkwind = (Tk_Window)clientData;
|
|
|
|
|
|
Window wind;
|
|
|
|
|
|
MagWindow *mw;
|
|
|
|
|
|
unsigned char LocRedirect = TxInputRedirect;
|
|
|
|
|
|
|
|
|
|
|
|
XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) xevent;
|
|
|
|
|
|
KeySym keysym;
|
|
|
|
|
|
int nbytes;
|
|
|
|
|
|
|
|
|
|
|
|
/* Keys and Buttons: Determine expansion of macros or redirect
|
|
|
|
|
|
* keys to the terminal or console.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
switch (xevent->type)
|
|
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case ButtonPress:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
XButtonEvent *ButtonEvent = (XButtonEvent *) xevent;
|
|
|
|
|
|
int txbutton;
|
|
|
|
|
|
|
|
|
|
|
|
switch (ButtonEvent->button) {
|
|
|
|
|
|
case Button1:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
txbutton = TX_LEFT_BUTTON;
|
|
|
|
|
|
keysym = XK_Pointer_Button1;
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case Button2:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
txbutton = TX_MIDDLE_BUTTON;
|
|
|
|
|
|
keysym = XK_Pointer_Button2;
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case Button3:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
txbutton = TX_RIGHT_BUTTON;
|
|
|
|
|
|
keysym = XK_Pointer_Button3;
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case Button4:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
txbutton = TX_BUTTON_4;
|
|
|
|
|
|
keysym = XK_Pointer_Button4;
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case Button5:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
txbutton = TX_BUTTON_5;
|
|
|
|
|
|
keysym = XK_Pointer_Button5;
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
nbytes = 0;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
if (mw && (mw->w_flags & WIND_SCROLLBARS))
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (WindButtonInFrame(mw, ButtonEvent->x,
|
|
|
|
|
|
grXtransY(mw, ButtonEvent->y),
|
|
|
|
|
|
txbutton))
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
goto keys_and_buttons;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case KeyPress:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
int keywstate, keymod, idx, idxmax;
|
|
|
|
|
|
char inChar[10];
|
|
|
|
|
|
Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT);
|
|
|
|
|
|
|
|
|
|
|
|
nbytes = XLookupString(KeyPressedEvent, inChar, sizeof(inChar),
|
2017-08-07 20:17:12 +02:00
|
|
|
|
&keysym, NULL);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
if (IsModifierKey(keysym)) break; /* Don't handle modifiers */
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
keys_and_buttons:
|
|
|
|
|
|
|
|
|
|
|
|
keymod = (LockMask | ControlMask | ShiftMask)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
& KeyPressedEvent->state;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#ifdef __APPLE__
|
|
|
|
|
|
if (KeyPressedEvent->state & (Mod1Mask | Mod2Mask |
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Mod3Mask | Mod4Mask | Mod5Mask))
|
|
|
|
|
|
keymod |= Mod1Mask;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#else
|
|
|
|
|
|
keymod |= (Mod1Mask & KeyPressedEvent->state);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (nbytes == 0) /* No ASCII equivalent */
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
keywstate = (keymod << 16) | (keysym & 0xffff);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (!strncmp(XKeysymToString(keysym), "KP_", 3))
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* keypad key (special case---would like to */
|
|
|
|
|
|
/* differentiate between shift-KP-# and # itself) */
|
|
|
|
|
|
keymod &= ~ShiftMask;
|
|
|
|
|
|
keywstate = (keymod << 16) | (keysym & 0xffff);
|
|
|
|
|
|
nbytes = 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
else /* ASCII-valued character */
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (!(keymod & (LockMask | Mod1Mask))) {
|
|
|
|
|
|
if (!(keymod & ControlMask))
|
|
|
|
|
|
keymod &= ~ShiftMask;
|
|
|
|
|
|
else if (!(keymod & ShiftMask))
|
|
|
|
|
|
keymod &= ~ControlMask;
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
idxmax = (nbytes == 0) ? 1 : nbytes;
|
|
|
|
|
|
for (idx = 0; idx < idxmax; idx++)
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (inChar[idx] == 3) /* Ctrl-C interrupt */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (SigInterruptPending)
|
|
|
|
|
|
MainExit(0); /* double Ctrl-C */
|
|
|
|
|
|
else
|
|
|
|
|
|
sigOnInterrupt(0); /* Set InterruptPending */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
else if (nbytes > 0)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if ((keymod & ControlMask) && (inChar[idx] < 32))
|
|
|
|
|
|
inChar[idx] += 'A' - 1;
|
|
|
|
|
|
|
|
|
|
|
|
keywstate = (keymod << 16) | ((int)inChar[idx] & 0xff);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
/* Allow buttons to bypass the console and be */
|
|
|
|
|
|
/* treated as macros. */
|
|
|
|
|
|
|
|
|
|
|
|
if (LocRedirect == TX_INPUT_REDIRECTED)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
switch (keysym)
|
|
|
|
|
|
{
|
|
|
|
|
|
case XK_Pointer_Button1:
|
|
|
|
|
|
case XK_Pointer_Button2:
|
|
|
|
|
|
case XK_Pointer_Button3:
|
|
|
|
|
|
case XK_Pointer_Button4:
|
|
|
|
|
|
case XK_Pointer_Button5:
|
|
|
|
|
|
LocRedirect = TX_INPUT_NORMAL;;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
if ((LocRedirect == TX_INPUT_REDIRECTED) && TxTkConsole)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tcl_SavedResult state;
|
|
|
|
|
|
static char outstr[] = "::tkcon::Insert .text \"x\" ";
|
|
|
|
|
|
|
|
|
|
|
|
switch (keysym)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
case XK_Return:
|
|
|
|
|
|
TxSetPoint(KeyPressedEvent->x,
|
|
|
|
|
|
grXtransY(mw, KeyPressedEvent->y),
|
|
|
|
|
|
mw->w_wid);
|
|
|
|
|
|
TxInputRedirect = TX_INPUT_PROCESSING;
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, "::tkcon::Eval .text",
|
|
|
|
|
|
19, 0);
|
|
|
|
|
|
TxInputRedirect = TX_INPUT_NORMAL;
|
|
|
|
|
|
TxSetPrompt('%');
|
|
|
|
|
|
|
|
|
|
|
|
Tcl_SaveResult(magicinterp, &state);
|
|
|
|
|
|
Tcl_EvalEx(magicinterp, "history event 0", 15, 0);
|
|
|
|
|
|
MacroDefine(mw->w_client, (int)'.',
|
|
|
|
|
|
Tcl_GetStringResult(magicinterp), NULL,
|
|
|
|
|
|
FALSE);
|
|
|
|
|
|
Tcl_RestoreResult(magicinterp, &state);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_Up:
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, "::tkcon::Event -1",
|
|
|
|
|
|
17, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_Down:
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, "::tkcon::Event 1",
|
|
|
|
|
|
16, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_Left:
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, ".text mark set insert "
|
|
|
|
|
|
"insert-1c ; .text see insert", 50, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_Right:
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, ".text mark set insert "
|
|
|
|
|
|
"insert+1c ; .text see insert", 50, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_BackSpace: case XK_Delete:
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, ".text delete insert-1c ;"
|
|
|
|
|
|
".text see insert", 40, 0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case XK_quotedbl: case XK_backslash: case XK_bracketleft:
|
|
|
|
|
|
outstr[23] = '\\';
|
|
|
|
|
|
outstr[24] = inChar[idx];
|
|
|
|
|
|
outstr[25] = '\"';
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, outstr, 26, 0);
|
|
|
|
|
|
outstr[24] = '\"';
|
|
|
|
|
|
outstr[25] = '\0';
|
|
|
|
|
|
default:
|
|
|
|
|
|
outstr[23] = inChar[idx];
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, outstr, 25, 0);
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
else if (LocRedirect == TX_INPUT_REDIRECTED) {
|
|
|
|
|
|
int tl;
|
|
|
|
|
|
if (TxBuffer == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
TxBuffer = Tcl_Alloc(2);
|
|
|
|
|
|
*TxBuffer = '\0';
|
|
|
|
|
|
tl = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
tl = strlen(TxBuffer);
|
|
|
|
|
|
TxBuffer = Tcl_Realloc(TxBuffer, tl + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (keysym == XK_BackSpace || keysym == XK_Delete)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tl >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tl > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
*(TxBuffer + tl - 1) = '\0';
|
|
|
|
|
|
TxPrintf("\b");
|
|
|
|
|
|
}
|
|
|
|
|
|
TxPrintf(" \b");
|
|
|
|
|
|
TxFlushOut();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (keysym == XK_Return)
|
|
|
|
|
|
{
|
|
|
|
|
|
*(TxBuffer + tl) = '\n';
|
|
|
|
|
|
*(TxBuffer + tl + 1) = '\0';
|
|
|
|
|
|
if (tl != 0) MacroDefine(mw->w_client,
|
|
|
|
|
|
XK_period, TxBuffer, NULL, FALSE);
|
|
|
|
|
|
TxInputRedirect = TX_INPUT_NORMAL;
|
|
|
|
|
|
TxSetPoint(KeyPressedEvent->x,
|
|
|
|
|
|
grXtransY(mw, KeyPressedEvent->y),
|
|
|
|
|
|
mw->w_wid);
|
|
|
|
|
|
TxPrintf("\n");
|
|
|
|
|
|
TxFlushOut();
|
|
|
|
|
|
Tcl_NotifyChannel(Tcl_GetStdChannel(TCL_STDIN),
|
|
|
|
|
|
TCL_READABLE);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
*(TxBuffer + tl) = *(inChar + idx);
|
|
|
|
|
|
*(TxBuffer + tl + 1) = '\0';
|
|
|
|
|
|
TxPrintf("%c", *(inChar + idx));
|
|
|
|
|
|
TxFlushOut();
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
bool iMacro;
|
|
|
|
|
|
char *macroDef;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
macroDef = MacroRetrieve(mw->w_client, keywstate, &iMacro);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Special handling: An imacro beginning with ':' */
|
|
|
|
|
|
/* sets the prompt to ':' and moves to the next char. */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (macroDef != NULL && *macroDef == ':' && iMacro)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TxTkConsole)
|
|
|
|
|
|
TxSetPrompt(':');
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
TxPrintf("\b\b: ");
|
|
|
|
|
|
TxFlushOut();
|
|
|
|
|
|
}
|
|
|
|
|
|
memmove(macroDef, macroDef + 1, strlen(macroDef + 1) + 1);
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
macroDef = MacroSubstitute(macroDef, "%W", Tk_PathName(tkwind));
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (macroDef == NULL)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (keysym != XK_Return)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *vis = MacroName(keywstate);
|
|
|
|
|
|
TxError("Unknown macro or short command: '%s'\n", vis);
|
|
|
|
|
|
|
|
|
|
|
|
freeMagic(vis);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Print Carriage Return & Put back Tcl/Tk prompt */
|
|
|
|
|
|
TxParseString("", NULL, NULL);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
int sl = strlen(macroDef);
|
|
|
|
|
|
|
|
|
|
|
|
if (iMacro)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Echo macro to interpreter, then redirect keys */
|
|
|
|
|
|
|
|
|
|
|
|
if (TxTkConsole)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *outstring = Tcl_Alloc(sl + 20);
|
|
|
|
|
|
sprintf(outstring, ".text insert end \"%s\"",
|
|
|
|
|
|
macroDef);
|
|
|
|
|
|
Tcl_EvalEx(consoleinterp, outstring, -1, 0);
|
|
|
|
|
|
Tcl_Free(outstring);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
TxBuffer = Tcl_Alloc(sl + 1);
|
|
|
|
|
|
strcpy(TxBuffer, macroDef);
|
|
|
|
|
|
TxPrintf("%s", macroDef);
|
|
|
|
|
|
TxFlushOut();
|
|
|
|
|
|
}
|
|
|
|
|
|
TxInputRedirect = TX_INPUT_REDIRECTED;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/* TxParseString is defined by tcltk/tclmagic.c
|
|
|
|
|
|
* and calls Tcl_Eval()
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
TxSetPoint(KeyPressedEvent->x,
|
|
|
|
|
|
grXtransY(mw, KeyPressedEvent->y),
|
|
|
|
|
|
mw->w_wid);
|
|
|
|
|
|
TxParseString(macroDef, NULL, NULL);
|
|
|
|
|
|
}
|
|
|
|
|
|
freeMagic(macroDef);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case ConfigureNotify:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
XConfigureEvent *ConfigureEvent = (XConfigureEvent*) xevent;
|
|
|
|
|
|
Rect screenRect;
|
|
|
|
|
|
int width, height;
|
|
|
|
|
|
bool result, need_resize;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
2017-08-04 20:25:41 +02:00
|
|
|
|
width = ConfigureEvent->width;
|
|
|
|
|
|
height = ConfigureEvent->height;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
screenRect.r_xbot = ConfigureEvent->x;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
screenRect.r_xtop = ConfigureEvent->x + width;
|
|
|
|
|
|
screenRect.r_ytop = glTransYs(ConfigureEvent->y);
|
|
|
|
|
|
screenRect.r_ybot = glTransYs(ConfigureEvent->y + height);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
need_resize = (screenRect.r_xbot != mw->w_screenArea.r_xbot ||
|
2017-08-07 20:17:12 +02:00
|
|
|
|
screenRect.r_xtop != mw->w_screenArea.r_xtop ||
|
|
|
|
|
|
screenRect.r_ybot != mw->w_screenArea.r_ybot ||
|
|
|
|
|
|
screenRect.r_ytop != mw->w_screenArea.r_ytop);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
/* Redraw the window */
|
|
|
|
|
|
|
|
|
|
|
|
WindReframe(mw, &screenRect, FALSE, FALSE);
|
|
|
|
|
|
WindRedisplay(mw);
|
|
|
|
|
|
if (need_resize) (*GrCreateBackingStorePtr)(mw);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case VisibilityNotify:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
XVisibilityEvent *VisEvent = (XVisibilityEvent*) xevent;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
switch (VisEvent->state)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
case VisibilityUnobscured:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
mw->w_flags &= ~WIND_OBSCURED;
|
|
|
|
|
|
if (mw->w_backingStore == (ClientData)NULL)
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
(*GrCreateBackingStorePtr)(mw);
|
|
|
|
|
|
if (mw->w_backingStore != (ClientData)NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
WindAreaChanged(mw, &mw->w_allArea);
|
|
|
|
|
|
WindUpdate();
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
case VisibilityPartiallyObscured:
|
|
|
|
|
|
case VisibilityFullyObscured:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
mw->w_flags |= WIND_OBSCURED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
case Expose:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-04 20:25:41 +02:00
|
|
|
|
XExposeEvent *ExposeEvent = (XExposeEvent*) xevent;
|
|
|
|
|
|
Rect screenRect;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
screenRect.r_xbot = ExposeEvent->x;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
screenRect.r_xtop = ExposeEvent->x + ExposeEvent->width;
|
|
|
|
|
|
screenRect.r_ytop = mw->w_allArea.r_ytop - ExposeEvent->y;
|
|
|
|
|
|
screenRect.r_ybot = mw->w_allArea.r_ytop -
|
|
|
|
|
|
(ExposeEvent->y + ExposeEvent->height);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
if (mw->w_backingStore != (ClientData)NULL)
|
|
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Rect surface;
|
|
|
|
|
|
(*GrGetBackingStorePtr)(mw, &screenRect);
|
|
|
|
|
|
WindScreenToSurface(mw, &screenRect, &surface);
|
|
|
|
|
|
DBWHLRedrawPrepWindow(mw, &surface);
|
|
|
|
|
|
WindDrawBorder(mw, &screenRect);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
2017-08-07 20:17:12 +02:00
|
|
|
|
WindAreaChanged(mw, &screenRect);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
WindUpdate();
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
case MapNotify:
|
|
|
|
|
|
case UnmapNotify:
|
|
|
|
|
|
case DestroyNotify: /* Do nothing */
|
2017-08-07 20:17:12 +02:00
|
|
|
|
break;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
default:
|
2017-08-07 20:17:12 +02:00
|
|
|
|
TxError("Tk Event: Unknown (%d)\n", xevent->type);
|
|
|
|
|
|
TxFlush();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* cairoSetDisplay:
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* This routine sets the appropriate parameters so that
|
|
|
|
|
|
* Magic will work with the X display.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Under Xlib, all input events (mouse and keyboard) are
|
|
|
|
|
|
* sent to one queue which has to be polled to discover
|
|
|
|
|
|
* whether there is any input or not. To fit the Magic
|
|
|
|
|
|
* interrupt-driven input model, a helper process is
|
|
|
|
|
|
* spawned which reads and blocks on the event queue,
|
|
|
|
|
|
* sending SIGIO's to Magic when it detects input. The
|
|
|
|
|
|
* input read in the helper process is then sent to Magic
|
|
|
|
|
|
* via a communication pipe.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results: success / fail
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects: Sets up the pipe.
|
|
|
|
|
|
*---------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2017-08-18 20:15:12 +02:00
|
|
|
|
cairoSetDisplay (dispType, outFileName, mouseFileName)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
char *dispType;
|
|
|
|
|
|
char *outFileName;
|
|
|
|
|
|
char *mouseFileName;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
char *planecount;
|
|
|
|
|
|
char *fullname;
|
|
|
|
|
|
FILE* f;
|
|
|
|
|
|
bool execFailed = FALSE;
|
|
|
|
|
|
int x, y, width, height;
|
|
|
|
|
|
|
|
|
|
|
|
WindPackageType = WIND_X_WINDOWS; /* to be changed? */
|
|
|
|
|
|
TxInputRedirect = TX_INPUT_NORMAL;
|
|
|
|
|
|
|
|
|
|
|
|
grCursorType = "color";
|
|
|
|
|
|
WindScrollBarWidth = 14;
|
|
|
|
|
|
|
|
|
|
|
|
/* Set up the procedure values in the indirection table. */
|
|
|
|
|
|
|
|
|
|
|
|
GrPixelCorrect = 0;
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrLockPtr = GrTCairoLock;
|
|
|
|
|
|
GrUnlockPtr = GrTCairoUnlock;
|
|
|
|
|
|
GrInitPtr = GrTCairoInit;
|
|
|
|
|
|
GrClosePtr = GrTCairoClose;
|
|
|
|
|
|
GrSetCMapPtr = GrTCairoSetCMap;
|
|
|
|
|
|
|
|
|
|
|
|
GrEnableTabletPtr = GrTCairoEnableTablet;
|
|
|
|
|
|
GrDisableTabletPtr = GrTCairoDisableTablet;
|
|
|
|
|
|
GrSetCursorPtr = GrTCairoSetCursor;
|
|
|
|
|
|
GrTextSizePtr = GrTCairoTextSize;
|
|
|
|
|
|
GrDrawGlyphPtr = GrTCairoDrawGlyph;
|
|
|
|
|
|
GrReadPixelPtr = GrTCairoReadPixel;
|
|
|
|
|
|
GrFlushPtr = GrTCairoFlush;
|
|
|
|
|
|
|
|
|
|
|
|
GrCreateWindowPtr = GrTCairoCreate;
|
|
|
|
|
|
GrDeleteWindowPtr = GrTCairoDelete;
|
|
|
|
|
|
GrConfigureWindowPtr = GrTCairoConfigure;
|
|
|
|
|
|
GrOverWindowPtr = GrTCairoRaise;
|
|
|
|
|
|
GrUnderWindowPtr = GrTCairoLower;
|
|
|
|
|
|
GrUpdateIconPtr = GrTCairoIconUpdate;
|
|
|
|
|
|
GrEventPendingPtr = GrTCairoEventPending;
|
|
|
|
|
|
GrWindowIdPtr = GrTCairoWindowId;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
GrWindowNamePtr = GrTkWindowName; /* from grTkCommon.c */
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrGetCursorPosPtr = grtcairoGetCursorPos;
|
|
|
|
|
|
GrGetCursorRootPosPtr = grtcairoGetCursorRootPos;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
/* local indirections */
|
2017-08-18 20:15:12 +02:00
|
|
|
|
grSetSPatternPtr = grtcairoSetSPattern;
|
|
|
|
|
|
grPutTextPtr = grtcairoPutText;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#ifdef VECTOR_FONTS
|
2017-08-18 20:15:12 +02:00
|
|
|
|
grFontTextPtr = grtcairoFontText;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#endif
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grDefineCursorPtr = grTkDefineCursor;
|
|
|
|
|
|
grFreeCursorPtr = grTkFreeCursors;
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrBitBltPtr = GrTCairoBitBlt;
|
|
|
|
|
|
grDrawGridPtr = grtcairoDrawGrid;
|
|
|
|
|
|
grDrawLinePtr = grtcairoDrawLine;
|
|
|
|
|
|
grSetWMandCPtr = grtcairoSetWMandC;
|
|
|
|
|
|
grFillRectPtr = grtcairoFillRect;
|
|
|
|
|
|
grSetStipplePtr = grtcairoSetStipple;
|
|
|
|
|
|
grSetLineStylePtr = grtcairoSetLineStyle;
|
|
|
|
|
|
grSetCharSizePtr = grtcairoSetCharSize;
|
|
|
|
|
|
grFillPolygonPtr = grtcairoFillPolygon;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
#ifdef X11_BACKING_STORE
|
2017-08-07 20:17:12 +02:00
|
|
|
|
GrFreeBackingStorePtr = grtkFreeBackingStore;
|
|
|
|
|
|
GrCreateBackingStorePtr = grtkCreateBackingStore;
|
|
|
|
|
|
GrGetBackingStorePtr = grtkGetBackingStore;
|
|
|
|
|
|
GrPutBackingStorePtr = grtkPutBackingStore;
|
|
|
|
|
|
GrScrollBackingStorePtr = grtkScrollBackingStore;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#else
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrFreeBackingStorePtr = grtcairoFreeBackingStore;
|
|
|
|
|
|
GrCreateBackingStorePtr = grtcairoCreateBackingStore;
|
|
|
|
|
|
GrGetBackingStorePtr = grtcairoGetBackingStore;
|
|
|
|
|
|
GrPutBackingStorePtr = grtcairoPutBackingStore;
|
|
|
|
|
|
GrScrollBackingStorePtr = grtcairoScrollBackingStore;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
#endif
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
if (execFailed) {
|
|
|
|
|
|
TxError("Execution failed!\n");
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
if (!GrTCairoInit()) {
|
2017-08-07 20:17:12 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Tk_GetVRootGeometry(Tk_MainWindow(magicinterp), &x, &y, &width, &height);
|
|
|
|
|
|
GrScreenRect.r_xbot = x;
|
|
|
|
|
|
GrScreenRect.r_ybot = y;
|
|
|
|
|
|
GrScreenRect.r_xtop = width + x;
|
|
|
|
|
|
GrScreenRect.r_ytop = height + y;
|
|
|
|
|
|
|
|
|
|
|
|
return Tk_MainWindow(magicinterp) ? TRUE : FALSE;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern void MakeWindowCommand();
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoCreate --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Create a new window under the X window system.
|
|
|
|
|
|
* Bind X window to Magic Window w.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* Success/Fail
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window created, window ID send to Xhelper.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoCreate(w, name)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
|
|
|
|
|
char *name;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window tkwind, tktop;
|
|
|
|
|
|
Window wind;
|
|
|
|
|
|
static int WindowNumber = 0;
|
|
|
|
|
|
HashEntry *entry;
|
|
|
|
|
|
char *windowplace;
|
|
|
|
|
|
char windowname[10];
|
|
|
|
|
|
int x = w->w_frameArea.r_xbot;
|
|
|
|
|
|
int y = glTransYs(w->w_frameArea.r_ytop);
|
|
|
|
|
|
int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot;
|
|
|
|
|
|
int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot;
|
|
|
|
|
|
unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap;
|
|
|
|
|
|
XSetWindowAttributes grAttributes;
|
|
|
|
|
|
|
|
|
|
|
|
WindSeparateRedisplay(w);
|
|
|
|
|
|
|
|
|
|
|
|
sprintf(windowname, ".magic%d", WindowNumber + 1);
|
|
|
|
|
|
if (windowplace = XGetDefault(grXdpy, "magic", windowname))
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
XParseGeometry(windowplace, &x, &y,
|
|
|
|
|
|
(unsigned int *)&width, (unsigned int *)&height);
|
|
|
|
|
|
w->w_frameArea.r_xbot = x;
|
|
|
|
|
|
w->w_frameArea.r_xtop = x + width;
|
|
|
|
|
|
w->w_frameArea.r_ytop = glTransYs(y);
|
|
|
|
|
|
w->w_frameArea.r_ybot = glTransYs(y + height);
|
|
|
|
|
|
WindReframe(w, &(w->w_frameArea), FALSE, FALSE);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grAttributes.colormap = XCreateColormap(grXdpy, RootWindow(grXdpy, grXscrn),
|
|
|
|
|
|
grVisualInfo->visual, AllocNone);
|
|
|
|
|
|
grAttributes.background_pixel = WhitePixel(grXdpy, grXscrn);
|
|
|
|
|
|
grAttributes.border_pixel = BlackPixel(grXdpy, grXscrn);
|
|
|
|
|
|
|
|
|
|
|
|
if (tktop = Tk_MainWindow(magicinterp))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!WindowNumber)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* To do: deal with grVisualInfo---destroy and recreate top */
|
|
|
|
|
|
/* frame if necessary */
|
|
|
|
|
|
|
|
|
|
|
|
if (Tk_WindowId(tktop) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Tk_SetWindowVisual(tktop, grVisualInfo->visual,
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.depth, grAttributes.colormap);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/* The Top-level window has already been mapped. We can't mess */
|
|
|
|
|
|
/* with it's visual. If the title is "wish", we'll assume that */
|
|
|
|
|
|
/* nobody else is claiming it, and unmap it. */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (!strcmp(Tk_Name(tktop), "wish")) Tk_UnmapWindow(tktop);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return 0; /* failure */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* Last parameter "" indicates a top-level window in the space of */
|
|
|
|
|
|
/* the parent. */
|
|
|
|
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
|
tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, windowname, "");
|
|
|
|
|
|
else
|
|
|
|
|
|
tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, name, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
/* TxError("Creating window named \"%s\", tkwind = 0x%x\n",
|
2017-08-04 20:25:41 +02:00
|
|
|
|
windowname, tkwind); TxFlush(); */
|
|
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (tkwind != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool result;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoFlush();
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.window = tkwind;
|
|
|
|
|
|
tcairoCurrent.mw = w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
w->w_grdata = (ClientData) tkwind;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashFind(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
HashSetValue(entry, w);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* ensure that the visual is what we wanted, if possible to change */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
Tk_SetWindowVisual(tkwind, grVisualInfo->visual, tcairoCurrent.depth,
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grAttributes.colormap);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* map the window, if necessary */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_MapWindow(tkwind);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* use x, y, width, height to size and position the window */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_GeometryRequest(tkwind, width, height);
|
|
|
|
|
|
/* Tk_MoveResizeWindow(tkwind, x, y, width, height); */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
wind = Tk_WindowId(tkwind);
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.windowid = wind;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
//glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext);
|
|
|
|
|
|
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
Tk_DefineCursor(tkwind, tcairoCurrent.cursor);
|
|
|
|
|
|
GrTCairoIconUpdate(w, w->w_caption);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
WindowNumber++;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* execute all Tk events up to current */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* set up Tk event handler to start processing */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_CreateEventHandler(tkwind, ExposureMask | StructureNotifyMask
|
|
|
|
|
|
| ButtonPressMask | KeyPressMask | VisibilityChangeMask,
|
2017-08-18 20:15:12 +02:00
|
|
|
|
(Tk_EventProc *)TCairoEventProc, (ClientData) tkwind);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/* set up commands to be passed expressly to this window */
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MakeWindowCommand((name == NULL) ? windowname : name, w);
|
|
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
return (WindowNumber == 1) ? grtcairoLoadFont() : 1;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
TxError("Could not open new Tk window\n");
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
return 0;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoDelete --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Destroy a Tk/OpenGL window.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window destroyed.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoDelete(w)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window xw;
|
|
|
|
|
|
HashEntry *entry;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
xw = (Tk_Window) w->w_grdata;
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)xw);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
HashSetValue(entry, NULL);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tcl_DeleteCommand(magicinterp, Tk_PathName(xw));
|
|
|
|
|
|
Tk_DestroyWindow(xw);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoConfigure --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Resize/ Move an existing X window.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window reconfigured to w->w_frameArea.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoConfigure(w)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (w->w_flags & WIND_OFFSCREEN) return;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_MoveResizeWindow((Tk_Window)w->w_grdata,
|
|
|
|
|
|
w->w_frameArea.r_xbot, glTransYs(w->w_frameArea.r_ytop),
|
|
|
|
|
|
w->w_frameArea.r_xtop - w->w_frameArea.r_xbot,
|
|
|
|
|
|
w->w_frameArea.r_ytop - w->w_frameArea.r_ybot);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoRaise --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Raise a window to the top of the screen such that nothing
|
|
|
|
|
|
* obscures it.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window raised.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoRaise(w)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window tkwind;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (w->w_flags & WIND_OFFSCREEN) return;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
tkwind = (Tk_Window)w->w_grdata;
|
|
|
|
|
|
Tk_RestackWindow(tkwind, Above, NULL);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoLower --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Lower a window below all other Tk windows.
|
|
|
|
|
|
* obscures it.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window lowered.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoLower(w)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window tkwind;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (w->w_flags & WIND_OFFSCREEN) return;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
tkwind = (Tk_Window)w->w_grdata;
|
|
|
|
|
|
Tk_RestackWindow(tkwind, Below, NULL);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoLock --
|
|
|
|
|
|
* Lock a window and set global variables "tcairoCurrent.window"
|
|
|
|
|
|
* and "tcairoCurrent.mw" to reference the locked window.
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window locked.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoLock(w, flag)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
|
|
|
|
|
bool flag;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Window wind;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grSimpleLock(w, flag);
|
|
|
|
|
|
if ( w != GR_LOCK_SCREEN )
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.mw = w;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
|
|
|
|
|
|
if (w->w_flags & WIND_OFFSCREEN)
|
|
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.window = (Tk_Window) NULL;
|
|
|
|
|
|
tcairoCurrent.windowid = (Pixmap) w->w_grdata;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoCurrent.window = (Tk_Window) w->w_grdata;
|
|
|
|
|
|
tcairoCurrent.windowid = Tk_WindowId(tcairoCurrent.window);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
2017-08-18 20:15:12 +02:00
|
|
|
|
tcairoSetProjection(w->w_allArea.r_xbot, w->w_allArea.r_ybot,
|
2017-08-30 22:34:42 +02:00
|
|
|
|
w->w_allArea.r_xtop - w->w_allArea.r_xbot,
|
|
|
|
|
|
w->w_allArea.r_ytop - w->w_allArea.r_ybot);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoUnlock --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Unlock a window, flushing stuff out to the display.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects:
|
|
|
|
|
|
* Window unlocked.
|
|
|
|
|
|
* Display update.
|
|
|
|
|
|
*
|
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoUnlock(w)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
/* GR_TCairo_FLUSH_BATCH(); */
|
|
|
|
|
|
GrTCairoFlush(); /* (?) Adds glFlush and glFinish to the above. */
|
2017-08-07 20:17:12 +02:00
|
|
|
|
grSimpleUnlock(w);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-07 20:17:12 +02:00
|
|
|
|
/*
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*-------------------------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoEventPending --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* check for pending graphics events.
|
|
|
|
|
|
* Here we use the X11 check for window events, because Tcl/Tk doesn't
|
|
|
|
|
|
* allows peeking into its event queue without executing whatever is
|
|
|
|
|
|
* in the queue.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* TRUE if an event is waiting in the event queue.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* None, hopefully (put back the event!)
|
|
|
|
|
|
*
|
|
|
|
|
|
*-------------------------------------------------------------------------
|
2017-08-07 20:17:12 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
2017-08-04 20:25:41 +02:00
|
|
|
|
bool
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoEventPending()
|
2017-08-07 20:17:12 +02:00
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
Window wind = tcairoCurrent.windowid;
|
2017-08-07 20:17:12 +02:00
|
|
|
|
XEvent genEvent;
|
|
|
|
|
|
bool retval;
|
|
|
|
|
|
|
|
|
|
|
|
XSync(grXdpy, FALSE); /* Necessary, or it won't catch mouse/key events */
|
|
|
|
|
|
retval = XCheckWindowEvent(grXdpy, wind, ExposureMask
|
|
|
|
|
|
| StructureNotifyMask | ButtonPressMask
|
|
|
|
|
|
| KeyPressMask, &genEvent);
|
|
|
|
|
|
if (retval) XPutBackEvent(grXdpy, &genEvent);
|
|
|
|
|
|
return retval;
|
|
|
|
|
|
}
|
2017-08-04 20:25:41 +02:00
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
|
*
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoIconUpdate -- updates the icon text with the window script
|
2017-08-04 20:25:41 +02:00
|
|
|
|
*
|
|
|
|
|
|
* Results: none
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side Effects: changes the icon text
|
|
|
|
|
|
*
|
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoIconUpdate(w, text) /* See Blt code */
|
2017-08-07 20:17:12 +02:00
|
|
|
|
MagWindow *w;
|
|
|
|
|
|
char *text;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window tkwind;
|
|
|
|
|
|
Window wind;
|
|
|
|
|
|
XClassHint class;
|
|
|
|
|
|
char *brack;
|
|
|
|
|
|
|
|
|
|
|
|
if (w->w_flags & WIND_OFFSCREEN) return;
|
|
|
|
|
|
|
|
|
|
|
|
tkwind = (Tk_Window)(w->w_grdata);
|
|
|
|
|
|
if (tkwind == NULL) {
|
|
|
|
|
|
tkwind = Tk_MainWindow(magicinterp);
|
|
|
|
|
|
if (tkwind == NULL) return;
|
|
|
|
|
|
}
|
|
|
|
|
|
wind = Tk_WindowId(tkwind);
|
|
|
|
|
|
if (wind == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
class.res_name = "magic";
|
|
|
|
|
|
class.res_class = "magic";
|
|
|
|
|
|
|
|
|
|
|
|
XSetClassHint( grXdpy, wind, &class);
|
|
|
|
|
|
if (text)
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
if (brack = strchr(text, '['))
|
|
|
|
|
|
{
|
|
|
|
|
|
brack--;
|
|
|
|
|
|
*brack = 0;
|
|
|
|
|
|
XSetIconName(grXdpy, wind, text);
|
|
|
|
|
|
XStoreName(grXdpy, wind, text);
|
|
|
|
|
|
*brack = ' ';
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (brack = strrchr(text, ' ')) text = brack + 1;
|
|
|
|
|
|
XSetIconName(grXdpy, wind, text);
|
|
|
|
|
|
XStoreName(grXdpy, wind, text);
|
2017-08-04 20:25:41 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*-------------------------------------------------------------------------
|
2017-08-18 20:15:12 +02:00
|
|
|
|
* GrTCairoWindowId --
|
2017-08-04 20:25:41 +02:00
|
|
|
|
* Get magic's ID number from the indicated MagWindow structure
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* The window ID number.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2017-08-18 20:15:12 +02:00
|
|
|
|
GrTCairoWindowId(tkname)
|
2017-08-07 20:17:12 +02:00
|
|
|
|
char *tkname;
|
2017-08-04 20:25:41 +02:00
|
|
|
|
{
|
2017-08-07 20:17:12 +02:00
|
|
|
|
Tk_Window tkwind;
|
|
|
|
|
|
MagWindow *mw;
|
|
|
|
|
|
HashEntry *entry;
|
|
|
|
|
|
int id = 0;
|
|
|
|
|
|
|
|
|
|
|
|
tkwind = Tk_NameToWindow(magicinterp, tkname, Tk_MainWindow(magicinterp));
|
|
|
|
|
|
if (tkwind != NULL)
|
|
|
|
|
|
{
|
2017-08-18 20:15:12 +02:00
|
|
|
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)tkwind);
|
2017-08-07 20:17:12 +02:00
|
|
|
|
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
|
2017-08-30 22:34:42 +02:00
|
|
|
|
if (mw) {
|
|
|
|
|
|
id = mw->w_wid;
|
|
|
|
|
|
}
|
2017-08-07 20:17:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
return id;
|
|
|
|
|
|
}
|