#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/poll.h>
#include "mgraph.h"
static FILE *input_f;
static struct stat input_stab;
static const char *input_filename;
+static int pause_updates;
+
+#define TITLE_MAX 100
+static char title[TITLE_MAX+1];
static void read_input(void) {
- int r;
+ int r, last_readlink_r, last_readlink_errno=0;
+ char symlink_check[sizeof(title)];
+
+ last_readlink_r= -2;
- if (input_f) fclose(input_f);
- input_f= fopen(input_filename, "rb"); if (!input_f) diee("input file");
+ for (;;) {
+ r= readlink(input_filename, symlink_check, TITLE_MAX);
+ assert(r<=TITLE_MAX);
+ assert(r!=-2);
+
+ if (r>=0) symlink_check[r]= 0;
+ else symlink_check[0]= 0;
+
+ if (r == last_readlink_r &&
+ (r<0
+ ? (errno==last_readlink_errno)
+ : !strcmp(symlink_check, title))) {
+ assert(input_f);
+ if (r<0) {
+ if (last_readlink_errno==EINVAL)
+ snprintf(title,sizeof(title),"%s",input_filename);
+ else
+ snprintf(title,sizeof(title),"? %s",strerror(last_readlink_errno));
+ }
+ break;
+ }
+
+ strcpy(title, symlink_check);
+ last_readlink_r= r;
+ last_readlink_errno= errno;
+
+ if (input_f) fclose(input_f);
+ input_f= fopen(input_filename, "rb"); if (!input_f) diee("input file");
+ }
if (fstat(fileno(input_f), &input_stab)) diee("fstat input file");
int v, k;
- FOR_VERTEX(v) {
+ FOR_VERTEX(v,INNER) {
input_gsl.data= &conformation[v][0];
GA( gsl_blas_dgemv(CblasNoTrans, 1.0,&transform_gsl, &input_gsl,
0.0, &result_gsl) );
int vb, ve[V6], e;
ntris= 0;
- FOR_VERTEX(vb) {
+ FOR_VERTEX(vb,INNER) {
/* We use the two triangles in the parallelogram vb, vb+e5, vb+e0, vb+e1.
* We go round each triangle clockwise (although our surface is non-
* orientable so it shouldn't matter). Picking the parallelogram
if (!vertex_in_triangles_checked) {
int v, expd;
- FOR_VERTEX(v) {
+ FOR_VERTEX(v,INNER) {
expd= RIM_VERTEX_P(v) ? 3 : 6;
if (vertex_in_triangles[v] != expd) {
fprintf(stderr,"vertex %02x used for %d triangles, expected %d\n",
static const unsigned long core_event_mask=
ButtonPressMask|ButtonReleaseMask|StructureNotifyMask|ButtonMotionMask|
- KeyPressMask;
+ KeyPressMask|SubstructureNotifyMask;
static void mkpixmaps(void) {
for (currentbuffer=0; currentbuffer<2; currentbuffer++) {
drawtriangles(&dmwhite);
printf("shown, %d/%d triangles cut\n", ncut, ntris);
}
-
+
+ XA( XStoreName(display,window,title) );
XA( XSetWindowBackgroundPixmap(display,window,pixmap) );
XA( XClearWindow(display,window) );
currentbuffer= !currentbuffer;
rotz[0][0]= cz; rotz[0][1]= sz; rotz[0][2]= 0;
rotz[1][0]= -sz; rotz[1][1]= cz; rotz[1][2]= 0;
rotz[2][0]= 0; rotz[2][1]= 0; rotz[2][2]= 1;
-}
+}
static void drag_rotate_delta(double dx, double dy) {
/* We multiple our transformation matrix by a matrix:
drag_position(x,y);
}
+static void transform_preset_record(const char *fn, const char *fn_new) {
+ FILE *f;
+ f= fopen(fn_new,"wb");
+ if (!f) diee("open new transform");
+ if (fwrite(transform,sizeof(transform),1,f) != 1) diee("write transform");
+ if (fclose(f)) diee("fclose new transform");
+ if (rename(fn_new,fn)) diee("install transform");
+}
+
+static void transform_preset_playback(const char *fn) {
+ FILE *f;
+ f= fopen(fn,"rb");
+ if (!f && errno==ENOENT) {
+ fprintf(stderr,"no preset %s\n",fn);
+ XBell(display,100);
+ return;
+ }
+ errno= 0;
+ if (fread(transform,sizeof(transform),1,f) != 1) {
+ perror("read preset!");
+ XBell(display,100);
+ return;
+ }
+ fclose(f);
+ show();
+}
+
static void event_key(XKeyEvent *e) {
KeySym ks;
- char buf[10];
- int r;
+ XKeyEvent e_nomod;
+ char buf[10], buf_nomod[10];
+ int r, r_nomod;
r= XLookupString(e,buf,sizeof(buf)-1,&ks,0);
if (!r) {
return;
}
- if (!strcmp(buf,"q")) exit(0);
- if (!strcmp(buf,"w")) {
+ if (!strcmp(buf,"q"))
+ exit(0);
+ else if (!strcmp(buf,"p"))
+ pause_updates= !pause_updates;
+ else if (!strcmp(buf,"w")) {
wireframe= !wireframe;
show();
return;
- }
- if (!strcmp(buf,"d")) {
+ } else if (!strcmp(buf,"d")) {
eyes_apart= eyes_apart>0 ? eyes_apart_min : eyes_apart_preferred;
show();
return;
}
+
+ e_nomod= *e;
+ e_nomod.state= 0;
+ buf_nomod[0]= 0;
+ r_nomod= XLookupString(&e_nomod,buf_nomod,sizeof(buf_nomod)-1,&ks,0);
+ if (r_nomod && !buf_nomod[1] && buf_nomod[0]>='0' && buf_nomod[0]<='9') {
+ char filename[20], filename_new[25];
+ snprintf(filename,sizeof(filename)-1,".view-preset-%s",buf_nomod);
+ snprintf(filename_new,sizeof(filename_new)-1,"%s.new",filename);
+ printf("transform preset %d %s\n", e->state, filename);
+ if (e->state) transform_preset_record(filename,filename_new);
+ else transform_preset_playback(filename);
+ return;
+ }
+
+ printf("unknown key keycode=%d state=0x%x char=%c 0x%02x "
+ "[rnm=%d bnm[0,1]=0x%02x,%02x]\n",
+ e->keycode, e->state, buf[0]>' ' && buf[0]<127 ? buf[0] : '?',
+ buf[0], r_nomod, buf_nomod[0], buf_nomod[1]);
+ printf("%d %d %d %d\n",
+ r_nomod,
+ !buf_nomod[1],
+ buf_nomod[0]>='0',
+ buf_nomod[0]<='9');
}
static void event_config(XConfigureEvent *e) {
static void topocheck(void) {
int v1,e,v2,eprime,v1prime, count;
- FOR_EDGE(v1,e,v2) {
+ FOR_EDGE(v1,e,v2, INNER) {
count= 0;
FOR_VEDGE(v2,eprime,v1prime)
if (v1prime==v1) count++;
struct pollfd *polls=0;
int motion_deferred=0, motion_x=-1, motion_y=-1;
+ mgraph_prepare();
topocheck();
if (argc==1) { printf("topology self-consistent, ok\n"); exit(0); }
polls[i].fd= ConnectionNumber(display);
polls[i].events= wantedevents;
- r= poll(polls, nxfds+1, motion_deferred ? 0 : 200);
+ r= poll(polls, nxfds+1, motion_deferred ? 0 : pause_updates ? -1 : 200);
if (r<0) {
if (errno==EINTR) continue;
diee("poll");
event_motion(motion_x, motion_y);
motion_deferred=0;
}
- check_input();
+ if (!pause_updates)
+ check_input();
continue;
}