/* context.c * * $Id$ * * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin * Copyright 2002, 2003 Sam Hocevar , Paris * * This software was derived from Elk 1.2, which was Copyright 1987, 1988, * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project * between TELES and Nixdorf Microprocessor Engineering, Berlin). * * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co- * owners or individual owners of copyright in this software, grant to any * person or company a worldwide, royalty free, license to * * i) copy this software, * ii) prepare derivative works based on this software, * iii) distribute copies of this software or derivative works, * iv) perform this software, or * v) display this software, * * provided that this notice is not removed and that neither Oliver Laumann * nor Teles nor Nixdorf are deemed to have made any representations as to * the suitability of this software for any purpose nor are held responsible * for any defects of this software. * * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include "xt.h" static SYMDESCR XtIM_Syms[] = { { "x-event", XtIMXEvent }, { "timer", XtIMTimer }, { "alternate-input", XtIMAlternateInput }, { 0, 0 } }; static SYMDESCR XtInputMask_Syms[] = { { "read", XtInputReadMask }, { "write", XtInputWriteMask }, { "exception", XtInputExceptMask }, { 0, 0 } }; static Object P_Destroy_Context(); Generic_Predicate (Context) Generic_Equal (Context, CONTEXT, context) Generic_Print (Context, "#[context %lu]", (unsigned int)(uintptr_t)POINTER(x)) static Object Internal_Make_Context (int finalize, XtAppContext context) { Object c; c = Find_Object (T_Context, (GENERIC)0, Match_Xt_Obj, context); if (Nullp (c)) { c = Alloc_Object (sizeof (struct S_Context), T_Context, 0); CONTEXT(c)->tag = Null; CONTEXT(c)->context = context; CONTEXT(c)->free = 0; Register_Object (c, (GENERIC)0, finalize ? P_Destroy_Context : (PFO)0, 1); XtAppSetWarningHandler (context, Xt_Warning); XtAppAddActionHook (context, (XtActionHookProc)Action_Hook, (XtPointer)0); } return c; } /* Backwards compatibility: */ Object Make_Context (XtAppContext context) { return Internal_Make_Context (1, context); } Object Make_Context_Foreign (XtAppContext context) { return Internal_Make_Context (0, context); } void Check_Context (Object c) { Check_Type (c, T_Context); if (CONTEXT(c)->free) Primitive_Error ("invalid context: ~s", c); } static Object P_Create_Context () { return Make_Context (XtCreateApplicationContext ()); } static Object P_Destroy_Context (Object c) { Check_Context (c); Free_Actions (CONTEXT(c)->context); XtDestroyApplicationContext (CONTEXT(c)->context); CONTEXT(c)->free = 1; Deregister_Object (c); return Void; } static Object P_Initialize_Display (Object c, Object d, Object name, Object class) { register char *sn = 0, *sc = "", *sd = 0; Display *dpy; extern char **Argv; extern int First_Arg, Argc; int argc = Argc - First_Arg + 1; Argv[First_Arg-1] = "elk"; Check_Context (c); if (!EQ(name, False)) sn = Get_Strsym (name); if (!EQ(class, False)) sc = Get_Strsym (class); if (TYPE(d) == T_Display) { XtDisplayInitialize (CONTEXT(c)->context, DISPLAY(d)->dpy, sn, sc, (XrmOptionDescRec *)0, 0, &argc, &Argv[First_Arg-1]); Argc = First_Arg + argc; return Void; } if (!EQ(d, False)) sd = Get_Strsym (d); dpy = XtOpenDisplay (CONTEXT(c)->context, sd, sn, sc, (XrmOptionDescRec *)0, 0, &argc, &Argv[First_Arg-1]); Argc = First_Arg + argc - 1; if (dpy == 0) { if (sd) Primitive_Error ("cannot open display ~s", d); else Primitive_Error ("cannot open display"); } return Make_Display (0, dpy); } /* Due to a bug in Xt this function drops core when invoked with a * display not owned by Xt. */ static Object P_Display_To_Context (Object d) { Check_Type (d, T_Display); return Make_Context_Foreign (XtDisplayToApplicationContext (DISPLAY(d)->dpy)); } static Object P_Set_Context_Fallback_Resources (int argc, Object *argv) { register char **p = 0; register int i; struct S_String *sp; Object con; con = argv[0]; Check_Context (con); if (argc > 1) { argv++; argc--; p = (char **)XtMalloc ((argc+1) * sizeof (char *)); for (i = 0; i < argc; i++) { Check_Type (argv[i], T_String); sp = STRING(argv[i]); p[i] = XtMalloc (sp->size + 1); memcpy (p[i], sp->data, sp->size); p[i][sp->size] = 0; } p[i] = 0; } XtAppSetFallbackResources (CONTEXT(con)->context, p); return Void; } static Object P_Context_Main_Loop (Object c) { Check_Context (c); XtAppMainLoop (CONTEXT(c)->context); /*NOTREACHED*/ return Void; } static Object P_Context_Pending (Object c) { Check_Context (c); return Bits_To_Symbols ((unsigned long)XtAppPending (CONTEXT(c)->context), 1, XtIM_Syms); } static Object P_Context_Process_Event (int argc, Object *argv) { XtInputMask mask = XtIMAll; Check_Context (argv[0]); if (argc == 2) mask = (XtInputMask)Symbols_To_Bits (argv[1], 1, XtIM_Syms); XtAppProcessEvent (CONTEXT(argv[0])->context, mask); return Void; } static Boolean Work_Proc (XtPointer client_data) { Object ret; ret = Funcall (Get_Function ((int)client_data), Null, 0); if (Truep (ret)) Deregister_Function ((int)client_data); return Truep (ret); } static Object P_Context_Add_Work_Proc (Object c, Object p) { XtWorkProcId id; register int i; Check_Context (c); Check_Procedure (p); i = Register_Function (p); id = XtAppAddWorkProc (CONTEXT(c)->context, Work_Proc, (XtPointer)i); return Make_Id ('w', (XtPointer)id, i); } static Object P_Remove_Work_Proc (Object id) { XtRemoveWorkProc ((XtWorkProcId)Use_Id (id, 'w')); Deregister_Function (IDENTIFIER(id)->num); return Void; } static void Timeout_Proc (XtPointer client_data, XtIntervalId *id) { Object proc, args; register int i = (int)client_data; args = Cons (Make_Id ('t', (XtPointer)*id, i), Null); proc = Get_Function (i); Deregister_Function (i); (void)Funcall (proc, args, 0); } static Object P_Context_Add_Timeout (Object c, Object n, Object p) { XtIntervalId id; register int i; Check_Context (c); Check_Procedure (p); i = Register_Function (p); id = XtAppAddTimeOut (CONTEXT(c)->context, (unsigned long)Get_Long (n), Timeout_Proc, (XtPointer)i); return Make_Id ('t', (XtPointer)id, i); } static Object P_Remove_Timeout (Object id) { XtRemoveTimeOut ((XtIntervalId)Use_Id (id, 't')); Deregister_Function (IDENTIFIER(id)->num); return Void; } /*ARGSUSED*/ static void Input_Proc (XtPointer client_data, int *src, XtInputId *id) { Object p, args; GC_Node2; p = Get_Function ((int)client_data); args = Null; GC_Link2 (p, args); args = Cons (Make_Id ('i', (XtPointer)*id, (int)client_data), Null); args = Cons (Car (p), args); GC_Unlink; (void)Funcall (Cdr (p), args, 0); } static Object P_Context_Add_Input (int argc, Object *argv) { Object c, src, p; XtInputId id; XtInputMask m; register int i; c = argv[0], src = argv[1], p = argv[2]; Check_Context (c); Check_Procedure (p); Check_Type (src, T_Port); if (!(PORT(src)->flags & P_OPEN)) Primitive_Error ("port has been closed: ~s", src); if (PORT(src)->flags & P_STRING) Primitive_Error ("invalid port: ~s", src); if (argc == 4) { m = Symbols_To_Bits (argv[3], 1, XtInputMask_Syms); } else { switch (PORT(src)->flags & (P_INPUT|P_BIDIR)) { case 0: m = XtInputWriteMask; break; case P_INPUT: m = XtInputReadMask; break; default: m = XtInputReadMask|XtInputWriteMask; break; } } i = Register_Function (Cons (src, p)); id = XtAppAddInput (CONTEXT(c)->context, fileno (PORT(src)->file), (XtPointer)m, Input_Proc, (XtPointer)i); return Make_Id ('i', (XtPointer)id, i); } static Object P_Remove_Input (Object id) { XtRemoveInput ((XtInputId)Use_Id (id, 'i')); Deregister_Function (IDENTIFIER(id)->num); return Void; } void elk_init_xt_context () { Generic_Define (Context, "context", "context?"); Define_Primitive (P_Create_Context, "create-context", 0, 0, EVAL); Define_Primitive (P_Destroy_Context, "destroy-context", 1, 1, EVAL); Define_Primitive (P_Initialize_Display, "initialize-display", 4, 4, EVAL); Define_Primitive (P_Display_To_Context, "display->context", 1, 1, EVAL); Define_Primitive (P_Set_Context_Fallback_Resources, "set-context-fallback-resources!", 1, MANY, VARARGS); Define_Primitive (P_Context_Main_Loop, "context-main-loop", 1, 1, EVAL); Define_Primitive (P_Context_Pending, "context-pending", 1, 1, EVAL); Define_Primitive (P_Context_Process_Event, "context-process-event", 1, 2, VARARGS); Define_Primitive (P_Context_Add_Work_Proc, "context-add-work-proc", 2, 2, EVAL); Define_Primitive (P_Remove_Work_Proc, "remove-work-proc", 1, 1, EVAL); Define_Primitive (P_Context_Add_Timeout,"context-add-timeout",3, 3, EVAL); Define_Primitive (P_Remove_Timeout, "remove-timeout", 1, 1, EVAL); Define_Primitive (P_Context_Add_Input, "context-add-input",3, 4, VARARGS); Define_Primitive (P_Remove_Input, "remove-input", 1, 1, EVAL); }