--- /dev/null
+#include "atf.h"
+#undef main
+#include <setjmp.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+
+#define RUN(file, line, name, ntrials) \
+ void name(void); \
+ runtestn(file, line, #name, name, ntrials)
+
+static char* Curr_File = 0;
+static char* Curr_Test = 0;
+static char* Curr_Expr = 0;
+static unsigned int Curr_Line = 0;
+static Value* Curr_Values;
+static jmp_buf Jump_Buf;
+static unsigned long Total = 0;
+static unsigned long Failed = 0;
+static uintptr_t Heap_Buf[1024*1024];
+static uintptr_t* Heap_Top = Heap_Buf;
+static uintptr_t* Heap_Base = Heap_Buf;
+static uintptr_t* Heap_End = Heap_Buf + sizeof(Heap_Buf)/sizeof(uintptr_t) - 1;
+enum {
+ FAIL_ASSERT = 1,
+ FAIL_OOM = 2
+};
+
+/* Basic Runtime Functions
+ ****************************/
+static int print_results(void)
+{
+ printf("%lu/%lu tests passed\n" , Total - Failed, Total);
+ return Failed;
+}
+
+static void print_values(void)
+{
+ Value* values = 0;
+ while (Curr_Values)
+ {
+ Value* val = Curr_Values;
+ Curr_Values = val->next;
+ val->next = values;
+ values = val;
+ }
+
+ while (values)
+ {
+ printf(" -> arg: ");
+ values->showfn(values);
+ values = values->next;
+ }
+}
+
+void* malloc(size_t size)
+{
+ void* ptr = Heap_Top;
+ size_t num_words = ((size & ~0x7) + ((size & 7) ? 1 : 0)) / sizeof(uintptr_t) + 1;
+ *Heap_Top = size;
+ Heap_Top += num_words;
+ if (Heap_Top > Heap_End)
+ {
+ Heap_Top = Heap_Base; // Reset heap in case printf mallocs.
+ fprintf(stderr,"%s:%d: MEM %s out of memory\n", Curr_File, Curr_Line, Curr_Test);
+ longjmp(Jump_Buf, FAIL_OOM);
+ }
+ else
+ {
+ memset(ptr, 0, size);
+ }
+ return ptr;
+}
+
+void* calloc(size_t num, size_t size)
+{
+ return malloc(num * size);
+}
+
+void* realloc(void* ptr, size_t new_size)
+{
+ uintptr_t old_size = *((uintptr_t*)ptr - 1);
+ void* newptr = malloc(new_size);
+ memcpy(newptr, ptr, old_size);
+ return newptr;
+}
+
+void free(void* ptr)
+{
+ (void)ptr; /* simply reset the buffer after each test */
+}
+
+void Assert(int cond, char* condstr, char* file, int line)
+{
+ if (!cond)
+ {
+ Curr_File = file;
+ Curr_Line = line;
+ Curr_Expr = condstr;
+ longjmp(Jump_Buf, 1);
+ }
+}
+
+static int runtest(void (*fn)(void))
+{
+ Curr_Values = 0;
+ Heap_Top = Heap_Base;
+ int code = setjmp(Jump_Buf);
+ if (code == 0)
+ {
+ fn();
+ }
+ return code;
+}
+
+static void runtestn(char* file, int line, char* fnname, void (*fn)(void), int ntrials)
+{
+ Curr_File = file;
+ Curr_Line = line;
+ Curr_Test = fnname;
+ Total++;
+ for (int i = 0; i < ntrials; i++)
+ {
+ int fail = runtest(fn);
+ if (fail != 0)
+ {
+ Failed++;
+ if (fail == FAIL_ASSERT)
+ {
+ if (ntrials == 1)
+ {
+ printf("%s:%d: FAIL for test %s \n -> CHECK( %s )\n", Curr_File, Curr_Line, Curr_Test, Curr_Expr);
+ }
+ else
+ {
+ printf("%s:%d: FAIL on trial %d/%d for test %s\n", Curr_File, Curr_Line, i, ntrials, Curr_Test);
+ print_values();
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void handle_signal(int sig)
+{
+ /* Determine the signal name */
+ char* sig_name = NULL;
+ switch(sig)
+ {
+ case SIGABRT: sig_name = "SIGABRT"; break;
+ case SIGBUS: sig_name = "SIGBUS"; break;
+ case SIGFPE: sig_name = "SIGFPE"; break;
+ case SIGILL: sig_name = "SIGILL"; break;
+ case SIGSEGV: sig_name = "SIGSEGV"; break;
+ case SIGSYS: sig_name = "SIGSYS"; break;
+ /* If we don't recognize it then just return and let the default handler
+ catch it. */
+ default: return;
+ }
+ /* Error and exit. No summary will be printed but the user will know which
+ test has crashed. */
+ fprintf(stderr,"%s:%d: CRASH %s (signal: %d - %s)\n", Curr_File, Curr_Line, Curr_Test, sig, sig_name);
+ Failed++;
+ (void)print_results();
+ _Exit(1);
+}
+
+/* Property Testing Functions
+ ****************************/
+void* ValueAlloc(void (*showfn)(Value* val), size_t num, size_t sz, void* data)
+{
+ Value* value = calloc(num, sizeof(Value) + sz);
+ value->showfn = showfn;
+ value->ndata = num;
+ value->next = Curr_Values;
+ Curr_Values = value;
+ if (data)
+ {
+ memcpy(value->data, data, num * sz);
+ }
+ return &(value->data[0]);
+}
+
+long RandR(long from, long to)
+{
+ return ((rand() % (to - from + 1)) + from);
+}
+
+long Rand(void)
+{
+ return rand();
+}
+
+void ShowLong(Value* val)
+{
+ printf("%ld\n", (val->data[0]));
+}
+
+void ShowBool(Value* val)
+{
+ printf("%s\n", (val->data[0] ? "true" : "false"));
+}
+
+void ShowChar(Value* val)
+{
+ printf("'%c'\n", (char)(val->data[0]));
+}
+
+void ShowString(Value* val)
+{
+ printf("'%s'\n", (char*)(val->data));
+}
+
+long MkLongR(long from, long to)
+{
+ return *((long*)ValueAlloc(ShowLong, 1, sizeof(long), &(long){RandR(from, to)}));
+}
+
+long MkLong(void)
+{
+ return *((long*)ValueAlloc(ShowLong, 1, sizeof(long), &(long){Rand()}));
+}
+
+uint8_t MkU8(void)
+{
+ return MkLongR(0, UINT8_MAX);
+}
+
+uint16_t MkU16(void)
+{
+ return MkLongR(0, UINT16_MAX);
+}
+
+uint32_t MkU32(void)
+{
+ return MkLongR(0, UINT32_MAX);
+}
+
+bool MkBool(void)
+{
+ return *((bool*)ValueAlloc(ShowBool, 1, sizeof(bool), &(bool){RandR(0, 1)}));
+}
+
+char MkAsciiChar(void)
+{
+ return *((char*)ValueAlloc(ShowChar, 1, sizeof(char), &(char){RandR(32, 127)}));
+}
+
+char* MkAsciiStringL(size_t len) {
+ char* val = ValueAlloc(ShowString, len+1, sizeof(char), 0);
+ for (size_t i = 0; i < len; i++)
+ {
+ *(val++) = RandR(32, 127);
+ }
+ return val;
+}
+
+char* MkAsciiString(void) {
+ return MkAsciiStringL(RandR(1, 1024));
+}
+
+/* Main Routine
+ ****************************/
+int main(int argc, char** argv)
+{
+ (void)runtestn;
+ unsigned int seed = (argc >= 2 ? strtoul(argv[1], 0, 0) : (unsigned int)time(0));
+ printf("Seed: %u\n", seed);
+ srand(seed);
+ signal(SIGABRT, handle_signal);
+ signal(SIGBUS, handle_signal);
+ signal(SIGFPE, handle_signal);
+ signal(SIGILL, handle_signal);
+ signal(SIGSEGV, handle_signal);
+ signal(SIGSYS, handle_signal);
+ Heap_Base = Heap_Top;
static void xbtnmotion(XConf* x, XEvent* e)
{
- while (XCheckTypedEvent(x->display, MotionNotify, e));
+ XMotionEvent *ev = &e->xmotion;
+ while (XCheckTypedWindowEvent(x->display, ev->window, ev->type, e));
size_t row, col;
- int xpos = e->xbutton.x, ypos = e->xbutton.y;
+ int xpos = ev->x, ypos = ev->y;
get_position(Focused, xpos, ypos, &row, &col);
telem_send("BTNMOVE(reg: %d, btn: 0x%x, x: %d, y: %d, r: %d, c: %d)\n",
- Focused, e->xbutton.state, xpos, ypos, row, col);
- if (PRESSED(e->xbutton.state, MouseLeft))
+ Focused, ev->state, xpos, ypos, row, col);
+ if (PRESSED(ev->state, MouseLeft))
view_setcursor(win_view(Focused), row, col, true);
}