From: TimePath Date: Wed, 26 Aug 2015 23:25:52 +0000 (+1000) Subject: Expand /lib X-Git-Tag: xonotic-v0.8.2~2022 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=8a10e95d3765188046ecb946b2a5015ed08b30df;p=xonotic%2Fxonotic-data.pk3dir.git Expand /lib --- diff --git a/qcsrc/common/buffs.qh b/qcsrc/common/buffs.qh index e0bda4c67..f1ef589ee 100644 --- a/qcsrc/common/buffs.qh +++ b/qcsrc/common/buffs.qh @@ -8,8 +8,6 @@ #include "teams.qh" #include "util.qh" -#include "registry.qh" - void RegisterBuffs(); const int BUFFS_MAX = 16; entity BUFFS[BUFFS_MAX], BUFFS_first, BUFFS_last; diff --git a/qcsrc/common/items/all.qh b/qcsrc/common/items/all.qh index e22bcd747..2e33119fb 100644 --- a/qcsrc/common/items/all.qh +++ b/qcsrc/common/items/all.qh @@ -1,5 +1,3 @@ -#include "../registry.qh" - #ifndef ITEMS_ALL_H #define ITEMS_ALL_H diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh index 6e566f6cc..bddf75b04 100644 --- a/qcsrc/common/items/item.qh +++ b/qcsrc/common/items/item.qh @@ -1,6 +1,5 @@ #ifndef GAMEITEM_H #define GAMEITEM_H -#include "../oo.qh" #define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__) /** If you register a new item, make sure to add it to all.inc */ CLASS(GameItem, Object) diff --git a/qcsrc/common/monsters/all.qh b/qcsrc/common/monsters/all.qh index 45adf5e59..4158b1537 100644 --- a/qcsrc/common/monsters/all.qh +++ b/qcsrc/common/monsters/all.qh @@ -1,5 +1,3 @@ -#include "../registry.qh" - #ifndef MONSTERS_ALL_H #define MONSTERS_ALL_H diff --git a/qcsrc/common/monsters/monster.qh b/qcsrc/common/monsters/monster.qh index 75eccd95d..79077acc3 100644 --- a/qcsrc/common/monsters/monster.qh +++ b/qcsrc/common/monsters/monster.qh @@ -3,7 +3,6 @@ bool m_null(int) { return false; } -#include "../oo.qh" /** If you register a new monster, make sure to add it to all.inc */ CLASS(Monster, Object) ATTRIB(Monster, monsterid, int, 0) diff --git a/qcsrc/common/mutators/mutator/waypoints/all.qh b/qcsrc/common/mutators/mutator/waypoints/all.qh index 9670a6f38..790d08698 100644 --- a/qcsrc/common/mutators/mutator/waypoints/all.qh +++ b/qcsrc/common/mutators/mutator/waypoints/all.qh @@ -1,5 +1,3 @@ -#include "../../../registry.qh" - #ifndef WAYPOINTS_ALL_H #define WAYPOINTS_ALL_H diff --git a/qcsrc/common/nades.qh b/qcsrc/common/nades.qh index 50f2e57e8..5a9877c4e 100644 --- a/qcsrc/common/nades.qh +++ b/qcsrc/common/nades.qh @@ -1,8 +1,6 @@ #ifndef NADES_H #define NADES_H -#include "oo.qh" -#include "registry.qh" #include "teams.qh" .float healer_lifetime; diff --git a/qcsrc/common/oo.qh b/qcsrc/common/oo.qh deleted file mode 100644 index 3c7237ef4..000000000 --- a/qcsrc/common/oo.qh +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef OO_H -#define OO_H - -#include "registry.qh" - -#ifdef MENUQC - #define NULL (null_entity) -#else - #define NULL (world) -#endif - -.string classname; -/** Location entity was spawned from in source */ -.string sourceLocFile; -.int sourceLocLine; -entity _spawn(); -entity __spawn(string _classname, string _sourceFile, int _sourceLine) { - entity this = _spawn(); - this.classname = _classname; - this.sourceLocFile = _sourceFile; - this.sourceLocLine = _sourceLine; - return this; -} - - - -#define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__) -#define entityclass_1(name) entityclass_2(name, Object) -#ifndef QCC_SUPPORT_ENTITYCLASS - #define entityclass_2(name, base) typedef entity name - #define class(name) - #define new(class) __spawn(#class, __FILE__, __LINE__) -#else - #define entityclass_2(name, base) entityclass name : base {} - #define class(name) [[class(name)]] - #define new(class) ((class) __spawn(#class, __FILE__, __LINE__)) -#endif - -// Classes have a `spawn##cname(entity)` constructor -// The parameter is used across [[accumulate]] functions - -// Macro to hide this implementation detail -#define NEW(cname, ...) \ - OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__) - -#define CONSTRUCT(cname, ...) \ - OVERLOAD(spawn##cname, this, ##__VA_ARGS__) - -#define CONSTRUCTOR(cname, ...) \ - cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \ - [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) - -.string vtblname; -.entity vtblbase; - -void RegisterClasses() { } -STATIC_INIT(RegisterClasses) { RegisterClasses(); } - -#define VTBL(cname, base) \ - INIT_STATIC(cname); \ - entity cname##_vtbl; \ - void cname##_vtbl_init() { \ - cname e = new(vtbl); \ - spawn##cname##_static(e); \ - e.vtblname = #cname; \ - /* Top level objects refer to themselves */ \ - e.vtblbase = base##_vtbl ? base##_vtbl : e; \ - cname##_vtbl = e; \ - } \ - ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init) - -#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this) -#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this) - -#define CLASS(cname, base) \ - entityclass(cname, base); \ - class(cname) .bool instanceOf##cname; \ - VTBL(cname, base) \ - INIT_STATIC(cname) { \ - if (cname##_vtbl) { \ - copyentity(cname##_vtbl, this); \ - return; \ - } \ - spawn##base##_static(this); \ - this.instanceOf##cname = true; \ - } \ - INIT(cname) { \ - /* Only statically initialize the current class, it contains everything it inherits */ \ - if (cname##_vtbl.vtblname == this.classname) { \ - spawn##cname##_static(this); \ - this.classname = #cname; \ - this.vtblname = string_null; \ - this.vtblbase = cname##_vtbl; \ - } \ - spawn##base##_1(this); \ - } - -#define METHOD(cname, name, prototype) \ - class(cname) .prototype name; \ - prototype cname##_##name; \ - INIT_STATIC(cname) { this.name = cname##_##name; } \ - prototype cname##_##name - -#define ATTRIB(cname, name, type, val) \ - class(cname) .type name; \ - INIT(cname) { this.name = val; } - -#define ATTRIBARRAY(cname, name, type, cnt) \ - class(cname) .type name[cnt]; - -#define ENDCLASS(cname) \ - [[last]] INIT(cname) { return this; } - -#define SUPER(cname) (cname##_vtbl.vtblbase) -#define super (this.vtblbase.vtblbase) - -#define spawn_static(this) -#define spawn_1(this) -#define _vtbl NULL -CLASS(Object, ); - METHOD(Object, describe, string(entity this)) { - string s = _("No description"); - if (cvar("developer")) { - for (int i = 0, n = numentityfields(); i < n; ++i) { - string value = getentityfieldstring(i, this); - if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value); - } - } - return s; - } - METHOD(Object, display, void(entity this, void(string name, string icon) returns)) { - returns(sprintf("entity %i", this), "nopreview_map"); - } -ENDCLASS(Object) -#undef spawn_static -#undef spawn_1 -#undef _vtbl - -#endif diff --git a/qcsrc/common/registry.qh b/qcsrc/common/registry.qh deleted file mode 100644 index 6e8557edf..000000000 --- a/qcsrc/common/registry.qh +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef REGISTRY_H -#define REGISTRY_H - -#include "oo.qh" -#include "util.qh" - -#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this) -#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this) - -#define REGISTER(initfunc, ns, array, counter, id, fld, inst) \ - entity ns##_##id; \ - REGISTER_INIT(ns, id) { } \ - REGISTER_INIT_POST(ns, id) { } \ - .entity enemy; /* internal next pointer */ \ - void Register_##ns##_##id() { \ - entity this = inst; \ - ns##_##id = this; \ - this.fld = counter; \ - array[counter++] = this; \ - if (!array##_first) array##_first = this; \ - if ( array##_last) array##_last.enemy = this; \ - array##_last = this; \ - Register_##ns##_##id##_init(this); \ - Register_##ns##_##id##_init_post(this); \ - } \ - ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \ - REGISTER_INIT(ns, id) - -void __static_init() { } -#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init) -#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init, func) - -#define STATIC_INIT(func) \ - void _static_##func(); \ - ACCUMULATE_FUNCTION(__static_init, _static_##func) \ - void _static_##func() - -#endif diff --git a/qcsrc/common/util-post.qh b/qcsrc/common/util-post.qh index 6d1ab21f9..6b43f34bf 100644 --- a/qcsrc/common/util-post.qh +++ b/qcsrc/common/util-post.qh @@ -3,6 +3,4 @@ #define spawn() new(entity) -#include "oo.qh" - #endif diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index 2e41ce76c..995d882f6 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -1,54 +1,6 @@ #ifndef COMMON_UTIL_H #define COMMON_UTIL_H -#ifdef QCC_SUPPORT_ACCUMULATE -# define ACCUMULATE_FUNCTION(func,otherfunc) \ - [[accumulate]] void func() { otherfunc(); } -# define CALL_ACCUMULATED_FUNCTION(func) \ - func() -#else -#ifdef HAVE_YO_DAWG_CPP -// TODO make ascii art pic of xzibit -// YO DAWG! -// I HERD YO LIEK MACROS -// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION -// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS -# define ACCUMULATE_FUNCTION(func,otherfunc) \ - #ifdef func \ - void __merge__##otherfunc() { func(); otherfunc(); } \ - #undef func \ - #define func __merge__##otherfunc \ - #else \ - #define func otherfunc \ - #endif -# define CALL_ACCUMULATED_FUNCTION(func) \ - func() -#else -# define ACCUMULATE_FUNCTION(func,otherfunc) \ - .float _ACCUMULATE_##func##__##otherfunc -void ACCUMULATE_call(string func) -{ - float i; - float n = numentityfields(); - string funcprefix = strcat("_ACCUMULATE_", func, "__"); - float funcprefixlen = strlen(funcprefix); - for(i = 0; i < n; ++i) - { - string name = entityfieldname(i); - if(substring(name, 0, funcprefixlen) == funcprefix) - callfunction(substring(name, funcprefixlen, -1)); - } -} -# define CALL_ACCUMULATED_FUNCTION(func) \ - ACCUMULATE_call(#func) -#endif -#endif - -// used for simplifying ACCUMULATE_FUNCTIONs -#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); } -#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; } -#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); } - // this returns a tempstring containing a copy of s with additional \n newlines added, it also replaces \n in the text with a real newline // NOTE: s IS allowed to be a tempstring string wordwrap(string s, float l); @@ -232,14 +184,6 @@ void WriteInt72_t(float dest, vector val); #endif #endif -// the NULL function -#ifdef QCC_SUPPORT_NIL -#define func_null nil -#define string_null nil -#else -var void func_null(void); -string string_null; -#endif float float2range11(float f); float float2range01(float f); @@ -408,17 +352,6 @@ vector animfixfps(entity e, vector a, vector b); void dedicated_print(string input); #endif -// todo: better way to do this? -#ifdef MENUQC -#define PROGNAME "MENUQC" -#else -#ifdef SVQC -#define PROGNAME "SVQC" -#else -#define PROGNAME "CSQC" -#endif -#endif - #ifndef MENUQC const float CNT_NORMAL = 1; const float CNT_GAMESTART = 2; diff --git a/qcsrc/lib/Accumulate.qh b/qcsrc/lib/Accumulate.qh new file mode 100644 index 000000000..423f36413 --- /dev/null +++ b/qcsrc/lib/Accumulate.qh @@ -0,0 +1,52 @@ +#ifndef ACCUMULATE_H +#define ACCUMULATE_H + +#ifdef QCC_SUPPORT_ACCUMULATE +# define ACCUMULATE_FUNCTION(func, otherfunc) \ + [[accumulate]] void func() { otherfunc(); } +# define CALL_ACCUMULATED_FUNCTION(func) \ + func() +#else +#ifdef HAVE_YO_DAWG_CPP +// TODO make ascii art pic of xzibit +// YO DAWG! +// I HERD YO LIEK MACROS +// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION +// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS +# define ACCUMULATE_FUNCTION(func,otherfunc) \ + #ifdef func \ + void __merge__##otherfunc() { func(); otherfunc(); } \ + #undef func \ + #define func __merge__##otherfunc \ + #else \ + #define func otherfunc \ + #endif +# define CALL_ACCUMULATED_FUNCTION(func) \ + func() +#else +# define ACCUMULATE_FUNCTION(func,otherfunc) \ + .float _ACCUMULATE_##func##__##otherfunc +void ACCUMULATE_call(string func) +{ + float i; + float n = numentityfields(); + string funcprefix = strcat("_ACCUMULATE_", func, "__"); + float funcprefixlen = strlen(funcprefix); + for(i = 0; i < n; ++i) + { + string name = entityfieldname(i); + if(substring(name, 0, funcprefixlen) == funcprefix) + callfunction(substring(name, funcprefixlen, -1)); + } +} +# define CALL_ACCUMULATED_FUNCTION(func) \ + ACCUMULATE_call(#func) +#endif +#endif + +// used for simplifying ACCUMULATE_FUNCTIONs +#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); } +#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; } +#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); } + +#endif diff --git a/qcsrc/lib/Lazy.qh b/qcsrc/lib/Lazy.qh index bf29049e7..fcf065189 100644 --- a/qcsrc/lib/Lazy.qh +++ b/qcsrc/lib/Lazy.qh @@ -1,5 +1,8 @@ #ifndef LAZY_H #define LAZY_H + +#include "OO.qh" + CLASS(Lazy, Object) ATTRIB(Lazy, m_get, entity(), func_null); CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; } diff --git a/qcsrc/lib/Nil.qh b/qcsrc/lib/Nil.qh new file mode 100644 index 000000000..87e3aea5e --- /dev/null +++ b/qcsrc/lib/Nil.qh @@ -0,0 +1,13 @@ +#ifndef NIL_H +#define NIL_H + +#ifdef QCC_SUPPORT_NIL +#define func_null nil +#define string_null nil +#else +// the NULL function +var void func_null(void); +string string_null; +#endif + +#endif diff --git a/qcsrc/lib/OO.qh b/qcsrc/lib/OO.qh new file mode 100644 index 000000000..63a70f7da --- /dev/null +++ b/qcsrc/lib/OO.qh @@ -0,0 +1,140 @@ +#ifndef OO_H +#define OO_H + +#include "Nil.qh" +#include "Registry.qh" + +#ifdef MENUQC + #define NULL (null_entity) +#else + #define NULL (world) +#endif + +.string classname; +/** Location entity was spawned from in source */ +.string sourceLocFile; +.int sourceLocLine; +entity _spawn(); +entity __spawn(string _classname, string _sourceFile, int _sourceLine) { + entity this = _spawn(); + this.classname = _classname; + this.sourceLocFile = _sourceFile; + this.sourceLocLine = _sourceLine; + return this; +} + + + +#define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__) +#define entityclass_1(name) entityclass_2(name, Object) +#ifndef QCC_SUPPORT_ENTITYCLASS + #define entityclass_2(name, base) typedef entity name + #define class(name) + #define new(class) __spawn(#class, __FILE__, __LINE__) +#else + #define entityclass_2(name, base) entityclass name : base {} + #define class(name) [[class(name)]] + #define new(class) ((class) __spawn(#class, __FILE__, __LINE__)) +#endif + +// Classes have a `spawn##cname(entity)` constructor +// The parameter is used across [[accumulate]] functions + +// Macro to hide this implementation detail +#define NEW(cname, ...) \ + OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__) + +#define CONSTRUCT(cname, ...) \ + OVERLOAD(spawn##cname, this, ##__VA_ARGS__) + +#define CONSTRUCTOR(cname, ...) \ + cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \ + [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) + +.string vtblname; +.entity vtblbase; + +void RegisterClasses() { } +STATIC_INIT(RegisterClasses) { RegisterClasses(); } + +#define VTBL(cname, base) \ + INIT_STATIC(cname); \ + entity cname##_vtbl; \ + void cname##_vtbl_init() { \ + cname e = new(vtbl); \ + spawn##cname##_static(e); \ + e.vtblname = #cname; \ + /* Top level objects refer to themselves */ \ + e.vtblbase = base##_vtbl ? base##_vtbl : e; \ + cname##_vtbl = e; \ + } \ + ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init) + +#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this) +#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this) + +#define CLASS(cname, base) \ + entityclass(cname, base); \ + class(cname) .bool instanceOf##cname; \ + VTBL(cname, base) \ + INIT_STATIC(cname) { \ + if (cname##_vtbl) { \ + copyentity(cname##_vtbl, this); \ + return; \ + } \ + spawn##base##_static(this); \ + this.instanceOf##cname = true; \ + } \ + INIT(cname) { \ + /* Only statically initialize the current class, it contains everything it inherits */ \ + if (cname##_vtbl.vtblname == this.classname) { \ + spawn##cname##_static(this); \ + this.classname = #cname; \ + this.vtblname = string_null; \ + this.vtblbase = cname##_vtbl; \ + } \ + spawn##base##_1(this); \ + } + +#define METHOD(cname, name, prototype) \ + class(cname) .prototype name; \ + prototype cname##_##name; \ + INIT_STATIC(cname) { this.name = cname##_##name; } \ + prototype cname##_##name + +#define ATTRIB(cname, name, type, val) \ + class(cname) .type name; \ + INIT(cname) { this.name = val; } + +#define ATTRIBARRAY(cname, name, type, cnt) \ + class(cname) .type name[cnt]; + +#define ENDCLASS(cname) \ + [[last]] INIT(cname) { return this; } + +#define SUPER(cname) (cname##_vtbl.vtblbase) +#define super (this.vtblbase.vtblbase) + +#define spawn_static(this) +#define spawn_1(this) +#define _vtbl NULL +CLASS(Object, ); + METHOD(Object, describe, string(entity this)) { + string s = _("No description"); + if (cvar("developer")) { + for (int i = 0, n = numentityfields(); i < n; ++i) { + string value = getentityfieldstring(i, this); + if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value); + } + } + return s; + } + METHOD(Object, display, void(entity this, void(string name, string icon) returns)) { + returns(sprintf("entity %i", this), "nopreview_map"); + } +ENDCLASS(Object) +#undef spawn_static +#undef spawn_1 +#undef _vtbl + +#endif diff --git a/qcsrc/lib/Progname.qh b/qcsrc/lib/Progname.qh new file mode 100644 index 000000000..ed112a5c2 --- /dev/null +++ b/qcsrc/lib/Progname.qh @@ -0,0 +1,14 @@ +#ifndef PROGNAME_H +#define PROGNAME_H + +#if defined(MENUQC) + #define PROGNAME "MENUQC" +#elif defined(SVQC) + #define PROGNAME "SVQC" +#elif defined(CSQC) + #define PROGNAME "CSQC" +#else + #error "Unable to detect PROGNAME" +#endif + +#endif diff --git a/qcsrc/lib/Registry.qh b/qcsrc/lib/Registry.qh new file mode 100644 index 000000000..8a93146d5 --- /dev/null +++ b/qcsrc/lib/Registry.qh @@ -0,0 +1,37 @@ +#ifndef REGISTRY_H +#define REGISTRY_H + +#include "OO.qh" + +#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this) +#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this) + +#define REGISTER(initfunc, ns, array, counter, id, fld, inst) \ + entity ns##_##id; \ + REGISTER_INIT(ns, id) { } \ + REGISTER_INIT_POST(ns, id) { } \ + .entity enemy; /* internal next pointer */ \ + void Register_##ns##_##id() { \ + entity this = inst; \ + ns##_##id = this; \ + this.fld = counter; \ + array[counter++] = this; \ + if (!array##_first) array##_first = this; \ + if ( array##_last) array##_last.enemy = this; \ + array##_last = this; \ + Register_##ns##_##id##_init(this); \ + Register_##ns##_##id##_init_post(this); \ + } \ + ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \ + REGISTER_INIT(ns, id) + +void __static_init() { } +#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init) +#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init, func) + +#define STATIC_INIT(func) \ + void _static_##func(); \ + ACCUMULATE_FUNCTION(__static_init, _static_##func) \ + void _static_##func() + +#endif diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 288553278..931bc50b4 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -1,2 +1,7 @@ +#include "Accumulate.qh" #include "Cvar.qh" #include "Lazy.qh" +#include "Nil.qh" +#include "OO.qh" +#include "Progname.qh" +#include "Registry.qh" diff --git a/qcsrc/menu/oo/base.qh b/qcsrc/menu/oo/base.qh index 28b87ab7f..894b4b928 100644 --- a/qcsrc/menu/oo/base.qh +++ b/qcsrc/menu/oo/base.qh @@ -1,8 +1,6 @@ #ifndef BASE_H #define BASE_H -#include "../../common/oo.qh" - #include "../../common/util.qh" #include "../../dpdefs/keycodes.qh"