summaryrefslogtreecommitdiff
path: root/zwgc
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@mit.edu>2009-03-16 03:15:21 +0000
committerGravatar Karl Ramm <kcr@mit.edu>2009-03-16 03:15:21 +0000
commit8344e6875d8492ee532b3316e970ad79d2a9d5c1 (patch)
tree7af6a0c1c45932f0b7a5f59cecf236efdf95e068 /zwgc
parent9e44e5ff31421c5ecc4d0c28d98e985b84360669 (diff)
more cmu stuff
Diffstat (limited to 'zwgc')
-rw-r--r--zwgc/plus.c520
-rw-r--r--zwgc/plus.h26
2 files changed, 546 insertions, 0 deletions
diff --git a/zwgc/plus.c b/zwgc/plus.c
new file mode 100644
index 0000000..9f445e0
--- /dev/null
+++ b/zwgc/plus.c
@@ -0,0 +1,520 @@
+/*
+ This file contains code related to the zwgcplus extension to zwgc.
+ zwgc is copyrighted by the Massachusetts Institute of Technology.
+ This file is public domain.
+ Written by Andrew Plotkin, ap1i+@andrew.cmu.edu
+ Timequeue code added by Ryan Ingram, ryani+@andrew.cmu.edu
+ Rewritten for incorporation into MIT zwgc from 2.0.2 by Derrick Brashear
+ */
+
+#include <sysdep.h>
+#ifdef CMU_ZWGCPLUS
+#if (!defined(lint) && !defined(SABER))
+static char rcsid_plus_c[] = "$Id$";
+#endif
+
+#include <zephyr/mit-copyright.h>
+#include <zephyr/zephyr.h>
+
+#include "new_memory.h"
+#include "node.h"
+#include "exec.h"
+#include "eval.h"
+#include "node.h"
+#include "buffer.h"
+#include "port.h"
+#include "variables.h"
+#include "notice.h"
+#include "X_gram.h"
+#include "xrevstack.h"
+#include "plus.h"
+
+int get_full_names = 0;
+
+#define HASHSIZE (251)
+
+typedef struct timenode_s {
+ ZNotice_t *notice;
+ struct timenode_s *next;
+ time_t when;
+ char *event_name;
+} TimeNode;
+
+typedef struct _notnode {
+ ZNotice_t *notice;
+ int fake_notice; /* if TRUE, do not call ZFreeNotice() */
+ int refcount;
+ struct _notnode *next;
+ char *opcode;
+ char *hname;
+} notnode;
+
+static ZNotice_t *stored_notice;
+static notnode *notlist[HASHSIZE];
+TimeNode *timeq_head = NULL;
+
+TimeNode
+*addtimenode(head, node)
+ TimeNode *head;
+ TimeNode *node;
+{
+ if(head == NULL) {
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "adding new timenode; creating queue\n");
+#endif
+ node->next = NULL;
+ return node;
+ }
+
+ if(head->when > node->when) {
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "adding new timenode at start of queue\n");
+#endif
+ node->next = head;
+ return node;
+ }
+
+ head->next = addtimenode(head->next, node);
+ return head;
+}
+
+void
+handle_timeq_event(event)
+ TimeNode *event;
+{
+ char *tmp;
+
+ char buf[128];
+ notnode *pt;
+ int bx = list_hash_fun(event->notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=event->notice; pt=pt->next);
+
+ /* "time-" + event_name + '\0' */
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "handle_timeq_event()\n");
+#endif
+
+ if (strlen(event->event_name)<123)
+ sprintf(buf, "time-%s", event->event_name);
+ else
+ sprintf(buf, "time-bogus");
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "opcode: %s\n", buf);
+#endif
+
+ event->notice->z_version = "zwgcplus-repeat";
+ event->notice->z_opcode = buf;
+
+ reprocess_notice(event->notice, pt->hname);
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "end handle_timeq_event()\n");
+#endif
+}
+
+void
+schedule_event(secs, name, notice)
+ long secs;
+ char *name;
+ ZNotice_t *notice;
+{
+ time_t eventtime = (time(NULL)) + secs;
+ TimeNode *newnode;
+ char *buf;
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "schedule_event(%ld, %ld, %s)\n", eventtime, secs, name);
+#endif
+
+ if(!notice || !name) return;
+
+ list_add_notice(notice);
+
+ newnode = (TimeNode *)malloc(sizeof(TimeNode));
+ buf = (char *)malloc(strlen(name) + 1);
+
+ strcpy(buf, name);
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "name: %s\n", buf);
+#endif
+
+ newnode->when = eventtime;
+ newnode->event_name = buf;
+ newnode->notice = notice;
+
+ timeq_head = addtimenode(timeq_head, newnode);
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "end schedule_event()\n");
+#endif
+}
+
+void
+free_timenode(node)
+ TimeNode *node;
+{
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "free_timenode(%s)\n", node->event_name);
+#endif
+
+ free(node->event_name);
+ free(node);
+}
+
+/* returns the number of notices destroyed */
+int
+destroy_timeq_notice(notice, name)
+ ZNotice_t *notice;
+ char *name;
+{
+ TimeNode *curr = timeq_head;
+ TimeNode *prev = NULL;
+ TimeNode *tmp;
+
+ int ct = 0;
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "destroy_timeq_notice(%s)\n", name);
+#endif
+
+ while(curr != NULL) {
+ if(curr->notice == notice &&
+ (!name || !strcmp(curr->event_name, name)))
+ {
+ ct++;
+ if(!prev) {
+ timeq_head = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ tmp = curr;
+ curr = curr->next;
+ free_timenode(tmp);
+ } else {
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+
+ return ct;
+}
+
+long
+plus_timequeue_events()
+{
+ /* returns number of seconds to the next event or 0L */
+ /* if there are no events remaining to be processed */
+
+ time_t timenow = time(NULL);
+ TimeNode *curr;
+
+ while(timeq_head != NULL && timeq_head->when <= timenow) {
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "handling event\n");
+#endif
+ handle_timeq_event(timeq_head);
+ curr = timeq_head;
+ timeq_head = timeq_head->next;
+ free_timenode(curr);
+ }
+
+#ifdef DEBUG_TIMEQUEUE
+ if(timeq_head != NULL)
+ fprintf(stderr, "next event in %ld seconds.\n",
+ (timeq_head->when) - timenow);
+#endif
+
+ return ((timeq_head == NULL) ? 0L : ((timeq_head->when) - timenow));
+}
+
+void
+plus_set_hname(notice, hname)
+ ZNotice_t *notice;
+ char *hname;
+{
+ notnode *pt;
+ int bx;
+
+ if (hname) {
+ bx = list_hash_fun(notice);
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+ pt->hname=(char *)malloc(strlen(hname)+1);
+ strcpy(pt->hname, hname);
+ }
+ return;
+}
+
+void
+plus_queue_notice(notice)
+ ZNotice_t *notice;
+{
+ char *val;
+ int howlong = 0;
+
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "plus_queue_notice()\n");
+#endif
+
+ val = var_get_variable("event_time");
+ if(val) {
+ if(strcmp(val, "kill")) {
+ howlong = atoi(val);
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "$event_time %d\n", howlong);
+#endif
+ } else {
+ val = var_get_variable("event_name");
+ if(!val || strcmp(val, "all"))
+ destroy_timeq_notice(notice, (val && val[0]) ? val : "event");
+ else
+ destroy_timeq_notice(notice, (char *)NULL);
+ }
+ }
+
+ if(howlong > 0) {
+ val = var_get_variable("event_name");
+#ifdef DEBUG_TIMEQUEUE
+ fprintf(stderr, "$event_name = %s\n", val);
+#endif
+ schedule_event(howlong, (val && val[0]) ? val : "event", notice);
+ }
+}
+
+int
+list_hash_fun(notice)
+ ZNotice_t *notice;
+{
+ int ix;
+ int res = 0, val = 1, ptval;
+ char *pt = (char *)(notice);
+
+ for (ix=0; ix<sizeof(ZNotice_t *); ix++) {
+ ptval = (int)pt[ix];
+ if (ptval<0) ptval = (-ptval);
+ res += val * ptval;
+ res %= HASHSIZE;
+ val *= 7;
+ };
+
+ return res;
+}
+
+/* initialize hash table */
+void
+init_noticelist()
+{
+ int ix;
+
+ stored_notice = NULL;
+
+ for (ix=0; ix<HASHSIZE; ix++) {
+ notlist[ix] = NULL;
+ }
+}
+
+void
+dump_noticelist()
+{
+ notnode *pt;
+ int bx;
+
+ for (bx=0; bx<HASHSIZE; bx++) {
+ for (pt=notlist[bx]; pt; pt=pt->next) {
+ fprintf(stderr, "Not %p: %d [%d]\n", pt->notice, pt->refcount, bx);
+ }
+ }
+}
+
+/* add notice to table. Either generate a new entry, or increment ref count. */
+void
+list_add_notice(notice)
+ ZNotice_t *notice;
+{
+ notnode *pt;
+ int bx = list_hash_fun(notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (pt) {
+ /* found entry */
+ pt->refcount++;
+ }
+ else {
+ /* no entry */
+ pt = (notnode *)malloc(sizeof(notnode));
+ pt->notice = notice;
+ pt->refcount = 0;
+ pt->fake_notice = 0;
+ pt->next = notlist[bx];
+ pt->opcode = notice->z_opcode;
+ pt->hname = NULL;
+ notlist[bx] = pt;
+ }
+
+ /*fprintf(stderr, "list_add_notice(%p)\n", notice);
+ dump_noticelist();*/
+}
+
+/* remove notice from table. If refcount reaches 0, return 1; if refcount is
+ still positive, return 0; if notice not there, return -1. */
+int
+list_del_notice(notice)
+ ZNotice_t *notice;
+{
+ notnode *pt, **ppt;
+ int bx = list_hash_fun(notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (!pt) {
+ /* no entry */
+ /*fprintf(stderr, "list_del_notice(%p): ERROR\n", notice);
+ dump_noticelist();*/
+ return (-1);
+ }
+
+ pt->refcount--;
+ if (pt->refcount > 0) {
+ /*fprintf(stderr, "list_del_notice(%p): count %d\n", notice, pt->refcount);
+ dump_noticelist();*/
+ return 0;
+ }
+
+ for (ppt = &(notlist[bx]); (*ppt)!=pt; ppt = &((*ppt)->next));
+
+ *ppt = (*ppt)->next;
+
+ if (!pt->fake_notice)
+ ZFreeNotice(pt->notice);
+ if (pt->hname)
+ free(pt->hname);
+ free(pt->notice);
+ free(pt);
+
+ /*fprintf(stderr, "list_del_notice(%p): count 0, gone\n", notice);*/
+ /*dump_noticelist();*/
+ return 1;
+}
+
+void
+set_notice_fake(notice, val)
+ ZNotice_t *notice;
+ int val;
+{
+ notnode *pt;
+ int bx = list_hash_fun(notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (pt) {
+ pt->fake_notice = val;
+ }
+}
+
+int
+get_notice_fake(notice)
+ ZNotice_t *notice;
+{
+ notnode *pt;
+ int bx = list_hash_fun(notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (pt) {
+ return pt->fake_notice;
+ }
+ else
+ return 0;
+}
+
+int
+get_list_refcount(notice)
+ ZNotice_t *notice;
+{
+ notnode *pt;
+ int bx = list_hash_fun(notice);
+
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (pt) {
+ /*fprintf(stderr, "get_list_refcount(%p): count %d\n", notice, pt->refcount);*/
+ return pt->refcount;
+ }
+ else {
+ /*fprintf(stderr, "get_list_refcount(%p): count 0\n", notice);*/
+ return 0;
+ }
+}
+
+/* export a reference to the current notice. */
+char
+*get_stored_notice()
+{
+ if (!stored_notice)
+ return NULL;
+
+ list_add_notice(stored_notice);
+
+ return (char *)stored_notice;
+}
+
+void
+set_stored_notice(notice)
+ ZNotice_t *notice;
+{
+ stored_notice = notice;
+}
+
+void
+plus_retry_notice(notice, ch, metaflag)
+ ZNotice_t *notice;
+ char ch;
+ int metaflag;
+{
+ char buf[128];
+ char *tmp;
+ notnode *pt;
+ int bx;
+
+ if (!notice)
+ return;
+
+ bx = list_hash_fun(notice);
+ for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
+
+ if (metaflag) tmp = "-meta";
+ else tmp = "";
+
+ if (ch==' ')
+ sprintf(buf, "key%s-space", tmp);
+ else if (ch==127)
+ sprintf(buf, "key%s-delete", tmp);
+ else if (ch==0)
+ sprintf(buf, "key%s-ctrl-@", tmp);
+ else if (ch==27)
+ sprintf(buf, "key%s-esc", tmp);
+ else if (isprint(ch))
+ sprintf(buf, "key%s-%c", tmp, ch);
+ else if (ch>=1 && ch<=26)
+ sprintf(buf, "key%s-ctrl-%c", tmp, ch+'a'-1);
+ else if (iscntrl(ch))
+ sprintf(buf, "key%s-ctrl-%c", tmp, ch+'A'-1);
+ else
+ sprintf(buf, "key%s-unknown", tmp);
+
+ /* concat the old opcode if they're running in "new" mode */
+ if (zwgcplus == 2 && pt && pt->opcode[0] &&
+ strcmp(pt->opcode, "") != 0)
+ {
+ strcat(buf, " ");
+ strncat(buf, pt->opcode, sizeof(buf)-strlen(buf));
+ }
+
+ notice->z_version = "zwgcplus-repeat";
+ notice->z_opcode = buf;
+
+ reprocess_notice(notice, NULL);
+}
+#endif /* CMU_ZWGCPLUS */
diff --git a/zwgc/plus.h b/zwgc/plus.h
new file mode 100644
index 0000000..2347174
--- /dev/null
+++ b/zwgc/plus.h
@@ -0,0 +1,26 @@
+/*
+ This file contains code related to the zwgcplus extension to zwgc.
+ zwgc is copyrighted by the Massachusetts Institute of Technology.
+ This file is public domain.
+ Written by Andrew Plotkin, ap1i+@andrew.cmu.edu
+ */
+
+#define NAMESIZE (256)
+
+extern int get_full_names;
+extern int zwgcplus;
+
+extern void init_noticelist();
+extern void dump_noticelist();
+extern void list_add_notice();
+extern int list_del_notice();
+extern int get_list_refcount();
+extern void set_notice_fake();
+extern int get_notice_fake();
+extern char *get_stored_notice();
+extern void plus_retry_notice();
+extern void set_stored_notice();
+extern void plus_window_deletions();
+
+extern void plus_queue_notice();
+extern long plus_timequeue_events();