diff --git a/scripts/base.js b/scripts/base.js index 71c63062..bab3cb9b 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -795,7 +795,7 @@ Object.defineProperty(Array.prototype, "forTo", { }); Object.defineProperty(Array.prototype, "dofilter", { - value: function (fn) { + value: function array_dofilter(fn) { for (let i = 0; i < this.length; i++) { if (!fn.call(this, this[i], i, this)) { this.splice(i, 1); @@ -807,19 +807,19 @@ Object.defineProperty(Array.prototype, "dofilter", { }); Object.defineProperty(Array.prototype, "reversed", { - value: function () { + value: function array_reversed() { var c = this.slice(); return c.reverse(); }, }); Object.defineProperty(Array.prototype, "rotate", { - value: function (a) { + value: function array_rotate(a) { return Vector.rotate(this, a); }, }); -Array.random = function(arr) { +Array.random = function random(arr) { if (!Array.isArray(arr)) return; return arr[Math.floor(Math.random()*arr.length)]; } diff --git a/scripts/engine.js b/scripts/engine.js index 9daa5ce3..ab8ba5d6 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -87,7 +87,6 @@ Resources.replstrs = function replstrs(path) { var stem = path.dir(); if (!console.enabled) script = Resources.rm_fn(/console\.(spam|info|warn|error)/, script); - if (!profile.enabled) script = Resources.rm_fn(/profile\.(cache|frame|endcache|endframe)/, script); if (!debug.enabled) { @@ -340,7 +339,7 @@ io.slurp = function slurp(path) var findpath = Resources.replpath(path); var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true); return ret; -}.hashify(); +} io.slurpbytes = function(path) { diff --git a/scripts/layout.js b/scripts/layout.js index 67345d06..2389f3af 100644 --- a/scripts/layout.js +++ b/scripts/layout.js @@ -86,7 +86,7 @@ clay.draw = function draw(size, fn) function create_view_fn(base_config) { var base = Object.assign(Object.create(clay_base), base_config); - return function(config = {}, fn) { + return function view(config = {}, fn) { config.__proto__ = base; var item = add_item(config); @@ -223,12 +223,11 @@ layout.draw_commands = function draw_commands(cmds, pos = [0,0]) { var mousepos = prosperon.camera.screen2hud(input.mouse.screenpos()); for (var cmd of cmds) { - cmd.boundingbox.x += pos.x; - cmd.boundingbox.y += pos.y; - cmd.content.x += pos.x; - cmd.content.y += pos.y; + var boundingbox = geometry.rect_move(cmd.boundingbox,pos); + var content = geometry.rect_move(cmd.content,pos); var config = cmd.config; - if (config.hovered && geometry.rect_point_inside(cmd.boundingbox, mousepos)) { + + if (config.hovered && geometry.rect_point_inside(boundingbox, mousepos)) { config.hovered.__proto__ = config; config = config.hovered; hovered = config; @@ -236,25 +235,31 @@ layout.draw_commands = function draw_commands(cmds, pos = [0,0]) if (config.background_image) if (config.slice) - render.slice9(config.background_image, cmd.boundingbox, config.slice, config.background_color); + render.slice9(config.background_image, boundingbox, config.slice, config.background_color); else - render.image(config.background_image, cmd.boundingbox, 0, config.color); + render.image(config.background_image, boundingbox, 0, config.color); else if (config.background_color) - render.rectangle(cmd.boundingbox, config.background_color); + render.rectangle(boundingbox, config.background_color); if (config.text) - render.text(config.text, cmd.content, config.font, config.font_size, config.color); + render.text(config.text, content, config.font, config.font_size, config.color); if (config.image) - render.image(config.image, cmd.content, 0, config.color); + render.image(config.image, content, 0, config.color); } } +var dbg_colors = {}; +layout.debug_colors = dbg_colors; +dbg_colors.content = [1,0,0,0.1]; +dbg_colors.boundingbox = [0,1,0,0,0.1]; +dbg_colors.margin = [0,0,1,0.1]; layout.draw_debug = function draw_debug(cmds, pos = [0,0]) { - for (var cmd of cmds) { - render.rectangle(cmd.content, [1,0,0,0.1]); - render.rectangle(cmd.boundingbox, [0,1,0,0.1]); - render.rectangle(cmd.marginbox, [0,0,1,0.1]); + for (var i = 0; i < cmds.length; i++) { + var cmd = cmds[i]; + render.rectangle(geometry.rect_move(cmd.content,pos), dbg_colors.content); + render.rectangle(geometry.rect_move(cmd.boundingbox,pos), dbg_colors.boundingbox); +// render.rectangle(geometry.rect_move(cmd.marginbox,pos), dbg_colors.margin); } } diff --git a/scripts/prosperon.js b/scripts/prosperon.js index 2974677f..d604f6ba 100644 --- a/scripts/prosperon.js +++ b/scripts/prosperon.js @@ -8,6 +8,7 @@ global.check_registers = function check_registers(obj) { fn.layer = obj[reg].layer; var name = obj.ur ? obj.ur.name : obj.toString(); obj.timers.push(Register.registries[reg].register(fn, name)); + if (!obj[reg].name) Object.defineProperty(obj[reg], 'name', {value:`${obj._file}_${reg}`}); } } @@ -550,6 +551,7 @@ var Register = { var dofn = function (...args) { fn(...args); }; + Object.defineProperty(dofn, 'name', {value:`do_${oname}`}); var left = 0; var right = fns.length - 1; @@ -579,7 +581,7 @@ var Register = { // tracy.fiber_leave(vector.fib); }; } else - prosperon[name] = function name(...args) { + prosperon[name] = function (...args) { var layer = undefined; for (var fn of fns) { if (layer !== fn.layer) { @@ -590,6 +592,7 @@ var Register = { } }; + Object.defineProperty(prosperon[name], 'name', {value:name}); prosperon[name].fns = fns; n.clear = function () { fns = []; diff --git a/scripts/render.js b/scripts/render.js index 2426c8a5..2ba1b3e9 100644 --- a/scripts/render.js +++ b/scripts/render.js @@ -732,8 +732,9 @@ render.sprites = function render_sprites() { } */ - render.use_shader(spritessboshader); var buckets = component.sprite_buckets(); + if (buckets.length === 0) return; + render.use_shader(spritessboshader); for (var l in buckets) { var layer = buckets[l]; for (var img in layer) { @@ -790,7 +791,7 @@ function check_flush(flush_fn) { } render.flush = check_flush; -render.forceflush = function() +render.forceflush = function forceflush() { if (nextflush) nextflush(); nextflush = undefined; @@ -871,20 +872,15 @@ render.coordinate = function render_coordinate(pos, size, color) { var queued_shader; var queued_pipe; render.rectangle = function render_rectangle(rect, color = Color.white, shader = polyssboshader, pipe = base_pipeline) { - var wh = [rect.width, rect.height]; var poly = poly_e(); - var pos = [rect.x,rect.y].add([rect.width,rect.height].scale(0.5)); - pos = pos.sub([rect.width,rect.height].scale([rect.anchor_x,rect.anchor_y])); - poly.transform.move(pos); - poly.transform.scale = [wh.x, wh.y, 1]; + poly.transform.rect(rect); poly.color = color; - queued_shader = shader; queued_pipe = pipe; check_flush(flush_poly); }; -render.text = function (str, rect, font = cur_font, size = 0, color = Color.white, wrap = -1, ) { +render.text = function text(str, rect, font = cur_font, size = 0, color = Color.white, wrap = -1, ) { if (typeof font === 'string') font = render.get_font(font); @@ -961,7 +957,7 @@ var stencil_writer = function stencil_writer(ref) render.stencil_writer = stencil_writer; // objects by default draw where the stencil buffer is 0 -render.fillmask = function(ref) +render.fillmask = function fillmask(ref) { render.forceflush(); var pipe = stencil_writer(ref); @@ -1415,7 +1411,7 @@ try{ if (render.draw_sprites) render.sprites(); prosperon.draw(); if (render.draw_particles) draw_emitters(); - render.fillmask(0); +// render.fillmask(0); render.forceflush(); render.set_projection_ortho({ l:0, @@ -1468,7 +1464,7 @@ try{ } }; -//if (dmon) dmon.watch('.'); +if (dmon) dmon.watch('.'); function dmon_cb(e) { @@ -1485,7 +1481,7 @@ function dmon_cb(e) prosperon.process = function process() { layout.newframe(); // check for hot reloading -// if (dmon) dmon.poll(dmon_cb); + if (dmon) dmon.poll(dmon_cb); var dt = profile.secs(profile.now()) - frame_t; frame_t = profile.secs(profile.now()); diff --git a/source/jsffi.c b/source/jsffi.c index e3d36350..0634a93f 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -2034,6 +2034,14 @@ JSC_CCALL(transform_trs, t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(js,argv[2]); ) +JSC_CCALL(transform_rect, + transform *t = js2transform(js,self); + rect r = js2rect(js,argv[0]); + t->pos = (HMM_Vec3){r.x,r.y,0}; + t->scale = (HMM_Vec3){r.w,r.h,1}; + t->rotation = QUAT1; +) + static const JSCFunctionListEntry js_transform_funcs[] = { CGETSET_ADD(transform, pos), CGETSET_ADD(transform, scale), @@ -2046,9 +2054,9 @@ static const JSCFunctionListEntry js_transform_funcs[] = { MIST_FUNC_DEF(transform, lookat, 1), MIST_FUNC_DEF(transform, direction, 1), MIST_FUNC_DEF(transform, unit, 0), + MIST_FUNC_DEF(transform, rect, 1), }; - JSC_CCALL(datastream_time, return number2js(js,plm_get_time(js2datastream(js,self)->plm)); ) JSC_CCALL(datastream_advance_frames, ds_advanceframes(js2datastream(js,self), js2number(js,argv[0]))) @@ -2232,12 +2240,30 @@ JSC_CCALL(geometry_cwh2rect, return rect2js(js,r); ) +JSC_CCALL(geometry_rect_pos, + rect r = js2rect(js,argv[0]); + return vec22js(js,(HMM_Vec2){ + .x = r.x, + .y = r.y + }); +) + +JSC_CCALL(geometry_rect_move, + rect r = js2rect(js,argv[0]); + HMM_Vec2 move = js2vec2(js,argv[1]); + r.x += move.x; + r.y += move.y; + return rect2js(js,r); +) + static const JSCFunctionListEntry js_geometry_funcs[] = { MIST_FUNC_DEF(geometry, rect_intersect, 2), MIST_FUNC_DEF(geometry, rect_inside, 2), MIST_FUNC_DEF(geometry, rect_random, 1), MIST_FUNC_DEF(geometry, cwh2rect, 2), MIST_FUNC_DEF(geometry, rect_point_inside, 2), + MIST_FUNC_DEF(geometry, rect_pos, 1), + MIST_FUNC_DEF(geometry, rect_move, 2), }; JSValue js_os_cwd(JSContext *js, JSValue self, int argc, JSValue *argv) diff --git a/source/wildmatch.c b/source/wildmatch.c new file mode 100644 index 00000000..62d48d51 --- /dev/null +++ b/source/wildmatch.c @@ -0,0 +1,314 @@ +/* + * Copyright (c), 2016 David Aguilar + * Based on the fnmatch implementation from OpenBSD. + * + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include "wildmatch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define EOS '\0' +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR -1 + +#define check_flag(flags, opts) ((flags) & (opts)) + +static int rangematch(const char *, char, int, const char **); + +int wildmatch(const char *pattern, const char *string, int flags) +{ + const char *stringstart; + const char *newp; + const char *slash; + char c, test; + char prev; + int wild = 0; + + /* WM_WILDSTAR implies WM_PATHNAME. */ + if (check_flag(flags, WM_WILDSTAR)) { + flags |= WM_PATHNAME; + } + + for (stringstart = string;;) { + switch (c = *pattern++) { + case EOS: + if (check_flag(flags, WM_LEADING_DIR) && *string == '/') + return WM_MATCH; + return (*string == EOS) ? WM_MATCH : WM_NOMATCH; + case '?': + if (*string == EOS) + return WM_NOMATCH; + if (*string == '/' && check_flag(flags, WM_PATHNAME)) + return WM_NOMATCH; + if (*string == '.' && check_flag(flags, WM_PERIOD) && + (string == stringstart || + (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/'))) + return WM_NOMATCH; + ++string; + break; + case '*': + c = *pattern; + wild = check_flag(flags, WM_WILDSTAR) && c == '*'; + if (wild) { + prev = pattern[-2]; + /* Collapse multiple stars and slash-** patterns, + * e.g. "** / *** / **** / **" (without spaces) + * is treated as a single ** wildstar. + */ + while (c == '*') { + c = *++pattern; + } + + while (c == '/' && pattern[1] == '*' && pattern[2] == '*') { + prev = c; + c = *++pattern; + while (c == '*') { + c = *++pattern; + } + } + if (c == '/' && + wildmatch(pattern+1, string, flags) == WM_MATCH) { + return WM_MATCH; + } + } else { + /* Collapse multiple stars. */ + while (c == '*') { + c = *++pattern; + } + } + + if (!wild && *string == '.' && check_flag(flags, WM_PERIOD) && + (string == stringstart || + (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/'))) { + return WM_NOMATCH; + } + /* Optimize for pattern with * or ** at end or before /. */ + if (c == EOS) { + if (wild && prev == '/') { + return WM_MATCH; + } + if (check_flag(flags, WM_PATHNAME)) { + return (check_flag(flags, WM_LEADING_DIR) || + strchr(string, '/') == NULL ? WM_MATCH : WM_NOMATCH); + } else { + return WM_MATCH; + } + } else if (c == '/') { + if (wild) { + slash = strchr(stringstart, '/'); + if (!slash) { + return WM_NOMATCH; + } + while (slash) { + if (wildmatch(pattern+1, slash+1, flags) == 0) { + return WM_MATCH; + } + slash = strchr(slash+1, '/'); + } + } else { + if (check_flag(flags, WM_PATHNAME)) { + if ((string = strchr(string, '/')) == NULL) { + return WM_NOMATCH; + } + } + } + } else if (wild) { + return WM_NOMATCH; + } + /* General case, use recursion. */ + while ((test = *string) != EOS) { + if (!wildmatch(pattern, string, flags & ~WM_PERIOD)) + return WM_MATCH; + if (test == '/' && check_flag(flags, WM_PATHNAME)) + break; + ++string; + } + return WM_NOMATCH; + case '[': + if (*string == EOS) + return WM_NOMATCH; + if (*string == '/' && check_flag(flags, WM_PATHNAME)) + return WM_NOMATCH; + if (*string == '.' && check_flag(flags, WM_PERIOD) && + (string == stringstart || + (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/'))) + return WM_NOMATCH; + + switch (rangematch(pattern, *string, flags, &newp)) { + case RANGE_ERROR: + /* not a good range, treat as normal text */ + ++string; + goto normal; + case RANGE_MATCH: + pattern = newp; + break; + case RANGE_NOMATCH: + return (WM_NOMATCH); + } + ++string; + break; + case '\\': + if (!check_flag(flags, WM_NOESCAPE)) { + if ((c = *pattern++) == EOS) { + c = '\\'; + --pattern; + if (*(string+1) == EOS) { + return WM_NOMATCH; + } + } + } + /* FALLTHROUGH */ + default: + normal: + if (c != *string && !(check_flag(flags, WM_CASEFOLD) && + (tolower((unsigned char)c) == + tolower((unsigned char)*string)))) + return WM_NOMATCH; + ++string; + break; + } + /* NOTREACHED */ + } +} + +static int +rangematch(const char *pattern, char test, int flags, const char **newp) +{ + int negate, ok; + char c, c2; + char tmp; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) + ++pattern; + + if (check_flag(flags, WM_CASEFOLD)) + test = tolower((unsigned char)test); + + /* + * A right bracket shall lose its special meaning and represent + * itself in a bracket expression if it occurs first in the list. + * -- POSIX.2 2.8.3.2 + */ + ok = 0; + c = *pattern++; + do { + if (c == '\\' && !check_flag(flags, WM_NOESCAPE)) + c = *pattern++; + + if (c == EOS) + return RANGE_ERROR; + + if (c == '/' && check_flag(flags, WM_PATHNAME)) + return RANGE_NOMATCH; + + if (*pattern == '-' + && (c2 = *(pattern+1)) != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !check_flag(flags, WM_NOESCAPE)) + c2 = *pattern++; + if (c2 == EOS) + return RANGE_ERROR; + + if (check_flag(flags, WM_CASEFOLD)) { + c = tolower((unsigned char)c); + c2 = tolower((unsigned char)c2); + } + if (c > c2) { + tmp = c2; + c2 = c; + c = tmp; + } + if (c <= test && test <= c2) { + ok = 1; + } + } + + if (c == '[' && *pattern == ':' && *(pattern+1) != EOS) { + + #define match_pattern(name) \ + !strncmp(pattern+1, name, sizeof(name)-1) + + #define check_pattern(name, predicate, value) {{ \ + if (match_pattern(name ":]")) { \ + if (predicate(value)) { \ + ok = 1; \ + } \ + pattern += sizeof(name ":]"); \ + continue; \ + } \ + }} + + if (match_pattern(":]")) { + continue; + } + check_pattern("alnum", isalnum, test); + check_pattern("alpha", isalpha, test); + check_pattern("blank", isblank, test); + check_pattern("cntrl", iscntrl, test); + check_pattern("digit", isdigit, test); + check_pattern("graph", isgraph, test); + check_pattern("lower", islower, test); + check_pattern("print", isprint, test); + check_pattern("punct", ispunct, test); + check_pattern("space", isspace, test); + check_pattern("xdigit", isxdigit, test); + c2 = check_flag(flags, WM_CASEFOLD) ? toupper(test) : test; + check_pattern("upper", isupper, c2); + /* fallthrough means match like a normal character */ + } + if (c == test) { + ok = 1; + } + } while ((c = *pattern++) != ']'); + + *newp = (const char *)pattern; + return (ok == negate) ? RANGE_NOMATCH : RANGE_MATCH; +} + +#ifdef __cplusplus +} +#endif diff --git a/source/wildmatch.h b/source/wildmatch.h new file mode 100644 index 00000000..bf00e926 --- /dev/null +++ b/source/wildmatch.h @@ -0,0 +1,80 @@ +/* + * Copyright (c), 2016 David Aguilar + * Based on the fnmatch implementation from OpenBSD. + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + * $OpenBSD: fnmatch.h,v 1.4 1997/09/22 05:25:32 millert Exp $ + */ +#ifndef _WILDMATCH_H_ +#define _WILDMATCH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define WM_MATCH 0 /* Match. */ +#define WM_NOMATCH 1 /* Match failed. */ + +#define WM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define WM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define WM_PERIOD 0x04 /* Period must be matched by period. */ +#define WM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define WM_CASEFOLD 0x10 /* Case insensitive search. */ +#define WM_PREFIX_DIRS 0x20 /* Unused */ +#define WM_WILDSTAR 0x40 /* Double-asterisks ** matches slash too. */ + +#define WM_IGNORECASE WM_CASEFOLD +#define WM_FILE_NAME WM_PATHNAME + +/* + * wildmatch is an extension of function fnmatch(3) as specified in + * POSIX 1003.2-1992, section B.6. + * + * Compares a filename or pathname to a pattern. + * + * wildmatch is fnmatch-compatible by default. Its new features are enabled + * by passing WM_WILDSTAR in flags, which makes ** match across path + * boundaries. WM_WILDSTAR implies WM_PATHNAME and WM_PERIOD. + * + * The WM_ flags are the named the same as their FNM_ fnmatch counterparts + * and are compatible in behavior to fnmatch(3) in the absence of WM_WILDSTAR. + */ + +int wildmatch(const char *pattern, const char *string, int flags); + + +#ifdef __cplusplus +} +#endif +#endif