2 This file contains code related to the zwgcplus extension to zwgc.
3 zwgc is copyrighted by the Massachusetts Institute of Technology.
4 This file is public domain.
5 Written by Andrew Plotkin, ap1i+@andrew.cmu.edu
6 Timequeue code added by Ryan Ingram, ryani+@andrew.cmu.edu
7 Rewritten for incorporation into MIT zwgc from 2.0.2 by Derrick Brashear
12 #if (!defined(lint) && !defined(SABER))
13 static char rcsid_plus_c[] = "$Id: plus.c,v 1.7 1998/08/10 22:54:11 shadow Exp $";
16 #include <zephyr/mit-copyright.h>
17 #include <zephyr/zephyr.h>
19 #include "new_memory.h"
26 #include "variables.h"
29 #include "xrevstack.h"
32 int get_full_names = 0;
34 #define HASHSIZE (251)
36 typedef struct timenode_s {
38 struct timenode_s *next;
43 typedef struct _notnode {
45 int fake_notice; /* if TRUE, do not call ZFreeNotice() */
47 struct _notnode *next;
52 static ZNotice_t *stored_notice;
53 static notnode *notlist[HASHSIZE];
54 TimeNode *timeq_head = NULL;
57 *addtimenode(head, node)
62 #ifdef DEBUG_TIMEQUEUE
63 fprintf(stderr, "adding new timenode; creating queue\n");
69 if(head->when > node->when) {
70 #ifdef DEBUG_TIMEQUEUE
71 fprintf(stderr, "adding new timenode at start of queue\n");
77 head->next = addtimenode(head->next, node);
82 handle_timeq_event(event)
89 int bx = list_hash_fun(event->notice);
91 for (pt=notlist[bx]; pt && pt->notice!=event->notice; pt=pt->next);
93 /* "time-" + event_name + '\0' */
94 #ifdef DEBUG_TIMEQUEUE
95 fprintf(stderr, "handle_timeq_event()\n");
98 if (strlen(event->event_name)<123)
99 sprintf(buf, "time-%s", event->event_name);
101 sprintf(buf, "time-bogus");
103 #ifdef DEBUG_TIMEQUEUE
104 fprintf(stderr, "opcode: %s\n", buf);
107 event->notice->z_version = "zwgcplus-repeat";
108 event->notice->z_opcode = buf;
110 reprocess_notice(event->notice, pt->hname);
112 #ifdef DEBUG_TIMEQUEUE
113 fprintf(stderr, "end handle_timeq_event()\n");
118 schedule_event(secs, name, notice)
123 time_t eventtime = (time(NULL)) + secs;
127 #ifdef DEBUG_TIMEQUEUE
128 fprintf(stderr, "schedule_event(%ld, %ld, %s)\n", eventtime, secs, name);
131 if(!notice || !name) return;
133 list_add_notice(notice);
135 newnode = (TimeNode *)malloc(sizeof(TimeNode));
136 buf = (char *)malloc(strlen(name) + 1);
140 #ifdef DEBUG_TIMEQUEUE
141 fprintf(stderr, "name: %s\n", buf);
144 newnode->when = eventtime;
145 newnode->event_name = buf;
146 newnode->notice = notice;
148 timeq_head = addtimenode(timeq_head, newnode);
149 #ifdef DEBUG_TIMEQUEUE
150 fprintf(stderr, "end schedule_event()\n");
158 #ifdef DEBUG_TIMEQUEUE
159 fprintf(stderr, "free_timenode(%s)\n", node->event_name);
162 free(node->event_name);
166 /* returns the number of notices destroyed */
168 destroy_timeq_notice(notice, name)
172 TimeNode *curr = timeq_head;
173 TimeNode *prev = NULL;
178 #ifdef DEBUG_TIMEQUEUE
179 fprintf(stderr, "destroy_timeq_notice(%s)\n", name);
182 while(curr != NULL) {
183 if(curr->notice == notice &&
184 (!name || !strcmp(curr->event_name, name)))
188 timeq_head = curr->next;
190 prev->next = curr->next;
205 plus_timequeue_events()
207 /* returns number of seconds to the next event or 0L */
208 /* if there are no events remaining to be processed */
210 time_t timenow = time(NULL);
213 while(timeq_head != NULL && timeq_head->when <= timenow) {
214 #ifdef DEBUG_TIMEQUEUE
215 fprintf(stderr, "handling event\n");
217 handle_timeq_event(timeq_head);
219 timeq_head = timeq_head->next;
223 #ifdef DEBUG_TIMEQUEUE
224 if(timeq_head != NULL)
225 fprintf(stderr, "next event in %ld seconds.\n",
226 (timeq_head->when) - timenow);
229 return ((timeq_head == NULL) ? 0L : ((timeq_head->when) - timenow));
233 plus_set_hname(notice, hname)
241 bx = list_hash_fun(notice);
242 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
243 pt->hname=(char *)malloc(strlen(hname)+1);
244 strcpy(pt->hname, hname);
250 plus_queue_notice(notice)
256 #ifdef DEBUG_TIMEQUEUE
257 fprintf(stderr, "plus_queue_notice()\n");
260 val = var_get_variable("event_time");
262 if(strcmp(val, "kill")) {
264 #ifdef DEBUG_TIMEQUEUE
265 fprintf(stderr, "$event_time %d\n", howlong);
268 val = var_get_variable("event_name");
269 if(!val || strcmp(val, "all"))
270 destroy_timeq_notice(notice, (val && val[0]) ? val : "event");
272 destroy_timeq_notice(notice, (char *)NULL);
277 val = var_get_variable("event_name");
278 #ifdef DEBUG_TIMEQUEUE
279 fprintf(stderr, "$event_name = %s\n", val);
281 schedule_event(howlong, (val && val[0]) ? val : "event", notice);
286 list_hash_fun(notice)
290 int res = 0, val = 1, ptval;
291 char *pt = (char *)(notice);
293 for (ix=0; ix<sizeof(ZNotice_t *); ix++) {
295 if (ptval<0) ptval = (-ptval);
304 /* initialize hash table */
310 stored_notice = NULL;
312 for (ix=0; ix<HASHSIZE; ix++) {
323 for (bx=0; bx<HASHSIZE; bx++) {
324 for (pt=notlist[bx]; pt; pt=pt->next) {
325 fprintf(stderr, "Not %p: %d [%d]\n", pt->notice, pt->refcount, bx);
330 /* add notice to table. Either generate a new entry, or increment ref count. */
332 list_add_notice(notice)
336 int bx = list_hash_fun(notice);
338 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
346 pt = (notnode *)malloc(sizeof(notnode));
350 pt->next = notlist[bx];
351 pt->opcode = notice->z_opcode;
356 /*fprintf(stderr, "list_add_notice(%p)\n", notice);
360 /* remove notice from table. If refcount reaches 0, return 1; if refcount is
361 still positive, return 0; if notice not there, return -1. */
363 list_del_notice(notice)
367 int bx = list_hash_fun(notice);
369 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
373 /*fprintf(stderr, "list_del_notice(%p): ERROR\n", notice);
379 if (pt->refcount > 0) {
380 /*fprintf(stderr, "list_del_notice(%p): count %d\n", notice, pt->refcount);
385 for (ppt = &(notlist[bx]); (*ppt)!=pt; ppt = &((*ppt)->next));
389 if (!pt->fake_notice)
390 ZFreeNotice(pt->notice);
396 /*fprintf(stderr, "list_del_notice(%p): count 0, gone\n", notice);*/
397 /*dump_noticelist();*/
402 set_notice_fake(notice, val)
407 int bx = list_hash_fun(notice);
409 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
412 pt->fake_notice = val;
417 get_notice_fake(notice)
421 int bx = list_hash_fun(notice);
423 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
426 return pt->fake_notice;
433 get_list_refcount(notice)
437 int bx = list_hash_fun(notice);
439 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
442 /*fprintf(stderr, "get_list_refcount(%p): count %d\n", notice, pt->refcount);*/
446 /*fprintf(stderr, "get_list_refcount(%p): count 0\n", notice);*/
451 /* export a reference to the current notice. */
458 list_add_notice(stored_notice);
460 return (char *)stored_notice;
464 set_stored_notice(notice)
467 stored_notice = notice;
471 plus_retry_notice(notice, ch, metaflag)
484 bx = list_hash_fun(notice);
485 for (pt=notlist[bx]; pt && pt->notice!=notice; pt=pt->next);
487 if (metaflag) tmp = "-meta";
491 sprintf(buf, "key%s-space", tmp);
493 sprintf(buf, "key%s-delete", tmp);
495 sprintf(buf, "key%s-ctrl-@", tmp);
497 sprintf(buf, "key%s-esc", tmp);
498 else if (isprint(ch))
499 sprintf(buf, "key%s-%c", tmp, ch);
500 else if (ch>=1 && ch<=26)
501 sprintf(buf, "key%s-ctrl-%c", tmp, ch+'a'-1);
502 else if (iscntrl(ch))
503 sprintf(buf, "key%s-ctrl-%c", tmp, ch+'A'-1);
505 sprintf(buf, "key%s-unknown", tmp);
507 /* concat the old opcode if they're running in "new" mode */
508 if (zwgcplus == 2 && pt && pt->opcode[0] &&
509 strcmp(pt->opcode, "") != 0)
512 strncat(buf, pt->opcode, sizeof(buf)-strlen(buf));
515 notice->z_version = "zwgcplus-repeat";
516 notice->z_opcode = buf;
518 reprocess_notice(notice, NULL);
520 #endif /* CMU_ZWGCPLUS */